From 63d18d875b8a136d59c98b7b571366b10b5d4f76 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Wed, 22 Jan 2014 16:00:53 -0800 Subject: [PATCH] Implement basic stack for ips Docker-DCO-1.1-Signed-off-by: Guillaume J. Charmes (github: creack) --- networkdriver/portallocator/allocator.go | 2 +- networkdriver/portallocator/ipset.go | 62 ++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 networkdriver/portallocator/ipset.go diff --git a/networkdriver/portallocator/allocator.go b/networkdriver/portallocator/allocator.go index 5d8e812309..3704fae485 100644 --- a/networkdriver/portallocator/allocator.go +++ b/networkdriver/portallocator/allocator.go @@ -5,11 +5,11 @@ import ( "errors" "github.com/dotcloud/docker/pkg/netlink" "net" + "sort" "sync" ) type networkSet map[iPNet]iPSet -type iPSet map[string]struct{} type iPNet struct { IP string diff --git a/networkdriver/portallocator/ipset.go b/networkdriver/portallocator/ipset.go new file mode 100644 index 0000000000..b7737bdb73 --- /dev/null +++ b/networkdriver/portallocator/ipset.go @@ -0,0 +1,62 @@ +package ipallocator + +import ( + "sync" +) + +// iPSet is a thread-safe sorted set and a stack. +type iPSet struct { + sync.RWMutex + set []string +} + +// Push takes a string and adds it to the set. If the elem aready exists, it has no effect. +func (s *iPSet) Push(elem string) { + s.RLock() + for i, e := range s.set { + if e == elem { + s.RUnlock() + return + } + } + s.RUnlock() + + s.Lock() + s.set = append(s.set, elem) + // Make sure the list is always sorted + sort.Strings(s.set) + s.Unlock() +} + +// Pop returns the first elemen from the list and removes it. +// If the list is empty, it returns an empty string +func (s *iPSet) Pop() string { + s.RLock() + + for i, e := range s.set { + ret := e + s.RUnlock() + s.Lock() + s.set = append(s.set[:i], s.set[i+1:]...) + s.Unlock() + return e + } + s.RUnlock() + return "" +} + +// Remove removes an element from the list. +// If the element is not found, it has no effect. +func (s *iPSet) Remove(elem string) { + for i, e := range s.set { + if e == elem { + s.set = append(s.set[:i], s.set[i+1:]...) + return + } + } +} + +// Len returns the length of the list. +func (s *iPSet) Len() int { + return len(s.set) +}