mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
vendor.sh: bump go-patricia to 2.2.4 to fix leaks
Signed-off-by: Cristian Staretu <cristian.staretu@gmail.com>
This commit is contained in:
parent
56cbfc587f
commit
3d714b5ed5
3 changed files with 246 additions and 38 deletions
|
@ -53,7 +53,7 @@ clone git github.com/gorilla/mux e444e69cbd
|
||||||
clone git github.com/kr/pty 5cf931ef8f
|
clone git github.com/kr/pty 5cf931ef8f
|
||||||
clone git github.com/mattn/go-shellwords v1.0.0
|
clone git github.com/mattn/go-shellwords v1.0.0
|
||||||
clone git github.com/mattn/go-sqlite3 v1.1.0
|
clone git github.com/mattn/go-sqlite3 v1.1.0
|
||||||
clone git github.com/tchap/go-patricia v2.1.0
|
clone git github.com/tchap/go-patricia v2.2.4
|
||||||
clone git github.com/vdemeester/shakers 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3
|
clone git github.com/vdemeester/shakers 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3
|
||||||
# forked golang.org/x/net package includes a patch for lazy loading trace templates
|
# forked golang.org/x/net package includes a patch for lazy loading trace templates
|
||||||
clone git golang.org/x/net 2beffdc2e92c8a3027590f898fe88f69af48a3f8 https://github.com/tonistiigi/net.git
|
clone git golang.org/x/net 2beffdc2e92c8a3027590f898fe88f69af48a3f8 https://github.com/tonistiigi/net.git
|
||||||
|
|
|
@ -5,16 +5,22 @@
|
||||||
|
|
||||||
package patricia
|
package patricia
|
||||||
|
|
||||||
import "sort"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"sort"
|
||||||
|
)
|
||||||
|
|
||||||
type childList interface {
|
type childList interface {
|
||||||
length() int
|
length() int
|
||||||
head() *Trie
|
head() *Trie
|
||||||
add(child *Trie) childList
|
add(child *Trie) childList
|
||||||
|
remove(b byte)
|
||||||
replace(b byte, child *Trie)
|
replace(b byte, child *Trie)
|
||||||
remove(child *Trie)
|
|
||||||
next(b byte) *Trie
|
next(b byte) *Trie
|
||||||
walk(prefix *Prefix, visitor VisitorFunc) error
|
walk(prefix *Prefix, visitor VisitorFunc) error
|
||||||
|
print(w io.Writer, indent int)
|
||||||
|
total() int
|
||||||
}
|
}
|
||||||
|
|
||||||
type tries []*Trie
|
type tries []*Trie
|
||||||
|
@ -38,7 +44,7 @@ type sparseChildList struct {
|
||||||
|
|
||||||
func newSparseChildList(maxChildrenPerSparseNode int) childList {
|
func newSparseChildList(maxChildrenPerSparseNode int) childList {
|
||||||
return &sparseChildList{
|
return &sparseChildList{
|
||||||
children: make(tries, 0, DefaultMaxChildrenPerSparseNode),
|
children: make(tries, 0, maxChildrenPerSparseNode),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +67,26 @@ func (list *sparseChildList) add(child *Trie) childList {
|
||||||
return newDenseChildList(list, child)
|
return newDenseChildList(list, child)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (list *sparseChildList) remove(b byte) {
|
||||||
|
for i, node := range list.children {
|
||||||
|
if node.prefix[0] == b {
|
||||||
|
list.children, list.children[len(list.children)-1] =
|
||||||
|
append(list.children[:i], list.children[i+1:]...),
|
||||||
|
nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is not supposed to be reached.
|
||||||
|
panic("removing non-existent child")
|
||||||
|
}
|
||||||
|
|
||||||
func (list *sparseChildList) replace(b byte, child *Trie) {
|
func (list *sparseChildList) replace(b byte, child *Trie) {
|
||||||
|
// Make a consistency check.
|
||||||
|
if p0 := child.prefix[0]; p0 != b {
|
||||||
|
panic(fmt.Errorf("child prefix mismatch: %v != %v", p0, b))
|
||||||
|
}
|
||||||
|
|
||||||
// Seek the child and replace it.
|
// Seek the child and replace it.
|
||||||
for i, node := range list.children {
|
for i, node := range list.children {
|
||||||
if node.prefix[0] == b {
|
if node.prefix[0] == b {
|
||||||
|
@ -71,18 +96,6 @@ func (list *sparseChildList) replace(b byte, child *Trie) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (list *sparseChildList) remove(child *Trie) {
|
|
||||||
for i, node := range list.children {
|
|
||||||
if node.prefix[0] == child.prefix[0] {
|
|
||||||
list.children = append(list.children[:i], list.children[i+1:]...)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is not supposed to be reached.
|
|
||||||
panic("removing non-existent child")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (list *sparseChildList) next(b byte) *Trie {
|
func (list *sparseChildList) next(b byte) *Trie {
|
||||||
for _, child := range list.children {
|
for _, child := range list.children {
|
||||||
if child.prefix[0] == b {
|
if child.prefix[0] == b {
|
||||||
|
@ -120,9 +133,29 @@ func (list *sparseChildList) walk(prefix *Prefix, visitor VisitorFunc) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (list *sparseChildList) total() int {
|
||||||
|
tot := 0
|
||||||
|
for _, child := range list.children {
|
||||||
|
if child != nil {
|
||||||
|
tot = tot + child.total()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tot
|
||||||
|
}
|
||||||
|
|
||||||
|
func (list *sparseChildList) print(w io.Writer, indent int) {
|
||||||
|
for _, child := range list.children {
|
||||||
|
if child != nil {
|
||||||
|
child.print(w, indent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type denseChildList struct {
|
type denseChildList struct {
|
||||||
min int
|
min int
|
||||||
max int
|
max int
|
||||||
|
numChildren int
|
||||||
|
headIndex int
|
||||||
children []*Trie
|
children []*Trie
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,57 +188,87 @@ func newDenseChildList(list *sparseChildList, child *Trie) childList {
|
||||||
}
|
}
|
||||||
children[int(child.prefix[0])-min] = child
|
children[int(child.prefix[0])-min] = child
|
||||||
|
|
||||||
return &denseChildList{min, max, children}
|
return &denseChildList{
|
||||||
|
min: min,
|
||||||
|
max: max,
|
||||||
|
numChildren: list.length() + 1,
|
||||||
|
headIndex: 0,
|
||||||
|
children: children,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (list *denseChildList) length() int {
|
func (list *denseChildList) length() int {
|
||||||
return list.max - list.min + 1
|
return list.numChildren
|
||||||
}
|
}
|
||||||
|
|
||||||
func (list *denseChildList) head() *Trie {
|
func (list *denseChildList) head() *Trie {
|
||||||
return list.children[0]
|
return list.children[list.headIndex]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (list *denseChildList) add(child *Trie) childList {
|
func (list *denseChildList) add(child *Trie) childList {
|
||||||
b := int(child.prefix[0])
|
b := int(child.prefix[0])
|
||||||
|
var i int
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case list.min <= b && b <= list.max:
|
case list.min <= b && b <= list.max:
|
||||||
if list.children[b-list.min] != nil {
|
if list.children[b-list.min] != nil {
|
||||||
panic("dense child list collision detected")
|
panic("dense child list collision detected")
|
||||||
}
|
}
|
||||||
list.children[b-list.min] = child
|
i = b - list.min
|
||||||
|
list.children[i] = child
|
||||||
|
|
||||||
case b < list.min:
|
case b < list.min:
|
||||||
children := make([]*Trie, list.max-b+1)
|
children := make([]*Trie, list.max-b+1)
|
||||||
children[0] = child
|
i = 0
|
||||||
|
children[i] = child
|
||||||
copy(children[list.min-b:], list.children)
|
copy(children[list.min-b:], list.children)
|
||||||
list.children = children
|
list.children = children
|
||||||
list.min = b
|
list.min = b
|
||||||
|
|
||||||
default: // b > list.max
|
default: // b > list.max
|
||||||
children := make([]*Trie, b-list.min+1)
|
children := make([]*Trie, b-list.min+1)
|
||||||
children[b-list.min] = child
|
i = b - list.min
|
||||||
|
children[i] = child
|
||||||
copy(children, list.children)
|
copy(children, list.children)
|
||||||
list.children = children
|
list.children = children
|
||||||
list.max = b
|
list.max = b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
list.numChildren++
|
||||||
|
if i < list.headIndex {
|
||||||
|
list.headIndex = i
|
||||||
|
}
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
func (list *denseChildList) replace(b byte, child *Trie) {
|
func (list *denseChildList) remove(b byte) {
|
||||||
list.children[int(b)-list.min] = nil
|
i := int(b) - list.min
|
||||||
list.children[int(child.prefix[0])-list.min] = child
|
|
||||||
}
|
|
||||||
|
|
||||||
func (list *denseChildList) remove(child *Trie) {
|
|
||||||
i := int(child.prefix[0]) - list.min
|
|
||||||
if list.children[i] == nil {
|
if list.children[i] == nil {
|
||||||
// This is not supposed to be reached.
|
// This is not supposed to be reached.
|
||||||
panic("removing non-existent child")
|
panic("removing non-existent child")
|
||||||
}
|
}
|
||||||
|
list.numChildren--
|
||||||
list.children[i] = nil
|
list.children[i] = nil
|
||||||
|
|
||||||
|
// Update head index.
|
||||||
|
if i == list.headIndex {
|
||||||
|
for ; i < len(list.children); i++ {
|
||||||
|
if list.children[i] != nil {
|
||||||
|
list.headIndex = i
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (list *denseChildList) replace(b byte, child *Trie) {
|
||||||
|
// Make a consistency check.
|
||||||
|
if p0 := child.prefix[0]; p0 != b {
|
||||||
|
panic(fmt.Errorf("child prefix mismatch: %v != %v", p0, b))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace the child.
|
||||||
|
list.children[int(b)-list.min] = child
|
||||||
}
|
}
|
||||||
|
|
||||||
func (list *denseChildList) next(b byte) *Trie {
|
func (list *denseChildList) next(b byte) *Trie {
|
||||||
|
@ -242,3 +305,21 @@ func (list *denseChildList) walk(prefix *Prefix, visitor VisitorFunc) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (list *denseChildList) print(w io.Writer, indent int) {
|
||||||
|
for _, child := range list.children {
|
||||||
|
if child != nil {
|
||||||
|
child.print(w, indent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (list *denseChildList) total() int {
|
||||||
|
tot := 0
|
||||||
|
for _, child := range list.children {
|
||||||
|
if child != nil {
|
||||||
|
tot = tot + child.total()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tot
|
||||||
|
}
|
||||||
|
|
|
@ -6,7 +6,11 @@
|
||||||
package patricia
|
package patricia
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
@ -130,6 +134,21 @@ func (trie *Trie) Visit(visitor VisitorFunc) error {
|
||||||
return trie.walk(nil, visitor)
|
return trie.walk(nil, visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (trie *Trie) size() int {
|
||||||
|
n := 0
|
||||||
|
|
||||||
|
trie.walk(nil, func(prefix Prefix, item Item) error {
|
||||||
|
n++
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func (trie *Trie) total() int {
|
||||||
|
return 1 + trie.children.total()
|
||||||
|
}
|
||||||
|
|
||||||
// VisitSubtree works much like Visit, but it only visits nodes matching prefix.
|
// VisitSubtree works much like Visit, but it only visits nodes matching prefix.
|
||||||
func (trie *Trie) VisitSubtree(prefix Prefix, visitor VisitorFunc) error {
|
func (trie *Trie) VisitSubtree(prefix Prefix, visitor VisitorFunc) error {
|
||||||
// Nil prefix not allowed.
|
// Nil prefix not allowed.
|
||||||
|
@ -219,11 +238,17 @@ func (trie *Trie) Delete(key Prefix) (deleted bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the relevant node.
|
// Find the relevant node.
|
||||||
parent, node, _, leftover := trie.findSubtree(key)
|
path, found, _ := trie.findSubtreePath(key)
|
||||||
if len(leftover) != 0 {
|
if !found {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node := path[len(path)-1]
|
||||||
|
var parent *Trie
|
||||||
|
if len(path) != 1 {
|
||||||
|
parent = path[len(path)-2]
|
||||||
|
}
|
||||||
|
|
||||||
// If the item is already set to nil, there is nothing to do.
|
// If the item is already set to nil, there is nothing to do.
|
||||||
if node.item == nil {
|
if node.item == nil {
|
||||||
return false
|
return false
|
||||||
|
@ -232,7 +257,53 @@ func (trie *Trie) Delete(key Prefix) (deleted bool) {
|
||||||
// Delete the item.
|
// Delete the item.
|
||||||
node.item = nil
|
node.item = nil
|
||||||
|
|
||||||
// Compact since that might be possible now.
|
// Initialise i before goto.
|
||||||
|
// Will be used later in a loop.
|
||||||
|
i := len(path) - 1
|
||||||
|
|
||||||
|
// In case there are some child nodes, we cannot drop the whole subtree.
|
||||||
|
// We can try to compact nodes, though.
|
||||||
|
if node.children.length() != 0 {
|
||||||
|
goto Compact
|
||||||
|
}
|
||||||
|
|
||||||
|
// In case we are at the root, just reset it and we are done.
|
||||||
|
if parent == nil {
|
||||||
|
node.reset()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// We can drop a subtree.
|
||||||
|
// Find the first ancestor that has its value set or it has 2 or more child nodes.
|
||||||
|
// That will be the node where to drop the subtree at.
|
||||||
|
for ; i >= 0; i-- {
|
||||||
|
if current := path[i]; current.item != nil || current.children.length() >= 2 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle the case when there is no such node.
|
||||||
|
// In other words, we can reset the whole tree.
|
||||||
|
if i == -1 {
|
||||||
|
path[0].reset()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// We can just remove the subtree here.
|
||||||
|
node = path[i]
|
||||||
|
if i == 0 {
|
||||||
|
parent = nil
|
||||||
|
} else {
|
||||||
|
parent = path[i-1]
|
||||||
|
}
|
||||||
|
// i+1 is always a valid index since i is never pointing to the last node.
|
||||||
|
// The loop above skips at least the last node since we are sure that the item
|
||||||
|
// is set to nil and it has no children, othewise we would be compacting instead.
|
||||||
|
node.children.remove(path[i+1].prefix[0])
|
||||||
|
|
||||||
|
Compact:
|
||||||
|
// The node is set to the first non-empty ancestor,
|
||||||
|
// so try to compact since that might be possible now.
|
||||||
if compacted := node.compact(); compacted != node {
|
if compacted := node.compact(); compacted != node {
|
||||||
if parent == nil {
|
if parent == nil {
|
||||||
*node = *compacted
|
*node = *compacted
|
||||||
|
@ -267,18 +338,26 @@ func (trie *Trie) DeleteSubtree(prefix Prefix) (deleted bool) {
|
||||||
|
|
||||||
// If we are in the root of the trie, reset the trie.
|
// If we are in the root of the trie, reset the trie.
|
||||||
if parent == nil {
|
if parent == nil {
|
||||||
root.prefix = nil
|
root.reset()
|
||||||
root.children = newSparseChildList(trie.maxPrefixPerNode)
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise remove the root node from its parent.
|
// Otherwise remove the root node from its parent.
|
||||||
parent.children.remove(root)
|
parent.children.remove(root.prefix[0])
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal helper methods -----------------------------------------------------
|
// Internal helper methods -----------------------------------------------------
|
||||||
|
|
||||||
|
func (trie *Trie) empty() bool {
|
||||||
|
return trie.item == nil && trie.children.length() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (trie *Trie) reset() {
|
||||||
|
trie.prefix = nil
|
||||||
|
trie.children = newSparseChildList(trie.maxPrefixPerNode)
|
||||||
|
}
|
||||||
|
|
||||||
func (trie *Trie) put(key Prefix, item Item, replace bool) (inserted bool) {
|
func (trie *Trie) put(key Prefix, item Item, replace bool) (inserted bool) {
|
||||||
// Nil prefix not allowed.
|
// Nil prefix not allowed.
|
||||||
if key == nil {
|
if key == nil {
|
||||||
|
@ -425,6 +504,43 @@ func (trie *Trie) findSubtree(prefix Prefix) (parent *Trie, root *Trie, found bo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (trie *Trie) findSubtreePath(prefix Prefix) (path []*Trie, found bool, leftover Prefix) {
|
||||||
|
// Find the subtree matching prefix.
|
||||||
|
root := trie
|
||||||
|
var subtreePath []*Trie
|
||||||
|
for {
|
||||||
|
// Append the current root to the path.
|
||||||
|
subtreePath = append(subtreePath, root)
|
||||||
|
|
||||||
|
// Compute what part of prefix matches.
|
||||||
|
common := root.longestCommonPrefixLength(prefix)
|
||||||
|
prefix = prefix[common:]
|
||||||
|
|
||||||
|
// We used up the whole prefix, subtree found.
|
||||||
|
if len(prefix) == 0 {
|
||||||
|
path = subtreePath
|
||||||
|
found = true
|
||||||
|
leftover = root.prefix[common:]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Partial match means that there is no subtree matching prefix.
|
||||||
|
if common < len(root.prefix) {
|
||||||
|
leftover = root.prefix[common:]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// There is some prefix left, move to the children.
|
||||||
|
child := root.children.next(prefix[0])
|
||||||
|
if child == nil {
|
||||||
|
// There is nowhere to continue, there is no subtree matching prefix.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
root = child
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (trie *Trie) walk(actualRootPrefix Prefix, visitor VisitorFunc) error {
|
func (trie *Trie) walk(actualRootPrefix Prefix, visitor VisitorFunc) error {
|
||||||
var prefix Prefix
|
var prefix Prefix
|
||||||
// Allocate a bit more space for prefix at the beginning.
|
// Allocate a bit more space for prefix at the beginning.
|
||||||
|
@ -459,6 +575,17 @@ func (trie *Trie) longestCommonPrefixLength(prefix Prefix) (i int) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (trie *Trie) dump() string {
|
||||||
|
writer := &bytes.Buffer{}
|
||||||
|
trie.print(writer, 0)
|
||||||
|
return writer.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (trie *Trie) print(writer io.Writer, indent int) {
|
||||||
|
fmt.Fprintf(writer, "%s%s %v\n", strings.Repeat(" ", indent), string(trie.prefix), trie.item)
|
||||||
|
trie.children.print(writer, indent+2)
|
||||||
|
}
|
||||||
|
|
||||||
// Errors ----------------------------------------------------------------------
|
// Errors ----------------------------------------------------------------------
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
Loading…
Add table
Reference in a new issue