Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memoize AscIfDefault sorting function #44

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 24 additions & 26 deletions ifaddrs.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,34 +104,29 @@ func AscIfAddress(p1Ptr, p2Ptr *IfAddr) int {
// AscIfDefault is a sorting function to sort IfAddrs by whether or not they
// have a default route or not. Non-equal types are deferred in the sort.
//
// FIXME: This is a particularly expensive sorting operation because of the
// non-memoized calls to NewRouteInfo(). In an ideal world the routeInfo data
// once at the start of the sort and pass it along as a context or by wrapping
// the IfAddr type with this information (this would also solve the inability to
// return errors and the possibility of failing silently). Fortunately,
// N*log(N) where N = 3 is only ~6.2 invocations. Not ideal, but not worth
// optimizing today. The common case is this gets called once or twice.
// Patches welcome.
func AscIfDefault(p1Ptr, p2Ptr *IfAddr) int {
// Returns a sorting function containing a memoized default interface name.
func AscIfDefault() func(p1Ptr, p2Ptr *IfAddr) int {
ri, err := NewRouteInfo()
if err != nil {
return sortDeferDecision
return func(p1Ptr, p2Ptr *IfAddr) int { return sortDeferDecision }
}

defaultIfName, err := ri.GetDefaultInterfaceName()
if err != nil {
return sortDeferDecision
return func(p1Ptr, p2Ptr *IfAddr) int { return sortDeferDecision }
}

switch {
case p1Ptr.Interface.Name == defaultIfName && p2Ptr.Interface.Name == defaultIfName:
return sortDeferDecision
case p1Ptr.Interface.Name == defaultIfName:
return sortReceiverBeforeArg
case p2Ptr.Interface.Name == defaultIfName:
return sortArgBeforeReceiver
default:
return sortDeferDecision
return func(p1Ptr, p2Ptr *IfAddr) int {
switch {
case p1Ptr.Interface.Name == defaultIfName && p2Ptr.Interface.Name == defaultIfName:
return sortDeferDecision
case p1Ptr.Interface.Name == defaultIfName:
return sortReceiverBeforeArg
case p2Ptr.Interface.Name == defaultIfName:
return sortArgBeforeReceiver
default:
return sortDeferDecision
}
}
}

Expand Down Expand Up @@ -172,8 +167,11 @@ func DescIfAddress(p1Ptr, p2Ptr *IfAddr) int {
}

// DescIfDefault is identical to AscIfDefault but reverse ordered.
func DescIfDefault(p1Ptr, p2Ptr *IfAddr) int {
return -1 * AscIfDefault(p1Ptr, p2Ptr)
func DescIfDefault() func(p1Ptr, p2Ptr *IfAddr) int {
ascIfDefault := AscIfDefault()
return func(p1Ptr, p2Ptr *IfAddr) int {
return -1 * ascIfDefault(p1Ptr, p2Ptr)
}
}

// DescIfName is identical to AscIfName but reverse ordered.
Expand Down Expand Up @@ -330,7 +328,7 @@ func GetPrivateInterfaces() (IfAddrs, error) {
return IfAddrs{}, nil
}

OrderedIfAddrBy(AscIfDefault, AscIfType, AscIfNetworkSize).Sort(privateIfs)
OrderedIfAddrBy(AscIfDefault(), AscIfType, AscIfNetworkSize).Sort(privateIfs)

privateIfs, _, err = IfByRFC("6890", privateIfs)
if err != nil {
Expand Down Expand Up @@ -378,7 +376,7 @@ func GetPublicInterfaces() (IfAddrs, error) {
return IfAddrs{}, nil
}

OrderedIfAddrBy(AscIfDefault, AscIfType, AscIfNetworkSize).Sort(publicIfs)
OrderedIfAddrBy(AscIfDefault(), AscIfType, AscIfNetworkSize).Sort(publicIfs)

_, publicIfs, err = IfByRFC("6890", publicIfs)
if err != nil {
Expand Down Expand Up @@ -1045,9 +1043,9 @@ func SortIfBy(selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, error) {
case "-address":
sortFuncs[i] = DescIfAddress
case "+default", "default":
sortFuncs[i] = AscIfDefault
sortFuncs[i] = AscIfDefault()
case "-default":
sortFuncs[i] = DescIfDefault
sortFuncs[i] = DescIfDefault()
case "+name", "name":
// The "name" selector returns an array of IfAddrs
// ordered by the interface name.
Expand Down