1// Copyright 2015 The etcd Authors 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 15package store 16 17import ( 18 "sort" 19 "time" 20 21 "github.com/jonboulle/clockwork" 22) 23 24// NodeExtern is the external representation of the 25// internal node with additional fields 26// PrevValue is the previous value of the node 27// TTL is time to live in second 28type NodeExtern struct { 29 Key string `json:"key,omitempty"` 30 Value *string `json:"value,omitempty"` 31 Dir bool `json:"dir,omitempty"` 32 Expiration *time.Time `json:"expiration,omitempty"` 33 TTL int64 `json:"ttl,omitempty"` 34 Nodes NodeExterns `json:"nodes,omitempty"` 35 ModifiedIndex uint64 `json:"modifiedIndex,omitempty"` 36 CreatedIndex uint64 `json:"createdIndex,omitempty"` 37} 38 39func (eNode *NodeExtern) loadInternalNode(n *node, recursive, sorted bool, clock clockwork.Clock) { 40 if n.IsDir() { // node is a directory 41 eNode.Dir = true 42 43 children, _ := n.List() 44 eNode.Nodes = make(NodeExterns, len(children)) 45 46 // we do not use the index in the children slice directly 47 // we need to skip the hidden one 48 i := 0 49 50 for _, child := range children { 51 if child.IsHidden() { // get will not return hidden nodes 52 continue 53 } 54 55 eNode.Nodes[i] = child.Repr(recursive, sorted, clock) 56 i++ 57 } 58 59 // eliminate hidden nodes 60 eNode.Nodes = eNode.Nodes[:i] 61 62 if sorted { 63 sort.Sort(eNode.Nodes) 64 } 65 66 } else { // node is a file 67 value, _ := n.Read() 68 eNode.Value = &value 69 } 70 71 eNode.Expiration, eNode.TTL = n.expirationAndTTL(clock) 72} 73 74func (eNode *NodeExtern) Clone() *NodeExtern { 75 if eNode == nil { 76 return nil 77 } 78 nn := &NodeExtern{ 79 Key: eNode.Key, 80 Dir: eNode.Dir, 81 TTL: eNode.TTL, 82 ModifiedIndex: eNode.ModifiedIndex, 83 CreatedIndex: eNode.CreatedIndex, 84 } 85 if eNode.Value != nil { 86 s := *eNode.Value 87 nn.Value = &s 88 } 89 if eNode.Expiration != nil { 90 t := *eNode.Expiration 91 nn.Expiration = &t 92 } 93 if eNode.Nodes != nil { 94 nn.Nodes = make(NodeExterns, len(eNode.Nodes)) 95 for i, n := range eNode.Nodes { 96 nn.Nodes[i] = n.Clone() 97 } 98 } 99 return nn 100} 101 102type NodeExterns []*NodeExtern 103 104// interfaces for sorting 105 106func (ns NodeExterns) Len() int { 107 return len(ns) 108} 109 110func (ns NodeExterns) Less(i, j int) bool { 111 return ns[i].Key < ns[j].Key 112} 113 114func (ns NodeExterns) Swap(i, j int) { 115 ns[i], ns[j] = ns[j], ns[i] 116} 117