Error handling, testing

This commit is contained in:
Jakob Borg
2013-12-20 00:01:34 +01:00
parent eba1c9e649
commit f5987fba32
6 changed files with 207 additions and 35 deletions

View File

@@ -49,7 +49,6 @@ type Connection struct {
mwriter *marshalWriter
wLock sync.RWMutex
closed bool
closedLock sync.RWMutex
awaiting map[int]chan asyncResult
nextId int
lastReceive time.Time
@@ -74,13 +73,14 @@ func NewConnection(nodeID string, reader io.Reader, writer io.Writer, receiver M
}
c := Connection{
receiver: receiver,
reader: flrd,
mreader: &marshalReader{flrd, 0, nil},
writer: flwr,
mwriter: &marshalWriter{flwr, 0, nil},
awaiting: make(map[int]chan asyncResult),
ID: nodeID,
receiver: receiver,
reader: flrd,
mreader: &marshalReader{flrd, 0, nil},
writer: flwr,
mwriter: &marshalWriter{flwr, 0, nil},
awaiting: make(map[int]chan asyncResult),
lastReceive: time.Now(),
ID: nodeID,
}
go c.readerLoop()
@@ -92,12 +92,15 @@ func NewConnection(nodeID string, reader io.Reader, writer io.Writer, receiver M
// Index writes the list of file information to the connected peer node
func (c *Connection) Index(idx []FileInfo) {
c.wLock.Lock()
defer c.wLock.Unlock()
c.mwriter.writeHeader(header{0, c.nextId, messageTypeIndex})
c.nextId = (c.nextId + 1) & 0xfff
c.mwriter.writeIndex(idx)
c.flush()
err := c.flush()
c.nextId = (c.nextId + 1) & 0xfff
c.wLock.Unlock()
if err != nil || c.mwriter.err != nil {
c.close()
return
}
}
// Request returns the bytes for the specified block after fetching them from the connected peer.
@@ -107,7 +110,17 @@ func (c *Connection) Request(name string, offset uint64, size uint32, hash []byt
c.awaiting[c.nextId] = rc
c.mwriter.writeHeader(header{0, c.nextId, messageTypeRequest})
c.mwriter.writeRequest(request{name, offset, size, hash})
c.flush()
if c.mwriter.err != nil {
c.wLock.Unlock()
c.close()
return nil, c.mwriter.err
}
err := c.flush()
if err != nil {
c.wLock.Unlock()
c.close()
return nil, err
}
c.nextId = (c.nextId + 1) & 0xfff
c.wLock.Unlock()
@@ -123,7 +136,12 @@ func (c *Connection) Ping() bool {
rc := make(chan asyncResult)
c.awaiting[c.nextId] = rc
c.mwriter.writeHeader(header{0, c.nextId, messageTypePing})
c.flush()
err := c.flush()
if err != nil || c.mwriter.err != nil {
c.wLock.Unlock()
c.close()
return false
}
c.nextId = (c.nextId + 1) & 0xfff
c.wLock.Unlock()
@@ -138,18 +156,20 @@ type flusher interface {
Flush() error
}
func (c *Connection) flush() {
func (c *Connection) flush() error {
if f, ok := c.writer.(flusher); ok {
f.Flush()
return f.Flush()
}
return nil
}
func (c *Connection) close() {
c.closedLock.Lock()
c.closed = true
c.closedLock.Unlock()
c.wLock.Lock()
if c.closed {
c.wLock.Unlock()
return
}
c.closed = true
for _, ch := range c.awaiting {
close(ch)
}
@@ -160,8 +180,8 @@ func (c *Connection) close() {
}
func (c *Connection) isClosed() bool {
c.closedLock.RLock()
defer c.closedLock.RUnlock()
c.wLock.RLock()
defer c.wLock.RUnlock()
return c.closed
}
@@ -215,9 +235,9 @@ func (c *Connection) readerLoop() {
case messageTypePing:
c.wLock.Lock()
c.mwriter.writeUint32(encodeHeader(header{0, hdr.msgID, messageTypePong}))
c.flush()
err := c.flush()
c.wLock.Unlock()
if c.mwriter.err != nil {
if err != nil || c.mwriter.err != nil {
c.close()
}
@@ -248,9 +268,12 @@ func (c *Connection) processRequest(msgID int) {
c.wLock.Lock()
c.mwriter.writeUint32(encodeHeader(header{0, msgID, messageTypeResponse}))
c.mwriter.writeResponse(data)
buffers.Put(data)
c.flush()
err := c.flush()
c.wLock.Unlock()
buffers.Put(data)
if c.mwriter.err != nil || err != nil {
c.close()
}
}()
}
}