type PortAllocationOperation … // Creates a portAllocationOperation, tracking a set of allocations & releases // If dryRun is specified, never actually allocate or release anything func StartOperation(pa Interface, dryRun bool) *PortAllocationOperation { … } // Will rollback unless marked as shouldRollback = false by a Commit(). Call from a defer block func (op *PortAllocationOperation) Finish() { … } // (Try to) undo any operations we did func (op *PortAllocationOperation) Rollback() []error { … } // (Try to) perform any deferred operations. // Note that even if this fails, we don't rollback; we always want to err on the side of over-allocation, // and Commit should be called _after_ the owner is written func (op *PortAllocationOperation) Commit() []error { … } // Allocates a port, and record it for future rollback func (op *PortAllocationOperation) Allocate(port int) error { … } // Allocates a port, and record it for future rollback func (op *PortAllocationOperation) AllocateNext() (int, error) { … } // Marks a port so that it will be released if this operation Commits func (op *PortAllocationOperation) ReleaseDeferred(port int) { … }