...
1
16
17 package portallocator
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 type PortAllocationOperation struct {
34 pa Interface
35 allocated []int
36 releaseDeferred []int
37 shouldRollback bool
38 dryRun bool
39 }
40
41
42
43 func StartOperation(pa Interface, dryRun bool) *PortAllocationOperation {
44 op := &PortAllocationOperation{}
45 op.pa = pa
46 op.allocated = []int{}
47 op.releaseDeferred = []int{}
48 op.shouldRollback = true
49 op.dryRun = dryRun
50 return op
51 }
52
53
54 func (op *PortAllocationOperation) Finish() {
55 if op.shouldRollback {
56 op.Rollback()
57 }
58 }
59
60
61 func (op *PortAllocationOperation) Rollback() []error {
62 if op.dryRun {
63 return nil
64 }
65
66 errors := []error{}
67
68 for _, allocated := range op.allocated {
69 err := op.pa.Release(allocated)
70 if err != nil {
71 errors = append(errors, err)
72 }
73 }
74
75 if len(errors) == 0 {
76 return nil
77 }
78 return errors
79 }
80
81
82
83
84 func (op *PortAllocationOperation) Commit() []error {
85 if op.dryRun {
86 return nil
87 }
88
89 errors := []error{}
90
91 for _, release := range op.releaseDeferred {
92 err := op.pa.Release(release)
93 if err != nil {
94 errors = append(errors, err)
95 }
96 }
97
98
99
100 op.shouldRollback = false
101
102 if len(errors) == 0 {
103 return nil
104 }
105
106 return errors
107 }
108
109
110 func (op *PortAllocationOperation) Allocate(port int) error {
111 if op.dryRun {
112 if op.pa.Has(port) {
113 return ErrAllocated
114 }
115 for _, a := range op.allocated {
116 if port == a {
117 return ErrAllocated
118 }
119 }
120 op.allocated = append(op.allocated, port)
121 return nil
122 }
123
124 err := op.pa.Allocate(port)
125 if err == nil {
126 op.allocated = append(op.allocated, port)
127 }
128 return err
129 }
130
131
132 func (op *PortAllocationOperation) AllocateNext() (int, error) {
133 if op.dryRun {
134
135
136
137 var lastPort int
138 for _, allocatedPort := range op.allocated {
139 if allocatedPort > lastPort {
140 lastPort = allocatedPort
141 }
142 }
143 if len(op.allocated) == 0 {
144 lastPort = 32768
145 }
146
147
148
149
150 for port := lastPort + 1; port < 100; port++ {
151 err := op.Allocate(port)
152 if err == nil {
153 return port, nil
154 }
155 }
156 op.allocated = append(op.allocated, lastPort+1)
157 return lastPort + 1, nil
158 }
159
160 port, err := op.pa.AllocateNext()
161 if err == nil {
162 op.allocated = append(op.allocated, port)
163 }
164 return port, err
165 }
166
167
168 func (op *PortAllocationOperation) ReleaseDeferred(port int) {
169 op.releaseDeferred = append(op.releaseDeferred, port)
170 }
171
View as plain text