Append
to append a new byteslice into a HPFile, and Append
will return the start position of this byteslice. Later you can pass this start position to ReadAt
and read this byteslice out. The position passed to ReadAt
must be the beginning of a byteslice, instead of its middle.[]byte("ILOVEYOU")
. We use MagicBytes to mark the beginning of an entry. In the entry file, you can find MagicBytes only at the beginning of every entries. If you read bytes out from a entry file and the beginning of these bytes is not "ILOVEYOU", then the read position must be wrong. This makes coding and debugging easier.-1
as the ending. Each Int32 takes 4 bytes, in little endian. Every position (except the last -1
) gives a position where has 8 zero bytes and should be replace by MagicBytes. These posistions are relative to the end of 4-byte Total Length.-1
as the ending. Each Int32 takes 4 bytes, in little endian. After the creation of last entry and before the creation of current entry, zero or more entries are deactived, and their serial numbers are recorded in this list.n
has 2*n
and 2*n+1
as its left child and right child. There is no node numbered as 0. The 2048 leaves in the tree are numbered from 2048~4095.mtree4YoungestTwig
.mtree4YoungestTwig
, as the youngest one.nodes
to store the upper-level nodes, which are acestors of non-pruned twigs.nodes
is just a golang map, which values are hash IDs stored in nodes, and keys are positions. How to present the position of a node in a Merkle tree? If a node is the N
-th node at level L
, the its position is calculated as an integer (L<<56)|N
. A node with postion of (L, N)
has two children: (L+1, 2*N)
and (L+1, 2*N+1)
.init()
function.PruneTwigs
.sync.Map
to cache the hot entries. This cache is valid only during a block's execution. When a block commits, it is cleared.PrepareForUpdate
and PrepareForDeletion
functions. In the marking phase, only the succeeded transactions marking some of these hot entries to be inserted, changed or deleted, using the Set
and Delete
functions. In the sweeping phase, the cached hot entries are sorted according to their keys and then we scan these sorted hot entries to update datatree.Get*
functions:ScanAllEntries
can iterate all these buffered changes. It is used to dump these changes to the underlying store.map[string]Serializable
. Its cache is not used to add an overlay. Instead, it is more like a file system cache in memory to avoid reading entries from hard disk. It only caches readonly objects, such as parameters which can be configured by proposals. You can further control which readonly objects can be cached by providing isCacheableKey func(k []byte) bool
, which returns true for keys whose value need to be cached.