diff --git a/libnetwork/bitseq/sequence.go b/libnetwork/bitseq/sequence.go index 6a3dc9f7ac..70a0e7a987 100644 --- a/libnetwork/bitseq/sequence.go +++ b/libnetwork/bitseq/sequence.go @@ -7,7 +7,6 @@ import ( "fmt" "sync" - "github.com/docker/libkv/store" "github.com/docker/libnetwork/datastore" "github.com/docker/libnetwork/netutils" ) @@ -59,13 +58,16 @@ func NewHandle(app string, ds datastore.DataStore, id string, numElements uint32 // (GetObject() does not set it): It is ok for now, // it will only cause the first allocation on this // node to go through a retry. - var bs []byte - if err := h.store.GetObject(datastore.Key(h.Key()...), bs); err == nil { - h.FromByteArray(bs) - } else if err != store.ErrKeyNotFound { - return nil, err + var bah []byte + if err := h.store.GetObject(datastore.Key(h.Key()...), &bah); err != nil { + if err != datastore.ErrKeyNotFound { + return nil, err + } + return h, nil } - return h, nil + err := h.FromByteArray(bah) + + return h, err } // Sequence reresents a recurring sequence of 32 bits long bitmasks @@ -159,7 +161,7 @@ func (s *Sequence) ToByteArray() ([]byte, error) { func (s *Sequence) FromByteArray(data []byte) error { l := len(data) if l%8 != 0 { - return fmt.Errorf("cannot deserialize byte sequence of lenght %d", l) + return fmt.Errorf("cannot deserialize byte sequence of lenght %d (%v)", l, data) } p := s @@ -212,6 +214,7 @@ func (h *Handle) PushReservation(bytePos, bitPos int, release bool) error { } else { h.unselected-- } + h.dbIndex = nh.dbIndex h.Unlock() } @@ -233,7 +236,7 @@ func (h *Handle) ToByteArray() ([]byte, error) { copy(ba[4:8], netutils.U32ToA(h.unselected)) bm, err := h.head.ToByteArray() if err != nil { - return nil, err + return nil, fmt.Errorf("failed to serialize head: %s", err.Error()) } ba = append(ba, bm...) @@ -242,10 +245,14 @@ func (h *Handle) ToByteArray() ([]byte, error) { // FromByteArray reads his handle's data from a byte array func (h *Handle) FromByteArray(ba []byte) error { + if ba == nil { + return fmt.Errorf("nil byte array") + } + nh := &Sequence{} err := nh.FromByteArray(ba[8:]) if err != nil { - return err + return fmt.Errorf("failed to deserialize head: %s", err.Error()) } h.Lock() diff --git a/libnetwork/bitseq/store.go b/libnetwork/bitseq/store.go index bbbe4c29ae..8f4a2669ec 100644 --- a/libnetwork/bitseq/store.go +++ b/libnetwork/bitseq/store.go @@ -1,6 +1,10 @@ package bitseq import ( + "encoding/json" + "fmt" + + log "github.com/Sirupsen/logrus" "github.com/docker/libnetwork/datastore" "github.com/docker/libnetwork/types" ) @@ -23,9 +27,15 @@ func (h *Handle) KeyPrefix() []string { func (h *Handle) Value() []byte { b, err := h.ToByteArray() if err != nil { + log.Warnf("Failed to serialize Handle: %v", err) + b = []byte{} + } + jv, err := json.Marshal(b) + if err != nil { + log.Warnf("Failed to json encode bitseq handler byte array: %v", err) return []byte{} } - return b + return jv } // Index returns the latest DB Index as seen by this object @@ -61,10 +71,14 @@ func (h *Handle) watchForChanges() error { case kvPair := <-kvpChan: // Only process remote update if kvPair != nil && (kvPair.LastIndex != h.getDBIndex()) { - h.Lock() - h.dbIndex = kvPair.LastIndex - h.Unlock() - h.FromByteArray(kvPair.Value) + err := h.fromDsValue(kvPair.Value) + if err != nil { + log.Warnf("Failed to reconstruct bitseq handle from ds watch: %s", err.Error()) + } else { + h.Lock() + h.dbIndex = kvPair.LastIndex + h.Unlock() + } } } } @@ -72,6 +86,17 @@ func (h *Handle) watchForChanges() error { return nil } +func (h *Handle) fromDsValue(value []byte) error { + var ba []byte + if err := json.Unmarshal(value, &ba); err != nil { + return fmt.Errorf("failed to decode json: %s", err.Error()) + } + if err := h.FromByteArray(ba); err != nil { + return fmt.Errorf("failed to decode handle: %s", err.Error()) + } + return nil +} + func (h *Handle) writeToStore() error { h.Lock() store := h.store diff --git a/libnetwork/idm/idm.go b/libnetwork/idm/idm.go index 0057091c9d..2321d77ea4 100644 --- a/libnetwork/idm/idm.go +++ b/libnetwork/idm/idm.go @@ -27,7 +27,7 @@ func New(ds datastore.DataStore, id string, start, end uint32) (*Idm, error) { h, err := bitseq.NewHandle("idm", ds, id, uint32(1+end-start)) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to initialize bit sequence handler: %s", err.Error()) } return &Idm{start: start, end: end, handle: h}, nil