req.go (2407B)
1 package lib9p 2 3 import ( 4 "sync" 5 ) 6 7 // request represents each requests. 8 type request struct { 9 tag uint16 10 // Ifcall is incomming 9P message 11 ifcall Msg 12 // Ofcall is response message to Ifcall. 13 ofcall Msg 14 fid *fid 15 afid *fid 16 // Oldreq is set with Tflush message. 17 oldreq *request 18 // Pool is the pool this request belongs to. 19 pool *reqPool 20 // Done is used by time consuming goroutines to check whether the request 21 // is flushed. 22 done chan struct{} 23 // listenErr is any error encountered while waiting for new 9P message. 24 listenErr error 25 // speakErrChan is used to report any error encountered while sending 26 // the response message. 27 // TODO: is this channel closed in all senarios? 28 speakErrChan chan error 29 // err is any error encountered while processing the request. 30 err error 31 } 32 33 // flush cancels the request by calling r.cancel. 34 // It also delete the request from its pool. 35 func (r *request) flush() { 36 // TODO: need mutex? 37 close(r.done) 38 r.pool.delete(r.tag) 39 } 40 41 // reqPool is the pool of Reqs the server is dealing with. 42 type reqPool struct { 43 m map[uint16]*request 44 *sync.Mutex 45 } 46 47 // newReqPool allocats a reqPool. 48 func newReqPool() *reqPool { 49 return &reqPool{ 50 make(map[uint16]*request), 51 new(sync.Mutex), 52 } 53 } 54 55 // Add allocates a request with the specified tag in reqPool rp. 56 // It returns (nil, ErrDupTag) if there is already a request with the specified tag, 57 // exept that if the tag is NOTAG, it deletes all the request in the map and 58 // allocats an req with that tag. 59 func (rp *reqPool) add(tag uint16) (*request, error) { 60 return reqPoolAdd(rp, tag) 61 } 62 63 var reqPoolAdd = func(rp *reqPool, tag uint16) (*request, error) { 64 rp.Lock() 65 defer rp.Unlock() 66 if tag == NOTAG { 67 for _, r := range rp.m { 68 close(r.done) 69 } 70 rp.m = make(map[uint16]*request) 71 } 72 if _, ok := rp.m[tag]; ok { 73 return nil, ErrDupTag 74 } 75 req := &request{ 76 pool: rp, 77 done: make(chan struct{}), 78 speakErrChan: make(chan error), 79 } 80 rp.m[tag] = req 81 return req, nil 82 } 83 84 // lookup looks for the request in the pool with tag. 85 // If found, it returns the found request and true, otherwise 86 // it returns nil and false. 87 func (rp *reqPool) lookup(tag uint16) (*request, bool) { 88 rp.Lock() 89 defer rp.Unlock() 90 r, ok := rp.m[tag] 91 return r, ok 92 } 93 94 // delete delets the request with tag from the pool. 95 func (rp *reqPool) delete(tag uint16) { 96 rp.Lock() 97 defer rp.Unlock() 98 delete(rp.m, tag) 99 }