leveldb.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // Copyright (C) 2014 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at http://mozilla.org/MPL/2.0/.
  6. //go:generate -command genxdr go run ../../Godeps/_workspace/src/github.com/calmh/xdr/cmd/genxdr/main.go
  7. //go:generate genxdr -o leveldb_xdr.go leveldb.go
  8. package db
  9. import (
  10. "bytes"
  11. "fmt"
  12. "github.com/syncthing/syncthing/lib/protocol"
  13. "github.com/syncthing/syncthing/lib/sync"
  14. "github.com/syndtr/goleveldb/leveldb"
  15. "github.com/syndtr/goleveldb/leveldb/opt"
  16. )
  17. var (
  18. clockTick int64
  19. clockMut = sync.NewMutex()
  20. )
  21. func clock(v int64) int64 {
  22. clockMut.Lock()
  23. defer clockMut.Unlock()
  24. if v > clockTick {
  25. clockTick = v + 1
  26. } else {
  27. clockTick++
  28. }
  29. return clockTick
  30. }
  31. const (
  32. KeyTypeDevice = iota
  33. KeyTypeGlobal
  34. KeyTypeBlock
  35. KeyTypeDeviceStatistic
  36. KeyTypeFolderStatistic
  37. KeyTypeVirtualMtime
  38. )
  39. type fileVersion struct {
  40. version protocol.Vector
  41. device []byte
  42. }
  43. type versionList struct {
  44. versions []fileVersion
  45. }
  46. func (l versionList) String() string {
  47. var b bytes.Buffer
  48. var id protocol.DeviceID
  49. b.WriteString("{")
  50. for i, v := range l.versions {
  51. if i > 0 {
  52. b.WriteString(", ")
  53. }
  54. copy(id[:], v.device)
  55. fmt.Fprintf(&b, "{%d, %v}", v.version, id)
  56. }
  57. b.WriteString("}")
  58. return b.String()
  59. }
  60. type fileList []protocol.FileInfo
  61. func (l fileList) Len() int {
  62. return len(l)
  63. }
  64. func (l fileList) Swap(a, b int) {
  65. l[a], l[b] = l[b], l[a]
  66. }
  67. func (l fileList) Less(a, b int) bool {
  68. return l[a].Name < l[b].Name
  69. }
  70. type dbReader interface {
  71. Get([]byte, *opt.ReadOptions) ([]byte, error)
  72. }
  73. // Flush batches to disk when they contain this many records.
  74. const batchFlushSize = 64
  75. // deviceKey returns a byte slice encoding the following information:
  76. // keyTypeDevice (1 byte)
  77. // folder (64 bytes)
  78. // device (32 bytes)
  79. // name (variable size)
  80. func deviceKey(folder, device, file []byte) []byte {
  81. return deviceKeyInto(nil, folder, device, file)
  82. }
  83. func deviceKeyInto(k []byte, folder, device, file []byte) []byte {
  84. reqLen := 1 + 64 + 32 + len(file)
  85. if len(k) < reqLen {
  86. k = make([]byte, reqLen)
  87. }
  88. k[0] = KeyTypeDevice
  89. if len(folder) > 64 {
  90. panic("folder name too long")
  91. }
  92. copy(k[1:], []byte(folder))
  93. copy(k[1+64:], device[:])
  94. copy(k[1+64+32:], []byte(file))
  95. return k[:reqLen]
  96. }
  97. func deviceKeyName(key []byte) []byte {
  98. return key[1+64+32:]
  99. }
  100. func deviceKeyFolder(key []byte) []byte {
  101. folder := key[1 : 1+64]
  102. izero := bytes.IndexByte(folder, 0)
  103. if izero < 0 {
  104. return folder
  105. }
  106. return folder[:izero]
  107. }
  108. func deviceKeyDevice(key []byte) []byte {
  109. return key[1+64 : 1+64+32]
  110. }
  111. // globalKey returns a byte slice encoding the following information:
  112. // keyTypeGlobal (1 byte)
  113. // folder (64 bytes)
  114. // name (variable size)
  115. func globalKey(folder, file []byte) []byte {
  116. k := make([]byte, 1+64+len(file))
  117. k[0] = KeyTypeGlobal
  118. if len(folder) > 64 {
  119. panic("folder name too long")
  120. }
  121. copy(k[1:], []byte(folder))
  122. copy(k[1+64:], []byte(file))
  123. return k
  124. }
  125. func globalKeyName(key []byte) []byte {
  126. return key[1+64:]
  127. }
  128. func globalKeyFolder(key []byte) []byte {
  129. folder := key[1 : 1+64]
  130. izero := bytes.IndexByte(folder, 0)
  131. if izero < 0 {
  132. return folder
  133. }
  134. return folder[:izero]
  135. }
  136. func getFile(db dbReader, folder, device, file []byte) (protocol.FileInfo, bool) {
  137. nk := deviceKey(folder, device, file)
  138. bs, err := db.Get(nk, nil)
  139. if err == leveldb.ErrNotFound {
  140. return protocol.FileInfo{}, false
  141. }
  142. if err != nil {
  143. panic(err)
  144. }
  145. var f protocol.FileInfo
  146. err = f.UnmarshalXDR(bs)
  147. if err != nil {
  148. panic(err)
  149. }
  150. return f, true
  151. }