namespaced.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  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 https://mozilla.org/MPL/2.0/.
  6. package db
  7. import (
  8. "encoding/binary"
  9. "time"
  10. "github.com/syndtr/goleveldb/leveldb"
  11. "github.com/syndtr/goleveldb/leveldb/util"
  12. )
  13. // NamespacedKV is a simple key-value store using a specific namespace within
  14. // a leveldb.
  15. type NamespacedKV struct {
  16. db *Instance
  17. prefix []byte
  18. }
  19. // NewNamespacedKV returns a new NamespacedKV that lives in the namespace
  20. // specified by the prefix.
  21. func NewNamespacedKV(db *Instance, prefix string) *NamespacedKV {
  22. return &NamespacedKV{
  23. db: db,
  24. prefix: []byte(prefix),
  25. }
  26. }
  27. // Reset removes all entries in this namespace.
  28. func (n *NamespacedKV) Reset() {
  29. it := n.db.NewIterator(util.BytesPrefix(n.prefix), nil)
  30. defer it.Release()
  31. batch := new(leveldb.Batch)
  32. for it.Next() {
  33. batch.Delete(it.Key())
  34. if batch.Len() > batchFlushSize {
  35. if err := n.db.Write(batch, nil); err != nil {
  36. panic(err)
  37. }
  38. batch.Reset()
  39. }
  40. }
  41. if batch.Len() > 0 {
  42. if err := n.db.Write(batch, nil); err != nil {
  43. panic(err)
  44. }
  45. }
  46. }
  47. // PutInt64 stores a new int64. Any existing value (even if of another type)
  48. // is overwritten.
  49. func (n *NamespacedKV) PutInt64(key string, val int64) {
  50. keyBs := append(n.prefix, []byte(key)...)
  51. var valBs [8]byte
  52. binary.BigEndian.PutUint64(valBs[:], uint64(val))
  53. n.db.Put(keyBs, valBs[:], nil)
  54. }
  55. // Int64 returns the stored value interpreted as an int64 and a boolean that
  56. // is false if no value was stored at the key.
  57. func (n *NamespacedKV) Int64(key string) (int64, bool) {
  58. keyBs := append(n.prefix, []byte(key)...)
  59. valBs, err := n.db.Get(keyBs, nil)
  60. if err != nil {
  61. return 0, false
  62. }
  63. val := binary.BigEndian.Uint64(valBs)
  64. return int64(val), true
  65. }
  66. // PutTime stores a new time.Time. Any existing value (even if of another
  67. // type) is overwritten.
  68. func (n *NamespacedKV) PutTime(key string, val time.Time) {
  69. keyBs := append(n.prefix, []byte(key)...)
  70. valBs, _ := val.MarshalBinary() // never returns an error
  71. n.db.Put(keyBs, valBs, nil)
  72. }
  73. // Time returns the stored value interpreted as a time.Time and a boolean
  74. // that is false if no value was stored at the key.
  75. func (n NamespacedKV) Time(key string) (time.Time, bool) {
  76. var t time.Time
  77. keyBs := append(n.prefix, []byte(key)...)
  78. valBs, err := n.db.Get(keyBs, nil)
  79. if err != nil {
  80. return t, false
  81. }
  82. err = t.UnmarshalBinary(valBs)
  83. return t, err == nil
  84. }
  85. // PutString stores a new string. Any existing value (even if of another type)
  86. // is overwritten.
  87. func (n *NamespacedKV) PutString(key, val string) {
  88. keyBs := append(n.prefix, []byte(key)...)
  89. n.db.Put(keyBs, []byte(val), nil)
  90. }
  91. // String returns the stored value interpreted as a string and a boolean that
  92. // is false if no value was stored at the key.
  93. func (n NamespacedKV) String(key string) (string, bool) {
  94. keyBs := append(n.prefix, []byte(key)...)
  95. valBs, err := n.db.Get(keyBs, nil)
  96. if err != nil {
  97. return "", false
  98. }
  99. return string(valBs), true
  100. }
  101. // PutBytes stores a new byte slice. Any existing value (even if of another type)
  102. // is overwritten.
  103. func (n *NamespacedKV) PutBytes(key string, val []byte) {
  104. keyBs := append(n.prefix, []byte(key)...)
  105. n.db.Put(keyBs, val, nil)
  106. }
  107. // Bytes returns the stored value as a raw byte slice and a boolean that
  108. // is false if no value was stored at the key.
  109. func (n NamespacedKV) Bytes(key string) ([]byte, bool) {
  110. keyBs := append(n.prefix, []byte(key)...)
  111. valBs, err := n.db.Get(keyBs, nil)
  112. if err != nil {
  113. return nil, false
  114. }
  115. return valBs, true
  116. }
  117. // PutBool stores a new boolean. Any existing value (even if of another type)
  118. // is overwritten.
  119. func (n *NamespacedKV) PutBool(key string, val bool) {
  120. keyBs := append(n.prefix, []byte(key)...)
  121. if val {
  122. n.db.Put(keyBs, []byte{0x0}, nil)
  123. } else {
  124. n.db.Put(keyBs, []byte{0x1}, nil)
  125. }
  126. }
  127. // Bool returns the stored value as a boolean and a boolean that
  128. // is false if no value was stored at the key.
  129. func (n NamespacedKV) Bool(key string) (bool, bool) {
  130. keyBs := append(n.prefix, []byte(key)...)
  131. valBs, err := n.db.Get(keyBs, nil)
  132. if err != nil {
  133. return false, false
  134. }
  135. return valBs[0] == 0x0, true
  136. }
  137. // Delete deletes the specified key. It is allowed to delete a nonexistent
  138. // key.
  139. func (n NamespacedKV) Delete(key string) {
  140. keyBs := append(n.prefix, []byte(key)...)
  141. n.db.Delete(keyBs, nil)
  142. }