leveldb_transaction.cc revision 868fa2fe829687343ffae624259930155e16dbd8
1// Copyright (c) 2013 The Chromium 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. 4 5#include "content/browser/indexed_db/leveldb/leveldb_transaction.h" 6 7#include <string> 8 9#include "base/logging.h" 10#include "content/browser/indexed_db/leveldb/leveldb_database.h" 11#include "content/browser/indexed_db/leveldb/leveldb_slice.h" 12#include "content/browser/indexed_db/leveldb/leveldb_write_batch.h" 13#include "third_party/leveldatabase/src/include/leveldb/db.h" 14 15namespace content { 16 17scoped_refptr<LevelDBTransaction> LevelDBTransaction::Create( 18 LevelDBDatabase* db) { 19 return make_scoped_refptr(new LevelDBTransaction(db)); 20} 21 22LevelDBTransaction::LevelDBTransaction(LevelDBDatabase* db) 23 : db_(db), snapshot_(db), comparator_(db->Comparator()), finished_(false) { 24 tree_.abstractor().comparator_ = comparator_; 25} 26 27LevelDBTransaction::AVLTreeNode::AVLTreeNode() {} 28LevelDBTransaction::AVLTreeNode::~AVLTreeNode() {} 29 30void LevelDBTransaction::ClearTree() { 31 TreeType::Iterator iterator; 32 iterator.StartIterLeast(&tree_); 33 34 std::vector<AVLTreeNode*> nodes; 35 36 while (*iterator) { 37 nodes.push_back(*iterator); 38 ++iterator; 39 } 40 tree_.Purge(); 41 42 for (size_t i = 0; i < nodes.size(); ++i) 43 delete nodes[i]; 44} 45 46LevelDBTransaction::~LevelDBTransaction() { ClearTree(); } 47 48static void InitVector(const LevelDBSlice& slice, std::vector<char>* vector) { 49 vector->clear(); 50 vector->insert(vector->end(), slice.begin(), slice.end()); 51} 52 53void LevelDBTransaction::Set(const LevelDBSlice& key, 54 std::vector<char>* value, 55 bool deleted) { 56 DCHECK(!finished_); 57 bool new_node = false; 58 AVLTreeNode* node = tree_.Search(key); 59 60 if (!node) { 61 node = new AVLTreeNode; 62 InitVector(key, &node->key); 63 tree_.Insert(node); 64 new_node = true; 65 } 66 node->value.swap(*value); 67 node->deleted = deleted; 68 69 if (new_node) 70 NotifyIteratorsOfTreeChange(); 71} 72 73void LevelDBTransaction::Put(const LevelDBSlice& key, 74 std::vector<char>* value) { 75 Set(key, value, false); 76} 77 78void LevelDBTransaction::Remove(const LevelDBSlice& key) { 79 std::vector<char> empty; 80 Set(key, &empty, true); 81} 82 83bool LevelDBTransaction::Get(const LevelDBSlice& key, 84 std::string* value, 85 bool* found) { 86 *found = false; 87 DCHECK(!finished_); 88 AVLTreeNode* node = tree_.Search(key); 89 90 if (node) { 91 if (node->deleted) 92 return true; 93 94 value->assign(node->value.begin(), node->value.end()); 95 *found = true; 96 return true; 97 } 98 99 bool ok = db_->Get(key, value, found, &snapshot_); 100 if (!ok) { 101 DCHECK(!*found); 102 return false; 103 } 104 return true; 105} 106 107bool LevelDBTransaction::Commit() { 108 DCHECK(!finished_); 109 110 if (tree_.IsEmpty()) { 111 finished_ = true; 112 return true; 113 } 114 115 scoped_ptr<LevelDBWriteBatch> write_batch = LevelDBWriteBatch::Create(); 116 117 TreeType::Iterator iterator; 118 iterator.StartIterLeast(&tree_); 119 120 while (*iterator) { 121 AVLTreeNode* node = *iterator; 122 if (!node->deleted) 123 write_batch->Put(LevelDBSlice(node->key), LevelDBSlice(node->value)); 124 else 125 write_batch->Remove(LevelDBSlice(node->key)); 126 ++iterator; 127 } 128 129 if (!db_->Write(*write_batch)) 130 return false; 131 132 ClearTree(); 133 finished_ = true; 134 return true; 135} 136 137void LevelDBTransaction::Rollback() { 138 DCHECK(!finished_); 139 finished_ = true; 140 ClearTree(); 141} 142 143scoped_ptr<LevelDBIterator> LevelDBTransaction::CreateIterator() { 144 return TransactionIterator::Create(this).PassAs<LevelDBIterator>(); 145} 146 147scoped_ptr<LevelDBTransaction::TreeIterator> 148LevelDBTransaction::TreeIterator::Create(LevelDBTransaction* transaction) { 149 return make_scoped_ptr(new TreeIterator(transaction)); 150} 151 152bool LevelDBTransaction::TreeIterator::IsValid() const { return !!*iterator_; } 153 154void LevelDBTransaction::TreeIterator::SeekToLast() { 155 iterator_.StartIterGreatest(tree_); 156 if (IsValid()) 157 key_ = (*iterator_)->key; 158} 159 160void LevelDBTransaction::TreeIterator::Seek(const LevelDBSlice& target) { 161 iterator_.StartIter(tree_, target, TreeType::EQUAL); 162 if (!IsValid()) 163 iterator_.StartIter(tree_, target, TreeType::GREATER); 164 165 if (IsValid()) 166 key_ = (*iterator_)->key; 167} 168 169void LevelDBTransaction::TreeIterator::Next() { 170 DCHECK(IsValid()); 171 ++iterator_; 172 if (IsValid()) { 173 DCHECK(transaction_->comparator_->Compare(LevelDBSlice((*iterator_)->key), 174 LevelDBSlice(key_)) > 175 0); 176 key_ = (*iterator_)->key; 177 } 178} 179 180void LevelDBTransaction::TreeIterator::Prev() { 181 DCHECK(IsValid()); 182 --iterator_; 183 if (IsValid()) { 184 DCHECK(tree_->abstractor().comparator_->Compare( 185 LevelDBSlice((*iterator_)->key), LevelDBSlice(key_)) < 186 0); 187 key_ = (*iterator_)->key; 188 } 189} 190 191LevelDBSlice LevelDBTransaction::TreeIterator::Key() const { 192 DCHECK(IsValid()); 193 return LevelDBSlice(key_); 194} 195 196LevelDBSlice LevelDBTransaction::TreeIterator::Value() const { 197 DCHECK(IsValid()); 198 DCHECK(!IsDeleted()); 199 return LevelDBSlice((*iterator_)->value); 200} 201 202bool LevelDBTransaction::TreeIterator::IsDeleted() const { 203 DCHECK(IsValid()); 204 return (*iterator_)->deleted; 205} 206 207void LevelDBTransaction::TreeIterator::Reset() { 208 DCHECK(IsValid()); 209 iterator_.StartIter(tree_, LevelDBSlice(key_), TreeType::EQUAL); 210 DCHECK(IsValid()); 211} 212 213LevelDBTransaction::TreeIterator::~TreeIterator() {} 214 215LevelDBTransaction::TreeIterator::TreeIterator(LevelDBTransaction* transaction) 216 : tree_(&transaction->tree_), transaction_(transaction) {} 217 218scoped_ptr<LevelDBTransaction::TransactionIterator> 219LevelDBTransaction::TransactionIterator::Create( 220 scoped_refptr<LevelDBTransaction> transaction) { 221 return make_scoped_ptr(new TransactionIterator(transaction)); 222} 223 224LevelDBTransaction::TransactionIterator::TransactionIterator( 225 scoped_refptr<LevelDBTransaction> transaction) 226 : transaction_(transaction), 227 comparator_(transaction_->comparator_), 228 tree_iterator_(TreeIterator::Create(transaction_.get())), 229 db_iterator_(transaction_->db_->CreateIterator(&transaction_->snapshot_)), 230 current_(0), 231 direction_(FORWARD), 232 tree_changed_(false) { 233 transaction_->RegisterIterator(this); 234} 235 236LevelDBTransaction::TransactionIterator::~TransactionIterator() { 237 transaction_->UnregisterIterator(this); 238} 239 240bool LevelDBTransaction::TransactionIterator::IsValid() const { 241 return !!current_; 242} 243 244void LevelDBTransaction::TransactionIterator::SeekToLast() { 245 tree_iterator_->SeekToLast(); 246 db_iterator_->SeekToLast(); 247 direction_ = REVERSE; 248 249 HandleConflictsAndDeletes(); 250 SetCurrentIteratorToLargestKey(); 251} 252 253void LevelDBTransaction::TransactionIterator::Seek(const LevelDBSlice& target) { 254 tree_iterator_->Seek(target); 255 db_iterator_->Seek(target); 256 direction_ = FORWARD; 257 258 HandleConflictsAndDeletes(); 259 SetCurrentIteratorToSmallestKey(); 260} 261 262void LevelDBTransaction::TransactionIterator::Next() { 263 DCHECK(IsValid()); 264 if (tree_changed_) 265 RefreshTreeIterator(); 266 267 if (direction_ != FORWARD) { 268 // Ensure the non-current iterator is positioned after Key(). 269 270 LevelDBIterator* non_current = 271 (current_ == db_iterator_.get()) ? tree_iterator_.get() 272 : db_iterator_.get(); 273 274 non_current->Seek(Key()); 275 if (non_current->IsValid() && 276 !comparator_->Compare(non_current->Key(), Key())) 277 non_current->Next(); // Take an extra step so the non-current key is 278 // strictly greater than Key(). 279 280 DCHECK(!non_current->IsValid() || 281 comparator_->Compare(non_current->Key(), Key()) > 0); 282 283 direction_ = FORWARD; 284 } 285 286 current_->Next(); 287 HandleConflictsAndDeletes(); 288 SetCurrentIteratorToSmallestKey(); 289} 290 291void LevelDBTransaction::TransactionIterator::Prev() { 292 DCHECK(IsValid()); 293 if (tree_changed_) 294 RefreshTreeIterator(); 295 296 if (direction_ != REVERSE) { 297 // Ensure the non-current iterator is positioned before Key(). 298 299 LevelDBIterator* non_current = 300 (current_ == db_iterator_.get()) ? tree_iterator_.get() 301 : db_iterator_.get(); 302 303 non_current->Seek(Key()); 304 if (non_current->IsValid()) { 305 // Iterator is at first entry >= Key(). 306 // Step back once to entry < key. 307 // This is why we don't check for the keys being the same before 308 // stepping, like we do in Next() above. 309 non_current->Prev(); 310 } else { 311 non_current->SeekToLast(); // Iterator has no entries >= Key(). Position 312 // at last entry. 313 } 314 DCHECK(!non_current->IsValid() || 315 comparator_->Compare(non_current->Key(), Key()) < 0); 316 317 direction_ = REVERSE; 318 } 319 320 current_->Prev(); 321 HandleConflictsAndDeletes(); 322 SetCurrentIteratorToLargestKey(); 323} 324 325LevelDBSlice LevelDBTransaction::TransactionIterator::Key() const { 326 DCHECK(IsValid()); 327 if (tree_changed_) 328 RefreshTreeIterator(); 329 return current_->Key(); 330} 331 332LevelDBSlice LevelDBTransaction::TransactionIterator::Value() const { 333 DCHECK(IsValid()); 334 if (tree_changed_) 335 RefreshTreeIterator(); 336 return current_->Value(); 337} 338 339void LevelDBTransaction::TransactionIterator::TreeChanged() { 340 tree_changed_ = true; 341} 342 343void LevelDBTransaction::TransactionIterator::RefreshTreeIterator() const { 344 DCHECK(tree_changed_); 345 346 tree_changed_ = false; 347 348 if (tree_iterator_->IsValid() && tree_iterator_.get() == current_) { 349 tree_iterator_->Reset(); 350 return; 351 } 352 353 if (db_iterator_->IsValid()) { 354 // There could be new nodes in the tree that we should iterate over. 355 356 if (direction_ == FORWARD) { 357 // Try to seek tree iterator to something greater than the db iterator. 358 tree_iterator_->Seek(db_iterator_->Key()); 359 if (tree_iterator_->IsValid() && 360 !comparator_->Compare(tree_iterator_->Key(), db_iterator_->Key())) 361 tree_iterator_->Next(); // If equal, take another step so the tree 362 // iterator is strictly greater. 363 } else { 364 // If going backward, seek to a key less than the db iterator. 365 DCHECK_EQ(REVERSE, direction_); 366 tree_iterator_->Seek(db_iterator_->Key()); 367 if (tree_iterator_->IsValid()) 368 tree_iterator_->Prev(); 369 } 370 } 371} 372 373bool LevelDBTransaction::TransactionIterator::TreeIteratorIsLower() const { 374 return comparator_->Compare(tree_iterator_->Key(), db_iterator_->Key()) < 0; 375} 376 377bool LevelDBTransaction::TransactionIterator::TreeIteratorIsHigher() const { 378 return comparator_->Compare(tree_iterator_->Key(), db_iterator_->Key()) > 0; 379} 380 381void LevelDBTransaction::TransactionIterator::HandleConflictsAndDeletes() { 382 bool loop = true; 383 384 while (loop) { 385 loop = false; 386 387 if (tree_iterator_->IsValid() && db_iterator_->IsValid() && 388 !comparator_->Compare(tree_iterator_->Key(), db_iterator_->Key())) { 389 // For equal keys, the tree iterator takes precedence, so move the 390 // database iterator another step. 391 if (direction_ == FORWARD) 392 db_iterator_->Next(); 393 else 394 db_iterator_->Prev(); 395 } 396 397 // Skip over delete markers in the tree iterator until it catches up with 398 // the db iterator. 399 if (tree_iterator_->IsValid() && tree_iterator_->IsDeleted()) { 400 if (direction_ == FORWARD && 401 (!db_iterator_->IsValid() || TreeIteratorIsLower())) { 402 tree_iterator_->Next(); 403 loop = true; 404 } else if (direction_ == REVERSE && 405 (!db_iterator_->IsValid() || TreeIteratorIsHigher())) { 406 tree_iterator_->Prev(); 407 loop = true; 408 } 409 } 410 } 411} 412 413void 414LevelDBTransaction::TransactionIterator::SetCurrentIteratorToSmallestKey() { 415 LevelDBIterator* smallest = 0; 416 417 if (tree_iterator_->IsValid()) 418 smallest = tree_iterator_.get(); 419 420 if (db_iterator_->IsValid()) { 421 if (!smallest || 422 comparator_->Compare(db_iterator_->Key(), smallest->Key()) < 0) 423 smallest = db_iterator_.get(); 424 } 425 426 current_ = smallest; 427} 428 429void LevelDBTransaction::TransactionIterator::SetCurrentIteratorToLargestKey() { 430 LevelDBIterator* largest = 0; 431 432 if (tree_iterator_->IsValid()) 433 largest = tree_iterator_.get(); 434 435 if (db_iterator_->IsValid()) { 436 if (!largest || 437 comparator_->Compare(db_iterator_->Key(), largest->Key()) > 0) 438 largest = db_iterator_.get(); 439 } 440 441 current_ = largest; 442} 443 444void LevelDBTransaction::RegisterIterator(TransactionIterator* iterator) { 445 DCHECK(iterators_.find(iterator) == iterators_.end()); 446 iterators_.insert(iterator); 447} 448 449void LevelDBTransaction::UnregisterIterator(TransactionIterator* iterator) { 450 DCHECK(iterators_.find(iterator) != iterators_.end()); 451 iterators_.erase(iterator); 452} 453 454void LevelDBTransaction::NotifyIteratorsOfTreeChange() { 455 for (std::set<TransactionIterator*>::iterator i = iterators_.begin(); 456 i != iterators_.end(); 457 ++i) { 458 TransactionIterator* transaction_iterator = *i; 459 transaction_iterator->TreeChanged(); 460 } 461} 462 463scoped_ptr<LevelDBWriteOnlyTransaction> LevelDBWriteOnlyTransaction::Create( 464 LevelDBDatabase* db) { 465 return make_scoped_ptr(new LevelDBWriteOnlyTransaction(db)); 466} 467 468LevelDBWriteOnlyTransaction::LevelDBWriteOnlyTransaction(LevelDBDatabase* db) 469 : db_(db), write_batch_(LevelDBWriteBatch::Create()), finished_(false) {} 470 471LevelDBWriteOnlyTransaction::~LevelDBWriteOnlyTransaction() { 472 write_batch_->Clear(); 473} 474 475void LevelDBWriteOnlyTransaction::Remove(const LevelDBSlice& key) { 476 DCHECK(!finished_); 477 write_batch_->Remove(key); 478} 479 480bool LevelDBWriteOnlyTransaction::Commit() { 481 DCHECK(!finished_); 482 483 if (!db_->Write(*write_batch_)) 484 return false; 485 486 finished_ = true; 487 write_batch_->Clear(); 488 return true; 489} 490 491} // namespace content 492