leveldb_backend.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // Copyright (C) 2018 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 backend
  7. import (
  8. "github.com/syndtr/goleveldb/leveldb"
  9. "github.com/syndtr/goleveldb/leveldb/iterator"
  10. "github.com/syndtr/goleveldb/leveldb/util"
  11. )
  12. // leveldbBackend implements Backend on top of a leveldb
  13. type leveldbBackend struct {
  14. ldb *leveldb.DB
  15. closeWG *closeWaitGroup
  16. location string
  17. }
  18. func newLeveldbBackend(ldb *leveldb.DB, location string) *leveldbBackend {
  19. return &leveldbBackend{
  20. ldb: ldb,
  21. closeWG: &closeWaitGroup{},
  22. location: location,
  23. }
  24. }
  25. func (b *leveldbBackend) NewReadTransaction() (ReadTransaction, error) {
  26. return b.newSnapshot()
  27. }
  28. func (b *leveldbBackend) newSnapshot() (leveldbSnapshot, error) {
  29. rel, err := newReleaser(b.closeWG)
  30. if err != nil {
  31. return leveldbSnapshot{}, err
  32. }
  33. snap, err := b.ldb.GetSnapshot()
  34. if err != nil {
  35. rel.Release()
  36. return leveldbSnapshot{}, wrapLeveldbErr(err)
  37. }
  38. return leveldbSnapshot{
  39. snap: snap,
  40. rel: rel,
  41. }, nil
  42. }
  43. func (b *leveldbBackend) Close() error {
  44. b.closeWG.CloseWait()
  45. return wrapLeveldbErr(b.ldb.Close())
  46. }
  47. func (b *leveldbBackend) Get(key []byte) ([]byte, error) {
  48. val, err := b.ldb.Get(key, nil)
  49. return val, wrapLeveldbErr(err)
  50. }
  51. func (b *leveldbBackend) NewPrefixIterator(prefix []byte) (Iterator, error) {
  52. return &leveldbIterator{b.ldb.NewIterator(util.BytesPrefix(prefix), nil)}, nil
  53. }
  54. func (b *leveldbBackend) NewRangeIterator(first, last []byte) (Iterator, error) {
  55. return &leveldbIterator{b.ldb.NewIterator(&util.Range{Start: first, Limit: last}, nil)}, nil
  56. }
  57. func (b *leveldbBackend) Location() string {
  58. return b.location
  59. }
  60. // leveldbSnapshot implements backend.ReadTransaction
  61. type leveldbSnapshot struct {
  62. snap *leveldb.Snapshot
  63. rel *releaser
  64. }
  65. func (l leveldbSnapshot) Get(key []byte) ([]byte, error) {
  66. val, err := l.snap.Get(key, nil)
  67. return val, wrapLeveldbErr(err)
  68. }
  69. func (l leveldbSnapshot) NewPrefixIterator(prefix []byte) (Iterator, error) {
  70. return l.snap.NewIterator(util.BytesPrefix(prefix), nil), nil
  71. }
  72. func (l leveldbSnapshot) NewRangeIterator(first, last []byte) (Iterator, error) {
  73. return l.snap.NewIterator(&util.Range{Start: first, Limit: last}, nil), nil
  74. }
  75. func (l leveldbSnapshot) Release() {
  76. l.snap.Release()
  77. l.rel.Release()
  78. }
  79. type leveldbIterator struct {
  80. iterator.Iterator
  81. }
  82. func (it *leveldbIterator) Error() error {
  83. return wrapLeveldbErr(it.Iterator.Error())
  84. }
  85. // wrapLeveldbErr wraps errors so that the backend package can recognize them
  86. func wrapLeveldbErr(err error) error {
  87. switch err {
  88. case leveldb.ErrClosed:
  89. return errClosed
  90. case leveldb.ErrNotFound:
  91. return errNotFound
  92. }
  93. return err
  94. }