Title: [109825] trunk/Source
Revision
109825
Author
jsb...@chromium.org
Date
2012-03-05 17:33:34 -0800 (Mon, 05 Mar 2012)

Log Message

IndexedDB: Handle LevelDB database corruption
https://bugs.webkit.org/show_bug.cgi?id=79413

Source/WebCore:

Add LevelDBDatabase::destroy() method so that clients can retry if open() fails.

Reviewed by Tony Chang.

Test: webkit_unit_tests --gtest_filter='LevelDBDatabaseTest.CorruptionTest'

* Modules/indexeddb/IDBLevelDBBackingStore.cpp: Implement open/destroy/open strategy.
(WebCore::IDBLevelDBBackingStore::open):
* platform/leveldb/LevelDBDatabase.cpp:
(WebCore::LevelDBDatabase::destroy):
(WebCore):
* platform/leveldb/LevelDBDatabase.h:
(LevelDBDatabase):

Source/WebKit/chromium:

Reviewed by Tony Chang.

* WebKit.gypi:
* tests/LevelDBTest.cpp: Added.
(WebCore):
(SimpleComparator):
(WebCore::SimpleComparator::compare):
(WebCore::SimpleComparator::name):
(WebCore::encodeString):
(WebCore::TEST):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (109824 => 109825)


--- trunk/Source/WebCore/ChangeLog	2012-03-06 01:18:42 UTC (rev 109824)
+++ trunk/Source/WebCore/ChangeLog	2012-03-06 01:33:34 UTC (rev 109825)
@@ -1,3 +1,22 @@
+2012-03-05  Joshua Bell  <jsb...@chromium.org>
+
+        IndexedDB: Handle LevelDB database corruption
+        https://bugs.webkit.org/show_bug.cgi?id=79413
+
+        Add LevelDBDatabase::destroy() method so that clients can retry if open() fails.
+
+        Reviewed by Tony Chang.
+
+        Test: webkit_unit_tests --gtest_filter='LevelDBDatabaseTest.CorruptionTest'
+
+        * Modules/indexeddb/IDBLevelDBBackingStore.cpp: Implement open/destroy/open strategy.
+        (WebCore::IDBLevelDBBackingStore::open):
+        * platform/leveldb/LevelDBDatabase.cpp:
+        (WebCore::LevelDBDatabase::destroy):
+        (WebCore):
+        * platform/leveldb/LevelDBDatabase.h:
+        (LevelDBDatabase):
+
 2012-03-05  Stephen Chenney  <schen...@chromium.org>
 
         [Chromium] SVG Composite of Offset crashes

Modified: trunk/Source/WebCore/Modules/indexeddb/IDBLevelDBBackingStore.cpp (109824 => 109825)


--- trunk/Source/WebCore/Modules/indexeddb/IDBLevelDBBackingStore.cpp	2012-03-06 01:18:42 UTC (rev 109824)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBLevelDBBackingStore.cpp	2012-03-06 01:33:34 UTC (rev 109825)
@@ -150,6 +150,22 @@
         String path = pathByAppendingComponent(pathBase, securityOrigin->databaseIdentifier() + ".indexeddb.leveldb");
 
         db = LevelDBDatabase::open(path, comparator.get());
+
+        if (!db) {
+            LOG_ERROR("IndexedDB backing store open failed, attempting cleanup");
+            bool success = LevelDBDatabase::destroy(path);
+            if (!success) {
+                LOG_ERROR("IndexedDB backing store cleanup failed");
+                return PassRefPtr<IDBBackingStore>();
+            }
+
+            LOG_ERROR("IndexedDB backing store cleanup succeeded, reopening");
+            db = LevelDBDatabase::open(path, comparator.get());
+            if (!db) {
+                LOG_ERROR("IndexedDB backing store reopen after recovery failed");
+                return PassRefPtr<IDBBackingStore>();
+            }
+        }
     }
 
     if (!db)

Modified: trunk/Source/WebCore/platform/leveldb/LevelDBDatabase.cpp (109824 => 109825)


--- trunk/Source/WebCore/platform/leveldb/LevelDBDatabase.cpp	2012-03-06 01:18:42 UTC (rev 109824)
+++ trunk/Source/WebCore/platform/leveldb/LevelDBDatabase.cpp	2012-03-06 01:33:34 UTC (rev 109825)
@@ -112,6 +112,13 @@
     return leveldb::DB::Open(options, path.utf8().data(), db);
 }
 
+bool LevelDBDatabase::destroy(const String& fileName)
+{
+    leveldb::Options options;
+    const leveldb::Status s = leveldb::DestroyDB(fileName.utf8().data(), options);
+    return s.ok();
+}
+
 PassOwnPtr<LevelDBDatabase> LevelDBDatabase::open(const String& fileName, const LevelDBComparator* comparator)
 {
     OwnPtr<ComparatorAdapter> comparatorAdapter = adoptPtr(new ComparatorAdapter(comparator));

Modified: trunk/Source/WebCore/platform/leveldb/LevelDBDatabase.h (109824 => 109825)


--- trunk/Source/WebCore/platform/leveldb/LevelDBDatabase.h	2012-03-06 01:18:42 UTC (rev 109824)
+++ trunk/Source/WebCore/platform/leveldb/LevelDBDatabase.h	2012-03-06 01:33:34 UTC (rev 109825)
@@ -50,6 +50,7 @@
 public:
     static PassOwnPtr<LevelDBDatabase> open(const String& fileName, const LevelDBComparator*);
     static PassOwnPtr<LevelDBDatabase> openInMemory(const LevelDBComparator*);
+    static bool destroy(const String& fileName);
     ~LevelDBDatabase();
 
     bool put(const LevelDBSlice& key, const Vector<char>& value);

Modified: trunk/Source/WebKit/chromium/ChangeLog (109824 => 109825)


--- trunk/Source/WebKit/chromium/ChangeLog	2012-03-06 01:18:42 UTC (rev 109824)
+++ trunk/Source/WebKit/chromium/ChangeLog	2012-03-06 01:33:34 UTC (rev 109825)
@@ -1,3 +1,19 @@
+2012-03-05  Joshua Bell  <jsb...@chromium.org>
+
+        IndexedDB: Handle LevelDB database corruption
+        https://bugs.webkit.org/show_bug.cgi?id=79413
+
+        Reviewed by Tony Chang.
+
+        * WebKit.gypi:
+        * tests/LevelDBTest.cpp: Added.
+        (WebCore):
+        (SimpleComparator):
+        (WebCore::SimpleComparator::compare):
+        (WebCore::SimpleComparator::name):
+        (WebCore::encodeString):
+        (WebCore::TEST):
+
 2012-03-05  Min Qin  <qin...@google.com>
 
         Enable context menu on android

Modified: trunk/Source/WebKit/chromium/WebKit.gypi (109824 => 109825)


--- trunk/Source/WebKit/chromium/WebKit.gypi	2012-03-06 01:18:42 UTC (rev 109824)
+++ trunk/Source/WebKit/chromium/WebKit.gypi	2012-03-06 01:33:34 UTC (rev 109825)
@@ -105,6 +105,7 @@
             'tests/KURLTest.cpp',
             'tests/LayerChromiumTest.cpp',
             'tests/LayerTextureUpdaterTest.cpp',
+            'tests/LevelDBTest.cpp',
             'tests/PaintAggregatorTest.cpp',
             'tests/PODArenaTest.cpp',
             'tests/PODIntervalTreeTest.cpp',

Added: trunk/Source/WebKit/chromium/tests/LevelDBTest.cpp (0 => 109825)


--- trunk/Source/WebKit/chromium/tests/LevelDBTest.cpp	                        (rev 0)
+++ trunk/Source/WebKit/chromium/tests/LevelDBTest.cpp	2012-03-06 01:33:34 UTC (rev 109825)
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(LEVELDB)
+
+#include "FileSystem.h"
+#include "LevelDBComparator.h"
+#include "LevelDBDatabase.h"
+#include "LevelDBSlice.h"
+#include <gtest/gtest.h>
+#include <webkit/support/webkit_support.h>
+#include <wtf/Vector.h>
+
+using namespace WebCore;
+
+namespace {
+
+class SimpleComparator : public LevelDBComparator {
+public:
+    virtual int compare(const LevelDBSlice& a, const LevelDBSlice& b) const OVERRIDE
+    {
+        size_t len = std::min(a.end() - a.begin(), b.end() - b.begin());
+        return memcmp(a.begin(), b.begin(), len);
+    }
+    virtual const char* name() const OVERRIDE { return "temp_comparator"; }
+};
+
+Vector<char> encodeString(const std::string& s)
+{
+    Vector<char> ret(s.size());
+    for (size_t i = 0; i < s.size(); ++i)
+        ret.append(s[i]);
+    return ret;
+}
+
+TEST(LevelDBDatabaseTest, CorruptionTest)
+{
+    OwnPtr<webkit_support::ScopedTempDirectory> tempDirectory = adoptPtr(webkit_support::CreateScopedTempDirectory());
+    tempDirectory->CreateUniqueTempDir();
+    const char* path = tempDirectory->path().c_str();
+
+    const Vector<char> key = encodeString("key");
+    const Vector<char> putValue = encodeString("value");
+    Vector<char> gotValue;
+    SimpleComparator comparator;
+
+    OwnPtr<LevelDBDatabase> leveldb = LevelDBDatabase::open(path, &comparator);
+    EXPECT_TRUE(leveldb);
+    bool success = leveldb->put(key, putValue);
+    EXPECT_TRUE(success);
+    leveldb.release();
+    EXPECT_FALSE(leveldb);
+
+    leveldb = LevelDBDatabase::open(path, &comparator);
+    EXPECT_TRUE(leveldb);
+    success = leveldb->get(key, gotValue);
+    EXPECT_TRUE(success);
+    EXPECT_EQ(putValue, gotValue);
+    leveldb.release();
+    EXPECT_FALSE(leveldb);
+
+    String filepath = pathByAppendingComponent(path, "CURRENT");
+    PlatformFileHandle handle = openFile(filepath, OpenForWrite);
+    truncateFile(handle, 0);
+    closeFile(handle);
+
+    leveldb = LevelDBDatabase::open(path, &comparator);
+    EXPECT_FALSE(leveldb);
+
+    bool destroyed = LevelDBDatabase::destroy(path);
+    EXPECT_TRUE(destroyed);
+
+    leveldb = LevelDBDatabase::open(path, &comparator);
+    EXPECT_TRUE(leveldb);
+    success = leveldb->get(key, gotValue);
+    EXPECT_FALSE(success);
+}
+
+} // namespace
+
+#endif // USE(LEVELDB)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to