Unreviewed. Fix GTK+ build after r168209.
[WebKit-https.git] / Source / WebCore / platform / leveldb / LevelDBDatabase.cpp
1 /*
2  * Copyright (C) 2011 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "LevelDBDatabase.h"
28
29 #if USE(LEVELDB)
30
31 #include "LevelDBComparator.h"
32 #include "LevelDBIterator.h"
33 #include "LevelDBSlice.h"
34 #include "LevelDBWriteBatch.h"
35 #include "Logging.h"
36 #include "NotImplemented.h"
37 #include <helpers/memenv/memenv.h>
38 #include <leveldb/comparator.h>
39 #include <leveldb/db.h>
40 #include <leveldb/env.h>
41 #include <leveldb/slice.h>
42 #include <string>
43 #include <wtf/text/CString.h>
44 #include <wtf/text/WTFString.h>
45
46 namespace leveldb {
47
48 static Env* IDBEnv()
49 {
50     return leveldb::Env::Default();
51 }
52
53 }
54
55 namespace WebCore {
56
57 static leveldb::Slice makeSlice(const Vector<char>& value)
58 {
59     return leveldb::Slice(value.data(), value.size());
60 }
61
62 static leveldb::Slice makeSlice(const LevelDBSlice& s)
63 {
64     return leveldb::Slice(s.begin(), s.end() - s.begin());
65 }
66
67 static LevelDBSlice makeLevelDBSlice(const leveldb::Slice& s)
68 {
69     return LevelDBSlice(s.data(), s.data() + s.size());
70 }
71
72 class ComparatorAdapter : public leveldb::Comparator {
73 public:
74     ComparatorAdapter(const LevelDBComparator* comparator)
75         : m_comparator(comparator)
76     {
77     }
78
79     virtual int Compare(const leveldb::Slice& a, const leveldb::Slice& b) const
80     {
81         return m_comparator->compare(makeLevelDBSlice(a), makeLevelDBSlice(b));
82     }
83
84     virtual const char* Name() const { return m_comparator->name(); }
85
86     // FIXME: Support the methods below in the future.
87     virtual void FindShortestSeparator(std::string* /* start */, const leveldb::Slice& /* limit */) const { }
88     virtual void FindShortSuccessor(std::string* /* key */) const { }
89
90 private:
91     const LevelDBComparator* m_comparator;
92 };
93
94 LevelDBSnapshot::LevelDBSnapshot(LevelDBDatabase* db)
95     : m_db(db->m_db.get())
96     , m_snapshot(m_db->GetSnapshot())
97 {
98 }
99
100 LevelDBSnapshot::~LevelDBSnapshot()
101 {
102     m_db->ReleaseSnapshot(m_snapshot);
103 }
104
105 LevelDBDatabase::LevelDBDatabase()
106 {
107 }
108
109 LevelDBDatabase::~LevelDBDatabase()
110 {
111     // m_db's destructor uses m_comparatorAdapter; order of deletion is important.
112     m_db = nullptr;
113     m_comparatorAdapter = nullptr;
114     m_env = nullptr;
115 }
116
117 static leveldb::Status openDB(leveldb::Comparator* comparator, leveldb::Env* env, const String& path, leveldb::DB** db)
118 {
119     leveldb::Options options;
120     options.comparator = comparator;
121     options.create_if_missing = true;
122     options.paranoid_checks = true;
123     // 20 max_open_files is the minimum LevelDB allows.
124     options.max_open_files = 20;
125     options.env = env;
126
127     return leveldb::DB::Open(options, path.utf8().data(), db);
128 }
129
130 bool LevelDBDatabase::destroy(const String& fileName)
131 {
132     leveldb::Options options;
133     options.env = leveldb::IDBEnv();
134     const leveldb::Status s = leveldb::DestroyDB(fileName.utf8().data(), options);
135     return s.ok();
136 }
137
138 std::unique_ptr<LevelDBDatabase> LevelDBDatabase::open(const String& fileName, const LevelDBComparator* comparator)
139 {
140     auto comparatorAdapter = std::make_unique<ComparatorAdapter>(comparator);
141
142     leveldb::DB* db;
143     const leveldb::Status s = openDB(comparatorAdapter.get(), leveldb::IDBEnv(), fileName, &db);
144
145     if (!s.ok()) {
146         LOG_ERROR("Failed to open LevelDB database from %s: %s", fileName.ascii().data(), s.ToString().c_str());
147         return nullptr;
148     }
149
150     auto result = std::make_unique<LevelDBDatabase>();
151     result->m_db = std::unique_ptr<leveldb::DB>(db);
152     result->m_comparatorAdapter = std::move(comparatorAdapter);
153     result->m_comparator = comparator;
154
155     return result;
156 }
157
158 std::unique_ptr<LevelDBDatabase> LevelDBDatabase::openInMemory(const LevelDBComparator* comparator)
159 {
160     auto comparatorAdapter = std::make_unique<ComparatorAdapter>(comparator);
161     std::unique_ptr<leveldb::Env> inMemoryEnv(leveldb::NewMemEnv(leveldb::IDBEnv()));
162
163     leveldb::DB* db;
164     const leveldb::Status s = openDB(comparatorAdapter.get(), inMemoryEnv.get(), String(), &db);
165
166     if (!s.ok()) {
167         LOG_ERROR("Failed to open in-memory LevelDB database: %s", s.ToString().c_str());
168         return nullptr;
169     }
170
171     auto result = std::make_unique<LevelDBDatabase>();
172     result->m_env = std::move(inMemoryEnv);
173     result->m_db = std::unique_ptr<leveldb::DB>(db);
174     result->m_comparatorAdapter = std::move(comparatorAdapter);
175     result->m_comparator = comparator;
176
177     return result;
178 }
179
180 bool LevelDBDatabase::put(const LevelDBSlice& key, const Vector<char>& value)
181 {
182     leveldb::WriteOptions writeOptions;
183     writeOptions.sync = true;
184
185     const leveldb::Status s = m_db->Put(writeOptions, makeSlice(key), makeSlice(value));
186     if (s.ok())
187         return true;
188     LOG_ERROR("LevelDB put failed: %s", s.ToString().c_str());
189     return false;
190 }
191
192 bool LevelDBDatabase::remove(const LevelDBSlice& key)
193 {
194     leveldb::WriteOptions writeOptions;
195     writeOptions.sync = true;
196
197     const leveldb::Status s = m_db->Delete(writeOptions, makeSlice(key));
198     if (s.ok())
199         return true;
200     if (s.IsNotFound())
201         return false;
202     LOG_ERROR("LevelDB remove failed: %s", s.ToString().c_str());
203     return false;
204 }
205
206 bool LevelDBDatabase::safeGet(const LevelDBSlice& key, Vector<char>& value, bool& found, const LevelDBSnapshot* snapshot)
207 {
208     found = false;
209     std::string result;
210     leveldb::ReadOptions readOptions;
211     readOptions.verify_checksums = true; // FIXME: Disable this if the performance impact is too great.
212     readOptions.snapshot = snapshot ? snapshot->m_snapshot : 0;
213
214     const leveldb::Status s = m_db->Get(readOptions, makeSlice(key), &result);
215     if (s.ok()) {
216         found = true;
217         value.clear();
218         value.append(result.c_str(), result.length());
219         return true;
220     }
221     if (s.IsNotFound())
222         return true;
223     LOG_ERROR("LevelDB get failed: %s", s.ToString().c_str());
224     return false;
225 }
226
227 bool LevelDBDatabase::write(LevelDBWriteBatch& writeBatch)
228 {
229     leveldb::WriteOptions writeOptions;
230     writeOptions.sync = true;
231
232     const leveldb::Status s = m_db->Write(writeOptions, writeBatch.m_writeBatch.get());
233     if (s.ok())
234         return true;
235     LOG_ERROR("LevelDB write failed: %s", s.ToString().c_str());
236     return false;
237 }
238
239 namespace {
240 class IteratorImpl : public LevelDBIterator {
241 public:
242     explicit IteratorImpl(std::unique_ptr<leveldb::Iterator>);
243     ~IteratorImpl() { };
244
245     virtual bool isValid() const;
246     virtual void seekToLast();
247     virtual void seek(const LevelDBSlice& target);
248     virtual void next();
249     virtual void prev();
250     virtual LevelDBSlice key() const;
251     virtual LevelDBSlice value() const;
252
253 private:
254     void checkStatus();
255
256     std::unique_ptr<leveldb::Iterator> m_iterator;
257 };
258 }
259
260 IteratorImpl::IteratorImpl(std::unique_ptr<leveldb::Iterator> it)
261     : m_iterator(std::move(it))
262 {
263 }
264
265 void IteratorImpl::checkStatus()
266 {
267     const leveldb::Status s = m_iterator->status();
268     if (!s.ok())
269         LOG_ERROR("LevelDB iterator error: %s", s.ToString().c_str());
270 }
271
272 bool IteratorImpl::isValid() const
273 {
274     return m_iterator->Valid();
275 }
276
277 void IteratorImpl::seekToLast()
278 {
279     m_iterator->SeekToLast();
280     checkStatus();
281 }
282
283 void IteratorImpl::seek(const LevelDBSlice& target)
284 {
285     m_iterator->Seek(makeSlice(target));
286     checkStatus();
287 }
288
289 void IteratorImpl::next()
290 {
291     ASSERT(isValid());
292     m_iterator->Next();
293     checkStatus();
294 }
295
296 void IteratorImpl::prev()
297 {
298     ASSERT(isValid());
299     m_iterator->Prev();
300     checkStatus();
301 }
302
303 LevelDBSlice IteratorImpl::key() const
304 {
305     ASSERT(isValid());
306     return makeLevelDBSlice(m_iterator->key());
307 }
308
309 LevelDBSlice IteratorImpl::value() const
310 {
311     ASSERT(isValid());
312     return makeLevelDBSlice(m_iterator->value());
313 }
314
315 std::unique_ptr<LevelDBIterator> LevelDBDatabase::createIterator(const LevelDBSnapshot* snapshot)
316 {
317     leveldb::ReadOptions readOptions;
318     readOptions.verify_checksums = true; // FIXME: Disable this if the performance impact is too great.
319     readOptions.snapshot = snapshot ? snapshot->m_snapshot : 0;
320     std::unique_ptr<leveldb::Iterator> i(m_db->NewIterator(readOptions));
321     if (!i) // FIXME: Double check if we actually need to check this.
322         return nullptr;
323     return std::make_unique<IteratorImpl>(std::move(i));
324 }
325
326 const LevelDBComparator* LevelDBDatabase::comparator() const
327 {
328     return m_comparator;
329 }
330
331 }
332
333 #endif