Commit 379cc163 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 59333e47
...@@ -403,6 +403,7 @@ func (c *Conn) errRecvShutdown() error { ...@@ -403,6 +403,7 @@ func (c *Conn) errRecvShutdown() error {
// recvPkt receives raw packet from connection // recvPkt receives raw packet from connection
func (c *Conn) recvPkt() (*PktBuf, error) { func (c *Conn) recvPkt() (*PktBuf, error) {
select { select {
// XXX maybe possible to detect "down" by seeing c.rxq is closed?
case <-c.down: case <-c.down:
return nil, c.err("recv", c.errRecvShutdown()) return nil, c.err("recv", c.errRecvShutdown())
......
...@@ -250,7 +250,7 @@ func TestMasterStorage(t *testing.T) { ...@@ -250,7 +250,7 @@ func TestMasterStorage(t *testing.T) {
tc.Expect(netconnect("s:2", "m:2", "m:1")) tc.Expect(netconnect("s:2", "m:2", "m:1"))
tc.Expect(conntx("s:2", "m:2", 1, &neo.RequestIdentification{ tc.Expect(conntx("s:2", "m:2", 1, &neo.RequestIdentification{
NodeType: neo.STORAGE, NodeType: neo.STORAGE,
NodeUUID: 0, UUID: 0,
Address: xnaddr("s:1"), Address: xnaddr("s:1"),
ClusterName: "abc1", ClusterName: "abc1",
IdTimestamp: 0, IdTimestamp: 0,
...@@ -260,10 +260,10 @@ func TestMasterStorage(t *testing.T) { ...@@ -260,10 +260,10 @@ func TestMasterStorage(t *testing.T) {
tc.Expect(conntx("m:2", "s:2", 1, &neo.AcceptIdentification{ tc.Expect(conntx("m:2", "s:2", 1, &neo.AcceptIdentification{
NodeType: neo.MASTER, NodeType: neo.MASTER,
MyNodeUUID: neo.UUID(neo.MASTER, 1), MyUUID: neo.UUID(neo.MASTER, 1),
NumPartitions: 1, NumPartitions: 1,
NumReplicas: 1, NumReplicas: 1,
YourNodeUUID: neo.UUID(neo.STORAGE, 1), YourUUID: neo.UUID(neo.STORAGE, 1),
})) }))
// TODO test ID rejects (uuid already registered, ...) // TODO test ID rejects (uuid already registered, ...)
...@@ -313,8 +313,8 @@ func TestMasterStorage(t *testing.T) { ...@@ -313,8 +313,8 @@ func TestMasterStorage(t *testing.T) {
TidDict: nil, // map[zodb.Tid]zodb.Tid{}, TidDict: nil, // map[zodb.Tid]zodb.Tid{},
})) }))
lastOid, err1 := zstor.LastOid() lastOid, err1 := zstor.LastOid(context.TODO())
lastTid, err2 := zstor.LastTid() lastTid, err2 := zstor.LastTid(context.TODO())
exc.Raiseif(xerr.Merge(err1, err2)) exc.Raiseif(xerr.Merge(err1, err2))
tc.Expect(conntx("m:2", "s:2", 1, &neo.LastIDs{})) tc.Expect(conntx("m:2", "s:2", 1, &neo.LastIDs{}))
tc.Expect(conntx("s:2", "m:2", 1, &neo.AnswerLastIDs{ tc.Expect(conntx("s:2", "m:2", 1, &neo.AnswerLastIDs{
......
...@@ -47,21 +47,7 @@ type Server interface { ...@@ -47,21 +47,7 @@ type Server interface {
// the listener is closed when Serve returns. // the listener is closed when Serve returns.
func Serve(ctx context.Context, l *neo.Listener, srv Server) error { func Serve(ctx context.Context, l *neo.Listener, srv Server) error {
fmt.Printf("xxx: serving on %s ...\n", l.Addr()) // XXX 'xxx' -> ? fmt.Printf("xxx: serving on %s ...\n", l.Addr()) // XXX 'xxx' -> ?
defer xio.CloseWhenDone(ctx, l)()
// close listener when either cancelling or returning (e.g. due to an error)
// ( when cancelling - listener close will signal to all accepts to
// terminate with an error )
// XXX dup -> utility
retch := make(chan struct{})
defer func() { close(retch) }()
go func() {
select {
case <-ctx.Done():
// XXX err = cancelled
case <-retch:
}
l.Close() // XXX err
}()
// main Accept -> ServeLink loop // main Accept -> ServeLink loop
for { for {
......
...@@ -32,6 +32,7 @@ import ( ...@@ -32,6 +32,7 @@ import (
"lab.nexedi.com/kirr/neo/go/xcommon/task" "lab.nexedi.com/kirr/neo/go/xcommon/task"
"lab.nexedi.com/kirr/neo/go/xcommon/xnet" "lab.nexedi.com/kirr/neo/go/xcommon/xnet"
"lab.nexedi.com/kirr/neo/go/xcommon/xcontext" "lab.nexedi.com/kirr/neo/go/xcommon/xcontext"
"lab.nexedi.com/kirr/neo/go/xcommon/xio"
"lab.nexedi.com/kirr/go123/xerr" "lab.nexedi.com/kirr/go123/xerr"
) )
...@@ -410,26 +411,9 @@ func (stor *Storage) m1serve(ctx context.Context, Mconn *neo.Conn) (err error) { ...@@ -410,26 +411,9 @@ func (stor *Storage) m1serve(ctx context.Context, Mconn *neo.Conn) (err error) {
// --- serve incoming connections from other nodes --- // --- serve incoming connections from other nodes ---
// ServeLink serves incoming node-node link connection // ServeLink serves incoming node-node link connection
// XXX +error return? func (stor *Storage) ServeLink(ctx context.Context, link *neo.NodeLink) (err error) {
func (stor *Storage) ServeLink(ctx context.Context, link *neo.NodeLink) { defer task.Runningf(&ctx, "serve %s", link)(&err)
log.Infof(ctx, "%s: serving new node", link) // XXX -> running? defer xio.CloseWhenDone(ctx, link)()
// close link when either cancelling or returning (e.g. due to an error)
// ( when cancelling - link.Close will signal to all current IO to
// terminate with an error )
// XXX dup -> utility
retch := make(chan struct{})
defer func() { close(retch) }()
go func() {
select {
case <-ctx.Done():
// XXX tell peers we are shutting down?
// XXX ret err = ctx.Err()
case <-retch:
}
log.Info(ctx, "%v: closing link", link)
link.Close() // XXX err
}()
// XXX only accept clients // XXX only accept clients
// XXX only accept when operational (?) // XXX only accept when operational (?)
...@@ -463,6 +447,8 @@ func (stor *Storage) ServeLink(ctx context.Context, link *neo.NodeLink) { ...@@ -463,6 +447,8 @@ func (stor *Storage) ServeLink(ctx context.Context, link *neo.NodeLink) {
} }
// TODO wait all spawned serveConn // TODO wait all spawned serveConn
return nil
} }
// withWhileOperational derives new context from ctx which will be cancelled, when either // withWhileOperational derives new context from ctx which will be cancelled, when either
......
...@@ -170,3 +170,29 @@ func Canceled(err error) bool { ...@@ -170,3 +170,29 @@ func Canceled(err error) bool {
return false return false
} }
// WhenDone arranges f to be called either when ctx is cancelled or surrounding
// function returns.
//
// To work as intended it should be called under defer like this:
//
// func myfunc(ctx, ...) {
// defer xcontext.WhenDone(ctx, func() { ... })()
func WhenDone(ctx context.Context, f func()) func() {
done := make(chan struct{})
go func() {
select {
case <-ctx.Done():
// ok
case <-done:
// ok
}
f()
}()
return func() {
close(done)
}
}
...@@ -4,10 +4,14 @@ ...@@ -4,10 +4,14 @@
package xio package xio
import ( import (
"context"
"fmt" "fmt"
"io" "io"
"net" "net"
"os" "os"
"lab.nexedi.com/kirr/neo/go/xcommon/log"
"lab.nexedi.com/kirr/neo/go/xcommon/xcontext"
) )
// XXX interface for a Reader/Writer which can report position // XXX interface for a Reader/Writer which can report position
...@@ -82,3 +86,22 @@ func Name(f interface {}) string { ...@@ -82,3 +86,22 @@ func Name(f interface {}) string {
return fmt.Sprintf("%#v", f) return fmt.Sprintf("%#v", f)
} }
} }
// CloseWhenDone arranges for c to be closed either when ctx is cancelled or
// surrounding function returns.
//
// To work as intended it should be called under defer like this:
//
// func myfunc(ctx, ...) {
// defer xio.CloseWhenDone(ctx, c)()
//
// The error - if c.Close() returns with any - is logged.
func CloseWhenDone(ctx context.Context, c io.Closer) func() {
return xcontext.WhenDone(ctx, func() {
err := c.Close()
if err != nil {
log.Error(ctx, err)
}
})
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment