req.go (2630B)
1 package client 2 3 import ( 4 "fmt" 5 "sync" 6 7 "git.mtkn.jp/lib9p" 8 ) 9 10 // req represents each requests of the client. 11 type req struct { 12 tag uint16 13 tmsg lib9p.Msg 14 rmsg lib9p.Msg 15 err error 16 errc chan error // To report any client side error to transact(). 17 rxc chan *req 18 } 19 20 // newReq allocates a req with msg. 21 func newReq(msg lib9p.Msg) *req { 22 return &req{ 23 tag: msg.GetTag(), 24 tmsg: msg, 25 rxc: make(chan *req), 26 errc: make(chan error), 27 } 28 } 29 30 // reqPool is the pool of Reqs the server is dealing with. 31 // TODO: unite this with tagPool 32 type reqPool struct { 33 m map[uint16]*req 34 *sync.Mutex 35 } 36 37 // newReqPool allocats a reqPool. 38 func newReqPool() *reqPool { 39 return &reqPool{ 40 make(map[uint16]*req), 41 new(sync.Mutex), 42 } 43 } 44 45 // Add allocates a request with the specified tag in reqPool rp. 46 // It returns (nil, ErrDupTag) if there is already a request with the specified tag. 47 func (rp *reqPool) add(r *req) error { 48 rp.Lock() 49 defer rp.Unlock() 50 if _, ok := rp.m[r.tag]; ok { 51 return lib9p.ErrDupTag 52 } 53 rp.m[r.tag] = r 54 return nil 55 } 56 57 // lookup looks for the request in the pool with tag. 58 // If found, it returns the found request and true, otherwise 59 // it returns nil and false. 60 func (rp *reqPool) lookup(tag uint16) (*req, bool) { 61 rp.Lock() 62 defer rp.Unlock() 63 r, ok := rp.m[tag] 64 return r, ok 65 } 66 67 // delete delets the request with tag from the pool. 68 func (rp *reqPool) delete(tag uint16) { 69 rp.Lock() 70 defer rp.Unlock() 71 delete(rp.m, tag) 72 } 73 74 func (rp *reqPool) cancelAll(err error) { 75 rp.Lock() 76 defer rp.Unlock() 77 for tag, r := range rp.m { 78 r.errc <- err 79 delete(rp.m, tag) 80 } 81 } 82 83 func (rp *reqPool) String() string { 84 rp.Lock() 85 defer rp.Unlock() 86 return fmt.Sprint(rp.m) 87 } 88 89 // tagPool is a pool of tags being used by a client. 90 type tagPool struct { 91 m map[uint16]bool 92 lock *sync.Mutex 93 } 94 95 func newTagPool() *tagPool { 96 return &tagPool{ 97 m: make(map[uint16]bool), 98 lock: new(sync.Mutex), 99 } 100 } 101 102 func (tp *tagPool) add() (uint16, error) { 103 tp.lock.Lock() 104 defer tp.lock.Unlock() 105 tag := lib9p.NOTAG 106 for i := uint16(0); i < i+1; i++ { 107 if _, ok := tp.m[i]; !ok { 108 tag = i 109 break 110 } 111 } 112 if tag == lib9p.NOTAG { 113 return lib9p.NOTAG, fmt.Errorf("run out of tag") 114 } 115 tp.m[tag] = true 116 return tag, nil 117 } 118 119 func (tp *tagPool) lookup(tag uint16) bool { 120 tp.lock.Lock() 121 defer tp.lock.Unlock() 122 _, ok := tp.m[tag] 123 return ok 124 } 125 126 func (tp *tagPool) delete(tag uint16) { 127 tp.lock.Lock() 128 defer tp.lock.Unlock() 129 delete(tp.m, tag) 130 } 131 132 func (tp *tagPool) String() string { 133 s := "[" 134 for tag := range tp.m { 135 s += fmt.Sprintf("%d ", tag) 136 } 137 if len(s) > 1 { 138 s = s[:len(s)-1] + "]" 139 } else { 140 s = "[]" 141 } 142 return s 143 }