| 160 | } |
| 161 | |
| 162 | IStorage *RocksDBStorageFactory::create(int db, key_load_iterator iter, void *privdata) |
| 163 | { |
| 164 | ++db; // skip default col family |
| 165 | std::shared_ptr<rocksdb::ColumnFamilyHandle> spcolfamily(m_vecspcols[db].release()); |
| 166 | std::shared_ptr<rocksdb::ColumnFamilyHandle> spexpirecolfamily(m_vecspexpirecols[db].release()); |
| 167 | size_t count = 0; |
| 168 | bool fUnclean = false; |
| 169 | |
| 170 | std::string value; |
| 171 | auto status = m_spdb->Get(rocksdb::ReadOptions(), spcolfamily.get(), rocksdb::Slice(count_key, sizeof(count_key)), &value); |
| 172 | if (status.ok() && value.size() == sizeof(size_t)) |
| 173 | { |
| 174 | count = *reinterpret_cast<const size_t*>(value.data()); |
| 175 | m_spdb->Delete(rocksdb::WriteOptions(), spcolfamily.get(), rocksdb::Slice(count_key, sizeof(count_key))); |
| 176 | } |
| 177 | else |
| 178 | { |
| 179 | fUnclean = true; |
| 180 | } |
| 181 | |
| 182 | if (fUnclean || iter != nullptr) |
| 183 | { |
| 184 | count = 0; |
| 185 | auto opts = rocksdb::ReadOptions(); |
| 186 | opts.tailing = true; |
| 187 | std::unique_ptr<rocksdb::Iterator> it = std::unique_ptr<rocksdb::Iterator>(m_spdb->NewIterator(opts, spcolfamily.get())); |
| 188 | |
| 189 | it->SeekToFirst(); |
| 190 | bool fFirstRealKey = true; |
| 191 | |
| 192 | for (;it->Valid(); it->Next()) { |
| 193 | if (FInternalKey(it->key().data(), it->key().size())) |
| 194 | continue; |
| 195 | if (fUnclean && it->Valid() && fFirstRealKey) |
| 196 | printf("\tDatabase %d was not shutdown cleanly, recomputing metrics\n", db); |
| 197 | fFirstRealKey = false; |
| 198 | if (iter != nullptr) |
| 199 | iter(it->key().data()+HASHSLOT_PREFIX_BYTES, it->key().size()-HASHSLOT_PREFIX_BYTES, privdata); |
| 200 | ++count; |
| 201 | } |
| 202 | } |
| 203 | return new RocksDBStorageProvider(this, m_spdb, spcolfamily, spexpirecolfamily, nullptr, count); |
| 204 | } |
| 205 | |
| 206 | const char *RocksDBStorageFactory::name() const |
| 207 | { |
no test coverage detected