| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- // Copyright 2014 The lldb Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- // Package lldb implements a low level database engine. The database model used
- // could be considered a specific implementation of some small(est)
- // intersection of models listed in [1]. As a settled term is lacking, it'll be
- // called here a 'Virtual memory model' (VMM).
- //
- // Changelog
- //
- // 2016-07-24: v1.0.4 brings some performance improvements.
- //
- // 2016-07-22: v1.0.3 brings some small performance improvements.
- //
- // 2016-07-12: v1.0.2 now uses packages from cznic/internal.
- //
- // 2016-07-12: v1.0.1 adds a license for testdata/fortunes.txt.
- //
- // 2016-07-11: First standalone release v1.0.0 of the package previously
- // published as experimental (github.com/cznic/exp/lldb).
- //
- // Filers
- //
- // A Filer is an abstraction of storage. A Filer may be a part of some process'
- // virtual address space, an OS file, a networked, remote file etc. Persistence
- // of the storage is optional, opaque to VMM and it is specific to a concrete
- // Filer implementation.
- //
- // Space management
- //
- // Mechanism to allocate, reallocate (resize), deallocate (and later reclaim
- // the unused) contiguous parts of a Filer, called blocks. Blocks are
- // identified and referred to by a handle, an int64.
- //
- // BTrees
- //
- // In addition to the VMM like services, lldb provides volatile and
- // non-volatile BTrees. Keys and values of a BTree are limited in size to 64kB
- // each (a bit more actually). Support for larger keys/values, if desired, can
- // be built atop a BTree to certain limits.
- //
- // Handles vs pointers
- //
- // A handle is the abstracted storage counterpart of a memory address. There
- // is one fundamental difference, though. Resizing a block never results in a
- // change to the handle which refers to the resized block, so a handle is more
- // akin to an unique numeric id/key. Yet it shares one property of pointers -
- // handles can be associated again with blocks after the original handle block
- // was deallocated. In other words, a handle uniqueness domain is the state of
- // the database and is not something comparable to e.g. an ever growing
- // numbering sequence.
- //
- // Also, as with memory pointers, dangling handles can be created and blocks
- // overwritten when such handles are used. Using a zero handle to refer to a
- // block will not panic; however, the resulting error is effectively the same
- // exceptional situation as dereferencing a nil pointer.
- //
- // Blocks
- //
- // Allocated/used blocks, are limited in size to only a little bit more than
- // 64kB. Bigger semantic entities/structures must be built in lldb's client
- // code. The content of a block has no semantics attached, it's only a fully
- // opaque `[]byte`.
- //
- // Scalars
- //
- // Use of "scalars" applies to EncodeScalars, DecodeScalars and Collate. Those
- // first two "to bytes" and "from bytes" functions are suggested for handling
- // multi-valued Allocator content items and/or keys/values of BTrees (using
- // Collate for keys). Types called "scalar" are:
- //
- // nil (the typeless one)
- // bool
- // all integral types: [u]int8, [u]int16, [u]int32, [u]int, [u]int64
- // all floating point types: float32, float64
- // all complex types: complex64, complex128
- // []byte (64kB max)
- // string (64kb max)
- //
- // Specific implementations
- //
- // Included are concrete implementations of some of the VMM interfaces included
- // to ease serving simple client code or for testing and possibly as an
- // example. More details in the documentation of such implementations.
- //
- // [1]: http://en.wikipedia.org/wiki/Database_model
- package lldb
- const (
- fltSz = 0x70 // size of the FLT
- maxShort = 251
- maxRq = 65787
- maxFLTRq = 4112
- maxHandle = 1<<56 - 1
- atomLen = 16
- tagUsedLong = 0xfc
- tagUsedRelocated = 0xfd
- tagFreeShort = 0xfe
- tagFreeLong = 0xff
- tagNotCompressed = 0
- tagCompressed = 1
- )
- // Content size n -> blocksize in atoms.
- func n2atoms(n int) int {
- if n > maxShort {
- n += 2
- }
- return (n+1)/16 + 1
- }
- // Content size n -> number of padding zeros.
- func n2padding(n int) int {
- if n > maxShort {
- n += 2
- }
- return 15 - (n+1)&15
- }
- // Handle <-> offset
- func h2off(h int64) int64 { return (h + 6) * 16 }
- func off2h(off int64) int64 { return off/16 - 6 }
- // Get a 7B int64 from b
- func b2h(b []byte) (h int64) {
- for _, v := range b[:7] {
- h = h<<8 | int64(v)
- }
- return
- }
- // Put a 7B int64 into b
- func h2b(b []byte, h int64) []byte {
- for i := range b[:7] {
- b[i], h = byte(h>>48), h<<8
- }
- return b
- }
- // Content length N (must be in [252, 65787]) to long used block M field.
- func n2m(n int) (m int) {
- return n % 0x10000
- }
- // Long used block M (must be in [0, 65535]) field to content length N.
- func m2n(m int) (n int) {
- if m <= maxShort {
- m += 0x10000
- }
- return m
- }
- func bpack(a []byte) []byte {
- if cap(a) > len(a) {
- return append([]byte(nil), a...)
- }
- return a
- }
|