lib9p

Go 9P library.
Log | Files | Refs | LICENSE

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 }