├── .gitignore
├── .idea
├── .name
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── encodings.xml
├── misc.xml
└── modules.xml
├── .travis.yml
├── AUTHORS
├── CHANGELOG.md
├── LICENSE
├── Makefile
├── README.md
├── analysis_options.yaml
├── example
├── isolate.dart
└── main.dart
├── leveldb_dart.iml
├── lib
├── leveldb.cc
├── leveldb.dart
└── libleveldb.so
├── pubspec.yaml
└── test
└── leveldb_test.dart
/.gitignore:
--------------------------------------------------------------------------------
1 | .packages
2 | *~
3 | pubspec.lock
4 | .pub
5 | .idea/workspace.xml
6 | .idea/tasks.xml
7 | lib/*.o
8 | .idea/libraries/*.xml
9 | .idea/vcs.xml
10 | .idea/php.xml
11 | .idea/markdown-navigator.xml
12 | .idea/markdown-navigator/
13 | .dart_tool/
14 | .idea/inspectionProfiles/
15 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | leveldb_dart
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | Python 2.7.10 (/usr/bin/python2.7)
21 |
22 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: dart
2 |
3 | # By default the latest stable dart release is used.
4 | #dart:
5 | # Install the latest stable release
6 | #- stable
7 |
8 | # Run tests on precise and trusty. They have a different gcc abi.
9 | matrix:
10 | include:
11 | - os: linux
12 | dist: trusty
13 | - os: linux
14 | dist: precise
15 | - os: osx
16 |
17 | dart_task:
18 | - test: --platform vm
19 | - dartanalyzer: --fatal-warnings .
20 | - dartfmt
21 |
22 |
23 |
--------------------------------------------------------------------------------
/AUTHORS:
--------------------------------------------------------------------------------
1 | Adam Lofts
2 | Simon Kuang
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## 7.0.0
4 |
5 | Breaking changes:
6 |
7 | - Dart null safety
8 | - Use leveldb 1.2.3
9 | - OSX support dropped
10 |
11 | ## 6.0.2
12 |
13 | Non-breaking changes:
14 |
15 | - Link to stdc++. This seems to be required for Dart SDK >= 2.2.0
16 |
17 | ## 6.0.1
18 |
19 | Non-breaking changes:
20 |
21 | - Add OSX platform support
22 |
23 | ## 6.0.0
24 |
25 | Breaking changes:
26 | - Upgrade to dart2
27 |
28 | ## 5.0.1
29 |
30 | Non-breaking changes
31 |
32 | - Add @required annotation to keyEncoding and valueEncoding in LevelDB.open
33 | - Improve docs
34 |
35 | ## 5.0.0
36 |
37 | Breaking changes:
38 |
39 | - Remove `LevelEncoding` interface and use `dart:codec` directly. This better aligns the interface with
40 | the dart way of encoding and decoding and allows easily fusing new codecs.
41 | - Add new json.dart example to demonstrate encoding objects to the database (as JSON).
42 |
43 | ## 4.0.0
44 |
45 | Minor API update for [Sound Dart](https://www.dartlang.org/guides/language/sound-dart)
46 |
47 | Breaking changes:
48 | - The `keyEncoding` and `valueEncoding` parameters are now required when using the `LevelDB.open` function.
49 | When encoding utf8 keys and values `LevelDB.openUtf8` is the recommended constructor.
50 |
51 | ## 3.0.0
52 |
53 | Breaking changes:
54 |
55 | - Add generic parameters to `LevelDB` to improve type safety when using the API.
56 | Key/Value encoding parameters have been moved to the `LevelDB.open` function.
57 | - Minimum dart sdk version updated to `1.23.0`
58 |
59 | Non-breaking changes:
60 |
61 | - Upgrade to leveldb 1.20. This version is compatible with the previous on-disk format. See: https://github.com/google/leveldb/releases/tag/v1.20
62 | - Add `shared` parameter to `LevelDB.open`. This feature allows referencing
63 | the same underlying database from multiple isolates.
64 | - Add an example demonstrating how to use the `shared` parameter in muliple
65 | isolates.
66 |
67 | ## 2.0.3
68 |
69 | - Build leveldb with better compatibility.
70 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Adam Lofts
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 |
2 | # Users of this package should not need to run this makefile.
3 | #
4 |
5 | # First build a static leveldb lib.
6 | # The build script already does this but you need to add a couple of options to the static build.
7 | # Make the line look like:
8 | # OPT ?= -O2 -DNDEBUG -fPIC
9 |
10 | # The -fPIC enables linking the static lib into the object we will build.
11 |
12 | # Then set the source:
13 |
14 | LEVELDB_SOURCE=/home/adam/dev/fp3/dart/leveldb-1.23
15 | DART_SDK=/home/adam/dev/tools/dart-sdk-2.12.4
16 |
17 | LIBS=$(LEVELDB_SOURCE)/build/libleveldb.a
18 | # Select prod/debug args
19 | ARGS=-O2 -Wall
20 | # ARGS=-g -O0 -Wall -D_GLIBCXX_USE_CXX11_ABI=0
21 |
22 | UNAME_S := $(shell uname -s)
23 |
24 | ifeq ($(UNAME_S),Darwin)
25 | LIB_NAME = libleveldb.dylib
26 | ARGS_LINK = -dynamic -undefined dynamic_lookup
27 | endif
28 | ifeq ($(UNAME_S),Linux)
29 | LIB_NAME = libleveldb.so
30 | ARGS_LINK = -shared -Wl,-soname,$(LIB_NAME)
31 | endif
32 |
33 | all: lib/libleveldb.so
34 |
35 | lib/leveldb.o: lib/leveldb.cc
36 | g++ $(ARGS) -fPIC -I$(DART_SDK) -I$(LEVELDB_SOURCE)/include -DDART_SHARED_LIB -c lib/leveldb.cc -o lib/leveldb.o
37 |
38 | lib/libleveldb.so: lib/leveldb.o
39 | gcc $(ARGS) lib/leveldb.o $(ARGS_LINK) -o lib/$(LIB_NAME) $(LIBS) -lstdc++
40 |
41 | clean:
42 | rm -f lib/*.o lib/*.so lib/*.dylib
43 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | *Fast & simple storage - a Dart LevelDB wrapper*
2 |
3 |
4 |
5 |
6 |
7 | Introduction
8 | ------------
9 |
10 | **[LevelDB](https://github.com/google/leveldb)** is a simple key/value data store built by Google, inspired by BigTable. It's used in Google
11 | Chrome and many other products. LevelDB supports arbitrary byte arrays as both keys and values, singular *get*, *put* and *delete*
12 | operations, *batched put and delete*, bi-directional iterators and simple compression using the very fast
13 | [Snappy](http://google.github.io/snappy/) algorithm.
14 |
15 | **leveldb_dart** aims to expose the features of LevelDB in a **Dart-friendly way**.
16 |
17 | LevelDB stores entries **sorted lexicographically by keys**. This makes [LevelDB.getItems](https://www.dartdocs.org/documentation/leveldb/latest/leveldb/LevelDB/getItems.html) a very powerful query mechanism.
18 |
19 | Platform Support
20 | ----------------
21 |
22 | - [x] Modern 64-bit Linux platforms (e.g. Fedora 25, 26, Ubuntu 14.04, 15.10)
23 | - [x] Mac OS X
24 |
25 | Unsupported platforms:
26 |
27 | - [ ] Android (See [issue #12](https://github.com/adamlofts/leveldb_dart/issues/12))
28 | - [ ] Windows (Not supported in base library [issue #466](https://github.com/google/leveldb/issues/466))
29 |
30 | Basic usage
31 | -----------
32 |
33 | Add `leveldb` to your `pubspec.yaml` file.
34 |
35 | ```
36 | name: myproject
37 | dependencies:
38 | leveldb:
39 | ```
40 |
41 | Open a database and read/write some keys and values..
42 |
43 | ```
44 | import 'dart:async';
45 | import 'package:leveldb/leveldb.dart';
46 |
47 | Future main() async {
48 | LevelDB db = await LevelDB.openUtf8("/tmp/testdb");
49 | db.put("abc", "def");
50 | String value = db.get("abc");
51 | print("value is $value"); // value2 is def
52 | }
53 | ```
54 | Check out [example/main.dart](https://github.com/adamlofts/leveldb_dart/blob/master/example/main.dart) to see how to read, write and iterate over keys and values.
55 |
56 | Documentation
57 | -------------
58 |
59 | API Documentation is available at https://www.dartdocs.org/documentation/leveldb/latest/
60 |
61 | Isolates (Threads)
62 | ------------------
63 |
64 | *leveldb_dart* supports access to a database from multiple isolates by passing
65 | `shared: true` to the
66 | [LevelDB.open](https://www.dartdocs.org/documentation/leveldb/latest/leveldb/LevelDB/open.html) function. The `LevelDB` object
67 | returned by this function will share an underlying reference to the object in other isolates and changes will
68 | be visible between isolates.
69 |
70 | See [example/isolate.dart](https://github.com/adamlofts/leveldb_dart/blob/master/example/isolate.dart) for an example of using a database from multiple isolates (OS threads).
71 |
72 |
73 | Feature Support
74 | ---------------
75 |
76 | - [x] Read and write keys
77 | - [x] Forward iteration
78 | - [x] Multi-isolate
79 | - [ ] Backward iteration
80 | - [ ] Snapshots
81 | - [ ] Bulk get / put
82 |
83 |
84 | Custom Encoding and Decoding
85 | ----------------------------
86 |
87 | By default you can use `LevelDB.openUtf8` to open a database with `String` keys and values which are encoded in UTF8. The `dart:codec` library
88 | can be used to create databases with custom encodings. See [example/json.dart](https://github.com/adamlofts/leveldb_dart/blob/master/example/json.dart)
89 | for an example which stores dart objects to the database via JSON encoding.
90 |
91 |
92 |
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | analyzer:
2 | strong-mode:
3 | implicit-casts: false
4 | implicit-dynamic: false
5 | linter:
6 | rules:
7 | - always_declare_return_types
8 | - always_specify_types
9 | - annotate_overrides
10 | - avoid_as
11 | - avoid_empty_else
12 | - avoid_init_to_null
13 | - avoid_return_types_on_setters
14 | - await_only_futures
15 | - camel_case_types
16 | - cancel_subscriptions
17 | - close_sinks
18 | - comment_references
19 | - constant_identifier_names
20 | - control_flow_in_finally
21 | - empty_catches
22 | - empty_constructor_bodies
23 | - empty_statements
24 | - hash_and_equals
25 | - implementation_imports
26 | - iterable_contains_unrelated_type
27 | - library_names
28 | - library_prefixes
29 | - list_remove_unrelated_type
30 | - non_constant_identifier_names
31 | - one_member_abstracts
32 | - only_throw_errors
33 | - overridden_fields
34 | - package_api_docs
35 | - package_names
36 | - package_prefixed_library_names
37 | - prefer_is_not_empty
38 | - public_member_api_docs
39 | - slash_for_doc_comments
40 | - sort_unnamed_constructors_first
41 | - test_types_in_equals
42 | - throw_in_finally
43 | - type_annotate_public_apis
44 | - type_init_formals
45 | - unawaited_futures
46 | - unnecessary_getters_setters
47 | - unrelated_type_equality_checks
48 | - valid_regexps
--------------------------------------------------------------------------------
/example/isolate.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'dart:isolate';
3 |
4 | import 'package:leveldb/leveldb.dart';
5 |
6 | /// This example demonstrates how to access a database from multiple isolates.
7 | /// Isolates are implemented as os-threads in the dart vm so this allows you to
8 | /// use multiple cores. Access to the underlying level db from multiple isolates is safe.
9 | Future main() async {
10 | // Spawn some isolates. Each of these will write a key then read a key from the next thread.
11 | List runners = new Iterable.generate(5).map((int index) {
12 | return new Runner.spawn(index);
13 | }).toList();
14 |
15 | await Future.wait(runners.map((Runner r) => r.finish));
16 | }
17 |
18 | /// This method is called in different OS threads by the dart VM.
19 | Future run(int index) async {
20 | // Because shared: true is passed the DB returned by this method will reference the same
21 | // database.
22 | LevelDB db =
23 | await LevelDB.openUtf8("/tmp/testdb", shared: true);
24 |
25 | // Write our key to the db
26 | print("Thread $index write key $index -> $index");
27 | db.put("$index", "$index");
28 |
29 | // Sleep 1 second
30 | await new Future.delayed(const Duration(seconds: 1));
31 |
32 | // Now read the key from the next thread
33 | String nextKey = "${(index + 1) % 5}";
34 | print("Thread $index read key $nextKey -> ${db.get(nextKey)}");
35 | }
36 |
37 | /// Helper class to run an isolate and wait for it to finish.
38 | class Runner {
39 | final Completer _finish = new Completer();
40 | final RawReceivePort _finishPort = new RawReceivePort();
41 |
42 | /// Run an isolate.
43 | Runner.spawn(int index) {
44 | _finishPort.handler = (dynamic _) {
45 | _finish.complete();
46 | _finishPort.close();
47 | };
48 | Isolate.spawn(run, index, onExit: _finishPort.sendPort);
49 | }
50 |
51 | /// Future completed when the isolate exits normally.
52 | Future get finish => _finish.future;
53 | }
54 |
--------------------------------------------------------------------------------
/example/main.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'dart:typed_data';
3 |
4 | import 'package:leveldb/leveldb.dart';
5 |
6 | /// main example.
7 | Future main() async {
8 | // Open a database. It is created if it does not already exist. Only one process can
9 | // open a database at a time.
10 | LevelDB db = await LevelDB.openUtf8("/tmp/testdb");
11 |
12 | // By default keys and values are strings.
13 | db.put("abc", "def");
14 |
15 | // Now get the key
16 | String? value = db.get("abc");
17 | print("value is $value"); // value2 is def
18 |
19 | // Delete the key
20 | db.delete("abc");
21 |
22 | // If a key does not exist we get null back
23 | String? value3 = db.get("abc");
24 | print("value3 is $value3"); // value3 is null
25 |
26 | // Now lets add a few key-value pairs
27 | for (int i in new Iterable.generate(5)) {
28 | db.put("key-$i", "value-$i");
29 | }
30 |
31 | // Iterate through the key-value pairs in key order.
32 | for (LevelItem v in db.getItems()) {
33 | print(
34 | "Row: ${v.key} ${v.value}"); // prints Row: key-0 value-0, Row: key-1 value-1, ...
35 | }
36 |
37 | // Iterate keys between key-1 and key-3
38 | for (LevelItem v in db.getItems(gte: "key-1", lte: "key-3")) {
39 | print(
40 | "Row: ${v.key} ${v.value}"); // prints Row: key-1 value-1, Row: key-2 value-2, Row: key-3 value-3
41 | }
42 |
43 | // Iterate explicitly. This avoids allocation of LevelItem objects if you never call it.current.
44 | LevelIterator it = db.getItems(limit: 1).iterator;
45 | while (it.moveNext()) {
46 | print("${it.currentKey} ${it.currentValue}");
47 | }
48 |
49 | // Just key iteration
50 | for (dynamic key in db.getItems().keys) {
51 | print("Key $key"); // Prints Key key-0, Key key-1, ...
52 | }
53 |
54 | // Value iteration
55 | for (dynamic value in db.getItems().values) {
56 | print("Value $value"); // Prints Key value-0, Key value-1, ...
57 | }
58 |
59 | // Close the db. This free's all resources associated with the db.
60 | // All iterators will throw if used after this call.
61 | db.close();
62 |
63 | // Open a new db which will use raw UInt8List data. This is faster since it avoids any decoding.
64 | LevelDB db2 =
65 | await LevelDB.openUint8List("/tmp/testdb");
66 |
67 | for (LevelItem item in db2.getItems()) {
68 | print("${item.key}"); // Prints [107, 101, 121, 45, 48], ...
69 | }
70 |
71 | db2.close();
72 | }
73 |
--------------------------------------------------------------------------------
/leveldb_dart.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/lib/leveldb.cc:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | #include
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 | #include