Initial commit of the driver
This commit is contained in:
parent
e85239c6b9
commit
77c384b6b0
32 changed files with 4161 additions and 0 deletions
358
docs/api/database.rst
Normal file
358
docs/api/database.rst
Normal file
|
@ -0,0 +1,358 @@
|
||||||
|
Database interactions
|
||||||
|
*********************
|
||||||
|
|
||||||
|
Database object
|
||||||
|
===============
|
||||||
|
|
||||||
|
.. py:class:: rocksdb.DB
|
||||||
|
|
||||||
|
.. py:method:: __init__(db_name, Options opts, read_only=False)
|
||||||
|
|
||||||
|
:param string db_name: Name of the database to open
|
||||||
|
:param opts: Options for this specific database
|
||||||
|
:type opts: :py:class:`rocksdb.Options`
|
||||||
|
:param bool read_only: If ``True`` the database is opened read-only.
|
||||||
|
All DB calls which modify data will raise an
|
||||||
|
Exception.
|
||||||
|
|
||||||
|
|
||||||
|
.. py:method:: put(key, value, sync=False, disable_wal=False)
|
||||||
|
|
||||||
|
Set the database entry for "key" to "value".
|
||||||
|
|
||||||
|
:param string key: Name for this entry
|
||||||
|
:param string value: Data for this entry
|
||||||
|
:param bool sync:
|
||||||
|
If ``True``, the write will be flushed from the operating system
|
||||||
|
buffer cache (by calling WritableFile::Sync()) before the write
|
||||||
|
is considered complete. If this flag is true, writes will be
|
||||||
|
slower.
|
||||||
|
|
||||||
|
If this flag is ``False``, and the machine crashes, some recent
|
||||||
|
writes may be lost. Note that if it is just the process that
|
||||||
|
crashes (i.e., the machine does not reboot), no writes will be
|
||||||
|
lost even if ``sync == False``.
|
||||||
|
|
||||||
|
In other words, a DB write with ``sync == False`` has similar
|
||||||
|
crash semantics as the "write()" system call. A DB write
|
||||||
|
with ``sync == True`` has similar crash semantics to a "write()"
|
||||||
|
system call followed by "fdatasync()".
|
||||||
|
|
||||||
|
:param bool disable_wal:
|
||||||
|
If ``True``, writes will not first go to the write ahead log,
|
||||||
|
and the write may got lost after a crash.
|
||||||
|
|
||||||
|
.. py:method:: delete(key, sync=False, disable_wal=False)
|
||||||
|
|
||||||
|
Remove the database entry for "key".
|
||||||
|
|
||||||
|
:param string key: Name to delete
|
||||||
|
:param sync: See :py:meth:`rocksdb.DB.put`
|
||||||
|
:param disable_wal: See :py:meth:`rocksdb.DB.put`
|
||||||
|
:raises rocksdb.errors.NotFound: If the key did not exists
|
||||||
|
|
||||||
|
.. py:method:: merge(key, value, sync=False, disable_wal=False)
|
||||||
|
|
||||||
|
Merge the database entry for "key" with "value".
|
||||||
|
The semantics of this operation is determined by the user provided
|
||||||
|
merge_operator when opening DB.
|
||||||
|
|
||||||
|
See :py:meth:`rocksdb.DB.put` for the parameters
|
||||||
|
|
||||||
|
:raises:
|
||||||
|
:py:exc:`rocksdb.errors.NotSupported` if this is called and
|
||||||
|
no :py:attr:`rocksdb.Options.merge_operator` was set at creation
|
||||||
|
|
||||||
|
|
||||||
|
.. py:method:: write(batch, sync=False, disable_wal=False)
|
||||||
|
|
||||||
|
Apply the specified updates to the database.
|
||||||
|
|
||||||
|
:param rocksdb.WriteBatch batch: Batch to apply
|
||||||
|
:param sync: See :py:meth:`rocksdb.DB.put`
|
||||||
|
:param disable_wal: See :py:meth:`rocksdb.DB.put`
|
||||||
|
|
||||||
|
.. py:method:: get(key, verify_checksums=False, fill_cache=True, prefix_seek=False, snapshot=None, read_tier="all")
|
||||||
|
|
||||||
|
:param string key: Name to get
|
||||||
|
|
||||||
|
:param bool verify_checksums:
|
||||||
|
If ``True``, all data read from underlying storage will be
|
||||||
|
verified against corresponding checksums.
|
||||||
|
|
||||||
|
:param bool fill_cache:
|
||||||
|
Should the "data block", "index block" or "filter block"
|
||||||
|
read for this iteration be cached in memory?
|
||||||
|
Callers may wish to set this field to ``False`` for bulk scans.
|
||||||
|
|
||||||
|
:param bool prefix_seek:
|
||||||
|
If this option is set and memtable implementation allows.
|
||||||
|
Seek might only return keys with the same prefix as the seek-key
|
||||||
|
|
||||||
|
:param snapshot:
|
||||||
|
If not ``None``, read as of the supplied snapshot
|
||||||
|
(which must belong to the DB that is being read and which must
|
||||||
|
not have been released). Is it ``None`` a implicit snapshot of the
|
||||||
|
state at the beginning of this read operation is used
|
||||||
|
:type snapshot: :py:class:`rocksdb.Snapshot`
|
||||||
|
|
||||||
|
:param string read_tier:
|
||||||
|
Specify if this read request should process data that ALREADY
|
||||||
|
resides on a particular cache. If the required data is not
|
||||||
|
found at the specified cache,
|
||||||
|
then :py:exc:`rocksdb.errors.Incomplete` is raised.
|
||||||
|
|
||||||
|
| Use ``all`` if a fetch from disk is allowed.
|
||||||
|
| Use ``cache`` if only data from cache is allowed.
|
||||||
|
|
||||||
|
:returns: ``None`` if not found, else the value for this key
|
||||||
|
|
||||||
|
.. py:method:: multi_get(keys, verify_checksums=False, fill_cache=True, prefix_seek=False, snapshot=None, read_tier="all")
|
||||||
|
|
||||||
|
:param keys: Keys to fetch
|
||||||
|
:type keys: list of strings
|
||||||
|
|
||||||
|
For the other params see :py:meth:`rocksdb.DB.get`
|
||||||
|
|
||||||
|
:returns:
|
||||||
|
A ``dict`` where the value is either ``string`` or ``None`` if not found
|
||||||
|
|
||||||
|
:raises: If the fetch for a single key fails
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
keys will not be "de-duplicated".
|
||||||
|
Duplicate keys will return duplicate values in order.
|
||||||
|
|
||||||
|
.. py:method:: key_may_exist(key, fetch=False, verify_checksums=False, fill_cache=True, prefix_seek=False, snapshot=None, read_tier="all")
|
||||||
|
|
||||||
|
If the key definitely does not exist in the database, then this method
|
||||||
|
returns ``False``, else ``True``. If the caller wants to obtain value
|
||||||
|
when the key is found in memory, fetch should be set to ``True``.
|
||||||
|
This check is potentially lighter-weight than invoking DB::get().
|
||||||
|
One way to make this lighter weight is to avoid doing any IOs.
|
||||||
|
|
||||||
|
:param string key: Key to check
|
||||||
|
:param bool fetch: Obtain also the value if found
|
||||||
|
|
||||||
|
For the other params see :py:meth:`rocksdb.DB.get`
|
||||||
|
|
||||||
|
:returns:
|
||||||
|
* ``(True, None)`` if key is found but value not in memory
|
||||||
|
* ``(True, None)`` if key is found and ``fetch=False``
|
||||||
|
* ``(True, <data>)`` if key is found and value in memory and ``fetch=True``
|
||||||
|
* ``(False, None)`` if key is not found
|
||||||
|
|
||||||
|
.. py:method:: iterkeys(prefix=None, fetch=False, verify_checksums=False, fill_cache=True, prefix_seek=False, snapshot=None, read_tier="all")
|
||||||
|
|
||||||
|
Iterate over the keys
|
||||||
|
|
||||||
|
:param string prefix: Not implemented yet
|
||||||
|
|
||||||
|
For other params see :py:meth:`rocksdb.DB.get`
|
||||||
|
|
||||||
|
:returns:
|
||||||
|
A iterator object which is not valid yet.
|
||||||
|
Call first one of the seek methods of the iterator to position it
|
||||||
|
|
||||||
|
:rtype: :py:class:`rocksdb.BaseIterator`
|
||||||
|
|
||||||
|
.. py:method:: itervalues(prefix=None, fetch=False, verify_checksums=False, fill_cache=True, prefix_seek=False, snapshot=None, read_tier="all")
|
||||||
|
|
||||||
|
Iterate over the values
|
||||||
|
|
||||||
|
:param string prefix: Not implemented yet
|
||||||
|
|
||||||
|
For other params see :py:meth:`rocksdb.DB.get`
|
||||||
|
|
||||||
|
:returns:
|
||||||
|
A iterator object which is not valid yet.
|
||||||
|
Call first one of the seek methods of the iterator to position it
|
||||||
|
|
||||||
|
:rtype: :py:class:`rocksdb.BaseIterator`
|
||||||
|
|
||||||
|
.. py:method:: iteritems(prefix=None, fetch=False, verify_checksums=False, fill_cache=True, prefix_seek=False, snapshot=None, read_tier="all")
|
||||||
|
|
||||||
|
Iterate over the items
|
||||||
|
|
||||||
|
:param string prefix: Not implemented yet
|
||||||
|
|
||||||
|
For other params see :py:meth:`rocksdb.DB.get`
|
||||||
|
|
||||||
|
:returns:
|
||||||
|
A iterator object which is not valid yet.
|
||||||
|
Call first one of the seek methods of the iterator to position it
|
||||||
|
|
||||||
|
:rtype: :py:class:`rocksdb.BaseIterator`
|
||||||
|
|
||||||
|
.. py:method:: snapshot()
|
||||||
|
|
||||||
|
Return a handle to the current DB state.
|
||||||
|
Iterators created with this handle will all observe a stable snapshot
|
||||||
|
of the current DB state.
|
||||||
|
|
||||||
|
:rtype: :py:class:`rocksdb.Snapshot`
|
||||||
|
|
||||||
|
|
||||||
|
.. py:method:: get_property(prop)
|
||||||
|
|
||||||
|
DB implementations can export properties about their state
|
||||||
|
via this method. If "property" is a valid property understood by this
|
||||||
|
DB implementation, a string with its value is returned.
|
||||||
|
Otherwise ``None``
|
||||||
|
|
||||||
|
Valid property names include:
|
||||||
|
|
||||||
|
* ``"rocksdb.num-files-at-level<N>"``: return the number of files at level <N>,
|
||||||
|
where <N> is an ASCII representation of a level number (e.g. "0").
|
||||||
|
|
||||||
|
* ``"rocksdb.stats"``: returns a multi-line string that describes statistics
|
||||||
|
about the internal operation of the DB.
|
||||||
|
|
||||||
|
* ``"rocksdb.sstables"``: returns a multi-line string that describes all
|
||||||
|
of the sstables that make up the db contents.
|
||||||
|
|
||||||
|
.. py:method:: get_live_files_metadata()
|
||||||
|
|
||||||
|
Returns a list of all table files.
|
||||||
|
|
||||||
|
It returns a list of dict's were each dict has the following keys.
|
||||||
|
|
||||||
|
``name``
|
||||||
|
Name of the file
|
||||||
|
|
||||||
|
``level``
|
||||||
|
Level at which this file resides
|
||||||
|
|
||||||
|
``size``
|
||||||
|
File size in bytes
|
||||||
|
|
||||||
|
``smallestkey``
|
||||||
|
Smallest user defined key in the file
|
||||||
|
|
||||||
|
``largestkey``
|
||||||
|
Largest user defined key in the file
|
||||||
|
|
||||||
|
``smallest_seqno``
|
||||||
|
smallest seqno in file
|
||||||
|
|
||||||
|
``largest_seqno``
|
||||||
|
largest seqno in file
|
||||||
|
|
||||||
|
.. py:attribute:: options
|
||||||
|
|
||||||
|
Returns the associated :py:class:`rocksdb.Options` instance.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Changes to this object have no effect anymore.
|
||||||
|
Consider this as read-only
|
||||||
|
|
||||||
|
Iterator
|
||||||
|
========
|
||||||
|
|
||||||
|
.. py:class:: rocksdb.BaseIterator
|
||||||
|
|
||||||
|
Base class for all iterators in this module. After creation a iterator is
|
||||||
|
invalid. Call one of the seek methods first before starting iteration
|
||||||
|
|
||||||
|
.. py:method:: seek_to_first()
|
||||||
|
|
||||||
|
Position at the first key in the source
|
||||||
|
|
||||||
|
.. py:method:: seek_to_last()
|
||||||
|
|
||||||
|
Position at the last key in the source
|
||||||
|
|
||||||
|
.. py:method:: seek(key)
|
||||||
|
|
||||||
|
:param string key: Position at the first key in the source that at or past
|
||||||
|
|
||||||
|
Methods to support the python iterator protocol
|
||||||
|
|
||||||
|
.. py:method:: __iter__()
|
||||||
|
.. py:method:: __next__()
|
||||||
|
.. py:method:: __reversed__()
|
||||||
|
|
||||||
|
Snapshot
|
||||||
|
========
|
||||||
|
|
||||||
|
.. py:class:: rocksdb.Snapshot
|
||||||
|
|
||||||
|
Opaque handler for a single Snapshot.
|
||||||
|
Snapshot is released if nobody holds a reference on it.
|
||||||
|
Retrieved via :py:meth:`rocksdb.DB.snapshot`
|
||||||
|
|
||||||
|
WriteBatch
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. py:class:: rocksdb.WriteBatch
|
||||||
|
|
||||||
|
WriteBatch holds a collection of updates to apply atomically to a DB.
|
||||||
|
|
||||||
|
The updates are applied in the order in which they are added
|
||||||
|
to the WriteBatch. For example, the value of "key" will be "v3"
|
||||||
|
after the following batch is written::
|
||||||
|
|
||||||
|
batch = rocksdb.WriteBatch()
|
||||||
|
batch.put("key", "v1")
|
||||||
|
batch.delete("key")
|
||||||
|
batch.put("key", "v2")
|
||||||
|
batch.put("key", "v3")
|
||||||
|
|
||||||
|
.. py:method:: __init__(data=None)
|
||||||
|
|
||||||
|
Creates a WriteBatch.
|
||||||
|
|
||||||
|
:param string data:
|
||||||
|
A serialized version of a previous WriteBatch. As retrieved
|
||||||
|
from a previous .data() call. If ``None`` a empty WriteBatch is
|
||||||
|
generated
|
||||||
|
|
||||||
|
.. py:method:: put(key, value)
|
||||||
|
|
||||||
|
Store the mapping "key->value" in the database.
|
||||||
|
|
||||||
|
:param string key: Name of the entry to store
|
||||||
|
:param string value: Data of this entry
|
||||||
|
|
||||||
|
.. py:method:: merge(key, value)
|
||||||
|
|
||||||
|
Merge "value" with the existing value of "key" in the database.
|
||||||
|
|
||||||
|
:param string key: Name of the entry to merge
|
||||||
|
:param string value: Data to merge
|
||||||
|
|
||||||
|
.. py:method:: delete(key)
|
||||||
|
|
||||||
|
If the database contains a mapping for "key", erase it. Else do nothing.
|
||||||
|
|
||||||
|
:param string key: Key to erase
|
||||||
|
|
||||||
|
.. py:method:: clear()
|
||||||
|
|
||||||
|
Clear all updates buffered in this batch.
|
||||||
|
|
||||||
|
.. py:method:: data()
|
||||||
|
|
||||||
|
Retrieve the serialized version of this batch.
|
||||||
|
|
||||||
|
:rtype: string
|
||||||
|
|
||||||
|
.. py:method:: count()
|
||||||
|
|
||||||
|
Returns the number of updates in the batch
|
||||||
|
|
||||||
|
:rtype: int
|
||||||
|
|
||||||
|
Errors
|
||||||
|
======
|
||||||
|
|
||||||
|
.. py:exception:: rocksdb.errors.NotFound
|
||||||
|
.. py:exception:: rocksdb.errors.Corruption
|
||||||
|
.. py:exception:: rocksdb.errors.NotSupported
|
||||||
|
.. py:exception:: rocksdb.errors.InvalidArgument
|
||||||
|
.. py:exception:: rocksdb.errors.RocksIOError
|
||||||
|
.. py:exception:: rocksdb.errors.MergeInProgress
|
||||||
|
.. py:exception:: rocksdb.errors.Incomplete
|
||||||
|
|
||||||
|
|
10
docs/api/index.rst
Normal file
10
docs/api/index.rst
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
Python driver for RocksDB
|
||||||
|
=========================
|
||||||
|
|
||||||
|
.. py:module:: rocksdb
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
|
||||||
|
Options <options>
|
||||||
|
Database <database>
|
||||||
|
Interfaces <interfaces>
|
210
docs/api/interfaces.rst
Normal file
210
docs/api/interfaces.rst
Normal file
|
@ -0,0 +1,210 @@
|
||||||
|
Interfaces
|
||||||
|
**********
|
||||||
|
|
||||||
|
Comparator
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. py:class:: rocksdb.interfaces.Comparator
|
||||||
|
|
||||||
|
A Comparator object provides a total order across slices that are
|
||||||
|
used as keys in an sstable or a database. A Comparator implementation
|
||||||
|
must be thread-safe since rocksdb may invoke its methods concurrently
|
||||||
|
from multiple threads.
|
||||||
|
|
||||||
|
.. py:method:: compare(a, b)
|
||||||
|
|
||||||
|
Three-way comparison.
|
||||||
|
|
||||||
|
:param string a: First field to compare
|
||||||
|
:param string b: Second field to compare
|
||||||
|
:returns: * -1 if a < b
|
||||||
|
* 0 if a == b
|
||||||
|
* 1 if a > b
|
||||||
|
:rtype: ``int``
|
||||||
|
|
||||||
|
.. py:method:: name()
|
||||||
|
|
||||||
|
The name of the comparator. Used to check for comparator
|
||||||
|
mismatches (i.e., a DB created with one comparator is
|
||||||
|
accessed using a different comparator).
|
||||||
|
|
||||||
|
The client of this package should switch to a new name whenever
|
||||||
|
the comparator implementation changes in a way that will cause
|
||||||
|
the relative ordering of any two keys to change.
|
||||||
|
|
||||||
|
Names starting with "rocksdb." are reserved and should not be used
|
||||||
|
by any clients of this package.
|
||||||
|
|
||||||
|
:rtype: ``string``
|
||||||
|
|
||||||
|
Merge Operator
|
||||||
|
==============
|
||||||
|
|
||||||
|
Essentially, a MergeOperator specifies the SEMANTICS of a merge, which only
|
||||||
|
client knows. It could be numeric addition, list append, string
|
||||||
|
concatenation, edit data structure, whatever.
|
||||||
|
The library, on the other hand, is concerned with the exercise of this
|
||||||
|
interface, at the right time (during get, iteration, compaction...)
|
||||||
|
|
||||||
|
To use merge, the client needs to provide an object implementing one of
|
||||||
|
the following interfaces:
|
||||||
|
|
||||||
|
* AssociativeMergeOperator - for most simple semantics (always take
|
||||||
|
two values, and merge them into one value, which is then put back
|
||||||
|
into rocksdb).
|
||||||
|
numeric addition and string concatenation are examples.
|
||||||
|
|
||||||
|
* MergeOperator - the generic class for all the more complex operations.
|
||||||
|
One method (FullMerge) to merge a Put/Delete value with a merge operand.
|
||||||
|
Another method (PartialMerge) that merges two operands together.
|
||||||
|
This is especially useful if your key values have a complex structure but
|
||||||
|
you would still like to support client-specific incremental updates.
|
||||||
|
|
||||||
|
AssociativeMergeOperator is simpler to implement.
|
||||||
|
MergeOperator is simply more powerful.
|
||||||
|
|
||||||
|
See this page for more details
|
||||||
|
https://github.com/facebook/rocksdb/wiki/Merge-Operator
|
||||||
|
|
||||||
|
AssociativeMergeOperator
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
.. py:class:: rocksdb.interfaces.AssociativeMergeOperator
|
||||||
|
|
||||||
|
.. py:method:: merge(key, existing_value, value)
|
||||||
|
|
||||||
|
Gives the client a way to express the read -> modify -> write semantics
|
||||||
|
|
||||||
|
:param string key: The key that's associated with this merge operation
|
||||||
|
:param string existing_value: The current value in the db.
|
||||||
|
``None`` indicates the key does not exist
|
||||||
|
before this op
|
||||||
|
:param string value: The value to update/merge the existing_value with
|
||||||
|
|
||||||
|
:returns: ``True`` and the new value on success.
|
||||||
|
All values passed in will be client-specific values.
|
||||||
|
So if this method returns false, it is because client
|
||||||
|
specified bad data or there was internal corruption.
|
||||||
|
The client should assume that this will be treated as an
|
||||||
|
error by the library.
|
||||||
|
|
||||||
|
:rtype: ``(bool, string)``
|
||||||
|
|
||||||
|
.. py:method:: name()
|
||||||
|
|
||||||
|
The name of the MergeOperator. Used to check for MergeOperator mismatches.
|
||||||
|
For example a DB created with one MergeOperator is accessed using a
|
||||||
|
different MergeOperator.
|
||||||
|
|
||||||
|
:rtype: ``string``
|
||||||
|
|
||||||
|
MergeOperator
|
||||||
|
-------------
|
||||||
|
|
||||||
|
.. py:class:: rocksdb.interfaces.MergeOperator
|
||||||
|
|
||||||
|
.. py:method:: full_merge(key, existing_value, operand_list)
|
||||||
|
|
||||||
|
Gives the client a way to express the read -> modify -> write semantics
|
||||||
|
|
||||||
|
:param string key: The key that's associated with this merge operation.
|
||||||
|
Client could multiplex the merge operator based on it
|
||||||
|
if the key space is partitioned and different subspaces
|
||||||
|
refer to different types of data which have different
|
||||||
|
merge operation semantics
|
||||||
|
|
||||||
|
:param string existing_value: The current value in the db.
|
||||||
|
``None`` indicates the key does not exist
|
||||||
|
before this op
|
||||||
|
|
||||||
|
:param operand_list: The sequence of merge operations to apply.
|
||||||
|
:type operand_list: list of strings
|
||||||
|
|
||||||
|
:returns: ``True`` and the new value on success.
|
||||||
|
All values passed in will be client-specific values.
|
||||||
|
So if this method returns false, it is because client
|
||||||
|
specified bad data or there was internal corruption.
|
||||||
|
The client should assume that this will be treated as an
|
||||||
|
error by the library.
|
||||||
|
|
||||||
|
:rtype: ``(bool, string)``
|
||||||
|
|
||||||
|
.. py:method:: partial_merge(key, left_operand, right_operand)
|
||||||
|
|
||||||
|
This function performs merge(left_op, right_op)
|
||||||
|
when both the operands are themselves merge operation types
|
||||||
|
that you would have passed to a DB::Merge() call in the same order.
|
||||||
|
For example DB::Merge(key,left_op), followed by DB::Merge(key,right_op)).
|
||||||
|
|
||||||
|
PartialMerge should combine them into a single merge operation that is
|
||||||
|
returned together with ``True``
|
||||||
|
This new value should be constructed such that a call to
|
||||||
|
DB::Merge(key, new_value) would yield the same result as a call
|
||||||
|
to DB::Merge(key, left_op) followed by DB::Merge(key, right_op).
|
||||||
|
|
||||||
|
If it is impossible or infeasible to combine the two operations,
|
||||||
|
return ``(False, None)`` The library will internally keep track of the
|
||||||
|
operations, and apply them in the correct order once a base-value
|
||||||
|
(a Put/Delete/End-of-Database) is seen.
|
||||||
|
|
||||||
|
:param string key: the key that is associated with this merge operation.
|
||||||
|
:param string left_operand: First operand to merge
|
||||||
|
:param string right_operand: Second operand to merge
|
||||||
|
:rtype: ``(bool, string)``
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Presently there is no way to differentiate between error/corruption
|
||||||
|
and simply "return false". For now, the client should simply return
|
||||||
|
false in any case it cannot perform partial-merge, regardless of reason.
|
||||||
|
If there is corruption in the data, handle it in the FullMerge() function,
|
||||||
|
and return false there.
|
||||||
|
|
||||||
|
.. py:method:: name()
|
||||||
|
|
||||||
|
The name of the MergeOperator. Used to check for MergeOperator mismatches.
|
||||||
|
For example a DB created with one MergeOperator is accessed using a
|
||||||
|
different MergeOperator.
|
||||||
|
|
||||||
|
:rtype: ``string``
|
||||||
|
|
||||||
|
FilterPolicy
|
||||||
|
============
|
||||||
|
|
||||||
|
.. py:class:: rocksdb.interfaces.FilterPolicy
|
||||||
|
|
||||||
|
.. py:method:: create_filter(keys)
|
||||||
|
|
||||||
|
Create a bytestring which can act as a filter for keys.
|
||||||
|
|
||||||
|
:param keys: list of keys (potentially with duplicates)
|
||||||
|
that are ordered according to the user supplied
|
||||||
|
comparator.
|
||||||
|
:type keys: list of strings
|
||||||
|
|
||||||
|
:returns: A filter that summarizes keys
|
||||||
|
:rtype: ``string``
|
||||||
|
|
||||||
|
.. py:method:: key_may_match(key, filter)
|
||||||
|
|
||||||
|
Check if the key is maybe in the filter.
|
||||||
|
|
||||||
|
:param string key: Key for a single entry inside the database
|
||||||
|
:param string filter: Contains the data returned by a preceding call
|
||||||
|
to create_filter on this class
|
||||||
|
:returns: This method must return ``True`` if the key was in the list
|
||||||
|
of keys passed to create_filter().
|
||||||
|
This method may return ``True`` or ``False`` if the key was
|
||||||
|
not on the list, but it should aim to return ``False`` with
|
||||||
|
a high probability.
|
||||||
|
:rtype: ``bool``
|
||||||
|
|
||||||
|
|
||||||
|
.. py:method:: name()
|
||||||
|
|
||||||
|
Return the name of this policy. Note that if the filter encoding
|
||||||
|
changes in an incompatible way, the name returned by this method
|
||||||
|
must be changed. Otherwise, old incompatible filters may be
|
||||||
|
passed to methods of this type.
|
||||||
|
|
||||||
|
:rtype: ``string``
|
748
docs/api/options.rst
Normal file
748
docs/api/options.rst
Normal file
|
@ -0,0 +1,748 @@
|
||||||
|
Options creation
|
||||||
|
****************
|
||||||
|
|
||||||
|
Options object
|
||||||
|
==============
|
||||||
|
|
||||||
|
|
||||||
|
.. py:class:: rocksdb.Options
|
||||||
|
|
||||||
|
.. IMPORTANT::
|
||||||
|
|
||||||
|
The default values mentioned here, describe the values of the
|
||||||
|
C++ library only. This wrapper does not set any default value
|
||||||
|
itself. So as soon as the rocksdb developers change a default value
|
||||||
|
this document could be outdated. So if you really depend on a default
|
||||||
|
value, double check it with the according version of the C++ library.
|
||||||
|
|
||||||
|
| Most recent default values should be here
|
||||||
|
| https://github.com/facebook/rocksdb/blob/master/include/rocksdb/options.h
|
||||||
|
| https://github.com/facebook/rocksdb/blob/master/util/options.cc
|
||||||
|
|
||||||
|
.. py:method:: __init__(**kwargs)
|
||||||
|
|
||||||
|
All options mentioned below can also be passed as keyword-arguments in
|
||||||
|
the constructor. For example::
|
||||||
|
|
||||||
|
import rocksdb
|
||||||
|
|
||||||
|
opts = rocksdb.Options(create_if_missing=True)
|
||||||
|
# is the same as
|
||||||
|
opts = rocksdb.Options()
|
||||||
|
opts.create_if_missing = True
|
||||||
|
|
||||||
|
|
||||||
|
.. py:attribute:: create_if_missing
|
||||||
|
|
||||||
|
If ``True``, the database will be created if it is missing.
|
||||||
|
|
||||||
|
| *Type:* ``bool``
|
||||||
|
| *Default:* ``False``
|
||||||
|
|
||||||
|
.. py:attribute:: error_if_exists
|
||||||
|
|
||||||
|
If ``True``, an error is raised if the database already exists.
|
||||||
|
|
||||||
|
| *Type:* ``bool``
|
||||||
|
| *Default:* ``False``
|
||||||
|
|
||||||
|
|
||||||
|
.. py:attribute:: paranoid_checks
|
||||||
|
|
||||||
|
If ``True``, the implementation will do aggressive checking of the
|
||||||
|
data it is processing and will stop early if it detects any
|
||||||
|
errors. This may have unforeseen ramifications: for example, a
|
||||||
|
corruption of one DB entry may cause a large number of entries to
|
||||||
|
become unreadable or for the entire DB to become unopenable.
|
||||||
|
If any of the writes to the database fails (Put, Delete, Merge, Write),
|
||||||
|
the database will switch to read-only mode and fail all other
|
||||||
|
Write operations.
|
||||||
|
|
||||||
|
| *Type:* ``bool``
|
||||||
|
| *Default:* ``False``
|
||||||
|
|
||||||
|
.. py:attribute:: write_buffer_size
|
||||||
|
|
||||||
|
Amount of data to build up in memory (backed by an unsorted log
|
||||||
|
on disk) before converting to a sorted on-disk file.
|
||||||
|
|
||||||
|
Larger values increase performance, especially during bulk loads.
|
||||||
|
Up to max_write_buffer_number write buffers may be held in memory
|
||||||
|
at the same time, so you may wish to adjust this parameter to control
|
||||||
|
memory usage. Also, a larger write buffer will result in a longer recovery
|
||||||
|
time the next time the database is opened.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``4194304``
|
||||||
|
|
||||||
|
.. py:attribute:: max_write_buffer_number
|
||||||
|
|
||||||
|
The maximum number of write buffers that are built up in memory.
|
||||||
|
The default is 2, so that when 1 write buffer is being flushed to
|
||||||
|
storage, new writes can continue to the other write buffer.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``2``
|
||||||
|
|
||||||
|
.. py:attribute:: min_write_buffer_number_to_merge
|
||||||
|
|
||||||
|
The minimum number of write buffers that will be merged together
|
||||||
|
before writing to storage. If set to 1, then
|
||||||
|
all write buffers are fushed to L0 as individual files and this increases
|
||||||
|
read amplification because a get request has to check in all of these
|
||||||
|
files. Also, an in-memory merge may result in writing lesser
|
||||||
|
data to storage if there are duplicate records in each of these
|
||||||
|
individual write buffers.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``1``
|
||||||
|
|
||||||
|
.. py:attribute:: max_open_files
|
||||||
|
|
||||||
|
Number of open files that can be used by the DB. You may need to
|
||||||
|
increase this if your database has a large working set (budget
|
||||||
|
one open file per 2MB of working set).
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``1000``
|
||||||
|
|
||||||
|
.. py:attribute:: block_cache
|
||||||
|
|
||||||
|
Control over blocks (user data is stored in a set of blocks, and
|
||||||
|
a block is the unit of reading from disk).
|
||||||
|
|
||||||
|
If not ``None`` use the specified cache for blocks.
|
||||||
|
If ``None``, rocksdb will automatically create and use an 8MB internal cache.
|
||||||
|
|
||||||
|
| *Type:* Instace of :py:class:`rocksdb.LRUCache`
|
||||||
|
| *Default:* ``None``
|
||||||
|
|
||||||
|
.. py:attribute:: block_cache_compressed
|
||||||
|
|
||||||
|
If not ``None`` use the specified cache for compressed blocks.
|
||||||
|
If ``None``, rocksdb will not use a compressed block cache.
|
||||||
|
|
||||||
|
| *Type:* Instace of :py:class:`rocksdb.LRUCache`
|
||||||
|
| *Default:* ``None``
|
||||||
|
|
||||||
|
.. py:attribute:: block_size
|
||||||
|
|
||||||
|
Approximate size of user data packed per block. Note that the
|
||||||
|
block size specified here corresponds to uncompressed data. The
|
||||||
|
actual size of the unit read from disk may be smaller if
|
||||||
|
compression is enabled. This parameter can be changed dynamically.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``4096``
|
||||||
|
|
||||||
|
|
||||||
|
.. py:attribute:: block_restart_interval
|
||||||
|
|
||||||
|
Number of keys between restart points for delta encoding of keys.
|
||||||
|
This parameter can be changed dynamically. Most clients should
|
||||||
|
leave this parameter alone.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``16``
|
||||||
|
|
||||||
|
.. py:attribute:: compression
|
||||||
|
|
||||||
|
Compress blocks using the specified compression algorithm.
|
||||||
|
This parameter can be changed dynamically.
|
||||||
|
|
||||||
|
| *Type:* Member of :py:class:`rocksdb.CompressionType`
|
||||||
|
| *Default:* :py:attr:`rocksdb.CompressionType.snappy_compression`
|
||||||
|
|
||||||
|
.. py:attribute:: whole_key_filtering
|
||||||
|
|
||||||
|
If ``True``, place whole keys in the filter (not just prefixes).
|
||||||
|
This must generally be true for gets to be efficient.
|
||||||
|
|
||||||
|
| *Type:* ``bool``
|
||||||
|
| *Default:* ``True``
|
||||||
|
|
||||||
|
|
||||||
|
.. py:attribute:: num_levels
|
||||||
|
|
||||||
|
Number of levels for this database
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``7``
|
||||||
|
|
||||||
|
|
||||||
|
.. py:attribute:: level0_file_num_compaction_trigger
|
||||||
|
|
||||||
|
Number of files to trigger level-0 compaction. A value <0 means that
|
||||||
|
level-0 compaction will not be triggered by number of files at all.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``4``
|
||||||
|
|
||||||
|
.. py:attribute:: level0_slowdown_writes_trigger
|
||||||
|
|
||||||
|
Soft limit on number of level-0 files. We start slowing down writes at this
|
||||||
|
point. A value <0 means that no writing slow down will be triggered by
|
||||||
|
number of files in level-0.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``8``
|
||||||
|
|
||||||
|
.. py:attribute:: level0_stop_writes_trigger
|
||||||
|
|
||||||
|
Maximum number of level-0 files. We stop writes at this point.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``12``
|
||||||
|
|
||||||
|
.. py:attribute:: max_mem_compaction_level
|
||||||
|
|
||||||
|
Maximum level to which a new compacted memtable is pushed if it
|
||||||
|
does not create overlap. We try to push to level 2 to avoid the
|
||||||
|
relatively expensive level 0=>1 compactions and to avoid some
|
||||||
|
expensive manifest file operations. We do not push all the way to
|
||||||
|
the largest level since that can generate a lot of wasted disk
|
||||||
|
space if the same key space is being repeatedly overwritten.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``2``
|
||||||
|
|
||||||
|
|
||||||
|
.. py:attribute:: target_file_size_base
|
||||||
|
|
||||||
|
| Target file size for compaction.
|
||||||
|
| target_file_size_base is per-file size for level-1.
|
||||||
|
| Target file size for level L can be calculated by
|
||||||
|
| target_file_size_base * (target_file_size_multiplier ^ (L-1)).
|
||||||
|
|
||||||
|
For example, if target_file_size_base is 2MB and
|
||||||
|
target_file_size_multiplier is 10, then each file on level-1 will
|
||||||
|
be 2MB, and each file on level 2 will be 20MB,
|
||||||
|
and each file on level-3 will be 200MB.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``2097152``
|
||||||
|
|
||||||
|
.. py:attribute:: target_file_size_multiplier
|
||||||
|
|
||||||
|
| by default target_file_size_multiplier is 1, which means
|
||||||
|
| by default files in different levels will have similar size.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``1``
|
||||||
|
|
||||||
|
.. py:attribute:: max_bytes_for_level_base
|
||||||
|
|
||||||
|
Control maximum total data size for a level.
|
||||||
|
*max_bytes_for_level_base* is the max total for level-1.
|
||||||
|
Maximum number of bytes for level L can be calculated as
|
||||||
|
(*max_bytes_for_level_base*) * (*max_bytes_for_level_multiplier* ^ (L-1))
|
||||||
|
For example, if *max_bytes_for_level_base* is 20MB, and if
|
||||||
|
*max_bytes_for_level_multiplier* is 10, total data size for level-1
|
||||||
|
will be 20MB, total file size for level-2 will be 200MB,
|
||||||
|
and total file size for level-3 will be 2GB.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``10485760``
|
||||||
|
|
||||||
|
.. py:attribute:: max_bytes_for_level_multiplier
|
||||||
|
|
||||||
|
See :py:attr:`max_bytes_for_level_base`
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``10``
|
||||||
|
|
||||||
|
.. py:attribute:: max_bytes_for_level_multiplier_additional
|
||||||
|
|
||||||
|
Different max-size multipliers for different levels.
|
||||||
|
These are multiplied by max_bytes_for_level_multiplier to arrive
|
||||||
|
at the max-size of each level.
|
||||||
|
|
||||||
|
| *Type:* ``[int]``
|
||||||
|
| *Default:* ``[1, 1, 1, 1, 1, 1, 1]``
|
||||||
|
|
||||||
|
.. py:attribute:: expanded_compaction_factor
|
||||||
|
|
||||||
|
Maximum number of bytes in all compacted files. We avoid expanding
|
||||||
|
the lower level file set of a compaction if it would make the
|
||||||
|
total compaction cover more than
|
||||||
|
(expanded_compaction_factor * targetFileSizeLevel()) many bytes.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``25``
|
||||||
|
|
||||||
|
.. py:attribute:: source_compaction_factor
|
||||||
|
|
||||||
|
Maximum number of bytes in all source files to be compacted in a
|
||||||
|
single compaction run. We avoid picking too many files in the
|
||||||
|
source level so that we do not exceed the total source bytes
|
||||||
|
for compaction to exceed
|
||||||
|
(source_compaction_factor * targetFileSizeLevel()) many bytes.
|
||||||
|
If 1 pick maxfilesize amount of data as the source of
|
||||||
|
a compaction.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``1``
|
||||||
|
|
||||||
|
.. py:attribute:: max_grandparent_overlap_factor
|
||||||
|
|
||||||
|
Control maximum bytes of overlaps in grandparent (i.e., level+2) before we
|
||||||
|
stop building a single file in a level->level+1 compaction.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``10``
|
||||||
|
|
||||||
|
.. py:attribute:: disable_data_sync
|
||||||
|
|
||||||
|
If true, then the contents of data files are not synced
|
||||||
|
to stable storage. Their contents remain in the OS buffers till the
|
||||||
|
OS decides to flush them. This option is good for bulk-loading
|
||||||
|
of data. Once the bulk-loading is complete, please issue a
|
||||||
|
sync to the OS to flush all dirty buffesrs to stable storage.
|
||||||
|
|
||||||
|
| *Type:* ``bool``
|
||||||
|
| *Default:* ``False``
|
||||||
|
|
||||||
|
.. py:attribute:: use_fsync
|
||||||
|
|
||||||
|
If true, then every store to stable storage will issue a fsync.
|
||||||
|
If false, then every store to stable storage will issue a fdatasync.
|
||||||
|
This parameter should be set to true while storing data to
|
||||||
|
filesystem like ext3 that can lose files after a reboot.
|
||||||
|
|
||||||
|
| *Type:* ``bool``
|
||||||
|
| *Default:* ``False``
|
||||||
|
|
||||||
|
.. py:attribute:: db_stats_log_interval
|
||||||
|
|
||||||
|
This number controls how often a new scribe log about
|
||||||
|
db deploy stats is written out.
|
||||||
|
-1 indicates no logging at all.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``1800``
|
||||||
|
|
||||||
|
.. py:attribute:: db_log_dir
|
||||||
|
|
||||||
|
This specifies the info LOG dir.
|
||||||
|
If it is empty, the log files will be in the same dir as data.
|
||||||
|
If it is non empty, the log files will be in the specified dir,
|
||||||
|
and the db data dir's absolute path will be used as the log file
|
||||||
|
name's prefix.
|
||||||
|
|
||||||
|
| *Type:* ``string``
|
||||||
|
| *Default:* ``""``
|
||||||
|
|
||||||
|
.. py:attribute:: wal_dir
|
||||||
|
|
||||||
|
This specifies the absolute dir path for write-ahead logs (WAL).
|
||||||
|
If it is empty, the log files will be in the same dir as data,
|
||||||
|
dbname is used as the data dir by default.
|
||||||
|
If it is non empty, the log files will be in kept the specified dir.
|
||||||
|
When destroying the db, all log files in wal_dir and the dir itself is deleted
|
||||||
|
|
||||||
|
| *Type:* ``string``
|
||||||
|
| *Default:* ``""``
|
||||||
|
|
||||||
|
.. py:attribute:: disable_seek_compaction
|
||||||
|
|
||||||
|
Disable compaction triggered by seek.
|
||||||
|
With bloomfilter and fast storage, a miss on one level
|
||||||
|
is very cheap if the file handle is cached in table cache
|
||||||
|
(which is true if max_open_files is large).
|
||||||
|
|
||||||
|
| *Type:* ``bool``
|
||||||
|
| *Default:* ``False``
|
||||||
|
|
||||||
|
.. py:attribute:: delete_obsolete_files_period_micros
|
||||||
|
|
||||||
|
The periodicity when obsolete files get deleted. The default
|
||||||
|
value is 6 hours. The files that get out of scope by compaction
|
||||||
|
process will still get automatically delete on every compaction,
|
||||||
|
regardless of this setting
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``21600000000``
|
||||||
|
|
||||||
|
.. py:attribute:: max_background_compactions
|
||||||
|
|
||||||
|
Maximum number of concurrent background jobs, submitted to
|
||||||
|
the default LOW priority thread pool
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``1``
|
||||||
|
|
||||||
|
.. py:attribute:: max_background_flushes
|
||||||
|
|
||||||
|
Maximum number of concurrent background memtable flush jobs, submitted to
|
||||||
|
the HIGH priority thread pool.
|
||||||
|
By default, all background jobs (major compaction and memtable flush) go
|
||||||
|
to the LOW priority pool. If this option is set to a positive number,
|
||||||
|
memtable flush jobs will be submitted to the HIGH priority pool.
|
||||||
|
It is important when the same Env is shared by multiple db instances.
|
||||||
|
Without a separate pool, long running major compaction jobs could
|
||||||
|
potentially block memtable flush jobs of other db instances, leading to
|
||||||
|
unnecessary Put stalls.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``0``
|
||||||
|
|
||||||
|
.. py:attribute:: max_log_file_size
|
||||||
|
|
||||||
|
Specify the maximal size of the info log file. If the log file
|
||||||
|
is larger than `max_log_file_size`, a new info log file will
|
||||||
|
be created.
|
||||||
|
If max_log_file_size == 0, all logs will be written to one
|
||||||
|
log file.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``0``
|
||||||
|
|
||||||
|
.. py:attribute:: log_file_time_to_roll
|
||||||
|
|
||||||
|
Time for the info log file to roll (in seconds).
|
||||||
|
If specified with non-zero value, log file will be rolled
|
||||||
|
if it has been active longer than `log_file_time_to_roll`.
|
||||||
|
A value of ``0`` means disabled.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``0``
|
||||||
|
|
||||||
|
.. py:attribute:: keep_log_file_num
|
||||||
|
|
||||||
|
Maximal info log files to be kept.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``1000``
|
||||||
|
|
||||||
|
.. py:attribute:: soft_rate_limit
|
||||||
|
|
||||||
|
Puts are delayed 0-1 ms when any level has a compaction score that exceeds
|
||||||
|
soft_rate_limit. This is ignored when == 0.0.
|
||||||
|
CONSTRAINT: soft_rate_limit <= hard_rate_limit. If this constraint does not
|
||||||
|
hold, RocksDB will set soft_rate_limit = hard_rate_limit.
|
||||||
|
A value of ``0`` means disabled.
|
||||||
|
|
||||||
|
| *Type:* ``float``
|
||||||
|
| *Default:* ``0``
|
||||||
|
|
||||||
|
.. py:attribute:: hard_rate_limit
|
||||||
|
|
||||||
|
Puts are delayed 1ms at a time when any level has a compaction score that
|
||||||
|
exceeds hard_rate_limit. This is ignored when <= 1.0.
|
||||||
|
A value fo ``0`` means disabled.
|
||||||
|
|
||||||
|
| *Type:* ``float``
|
||||||
|
| *Default:* ``0``
|
||||||
|
|
||||||
|
.. py:attribute:: rate_limit_delay_max_milliseconds
|
||||||
|
|
||||||
|
Max time a put will be stalled when hard_rate_limit is enforced. If 0, then
|
||||||
|
there is no limit.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``1000``
|
||||||
|
|
||||||
|
.. py:attribute:: max_manifest_file_size
|
||||||
|
|
||||||
|
manifest file is rolled over on reaching this limit.
|
||||||
|
The older manifest file be deleted.
|
||||||
|
The default value is MAX_INT so that roll-over does not take place.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``(2**64) - 1``
|
||||||
|
|
||||||
|
.. py:attribute:: no_block_cache
|
||||||
|
|
||||||
|
Disable block cache. If this is set to true,
|
||||||
|
then no block cache should be used, and the block_cache should
|
||||||
|
point to ``None``
|
||||||
|
|
||||||
|
| *Type:* ``bool``
|
||||||
|
| *Default:* ``False``
|
||||||
|
|
||||||
|
.. py:attribute:: table_cache_numshardbits
|
||||||
|
|
||||||
|
Number of shards used for table cache.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``4``
|
||||||
|
|
||||||
|
.. py:attribute:: table_cache_remove_scan_count_limit
|
||||||
|
|
||||||
|
During data eviction of table's LRU cache, it would be inefficient
|
||||||
|
to strictly follow LRU because this piece of memory will not really
|
||||||
|
be released unless its refcount falls to zero. Instead, make two
|
||||||
|
passes: the first pass will release items with refcount = 1,
|
||||||
|
and if not enough space releases after scanning the number of
|
||||||
|
elements specified by this parameter, we will remove items in LRU
|
||||||
|
order.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``16``
|
||||||
|
|
||||||
|
.. py:attribute:: arena_block_size
|
||||||
|
|
||||||
|
size of one block in arena memory allocation.
|
||||||
|
If <= 0, a proper value is automatically calculated (usually 1/10 of
|
||||||
|
writer_buffer_size).
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``0``
|
||||||
|
|
||||||
|
.. py:attribute:: disable_auto_compactions
|
||||||
|
|
||||||
|
Disable automatic compactions. Manual compactions can still
|
||||||
|
be issued on this database.
|
||||||
|
|
||||||
|
| *Type:* ``bool``
|
||||||
|
| *Default:* ``False``
|
||||||
|
|
||||||
|
.. py:attribute:: wal_ttl_seconds, wal_size_limit_mb
|
||||||
|
|
||||||
|
The following two fields affect how archived logs will be deleted.
|
||||||
|
|
||||||
|
1. If both set to 0, logs will be deleted asap and will not get into
|
||||||
|
the archive.
|
||||||
|
2. If wal_ttl_seconds is 0 and wal_size_limit_mb is not 0,
|
||||||
|
WAL files will be checked every 10 min and if total size is greater
|
||||||
|
then wal_size_limit_mb, they will be deleted starting with the
|
||||||
|
earliest until size_limit is met. All empty files will be deleted.
|
||||||
|
3. If wal_ttl_seconds is not 0 and wal_size_limit_mb is 0, then
|
||||||
|
WAL files will be checked every wal_ttl_secondsi / 2 and those that
|
||||||
|
are older than wal_ttl_seconds will be deleted.
|
||||||
|
4. If both are not 0, WAL files will be checked every 10 min and both
|
||||||
|
checks will be performed with ttl being first.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``0``
|
||||||
|
|
||||||
|
.. py:attribute:: manifest_preallocation_size
|
||||||
|
|
||||||
|
Number of bytes to preallocate (via fallocate) the manifest
|
||||||
|
files. Default is 4mb, which is reasonable to reduce random IO
|
||||||
|
as well as prevent overallocation for mounts that preallocate
|
||||||
|
large amounts of data (such as xfs's allocsize option).
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``4194304``
|
||||||
|
|
||||||
|
.. py:attribute:: purge_redundant_kvs_while_flush
|
||||||
|
|
||||||
|
Purge duplicate/deleted keys when a memtable is flushed to storage.
|
||||||
|
|
||||||
|
| *Type:* ``bool``
|
||||||
|
| *Default:* ``True``
|
||||||
|
|
||||||
|
.. py:attribute:: allow_os_buffer
|
||||||
|
|
||||||
|
Data being read from file storage may be buffered in the OS
|
||||||
|
|
||||||
|
| *Type:* ``bool``
|
||||||
|
| *Default:* ``True``
|
||||||
|
|
||||||
|
.. py:attribute:: allow_mmap_reads
|
||||||
|
|
||||||
|
Allow the OS to mmap file for reading sst tables
|
||||||
|
|
||||||
|
| *Type:* ``bool``
|
||||||
|
| *Default:* ``False``
|
||||||
|
|
||||||
|
.. py:attribute:: allow_mmap_writes
|
||||||
|
|
||||||
|
Allow the OS to mmap file for writing
|
||||||
|
|
||||||
|
| *Type:* ``bool``
|
||||||
|
| *Default:* ``True``
|
||||||
|
|
||||||
|
.. py:attribute:: is_fd_close_on_exec
|
||||||
|
|
||||||
|
Disable child process inherit open files
|
||||||
|
|
||||||
|
| *Type:* ``bool``
|
||||||
|
| *Default:* ``True``
|
||||||
|
|
||||||
|
.. py:attribute:: skip_log_error_on_recovery
|
||||||
|
|
||||||
|
Skip log corruption error on recovery
|
||||||
|
(If client is ok with losing most recent changes)
|
||||||
|
|
||||||
|
| *Type:* ``bool``
|
||||||
|
| *Default:* ``False``
|
||||||
|
|
||||||
|
.. py:attribute:: stats_dump_period_sec
|
||||||
|
|
||||||
|
If not zero, dump rocksdb.stats to LOG every stats_dump_period_sec
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``3600``
|
||||||
|
|
||||||
|
.. py:attribute:: block_size_deviation
|
||||||
|
|
||||||
|
This is used to close a block before it reaches the configured
|
||||||
|
'block_size'. If the percentage of free space in the current block is less
|
||||||
|
than this specified number and adding a new record to the block will
|
||||||
|
exceed the configured block size, then this block will be closed and the
|
||||||
|
new record will be written to the next block.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``10``
|
||||||
|
|
||||||
|
.. py:attribute:: advise_random_on_open
|
||||||
|
|
||||||
|
If set true, will hint the underlying file system that the file
|
||||||
|
access pattern is random, when a sst file is opened.
|
||||||
|
|
||||||
|
| *Type:* ``bool``
|
||||||
|
| *Default:* ``True``
|
||||||
|
|
||||||
|
.. py:attribute:: use_adaptive_mutex
|
||||||
|
|
||||||
|
Use adaptive mutex, which spins in the user space before resorting
|
||||||
|
to kernel. This could reduce context switch when the mutex is not
|
||||||
|
heavily contended. However, if the mutex is hot, we could end up
|
||||||
|
wasting spin time.
|
||||||
|
|
||||||
|
| *Type:* ``bool``
|
||||||
|
| *Default:* ``False``
|
||||||
|
|
||||||
|
.. py:attribute:: bytes_per_sync
|
||||||
|
|
||||||
|
Allows OS to incrementally sync files to disk while they are being
|
||||||
|
written, asynchronously, in the background.
|
||||||
|
Issue one request for every bytes_per_sync written. 0 turns it off.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``0``
|
||||||
|
|
||||||
|
.. py:attribute:: filter_deletes
|
||||||
|
|
||||||
|
Use KeyMayExist API to filter deletes when this is true.
|
||||||
|
If KeyMayExist returns false, i.e. the key definitely does not exist, then
|
||||||
|
the delete is a noop. KeyMayExist only incurs in-memory look up.
|
||||||
|
This optimization avoids writing the delete to storage when appropriate.
|
||||||
|
|
||||||
|
| *Type:* ``bool``
|
||||||
|
| *Default:* ``False``
|
||||||
|
|
||||||
|
.. py:attribute:: max_sequential_skip_in_iterations
|
||||||
|
|
||||||
|
An iteration->Next() sequentially skips over keys with the same
|
||||||
|
user-key unless this option is set. This number specifies the number
|
||||||
|
of keys (with the same userkey) that will be sequentially
|
||||||
|
skipped before a reseek is issued.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``8``
|
||||||
|
|
||||||
|
.. py:attribute:: inplace_update_support
|
||||||
|
|
||||||
|
Allows thread-safe inplace updates. Requires Updates if
|
||||||
|
|
||||||
|
* key exists in current memtable
|
||||||
|
* new sizeof(new_value) <= sizeof(old_value)
|
||||||
|
* old_value for that key is a put i.e. kTypeValue
|
||||||
|
|
||||||
|
| *Type:* ``bool``
|
||||||
|
| *Default:* ``False``
|
||||||
|
|
||||||
|
.. py:attribute:: inplace_update_num_locks
|
||||||
|
|
||||||
|
| Number of locks used for inplace update.
|
||||||
|
| Default: 10000, if inplace_update_support = true, else 0.
|
||||||
|
|
||||||
|
| *Type:* ``int``
|
||||||
|
| *Default:* ``10000``
|
||||||
|
|
||||||
|
.. py:attribute:: comparator
|
||||||
|
|
||||||
|
Comparator used to define the order of keys in the table.
|
||||||
|
A python comparator must implement the :py:class:`rocksdb.interfaces.Comparator`
|
||||||
|
interface.
|
||||||
|
|
||||||
|
*Requires*: The client must ensure that the comparator supplied
|
||||||
|
here has the same name and orders keys *exactly* the same as the
|
||||||
|
comparator provided to previous open calls on the same DB.
|
||||||
|
|
||||||
|
*Default:* :py:class:`rocksdb.BytewiseComparator`
|
||||||
|
|
||||||
|
.. py:attribute:: merge_operator
|
||||||
|
|
||||||
|
The client must provide a merge operator if Merge operation
|
||||||
|
needs to be accessed. Calling Merge on a DB without a merge operator
|
||||||
|
would result in :py:exc:`rocksdb.errors.NotSupported`. The client must
|
||||||
|
ensure that the merge operator supplied here has the same name and
|
||||||
|
*exactly* the same semantics as the merge operator provided to
|
||||||
|
previous open calls on the same DB. The only exception is reserved
|
||||||
|
for upgrade, where a DB previously without a merge operator is
|
||||||
|
introduced to Merge operation for the first time. It's necessary to
|
||||||
|
specify a merge operator when openning the DB in this case.
|
||||||
|
|
||||||
|
A python merge operator must implement the
|
||||||
|
:py:class:`rocksdb.interfaces.MergeOperator` or
|
||||||
|
:py:class:`rocksdb.interfaces.AssociativeMergeOperator`
|
||||||
|
interface.
|
||||||
|
|
||||||
|
*Default:* ``None``
|
||||||
|
|
||||||
|
.. py:attribute:: filter_policy
|
||||||
|
|
||||||
|
If not ``None`` use the specified filter policy to reduce disk reads.
|
||||||
|
A python filter policy must implement the
|
||||||
|
:py:class:`rocksdb.interfaces.FilterPolicy` interface.
|
||||||
|
Recommendes is a instance of :py:class:`rocksdb.BloomFilterPolicy`
|
||||||
|
|
||||||
|
*Default:* ``None``
|
||||||
|
|
||||||
|
CompressionTypes
|
||||||
|
================
|
||||||
|
|
||||||
|
.. py:class:: rocksdb.CompressionType
|
||||||
|
|
||||||
|
Defines the support compression types
|
||||||
|
|
||||||
|
.. py:attribute:: no_compression
|
||||||
|
.. py:attribute:: snappy_compression
|
||||||
|
.. py:attribute:: zlib_compression
|
||||||
|
.. py:attribute:: bzip2_compression
|
||||||
|
|
||||||
|
BytewiseComparator
|
||||||
|
==================
|
||||||
|
|
||||||
|
.. py:class:: rocksdb.BytewiseComparator
|
||||||
|
|
||||||
|
Wraps the rocksdb Bytewise Comparator, it uses lexicographic byte-wise
|
||||||
|
ordering
|
||||||
|
|
||||||
|
BloomFilterPolicy
|
||||||
|
=================
|
||||||
|
|
||||||
|
.. py:class:: rocksdb.BloomFilterPolicy
|
||||||
|
|
||||||
|
Wraps the rocksdb BloomFilter Policy
|
||||||
|
|
||||||
|
.. py:method:: __init__(bits_per_key)
|
||||||
|
|
||||||
|
:param int bits_per_key:
|
||||||
|
Specifies the approximately number of bits per key.
|
||||||
|
A good value for bits_per_key is 10, which yields a filter with
|
||||||
|
~ 1% false positive rate.
|
||||||
|
|
||||||
|
|
||||||
|
LRUCache
|
||||||
|
========
|
||||||
|
|
||||||
|
.. py:class:: rocksdb.LRUCache
|
||||||
|
|
||||||
|
Wraps the rocksdb LRUCache
|
||||||
|
|
||||||
|
.. py:method:: __init__(capacity, shard_bits=None, rm_scan_count_limit=None)
|
||||||
|
|
||||||
|
Create a new cache with a fixed size capacity. The cache is sharded
|
||||||
|
to 2^numShardBits shards, by hash of the key. The total capacity
|
||||||
|
is divided and evenly assigned to each shard. Inside each shard,
|
||||||
|
the eviction is done in two passes: first try to free spaces by
|
||||||
|
evicting entries that are among the most least used removeScanCountLimit
|
||||||
|
entries and do not have reference other than by the cache itself, in
|
||||||
|
the least-used order. If not enough space is freed, further free the
|
||||||
|
entries in least used order.
|
||||||
|
|
262
docs/conf.py
Normal file
262
docs/conf.py
Normal file
|
@ -0,0 +1,262 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# pyrocksdb documentation build configuration file, created by
|
||||||
|
# sphinx-quickstart on Tue Dec 31 12:50:54 2013.
|
||||||
|
#
|
||||||
|
# This file is execfile()d with the current directory set to its
|
||||||
|
# containing dir.
|
||||||
|
#
|
||||||
|
# Note that not all possible configuration values are present in this
|
||||||
|
# autogenerated file.
|
||||||
|
#
|
||||||
|
# All configuration values have a default; values that are commented out
|
||||||
|
# serve to show the default.
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
|
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||||
|
#sys.path.insert(0, os.path.abspath('.'))
|
||||||
|
|
||||||
|
# -- General configuration ------------------------------------------------
|
||||||
|
|
||||||
|
# If your documentation needs a minimal Sphinx version, state it here.
|
||||||
|
#needs_sphinx = '1.0'
|
||||||
|
|
||||||
|
# Add any Sphinx extension module names here, as strings. They can be
|
||||||
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||||
|
# ones.
|
||||||
|
extensions = [
|
||||||
|
'sphinx.ext.autodoc',
|
||||||
|
'sphinx.ext.todo',
|
||||||
|
'sphinx.ext.viewcode',
|
||||||
|
]
|
||||||
|
|
||||||
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
|
templates_path = ['_templates']
|
||||||
|
|
||||||
|
# The suffix of source filenames.
|
||||||
|
source_suffix = '.rst'
|
||||||
|
|
||||||
|
# The encoding of source files.
|
||||||
|
#source_encoding = 'utf-8-sig'
|
||||||
|
|
||||||
|
# The master toctree document.
|
||||||
|
master_doc = 'index'
|
||||||
|
|
||||||
|
# General information about the project.
|
||||||
|
project = u'pyrocksdb'
|
||||||
|
copyright = u'2013, sh'
|
||||||
|
|
||||||
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
|
# |version| and |release|, also used in various other places throughout the
|
||||||
|
# built documents.
|
||||||
|
#
|
||||||
|
# The short X.Y version.
|
||||||
|
version = '0.1'
|
||||||
|
# The full version, including alpha/beta/rc tags.
|
||||||
|
release = '0.1'
|
||||||
|
|
||||||
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
|
# for a list of supported languages.
|
||||||
|
#language = None
|
||||||
|
|
||||||
|
# There are two options for replacing |today|: either, you set today to some
|
||||||
|
# non-false value, then it is used:
|
||||||
|
#today = ''
|
||||||
|
# Else, today_fmt is used as the format for a strftime call.
|
||||||
|
#today_fmt = '%B %d, %Y'
|
||||||
|
|
||||||
|
# List of patterns, relative to source directory, that match files and
|
||||||
|
# directories to ignore when looking for source files.
|
||||||
|
exclude_patterns = ['_build']
|
||||||
|
|
||||||
|
# The reST default role (used for this markup: `text`) to use for all
|
||||||
|
# documents.
|
||||||
|
#default_role = None
|
||||||
|
|
||||||
|
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||||
|
#add_function_parentheses = True
|
||||||
|
|
||||||
|
# If true, the current module name will be prepended to all description
|
||||||
|
# unit titles (such as .. function::).
|
||||||
|
#add_module_names = True
|
||||||
|
|
||||||
|
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||||
|
# output. They are ignored by default.
|
||||||
|
#show_authors = False
|
||||||
|
|
||||||
|
# The name of the Pygments (syntax highlighting) style to use.
|
||||||
|
pygments_style = 'sphinx'
|
||||||
|
|
||||||
|
# A list of ignored prefixes for module index sorting.
|
||||||
|
#modindex_common_prefix = []
|
||||||
|
|
||||||
|
# If true, keep warnings as "system message" paragraphs in the built documents.
|
||||||
|
#keep_warnings = False
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for HTML output ----------------------------------------------
|
||||||
|
|
||||||
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
|
# a list of builtin themes.
|
||||||
|
html_theme = 'default'
|
||||||
|
|
||||||
|
# Theme options are theme-specific and customize the look and feel of a theme
|
||||||
|
# further. For a list of options available for each theme, see the
|
||||||
|
# documentation.
|
||||||
|
#html_theme_options = {}
|
||||||
|
|
||||||
|
# Add any paths that contain custom themes here, relative to this directory.
|
||||||
|
#html_theme_path = []
|
||||||
|
|
||||||
|
# The name for this set of Sphinx documents. If None, it defaults to
|
||||||
|
# "<project> v<release> documentation".
|
||||||
|
#html_title = None
|
||||||
|
|
||||||
|
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||||
|
#html_short_title = None
|
||||||
|
|
||||||
|
# The name of an image file (relative to this directory) to place at the top
|
||||||
|
# of the sidebar.
|
||||||
|
#html_logo = None
|
||||||
|
|
||||||
|
# The name of an image file (within the static path) to use as favicon of the
|
||||||
|
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||||
|
# pixels large.
|
||||||
|
#html_favicon = None
|
||||||
|
|
||||||
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
|
html_static_path = ['_static']
|
||||||
|
|
||||||
|
# Add any extra paths that contain custom files (such as robots.txt or
|
||||||
|
# .htaccess) here, relative to this directory. These files are copied
|
||||||
|
# directly to the root of the documentation.
|
||||||
|
#html_extra_path = []
|
||||||
|
|
||||||
|
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||||
|
# using the given strftime format.
|
||||||
|
#html_last_updated_fmt = '%b %d, %Y'
|
||||||
|
|
||||||
|
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||||
|
# typographically correct entities.
|
||||||
|
#html_use_smartypants = True
|
||||||
|
|
||||||
|
# Custom sidebar templates, maps document names to template names.
|
||||||
|
#html_sidebars = {}
|
||||||
|
|
||||||
|
# Additional templates that should be rendered to pages, maps page names to
|
||||||
|
# template names.
|
||||||
|
#html_additional_pages = {}
|
||||||
|
|
||||||
|
# If false, no module index is generated.
|
||||||
|
#html_domain_indices = True
|
||||||
|
|
||||||
|
# If false, no index is generated.
|
||||||
|
#html_use_index = True
|
||||||
|
|
||||||
|
# If true, the index is split into individual pages for each letter.
|
||||||
|
#html_split_index = False
|
||||||
|
|
||||||
|
# If true, links to the reST sources are added to the pages.
|
||||||
|
#html_show_sourcelink = True
|
||||||
|
|
||||||
|
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||||
|
#html_show_sphinx = True
|
||||||
|
|
||||||
|
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||||
|
#html_show_copyright = True
|
||||||
|
|
||||||
|
# If true, an OpenSearch description file will be output, and all pages will
|
||||||
|
# contain a <link> tag referring to it. The value of this option must be the
|
||||||
|
# base URL from which the finished HTML is served.
|
||||||
|
#html_use_opensearch = ''
|
||||||
|
|
||||||
|
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||||
|
#html_file_suffix = None
|
||||||
|
|
||||||
|
# Output file base name for HTML help builder.
|
||||||
|
htmlhelp_basename = 'pyrocksdbdoc'
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for LaTeX output ---------------------------------------------
|
||||||
|
|
||||||
|
latex_elements = {
|
||||||
|
# The paper size ('letterpaper' or 'a4paper').
|
||||||
|
#'papersize': 'letterpaper',
|
||||||
|
|
||||||
|
# The font size ('10pt', '11pt' or '12pt').
|
||||||
|
#'pointsize': '10pt',
|
||||||
|
|
||||||
|
# Additional stuff for the LaTeX preamble.
|
||||||
|
#'preamble': '',
|
||||||
|
}
|
||||||
|
|
||||||
|
# Grouping the document tree into LaTeX files. List of tuples
|
||||||
|
# (source start file, target name, title,
|
||||||
|
# author, documentclass [howto, manual, or own class]).
|
||||||
|
latex_documents = [
|
||||||
|
('index', 'pyrocksdb.tex', u'pyrocksdb Documentation',
|
||||||
|
u'sh', 'manual'),
|
||||||
|
]
|
||||||
|
|
||||||
|
# The name of an image file (relative to this directory) to place at the top of
|
||||||
|
# the title page.
|
||||||
|
#latex_logo = None
|
||||||
|
|
||||||
|
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||||
|
# not chapters.
|
||||||
|
#latex_use_parts = False
|
||||||
|
|
||||||
|
# If true, show page references after internal links.
|
||||||
|
#latex_show_pagerefs = False
|
||||||
|
|
||||||
|
# If true, show URL addresses after external links.
|
||||||
|
#latex_show_urls = False
|
||||||
|
|
||||||
|
# Documents to append as an appendix to all manuals.
|
||||||
|
#latex_appendices = []
|
||||||
|
|
||||||
|
# If false, no module index is generated.
|
||||||
|
#latex_domain_indices = True
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for manual page output ---------------------------------------
|
||||||
|
|
||||||
|
# One entry per manual page. List of tuples
|
||||||
|
# (source start file, name, description, authors, manual section).
|
||||||
|
man_pages = [
|
||||||
|
('index', 'pyrocksdb', u'pyrocksdb Documentation',
|
||||||
|
[u'sh'], 1)
|
||||||
|
]
|
||||||
|
|
||||||
|
# If true, show URL addresses after external links.
|
||||||
|
#man_show_urls = False
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for Texinfo output -------------------------------------------
|
||||||
|
|
||||||
|
# Grouping the document tree into Texinfo files. List of tuples
|
||||||
|
# (source start file, target name, title, author,
|
||||||
|
# dir menu entry, description, category)
|
||||||
|
texinfo_documents = [
|
||||||
|
('index', 'pyrocksdb', u'pyrocksdb Documentation',
|
||||||
|
u'sh', 'pyrocksdb', 'One line description of project.',
|
||||||
|
'Miscellaneous'),
|
||||||
|
]
|
||||||
|
|
||||||
|
# Documents to append as an appendix to all manuals.
|
||||||
|
#texinfo_appendices = []
|
||||||
|
|
||||||
|
# If false, no module index is generated.
|
||||||
|
#texinfo_domain_indices = True
|
||||||
|
|
||||||
|
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||||
|
#texinfo_show_urls = 'footnote'
|
||||||
|
|
||||||
|
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
||||||
|
#texinfo_no_detailmenu = False
|
42
docs/index.rst
Normal file
42
docs/index.rst
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
Welcome to pyrocksdb's documentation!
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
Overview
|
||||||
|
--------
|
||||||
|
Python bindings to the C++ interface of http://rocksdb.org/ using cython::
|
||||||
|
|
||||||
|
import rocksdb
|
||||||
|
db = rocksdb.DB("test.db", rocksdb.Options(create_if_missing=True))
|
||||||
|
db.put("a", "b")
|
||||||
|
print db.get("a")
|
||||||
|
|
||||||
|
Tested with python2.7
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
Instructions how to install <installation>
|
||||||
|
Tutorial <tutorial/index>
|
||||||
|
API <api/index>
|
||||||
|
|
||||||
|
|
||||||
|
RoadMap/TODO
|
||||||
|
------------
|
||||||
|
|
||||||
|
* Links from tutorial to API pages (for example merge operator)
|
||||||
|
* support python3.3.
|
||||||
|
Make it fix what kind of strings are allow.
|
||||||
|
|
||||||
|
* Arbitrary ``unicode`` and then do some encoding/decoding, like
|
||||||
|
`redis-driver <https://github.com/andymccurdy/redis-py/blob/2.8.0/redis/connection.py#L319>`_
|
||||||
|
|
||||||
|
* Or just ASCII ``bytes`` and let the user handle unicode.
|
||||||
|
|
||||||
|
* support prefix API
|
||||||
|
|
||||||
|
Indices and tables
|
||||||
|
==================
|
||||||
|
|
||||||
|
* :ref:`genindex`
|
||||||
|
* :ref:`modindex`
|
||||||
|
* :ref:`search`
|
35
docs/installation.rst
Normal file
35
docs/installation.rst
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
Installing
|
||||||
|
**********
|
||||||
|
.. highlight:: bash
|
||||||
|
|
||||||
|
|
||||||
|
Building rocksdb
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Briefly describes how to build rocksdb under a ordinary debian/ubuntu.
|
||||||
|
For more details consider https://github.com/facebook/rocksdb/blob/master/INSTALL.md::
|
||||||
|
|
||||||
|
$ apt-get install build-essential
|
||||||
|
$ apt-get install libsnappy-dev zlib1g-dev libbz2-dev libgflags-dev
|
||||||
|
$ git clone https://github.com/facebook/rocksdb.git
|
||||||
|
$ cd rocksdb
|
||||||
|
$ make librocksdb.so librocksdb.so.2 librocksdb.so.2.0
|
||||||
|
|
||||||
|
If you do not want to call ``make install`` export the following enviroment
|
||||||
|
variables::
|
||||||
|
|
||||||
|
$ export CPLUS_INCLUDE_PATH=${CPLUS_INCLUDE_PATH}:`pwd`/include
|
||||||
|
$ export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:`pwd`
|
||||||
|
$ export LIBRARY_PATH=${LIBRARY_PATH}:`pwd`
|
||||||
|
|
||||||
|
Building pyrocksdb
|
||||||
|
------------------
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ apt-get install python-virtualenv python-dev
|
||||||
|
$ virtualenv pyrocks_test
|
||||||
|
$ cd pyrocks_test
|
||||||
|
$ . bin/active
|
||||||
|
$ pip install Cython
|
||||||
|
$ pip install .....
|
168
docs/tutorial/index.rst
Normal file
168
docs/tutorial/index.rst
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
Basic Usage of pyrocksdb
|
||||||
|
************************
|
||||||
|
|
||||||
|
Open
|
||||||
|
====
|
||||||
|
|
||||||
|
The most basic open call is ::
|
||||||
|
|
||||||
|
import rocksdb
|
||||||
|
|
||||||
|
db = rocksdb.DB("test.db", rocksdb.Options(create_if_missing=True))
|
||||||
|
|
||||||
|
A more production ready open can look like this ::
|
||||||
|
|
||||||
|
import rocksdb
|
||||||
|
|
||||||
|
opts = rocksdb.Options()
|
||||||
|
opts.create_if_missing = True
|
||||||
|
opts.max_open_files = 300000
|
||||||
|
opts.write_buffer_size = 67108864
|
||||||
|
opts.max_write_buffer_number = 3
|
||||||
|
opts.target_file_size_base = 67108864
|
||||||
|
opts.filter_policy = rocksdb.BloomFilterPolicy(10)
|
||||||
|
opts.block_cache = rocksdb.LRUCache(2 * (1024 ** 3))
|
||||||
|
opts.block_cache_compressed = rocksdb.LRUCache(500 * (1024 ** 2))
|
||||||
|
|
||||||
|
db = rocksdb.DB("test.db", opts)
|
||||||
|
|
||||||
|
It assings a cache of 2.5G, uses a bloom filter for faster lookups and keeps
|
||||||
|
more data (64 MB) in memory before writting a .sst file
|
||||||
|
|
||||||
|
Access
|
||||||
|
======
|
||||||
|
|
||||||
|
Store, Get, Delete is straight forward ::
|
||||||
|
|
||||||
|
# Store
|
||||||
|
db.put("key", "value")
|
||||||
|
|
||||||
|
# Get
|
||||||
|
db.get("key")
|
||||||
|
|
||||||
|
# Delete
|
||||||
|
db.delete("key")
|
||||||
|
|
||||||
|
It is also possible to gather modifications and
|
||||||
|
apply them in a single operation ::
|
||||||
|
|
||||||
|
batch = rocksdb.WriteBatch()
|
||||||
|
batch.put("key", "v1")
|
||||||
|
batch.delete("key")
|
||||||
|
batch.put("key", "v2")
|
||||||
|
batch.put("key", "v3")
|
||||||
|
|
||||||
|
db.write(batch)
|
||||||
|
|
||||||
|
Fetch of multiple values at once ::
|
||||||
|
|
||||||
|
db.put("key1", "v1")
|
||||||
|
db.put("key2", "v2")
|
||||||
|
|
||||||
|
ret = db.multi_get(["key1", "key2", "key3"])
|
||||||
|
|
||||||
|
# prints "v1"
|
||||||
|
print ret["key1"]
|
||||||
|
|
||||||
|
# prints None
|
||||||
|
print ret["key3"]
|
||||||
|
|
||||||
|
Iteration
|
||||||
|
=========
|
||||||
|
|
||||||
|
Iterators behave slightly different than expected. Per default they are not
|
||||||
|
valid. So you have to call one of its seek methods first ::
|
||||||
|
|
||||||
|
db.put("key1", "v1")
|
||||||
|
db.put("key2", "v2")
|
||||||
|
db.put("key3", "v3")
|
||||||
|
|
||||||
|
it = db.iterkeys()
|
||||||
|
it.seek_to_first()
|
||||||
|
|
||||||
|
# prints ['key1', 'key2', 'key3']
|
||||||
|
print list(it)
|
||||||
|
|
||||||
|
it.seek_to_last()
|
||||||
|
# prints ['key3']
|
||||||
|
print list(it)
|
||||||
|
|
||||||
|
it.seek('key2')
|
||||||
|
# prints ['key2', 'key3']
|
||||||
|
print list(it)
|
||||||
|
|
||||||
|
There are also methods to iterate over values/items ::
|
||||||
|
|
||||||
|
it = db.itervalues()
|
||||||
|
it.seek_to_first()
|
||||||
|
|
||||||
|
# prints ['v1', 'v2', 'v3']
|
||||||
|
print list(it)
|
||||||
|
|
||||||
|
it = db.iteritems()
|
||||||
|
it.seek_to_first()
|
||||||
|
|
||||||
|
# prints [('key1', 'v1'), ('key2, 'v2'), ('key3', 'v3')]
|
||||||
|
print list(it)
|
||||||
|
|
||||||
|
Reversed iteration ::
|
||||||
|
|
||||||
|
it = db.iteritems()
|
||||||
|
it.seek_to_last()
|
||||||
|
|
||||||
|
# prints [('key3', 'v3'), ('key2', 'v2'), ('key1', 'v1')]
|
||||||
|
print list(reversed(it))
|
||||||
|
|
||||||
|
|
||||||
|
Snapshots
|
||||||
|
=========
|
||||||
|
|
||||||
|
Snapshots are nice to get a consistent view on the database ::
|
||||||
|
|
||||||
|
self.db.put("a", "1")
|
||||||
|
self.db.put("b", "2")
|
||||||
|
|
||||||
|
snapshot = self.db.snapshot()
|
||||||
|
self.db.put("a", "2")
|
||||||
|
self.db.delete("b")
|
||||||
|
|
||||||
|
it = self.db.iteritems()
|
||||||
|
it.seek_to_first()
|
||||||
|
|
||||||
|
# prints {'a': '2'}
|
||||||
|
print dict(it)
|
||||||
|
|
||||||
|
it = self.db.iteritems(snapshot=snapshot)
|
||||||
|
it.seek_to_first()
|
||||||
|
|
||||||
|
# prints {'a': '1', 'b': '2'}
|
||||||
|
print dict(it)
|
||||||
|
|
||||||
|
|
||||||
|
MergeOperator
|
||||||
|
=============
|
||||||
|
|
||||||
|
Merge operators are useful for efficient read-modify-write operations.
|
||||||
|
|
||||||
|
The simple Associative merge ::
|
||||||
|
|
||||||
|
class AssocCounter(rocksdb.interfaces.AssociativeMergeOperator):
|
||||||
|
def merge(self, key, existing_value, value):
|
||||||
|
if existing_value:
|
||||||
|
return (True, str(int(existing_value) + int(value)))
|
||||||
|
return (True, value)
|
||||||
|
|
||||||
|
def name(self):
|
||||||
|
return 'AssocCounter'
|
||||||
|
|
||||||
|
|
||||||
|
opts = rocksdb.Options()
|
||||||
|
opts.create_if_missing = True
|
||||||
|
opts.merge_operator = AssocCounter()
|
||||||
|
db = rocksdb.DB('test.db', opts)
|
||||||
|
|
||||||
|
db.merge("a", "1")
|
||||||
|
db.merge("a", "1")
|
||||||
|
|
||||||
|
# prints '2'
|
||||||
|
print db.get("a")
|
1
rocksdb/__init__.py
Normal file
1
rocksdb/__init__.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
from _rocksdb import *
|
1245
rocksdb/_rocksdb.pyx
Normal file
1245
rocksdb/_rocksdb.pyx
Normal file
File diff suppressed because it is too large
Load diff
9
rocksdb/cache.pxd
Normal file
9
rocksdb/cache.pxd
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
from std_memory cimport shared_ptr
|
||||||
|
|
||||||
|
cdef extern from "rocksdb/cache.h" namespace "rocksdb":
|
||||||
|
cdef cppclass Cache:
|
||||||
|
pass
|
||||||
|
|
||||||
|
cdef extern shared_ptr[Cache] NewLRUCache(size_t)
|
||||||
|
cdef extern shared_ptr[Cache] NewLRUCache(size_t, int)
|
||||||
|
cdef extern shared_ptr[Cache] NewLRUCache(size_t, int, int)
|
14
rocksdb/comparator.pxd
Normal file
14
rocksdb/comparator.pxd
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
from libcpp.string cimport string
|
||||||
|
from slice_ cimport Slice
|
||||||
|
cdef extern from "rocksdb/comparator.h" namespace "rocksdb":
|
||||||
|
cdef cppclass Comparator:
|
||||||
|
const char* Name()
|
||||||
|
int Compare(const Slice&, const Slice&) const
|
||||||
|
|
||||||
|
cdef extern const Comparator* BytewiseComparator()
|
||||||
|
|
||||||
|
ctypedef int (*compare_func)(void*, const Slice&, const Slice&)
|
||||||
|
|
||||||
|
cdef extern from "cpp/comparator_wrapper.hpp" namespace "py_rocks":
|
||||||
|
cdef cppclass ComparatorWrapper:
|
||||||
|
ComparatorWrapper(string, void*, compare_func)
|
37
rocksdb/cpp/comparator_wrapper.hpp
Normal file
37
rocksdb/cpp/comparator_wrapper.hpp
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#include "rocksdb/comparator.h"
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using rocksdb::Comparator;
|
||||||
|
using rocksdb::Slice;
|
||||||
|
|
||||||
|
namespace py_rocks {
|
||||||
|
class ComparatorWrapper: public Comparator {
|
||||||
|
public:
|
||||||
|
typedef int (*compare_func)(void*, const Slice&, const Slice&);
|
||||||
|
|
||||||
|
ComparatorWrapper(
|
||||||
|
string name,
|
||||||
|
void* compare_context,
|
||||||
|
compare_func compare_callback):
|
||||||
|
name(name),
|
||||||
|
compare_context(compare_context),
|
||||||
|
compare_callback(compare_callback)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int Compare(const Slice& a, const Slice& b) const {
|
||||||
|
return this->compare_callback(this->compare_context, a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* Name() const {
|
||||||
|
return this->name.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FindShortestSeparator(string* start, const Slice& limit) const {}
|
||||||
|
void FindShortSuccessor(string* key) const {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
string name;
|
||||||
|
void* compare_context;
|
||||||
|
compare_func compare_callback;
|
||||||
|
};
|
||||||
|
}
|
62
rocksdb/cpp/filter_policy_wrapper.hpp
Normal file
62
rocksdb/cpp/filter_policy_wrapper.hpp
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
#include "rocksdb/filter_policy.h"
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using rocksdb::FilterPolicy;
|
||||||
|
using rocksdb::Slice;
|
||||||
|
|
||||||
|
namespace py_rocks {
|
||||||
|
class FilterPolicyWrapper: public FilterPolicy {
|
||||||
|
public:
|
||||||
|
typedef void (*create_filter_func)(
|
||||||
|
void* ctx,
|
||||||
|
const Slice* keys,
|
||||||
|
int n,
|
||||||
|
string* dst);
|
||||||
|
|
||||||
|
typedef bool (*key_may_match_func)(
|
||||||
|
void* ctx,
|
||||||
|
const Slice& key,
|
||||||
|
const Slice& filter);
|
||||||
|
|
||||||
|
FilterPolicyWrapper(
|
||||||
|
string name,
|
||||||
|
void* create_filter_context,
|
||||||
|
void* key_may_match_context,
|
||||||
|
create_filter_func create_filter_callback,
|
||||||
|
key_may_match_func key_may_match_callback):
|
||||||
|
name(name),
|
||||||
|
create_filter_context(create_filter_context),
|
||||||
|
key_may_match_context(key_may_match_context),
|
||||||
|
create_filter_callback(create_filter_callback),
|
||||||
|
key_may_match_callback(key_may_match_callback)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void
|
||||||
|
CreateFilter(const Slice* keys, int n, std::string* dst) const {
|
||||||
|
this->create_filter_callback(
|
||||||
|
this->create_filter_context,
|
||||||
|
keys,
|
||||||
|
n,
|
||||||
|
dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
KeyMayMatch(const Slice& key, const Slice& filter) const {
|
||||||
|
return this->key_may_match_callback(
|
||||||
|
this->key_may_match_context,
|
||||||
|
key,
|
||||||
|
filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* Name() const {
|
||||||
|
return this->name.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
string name;
|
||||||
|
void* create_filter_context;
|
||||||
|
void* key_may_match_context;
|
||||||
|
create_filter_func create_filter_callback;
|
||||||
|
key_may_match_func key_may_match_callback;
|
||||||
|
};
|
||||||
|
}
|
132
rocksdb/cpp/merge_operator_wrapper.hpp
Normal file
132
rocksdb/cpp/merge_operator_wrapper.hpp
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
#include "rocksdb/merge_operator.h"
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::deque;
|
||||||
|
using rocksdb::Slice;
|
||||||
|
using rocksdb::Logger;
|
||||||
|
using rocksdb::MergeOperator;
|
||||||
|
using rocksdb::AssociativeMergeOperator;
|
||||||
|
|
||||||
|
namespace py_rocks {
|
||||||
|
class AssociativeMergeOperatorWrapper: public AssociativeMergeOperator {
|
||||||
|
public:
|
||||||
|
typedef bool (*merge_func)(
|
||||||
|
void*,
|
||||||
|
const Slice& key,
|
||||||
|
const Slice* existing_value,
|
||||||
|
const Slice& value,
|
||||||
|
std::string* new_value,
|
||||||
|
Logger* logger);
|
||||||
|
|
||||||
|
|
||||||
|
AssociativeMergeOperatorWrapper(
|
||||||
|
string name,
|
||||||
|
void* merge_context,
|
||||||
|
merge_func merge_callback):
|
||||||
|
name(name),
|
||||||
|
merge_context(merge_context),
|
||||||
|
merge_callback(merge_callback)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool Merge(
|
||||||
|
const Slice& key,
|
||||||
|
const Slice* existing_value,
|
||||||
|
const Slice& value,
|
||||||
|
std::string* new_value,
|
||||||
|
Logger* logger) const
|
||||||
|
{
|
||||||
|
return this->merge_callback(
|
||||||
|
this->merge_context,
|
||||||
|
key,
|
||||||
|
existing_value,
|
||||||
|
value,
|
||||||
|
new_value,
|
||||||
|
logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* Name() const {
|
||||||
|
return this->name.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
string name;
|
||||||
|
void* merge_context;
|
||||||
|
merge_func merge_callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MergeOperatorWrapper: public MergeOperator {
|
||||||
|
public:
|
||||||
|
typedef bool (*full_merge_func)(
|
||||||
|
void* ctx,
|
||||||
|
const Slice& key,
|
||||||
|
const Slice* existing_value,
|
||||||
|
const deque<string>& operand_list,
|
||||||
|
string* new_value,
|
||||||
|
Logger* logger);
|
||||||
|
|
||||||
|
typedef bool (*partial_merge_func)(
|
||||||
|
void* ctx,
|
||||||
|
const Slice& key,
|
||||||
|
const Slice& left_op,
|
||||||
|
const Slice& right_op,
|
||||||
|
string* new_value,
|
||||||
|
Logger* logger);
|
||||||
|
|
||||||
|
MergeOperatorWrapper(
|
||||||
|
string name,
|
||||||
|
void* full_merge_context,
|
||||||
|
void* partial_merge_context,
|
||||||
|
full_merge_func full_merge_callback,
|
||||||
|
partial_merge_func partial_merge_callback):
|
||||||
|
name(name),
|
||||||
|
full_merge_context(full_merge_context),
|
||||||
|
partial_merge_context(partial_merge_context),
|
||||||
|
full_merge_callback(full_merge_callback),
|
||||||
|
partial_merge_callback(partial_merge_callback)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool FullMerge(
|
||||||
|
const Slice& key,
|
||||||
|
const Slice* existing_value,
|
||||||
|
const deque<string>& operand_list,
|
||||||
|
string* new_value,
|
||||||
|
Logger* logger) const
|
||||||
|
{
|
||||||
|
return this->full_merge_callback(
|
||||||
|
this->full_merge_context,
|
||||||
|
key,
|
||||||
|
existing_value,
|
||||||
|
operand_list,
|
||||||
|
new_value,
|
||||||
|
logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PartialMerge (
|
||||||
|
const Slice& key,
|
||||||
|
const Slice& left_operand,
|
||||||
|
const Slice& right_operand,
|
||||||
|
string* new_value,
|
||||||
|
Logger* logger) const
|
||||||
|
{
|
||||||
|
return this->partial_merge_callback(
|
||||||
|
this->partial_merge_context,
|
||||||
|
key,
|
||||||
|
left_operand,
|
||||||
|
right_operand,
|
||||||
|
new_value,
|
||||||
|
logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* Name() const {
|
||||||
|
return this->name.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
string name;
|
||||||
|
void* full_merge_context;
|
||||||
|
void* partial_merge_context;
|
||||||
|
full_merge_func full_merge_callback;
|
||||||
|
partial_merge_func partial_merge_callback;
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
8
rocksdb/cpp/utils.hpp
Normal file
8
rocksdb/cpp/utils.hpp
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace py_rocks {
|
||||||
|
template <typename T>
|
||||||
|
const T* vector_data(std::vector<T>& v) {
|
||||||
|
return v.data();
|
||||||
|
}
|
||||||
|
}
|
128
rocksdb/db.pxd
Normal file
128
rocksdb/db.pxd
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
cimport options
|
||||||
|
from libc.stdint cimport uint64_t
|
||||||
|
from status cimport Status
|
||||||
|
from libcpp cimport bool as cpp_bool
|
||||||
|
from libcpp.string cimport string
|
||||||
|
from libcpp.vector cimport vector
|
||||||
|
from slice_ cimport Slice
|
||||||
|
from snapshot cimport Snapshot
|
||||||
|
from iterator cimport Iterator
|
||||||
|
|
||||||
|
# TODO: Move this to a separate .pxd file
|
||||||
|
cdef extern from "rocksdb/write_batch.h" namespace "rocksdb":
|
||||||
|
cdef cppclass WriteBatch:
|
||||||
|
WriteBatch() except +
|
||||||
|
WriteBatch(string) except +
|
||||||
|
void Put(const Slice&, const Slice&)
|
||||||
|
void Merge(const Slice&, const Slice&)
|
||||||
|
void Delete(const Slice&)
|
||||||
|
void PutLogData(const Slice&)
|
||||||
|
void Clear()
|
||||||
|
string Data()
|
||||||
|
int Count() const
|
||||||
|
|
||||||
|
cdef extern from "rocksdb/db.h" namespace "rocksdb":
|
||||||
|
ctypedef uint64_t SequenceNumber
|
||||||
|
|
||||||
|
cdef struct LiveFileMetaData:
|
||||||
|
string name
|
||||||
|
int level
|
||||||
|
size_t size
|
||||||
|
string smallestkey
|
||||||
|
string largestkey
|
||||||
|
SequenceNumber smallest_seqno
|
||||||
|
SequenceNumber largest_seqno
|
||||||
|
|
||||||
|
cdef cppclass Range:
|
||||||
|
Range(const Slice&, const Slice&)
|
||||||
|
|
||||||
|
cdef cppclass DB:
|
||||||
|
Status Put(
|
||||||
|
const options.WriteOptions&,
|
||||||
|
const Slice&,
|
||||||
|
const Slice&)
|
||||||
|
|
||||||
|
Status Delete(
|
||||||
|
const options.WriteOptions&,
|
||||||
|
const Slice&)
|
||||||
|
|
||||||
|
Status Merge(
|
||||||
|
const options.WriteOptions&,
|
||||||
|
const Slice&,
|
||||||
|
const Slice&)
|
||||||
|
|
||||||
|
Status Write(
|
||||||
|
const options.WriteOptions&,
|
||||||
|
WriteBatch*)
|
||||||
|
|
||||||
|
Status Get(
|
||||||
|
const options.ReadOptions&,
|
||||||
|
const Slice&,
|
||||||
|
string*)
|
||||||
|
|
||||||
|
vector[Status] MultiGet(
|
||||||
|
const options.ReadOptions&,
|
||||||
|
const vector[Slice]&,
|
||||||
|
vector[string]*)
|
||||||
|
|
||||||
|
cpp_bool KeyMayExist(
|
||||||
|
const options.ReadOptions&,
|
||||||
|
Slice&,
|
||||||
|
string*,
|
||||||
|
cpp_bool*)
|
||||||
|
|
||||||
|
cpp_bool KeyMayExist(
|
||||||
|
const options.ReadOptions&,
|
||||||
|
Slice&,
|
||||||
|
string*)
|
||||||
|
|
||||||
|
Iterator* NewIterator(
|
||||||
|
const options.ReadOptions&)
|
||||||
|
|
||||||
|
const Snapshot* GetSnapshot()
|
||||||
|
|
||||||
|
void ReleaseSnapshot(const Snapshot*)
|
||||||
|
|
||||||
|
cpp_bool GetProperty(
|
||||||
|
const Slice&,
|
||||||
|
string*)
|
||||||
|
|
||||||
|
void GetApproximateSizes(
|
||||||
|
const Range*
|
||||||
|
int,
|
||||||
|
uint64_t*)
|
||||||
|
|
||||||
|
void CompactRange(
|
||||||
|
const Slice*,
|
||||||
|
const Slice*,
|
||||||
|
bool,
|
||||||
|
int)
|
||||||
|
|
||||||
|
int NumberLevels()
|
||||||
|
int MaxMemCompactionLevel()
|
||||||
|
int Level0StopWriteTrigger()
|
||||||
|
const string& GetName() const
|
||||||
|
Status Flush(const options.FlushOptions&)
|
||||||
|
Status DisableFileDeletions()
|
||||||
|
Status EnableFileDeletions()
|
||||||
|
|
||||||
|
# TODO: Status GetSortedWalFiles(VectorLogPtr& files)
|
||||||
|
# TODO: SequenceNumber GetLatestSequenceNumber()
|
||||||
|
# TODO: Status GetUpdatesSince(
|
||||||
|
# SequenceNumber seq_number,
|
||||||
|
# unique_ptr[TransactionLogIterator]*)
|
||||||
|
|
||||||
|
Status DeleteFile(string)
|
||||||
|
void GetLiveFilesMetaData(vector[LiveFileMetaData]*)
|
||||||
|
|
||||||
|
|
||||||
|
cdef Status DB_Open "rocksdb::DB::Open"(
|
||||||
|
const options.Options&,
|
||||||
|
const string&,
|
||||||
|
DB**)
|
||||||
|
|
||||||
|
cdef Status DB_OpenForReadOnly "rocksdb::DB::OpenForReadOnly"(
|
||||||
|
const options.Options&,
|
||||||
|
const string&,
|
||||||
|
DB**,
|
||||||
|
cpp_bool)
|
20
rocksdb/errors.py
Normal file
20
rocksdb/errors.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
class NotFound(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Corruption(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class NotSupported(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class InvalidArgument(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class RocksIOError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class MergeInProgress(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Incomplete(Exception):
|
||||||
|
pass
|
23
rocksdb/filter_policy.pxd
Normal file
23
rocksdb/filter_policy.pxd
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
from libcpp cimport bool as cpp_bool
|
||||||
|
from libcpp.string cimport string
|
||||||
|
from slice_ cimport Slice
|
||||||
|
|
||||||
|
cdef extern from "rocksdb/filter_policy.h" namespace "rocksdb":
|
||||||
|
cdef cppclass FilterPolicy:
|
||||||
|
void CreateFilter(const Slice*, int, string*) const
|
||||||
|
cpp_bool KeyMayMatch(const Slice&, const Slice&) const
|
||||||
|
const char* Name() const
|
||||||
|
|
||||||
|
cdef extern const FilterPolicy* NewBloomFilterPolicy(int)
|
||||||
|
|
||||||
|
ctypedef void (*create_filter_func)(void*, const Slice*, int, string*)
|
||||||
|
ctypedef cpp_bool (*key_may_match_func)(void*, const Slice&, const Slice&)
|
||||||
|
|
||||||
|
cdef extern from "cpp/filter_policy_wrapper.hpp" namespace "py_rocks":
|
||||||
|
cdef cppclass FilterPolicyWrapper:
|
||||||
|
FilterPolicyWrapper(
|
||||||
|
string,
|
||||||
|
void*,
|
||||||
|
void*,
|
||||||
|
create_filter_func,
|
||||||
|
key_may_match_func)
|
58
rocksdb/interfaces.py
Normal file
58
rocksdb/interfaces.py
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
from abc import ABCMeta
|
||||||
|
from abc import abstractmethod
|
||||||
|
|
||||||
|
|
||||||
|
class Comparator:
|
||||||
|
__metaclass__ = ABCMeta
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def compare(self, a, b):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def name(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class AssociativeMergeOperator:
|
||||||
|
__metaclass__ = ABCMeta
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def merge(self, key, existing_value, value):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def name(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class MergeOperator:
|
||||||
|
__metaclass__ = ABCMeta
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def full_merge(self, key, existing_value, operand_list):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def partial_merge(self, key, left_operand, right_operand):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def name(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class FilterPolicy:
|
||||||
|
__metaclass__ = ABCMeta
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def name(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def create_filter(self, keys):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def key_may_match(self, key, filter_):
|
||||||
|
pass
|
15
rocksdb/iterator.pxd
Normal file
15
rocksdb/iterator.pxd
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
from libcpp cimport bool as cpp_bool
|
||||||
|
from slice_ cimport Slice
|
||||||
|
from status cimport Status
|
||||||
|
|
||||||
|
cdef extern from "rocksdb/iterator.h" namespace "rocksdb":
|
||||||
|
cdef cppclass Iterator:
|
||||||
|
cpp_bool Valid() const
|
||||||
|
void SeekToFirst()
|
||||||
|
void SeekToLast()
|
||||||
|
void Seek(const Slice&)
|
||||||
|
void Next()
|
||||||
|
void Prev()
|
||||||
|
Slice key() const
|
||||||
|
Slice value() const
|
||||||
|
Status status() const
|
5
rocksdb/logger.pxd
Normal file
5
rocksdb/logger.pxd
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
cdef extern from "rocksdb/env.h" namespace "rocksdb":
|
||||||
|
cdef cppclass Logger:
|
||||||
|
pass
|
||||||
|
|
||||||
|
void Log(Logger*, const char*, ...)
|
45
rocksdb/merge_operator.pxd
Normal file
45
rocksdb/merge_operator.pxd
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
from libcpp.string cimport string
|
||||||
|
from libcpp cimport bool as cpp_bool
|
||||||
|
from libcpp.deque cimport deque
|
||||||
|
from slice_ cimport Slice
|
||||||
|
from logger cimport Logger
|
||||||
|
|
||||||
|
cdef extern from "rocksdb/merge_operator.h" namespace "rocksdb":
|
||||||
|
cdef cppclass MergeOperator:
|
||||||
|
pass
|
||||||
|
|
||||||
|
ctypedef cpp_bool (*merge_func)(
|
||||||
|
void*,
|
||||||
|
const Slice&,
|
||||||
|
const Slice*,
|
||||||
|
const Slice&,
|
||||||
|
string*,
|
||||||
|
Logger*)
|
||||||
|
|
||||||
|
ctypedef cpp_bool (*full_merge_func)(
|
||||||
|
void* ctx,
|
||||||
|
const Slice& key,
|
||||||
|
const Slice* existing_value,
|
||||||
|
const deque[string]& operand_list,
|
||||||
|
string* new_value,
|
||||||
|
Logger* logger)
|
||||||
|
|
||||||
|
ctypedef cpp_bool (*partial_merge_func)(
|
||||||
|
void* ctx,
|
||||||
|
const Slice& key,
|
||||||
|
const Slice& left_op,
|
||||||
|
const Slice& right_op,
|
||||||
|
string* new_value,
|
||||||
|
Logger* logger)
|
||||||
|
|
||||||
|
cdef extern from "cpp/merge_operator_wrapper.hpp" namespace "py_rocks":
|
||||||
|
cdef cppclass AssociativeMergeOperatorWrapper:
|
||||||
|
AssociativeMergeOperatorWrapper(string, void*, merge_func)
|
||||||
|
|
||||||
|
cdef cppclass MergeOperatorWrapper:
|
||||||
|
MergeOperatorWrapper(
|
||||||
|
string,
|
||||||
|
void*,
|
||||||
|
void*,
|
||||||
|
full_merge_func,
|
||||||
|
partial_merge_func)
|
123
rocksdb/options.pxd
Normal file
123
rocksdb/options.pxd
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
from libcpp cimport bool as cpp_bool
|
||||||
|
from libcpp.string cimport string
|
||||||
|
from libcpp.vector cimport vector
|
||||||
|
from libc.stdint cimport uint64_t
|
||||||
|
from std_memory cimport shared_ptr
|
||||||
|
from comparator cimport Comparator
|
||||||
|
from merge_operator cimport MergeOperator
|
||||||
|
from filter_policy cimport FilterPolicy
|
||||||
|
from cache cimport Cache
|
||||||
|
from logger cimport Logger
|
||||||
|
from slice_ cimport Slice
|
||||||
|
from snapshot cimport Snapshot
|
||||||
|
|
||||||
|
cdef extern from "rocksdb/options.h" namespace "rocksdb":
|
||||||
|
ctypedef enum CompressionType:
|
||||||
|
kNoCompression
|
||||||
|
kSnappyCompression
|
||||||
|
kZlibCompression
|
||||||
|
kBZip2Compression
|
||||||
|
|
||||||
|
ctypedef enum ReadTier:
|
||||||
|
kReadAllTier
|
||||||
|
kBlockCacheTier
|
||||||
|
|
||||||
|
cdef cppclass Options:
|
||||||
|
const Comparator* comparator
|
||||||
|
shared_ptr[MergeOperator] merge_operator
|
||||||
|
const FilterPolicy* filter_policy
|
||||||
|
# TODO: compaction_filter
|
||||||
|
# TODO: compaction_filter_factory
|
||||||
|
cpp_bool create_if_missing
|
||||||
|
cpp_bool error_if_exists
|
||||||
|
cpp_bool paranoid_checks
|
||||||
|
# TODO: env
|
||||||
|
# TODO: info_log
|
||||||
|
size_t write_buffer_size
|
||||||
|
int max_write_buffer_number
|
||||||
|
int min_write_buffer_number_to_merge
|
||||||
|
int max_open_files
|
||||||
|
shared_ptr[Cache] block_cache
|
||||||
|
shared_ptr[Cache] block_cache_compressed
|
||||||
|
size_t block_size
|
||||||
|
int block_restart_interval
|
||||||
|
CompressionType compression
|
||||||
|
# TODO: compression_per_level
|
||||||
|
# TODO: compression_opts
|
||||||
|
# TODO: prefix_extractor
|
||||||
|
cpp_bool whole_key_filtering
|
||||||
|
int num_levels
|
||||||
|
int level0_file_num_compaction_trigger
|
||||||
|
int level0_slowdown_writes_trigger
|
||||||
|
int level0_stop_writes_trigger
|
||||||
|
int max_mem_compaction_level
|
||||||
|
int target_file_size_base
|
||||||
|
int target_file_size_multiplier
|
||||||
|
uint64_t max_bytes_for_level_base
|
||||||
|
int max_bytes_for_level_multiplier
|
||||||
|
vector[int] max_bytes_for_level_multiplier_additional
|
||||||
|
int expanded_compaction_factor
|
||||||
|
int source_compaction_factor
|
||||||
|
int max_grandparent_overlap_factor
|
||||||
|
# TODO: statistics
|
||||||
|
cpp_bool disableDataSync
|
||||||
|
cpp_bool use_fsync
|
||||||
|
int db_stats_log_interval
|
||||||
|
string db_log_dir
|
||||||
|
string wal_dir
|
||||||
|
cpp_bool disable_seek_compaction
|
||||||
|
uint64_t delete_obsolete_files_period_micros
|
||||||
|
int max_background_compactions
|
||||||
|
int max_background_flushes
|
||||||
|
size_t max_log_file_size
|
||||||
|
size_t log_file_time_to_roll
|
||||||
|
size_t keep_log_file_num
|
||||||
|
double soft_rate_limit
|
||||||
|
double hard_rate_limit
|
||||||
|
unsigned int rate_limit_delay_max_milliseconds
|
||||||
|
uint64_t max_manifest_file_size
|
||||||
|
cpp_bool no_block_cache
|
||||||
|
int table_cache_numshardbits
|
||||||
|
int table_cache_remove_scan_count_limit
|
||||||
|
size_t arena_block_size
|
||||||
|
# TODO: PrepareForBulkLoad()
|
||||||
|
cpp_bool disable_auto_compactions
|
||||||
|
uint64_t WAL_ttl_seconds
|
||||||
|
uint64_t WAL_size_limit_MB
|
||||||
|
size_t manifest_preallocation_size
|
||||||
|
cpp_bool purge_redundant_kvs_while_flush
|
||||||
|
cpp_bool allow_os_buffer
|
||||||
|
cpp_bool allow_mmap_reads
|
||||||
|
cpp_bool allow_mmap_writes
|
||||||
|
cpp_bool is_fd_close_on_exec
|
||||||
|
cpp_bool skip_log_error_on_recovery
|
||||||
|
unsigned int stats_dump_period_sec
|
||||||
|
int block_size_deviation
|
||||||
|
cpp_bool advise_random_on_open
|
||||||
|
# TODO: enum { NONE, NORMAL, SEQUENTIAL, WILLNEED } access_hint_on_compaction_start
|
||||||
|
cpp_bool use_adaptive_mutex
|
||||||
|
uint64_t bytes_per_sync
|
||||||
|
# TODO: CompactionStyle compaction_style
|
||||||
|
# TODO: CompactionOptionsUniversal compaction_options_universal
|
||||||
|
cpp_bool filter_deletes
|
||||||
|
uint64_t max_sequential_skip_in_iterations
|
||||||
|
# TODO: memtable_factory
|
||||||
|
# TODO: table_factory
|
||||||
|
# TODO: table_properties_collectors
|
||||||
|
cpp_bool inplace_update_support
|
||||||
|
size_t inplace_update_num_locks
|
||||||
|
|
||||||
|
cdef cppclass WriteOptions:
|
||||||
|
cpp_bool sync
|
||||||
|
cpp_bool disableWAL
|
||||||
|
|
||||||
|
cdef cppclass ReadOptions:
|
||||||
|
cpp_bool verify_checksums
|
||||||
|
cpp_bool fill_cache
|
||||||
|
cpp_bool prefix_seek
|
||||||
|
const Slice* prefix
|
||||||
|
const Snapshot* snapshot
|
||||||
|
ReadTier read_tier
|
||||||
|
|
||||||
|
cdef cppclass FlushOptions:
|
||||||
|
cpp_bool wait
|
29
rocksdb/slice_.pxd
Normal file
29
rocksdb/slice_.pxd
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
from libcpp.string cimport string
|
||||||
|
from libcpp cimport bool as cpp_bool
|
||||||
|
from cpython.string cimport PyString_Size
|
||||||
|
from cpython.string cimport PyString_AsString
|
||||||
|
from cpython.string cimport PyString_FromStringAndSize
|
||||||
|
|
||||||
|
cdef extern from "rocksdb/slice.h" namespace "rocksdb":
|
||||||
|
cdef cppclass Slice:
|
||||||
|
Slice()
|
||||||
|
Slice(const char*, size_t)
|
||||||
|
Slice(const string&)
|
||||||
|
Slice(const char*)
|
||||||
|
|
||||||
|
const char* data()
|
||||||
|
size_t size()
|
||||||
|
cpp_bool empty()
|
||||||
|
char operator[](int)
|
||||||
|
void clear()
|
||||||
|
void remove_prefix(size_t)
|
||||||
|
string ToString()
|
||||||
|
string ToString(cpp_bool)
|
||||||
|
int compare(const Slice&)
|
||||||
|
cpp_bool starts_with(const Slice&)
|
||||||
|
|
||||||
|
cdef inline Slice str_to_slice(str ob):
|
||||||
|
return Slice(PyString_AsString(ob), PyString_Size(ob))
|
||||||
|
|
||||||
|
cdef inline str slice_to_str(Slice ob):
|
||||||
|
return PyString_FromStringAndSize(ob.data(), ob.size())
|
3
rocksdb/snapshot.pxd
Normal file
3
rocksdb/snapshot.pxd
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
cdef extern from "rocksdb/db.h" namespace "rocksdb":
|
||||||
|
cdef cppclass Snapshot:
|
||||||
|
pass
|
15
rocksdb/status.pxd
Normal file
15
rocksdb/status.pxd
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
from libcpp cimport bool as cpp_bool
|
||||||
|
from libcpp.string cimport string
|
||||||
|
|
||||||
|
cdef extern from "rocksdb/status.h" namespace "rocksdb":
|
||||||
|
cdef cppclass Status:
|
||||||
|
Status()
|
||||||
|
cpp_bool ok() const
|
||||||
|
cpp_bool IsNotFound() const
|
||||||
|
cpp_bool IsCorruption() const
|
||||||
|
cpp_bool IsNotSupported() const
|
||||||
|
cpp_bool IsInvalidArgument() const
|
||||||
|
cpp_bool IsIOError() const
|
||||||
|
cpp_bool IsMergeInProgress() const
|
||||||
|
cpp_bool IsIncomplete() const
|
||||||
|
string ToString() const
|
7
rocksdb/std_memory.pxd
Normal file
7
rocksdb/std_memory.pxd
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
cdef extern from "<memory>" namespace "std":
|
||||||
|
cdef cppclass shared_ptr[T]:
|
||||||
|
shared_ptr()
|
||||||
|
shared_ptr(T*)
|
||||||
|
void reset()
|
||||||
|
void reset(T*)
|
||||||
|
T* get()
|
0
rocksdb/tests/__init__.py
Normal file
0
rocksdb/tests/__init__.py
Normal file
256
rocksdb/tests/test_db.py
Normal file
256
rocksdb/tests/test_db.py
Normal file
|
@ -0,0 +1,256 @@
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import gc
|
||||||
|
import unittest
|
||||||
|
import rocksdb
|
||||||
|
|
||||||
|
|
||||||
|
class TestHelper(object):
|
||||||
|
def _clean(self):
|
||||||
|
if os.path.exists('/tmp/test'):
|
||||||
|
shutil.rmtree("/tmp/test")
|
||||||
|
|
||||||
|
def _close_db(self):
|
||||||
|
del self.db
|
||||||
|
gc.collect()
|
||||||
|
|
||||||
|
|
||||||
|
class TestDB(unittest.TestCase, TestHelper):
|
||||||
|
def setUp(self):
|
||||||
|
opts = rocksdb.Options(create_if_missing=True)
|
||||||
|
self._clean()
|
||||||
|
self.db = rocksdb.DB("/tmp/test", opts)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
self._close_db()
|
||||||
|
|
||||||
|
def test_get_none(self):
|
||||||
|
self.assertIsNone(self.db.get('xxx'))
|
||||||
|
|
||||||
|
def test_put_get(self):
|
||||||
|
self.db.put("a", "b")
|
||||||
|
self.assertEqual("b", self.db.get("a"))
|
||||||
|
|
||||||
|
def test_multi_get(self):
|
||||||
|
self.db.put("a", "1")
|
||||||
|
self.db.put("b", "2")
|
||||||
|
self.db.put("c", "3")
|
||||||
|
|
||||||
|
ret = self.db.multi_get(['a', 'b', 'c'])
|
||||||
|
ref = {'a': '1', 'c': '3', 'b': '2'}
|
||||||
|
self.assertEqual(ref, ret)
|
||||||
|
|
||||||
|
def test_delete(self):
|
||||||
|
self.db.put("a", "b")
|
||||||
|
self.assertEqual("b", self.db.get("a"))
|
||||||
|
self.db.delete("a")
|
||||||
|
self.assertIsNone(self.db.get("a"))
|
||||||
|
|
||||||
|
def test_write_batch(self):
|
||||||
|
batch = rocksdb.WriteBatch()
|
||||||
|
batch.put("key", "v1")
|
||||||
|
batch.delete("key")
|
||||||
|
batch.put("key", "v2")
|
||||||
|
batch.put("key", "v3")
|
||||||
|
batch.put("a", "b")
|
||||||
|
|
||||||
|
self.db.write(batch)
|
||||||
|
ref = {'a': 'b', 'key': 'v3'}
|
||||||
|
ret = self.db.multi_get(['key', 'a'])
|
||||||
|
self.assertEqual(ref, ret)
|
||||||
|
|
||||||
|
def test_key_may_exists(self):
|
||||||
|
self.db.put("a", '1')
|
||||||
|
|
||||||
|
self.assertEqual((False, None), self.db.key_may_exist("x"))
|
||||||
|
self.assertEqual((False, None), self.db.key_may_exist('x', True))
|
||||||
|
self.assertEqual((True, None), self.db.key_may_exist('a'))
|
||||||
|
self.assertEqual((True, '1'), self.db.key_may_exist('a', True))
|
||||||
|
|
||||||
|
def test_iter_keys(self):
|
||||||
|
for x in range(300):
|
||||||
|
self.db.put(str(x), str(x))
|
||||||
|
|
||||||
|
it = self.db.iterkeys()
|
||||||
|
|
||||||
|
self.assertEqual([], list(it))
|
||||||
|
|
||||||
|
it.seek_to_last()
|
||||||
|
self.assertEqual(['99'], list(it))
|
||||||
|
|
||||||
|
ref = sorted([str(x) for x in range(300)])
|
||||||
|
it.seek_to_first()
|
||||||
|
self.assertEqual(ref, list(it))
|
||||||
|
|
||||||
|
it.seek('90')
|
||||||
|
ref = ['90', '91', '92', '93', '94', '95', '96', '97', '98', '99']
|
||||||
|
self.assertEqual(ref, list(it))
|
||||||
|
|
||||||
|
def test_iter_values(self):
|
||||||
|
for x in range(300):
|
||||||
|
self.db.put(str(x), str(x * 1000))
|
||||||
|
|
||||||
|
it = self.db.itervalues()
|
||||||
|
|
||||||
|
self.assertEqual([], list(it))
|
||||||
|
|
||||||
|
it.seek_to_last()
|
||||||
|
self.assertEqual(['99000'], list(it))
|
||||||
|
|
||||||
|
ref = sorted([str(x) for x in range(300)])
|
||||||
|
ref = [str(int(x) * 1000) for x in ref]
|
||||||
|
it.seek_to_first()
|
||||||
|
self.assertEqual(ref, list(it))
|
||||||
|
|
||||||
|
it.seek('90')
|
||||||
|
ref = [str(x * 1000) for x in range(90, 100)]
|
||||||
|
self.assertEqual(ref, list(it))
|
||||||
|
|
||||||
|
def test_iter_items(self):
|
||||||
|
for x in range(300):
|
||||||
|
self.db.put(str(x), str(x * 1000))
|
||||||
|
|
||||||
|
it = self.db.iteritems()
|
||||||
|
|
||||||
|
self.assertEqual([], list(it))
|
||||||
|
|
||||||
|
it.seek_to_last()
|
||||||
|
self.assertEqual([('99', '99000')], list(it))
|
||||||
|
|
||||||
|
ref = sorted([str(x) for x in range(300)])
|
||||||
|
ref = [(x, str(int(x) * 1000)) for x in ref]
|
||||||
|
it.seek_to_first()
|
||||||
|
self.assertEqual(ref, list(it))
|
||||||
|
|
||||||
|
it.seek('90')
|
||||||
|
ref = [(str(x), str(x * 1000)) for x in range(90, 100)]
|
||||||
|
self.assertEqual(ref, list(it))
|
||||||
|
|
||||||
|
def test_reverse_iter(self):
|
||||||
|
for x in range(100):
|
||||||
|
self.db.put(str(x), str(x * 1000))
|
||||||
|
|
||||||
|
it = self.db.iteritems()
|
||||||
|
it.seek_to_last()
|
||||||
|
|
||||||
|
ref = reversed(sorted([str(x) for x in range(100)]))
|
||||||
|
ref = [(x, str(int(x) * 1000)) for x in ref]
|
||||||
|
|
||||||
|
self.assertEqual(ref, list(reversed(it)))
|
||||||
|
|
||||||
|
def test_snapshot(self):
|
||||||
|
self.db.put("a", "1")
|
||||||
|
self.db.put("b", "2")
|
||||||
|
|
||||||
|
snapshot = self.db.snapshot()
|
||||||
|
self.db.put("a", "2")
|
||||||
|
self.db.delete("b")
|
||||||
|
|
||||||
|
it = self.db.iteritems()
|
||||||
|
it.seek_to_first()
|
||||||
|
self.assertEqual({'a': '2'}, dict(it))
|
||||||
|
|
||||||
|
it = self.db.iteritems(snapshot=snapshot)
|
||||||
|
it.seek_to_first()
|
||||||
|
self.assertEqual({'a': '1', 'b': '2'}, dict(it))
|
||||||
|
|
||||||
|
def test_get_property(self):
|
||||||
|
for x in range(300):
|
||||||
|
self.db.put(str(x), str(x))
|
||||||
|
|
||||||
|
self.assertIsNotNone(self.db.get_property('rocksdb.stats'))
|
||||||
|
self.assertIsNotNone(self.db.get_property('rocksdb.sstables'))
|
||||||
|
self.assertIsNotNone(self.db.get_property('rocksdb.num-files-at-level0'))
|
||||||
|
self.assertIsNone(self.db.get_property('does not exsits'))
|
||||||
|
|
||||||
|
|
||||||
|
class AssocCounter(rocksdb.interfaces.AssociativeMergeOperator):
|
||||||
|
def merge(self, key, existing_value, value):
|
||||||
|
if existing_value:
|
||||||
|
return (True, str(int(existing_value) + int(value)))
|
||||||
|
return (True, value)
|
||||||
|
|
||||||
|
def name(self):
|
||||||
|
return 'AssocCounter'
|
||||||
|
|
||||||
|
|
||||||
|
class TestAssocMerge(unittest.TestCase, TestHelper):
|
||||||
|
def setUp(self):
|
||||||
|
opts = rocksdb.Options()
|
||||||
|
opts.create_if_missing = True
|
||||||
|
opts.merge_operator = AssocCounter()
|
||||||
|
self._clean()
|
||||||
|
self.db = rocksdb.DB('/tmp/test', opts)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
self._close_db()
|
||||||
|
|
||||||
|
def test_merge(self):
|
||||||
|
for x in range(1000):
|
||||||
|
self.db.merge("a", str(x))
|
||||||
|
self.assertEqual(str(sum(range(1000))), self.db.get('a'))
|
||||||
|
|
||||||
|
|
||||||
|
class FullCounter(rocksdb.interfaces.MergeOperator):
|
||||||
|
def name(self):
|
||||||
|
return 'fullcounter'
|
||||||
|
|
||||||
|
def full_merge(self, key, existing_value, operand_list):
|
||||||
|
ret = sum([int(x) for x in operand_list])
|
||||||
|
if existing_value:
|
||||||
|
ret += int(existing_value)
|
||||||
|
|
||||||
|
return (True, str(ret))
|
||||||
|
|
||||||
|
def partial_merge(self, key, left, right):
|
||||||
|
return (True, str(int(left) + int(right)))
|
||||||
|
|
||||||
|
|
||||||
|
class TestFullMerge(unittest.TestCase, TestHelper):
|
||||||
|
def setUp(self):
|
||||||
|
opts = rocksdb.Options()
|
||||||
|
opts.create_if_missing = True
|
||||||
|
opts.merge_operator = FullCounter()
|
||||||
|
self._clean()
|
||||||
|
self.db = rocksdb.DB('/tmp/test', opts)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
self._close_db()
|
||||||
|
|
||||||
|
def test_merge(self):
|
||||||
|
for x in range(1000):
|
||||||
|
self.db.merge("a", str(x))
|
||||||
|
self.assertEqual(str(sum(range(1000))), self.db.get('a'))
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleComparator(rocksdb.interfaces.Comparator):
|
||||||
|
def name(self):
|
||||||
|
return 'mycompare'
|
||||||
|
|
||||||
|
def compare(self, a, b):
|
||||||
|
a = int(a)
|
||||||
|
b = int(b)
|
||||||
|
if a < b:
|
||||||
|
return -1
|
||||||
|
if a == b:
|
||||||
|
return 0
|
||||||
|
if a > b:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
class TestComparator(unittest.TestCase, TestHelper):
|
||||||
|
def setUp(self):
|
||||||
|
opts = rocksdb.Options()
|
||||||
|
opts.create_if_missing = True
|
||||||
|
opts.comparator = SimpleComparator()
|
||||||
|
self._clean()
|
||||||
|
self.db = rocksdb.DB('/tmp/test', opts)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
self._close_db()
|
||||||
|
|
||||||
|
def test_compare(self):
|
||||||
|
for x in range(1000):
|
||||||
|
self.db.put(str(x), str(x))
|
||||||
|
|
||||||
|
self.assertEqual('300', self.db.get('300'))
|
54
rocksdb/tests/test_options.py
Normal file
54
rocksdb/tests/test_options.py
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
import unittest
|
||||||
|
import rocksdb
|
||||||
|
|
||||||
|
class TestFilterPolicy(rocksdb.interfaces.FilterPolicy):
|
||||||
|
def create_filter(self, keys):
|
||||||
|
return 'nix'
|
||||||
|
|
||||||
|
def key_may_match(self, key, fil):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def name(self):
|
||||||
|
return 'testfilter'
|
||||||
|
|
||||||
|
class TestMergeOperator(rocksdb.interfaces.MergeOperator):
|
||||||
|
def full_merge(self, *args, **kwargs):
|
||||||
|
return (False, None)
|
||||||
|
|
||||||
|
def partial_merge(self, *args, **kwargs):
|
||||||
|
return (False, None)
|
||||||
|
|
||||||
|
def name(self):
|
||||||
|
return 'testmergeop'
|
||||||
|
|
||||||
|
class TestOptions(unittest.TestCase):
|
||||||
|
def test_simple(self):
|
||||||
|
opts = rocksdb.Options()
|
||||||
|
self.assertEqual(False, opts.paranoid_checks)
|
||||||
|
opts.paranoid_checks = True
|
||||||
|
self.assertEqual(True, opts.paranoid_checks)
|
||||||
|
|
||||||
|
self.assertIsNone(opts.filter_policy)
|
||||||
|
ob = TestFilterPolicy()
|
||||||
|
opts.filter_policy = ob
|
||||||
|
self.assertEqual(opts.filter_policy, ob)
|
||||||
|
|
||||||
|
self.assertIsNone(opts.merge_operator)
|
||||||
|
ob = TestMergeOperator()
|
||||||
|
opts.merge_operator = ob
|
||||||
|
self.assertEqual(opts.merge_operator, ob)
|
||||||
|
|
||||||
|
self.assertIsInstance(
|
||||||
|
opts.comparator,
|
||||||
|
rocksdb.BytewiseComparator)
|
||||||
|
|
||||||
|
self.assertEqual('snappy_compression', opts.compression)
|
||||||
|
opts.compression = rocksdb.CompressionType.no_compression
|
||||||
|
self.assertEqual('no_compression', opts.compression)
|
||||||
|
|
||||||
|
self.assertEqual(opts.block_size, 4096)
|
||||||
|
|
||||||
|
self.assertIsNone(opts.block_cache)
|
||||||
|
ob = rocksdb.LRUCache(100)
|
||||||
|
opts.block_cache = ob
|
||||||
|
self.assertEqual(ob, opts.block_cache)
|
39
setup.py
Normal file
39
setup.py
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
from setuptools import setup, find_packages
|
||||||
|
from distutils.extension import Extension
|
||||||
|
from Cython.Build import cythonize
|
||||||
|
|
||||||
|
extension_defaults = {
|
||||||
|
'extra_compile_args': [
|
||||||
|
'-std=gnu++11',
|
||||||
|
'-O3',
|
||||||
|
'-Wall',
|
||||||
|
'-Wextra',
|
||||||
|
'-Wconversion',
|
||||||
|
'-fno-strict-aliasing'
|
||||||
|
],
|
||||||
|
'language': 'c++',
|
||||||
|
'libraries': [
|
||||||
|
'bz2',
|
||||||
|
'z',
|
||||||
|
'rocksdb'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
mod1 = Extension(
|
||||||
|
'rocksdb._rocksdb',
|
||||||
|
['rocksdb/_rocksdb.pyx'],
|
||||||
|
**extension_defaults
|
||||||
|
)
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name="pyrocksdb",
|
||||||
|
install_requires=[
|
||||||
|
'setuptools',
|
||||||
|
'Cython',
|
||||||
|
],
|
||||||
|
package_dir={'rocksdb': 'rocksdb'},
|
||||||
|
packages=find_packages('.'),
|
||||||
|
ext_modules=cythonize([mod1]),
|
||||||
|
test_suite='rocksdb.tests',
|
||||||
|
include_package_data=True
|
||||||
|
)
|
Loading…
Reference in a new issue