You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: portallocator.go
    path of file: ./repos/moby/vendor/github.com/moby/swarmkit/v2/manager/allocator/cnmallocator
    
    the code of the file until where you have to start completion: package cnmallocator

import (
	"github.com/moby/swarmkit/v2/api"
	"github.com/moby/swarmkit/v2/internal/idm"
)

const (
	// Start of the dynamic port range from which node ports will
	// be allocated when the user did not specify a port.
	dynamicPortStart = 30000

	// End of the dynamic port range from which node ports will be
	// allocated when the user did not specify a port.
	dynamicPortEnd = 32767

	// The start of master port range which will hold all the
	// allocation state of ports allocated so far regardless of
	// whether it was user defined or not.
	masterPortStart = 1

	// The end of master port range which will hold all the
	// allocation state of ports allocated so far regardless of
	// whether it was user defined or not.
	masterPortEnd = 65535
)

type portAllocator struct {
	// portspace definition per protocol
	portSpaces map[api.PortConfig_Protocol]*portSpace
}

type portSpace struct {
	protocol         api.PortConfig_Protocol
	masterPortSpace  *idm.IDM
	dynamicPortSpace *idm.IDM
}

type allocatedPorts map[api.PortConfig]map[uint32]*api.PortConfig

// addState add the state of an allocated port to the collection.
// `a
    
func reconcilePortConfigs(s *api.Service) []*api.PortConfig {
	// If runtime state hasn't been created or if port config has
	// changed from port state return the port config from Spec.
	if s.Endpoint == nil || len(s.Spec.Endpoint.Ports) != len(s.Endpoint.Ports) {
		return s.Spec.Endpoint.Ports
	}

	portStates := allocatedPorts{}
	for _, portState := range s.Endpoint.Ports {
		if portState.PublishMode == api.PublishModeIngress {
			portStates.addState(portState)
		}
	}

	var portConfigs []*api.PortConfig

	// Process the portConfig with portConfig.PublishMode != api.PublishModeIngress
	// and PublishedPort != 0 (high priority)
	for _, portConfig := range s.Spec.Endpoint.Ports {
		if portConfig.PublishMode != api.PublishModeIngress {
			// If the PublishMode is not Ingress simply pick up the port config.
			portConfigs = append(portConfigs, portConfig)
		} else if portConfig.PublishedPort != 0 {
			// Otherwise we only process PublishedPort != 0 in this round

			// Remove record from portState
			portStates.delState(portConfig)

			// For PublishedPort != 0 prefer the portConfig
			portConfigs = append(portConfigs, portConfig)
		}
	}

	// Iterate portConfigs with PublishedPort == 0 (low priority)
	for _, portConfig := range s.Spec.Endpoint.Ports {
		// Ignore ports which are not PublishModeIngress (already processed)
		// And we only process PublishedPort == 0 in this round
		// So the following:
		//  `portConfig.PublishMode == api.PublishModeIngress && portConfig.PublishedPort == 0`
		if portConfig.PublishMode == api.PublishModeIngress && portConfig.PublishedPort == 0 {
			// If the portConfig is exactly the same as portState
			// except if SwarmPort is not user-define then prefer
			// portState to ensure sticky allocation of the same
			// port that was allocated before.

			// Remove record from portState
			if portState := portStates.delState(portConfig); portState != nil {
				portConfigs = append(portConfigs, portState)
				continue
			}

			// For all other cases prefer the portConfig
			portConfigs = append(portConfigs, portConfig)
		}
	}

	return portConfigs
}