github.com/braveheart12/insolar-09-08-19@v0.8.7/ledger/storage/jet/tree.go (about)

     1  /*
     2   *    Copyright 2019 Insolar Technologies
     3   *
     4   *    Licensed under the Apache License, Version 2.0 (the "License");
     5   *    you may not use this file except in compliance with the License.
     6   *    You may obtain a copy of the License at
     7   *
     8   *        http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   *    Unless required by applicable law or agreed to in writing, software
    11   *    distributed under the License is distributed on an "AS IS" BASIS,
    12   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   *    See the License for the specific language governing permissions and
    14   *    limitations under the License.
    15   */
    16  
    17  package jet
    18  
    19  import (
    20  	"bytes"
    21  	"fmt"
    22  	"strings"
    23  
    24  	"github.com/insolar/insolar/core"
    25  	"github.com/pkg/errors"
    26  	"github.com/ugorji/go/codec"
    27  )
    28  
    29  type jet struct {
    30  	Left   *jet
    31  	Right  *jet
    32  	Actual bool
    33  }
    34  
    35  // Find returns jet for provided reference.
    36  func (j *jet) Find(val []byte, depth uint8) (*jet, uint8) {
    37  	if j == nil || val == nil {
    38  		return nil, 0
    39  	}
    40  
    41  	if getBit(val, depth) {
    42  		if j.Right != nil {
    43  			return j.Right.Find(val, depth+1)
    44  		}
    45  	} else {
    46  		if j.Left != nil {
    47  			return j.Left.Find(val, depth+1)
    48  		}
    49  	}
    50  	return j, depth
    51  }
    52  
    53  // Update add missing tree branches for provided prefix.
    54  func (j *jet) Update(prefix []byte, setActual bool, maxDepth, depth uint8) {
    55  	if depth == maxDepth {
    56  		if setActual {
    57  			j.Actual = true
    58  		}
    59  		return
    60  	}
    61  
    62  	if j.Right == nil {
    63  		j.Right = &jet{}
    64  	}
    65  	if j.Left == nil {
    66  		j.Left = &jet{}
    67  	}
    68  	if getBit(prefix, depth) {
    69  		j.Right.Update(prefix, setActual, maxDepth, depth+1)
    70  	} else {
    71  		j.Left.Update(prefix, setActual, maxDepth, depth+1)
    72  	}
    73  }
    74  
    75  // Clone clones tree either keeping actuality state or resetting it to false
    76  func (j *jet) Clone(keep bool) *jet {
    77  	res := &jet{Actual: keep && j.Actual}
    78  	if j.Left != nil {
    79  		res.Left = j.Left.Clone(keep)
    80  	}
    81  	if j.Right != nil {
    82  		res.Right = j.Right.Clone(keep)
    83  	}
    84  	return res
    85  }
    86  
    87  func (j *jet) ExtractLeafIDs(ids *[]core.RecordID, path []byte, depth uint8) {
    88  	if j == nil {
    89  		return
    90  	}
    91  	if j.Left == nil && j.Right == nil {
    92  		*ids = append(*ids, *NewID(depth, path))
    93  		return
    94  	}
    95  
    96  	if j.Left != nil {
    97  		j.Left.ExtractLeafIDs(ids, path, depth+1)
    98  	}
    99  	if j.Right != nil {
   100  		rightPath := make([]byte, len(path))
   101  		copy(rightPath, path)
   102  		setBit(rightPath, depth)
   103  		j.Right.ExtractLeafIDs(ids, rightPath, depth+1)
   104  	}
   105  }
   106  
   107  // Tree stores jet in a binary tree.
   108  type Tree struct {
   109  	Head *jet
   110  }
   111  
   112  // String visualizes Jet's tree.
   113  func (t Tree) String() string {
   114  	if t.Head == nil {
   115  		return "<nil>"
   116  	}
   117  	return nodeDeepFmt(0, "", t.Head)
   118  }
   119  
   120  func (t *Tree) toArray() []*jet {
   121  	queue := []*jet{t.Head}
   122  	queueIndex := 0
   123  	lastElementIndex := 0
   124  
   125  	for queueIndex <= lastElementIndex {
   126  		currentNode := queue[queueIndex]
   127  		if currentNode == nil {
   128  			queueIndex++
   129  			continue
   130  		}
   131  		nextLeftIndex := (queueIndex * 2) + 1
   132  		nextRightIndex := (queueIndex * 2) + 2
   133  
   134  		if nextRightIndex >= len(queue) {
   135  			for nextRightIndex >= len(queue) {
   136  				queue = append(queue, nil)
   137  			}
   138  		}
   139  
   140  		queue[nextLeftIndex] = queue[queueIndex].Left
   141  		queue[nextRightIndex] = queue[queueIndex].Right
   142  
   143  		if queue[nextLeftIndex] != nil && nextLeftIndex > lastElementIndex {
   144  			lastElementIndex = nextLeftIndex
   145  		}
   146  
   147  		if queue[nextRightIndex] != nil && nextRightIndex > lastElementIndex {
   148  			lastElementIndex = nextRightIndex
   149  		}
   150  		queueIndex++
   151  	}
   152  
   153  	return queue[:lastElementIndex+1]
   154  }
   155  
   156  // Merge merges two trees to one
   157  func (t *Tree) Merge(newTree *Tree) *Tree {
   158  	maxLengthFunc := func(left int, right int) int {
   159  		if left > right {
   160  			return left
   161  		}
   162  
   163  		return right
   164  	}
   165  
   166  	savedTree := t.toArray()
   167  	inputTree := newTree.toArray()
   168  
   169  	maxLength := maxLengthFunc(len(savedTree), len(inputTree))
   170  
   171  	result := make([]*jet, maxLength)
   172  
   173  	for index := 0; index < maxLength; index++ {
   174  		var savedItem *jet
   175  		var newItem *jet
   176  
   177  		if index < len(savedTree) {
   178  			savedItem = savedTree[index]
   179  		}
   180  		if index < len(inputTree) {
   181  			newItem = inputTree[index]
   182  		}
   183  
   184  		if savedItem == nil {
   185  			result[index] = newItem
   186  			continue
   187  		}
   188  		if newItem == nil {
   189  			result[index] = savedItem
   190  			continue
   191  		}
   192  
   193  		if !savedItem.Actual && newItem.Actual {
   194  			result[index] = newItem
   195  		} else {
   196  			result[index] = savedItem
   197  		}
   198  	}
   199  
   200  	for index := 0; index < (maxLength/2)+1; index++ {
   201  		current := result[index]
   202  		if current != nil {
   203  			leftIndex := index*2 + 1
   204  			if leftIndex < len(result) {
   205  				current.Left = result[index*2+1]
   206  			}
   207  
   208  			rightIndex := index*2 + 2
   209  			if rightIndex < len(result) {
   210  				current.Right = result[index*2+2]
   211  			}
   212  		}
   213  	}
   214  
   215  	return &Tree{Head: result[0]}
   216  }
   217  
   218  func nodeDeepFmt(deep int, binPrefix string, node *jet) string {
   219  	prefix := strings.Repeat(" ", deep)
   220  	if deep == 0 {
   221  		prefix = "root"
   222  	}
   223  	s := fmt.Sprintf("%s%v (level=%v actual=%v)\n", prefix, binPrefix, deep, node.Actual)
   224  
   225  	if node.Left != nil {
   226  		s += nodeDeepFmt(deep+1, binPrefix+"0", node.Left)
   227  	}
   228  	if node.Right != nil {
   229  		s += nodeDeepFmt(deep+1, binPrefix+"1", node.Right)
   230  	}
   231  	return s
   232  }
   233  
   234  // NewTree creates new tree.
   235  func NewTree(isActual bool) *Tree {
   236  	return &Tree{Head: &jet{Actual: isActual}}
   237  }
   238  
   239  // Clone clones the tree keeping actuality or setting everything to false
   240  func (t *Tree) Clone(keep bool) *Tree {
   241  	return &Tree{Head: t.Head.Clone(keep)}
   242  }
   243  
   244  // Find returns jet for provided reference. If found jet is actual, the second argument will be true.
   245  func (t *Tree) Find(id core.RecordID) (*core.RecordID, bool) {
   246  	if id.Pulse() == core.PulseNumberJet {
   247  		return &id, true
   248  	}
   249  	hash := id.Hash()
   250  	j, depth := t.Head.Find(hash, 0)
   251  	return NewID(uint8(depth), ResetBits(hash, depth)), j.Actual
   252  }
   253  
   254  // Update add missing tree branches for provided prefix. If 'setActual' is set, all encountered nodes will be marked as
   255  // actual.
   256  func (t *Tree) Update(id core.RecordID, setActual bool) {
   257  	maxDepth, prefix := Jet(id)
   258  	t.Head.Update(prefix, setActual, maxDepth, 0)
   259  }
   260  
   261  // Bytes serializes pulse.
   262  func (t *Tree) Bytes() []byte {
   263  	var buf bytes.Buffer
   264  	enc := codec.NewEncoder(&buf, &codec.CborHandle{})
   265  	enc.MustEncode(t)
   266  	return buf.Bytes()
   267  }
   268  
   269  // Split looks for provided jet and creates (and returns) two branches for it. If provided jet is not found, an error
   270  // will be returned.
   271  func (t *Tree) Split(jetID core.RecordID) (*core.RecordID, *core.RecordID, error) {
   272  	depth, prefix := Jet(jetID)
   273  	j, foundDepth := t.Head.Find(prefix, 0)
   274  	if depth != foundDepth {
   275  		return nil, nil, errors.New("failed to split: incorrect jet provided")
   276  	}
   277  	j.Right = &jet{}
   278  	j.Left = &jet{}
   279  	leftPrefix := ResetBits(prefix, depth)
   280  	rightPrefix := ResetBits(prefix, depth)
   281  	setBit(rightPrefix, depth)
   282  	return NewID(depth+1, leftPrefix), NewID(depth+1, rightPrefix), nil
   283  }
   284  
   285  func (t *Tree) LeafIDs() []core.RecordID {
   286  	var ids []core.RecordID
   287  	t.Head.ExtractLeafIDs(&ids, make([]byte, core.RecordHashSize), 0)
   288  	return ids
   289  }
   290  
   291  func getBit(value []byte, index uint8) bool {
   292  	if uint(index) >= uint(len(value)*8) {
   293  		panic(fmt.Sprintf("index overflow: value=%08b, index=%v", value, index))
   294  	}
   295  	byteIndex := uint(index / 8)
   296  	bitIndex := uint(7 - index%8)
   297  	mask := byte(1 << bitIndex)
   298  	return value[byteIndex]&mask != 0
   299  }
   300  
   301  func setBit(value []byte, index uint8) {
   302  	if uint(index) >= uint(len(value)*8) {
   303  		panic("index overflow")
   304  	}
   305  	byteIndex := uint(index / 8)
   306  	bitIndex := uint(7 - index%8)
   307  	mask := byte(1 << bitIndex)
   308  	value[byteIndex] |= mask
   309  }
   310  
   311  // ResetBits returns a new byte slice with all bits in 'value' reset, starting from 'start' number of bit. If 'start'
   312  // is bigger than len(value), the original slice will be returned.
   313  func ResetBits(value []byte, start uint8) []byte {
   314  	if int(start) >= len(value)*8 {
   315  		return value
   316  	}
   317  
   318  	startByte := start / 8
   319  	startBit := start % 8
   320  
   321  	result := make([]byte, len(value))
   322  	copy(result, value[:startByte])
   323  
   324  	// Reset bits in starting byte.
   325  	mask := byte(0xFF)
   326  	mask <<= 8 - byte(startBit)
   327  	result[startByte] = value[startByte] & mask
   328  
   329  	return result
   330  }