Exemple #1
0
// Enter with hc the hashcode for the key shifted appropriately for the
// current depth, the depth as a zero-based integer, and the full key.
// Return nil if no matching entry is found or the value associated with
// the matching entry or any error encountered.
//
// The caller guarantees that depth<=Root.maxTableDepth.
//
func (table *Table) findLeaf(hc uint64, depth uint, key KeyI) (
	value interface{}, err error) { // 1 of 90 samples cum

	ndx := hc & table.mask // 27 of 52; MOVQ 10(DX),CX
	flag := uint64(1 << ndx)

	if table.bitmap&flag != 0 {
		// the node is present; get its position in the slice
		var slotNbr uint
		mask := flag - 1
		if mask != 0 {
			slotNbr = uint(xu.BitCount64(table.bitmap & mask)) // gets expanded inline; 0/52
		}
		node := table.slots[slotNbr] // 20 of 52 - ADDQ BP,BX
		if node.IsLeaf() {
			myLeaf := node.(*Leaf)
			myKey := myLeaf.Key.(BytesKey) // 5 of 92 cum - lib call assest
			searchKey := key.(BytesKey)    // 7 of 92 cum - lib call assert
			if bytes.Equal(searchKey.Slice, myKey.Slice) {
				value = myLeaf.Value
			}
			// otherwise the value returned is nil
		} else {
			// node is a table, so recurse
			depth++
			if depth <= table.root.maxTableDepth {
				tDeeper := node.(*Table)
				hc >>= table.w
				value, err = tDeeper.findLeaf(hc, depth, key)
			}
			// otherwise the value returned is nil
		}
	}
	return
}
Exemple #2
0
// Enter with hc the hashcode for the key shifted appropriately for the
// current depth, so that the first w bits of the shifted hashcode can
// be used as the index of the leaf in the table.
//
// The caller guarantees that depth <= Root.maxTableDepth.
func (table *Table) deleteLeaf(hc uint64, depth uint, key KeyI) (
	err error) {

	if len(table.slots) == 0 {
		err = NotFound
	} else {
		ndx := hc & table.mask
		flag := uint64(1 << ndx)
		mask := flag - 1
		if table.bitmap&flag == 0 {
			err = NotFound
		} else {
			// the node is present; get its position in the slice
			var slotNbr uint
			if mask != 0 {
				slotNbr = xu.BitCount64(table.bitmap & mask)
			}
			node := table.slots[slotNbr]
			if node.IsLeaf() {
				myLeaf := node.(*Leaf)
				myKey := myLeaf.Key.(BytesKey)
				searchKey := key.(BytesKey)
				if bytes.Equal(searchKey.Slice, myKey.Slice) {
					err = table.removeFromSlices(slotNbr)
					table.bitmap &= ^flag
				} else {
					err = NotFound
				}
			} else {
				// node is a table, so recurse
				depth++
				if depth > table.root.maxTableDepth {
					err = NotFound
				} else {
					tDeeper := node.(*Table)
					hc >>= table.w
					err = tDeeper.deleteLeaf(hc, depth, key)
				}
			}
		}
	}
	return
}
Exemple #3
0
func (s *XLSuite) doTestTableDepthZeroInserts(c *C, w, t uint) {
	var (
		err                     error
		bitmap, flag, idx, mask uint64
	)
	dummyRoot, err := NewRoot(w, t)
	c.Assert(err, IsNil)
	c.Assert(dummyRoot.maxTableDepth, Equals, (64-t)/w)

	depth := uint(1)
	SLOT_COUNT := uint(1 << w)
	// create that many quasi-random keys
	rng := xr.MakeSimpleRNG()
	perm := rng.Perm(int(SLOT_COUNT)) // a random permutation of [0..SLOT_COUNT)
	rawKeys := make([][]byte, SLOT_COUNT)

	// create the first leaf ----------------------------------------
	ndx := byte(perm[0])
	rawKey, bKey, hc, firstLeaf := s.makeNthKey(c, ndx, SLOT_COUNT)
	rawKeys[0] = rawKey
	c.Assert(err, IsNil)

	table, err := NewTableWithLeaf(depth, dummyRoot, firstLeaf)
	c.Assert(err, IsNil)
	c.Assert(table, NotNil)
	//c.Assert(table.GetDepth(), Equals, depth)
	c.Assert(table.getLeafCount(), Equals, uint(1))

	// verify that the first leaf is in the table -------------------
	value, err := table.findLeaf(hc, depth, bKey)
	c.Assert(err, IsNil)
	c.Assert(value, NotNil)
	p := value.(*[]byte)
	c.Assert(bytes.Equal(rawKey, *p), Equals, true)

	// check table attributes ---------------------------------------
	c.Assert(table.w, Equals, w)
	c.Assert(table.t, Equals, t)
	flag = uint64(1)
	flag <<= (t + w)
	expectedMask := flag - 1
	c.Assert(table.mask, Equals, expectedMask)
	c.Assert(table.MaxSlots(), Equals, SLOT_COUNT)

	// verify bit mask is as expected, firstLeaf having been inserted
	idx = hc & table.mask
	flag = 1 << idx
	mask = flag - 1
	slotNbr := xu.BitCount64(bitmap & mask)
	c.Assert(0 <= slotNbr && slotNbr < SLOT_COUNT, Equals, true)
	occupied := uint64(1 << idx)
	bitmap |= occupied

	// insert the rest of the leaves --------------------------------
	for i := uint(1); i < SLOT_COUNT; i++ {

		ndx := byte(perm[i])
		rawKey, bKey, hc, leaf := s.makeNthKey(c, ndx, SLOT_COUNT)
		rawKeys[i] = rawKey
		value, err := table.findLeaf(hc, depth, bKey)
		c.Assert(err, IsNil)
		c.Assert(value, IsNil)

		err = table.insertLeaf(hc, depth, leaf)
		c.Assert(err, IsNil)

		// insert the value into the hash slice in such a way as
		// to maintain order
		idx = hc & table.mask
		flag = 1 << idx
		mask = flag - 1
		slotNbr := xu.BitCount64(bitmap & mask)
		c.Assert(0 <= slotNbr && slotNbr < SLOT_COUNT, Equals, true)
		occupied := uint64(1 << idx)
		bitmap |= occupied
		c.Assert(table.bitmap, Equals, bitmap)

		v, err := table.findLeaf(hc, depth, bKey)
		c.Assert(err, IsNil)
		vBytes := v.(*[]byte)
		c.Assert(bytes.Equal(*vBytes, rawKey), Equals, true)

	}
	// verify that the order of entries in the slots is as expected
	// remove each key, then verify that it is in fact gone
	c.Assert(uint(len(table.slots)), Equals, SLOT_COUNT)
	for i := uint(0); i < SLOT_COUNT; i++ {
		key := rawKeys[i]

		// verify it is present -------------------------------------
		bKey, err := NewBytesKey(key)
		c.Assert(err, IsNil)
		c.Assert(bKey, NotNil)
		hc := bKey.Hashcode()
		v, err := table.findLeaf(hc, depth, bKey)
		c.Assert(err, IsNil)
		c.Assert(v, NotNil)
		vAsKey := v.(*[]byte)
		c.Assert(bytes.Equal(*vAsKey, key), Equals, true)

		// delete it ------------------------------------------------
		// depth is zero, so hc unshifted
		err = table.deleteLeaf(hc, depth, bKey)
		c.Assert(err, IsNil)

		// verify that it is gone -----------------------------------
		v, err = table.findLeaf(hc, depth, bKey)
		c.Assert(err, IsNil)
		c.Assert(v, IsNil)

		_ = idx // DEBUG
	}
}
Exemple #4
0
// Enter with hc having been shifted so that the first w bits are ndx.
// 2014-05-13: Performance of this function was considerably improved (runtime
// down 25-50%) by replacing slice appends with slice make/copy sequences.
//
// The caller guarantees that depth <= Root.maxTableDepth.
func (table *Table) insertLeaf(hc uint64, depth uint, leaf *Leaf) (err error) {

	var slotNbr uint // whatever is in first line: about 15 of 37
	ndx := hc & table.mask
	flag := uint64(1 << ndx)
	mask := flag - 1
	if mask != 0 {
		slotNbr = xu.BitCount64(table.bitmap & mask)
	}
	sliceSize := uint(len(table.slots))
	if sliceSize == 0 {
		table.slots = []HTNodeI{leaf}
		table.bitmap |= flag
	} else {
		// Is there is already something at this slotNbr ?
		if table.bitmap&flag != 0 {
			entry := table.slots[slotNbr]

			if entry.IsLeaf() {
				// if it's a leaf, we replace the value iff the keys match
				curLeaf := entry.(*Leaf)
				curKey := curLeaf.Key.(BytesKey)
				newKey := leaf.Key.(BytesKey)
				if bytes.Equal(curKey.Slice, newKey.Slice) {
					// the keys match, so we replace the value
					curLeaf.Value = leaf.Value
				} else {
					var (
						tableDeeper *Table
					)
					depth++
					if depth > table.root.maxTableDepth {
						err = MaxTableDepthExceeded
					} else {
						oldLeaf := entry.(*Leaf)
						tableDeeper, err = NewTableWithLeaf(
							depth, table.root, oldLeaf)
						if err == nil {
							hc >>= table.w // this is hashcode for the NEW leaf
							// then put the new leaf in the new table
							err = tableDeeper.insertLeaf(hc, depth, leaf)
							if err == nil {
								// the new table replaces the existing leaf
								table.slots[slotNbr] = tableDeeper
							}
						}
					}
				}
			} else {
				depth++
				if depth > table.root.maxTableDepth {
					err = MaxTableDepthExceeded
				} else {
					// otherwise it's a table, so recurse
					tDeeper := entry.(*Table)
					hc >>= table.w
					err = tDeeper.insertLeaf(hc, depth, leaf)
				}
			}
		} else if slotNbr == 0 {
			leftSlots := make([]HTNodeI, sliceSize+1)
			leftSlots[0] = leaf
			copy(leftSlots[1:], table.slots[:])
			table.slots = leftSlots
			table.bitmap |= flag
		} else if slotNbr == sliceSize {
			table.slots = append(table.slots, leaf)
			table.bitmap |= flag
		} else {
			leftSlots := make([]HTNodeI, sliceSize+1)
			copy(leftSlots[:slotNbr], table.slots[:slotNbr])
			leftSlots[slotNbr] = leaf
			copy(leftSlots[slotNbr+1:], table.slots[slotNbr:])
			table.slots = leftSlots
			table.bitmap |= flag
		}
	}
	return
}