瀏覽代碼

Merge pull request #54 from aboch/pa

Port Allocator as a libnetwork package
Jana Radhakrishnan 10 年之前
父節點
當前提交
cf40ea9ea9

+ 1 - 8
libnetwork/drivers/bridge/bridge.go

@@ -23,17 +23,10 @@ const (
 )
 
 var (
-	once        sync.Once
 	ipAllocator *ipallocator.IPAllocator
 	portMapper  *portmapper.PortMapper
 )
 
-func initPortMapper() {
-	once.Do(func() {
-		portMapper = portmapper.New()
-	})
-}
-
 // Configuration info for the "simplebridge" driver.
 type Configuration struct {
 	BridgeName            string
@@ -70,7 +63,7 @@ type driver struct {
 
 func init() {
 	ipAllocator = ipallocator.New()
-	initPortMapper()
+	portMapper = portmapper.New()
 }
 
 // New provides a new instance of bridge driver instance

+ 13 - 0
libnetwork/portallocator/portallocator.go → libnetwork/pkg/portallocator/portallocator.go

@@ -26,6 +26,9 @@ var (
 	// ErrUnknownProtocol is returned when an unknown protocol was specified
 	ErrUnknownProtocol = errors.New("unknown protocol")
 	defaultIP          = net.ParseIP("0.0.0.0")
+	once               sync.Once
+	instance           *PortAllocator
+	createInstance     = func() { instance = newInstance() }
 )
 
 // ErrPortAlreadyAllocated is the returned error information when a requested port is already being used
@@ -79,6 +82,16 @@ type (
 
 // New returns a new instance of PortAllocator
 func New() *PortAllocator {
+	// Port Allocator is a singleton
+	// Note: Long term solution will be each PortAllocator will have access to
+	// the OS so that it can have up to date view of the OS port allocation.
+	// When this happens singleton behavior will be removed. Clients do not
+	// need to worry about this, they will not see a change in behavior.
+	once.Do(createInstance)
+	return instance
+}
+
+func newInstance() *PortAllocator {
 	start, end, err := getDynamicPortRange()
 	if err != nil {
 		logrus.Warn(err)

+ 13 - 0
libnetwork/portallocator/portallocator_test.go → libnetwork/pkg/portallocator/portallocator_test.go

@@ -5,8 +5,13 @@ import (
 	"testing"
 )
 
+func resetPortAllocator() {
+	instance = newInstance()
+}
+
 func TestRequestNewPort(t *testing.T) {
 	p := New()
+	defer resetPortAllocator()
 
 	port, err := p.RequestPort(defaultIP, "tcp", 0)
 	if err != nil {
@@ -20,11 +25,13 @@ func TestRequestNewPort(t *testing.T) {
 
 func TestRequestSpecificPort(t *testing.T) {
 	p := New()
+	defer resetPortAllocator()
 
 	port, err := p.RequestPort(defaultIP, "tcp", 5000)
 	if err != nil {
 		t.Fatal(err)
 	}
+
 	if port != 5000 {
 		t.Fatalf("Expected port 5000 got %d", port)
 	}
@@ -48,6 +55,7 @@ func TestReleasePort(t *testing.T) {
 
 func TestReuseReleasedPort(t *testing.T) {
 	p := New()
+	defer resetPortAllocator()
 
 	port, err := p.RequestPort(defaultIP, "tcp", 5000)
 	if err != nil {
@@ -69,6 +77,7 @@ func TestReuseReleasedPort(t *testing.T) {
 
 func TestReleaseUnreadledPort(t *testing.T) {
 	p := New()
+	defer resetPortAllocator()
 
 	port, err := p.RequestPort(defaultIP, "tcp", 5000)
 	if err != nil {
@@ -95,6 +104,7 @@ func TestUnknowProtocol(t *testing.T) {
 
 func TestAllocateAllPorts(t *testing.T) {
 	p := New()
+	defer resetPortAllocator()
 
 	for i := 0; i <= p.End-p.Begin; i++ {
 		port, err := p.RequestPort(defaultIP, "tcp", 0)
@@ -145,6 +155,7 @@ func TestAllocateAllPorts(t *testing.T) {
 
 func BenchmarkAllocatePorts(b *testing.B) {
 	p := New()
+	defer resetPortAllocator()
 
 	for i := 0; i < b.N; i++ {
 		for i := 0; i <= p.End-p.Begin; i++ {
@@ -163,6 +174,7 @@ func BenchmarkAllocatePorts(b *testing.B) {
 
 func TestPortAllocation(t *testing.T) {
 	p := New()
+	defer resetPortAllocator()
 
 	ip := net.ParseIP("192.168.0.1")
 	ip2 := net.ParseIP("192.168.0.2")
@@ -224,6 +236,7 @@ func TestPortAllocation(t *testing.T) {
 
 func TestNoDuplicateBPR(t *testing.T) {
 	p := New()
+	defer resetPortAllocator()
 
 	if port, err := p.RequestPort(defaultIP, "tcp", p.Begin); err != nil {
 		t.Fatal(err)

+ 1 - 1
libnetwork/portmapper/mapper.go

@@ -8,7 +8,7 @@ import (
 
 	"github.com/Sirupsen/logrus"
 	"github.com/docker/docker/pkg/iptables"
-	"github.com/docker/libnetwork/portallocator"
+	"github.com/docker/libnetwork/pkg/portallocator"
 )
 
 type mapping struct {