123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409 |
- // Copyright (C) 2018 The Syncthing Authors.
- //
- // This Source Code Form is subject to the terms of the Mozilla Public
- // License, v. 2.0. If a copy of the MPL was not distributed with this file,
- // You can obtain one at https://mozilla.org/MPL/2.0/.
- package olddb
- import (
- "encoding/binary"
- )
- const (
- keyPrefixLen = 1
- keyFolderLen = 4 // indexed
- keyDeviceLen = 4 // indexed
- keySequenceLen = 8
- keyHashLen = 32
- maxInt64 int64 = 1<<63 - 1
- )
- const (
- // KeyTypeDevice <int32 folder ID> <int32 device ID> <file name> = FileInfo
- KeyTypeDevice byte = 0
- // KeyTypeGlobal <int32 folder ID> <file name> = VersionList
- KeyTypeGlobal byte = 1
- // KeyTypeBlock <int32 folder ID> <32 bytes hash> <§file name> = int32 (block index)
- KeyTypeBlock byte = 2
- // KeyTypeDeviceStatistic <device ID as string> <some string> = some value
- KeyTypeDeviceStatistic byte = 3
- // KeyTypeFolderStatistic <folder ID as string> <some string> = some value
- KeyTypeFolderStatistic byte = 4
- // KeyTypeVirtualMtime <int32 folder ID> <file name> = mtimeMapping
- KeyTypeVirtualMtime byte = 5
- // KeyTypeFolderIdx <int32 id> = string value
- KeyTypeFolderIdx byte = 6
- // KeyTypeDeviceIdx <int32 id> = string value
- KeyTypeDeviceIdx byte = 7
- // KeyTypeIndexID <int32 device ID> <int32 folder ID> = protocol.IndexID
- KeyTypeIndexID byte = 8
- // KeyTypeFolderMeta <int32 folder ID> = CountsSet
- KeyTypeFolderMeta byte = 9
- // KeyTypeMiscData <some string> = some value
- KeyTypeMiscData byte = 10
- // KeyTypeSequence <int32 folder ID> <int64 sequence number> = KeyTypeDevice key
- KeyTypeSequence byte = 11
- // KeyTypeNeed <int32 folder ID> <file name> = <nothing>
- KeyTypeNeed byte = 12
- // KeyTypeBlockList <block list hash> = BlockList
- KeyTypeBlockList byte = 13
- // KeyTypeBlockListMap <int32 folder ID> <block list hash> <file name> = <nothing>
- KeyTypeBlockListMap byte = 14
- // KeyTypeVersion <version hash> = Vector
- KeyTypeVersion byte = 15
- // KeyTypePendingFolder <int32 device ID> <folder ID as string> = ObservedFolder
- KeyTypePendingFolder byte = 16
- // KeyTypePendingDevice <device ID in wire format> = ObservedDevice
- KeyTypePendingDevice byte = 17
- )
- type keyer interface {
- // device file key stuff
- GenerateDeviceFileKey(key, folder, device, name []byte) (deviceFileKey, error)
- NameFromDeviceFileKey(key []byte) []byte
- DeviceFromDeviceFileKey(key []byte) ([]byte, bool)
- FolderFromDeviceFileKey(key []byte) ([]byte, bool)
- // global version key stuff
- GenerateGlobalVersionKey(key, folder, name []byte) (globalVersionKey, error)
- NameFromGlobalVersionKey(key []byte) []byte
- // block map key stuff (former BlockMap)
- GenerateBlockMapKey(key, folder, hash, name []byte) (blockMapKey, error)
- NameFromBlockMapKey(key []byte) []byte
- GenerateBlockListMapKey(key, folder, hash, name []byte) (blockListMapKey, error)
- NameFromBlockListMapKey(key []byte) []byte
- // file need index
- GenerateNeedFileKey(key, folder, name []byte) (needFileKey, error)
- // file sequence index
- GenerateSequenceKey(key, folder []byte, seq int64) (sequenceKey, error)
- SequenceFromSequenceKey(key []byte) int64
- // index IDs
- GenerateIndexIDKey(key, device, folder []byte) (indexIDKey, error)
- FolderFromIndexIDKey(key []byte) ([]byte, bool)
- DeviceFromIndexIDKey(key []byte) ([]byte, bool)
- // Mtimes
- GenerateMtimesKey(key, folder []byte) (mtimesKey, error)
- // Folder metadata
- GenerateFolderMetaKey(key, folder []byte) (folderMetaKey, error)
- // Block lists
- GenerateBlockListKey(key []byte, hash []byte) blockListKey
- // Version vectors
- GenerateVersionKey(key []byte, hash []byte) versionKey
- // Pending (unshared) folders and devices
- GeneratePendingFolderKey(key, device, folder []byte) (pendingFolderKey, error)
- FolderFromPendingFolderKey(key []byte) []byte
- DeviceFromPendingFolderKey(key []byte) ([]byte, bool)
- GeneratePendingDeviceKey(key, device []byte) pendingDeviceKey
- DeviceFromPendingDeviceKey(key []byte) []byte
- }
- // defaultKeyer implements our key scheme. It needs folder and device
- // indexes.
- type defaultKeyer struct {
- folderIdx *smallIndex
- deviceIdx *smallIndex
- }
- func newDefaultKeyer(folderIdx, deviceIdx *smallIndex) defaultKeyer {
- return defaultKeyer{
- folderIdx: folderIdx,
- deviceIdx: deviceIdx,
- }
- }
- type deviceFileKey []byte
- func (k deviceFileKey) WithoutNameAndDevice() []byte {
- return k[:keyPrefixLen+keyFolderLen]
- }
- func (k deviceFileKey) WithoutName() []byte {
- return k[:keyPrefixLen+keyFolderLen+keyDeviceLen]
- }
- func (k defaultKeyer) GenerateDeviceFileKey(key, folder, device, name []byte) (deviceFileKey, error) {
- folderID, err := k.folderIdx.ID(folder)
- if err != nil {
- return nil, err
- }
- deviceID, err := k.deviceIdx.ID(device)
- if err != nil {
- return nil, err
- }
- key = resize(key, keyPrefixLen+keyFolderLen+keyDeviceLen+len(name))
- key[0] = KeyTypeDevice
- binary.BigEndian.PutUint32(key[keyPrefixLen:], folderID)
- binary.BigEndian.PutUint32(key[keyPrefixLen+keyFolderLen:], deviceID)
- copy(key[keyPrefixLen+keyFolderLen+keyDeviceLen:], name)
- return key, nil
- }
- func (defaultKeyer) NameFromDeviceFileKey(key []byte) []byte {
- return key[keyPrefixLen+keyFolderLen+keyDeviceLen:]
- }
- func (k defaultKeyer) DeviceFromDeviceFileKey(key []byte) ([]byte, bool) {
- return k.deviceIdx.Val(binary.BigEndian.Uint32(key[keyPrefixLen+keyFolderLen:]))
- }
- func (k defaultKeyer) FolderFromDeviceFileKey(key []byte) ([]byte, bool) {
- return k.folderIdx.Val(binary.BigEndian.Uint32(key[keyPrefixLen:]))
- }
- type globalVersionKey []byte
- func (k globalVersionKey) WithoutName() []byte {
- return k[:keyPrefixLen+keyFolderLen]
- }
- func (k defaultKeyer) GenerateGlobalVersionKey(key, folder, name []byte) (globalVersionKey, error) {
- folderID, err := k.folderIdx.ID(folder)
- if err != nil {
- return nil, err
- }
- key = resize(key, keyPrefixLen+keyFolderLen+len(name))
- key[0] = KeyTypeGlobal
- binary.BigEndian.PutUint32(key[keyPrefixLen:], folderID)
- copy(key[keyPrefixLen+keyFolderLen:], name)
- return key, nil
- }
- func (defaultKeyer) NameFromGlobalVersionKey(key []byte) []byte {
- return key[keyPrefixLen+keyFolderLen:]
- }
- type blockMapKey []byte
- func (k defaultKeyer) GenerateBlockMapKey(key, folder, hash, name []byte) (blockMapKey, error) {
- folderID, err := k.folderIdx.ID(folder)
- if err != nil {
- return nil, err
- }
- key = resize(key, keyPrefixLen+keyFolderLen+keyHashLen+len(name))
- key[0] = KeyTypeBlock
- binary.BigEndian.PutUint32(key[keyPrefixLen:], folderID)
- copy(key[keyPrefixLen+keyFolderLen:], hash)
- copy(key[keyPrefixLen+keyFolderLen+keyHashLen:], name)
- return key, nil
- }
- func (defaultKeyer) NameFromBlockMapKey(key []byte) []byte {
- return key[keyPrefixLen+keyFolderLen+keyHashLen:]
- }
- func (k blockMapKey) WithoutHashAndName() []byte {
- return k[:keyPrefixLen+keyFolderLen]
- }
- type blockListMapKey []byte
- func (k defaultKeyer) GenerateBlockListMapKey(key, folder, hash, name []byte) (blockListMapKey, error) {
- folderID, err := k.folderIdx.ID(folder)
- if err != nil {
- return nil, err
- }
- key = resize(key, keyPrefixLen+keyFolderLen+keyHashLen+len(name))
- key[0] = KeyTypeBlockListMap
- binary.BigEndian.PutUint32(key[keyPrefixLen:], folderID)
- copy(key[keyPrefixLen+keyFolderLen:], hash)
- copy(key[keyPrefixLen+keyFolderLen+keyHashLen:], name)
- return key, nil
- }
- func (defaultKeyer) NameFromBlockListMapKey(key []byte) []byte {
- return key[keyPrefixLen+keyFolderLen+keyHashLen:]
- }
- func (k blockListMapKey) WithoutHashAndName() []byte {
- return k[:keyPrefixLen+keyFolderLen]
- }
- type needFileKey []byte
- func (k needFileKey) WithoutName() []byte {
- return k[:keyPrefixLen+keyFolderLen]
- }
- func (k defaultKeyer) GenerateNeedFileKey(key, folder, name []byte) (needFileKey, error) {
- folderID, err := k.folderIdx.ID(folder)
- if err != nil {
- return nil, err
- }
- key = resize(key, keyPrefixLen+keyFolderLen+len(name))
- key[0] = KeyTypeNeed
- binary.BigEndian.PutUint32(key[keyPrefixLen:], folderID)
- copy(key[keyPrefixLen+keyFolderLen:], name)
- return key, nil
- }
- type sequenceKey []byte
- func (k sequenceKey) WithoutSequence() []byte {
- return k[:keyPrefixLen+keyFolderLen]
- }
- func (k defaultKeyer) GenerateSequenceKey(key, folder []byte, seq int64) (sequenceKey, error) {
- folderID, err := k.folderIdx.ID(folder)
- if err != nil {
- return nil, err
- }
- key = resize(key, keyPrefixLen+keyFolderLen+keySequenceLen)
- key[0] = KeyTypeSequence
- binary.BigEndian.PutUint32(key[keyPrefixLen:], folderID)
- binary.BigEndian.PutUint64(key[keyPrefixLen+keyFolderLen:], uint64(seq))
- return key, nil
- }
- func (defaultKeyer) SequenceFromSequenceKey(key []byte) int64 {
- return int64(binary.BigEndian.Uint64(key[keyPrefixLen+keyFolderLen:]))
- }
- type indexIDKey []byte
- func (k defaultKeyer) GenerateIndexIDKey(key, device, folder []byte) (indexIDKey, error) {
- deviceID, err := k.deviceIdx.ID(device)
- if err != nil {
- return nil, err
- }
- folderID, err := k.folderIdx.ID(folder)
- if err != nil {
- return nil, err
- }
- key = resize(key, keyPrefixLen+keyDeviceLen+keyFolderLen)
- key[0] = KeyTypeIndexID
- binary.BigEndian.PutUint32(key[keyPrefixLen:], deviceID)
- binary.BigEndian.PutUint32(key[keyPrefixLen+keyDeviceLen:], folderID)
- return key, nil
- }
- func (k defaultKeyer) FolderFromIndexIDKey(key []byte) ([]byte, bool) {
- return k.folderIdx.Val(binary.BigEndian.Uint32(key[keyPrefixLen+keyDeviceLen:]))
- }
- func (k defaultKeyer) DeviceFromIndexIDKey(key []byte) ([]byte, bool) {
- return k.folderIdx.Val(binary.BigEndian.Uint32(key[keyPrefixLen : keyPrefixLen+keyDeviceLen]))
- }
- type mtimesKey []byte
- func (k defaultKeyer) GenerateMtimesKey(key, folder []byte) (mtimesKey, error) {
- folderID, err := k.folderIdx.ID(folder)
- if err != nil {
- return nil, err
- }
- key = resize(key, keyPrefixLen+keyFolderLen)
- key[0] = KeyTypeVirtualMtime
- binary.BigEndian.PutUint32(key[keyPrefixLen:], folderID)
- return key, nil
- }
- type folderMetaKey []byte
- func (k defaultKeyer) GenerateFolderMetaKey(key, folder []byte) (folderMetaKey, error) {
- folderID, err := k.folderIdx.ID(folder)
- if err != nil {
- return nil, err
- }
- key = resize(key, keyPrefixLen+keyFolderLen)
- key[0] = KeyTypeFolderMeta
- binary.BigEndian.PutUint32(key[keyPrefixLen:], folderID)
- return key, nil
- }
- type blockListKey []byte
- func (defaultKeyer) GenerateBlockListKey(key []byte, hash []byte) blockListKey {
- key = resize(key, keyPrefixLen+len(hash))
- key[0] = KeyTypeBlockList
- copy(key[keyPrefixLen:], hash)
- return key
- }
- func (k blockListKey) Hash() []byte {
- return k[keyPrefixLen:]
- }
- type versionKey []byte
- func (defaultKeyer) GenerateVersionKey(key []byte, hash []byte) versionKey {
- key = resize(key, keyPrefixLen+len(hash))
- key[0] = KeyTypeVersion
- copy(key[keyPrefixLen:], hash)
- return key
- }
- func (k versionKey) Hash() []byte {
- return k[keyPrefixLen:]
- }
- type pendingFolderKey []byte
- func (k defaultKeyer) GeneratePendingFolderKey(key, device, folder []byte) (pendingFolderKey, error) {
- deviceID, err := k.deviceIdx.ID(device)
- if err != nil {
- return nil, err
- }
- key = resize(key, keyPrefixLen+keyDeviceLen+len(folder))
- key[0] = KeyTypePendingFolder
- binary.BigEndian.PutUint32(key[keyPrefixLen:], deviceID)
- copy(key[keyPrefixLen+keyDeviceLen:], folder)
- return key, nil
- }
- func (defaultKeyer) FolderFromPendingFolderKey(key []byte) []byte {
- return key[keyPrefixLen+keyDeviceLen:]
- }
- func (k defaultKeyer) DeviceFromPendingFolderKey(key []byte) ([]byte, bool) {
- return k.deviceIdx.Val(binary.BigEndian.Uint32(key[keyPrefixLen:]))
- }
- type pendingDeviceKey []byte
- func (defaultKeyer) GeneratePendingDeviceKey(key, device []byte) pendingDeviceKey {
- key = resize(key, keyPrefixLen+len(device))
- key[0] = KeyTypePendingDevice
- copy(key[keyPrefixLen:], device)
- return key
- }
- func (defaultKeyer) DeviceFromPendingDeviceKey(key []byte) []byte {
- return key[keyPrefixLen:]
- }
- // resize returns a byte slice of the specified size, reusing bs if possible
- func resize(bs []byte, size int) []byte {
- if cap(bs) < size {
- return make([]byte, size)
- }
- return bs[:size]
- }
|