Browse code

Enable construction of TruncIndex from id array.

Fixes #5166

Current graph.restore is essentially O(n^2 log n) due to how
suffixarray creation works.

Rather than create/append/create new this supports creation from a seed
array of ids.

Functional testing shows this eliminates the hang on Creating image
graph reported on list.

Docker-DCO-1.1-Signed-off-by: Paul Nasrat <pnasrat@gmail.com> (github: pnasrat)

Paul Nasrat authored on 2014/04/12 05:39:58
Showing 4 changed files
... ...
@@ -40,7 +40,7 @@ func NewGraph(root string, driver graphdriver.Driver) (*Graph, error) {
40 40
 
41 41
 	graph := &Graph{
42 42
 		Root:    abspath,
43
-		idIndex: utils.NewTruncIndex(),
43
+		idIndex: utils.NewTruncIndex([]string{}),
44 44
 		driver:  driver,
45 45
 	}
46 46
 	if err := graph.restore(); err != nil {
... ...
@@ -54,12 +54,14 @@ func (graph *Graph) restore() error {
54 54
 	if err != nil {
55 55
 		return err
56 56
 	}
57
+	var ids = []string{}
57 58
 	for _, v := range dir {
58 59
 		id := v.Name()
59 60
 		if graph.driver.Exists(id) {
60
-			graph.idIndex.Add(id)
61
+			ids = append(ids, id)
61 62
 		}
62 63
 	}
64
+	graph.idIndex = utils.NewTruncIndex(ids)
63 65
 	utils.Debugf("Restored %d elements", len(dir))
64 66
 	return nil
65 67
 }
... ...
@@ -779,7 +779,7 @@ func NewRuntimeFromDirectory(config *daemonconfig.Config, eng *engine.Engine) (*
779 779
 		containers:     list.New(),
780 780
 		graph:          g,
781 781
 		repositories:   repositories,
782
-		idIndex:        utils.NewTruncIndex(),
782
+		idIndex:        utils.NewTruncIndex([]string{}),
783 783
 		sysInfo:        sysInfo,
784 784
 		volumes:        volumes,
785 785
 		config:         config,
... ...
@@ -426,12 +426,17 @@ type TruncIndex struct {
426 426
 	bytes []byte
427 427
 }
428 428
 
429
-func NewTruncIndex() *TruncIndex {
430
-	return &TruncIndex{
431
-		index: suffixarray.New([]byte{' '}),
429
+func NewTruncIndex(ids []string) (idx *TruncIndex) {
430
+	idx = &TruncIndex{
432 431
 		ids:   make(map[string]bool),
433 432
 		bytes: []byte{' '},
434 433
 	}
434
+	for _, id := range ids {
435
+		idx.ids[id] = true
436
+		idx.bytes = append(idx.bytes, []byte(id+" ")...)
437
+	}
438
+	idx.index = suffixarray.New(idx.bytes)
439
+	return
435 440
 }
436 441
 
437 442
 func (idx *TruncIndex) Add(id string) error {
... ...
@@ -138,7 +138,8 @@ func TestRaceWriteBroadcaster(t *testing.T) {
138 138
 
139 139
 // Test the behavior of TruncIndex, an index for querying IDs from a non-conflicting prefix.
140 140
 func TestTruncIndex(t *testing.T) {
141
-	index := NewTruncIndex()
141
+	ids := []string{}
142
+	index := NewTruncIndex(ids)
142 143
 	// Get on an empty index
143 144
 	if _, err := index.Get("foobar"); err == nil {
144 145
 		t.Fatal("Get on an empty index should return an error")