github.com/coreos/mantle@v0.13.0/storage/index/tree.go (about)

     1  // Copyright 2016 CoreOS, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package index
    16  
    17  import (
    18  	"strings"
    19  
    20  	gs "google.golang.org/api/storage/v1"
    21  
    22  	"github.com/coreos/mantle/lang/natsort"
    23  	"github.com/coreos/mantle/storage"
    24  )
    25  
    26  type IndexTree struct {
    27  	bucket   *storage.Bucket
    28  	prefixes map[string]bool
    29  	subdirs  map[string][]string
    30  	objects  map[string][]*gs.Object
    31  }
    32  
    33  func NewIndexTree(bucket *storage.Bucket, includeEmpty bool) *IndexTree {
    34  	t := &IndexTree{
    35  		bucket:   bucket,
    36  		prefixes: make(map[string]bool),
    37  		subdirs:  make(map[string][]string),
    38  		objects:  make(map[string][]*gs.Object),
    39  	}
    40  
    41  	for _, prefix := range bucket.Prefixes() {
    42  		if includeEmpty {
    43  			t.addDir(prefix)
    44  		} else {
    45  			t.prefixes[prefix] = false // initialize as empty
    46  		}
    47  	}
    48  
    49  	indexes := NewIndexSet(bucket)
    50  	for _, obj := range bucket.Objects() {
    51  		if indexes.NotIndex(obj) {
    52  			t.addObj(obj)
    53  		}
    54  	}
    55  
    56  	for _, dirs := range t.subdirs {
    57  		natsort.Strings(dirs)
    58  	}
    59  
    60  	for _, objs := range t.objects {
    61  		storage.SortObjects(objs)
    62  	}
    63  
    64  	return t
    65  }
    66  
    67  func (t *IndexTree) addObj(obj *gs.Object) {
    68  	prefix := storage.NextPrefix(obj.Name)
    69  	t.objects[prefix] = append(t.objects[prefix], obj)
    70  	t.addDir(prefix)
    71  }
    72  
    73  func (t *IndexTree) addDir(prefix string) {
    74  	for !t.prefixes[prefix] {
    75  		t.prefixes[prefix] = true // mark as not empty
    76  		if prefix == "" {
    77  			return
    78  		}
    79  		parent := storage.NextPrefix(prefix)
    80  		t.subdirs[parent] = append(t.subdirs[parent], prefix)
    81  		prefix = storage.NextPrefix(prefix)
    82  	}
    83  }
    84  
    85  func (t *IndexTree) Prefixes(dir string) []string {
    86  	prefixes := make([]string, 0, len(t.prefixes))
    87  	for prefix := range t.prefixes {
    88  		if strings.HasPrefix(prefix, dir) {
    89  			prefixes = append(prefixes, prefix)
    90  		}
    91  	}
    92  	return prefixes
    93  }