| 140 | |
| 141 | |
| 142 | Try<Storage::State> LevelDBStorage::restore(const string& path) |
| 143 | { |
| 144 | leveldb::Options options; |
| 145 | options.create_if_missing = true; |
| 146 | |
| 147 | // TODO(benh): Can't use varint comparator until bug discussed at |
| 148 | // groups.google.com/group/leveldb/browse_thread/thread/17eac39168909ba7 |
| 149 | // gets fixed. For now, we are using the default byte-wise |
| 150 | // comparator and *assuming* that the encoding from unsigned long to |
| 151 | // string produces a stable ordering. Checks below. |
| 152 | // options.comparator = &comparator; |
| 153 | |
| 154 | const string& one = encode(1); |
| 155 | const string& two = encode(2); |
| 156 | const string& ten = encode(10); |
| 157 | |
| 158 | CHECK(leveldb::BytewiseComparator()->Compare(one, two) < 0); |
| 159 | CHECK(leveldb::BytewiseComparator()->Compare(two, one) > 0); |
| 160 | CHECK(leveldb::BytewiseComparator()->Compare(one, ten) < 0); |
| 161 | CHECK(leveldb::BytewiseComparator()->Compare(ten, two) > 0); |
| 162 | CHECK(leveldb::BytewiseComparator()->Compare(ten, ten) == 0); |
| 163 | |
| 164 | Stopwatch stopwatch; |
| 165 | stopwatch.start(); |
| 166 | |
| 167 | leveldb::Status status = leveldb::DB::Open(options, path, &db); |
| 168 | |
| 169 | if (!status.ok()) { |
| 170 | // TODO(benh): Consider trying to repair the DB. |
| 171 | return Error(status.ToString()); |
| 172 | } |
| 173 | |
| 174 | VLOG(1) << "Opened db in " << stopwatch.elapsed(); |
| 175 | |
| 176 | stopwatch.start(); // Restart the stopwatch. |
| 177 | |
| 178 | // TODO(benh): Conditionally compact to avoid long recovery times? |
| 179 | db->CompactRange(nullptr, nullptr); |
| 180 | |
| 181 | VLOG(1) << "Compacted db in " << stopwatch.elapsed(); |
| 182 | |
| 183 | State state; |
| 184 | state.begin = 0; |
| 185 | state.end = 0; |
| 186 | |
| 187 | // TODO(benh): Consider just reading the "promise" record (e.g., |
| 188 | // 'encode(0, false)') and then iterating over the rest of the |
| 189 | // records and confirming that they are all indeed of type |
| 190 | // Record::Action. |
| 191 | |
| 192 | stopwatch.start(); // Restart the stopwatch. |
| 193 | |
| 194 | leveldb::Iterator* iterator = db->NewIterator(leveldb::ReadOptions()); |
| 195 | |
| 196 | VLOG(1) << "Created db iterator in " << stopwatch.elapsed(); |
| 197 | |
| 198 | stopwatch.start(); // Restart the stopwatch. |
| 199 | |