aboutsummaryrefslogtreecommitdiff
path: root/src/leveldb/doc/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'src/leveldb/doc/index.html')
-rw-r--r--src/leveldb/doc/index.html549
1 files changed, 0 insertions, 549 deletions
diff --git a/src/leveldb/doc/index.html b/src/leveldb/doc/index.html
deleted file mode 100644
index 3ed0ed9d9..000000000
--- a/src/leveldb/doc/index.html
+++ /dev/null
@@ -1,549 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<link rel="stylesheet" type="text/css" href="doc.css" />
-<title>Leveldb</title>
-</head>
-
-<body>
-<h1>Leveldb</h1>
-<address>Jeff Dean, Sanjay Ghemawat</address>
-<p>
-The <code>leveldb</code> library provides a persistent key value store. Keys and
-values are arbitrary byte arrays. The keys are ordered within the key
-value store according to a user-specified comparator function.
-
-<p>
-<h1>Opening A Database</h1>
-<p>
-A <code>leveldb</code> database has a name which corresponds to a file system
-directory. All of the contents of database are stored in this
-directory. The following example shows how to open a database,
-creating it if necessary:
-<p>
-<pre>
- #include &lt;assert&gt;
- #include "leveldb/db.h"
-
- leveldb::DB* db;
- leveldb::Options options;
- options.create_if_missing = true;
- leveldb::Status status = leveldb::DB::Open(options, "/tmp/testdb", &amp;db);
- assert(status.ok());
- ...
-</pre>
-If you want to raise an error if the database already exists, add
-the following line before the <code>leveldb::DB::Open</code> call:
-<pre>
- options.error_if_exists = true;
-</pre>
-<h1>Status</h1>
-<p>
-You may have noticed the <code>leveldb::Status</code> type above. Values of this
-type are returned by most functions in <code>leveldb</code> that may encounter an
-error. You can check if such a result is ok, and also print an
-associated error message:
-<p>
-<pre>
- leveldb::Status s = ...;
- if (!s.ok()) cerr &lt;&lt; s.ToString() &lt;&lt; endl;
-</pre>
-<h1>Closing A Database</h1>
-<p>
-When you are done with a database, just delete the database object.
-Example:
-<p>
-<pre>
- ... open the db as described above ...
- ... do something with db ...
- delete db;
-</pre>
-<h1>Reads And Writes</h1>
-<p>
-The database provides <code>Put</code>, <code>Delete</code>, and <code>Get</code> methods to
-modify/query the database. For example, the following code
-moves the value stored under key1 to key2.
-<pre>
- std::string value;
- leveldb::Status s = db-&gt;Get(leveldb::ReadOptions(), key1, &amp;value);
- if (s.ok()) s = db-&gt;Put(leveldb::WriteOptions(), key2, value);
- if (s.ok()) s = db-&gt;Delete(leveldb::WriteOptions(), key1);
-</pre>
-
-<h1>Atomic Updates</h1>
-<p>
-Note that if the process dies after the Put of key2 but before the
-delete of key1, the same value may be left stored under multiple keys.
-Such problems can be avoided by using the <code>WriteBatch</code> class to
-atomically apply a set of updates:
-<p>
-<pre>
- #include "leveldb/write_batch.h"
- ...
- std::string value;
- leveldb::Status s = db-&gt;Get(leveldb::ReadOptions(), key1, &amp;value);
- if (s.ok()) {
- leveldb::WriteBatch batch;
- batch.Delete(key1);
- batch.Put(key2, value);
- s = db-&gt;Write(leveldb::WriteOptions(), &amp;batch);
- }
-</pre>
-The <code>WriteBatch</code> holds a sequence of edits to be made to the database,
-and these edits within the batch are applied in order. Note that we
-called <code>Delete</code> before <code>Put</code> so that if <code>key1</code> is identical to <code>key2</code>,
-we do not end up erroneously dropping the value entirely.
-<p>
-Apart from its atomicity benefits, <code>WriteBatch</code> may also be used to
-speed up bulk updates by placing lots of individual mutations into the
-same batch.
-
-<h1>Synchronous Writes</h1>
-By default, each write to <code>leveldb</code> is asynchronous: it
-returns after pushing the write from the process into the operating
-system. The transfer from operating system memory to the underlying
-persistent storage happens asynchronously. The <code>sync</code> flag
-can be turned on for a particular write to make the write operation
-not return until the data being written has been pushed all the way to
-persistent storage. (On Posix systems, this is implemented by calling
-either <code>fsync(...)</code> or <code>fdatasync(...)</code> or
-<code>msync(..., MS_SYNC)</code> before the write operation returns.)
-<pre>
- leveldb::WriteOptions write_options;
- write_options.sync = true;
- db-&gt;Put(write_options, ...);
-</pre>
-Asynchronous writes are often more than a thousand times as fast as
-synchronous writes. The downside of asynchronous writes is that a
-crash of the machine may cause the last few updates to be lost. Note
-that a crash of just the writing process (i.e., not a reboot) will not
-cause any loss since even when <code>sync</code> is false, an update
-is pushed from the process memory into the operating system before it
-is considered done.
-
-<p>
-Asynchronous writes can often be used safely. For example, when
-loading a large amount of data into the database you can handle lost
-updates by restarting the bulk load after a crash. A hybrid scheme is
-also possible where every Nth write is synchronous, and in the event
-of a crash, the bulk load is restarted just after the last synchronous
-write finished by the previous run. (The synchronous write can update
-a marker that describes where to restart on a crash.)
-
-<p>
-<code>WriteBatch</code> provides an alternative to asynchronous writes.
-Multiple updates may be placed in the same <code>WriteBatch</code> and
-applied together using a synchronous write (i.e.,
-<code>write_options.sync</code> is set to true). The extra cost of
-the synchronous write will be amortized across all of the writes in
-the batch.
-
-<p>
-<h1>Concurrency</h1>
-<p>
-A database may only be opened by one process at a time.
-The <code>leveldb</code> implementation acquires a lock from the
-operating system to prevent misuse. Within a single process, the
-same <code>leveldb::DB</code> object may be safely shared by multiple
-concurrent threads. I.e., different threads may write into or fetch
-iterators or call <code>Get</code> on the same database without any
-external synchronization (the leveldb implementation will
-automatically do the required synchronization). However other objects
-(like Iterator and WriteBatch) may require external synchronization.
-If two threads share such an object, they must protect access to it
-using their own locking protocol. More details are available in
-the public header files.
-<p>
-<h1>Iteration</h1>
-<p>
-The following example demonstrates how to print all key,value pairs
-in a database.
-<p>
-<pre>
- leveldb::Iterator* it = db-&gt;NewIterator(leveldb::ReadOptions());
- for (it-&gt;SeekToFirst(); it-&gt;Valid(); it-&gt;Next()) {
- cout &lt;&lt; it-&gt;key().ToString() &lt;&lt; ": " &lt;&lt; it-&gt;value().ToString() &lt;&lt; endl;
- }
- assert(it-&gt;status().ok()); // Check for any errors found during the scan
- delete it;
-</pre>
-The following variation shows how to process just the keys in the
-range <code>[start,limit)</code>:
-<p>
-<pre>
- for (it-&gt;Seek(start);
- it-&gt;Valid() &amp;&amp; it-&gt;key().ToString() &lt; limit;
- it-&gt;Next()) {
- ...
- }
-</pre>
-You can also process entries in reverse order. (Caveat: reverse
-iteration may be somewhat slower than forward iteration.)
-<p>
-<pre>
- for (it-&gt;SeekToLast(); it-&gt;Valid(); it-&gt;Prev()) {
- ...
- }
-</pre>
-<h1>Snapshots</h1>
-<p>
-Snapshots provide consistent read-only views over the entire state of
-the key-value store. <code>ReadOptions::snapshot</code> may be non-NULL to indicate
-that a read should operate on a particular version of the DB state.
-If <code>ReadOptions::snapshot</code> is NULL, the read will operate on an
-implicit snapshot of the current state.
-<p>
-Snapshots are created by the DB::GetSnapshot() method:
-<p>
-<pre>
- leveldb::ReadOptions options;
- options.snapshot = db-&gt;GetSnapshot();
- ... apply some updates to db ...
- leveldb::Iterator* iter = db-&gt;NewIterator(options);
- ... read using iter to view the state when the snapshot was created ...
- delete iter;
- db-&gt;ReleaseSnapshot(options.snapshot);
-</pre>
-Note that when a snapshot is no longer needed, it should be released
-using the DB::ReleaseSnapshot interface. This allows the
-implementation to get rid of state that was being maintained just to
-support reading as of that snapshot.
-<h1>Slice</h1>
-<p>
-The return value of the <code>it->key()</code> and <code>it->value()</code> calls above
-are instances of the <code>leveldb::Slice</code> type. <code>Slice</code> is a simple
-structure that contains a length and a pointer to an external byte
-array. Returning a <code>Slice</code> is a cheaper alternative to returning a
-<code>std::string</code> since we do not need to copy potentially large keys and
-values. In addition, <code>leveldb</code> methods do not return null-terminated
-C-style strings since <code>leveldb</code> keys and values are allowed to
-contain '\0' bytes.
-<p>
-C++ strings and null-terminated C-style strings can be easily converted
-to a Slice:
-<p>
-<pre>
- leveldb::Slice s1 = "hello";
-
- std::string str("world");
- leveldb::Slice s2 = str;
-</pre>
-A Slice can be easily converted back to a C++ string:
-<pre>
- std::string str = s1.ToString();
- assert(str == std::string("hello"));
-</pre>
-Be careful when using Slices since it is up to the caller to ensure that
-the external byte array into which the Slice points remains live while
-the Slice is in use. For example, the following is buggy:
-<p>
-<pre>
- leveldb::Slice slice;
- if (...) {
- std::string str = ...;
- slice = str;
- }
- Use(slice);
-</pre>
-When the <code>if</code> statement goes out of scope, <code>str</code> will be destroyed and the
-backing storage for <code>slice</code> will disappear.
-<p>
-<h1>Comparators</h1>
-<p>
-The preceding examples used the default ordering function for key,
-which orders bytes lexicographically. You can however supply a custom
-comparator when opening a database. For example, suppose each
-database key consists of two numbers and we should sort by the first
-number, breaking ties by the second number. First, define a proper
-subclass of <code>leveldb::Comparator</code> that expresses these rules:
-<p>
-<pre>
- class TwoPartComparator : public leveldb::Comparator {
- public:
- // Three-way comparison function:
- // if a &lt; b: negative result
- // if a &gt; b: positive result
- // else: zero result
- int Compare(const leveldb::Slice&amp; a, const leveldb::Slice&amp; b) const {
- int a1, a2, b1, b2;
- ParseKey(a, &amp;a1, &amp;a2);
- ParseKey(b, &amp;b1, &amp;b2);
- if (a1 &lt; b1) return -1;
- if (a1 &gt; b1) return +1;
- if (a2 &lt; b2) return -1;
- if (a2 &gt; b2) return +1;
- return 0;
- }
-
- // Ignore the following methods for now:
- const char* Name() const { return "TwoPartComparator"; }
- void FindShortestSeparator(std::string*, const leveldb::Slice&amp;) const { }
- void FindShortSuccessor(std::string*) const { }
- };
-</pre>
-Now create a database using this custom comparator:
-<p>
-<pre>
- TwoPartComparator cmp;
- leveldb::DB* db;
- leveldb::Options options;
- options.create_if_missing = true;
- options.comparator = &amp;cmp;
- leveldb::Status status = leveldb::DB::Open(options, "/tmp/testdb", &amp;db);
- ...
-</pre>
-<h2>Backwards compatibility</h2>
-<p>
-The result of the comparator's <code>Name</code> method is attached to the
-database when it is created, and is checked on every subsequent
-database open. If the name changes, the <code>leveldb::DB::Open</code> call will
-fail. Therefore, change the name if and only if the new key format
-and comparison function are incompatible with existing databases, and
-it is ok to discard the contents of all existing databases.
-<p>
-You can however still gradually evolve your key format over time with
-a little bit of pre-planning. For example, you could store a version
-number at the end of each key (one byte should suffice for most uses).
-When you wish to switch to a new key format (e.g., adding an optional
-third part to the keys processed by <code>TwoPartComparator</code>),
-(a) keep the same comparator name (b) increment the version number
-for new keys (c) change the comparator function so it uses the
-version numbers found in the keys to decide how to interpret them.
-<p>
-<h1>Performance</h1>
-<p>
-Performance can be tuned by changing the default values of the
-types defined in <code>include/leveldb/options.h</code>.
-
-<p>
-<h2>Block size</h2>
-<p>
-<code>leveldb</code> groups adjacent keys together into the same block and such a
-block is the unit of transfer to and from persistent storage. The
-default block size is approximately 4096 uncompressed bytes.
-Applications that mostly do bulk scans over the contents of the
-database may wish to increase this size. Applications that do a lot
-of point reads of small values may wish to switch to a smaller block
-size if performance measurements indicate an improvement. There isn't
-much benefit in using blocks smaller than one kilobyte, or larger than
-a few megabytes. Also note that compression will be more effective
-with larger block sizes.
-<p>
-<h2>Compression</h2>
-<p>
-Each block is individually compressed before being written to
-persistent storage. Compression is on by default since the default
-compression method is very fast, and is automatically disabled for
-uncompressible data. In rare cases, applications may want to disable
-compression entirely, but should only do so if benchmarks show a
-performance improvement:
-<p>
-<pre>
- leveldb::Options options;
- options.compression = leveldb::kNoCompression;
- ... leveldb::DB::Open(options, name, ...) ....
-</pre>
-<h2>Cache</h2>
-<p>
-The contents of the database are stored in a set of files in the
-filesystem and each file stores a sequence of compressed blocks. If
-<code>options.cache</code> is non-NULL, it is used to cache frequently used
-uncompressed block contents.
-<p>
-<pre>
- #include "leveldb/cache.h"
-
- leveldb::Options options;
- options.cache = leveldb::NewLRUCache(100 * 1048576); // 100MB cache
- leveldb::DB* db;
- leveldb::DB::Open(options, name, &db);
- ... use the db ...
- delete db
- delete options.cache;
-</pre>
-Note that the cache holds uncompressed data, and therefore it should
-be sized according to application level data sizes, without any
-reduction from compression. (Caching of compressed blocks is left to
-the operating system buffer cache, or any custom <code>Env</code>
-implementation provided by the client.)
-<p>
-When performing a bulk read, the application may wish to disable
-caching so that the data processed by the bulk read does not end up
-displacing most of the cached contents. A per-iterator option can be
-used to achieve this:
-<p>
-<pre>
- leveldb::ReadOptions options;
- options.fill_cache = false;
- leveldb::Iterator* it = db-&gt;NewIterator(options);
- for (it-&gt;SeekToFirst(); it-&gt;Valid(); it-&gt;Next()) {
- ...
- }
-</pre>
-<h2>Key Layout</h2>
-<p>
-Note that the unit of disk transfer and caching is a block. Adjacent
-keys (according to the database sort order) will usually be placed in
-the same block. Therefore the application can improve its performance
-by placing keys that are accessed together near each other and placing
-infrequently used keys in a separate region of the key space.
-<p>
-For example, suppose we are implementing a simple file system on top
-of <code>leveldb</code>. The types of entries we might wish to store are:
-<p>
-<pre>
- filename -&gt; permission-bits, length, list of file_block_ids
- file_block_id -&gt; data
-</pre>
-We might want to prefix <code>filename</code> keys with one letter (say '/') and the
-<code>file_block_id</code> keys with a different letter (say '0') so that scans
-over just the metadata do not force us to fetch and cache bulky file
-contents.
-<p>
-<h2>Filters</h2>
-<p>
-Because of the way <code>leveldb</code> data is organized on disk,
-a single <code>Get()</code> call may involve multiple reads from disk.
-The optional <code>FilterPolicy</code> mechanism can be used to reduce
-the number of disk reads substantially.
-<pre>
- leveldb::Options options;
- options.filter_policy = NewBloomFilterPolicy(10);
- leveldb::DB* db;
- leveldb::DB::Open(options, "/tmp/testdb", &amp;db);
- ... use the database ...
- delete db;
- delete options.filter_policy;
-</pre>
-The preceding code associates a
-<a href="http://en.wikipedia.org/wiki/Bloom_filter">Bloom filter</a>
-based filtering policy with the database. Bloom filter based
-filtering relies on keeping some number of bits of data in memory per
-key (in this case 10 bits per key since that is the argument we passed
-to NewBloomFilterPolicy). This filter will reduce the number of unnecessary
-disk reads needed for <code>Get()</code> calls by a factor of
-approximately a 100. Increasing the bits per key will lead to a
-larger reduction at the cost of more memory usage. We recommend that
-applications whose working set does not fit in memory and that do a
-lot of random reads set a filter policy.
-<p>
-If you are using a custom comparator, you should ensure that the filter
-policy you are using is compatible with your comparator. For example,
-consider a comparator that ignores trailing spaces when comparing keys.
-<code>NewBloomFilterPolicy</code> must not be used with such a comparator.
-Instead, the application should provide a custom filter policy that
-also ignores trailing spaces. For example:
-<pre>
- class CustomFilterPolicy : public leveldb::FilterPolicy {
- private:
- FilterPolicy* builtin_policy_;
- public:
- CustomFilterPolicy() : builtin_policy_(NewBloomFilterPolicy(10)) { }
- ~CustomFilterPolicy() { delete builtin_policy_; }
-
- const char* Name() const { return "IgnoreTrailingSpacesFilter"; }
-
- void CreateFilter(const Slice* keys, int n, std::string* dst) const {
- // Use builtin bloom filter code after removing trailing spaces
- std::vector&lt;Slice&gt; trimmed(n);
- for (int i = 0; i &lt; n; i++) {
- trimmed[i] = RemoveTrailingSpaces(keys[i]);
- }
- return builtin_policy_-&gt;CreateFilter(&amp;trimmed[i], n, dst);
- }
-
- bool KeyMayMatch(const Slice& key, const Slice& filter) const {
- // Use builtin bloom filter code after removing trailing spaces
- return builtin_policy_-&gt;KeyMayMatch(RemoveTrailingSpaces(key), filter);
- }
- };
-</pre>
-<p>
-Advanced applications may provide a filter policy that does not use
-a bloom filter but uses some other mechanism for summarizing a set
-of keys. See <code>leveldb/filter_policy.h</code> for detail.
-<p>
-<h1>Checksums</h1>
-<p>
-<code>leveldb</code> associates checksums with all data it stores in the file system.
-There are two separate controls provided over how aggressively these
-checksums are verified:
-<p>
-<ul>
-<li> <code>ReadOptions::verify_checksums</code> may be set to true to force
- checksum verification of all data that is read from the file system on
- behalf of a particular read. By default, no such verification is
- done.
-<p>
-<li> <code>Options::paranoid_checks</code> may be set to true before opening a
- database to make the database implementation raise an error as soon as
- it detects an internal corruption. Depending on which portion of the
- database has been corrupted, the error may be raised when the database
- is opened, or later by another database operation. By default,
- paranoid checking is off so that the database can be used even if
- parts of its persistent storage have been corrupted.
-<p>
- If a database is corrupted (perhaps it cannot be opened when
- paranoid checking is turned on), the <code>leveldb::RepairDB</code> function
- may be used to recover as much of the data as possible
-<p>
-</ul>
-<h1>Approximate Sizes</h1>
-<p>
-The <code>GetApproximateSizes</code> method can used to get the approximate
-number of bytes of file system space used by one or more key ranges.
-<p>
-<pre>
- leveldb::Range ranges[2];
- ranges[0] = leveldb::Range("a", "c");
- ranges[1] = leveldb::Range("x", "z");
- uint64_t sizes[2];
- leveldb::Status s = db-&gt;GetApproximateSizes(ranges, 2, sizes);
-</pre>
-The preceding call will set <code>sizes[0]</code> to the approximate number of
-bytes of file system space used by the key range <code>[a..c)</code> and
-<code>sizes[1]</code> to the approximate number of bytes used by the key range
-<code>[x..z)</code>.
-<p>
-<h1>Environment</h1>
-<p>
-All file operations (and other operating system calls) issued by the
-<code>leveldb</code> implementation are routed through a <code>leveldb::Env</code> object.
-Sophisticated clients may wish to provide their own <code>Env</code>
-implementation to get better control. For example, an application may
-introduce artificial delays in the file IO paths to limit the impact
-of <code>leveldb</code> on other activities in the system.
-<p>
-<pre>
- class SlowEnv : public leveldb::Env {
- .. implementation of the Env interface ...
- };
-
- SlowEnv env;
- leveldb::Options options;
- options.env = &amp;env;
- Status s = leveldb::DB::Open(options, ...);
-</pre>
-<h1>Porting</h1>
-<p>
-<code>leveldb</code> may be ported to a new platform by providing platform
-specific implementations of the types/methods/functions exported by
-<code>leveldb/port/port.h</code>. See <code>leveldb/port/port_example.h</code> for more
-details.
-<p>
-In addition, the new platform may need a new default <code>leveldb::Env</code>
-implementation. See <code>leveldb/util/env_posix.h</code> for an example.
-
-<h1>Other Information</h1>
-
-<p>
-Details about the <code>leveldb</code> implementation may be found in
-the following documents:
-<ul>
-<li> <a href="impl.html">Implementation notes</a>
-<li> <a href="table_format.txt">Format of an immutable Table file</a>
-<li> <a href="log_format.txt">Format of a log file</a>
-</ul>
-
-</body>
-</html>