commit - db96364a86ef8eec2d65c3968f638e5d547dd150
commit + 50a8a16a89824975e76df0c5fd2202ea54ef345e
blob - /dev/null
blob + 16e148eaaa58c36a4f86250a8bc46dc489bbf9f4 (mode 644)
--- /dev/null
+++ .travis.yml
+language: go
+
+go:
+ - 1.6
+
+script:
+ - go test -coverprofile=coverage.txt -covermode=atomic -race
+
+# CODECOV_TOKEN set in travisCI ENV
+after_success:
+ - bash <(curl -s https://codecov.io/bash)
blob - 1bdd1dad5480d8885448ed2e0bff49d513b8679d
blob + 6e52d0f1dfbcab2138a49cf9059b9dda62652e67
--- README.md
+++ README.md
-# p9p [![GoDoc](https://godoc.org/github.com/docker/go-p9p?status.svg)](https://godoc.org/github.com/docker/go-p9p) [![CircleCI](https://circleci.com/gh/docker/go-p9p.svg?style=shield)](https://circleci.com/gh/docker/go-p9p) [![Go Report Card](https://goreportcard.com/badge/github.com/docker/go-p9p)](https://goreportcard.com/report/github.com/docker/go-p9p) [![Badge Badge](http://badge-server.badge-validate.80d2e13b.svc.dockerapp.io:8088/github.com/docker/go-p9p)](https://github.com/docker/go-p9p)
+# p9p [![GoDoc](https://godoc.org/github.com/docker/go-p9p?status.svg)](https://godoc.org/github.com/docker/go-p9p) [![Apache licensed](https://img.shields.io/badge/license-Apache-blue.svg)](https://raw.githubusercontent.com/docker/go-p9p/master/LICENSE) [![CircleCI](https://circleci.com/gh/docker/go-p9p.svg?style=shield)](https://circleci.com/gh/docker/go-p9p) [![TravisCI](https://travis-ci.org/docker/go-p9p.svg?branch=master)](https://travis-ci.org/docker/go-p9p) [![Go Report Card](https://goreportcard.com/badge/github.com/docker/go-p9p)](https://goreportcard.com/report/github.com/docker/go-p9p)
+[![Badge Badge](http://badge-server.badge-validate.80d2e13b.svc.dockerapp.io:8088/github.com/docker/go-p9p)](https://github.com/docker/go-p9p)
A modern, performant 9P library for Go.
blob - e17a6b70611d29e021f7791f0ef72032b4c16c27
blob + e7b76521e84d5fdbe9dc8059e923ee9cbd01f144
--- fcall.go
+++ fcall.go
}
func newFcall(tag Tag, msg Message) *Fcall {
- switch msg.Type() {
- case Tversion, Rversion:
- tag = NOTAG
- }
-
return &Fcall{
Type: msg.Type(),
Tag: tag,
blob - 8a19e3836a0154314bf8f609fbf91e0ea0a29314
blob + 8a88fa3b9a090adadc8d61c1c98894b0c917e6d6
--- transport.go
+++ transport.go
package p9p
import (
+ "errors"
"fmt"
"log"
"net"
var _ roundTripper = &transport{}
-func newTransport(ctx context.Context, ch *channel) roundTripper {
+func newTransport(ctx context.Context, ch Channel) roundTripper {
t := &transport{
ctx: ctx,
ch: ch,
}
}
+// allocateTag returns a valid tag given a tag pool map. It receives a hint as
+// to where to start the tag search. It returns an error if the allocation is
+// not possible. The provided map must not contain NOTAG as a key.
+func allocateTag(r *fcallRequest, m map[Tag]*fcallRequest, hint Tag) (Tag, error) {
+ // The tag pool is depleted if 65535 (0xFFFF) tags are taken.
+ if len(m) >= 0xFFFF {
+ return 0, errors.New("tag pool depleted")
+ }
+
+ // Look for the first tag that doesn't exist in the map and return it.
+ for i := 0; i < 0xFFFF; i++ {
+ hint++
+ if hint == NOTAG {
+ hint = 0
+ }
+
+ if _, exists := m[hint]; !exists {
+ return hint, nil
+ }
+ }
+
+ return 0, errors.New("allocateTag: unexpected error")
+}
+
// handle takes messages off the wire and wakes up the waiting tag call.
func (t *transport) handle() {
defer func() {
// the following variable block are protected components owned by this thread.
var (
responses = make(chan *Fcall)
- tags Tag
// outstanding provides a map of tags to outstanding requests.
outstanding = map[Tag]*fcallRequest{}
+ selected Tag
)
// loop to read messages off of the connection
for {
select {
case req := <-t.requests:
- // BUG(stevvooe): This is an awful tag allocation procedure.
- // Replace this with something that let's us allocate tags and
- // associate data with them, returning to them to a pool when
- // complete. Such a system would provide a lot of information
- // about outstanding requests.
- tags++
- fcall := newFcall(tags, req.message)
- outstanding[fcall.Tag] = req
+ var err error
+ selected, err = allocateTag(req, outstanding, selected)
+ if err != nil {
+ req.err <- err
+ continue
+ }
+
+ outstanding[selected] = req
+ fcall := newFcall(selected, req.message)
+
// TODO(stevvooe): Consider the case of requests that never
// receive a response. We need to remove the fcall context from
// the tag map and dealloc the tag. We may also want to send a