Changeset 128217 in webkit
- Timestamp:
- Sep 11, 2012 12:17:20 PM (12 years ago)
- Location:
- trunk/Source
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r128215 r128217 1 2012-09-11 Joshua Bell <jsbell@chromium.org> 2 3 IndexedDB: IDBObjectStore.count() is slow 4 https://bugs.webkit.org/show_bug.cgi?id=96033 5 6 Reviewed by Tony Chang. 7 8 Avoid decoding record values when performing count() iteration, and factor out common code 9 used for initializing object store and index cursors. Also, remove unused indexDataId() 10 methods (which date back to the SQLite backing store), and rename some p's and q's. 11 12 No new tests - no functional changes. Covered by existing test: 13 LayoutTests/storage/indexeddb/objectstore-count.html 14 15 * Modules/indexeddb/IDBBackingStore.h: Expose new (internal) ObjectStoreKeyCursor 16 (IDBBackingStore): 17 * Modules/indexeddb/IDBLevelDBBackingStore.cpp: 18 (WebCore): Factor out common CursorOptions initialization code. The objectStoreCursorOptions() 19 function is needed for this patch. The indexCursorOptions() function is not, but eliminates 20 duplicated code and is a nearly identical refactor. 21 (WebCore::IDBLevelDBBackingStore::openObjectStoreCursor): Refactor. 22 (WebCore::IDBLevelDBBackingStore::openObjectStoreKeyCursor): Implement. 23 (WebCore::IDBLevelDBBackingStore::openIndexKeyCursor): Refactor. 24 (WebCore::IDBLevelDBBackingStore::openIndexCursor): Ditto. 25 * Modules/indexeddb/IDBLevelDBBackingStore.h: 26 (IDBLevelDBBackingStore): 27 * Modules/indexeddb/IDBObjectStoreBackendImpl.cpp: 28 (WebCore::IDBObjectStoreBackendImpl::countInternal): Use ObjectStoreKeyCursor for iteration. 29 1 30 2012-09-11 Ojan Vafai <ojan@chromium.org> 2 31 -
trunk/Source/WebCore/Modules/indexeddb/IDBBackingStore.h
r124675 r128217 102 102 virtual String value() = 0; 103 103 virtual PassRefPtr<ObjectStoreRecordIdentifier> objectStoreRecordIdentifier() = 0; 104 virtual int64_t indexDataId() = 0;105 104 virtual void close() = 0; 106 105 virtual ~Cursor() { }; … … 108 107 109 108 virtual PassRefPtr<Cursor> openObjectStoreCursor(int64_t databaseId, int64_t objectStoreId, const IDBKeyRange*, IDBCursor::Direction) = 0; 109 virtual PassRefPtr<Cursor> openObjectStoreKeyCursor(int64_t databaseId, int64_t objectStoreId, const IDBKeyRange*, IDBCursor::Direction) = 0; 110 110 virtual PassRefPtr<Cursor> openIndexKeyCursor(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange*, IDBCursor::Direction) = 0; 111 111 virtual PassRefPtr<Cursor> openIndexCursor(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange*, IDBCursor::Direction) = 0; -
trunk/Source/WebCore/Modules/indexeddb/IDBLevelDBBackingStore.cpp
r128136 r128217 1140 1140 virtual String value() = 0; 1141 1141 virtual PassRefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> objectStoreRecordIdentifier() = 0; 1142 virtual int64_t indexDataId() = 0;1143 1142 virtual void close() { } 1144 1143 … … 1318 1317 } 1319 1318 1319 class ObjectStoreKeyCursorImpl : public CursorImplCommon { 1320 public: 1321 static PassRefPtr<ObjectStoreKeyCursorImpl> create(LevelDBTransaction* transaction, const CursorOptions& cursorOptions) 1322 { 1323 return adoptRef(new ObjectStoreKeyCursorImpl(transaction, cursorOptions)); 1324 } 1325 1326 virtual PassRefPtr<IDBBackingStore::Cursor> clone() 1327 { 1328 return adoptRef(new ObjectStoreKeyCursorImpl(this)); 1329 } 1330 1331 // CursorImplCommon 1332 virtual String value() { ASSERT_NOT_REACHED(); return String(); } 1333 virtual PassRefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> objectStoreRecordIdentifier() OVERRIDE 1334 { 1335 return m_identifier; 1336 } 1337 virtual bool loadCurrentRow(); 1338 1339 private: 1340 ObjectStoreKeyCursorImpl(LevelDBTransaction* transaction, const CursorOptions& cursorOptions) 1341 : CursorImplCommon(transaction, cursorOptions) 1342 { 1343 } 1344 1345 ObjectStoreKeyCursorImpl(const ObjectStoreKeyCursorImpl* other) 1346 : CursorImplCommon(other) 1347 { 1348 } 1349 1350 RefPtr<LevelDBRecordIdentifier> m_identifier; 1351 }; 1352 1353 bool ObjectStoreKeyCursorImpl::loadCurrentRow() 1354 { 1355 const char* keyPosition = m_iterator->key().begin(); 1356 const char* keyLimit = m_iterator->key().end(); 1357 1358 ObjectStoreDataKey objectStoreDataKey; 1359 keyPosition = ObjectStoreDataKey::decode(keyPosition, keyLimit, &objectStoreDataKey); 1360 ASSERT(keyPosition); 1361 if (!keyPosition) 1362 return false; 1363 1364 m_currentKey = objectStoreDataKey.userKey(); 1365 1366 int64_t version; 1367 const char* valuePosition = decodeVarInt(m_iterator->value().begin(), m_iterator->value().end(), version); 1368 ASSERT(valuePosition); 1369 if (!valuePosition) 1370 return false; 1371 1372 // FIXME: This re-encodes what was just decoded; try and optimize. 1373 m_identifier = LevelDBRecordIdentifier::create(encodeIDBKey(*m_currentKey), version); 1374 1375 return true; 1376 } 1377 1320 1378 class ObjectStoreCursorImpl : public CursorImplCommon { 1321 1379 public: … … 1336 1394 return m_identifier; 1337 1395 } 1338 virtual int64_t indexDataId() { ASSERT_NOT_REACHED(); return 0; }1339 1396 virtual bool loadCurrentRow(); 1340 1397 … … 1357 1414 bool ObjectStoreCursorImpl::loadCurrentRow() 1358 1415 { 1359 const char* p= m_iterator->key().begin();1416 const char* keyPosition = m_iterator->key().begin(); 1360 1417 const char* keyLimit = m_iterator->key().end(); 1361 1418 1362 1419 ObjectStoreDataKey objectStoreDataKey; 1363 p = ObjectStoreDataKey::decode(p, keyLimit, &objectStoreDataKey);1364 ASSERT( p);1365 if (! p)1420 keyPosition = ObjectStoreDataKey::decode(keyPosition, keyLimit, &objectStoreDataKey); 1421 ASSERT(keyPosition); 1422 if (!keyPosition) 1366 1423 return false; 1367 1424 … … 1369 1426 1370 1427 int64_t version; 1371 const char* q= decodeVarInt(m_iterator->value().begin(), m_iterator->value().end(), version);1372 ASSERT( q);1373 if (! q)1428 const char* valuePosition = decodeVarInt(m_iterator->value().begin(), m_iterator->value().end(), version); 1429 ASSERT(valuePosition); 1430 if (!valuePosition) 1374 1431 return false; 1375 1432 … … 1377 1434 m_identifier = LevelDBRecordIdentifier::create(encodeIDBKey(*m_currentKey), version); 1378 1435 1379 m_currentValue = decodeString( q, m_iterator->value().end());1436 m_currentValue = decodeString(valuePosition, m_iterator->value().end()); 1380 1437 1381 1438 return true; … … 1398 1455 virtual PassRefPtr<IDBKey> primaryKey() { return m_primaryKey; } 1399 1456 virtual PassRefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> objectStoreRecordIdentifier() { ASSERT_NOT_REACHED(); return 0; } 1400 virtual int64_t indexDataId() { ASSERT_NOT_REACHED(); return 0; }1401 1457 virtual bool loadCurrentRow(); 1402 1458 … … 1418 1474 bool IndexKeyCursorImpl::loadCurrentRow() 1419 1475 { 1420 const char* p= m_iterator->key().begin();1476 const char* keyPosition = m_iterator->key().begin(); 1421 1477 const char* keyLimit = m_iterator->key().end(); 1478 1422 1479 IndexDataKey indexDataKey; 1423 p = IndexDataKey::decode(p, keyLimit, &indexDataKey);1480 keyPosition = IndexDataKey::decode(keyPosition, keyLimit, &indexDataKey); 1424 1481 1425 1482 m_currentKey = indexDataKey.userKey(); 1426 1483 1427 1484 int64_t indexDataVersion; 1428 const char* q= decodeVarInt(m_iterator->value().begin(), m_iterator->value().end(), indexDataVersion);1429 ASSERT( q);1430 if (! q)1431 return false; 1432 1433 q = decodeIDBKey(q, m_iterator->value().end(), m_primaryKey);1434 ASSERT( q);1435 if (! q)1485 const char* valuePosition = decodeVarInt(m_iterator->value().begin(), m_iterator->value().end(), indexDataVersion); 1486 ASSERT(valuePosition); 1487 if (!valuePosition) 1488 return false; 1489 1490 valuePosition = decodeIDBKey(valuePosition, m_iterator->value().end(), m_primaryKey); 1491 ASSERT(valuePosition); 1492 if (!valuePosition) 1436 1493 return false; 1437 1494 … … 1474 1531 virtual PassRefPtr<IDBKey> primaryKey() { return m_primaryKey; } 1475 1532 virtual PassRefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> objectStoreRecordIdentifier() { ASSERT_NOT_REACHED(); return 0; } 1476 virtual int64_t indexDataId() { ASSERT_NOT_REACHED(); return 0; }1477 1533 bool loadCurrentRow(); 1478 1534 … … 1498 1554 bool IndexCursorImpl::loadCurrentRow() 1499 1555 { 1500 const char* p= m_iterator->key().begin();1501 const char* limit = m_iterator->key().end();1556 const char* keyPosition = m_iterator->key().begin(); 1557 const char* keyLimit = m_iterator->key().end(); 1502 1558 1503 1559 IndexDataKey indexDataKey; 1504 p = IndexDataKey::decode(p, limit, &indexDataKey);1560 keyPosition = IndexDataKey::decode(keyPosition, keyLimit, &indexDataKey); 1505 1561 1506 1562 m_currentKey = indexDataKey.userKey(); 1507 1563 1508 const char* q= m_iterator->value().begin();1564 const char* valuePosition = m_iterator->value().begin(); 1509 1565 const char* valueLimit = m_iterator->value().end(); 1510 1566 1511 1567 int64_t indexDataVersion; 1512 q = decodeVarInt(q, valueLimit, indexDataVersion);1513 ASSERT( q);1514 if (! q)1515 return false; 1516 q = decodeIDBKey(q, valueLimit, m_primaryKey);1517 ASSERT( q);1518 if (! q)1568 valuePosition = decodeVarInt(valuePosition, valueLimit, indexDataVersion); 1569 ASSERT(valuePosition); 1570 if (!valuePosition) 1571 return false; 1572 valuePosition = decodeIDBKey(valuePosition, valueLimit, m_primaryKey); 1573 ASSERT(valuePosition); 1574 if (!valuePosition) 1519 1575 return false; 1520 1576 … … 1542 1598 } 1543 1599 1544 } 1545 1546 PassRefPtr<IDBBackingStore::Cursor> IDBLevelDBBackingStore::openObjectStoreCursor(int64_t databaseId, int64_t objectStoreId, const IDBKeyRange* range, IDBCursor::Direction direction) 1547 { 1548 IDB_TRACE("IDBLevelDBBackingStore::openObjectStoreCursor"); 1549 ASSERT(m_currentTransaction); 1550 CursorOptions cursorOptions; 1551 1600 bool objectStoreCursorOptions(LevelDBTransaction* transaction, int64_t databaseId, int64_t objectStoreId, const IDBKeyRange* range, IDBCursor::Direction direction, CursorOptions& cursorOptions) 1601 { 1552 1602 bool lowerBound = range && range->lower(); 1553 1603 bool upperBound = range && range->upper(); … … 1570 1620 else { 1571 1621 // We need a key that exists. 1572 if (!findGreatestKeyLessThanOrEqual( m_currentTransaction.get(), cursorOptions.highKey, cursorOptions.highKey))1573 return 0;1622 if (!findGreatestKeyLessThanOrEqual(transaction, cursorOptions.highKey, cursorOptions.highKey)) 1623 return false; 1574 1624 cursorOptions.highOpen = false; 1575 1625 } … … 1581 1631 // For reverse cursors, we need a key that exists. 1582 1632 Vector<char> foundHighKey; 1583 if (!findGreatestKeyLessThanOrEqual( m_currentTransaction.get(), cursorOptions.highKey, foundHighKey))1584 return 0;1633 if (!findGreatestKeyLessThanOrEqual(transaction, cursorOptions.highKey, foundHighKey)) 1634 return false; 1585 1635 1586 1636 // If the target key should not be included, but we end up with a smaller key, we should include that. … … 1592 1642 } 1593 1643 1594 RefPtr<ObjectStoreCursorImpl> cursor = ObjectStoreCursorImpl::create(m_currentTransaction.get(), cursorOptions); 1595 if (!cursor->firstSeek()) 1596 return 0; 1597 1598 return cursor.release(); 1599 } 1600 1601 PassRefPtr<IDBBackingStore::Cursor> IDBLevelDBBackingStore::openIndexKeyCursor(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange* range, IDBCursor::Direction direction) 1602 { 1603 IDB_TRACE("IDBLevelDBBackingStore::openIndexKeyCursor"); 1604 ASSERT(m_currentTransaction); 1605 CursorOptions cursorOptions; 1644 return true; 1645 } 1646 1647 bool indexCursorOptions(LevelDBTransaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange* range, IDBCursor::Direction direction, CursorOptions& cursorOptions) 1648 { 1649 ASSERT(transaction); 1606 1650 bool lowerBound = range && range->lower(); 1607 1651 bool upperBound = range && range->upper(); … … 1622 1666 1623 1667 if (!cursorOptions.forward) { // We need a key that exists. 1624 if (!findGreatestKeyLessThanOrEqual( m_currentTransaction.get(), cursorOptions.highKey, cursorOptions.highKey))1625 return 0;1668 if (!findGreatestKeyLessThanOrEqual(transaction, cursorOptions.highKey, cursorOptions.highKey)) 1669 return false; 1626 1670 cursorOptions.highOpen = false; 1627 1671 } … … 1631 1675 1632 1676 Vector<char> foundHighKey; 1633 if (!findGreatestKeyLessThanOrEqual( m_currentTransaction.get(), cursorOptions.highKey, foundHighKey)) // Seek to the *last* key in the set of non-unique keys.1634 return 0;1677 if (!findGreatestKeyLessThanOrEqual(transaction, cursorOptions.highKey, foundHighKey)) // Seek to the *last* key in the set of non-unique keys. 1678 return false; 1635 1679 1636 1680 // If the target key should not be included, but we end up with a smaller key, we should include that. … … 1641 1685 } 1642 1686 1687 return true; 1688 } 1689 1690 } 1691 1692 PassRefPtr<IDBBackingStore::Cursor> IDBLevelDBBackingStore::openObjectStoreCursor(int64_t databaseId, int64_t objectStoreId, const IDBKeyRange* range, IDBCursor::Direction direction) 1693 { 1694 IDB_TRACE("IDBLevelDBBackingStore::openObjectStoreCursor"); 1695 ASSERT(m_currentTransaction); 1696 CursorOptions cursorOptions; 1697 if (!objectStoreCursorOptions(m_currentTransaction.get(), databaseId, objectStoreId, range, direction, cursorOptions)) 1698 return 0; 1699 RefPtr<ObjectStoreCursorImpl> cursor = ObjectStoreCursorImpl::create(m_currentTransaction.get(), cursorOptions); 1700 if (!cursor->firstSeek()) 1701 return 0; 1702 1703 return cursor.release(); 1704 } 1705 1706 PassRefPtr<IDBBackingStore::Cursor> IDBLevelDBBackingStore::openObjectStoreKeyCursor(int64_t databaseId, int64_t objectStoreId, const IDBKeyRange* range, IDBCursor::Direction direction) 1707 { 1708 IDB_TRACE("IDBLevelDBBackingStore::openObjectStoreKeyCursor"); 1709 ASSERT(m_currentTransaction); 1710 CursorOptions cursorOptions; 1711 if (!objectStoreCursorOptions(m_currentTransaction.get(), databaseId, objectStoreId, range, direction, cursorOptions)) 1712 return 0; 1713 RefPtr<ObjectStoreKeyCursorImpl> cursor = ObjectStoreKeyCursorImpl::create(m_currentTransaction.get(), cursorOptions); 1714 if (!cursor->firstSeek()) 1715 return 0; 1716 1717 return cursor.release(); 1718 } 1719 1720 PassRefPtr<IDBBackingStore::Cursor> IDBLevelDBBackingStore::openIndexKeyCursor(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange* range, IDBCursor::Direction direction) 1721 { 1722 IDB_TRACE("IDBLevelDBBackingStore::openIndexKeyCursor"); 1723 ASSERT(m_currentTransaction); 1724 CursorOptions cursorOptions; 1725 if (!indexCursorOptions(m_currentTransaction.get(), databaseId, objectStoreId, indexId, range, direction, cursorOptions)) 1726 return 0; 1643 1727 RefPtr<IndexKeyCursorImpl> cursor = IndexKeyCursorImpl::create(m_currentTransaction.get(), cursorOptions); 1644 1728 if (!cursor->firstSeek()) … … 1653 1737 ASSERT(m_currentTransaction); 1654 1738 CursorOptions cursorOptions; 1655 bool lowerBound = range && range->lower(); 1656 bool upperBound = range && range->upper(); 1657 cursorOptions.forward = (direction == IDBCursor::NEXT_NO_DUPLICATE || direction == IDBCursor::NEXT); 1658 cursorOptions.unique = (direction == IDBCursor::NEXT_NO_DUPLICATE || direction == IDBCursor::PREV_NO_DUPLICATE); 1659 1660 if (!lowerBound) { 1661 cursorOptions.lowKey = IndexDataKey::encodeMinKey(databaseId, objectStoreId, indexId); 1662 cursorOptions.lowOpen = false; // Included. 1663 } else { 1664 cursorOptions.lowKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, *range->lower()); 1665 cursorOptions.lowOpen = range->lowerOpen(); 1666 } 1667 1668 if (!upperBound) { 1669 cursorOptions.highKey = IndexDataKey::encodeMaxKey(databaseId, objectStoreId, indexId); 1670 cursorOptions.highOpen = false; // Included. 1671 1672 if (!cursorOptions.forward) { // We need a key that exists. 1673 if (!findGreatestKeyLessThanOrEqual(m_currentTransaction.get(), cursorOptions.highKey, cursorOptions.highKey)) 1674 return 0; 1675 cursorOptions.highOpen = false; 1676 } 1677 } else { 1678 cursorOptions.highKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, *range->upper()); 1679 cursorOptions.highOpen = range->upperOpen(); 1680 1681 Vector<char> foundHighKey; 1682 if (!findGreatestKeyLessThanOrEqual(m_currentTransaction.get(), cursorOptions.highKey, foundHighKey)) // Seek to the *last* key in the set of non-unique keys. 1683 return 0; 1684 1685 // If the target key should not be included, but we end up with a smaller key, we should include that. 1686 if (cursorOptions.highOpen && compareIndexKeys(foundHighKey, cursorOptions.highKey) < 0) 1687 cursorOptions.highOpen = false; 1688 1689 cursorOptions.highKey = foundHighKey; 1690 } 1691 1739 if (!indexCursorOptions(m_currentTransaction.get(), databaseId, objectStoreId, indexId, range, direction, cursorOptions)) 1740 return 0; 1692 1741 RefPtr<IndexCursorImpl> cursor = IndexCursorImpl::create(m_currentTransaction.get(), cursorOptions); 1693 1742 if (!cursor->firstSeek()) -
trunk/Source/WebCore/Modules/indexeddb/IDBLevelDBBackingStore.h
r125627 r128217 74 74 virtual bool keyExistsInIndex(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& indexKey, RefPtr<IDBKey>& foundPrimaryKey); 75 75 76 virtual PassRefPtr<Cursor> openObjectStoreKeyCursor(int64_t databaseId, int64_t objectStoreId, const IDBKeyRange*, IDBCursor::Direction); 76 77 virtual PassRefPtr<Cursor> openObjectStoreCursor(int64_t databaseId, int64_t objectStoreId, const IDBKeyRange*, IDBCursor::Direction); 77 78 virtual PassRefPtr<Cursor> openIndexKeyCursor(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange*, IDBCursor::Direction); -
trunk/Source/WebCore/Modules/indexeddb/IDBObjectStoreBackendImpl.cpp
r127752 r128217 542 542 IDB_TRACE("IDBObjectStoreBackendImpl::countInternal"); 543 543 uint32_t count = 0; 544 RefPtr<IDBBackingStore::Cursor> backingStoreCursor = objectStore->backingStore()->openObjectStore Cursor(objectStore->databaseId(), objectStore->id(), range.get(), IDBCursor::NEXT);544 RefPtr<IDBBackingStore::Cursor> backingStoreCursor = objectStore->backingStore()->openObjectStoreKeyCursor(objectStore->databaseId(), objectStore->id(), range.get(), IDBCursor::NEXT); 545 545 if (!backingStoreCursor) { 546 546 callbacks->onSuccess(SerializedScriptValue::numberValue(count)); -
trunk/Source/WebKit/chromium/tests/IDBFakeBackingStore.h
r124675 r128217 64 64 virtual bool keyExistsInIndex(int64_t databaseid, int64_t objectStoreId, int64_t indexId, const IDBKey& indexKey, RefPtr<IDBKey>& foundPrimaryKey) OVERRIDE { return false; } 65 65 66 virtual PassRefPtr<Cursor> openObjectStoreKeyCursor(int64_t databaseId, int64_t objectStoreId, const IDBKeyRange*, IDBCursor::Direction) OVERRIDE { return PassRefPtr<Cursor>(); } 66 67 virtual PassRefPtr<Cursor> openObjectStoreCursor(int64_t databaseId, int64_t objectStoreId, const IDBKeyRange*, IDBCursor::Direction) OVERRIDE { return PassRefPtr<Cursor>(); } 67 68 virtual PassRefPtr<Cursor> openIndexKeyCursor(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange*, IDBCursor::Direction) OVERRIDE { return PassRefPtr<Cursor>(); }
Note: See TracChangeset
for help on using the changeset viewer.