diff --git a/libnetwork/idm/idm.go b/libnetwork/idm/idm.go index 84839c1c9b..20be113c83 100644 --- a/libnetwork/idm/idm.go +++ b/libnetwork/idm/idm.go @@ -15,7 +15,7 @@ type Idm struct { handle *bitseq.Handle } -// New returns an instance of id manager for a set of [start-end] numerical ids +// New returns an instance of id manager for a [start,end] set of numerical ids func New(ds datastore.DataStore, id string, start, end uint64) (*Idm, error) { if id == "" { return nil, fmt.Errorf("Invalid id") @@ -54,7 +54,7 @@ func (i *Idm) GetSpecificID(id uint64) error { return i.handle.Set(id - i.start) } -// GetIDInRange returns the first available id in the set within a range +// GetIDInRange returns the first available id in the set within a [start,end] range func (i *Idm) GetIDInRange(start, end uint64) (uint64, error) { if i.handle == nil { return 0, fmt.Errorf("ID set is not initialized") @@ -64,7 +64,9 @@ func (i *Idm) GetIDInRange(start, end uint64) (uint64, error) { return 0, fmt.Errorf("Requested range does not belong to the set") } - return i.handle.SetAnyInRange(start, end-start) + ordinal, err := i.handle.SetAnyInRange(start-i.start, end-i.start) + + return i.start + ordinal, err } // Release releases the specified id diff --git a/libnetwork/idm/idm_test.go b/libnetwork/idm/idm_test.go index 658755c93f..2100943a55 100644 --- a/libnetwork/idm/idm_test.go +++ b/libnetwork/idm/idm_test.go @@ -108,3 +108,129 @@ func TestUninitialized(t *testing.T) { t.Fatalf("Expected failure but succeeded") } } + +func TestAllocateInRange(t *testing.T) { + i, err := New(nil, "myset", 5, 10) + if err != nil { + t.Fatal(err) + } + + o, err := i.GetIDInRange(6, 6) + if err != nil { + t.Fatal(err) + } + if o != 6 { + t.Fatalf("Unexpected id returned. Expected: 6. Got: %d", o) + } + + if err = i.GetSpecificID(6); err == nil { + t.Fatalf("Expected failure but succeeded") + } + + o, err = i.GetID() + if err != nil { + t.Fatal(err) + } + if o != 5 { + t.Fatalf("Unexpected id returned. Expected: 5. Got: %d", o) + } + + i.Release(6) + + o, err = i.GetID() + if err != nil { + t.Fatal(err) + } + if o != 6 { + t.Fatalf("Unexpected id returned. Expected: 6. Got: %d", o) + } + + for n := 7; n <= 10; n++ { + o, err := i.GetIDInRange(7, 10) + if err != nil { + t.Fatal(err) + } + if o != uint64(n) { + t.Fatalf("Unexpected id returned. Expected: %d. Got: %d", n, o) + } + } + + if err = i.GetSpecificID(7); err == nil { + t.Fatalf("Expected failure but succeeded") + } + + if err = i.GetSpecificID(10); err == nil { + t.Fatalf("Expected failure but succeeded") + } + + i.Release(10) + + o, err = i.GetIDInRange(5, 10) + if err != nil { + t.Fatal(err) + } + if o != 10 { + t.Fatalf("Unexpected id returned. Expected: 10. Got: %d", o) + } + + i.Release(5) + + o, err = i.GetIDInRange(5, 10) + if err != nil { + t.Fatal(err) + } + if o != 5 { + t.Fatalf("Unexpected id returned. Expected: 5. Got: %d", o) + } + + for n := 5; n <= 10; n++ { + i.Release(uint64(n)) + } + + for n := 5; n <= 10; n++ { + o, err := i.GetIDInRange(5, 10) + if err != nil { + t.Fatal(err) + } + if o != uint64(n) { + t.Fatalf("Unexpected id returned. Expected: %d. Got: %d", n, o) + } + } + + for n := 5; n <= 10; n++ { + if err = i.GetSpecificID(uint64(n)); err == nil { + t.Fatalf("Expected failure but succeeded for id: %d", n) + } + } + + // New larger set + ul := uint64((1 << 24) - 1) + i, err = New(nil, "newset", 0, ul) + if err != nil { + t.Fatal(err) + } + + o, err = i.GetIDInRange(4096, ul) + if err != nil { + t.Fatal(err) + } + if o != 4096 { + t.Fatalf("Unexpected id returned. Expected: 4096. Got: %d", o) + } + + o, err = i.GetIDInRange(4096, ul) + if err != nil { + t.Fatal(err) + } + if o != 4097 { + t.Fatalf("Unexpected id returned. Expected: 4097. Got: %d", o) + } + + o, err = i.GetIDInRange(4096, ul) + if err != nil { + t.Fatal(err) + } + if o != 4098 { + t.Fatalf("Unexpected id returned. Expected: 4098. Got: %d", o) + } +}