leveldb-ruby 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. data/README +17 -0
  2. data/ext/leveldb/extconf.rb +10 -0
  3. data/ext/leveldb/leveldb.cc +181 -0
  4. data/leveldb/Makefile +172 -0
  5. data/leveldb/db/builder.cc +90 -0
  6. data/leveldb/db/builder.h +36 -0
  7. data/leveldb/db/corruption_test.cc +354 -0
  8. data/leveldb/db/db_bench.cc +677 -0
  9. data/leveldb/db/db_impl.cc +1236 -0
  10. data/leveldb/db/db_impl.h +180 -0
  11. data/leveldb/db/db_iter.cc +298 -0
  12. data/leveldb/db/db_iter.h +26 -0
  13. data/leveldb/db/db_test.cc +1192 -0
  14. data/leveldb/db/dbformat.cc +87 -0
  15. data/leveldb/db/dbformat.h +165 -0
  16. data/leveldb/db/dbformat_test.cc +112 -0
  17. data/leveldb/db/filename.cc +135 -0
  18. data/leveldb/db/filename.h +80 -0
  19. data/leveldb/db/filename_test.cc +122 -0
  20. data/leveldb/db/log_format.h +35 -0
  21. data/leveldb/db/log_reader.cc +254 -0
  22. data/leveldb/db/log_reader.h +108 -0
  23. data/leveldb/db/log_test.cc +500 -0
  24. data/leveldb/db/log_writer.cc +103 -0
  25. data/leveldb/db/log_writer.h +48 -0
  26. data/leveldb/db/memtable.cc +108 -0
  27. data/leveldb/db/memtable.h +85 -0
  28. data/leveldb/db/repair.cc +384 -0
  29. data/leveldb/db/skiplist.h +378 -0
  30. data/leveldb/db/skiplist_test.cc +378 -0
  31. data/leveldb/db/snapshot.h +66 -0
  32. data/leveldb/db/table_cache.cc +95 -0
  33. data/leveldb/db/table_cache.h +50 -0
  34. data/leveldb/db/version_edit.cc +268 -0
  35. data/leveldb/db/version_edit.h +106 -0
  36. data/leveldb/db/version_edit_test.cc +46 -0
  37. data/leveldb/db/version_set.cc +1060 -0
  38. data/leveldb/db/version_set.h +306 -0
  39. data/leveldb/db/write_batch.cc +138 -0
  40. data/leveldb/db/write_batch_internal.h +45 -0
  41. data/leveldb/db/write_batch_test.cc +89 -0
  42. data/leveldb/include/leveldb/cache.h +99 -0
  43. data/leveldb/include/leveldb/comparator.h +63 -0
  44. data/leveldb/include/leveldb/db.h +148 -0
  45. data/leveldb/include/leveldb/env.h +302 -0
  46. data/leveldb/include/leveldb/iterator.h +100 -0
  47. data/leveldb/include/leveldb/options.h +198 -0
  48. data/leveldb/include/leveldb/slice.h +109 -0
  49. data/leveldb/include/leveldb/status.h +100 -0
  50. data/leveldb/include/leveldb/table.h +70 -0
  51. data/leveldb/include/leveldb/table_builder.h +91 -0
  52. data/leveldb/include/leveldb/write_batch.h +64 -0
  53. data/leveldb/port/port.h +23 -0
  54. data/leveldb/port/port_android.cc +64 -0
  55. data/leveldb/port/port_android.h +150 -0
  56. data/leveldb/port/port_chromium.cc +80 -0
  57. data/leveldb/port/port_chromium.h +97 -0
  58. data/leveldb/port/port_example.h +115 -0
  59. data/leveldb/port/port_osx.cc +50 -0
  60. data/leveldb/port/port_osx.h +125 -0
  61. data/leveldb/port/port_posix.cc +50 -0
  62. data/leveldb/port/port_posix.h +94 -0
  63. data/leveldb/port/sha1_portable.cc +298 -0
  64. data/leveldb/port/sha1_portable.h +25 -0
  65. data/leveldb/port/sha1_test.cc +39 -0
  66. data/leveldb/port/win/stdint.h +24 -0
  67. data/leveldb/table/block.cc +263 -0
  68. data/leveldb/table/block.h +43 -0
  69. data/leveldb/table/block_builder.cc +109 -0
  70. data/leveldb/table/block_builder.h +57 -0
  71. data/leveldb/table/format.cc +131 -0
  72. data/leveldb/table/format.h +103 -0
  73. data/leveldb/table/iterator.cc +67 -0
  74. data/leveldb/table/iterator_wrapper.h +63 -0
  75. data/leveldb/table/merger.cc +197 -0
  76. data/leveldb/table/merger.h +26 -0
  77. data/leveldb/table/table.cc +175 -0
  78. data/leveldb/table/table_builder.cc +227 -0
  79. data/leveldb/table/table_test.cc +845 -0
  80. data/leveldb/table/two_level_iterator.cc +182 -0
  81. data/leveldb/table/two_level_iterator.h +34 -0
  82. data/leveldb/util/arena.cc +68 -0
  83. data/leveldb/util/arena.h +68 -0
  84. data/leveldb/util/arena_test.cc +68 -0
  85. data/leveldb/util/cache.cc +255 -0
  86. data/leveldb/util/cache_test.cc +169 -0
  87. data/leveldb/util/coding.cc +194 -0
  88. data/leveldb/util/coding.h +104 -0
  89. data/leveldb/util/coding_test.cc +173 -0
  90. data/leveldb/util/comparator.cc +72 -0
  91. data/leveldb/util/crc32c.cc +332 -0
  92. data/leveldb/util/crc32c.h +45 -0
  93. data/leveldb/util/crc32c_test.cc +72 -0
  94. data/leveldb/util/env.cc +77 -0
  95. data/leveldb/util/env_chromium.cc +612 -0
  96. data/leveldb/util/env_posix.cc +606 -0
  97. data/leveldb/util/env_test.cc +102 -0
  98. data/leveldb/util/hash.cc +45 -0
  99. data/leveldb/util/hash.h +19 -0
  100. data/leveldb/util/histogram.cc +128 -0
  101. data/leveldb/util/histogram.h +41 -0
  102. data/leveldb/util/logging.cc +81 -0
  103. data/leveldb/util/logging.h +47 -0
  104. data/leveldb/util/mutexlock.h +39 -0
  105. data/leveldb/util/options.cc +28 -0
  106. data/leveldb/util/random.h +59 -0
  107. data/leveldb/util/status.cc +75 -0
  108. data/leveldb/util/testharness.cc +65 -0
  109. data/leveldb/util/testharness.h +129 -0
  110. data/leveldb/util/testutil.cc +51 -0
  111. data/leveldb/util/testutil.h +53 -0
  112. data/lib/leveldb.rb +36 -0
  113. metadata +183 -0
@@ -0,0 +1,87 @@
1
+ // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file. See the AUTHORS file for names of contributors.
4
+
5
+ #include <stdio.h>
6
+ #include "db/dbformat.h"
7
+ #include "port/port.h"
8
+ #include "util/coding.h"
9
+
10
+ namespace leveldb {
11
+
12
+ static uint64_t PackSequenceAndType(uint64_t seq, ValueType t) {
13
+ assert(seq <= kMaxSequenceNumber);
14
+ assert(t <= kValueTypeForSeek);
15
+ return (seq << 8) | t;
16
+ }
17
+
18
+ void AppendInternalKey(std::string* result, const ParsedInternalKey& key) {
19
+ result->append(key.user_key.data(), key.user_key.size());
20
+ PutFixed64(result, PackSequenceAndType(key.sequence, key.type));
21
+ }
22
+
23
+ std::string ParsedInternalKey::DebugString() const {
24
+ char buf[50];
25
+ snprintf(buf, sizeof(buf), "' @ %llu : %d",
26
+ (unsigned long long) sequence,
27
+ int(type));
28
+ std::string result = "'";
29
+ result += user_key.ToString();
30
+ result += buf;
31
+ return result;
32
+ }
33
+
34
+ const char* InternalKeyComparator::Name() const {
35
+ return "leveldb.InternalKeyComparator";
36
+ }
37
+
38
+ int InternalKeyComparator::Compare(const Slice& akey, const Slice& bkey) const {
39
+ // Order by:
40
+ // increasing user key (according to user-supplied comparator)
41
+ // decreasing sequence number
42
+ // decreasing type (though sequence# should be enough to disambiguate)
43
+ int r = user_comparator_->Compare(ExtractUserKey(akey), ExtractUserKey(bkey));
44
+ if (r == 0) {
45
+ const uint64_t anum = DecodeFixed64(akey.data() + akey.size() - 8);
46
+ const uint64_t bnum = DecodeFixed64(bkey.data() + bkey.size() - 8);
47
+ if (anum > bnum) {
48
+ r = -1;
49
+ } else if (anum < bnum) {
50
+ r = +1;
51
+ }
52
+ }
53
+ return r;
54
+ }
55
+
56
+ void InternalKeyComparator::FindShortestSeparator(
57
+ std::string* start,
58
+ const Slice& limit) const {
59
+ // Attempt to shorten the user portion of the key
60
+ Slice user_start = ExtractUserKey(*start);
61
+ Slice user_limit = ExtractUserKey(limit);
62
+ std::string tmp(user_start.data(), user_start.size());
63
+ user_comparator_->FindShortestSeparator(&tmp, user_limit);
64
+ if (user_comparator_->Compare(*start, tmp) < 0) {
65
+ // User key has become larger. Tack on the earliest possible
66
+ // number to the shortened user key.
67
+ PutFixed64(&tmp, PackSequenceAndType(kMaxSequenceNumber,kValueTypeForSeek));
68
+ assert(this->Compare(*start, tmp) < 0);
69
+ assert(this->Compare(tmp, limit) < 0);
70
+ start->swap(tmp);
71
+ }
72
+ }
73
+
74
+ void InternalKeyComparator::FindShortSuccessor(std::string* key) const {
75
+ Slice user_key = ExtractUserKey(*key);
76
+ std::string tmp(user_key.data(), user_key.size());
77
+ user_comparator_->FindShortSuccessor(&tmp);
78
+ if (user_comparator_->Compare(user_key, tmp) < 0) {
79
+ // User key has become larger. Tack on the earliest possible
80
+ // number to the shortened user key.
81
+ PutFixed64(&tmp, PackSequenceAndType(kMaxSequenceNumber,kValueTypeForSeek));
82
+ assert(this->Compare(*key, tmp) < 0);
83
+ key->swap(tmp);
84
+ }
85
+ }
86
+
87
+ }
@@ -0,0 +1,165 @@
1
+ // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file. See the AUTHORS file for names of contributors.
4
+
5
+ #ifndef STORAGE_LEVELDB_DB_FORMAT_H_
6
+ #define STORAGE_LEVELDB_DB_FORMAT_H_
7
+
8
+ #include <stdio.h>
9
+ #include "leveldb/comparator.h"
10
+ #include "leveldb/db.h"
11
+ #include "leveldb/slice.h"
12
+ #include "leveldb/table_builder.h"
13
+ #include "util/coding.h"
14
+ #include "util/logging.h"
15
+
16
+ namespace leveldb {
17
+
18
+ // Grouping of constants. We may want to make some of these
19
+ // parameters set via options.
20
+ namespace config {
21
+ static const int kNumLevels = 7;
22
+
23
+ // Level-0 compaction is started when we hit this many files.
24
+ static const int kL0_CompactionTrigger = 4;
25
+
26
+ // Soft limit on number of level-0 files. We slow down writes at this point.
27
+ static const int kL0_SlowdownWritesTrigger = 8;
28
+
29
+ // Maximum number of level-0 files. We stop writes at this point.
30
+ static const int kL0_StopWritesTrigger = 12;
31
+
32
+ }
33
+
34
+ class InternalKey;
35
+
36
+ // Value types encoded as the last component of internal keys.
37
+ // DO NOT CHANGE THESE ENUM VALUES: they are embedded in the on-disk
38
+ // data structures.
39
+ enum ValueType {
40
+ kTypeDeletion = 0x0,
41
+ kTypeValue = 0x1,
42
+ };
43
+ // kValueTypeForSeek defines the ValueType that should be passed when
44
+ // constructing a ParsedInternalKey object for seeking to a particular
45
+ // sequence number (since we sort sequence numbers in decreasing order
46
+ // and the value type is embedded as the low 8 bits in the sequence
47
+ // number in internal keys, we need to use the highest-numbered
48
+ // ValueType, not the lowest).
49
+ static const ValueType kValueTypeForSeek = kTypeValue;
50
+
51
+ typedef uint64_t SequenceNumber;
52
+
53
+ // We leave eight bits empty at the bottom so a type and sequence#
54
+ // can be packed together into 64-bits.
55
+ static const SequenceNumber kMaxSequenceNumber =
56
+ ((0x1ull << 56) - 1);
57
+
58
+ struct ParsedInternalKey {
59
+ Slice user_key;
60
+ SequenceNumber sequence;
61
+ ValueType type;
62
+
63
+ ParsedInternalKey() { } // Intentionally left uninitialized (for speed)
64
+ ParsedInternalKey(const Slice& u, const SequenceNumber& seq, ValueType t)
65
+ : user_key(u), sequence(seq), type(t) { }
66
+ std::string DebugString() const;
67
+ };
68
+
69
+ // Return the length of the encoding of "key".
70
+ inline size_t InternalKeyEncodingLength(const ParsedInternalKey& key) {
71
+ return key.user_key.size() + 8;
72
+ }
73
+
74
+ // Append the serialization of "key" to *result.
75
+ extern void AppendInternalKey(std::string* result,
76
+ const ParsedInternalKey& key);
77
+
78
+ // Attempt to parse an internal key from "internal_key". On success,
79
+ // stores the parsed data in "*result", and returns true.
80
+ //
81
+ // On error, returns false, leaves "*result" in an undefined state.
82
+ extern bool ParseInternalKey(const Slice& internal_key,
83
+ ParsedInternalKey* result);
84
+
85
+ // Returns the user key portion of an internal key.
86
+ inline Slice ExtractUserKey(const Slice& internal_key) {
87
+ assert(internal_key.size() >= 8);
88
+ return Slice(internal_key.data(), internal_key.size() - 8);
89
+ }
90
+
91
+ inline ValueType ExtractValueType(const Slice& internal_key) {
92
+ assert(internal_key.size() >= 8);
93
+ const size_t n = internal_key.size();
94
+ uint64_t num = DecodeFixed64(internal_key.data() + n - 8);
95
+ unsigned char c = num & 0xff;
96
+ return static_cast<ValueType>(c);
97
+ }
98
+
99
+ // A comparator for internal keys that uses a specified comparator for
100
+ // the user key portion and breaks ties by decreasing sequence number.
101
+ class InternalKeyComparator : public Comparator {
102
+ private:
103
+ const Comparator* user_comparator_;
104
+ public:
105
+ explicit InternalKeyComparator(const Comparator* c) : user_comparator_(c) { }
106
+ virtual const char* Name() const;
107
+ virtual int Compare(const Slice& a, const Slice& b) const;
108
+ virtual void FindShortestSeparator(
109
+ std::string* start,
110
+ const Slice& limit) const;
111
+ virtual void FindShortSuccessor(std::string* key) const;
112
+
113
+ const Comparator* user_comparator() const { return user_comparator_; }
114
+
115
+ int Compare(const InternalKey& a, const InternalKey& b) const;
116
+ };
117
+
118
+ // Modules in this directory should keep internal keys wrapped inside
119
+ // the following class instead of plain strings so that we do not
120
+ // incorrectly use string comparisons instead of an InternalKeyComparator.
121
+ class InternalKey {
122
+ private:
123
+ std::string rep_;
124
+ public:
125
+ InternalKey() { } // Leave rep_ as empty to indicate it is invalid
126
+ InternalKey(const Slice& user_key, SequenceNumber s, ValueType t) {
127
+ AppendInternalKey(&rep_, ParsedInternalKey(user_key, s, t));
128
+ }
129
+
130
+ void DecodeFrom(const Slice& s) { rep_.assign(s.data(), s.size()); }
131
+ Slice Encode() const {
132
+ assert(!rep_.empty());
133
+ return rep_;
134
+ }
135
+
136
+ Slice user_key() const { return ExtractUserKey(rep_); }
137
+
138
+ void SetFrom(const ParsedInternalKey& p) {
139
+ rep_.clear();
140
+ AppendInternalKey(&rep_, p);
141
+ }
142
+
143
+ void Clear() { rep_.clear(); }
144
+ };
145
+
146
+ inline int InternalKeyComparator::Compare(
147
+ const InternalKey& a, const InternalKey& b) const {
148
+ return Compare(a.Encode(), b.Encode());
149
+ }
150
+
151
+ inline bool ParseInternalKey(const Slice& internal_key,
152
+ ParsedInternalKey* result) {
153
+ const size_t n = internal_key.size();
154
+ if (n < 8) return false;
155
+ uint64_t num = DecodeFixed64(internal_key.data() + n - 8);
156
+ unsigned char c = num & 0xff;
157
+ result->sequence = num >> 8;
158
+ result->type = static_cast<ValueType>(c);
159
+ result->user_key = Slice(internal_key.data(), n - 8);
160
+ return (c <= static_cast<unsigned char>(kTypeValue));
161
+ }
162
+
163
+ }
164
+
165
+ #endif // STORAGE_LEVELDB_DB_FORMAT_H_
@@ -0,0 +1,112 @@
1
+ // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file. See the AUTHORS file for names of contributors.
4
+
5
+ #include "db/dbformat.h"
6
+ #include "util/logging.h"
7
+ #include "util/testharness.h"
8
+
9
+ namespace leveldb {
10
+
11
+ static std::string IKey(const std::string& user_key,
12
+ uint64_t seq,
13
+ ValueType vt) {
14
+ std::string encoded;
15
+ AppendInternalKey(&encoded, ParsedInternalKey(user_key, seq, vt));
16
+ return encoded;
17
+ }
18
+
19
+ static std::string Shorten(const std::string& s, const std::string& l) {
20
+ std::string result = s;
21
+ InternalKeyComparator(BytewiseComparator()).FindShortestSeparator(&result, l);
22
+ return result;
23
+ }
24
+
25
+ static std::string ShortSuccessor(const std::string& s) {
26
+ std::string result = s;
27
+ InternalKeyComparator(BytewiseComparator()).FindShortSuccessor(&result);
28
+ return result;
29
+ }
30
+
31
+ static void TestKey(const std::string& key,
32
+ uint64_t seq,
33
+ ValueType vt) {
34
+ std::string encoded = IKey(key, seq, vt);
35
+
36
+ Slice in(encoded);
37
+ ParsedInternalKey decoded("", 0, kTypeValue);
38
+
39
+ ASSERT_TRUE(ParseInternalKey(in, &decoded));
40
+ ASSERT_EQ(key, decoded.user_key.ToString());
41
+ ASSERT_EQ(seq, decoded.sequence);
42
+ ASSERT_EQ(vt, decoded.type);
43
+
44
+ ASSERT_TRUE(!ParseInternalKey(Slice("bar"), &decoded));
45
+ }
46
+
47
+ class FormatTest { };
48
+
49
+ TEST(FormatTest, InternalKey_EncodeDecode) {
50
+ const char* keys[] = { "", "k", "hello", "longggggggggggggggggggggg" };
51
+ const uint64_t seq[] = {
52
+ 1, 2, 3,
53
+ (1ull << 8) - 1, 1ull << 8, (1ull << 8) + 1,
54
+ (1ull << 16) - 1, 1ull << 16, (1ull << 16) + 1,
55
+ (1ull << 32) - 1, 1ull << 32, (1ull << 32) + 1
56
+ };
57
+ for (int k = 0; k < sizeof(keys) / sizeof(keys[0]); k++) {
58
+ for (int s = 0; s < sizeof(seq) / sizeof(seq[0]); s++) {
59
+ TestKey(keys[k], seq[s], kTypeValue);
60
+ TestKey("hello", 1, kTypeDeletion);
61
+ }
62
+ }
63
+ }
64
+
65
+ TEST(FormatTest, InternalKeyShortSeparator) {
66
+ // When user keys are same
67
+ ASSERT_EQ(IKey("foo", 100, kTypeValue),
68
+ Shorten(IKey("foo", 100, kTypeValue),
69
+ IKey("foo", 99, kTypeValue)));
70
+ ASSERT_EQ(IKey("foo", 100, kTypeValue),
71
+ Shorten(IKey("foo", 100, kTypeValue),
72
+ IKey("foo", 101, kTypeValue)));
73
+ ASSERT_EQ(IKey("foo", 100, kTypeValue),
74
+ Shorten(IKey("foo", 100, kTypeValue),
75
+ IKey("foo", 100, kTypeValue)));
76
+ ASSERT_EQ(IKey("foo", 100, kTypeValue),
77
+ Shorten(IKey("foo", 100, kTypeValue),
78
+ IKey("foo", 100, kTypeDeletion)));
79
+
80
+ // When user keys are misordered
81
+ ASSERT_EQ(IKey("foo", 100, kTypeValue),
82
+ Shorten(IKey("foo", 100, kTypeValue),
83
+ IKey("bar", 99, kTypeValue)));
84
+
85
+ // When user keys are different, but correctly ordered
86
+ ASSERT_EQ(IKey("g", kMaxSequenceNumber, kValueTypeForSeek),
87
+ Shorten(IKey("foo", 100, kTypeValue),
88
+ IKey("hello", 200, kTypeValue)));
89
+
90
+ // When start user key is prefix of limit user key
91
+ ASSERT_EQ(IKey("foo", 100, kTypeValue),
92
+ Shorten(IKey("foo", 100, kTypeValue),
93
+ IKey("foobar", 200, kTypeValue)));
94
+
95
+ // When limit user key is prefix of start user key
96
+ ASSERT_EQ(IKey("foobar", 100, kTypeValue),
97
+ Shorten(IKey("foobar", 100, kTypeValue),
98
+ IKey("foo", 200, kTypeValue)));
99
+ }
100
+
101
+ TEST(FormatTest, InternalKeyShortestSuccessor) {
102
+ ASSERT_EQ(IKey("g", kMaxSequenceNumber, kValueTypeForSeek),
103
+ ShortSuccessor(IKey("foo", 100, kTypeValue)));
104
+ ASSERT_EQ(IKey("\xff\xff", 100, kTypeValue),
105
+ ShortSuccessor(IKey("\xff\xff", 100, kTypeValue)));
106
+ }
107
+
108
+ }
109
+
110
+ int main(int argc, char** argv) {
111
+ return leveldb::test::RunAllTests();
112
+ }
@@ -0,0 +1,135 @@
1
+ // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file. See the AUTHORS file for names of contributors.
4
+
5
+ #include <ctype.h>
6
+ #include <stdio.h>
7
+ #include "db/filename.h"
8
+ #include "db/dbformat.h"
9
+ #include "leveldb/env.h"
10
+ #include "util/logging.h"
11
+
12
+ namespace leveldb {
13
+
14
+ static std::string MakeFileName(const std::string& name, uint64_t number,
15
+ const char* suffix) {
16
+ char buf[100];
17
+ snprintf(buf, sizeof(buf), "/%06llu.%s",
18
+ static_cast<unsigned long long>(number),
19
+ suffix);
20
+ return name + buf;
21
+ }
22
+
23
+ std::string LogFileName(const std::string& name, uint64_t number) {
24
+ assert(number > 0);
25
+ return MakeFileName(name, number, "log");
26
+ }
27
+
28
+ std::string TableFileName(const std::string& name, uint64_t number) {
29
+ assert(number > 0);
30
+ return MakeFileName(name, number, "sst");
31
+ }
32
+
33
+ std::string DescriptorFileName(const std::string& dbname, uint64_t number) {
34
+ assert(number > 0);
35
+ char buf[100];
36
+ snprintf(buf, sizeof(buf), "/MANIFEST-%06llu",
37
+ static_cast<unsigned long long>(number));
38
+ return dbname + buf;
39
+ }
40
+
41
+ std::string CurrentFileName(const std::string& dbname) {
42
+ return dbname + "/CURRENT";
43
+ }
44
+
45
+ std::string LockFileName(const std::string& dbname) {
46
+ return dbname + "/LOCK";
47
+ }
48
+
49
+ std::string TempFileName(const std::string& dbname, uint64_t number) {
50
+ assert(number > 0);
51
+ return MakeFileName(dbname, number, "dbtmp");
52
+ }
53
+
54
+ std::string InfoLogFileName(const std::string& dbname) {
55
+ return dbname + "/LOG";
56
+ }
57
+
58
+ // Return the name of the old info log file for "dbname".
59
+ std::string OldInfoLogFileName(const std::string& dbname) {
60
+ return dbname + "/LOG.old";
61
+ }
62
+
63
+
64
+ // Owned filenames have the form:
65
+ // dbname/CURRENT
66
+ // dbname/LOCK
67
+ // dbname/LOG
68
+ // dbname/LOG.old
69
+ // dbname/MANIFEST-[0-9]+
70
+ // dbname/[0-9]+.(log|sst)
71
+ bool ParseFileName(const std::string& fname,
72
+ uint64_t* number,
73
+ FileType* type) {
74
+ Slice rest(fname);
75
+ if (rest == "CURRENT") {
76
+ *number = 0;
77
+ *type = kCurrentFile;
78
+ } else if (rest == "LOCK") {
79
+ *number = 0;
80
+ *type = kDBLockFile;
81
+ } else if (rest == "LOG" || rest == "LOG.old") {
82
+ *number = 0;
83
+ *type = kInfoLogFile;
84
+ } else if (rest.starts_with("MANIFEST-")) {
85
+ rest.remove_prefix(strlen("MANIFEST-"));
86
+ uint64_t num;
87
+ if (!ConsumeDecimalNumber(&rest, &num)) {
88
+ return false;
89
+ }
90
+ if (!rest.empty()) {
91
+ return false;
92
+ }
93
+ *type = kDescriptorFile;
94
+ *number = num;
95
+ } else {
96
+ // Avoid strtoull() to keep filename format independent of the
97
+ // current locale
98
+ uint64_t num;
99
+ if (!ConsumeDecimalNumber(&rest, &num)) {
100
+ return false;
101
+ }
102
+ Slice suffix = rest;
103
+ if (suffix == Slice(".log")) {
104
+ *type = kLogFile;
105
+ } else if (suffix == Slice(".sst")) {
106
+ *type = kTableFile;
107
+ } else if (suffix == Slice(".dbtmp")) {
108
+ *type = kTempFile;
109
+ } else {
110
+ return false;
111
+ }
112
+ *number = num;
113
+ }
114
+ return true;
115
+ }
116
+
117
+ Status SetCurrentFile(Env* env, const std::string& dbname,
118
+ uint64_t descriptor_number) {
119
+ // Remove leading "dbname/" and add newline to manifest file name
120
+ std::string manifest = DescriptorFileName(dbname, descriptor_number);
121
+ Slice contents = manifest;
122
+ assert(contents.starts_with(dbname + "/"));
123
+ contents.remove_prefix(dbname.size() + 1);
124
+ std::string tmp = TempFileName(dbname, descriptor_number);
125
+ Status s = WriteStringToFile(env, contents.ToString() + "\n", tmp);
126
+ if (s.ok()) {
127
+ s = env->RenameFile(tmp, CurrentFileName(dbname));
128
+ }
129
+ if (!s.ok()) {
130
+ env->DeleteFile(tmp);
131
+ }
132
+ return s;
133
+ }
134
+
135
+ }