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 ENABLE(LEVELDB)
30
31 #include "LevelDBComparator.h"
32 #include "LevelDBIterator.h"
33 #include "LevelDBSlice.h"
34 #include <leveldb/comparator.h>
35 #include <leveldb/db.h>
36 #include <leveldb/slice.h>
37 #include <string>
38 #include <wtf/PassOwnPtr.h>
39 #include <wtf/text/CString.h>
40 #include <wtf/text/WTFString.h>
41
42 namespace WebCore {
43
makeSlice(const Vector<char> & value)44 static leveldb::Slice makeSlice(const Vector<char>& value)
45 {
46 return leveldb::Slice(value.data(), value.size());
47 }
48
makeSlice(const LevelDBSlice & s)49 static leveldb::Slice makeSlice(const LevelDBSlice& s)
50 {
51 return leveldb::Slice(s.begin(), s.end() - s.begin());
52 }
53
makeLevelDBSlice(const leveldb::Slice & s)54 static LevelDBSlice makeLevelDBSlice(const leveldb::Slice& s)
55 {
56 return LevelDBSlice(s.data(), s.data() + s.size());
57 }
58
makeVector(const std::string & s)59 static Vector<char> makeVector(const std::string& s)
60 {
61 Vector<char> res;
62 res.append(s.c_str(), s.length());
63 return res;
64 }
65
66 namespace {
67 class ComparatorAdapter : public leveldb::Comparator {
68 public:
ComparatorAdapter(const LevelDBComparator * comparator)69 ComparatorAdapter(const LevelDBComparator* comparator)
70 : m_comparator(comparator)
71 {
72 }
73
Compare(const leveldb::Slice & a,const leveldb::Slice & b) const74 virtual int Compare(const leveldb::Slice& a, const leveldb::Slice& b) const
75 {
76 return m_comparator->compare(makeLevelDBSlice(a), makeLevelDBSlice(b));
77 }
78
Name() const79 virtual const char* Name() const { return m_comparator->name(); }
80
81 // FIXME: Support the methods below in the future.
FindShortestSeparator(std::string * start,const leveldb::Slice & limit) const82 virtual void FindShortestSeparator(std::string* start, const leveldb::Slice& limit) const { }
FindShortSuccessor(std::string * key) const83 virtual void FindShortSuccessor(std::string* key) const { }
84
85 private:
86 const LevelDBComparator* m_comparator;
87 };
88 }
89
LevelDBDatabase()90 LevelDBDatabase::LevelDBDatabase()
91 : m_db(0)
92 {
93 }
94
~LevelDBDatabase()95 LevelDBDatabase::~LevelDBDatabase()
96 {
97 }
98
open(const String & fileName,const LevelDBComparator * comparator)99 LevelDBDatabase* LevelDBDatabase::open(const String& fileName, const LevelDBComparator* comparator)
100 {
101 OwnPtr<ComparatorAdapter> comparatorAdapter(new ComparatorAdapter(comparator));
102
103 LevelDBDatabase* result = new LevelDBDatabase();
104
105 leveldb::Options options;
106 options.comparator = comparatorAdapter.get();
107 options.create_if_missing = true;
108 leveldb::DB* db;
109 leveldb::Status s = leveldb::DB::Open(options, fileName.utf8().data(), &db);
110
111 if (!s.ok()) {
112 delete result;
113 return 0;
114 }
115
116 result->m_db = WTF::adoptPtr(db);
117 result->m_comparatorAdapter = comparatorAdapter.release();
118
119 return result;
120 }
121
122
put(const LevelDBSlice & key,const Vector<char> & value)123 bool LevelDBDatabase::put(const LevelDBSlice& key, const Vector<char>& value)
124 {
125 leveldb::WriteOptions writeOptions;
126 writeOptions.sync = false;
127
128 return m_db->Put(writeOptions, makeSlice(key), makeSlice(value)).ok();
129 }
130
remove(const LevelDBSlice & key)131 bool LevelDBDatabase::remove(const LevelDBSlice& key)
132 {
133 leveldb::WriteOptions writeOptions;
134 writeOptions.sync = false;
135
136 return m_db->Delete(writeOptions, makeSlice(key)).ok();
137 }
138
get(const LevelDBSlice & key,Vector<char> & value)139 bool LevelDBDatabase::get(const LevelDBSlice& key, Vector<char>& value)
140 {
141 std::string result;
142 if (!m_db->Get(leveldb::ReadOptions(), makeSlice(key), &result).ok())
143 return false;
144
145 value = makeVector(result);
146 return true;
147 }
148
newIterator()149 LevelDBIterator* LevelDBDatabase::newIterator()
150 {
151 leveldb::Iterator* i = m_db->NewIterator(leveldb::ReadOptions());
152 if (!i) // FIXME: Double check if we actually need to check this.
153 return 0;
154 return new LevelDBIterator(i);
155 }
156
157 } // namespace WebCore
158
159 #endif // ENABLE(LEVELDB)
160