mirror of
https://github.com/logos-storage/nim-leveldb.git
synced 2026-01-10 01:23:09 +00:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a0cd8de6b | ||
|
|
378ef63e26 | ||
|
|
bd9b8394a7 | ||
|
|
4da61d231a | ||
|
|
3805148c2f | ||
|
|
9e89afa856 | ||
|
|
37c92f69b5 | ||
|
|
c70c51f5b3 | ||
|
|
3cb21890d4 | ||
|
|
5f0a4ea871 | ||
|
|
f0d18f6d35 | ||
|
|
06947b4b60 | ||
|
|
ec4754b7a7 | ||
|
|
dfe142f00a | ||
|
|
986ad266eb | ||
|
|
f51e61c5ce | ||
|
|
9dc532b856 | ||
|
|
e6ba737764 | ||
|
|
760acd2767 |
7
.github/workflows/main.yml
vendored
7
.github/workflows/main.yml
vendored
@ -8,14 +8,15 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macOS-latest, windows-latest]
|
||||
nim: [stable, 1.6.18]
|
||||
nim: [stable, 1.6.18, 2.0.12]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- uses: iffy/install-nim@v4
|
||||
- uses: jiro4989/setup-nim-action@v2
|
||||
with:
|
||||
version: ${{ matrix.nim }}
|
||||
nim-version: ${{matrix.nim}}
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Build
|
||||
run: nimble install -y
|
||||
- name: Test
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@ -8,4 +8,5 @@ leveldbtool
|
||||
*.html
|
||||
*.css
|
||||
build
|
||||
|
||||
nimbledeps
|
||||
*.exe
|
||||
|
||||
24
README.md
24
README.md
@ -6,6 +6,8 @@ Original nim LevelDB wrapper: [HERE](https://github.com/zielmicha/leveldb.nim)
|
||||
|
||||
Replacing of system library dependency with self-contained C/CPP interoperability by (Codex.Storage)[https://codex.storage]
|
||||
|
||||
## Usage
|
||||
|
||||
Create a database:
|
||||
```Nim
|
||||
import leveldbstatic
|
||||
@ -49,3 +51,25 @@ Iterate over subset of database content:
|
||||
|
||||
db.close()
|
||||
```
|
||||
|
||||
## Compiling with optimizations
|
||||
|
||||
CMake is used during compilation to determine which of the following optimization options are enabled. You can set the following nim compiler flags to 0 or 1 to override them:
|
||||
- fdatasync from <unistd.h> `--passC:-DHAVE_FDATASYNC=1`
|
||||
- F_FULLSYNC from <fcntl.h> `--passC:-DHAVE_FULLFSYNC=1`
|
||||
- O_CLOEXEC from <fcntl.h> `--passC:-DHAVE_O_CLOEXEC=1`
|
||||
- crc32c from <crc32c/crc32c.h> `--passC:-DHAVE_CRC32C=1`
|
||||
- snappy from <snappy.h> `--passC:-DHAVE_SNAPPY=1`
|
||||
- zstd from <zstd.h> `--passC:-DHAVE_ZSTD=1`
|
||||
|
||||
## Updating
|
||||
|
||||
When you want to update this library to a new version of LevelDB, follow these steps:
|
||||
- Update LevelDB submodule to new version.
|
||||
- Run 'build.sh'.
|
||||
- Run 'nimble build' and 'nimble test'.
|
||||
- Make sure everything's working.
|
||||
- Increment version of this library in 'leveldbstatic.nimble'.
|
||||
- Commit the changes.
|
||||
- Tag the commit with the new version number.
|
||||
- Push.
|
||||
|
||||
4
build.sh
4
build.sh
@ -21,7 +21,7 @@ rm -Rf "${sourceDir}/benchmarks"
|
||||
rm "${sourceDir}/util/testutil.cc"
|
||||
|
||||
# Prelude:
|
||||
cat "${root}/leveldb/prelude.nim" > "${output}"
|
||||
cat "${root}/leveldbstatic/prelude.nim" > "${output}"
|
||||
echo >> "${output}"
|
||||
|
||||
# assemble files to be compiled:
|
||||
@ -47,10 +47,8 @@ toast \
|
||||
--includeDirs="${sourceDir}/helpers/memenv" \
|
||||
--includeDirs="${sourceDir}/port" \
|
||||
--includeDirs="${sourceDir}/include" \
|
||||
--includeDirs="${buildDir}/include" \
|
||||
"${sourceDir}/include/leveldb/c.h" >> "${output}"
|
||||
|
||||
sed -i 's/\bpassC\b/passc/g' "${output}"
|
||||
sed -i 's/{\.compile\:\ \"\./{\.compile\:\ root\ \&\ \"/g' "${output}"
|
||||
sed -i 's/{\.passc\:\ \"-I\./{\.passc\:\ \"-I\"\ \&\ root\ \&\ \"/g' "${output}"
|
||||
|
||||
|
||||
0
build/.gitkeep
Normal file
0
build/.gitkeep
Normal file
@ -1,38 +0,0 @@
|
||||
// Copyright 2017 The LevelDB Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
||||
|
||||
#ifndef STORAGE_LEVELDB_PORT_PORT_CONFIG_H_
|
||||
#define STORAGE_LEVELDB_PORT_PORT_CONFIG_H_
|
||||
|
||||
// Define to 1 if you have a definition for fdatasync() in <unistd.h>.
|
||||
#if !defined(HAVE_FDATASYNC)
|
||||
#define HAVE_FDATASYNC 1
|
||||
#endif // !defined(HAVE_FDATASYNC)
|
||||
|
||||
// Define to 1 if you have a definition for F_FULLFSYNC in <fcntl.h>.
|
||||
#if !defined(HAVE_FULLFSYNC)
|
||||
#define HAVE_FULLFSYNC 0
|
||||
#endif // !defined(HAVE_FULLFSYNC)
|
||||
|
||||
// Define to 1 if you have a definition for O_CLOEXEC in <fcntl.h>.
|
||||
#if !defined(HAVE_O_CLOEXEC)
|
||||
#define HAVE_O_CLOEXEC 1
|
||||
#endif // !defined(HAVE_O_CLOEXEC)
|
||||
|
||||
// Define to 1 if you have Google CRC32C.
|
||||
#if !defined(HAVE_CRC32C)
|
||||
#define HAVE_CRC32C 0
|
||||
#endif // !defined(HAVE_CRC32C)
|
||||
|
||||
// Define to 1 if you have Google Snappy.
|
||||
#if !defined(HAVE_SNAPPY)
|
||||
#define HAVE_SNAPPY 0
|
||||
#endif // !defined(HAVE_SNAPPY)
|
||||
|
||||
// Define to 1 if you have Zstd.
|
||||
#if !defined(HAVE_Zstd)
|
||||
#define HAVE_ZSTD 0
|
||||
#endif // !defined(HAVE_ZSTD)
|
||||
|
||||
#endif // STORAGE_LEVELDB_PORT_PORT_CONFIG_H_
|
||||
@ -76,6 +76,13 @@ type
|
||||
|
||||
LevelDbException* = object of CatchableError
|
||||
|
||||
IterNext* = proc(): (string, string) {.gcsafe, closure, raises: [LevelDbException].}
|
||||
IterDispose* = proc() {.gcsafe, closure, raises: [].}
|
||||
LevelDbQueryIter* = ref object
|
||||
finished*: bool
|
||||
next*: IterNext
|
||||
dispose*: IterDispose
|
||||
|
||||
const
|
||||
version* = block:
|
||||
const configFile = "leveldbstatic.nimble"
|
||||
@ -406,6 +413,81 @@ iterator iterRange*(self: LevelDb, start, limit: string): (string, string) =
|
||||
break
|
||||
yield (key, value)
|
||||
|
||||
|
||||
proc getIterKey(iterPtr: ptr leveldb_iterator_t): string =
|
||||
var len: csize_t
|
||||
var str: cstring
|
||||
|
||||
str = leveldb_iter_key(iterPtr, addr len)
|
||||
return newString(str, len)
|
||||
|
||||
proc getIterValue(iterPtr: ptr leveldb_iterator_t): string =
|
||||
var len: csize_t
|
||||
var str: cstring
|
||||
|
||||
str = leveldb_iter_value(iterPtr, addr len)
|
||||
return newString(str, len)
|
||||
|
||||
proc seekToQueryStart(iterPtr: ptr leveldb_iterator_t, prefix: string, skip: int) =
|
||||
if prefix.len > 0:
|
||||
leveldb_iter_seek(iterPtr, prefix, prefix.len.csize_t)
|
||||
else:
|
||||
leveldb_iter_seek_to_first(iterPtr)
|
||||
for i in 0..<skip:
|
||||
leveldb_iter_next(iterPtr)
|
||||
|
||||
proc closeIter(iter: LevelDbQueryIter, iterPtr: ptr leveldb_iterator_t) =
|
||||
iter.finished = true
|
||||
leveldb_iter_destroy(iterPtr)
|
||||
|
||||
proc queryIter*(self: LevelDb, prefix: string = "", keysOnly: bool = false, skip: int = 0, limit: int = 0): LevelDbQueryIter =
|
||||
var iterPtr = leveldb_create_iterator(self.db, self.readOptions)
|
||||
|
||||
seekToQueryStart(iterPtr, prefix, skip)
|
||||
|
||||
var
|
||||
iter = LevelDbQueryIter()
|
||||
remaining = limit
|
||||
let emptyResponse = ("", "")
|
||||
|
||||
proc getNext(): (string, string) {.gcsafe, closure.} =
|
||||
if iter.finished:
|
||||
return emptyResponse
|
||||
|
||||
if leveldb_iter_valid(iterPtr) == levelDbFalse or (limit > 0 and remaining == 0):
|
||||
iter.closeIter(iterPtr)
|
||||
return emptyResponse
|
||||
if limit > 0:
|
||||
dec remaining
|
||||
|
||||
let
|
||||
keyStr = getIterKey(iterPtr)
|
||||
valueStr = if keysOnly: "" else: getIterValue(iterPtr)
|
||||
|
||||
var err: cstring = nil
|
||||
leveldb_iter_get_error(iterPtr, addr err)
|
||||
checkError(err)
|
||||
|
||||
leveldb_iter_next(iterPtr)
|
||||
|
||||
if prefix.len > 0:
|
||||
if keyStr.startsWith(prefix):
|
||||
return (keyStr, valueStr)
|
||||
else:
|
||||
iter.closeIter(iterPtr)
|
||||
return emptyResponse
|
||||
else:
|
||||
return (keyStr, valueStr)
|
||||
|
||||
proc dispose() {.gcsafe, closure.} =
|
||||
if not iter.finished:
|
||||
iter.closeIter(iterPtr)
|
||||
|
||||
iter.finished = false
|
||||
iter.next = getNext
|
||||
iter.dispose = dispose
|
||||
return iter
|
||||
|
||||
proc removeDb*(name: string) =
|
||||
## Remove the database `name`.
|
||||
var err: cstring = nil
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# Package
|
||||
|
||||
version = "0.1.0"
|
||||
version = "0.2.1"
|
||||
author = "leveldbstatic authors"
|
||||
description = "Statically linked LevelDB wrapper for Nim"
|
||||
license = "MIT"
|
||||
|
||||
@ -1,8 +1,46 @@
|
||||
import os
|
||||
|
||||
const root = currentSourcePath.parentDir.parentDir
|
||||
const envWindows = root/"vendor"/"util"/"env_windows.cc"
|
||||
const envPosix = root/"vendor"/"util"/"env_posix.cc"
|
||||
const
|
||||
root = currentSourcePath.parentDir.parentDir
|
||||
envWindows = root/"vendor"/"util"/"env_windows.cc"
|
||||
envPosix = root/"vendor"/"util"/"env_posix.cc"
|
||||
|
||||
LevelDbCMakeFlags {.strdefine.} =
|
||||
when defined(macosx):
|
||||
"-DCMAKE_BUILD_TYPE=Release -DLEVELDB_BUILD_BENCHMARKS=OFF"
|
||||
elif defined(windows):
|
||||
"-G\"MSYS Makefiles\" -DCMAKE_BUILD_TYPE=Release -DLEVELDB_BUILD_BENCHMARKS=OFF"
|
||||
else:
|
||||
"-DCMAKE_BUILD_TYPE=Release -DLEVELDB_BUILD_BENCHMARKS=OFF"
|
||||
|
||||
LevelDbCMakeCommonFlags = " -DCMAKE_POLICY_VERSION_MINIMUM=3.31"
|
||||
|
||||
LevelDbDir {.strdefine.} = $(root/"vendor")
|
||||
buildDir = $(root/"build")
|
||||
|
||||
proc buildLevelDb() =
|
||||
if fileExists(buildDir/"Makefile"):
|
||||
echo "LevelDB already build. Delete '" & buildDir & "' to force rebuild."
|
||||
return
|
||||
|
||||
echo "Initializing submodule..."
|
||||
discard gorge "git submodule deinit -f \"" & root & "\""
|
||||
discard gorge "git submodule update --init --recursive --checkout \"" & root & "\""
|
||||
|
||||
echo "\nClean dir: \"" & buildDir & "\""
|
||||
discard gorge "rm -rf " & buildDir
|
||||
discard gorge "mkdir -p " & buildDir
|
||||
|
||||
let cmd = "cmake -S \"" & LevelDbDir & "\" -B \"" & buildDir & "\" " & LevelDbCMakeFlags & LevelDbCMakeCommonFlags
|
||||
echo "\nBuilding LevelDB: " & cmd
|
||||
let (output, exitCode) = gorgeEx cmd
|
||||
if exitCode != 0:
|
||||
discard gorge "rm -rf " & buildDir
|
||||
echo output
|
||||
raise (ref Defect)(msg: "Failed to build LevelDB")
|
||||
|
||||
static:
|
||||
buildLevelDb()
|
||||
|
||||
when defined(windows):
|
||||
{.compile: envWindows.}
|
||||
@ -13,13 +51,3 @@ when defined(windows):
|
||||
when defined(posix):
|
||||
{.compile: envPosix.}
|
||||
{.passc: "-DLEVELDB_PLATFORM_POSIX".}
|
||||
|
||||
|
||||
{.passc: "-DHAVE_FDATASYNC=0".}
|
||||
{.passc: "-DHAVE_FULLFSYNC=0".}
|
||||
{.passc: "-DHAVE_O_CLOEXEC=0".}
|
||||
{.passc: "-DHAVE_CRC32C=0".}
|
||||
{.passc: "-DHAVE_SNAPPY=0".}
|
||||
{.passc: "-DHAVE_ZSTD=0".}
|
||||
{.passc: "-DHAVE_Zstd=0".}
|
||||
|
||||
|
||||
@ -1,8 +1,46 @@
|
||||
import os
|
||||
|
||||
const root = currentSourcePath.parentDir.parentDir
|
||||
const envWindows = root/"vendor"/"util"/"env_windows.cc"
|
||||
const envPosix = root/"vendor"/"util"/"env_posix.cc"
|
||||
const
|
||||
root = currentSourcePath.parentDir.parentDir
|
||||
envWindows = root/"vendor"/"util"/"env_windows.cc"
|
||||
envPosix = root/"vendor"/"util"/"env_posix.cc"
|
||||
|
||||
LevelDbCMakeFlags {.strdefine.} =
|
||||
when defined(macosx):
|
||||
"-DCMAKE_BUILD_TYPE=Release -DLEVELDB_BUILD_BENCHMARKS=OFF"
|
||||
elif defined(windows):
|
||||
"-G\"MSYS Makefiles\" -DCMAKE_BUILD_TYPE=Release -DLEVELDB_BUILD_BENCHMARKS=OFF"
|
||||
else:
|
||||
"-DCMAKE_BUILD_TYPE=Release -DLEVELDB_BUILD_BENCHMARKS=OFF"
|
||||
|
||||
LevelDbCMakeCommonFlags = " -DCMAKE_POLICY_VERSION_MINIMUM=3.31"
|
||||
|
||||
LevelDbDir {.strdefine.} = $(root/"vendor")
|
||||
buildDir = $(root/"build")
|
||||
|
||||
proc buildLevelDb() =
|
||||
if fileExists(buildDir/"Makefile"):
|
||||
echo "LevelDB already build. Delete '" & buildDir & "' to force rebuild."
|
||||
return
|
||||
|
||||
echo "Initializing submodule..."
|
||||
discard gorge "git submodule deinit -f \"" & root & "\""
|
||||
discard gorge "git submodule update --init --recursive --checkout \"" & root & "\""
|
||||
|
||||
echo "\nClean dir: \"" & buildDir & "\""
|
||||
discard gorge "rm -rf " & buildDir
|
||||
discard gorge "mkdir -p " & buildDir
|
||||
|
||||
let cmd = "cmake -S \"" & LevelDbDir & "\" -B \"" & buildDir & "\" " & LevelDbCMakeFlags & LevelDbCMakeCommonFlags
|
||||
echo "\nBuilding LevelDB: " & cmd
|
||||
let (output, exitCode) = gorgeEx cmd
|
||||
if exitCode != 0:
|
||||
discard gorge "rm -rf " & buildDir
|
||||
echo output
|
||||
raise (ref Defect)(msg: "Failed to build LevelDB")
|
||||
|
||||
static:
|
||||
buildLevelDb()
|
||||
|
||||
when defined(windows):
|
||||
{.compile: envWindows.}
|
||||
@ -14,19 +52,9 @@ when defined(posix):
|
||||
{.compile: envPosix.}
|
||||
{.passc: "-DLEVELDB_PLATFORM_POSIX".}
|
||||
|
||||
|
||||
{.passc: "-DHAVE_FDATASYNC=0".}
|
||||
{.passc: "-DHAVE_FULLFSYNC=0".}
|
||||
{.passc: "-DHAVE_O_CLOEXEC=0".}
|
||||
{.passc: "-DHAVE_CRC32C=0".}
|
||||
{.passc: "-DHAVE_SNAPPY=0".}
|
||||
{.passc: "-DHAVE_ZSTD=0".}
|
||||
{.passc: "-DHAVE_Zstd=0".}
|
||||
|
||||
|
||||
# Generated @ 2024-05-13T12:00:58+02:00
|
||||
# Generated @ 2024-12-09T16:35:09+01:00
|
||||
# Command line:
|
||||
# /home/ben/.nimble/pkgs/nimterop-0.6.13/nimterop/toast --compile=./vendor/db/log_writer.cc --compile=./vendor/db/db_impl.cc --compile=./vendor/db/db_iter.cc --compile=./vendor/db/dumpfile.cc --compile=./vendor/db/c.cc --compile=./vendor/db/builder.cc --compile=./vendor/db/filename.cc --compile=./vendor/db/write_batch.cc --compile=./vendor/db/table_cache.cc --compile=./vendor/db/version_edit.cc --compile=./vendor/db/dbformat.cc --compile=./vendor/db/log_reader.cc --compile=./vendor/db/memtable.cc --compile=./vendor/db/version_set.cc --compile=./vendor/db/repair.cc --compile=./vendor/table/block.cc --compile=./vendor/table/two_level_iterator.cc --compile=./vendor/table/table_builder.cc --compile=./vendor/table/iterator.cc --compile=./vendor/table/block_builder.cc --compile=./vendor/table/merger.cc --compile=./vendor/table/format.cc --compile=./vendor/table/filter_block.cc --compile=./vendor/table/table.cc --compile=./vendor/util/hash.cc --compile=./vendor/util/arena.cc --compile=./vendor/util/options.cc --compile=./vendor/util/histogram.cc --compile=./vendor/util/crc32c.cc --compile=./vendor/util/env.cc --compile=./vendor/util/filter_policy.cc --compile=./vendor/util/bloom.cc --compile=./vendor/util/logging.cc --compile=./vendor/util/coding.cc --compile=./vendor/util/status.cc --compile=./vendor/util/cache.cc --compile=./vendor/util/comparator.cc --compile=./vendor/helpers/memenv/memenv.cc --pnim --preprocess --noHeader --includeDirs=./vendor --includeDirs=./vendor/helpers --includeDirs=./vendor/helpers/memenv --includeDirs=./vendor/port --includeDirs=./vendor/include --includeDirs=./build/include ./vendor/include/leveldb/c.h
|
||||
# /home/arnaud/.nimble/pkgs2/nimterop-0.6.13-a93246b2ad5531db11e51de7b2d188c42d95576a/nimterop/toast --compile=./vendor/util/bloom.cc --compile=./vendor/util/arena.cc --compile=./vendor/util/env.cc --compile=./vendor/util/filter_policy.cc --compile=./vendor/util/histogram.cc --compile=./vendor/util/hash.cc --compile=./vendor/util/comparator.cc --compile=./vendor/util/options.cc --compile=./vendor/util/logging.cc --compile=./vendor/util/status.cc --compile=./vendor/util/coding.cc --compile=./vendor/util/cache.cc --compile=./vendor/util/crc32c.cc --compile=./vendor/table/table.cc --compile=./vendor/table/format.cc --compile=./vendor/table/table_builder.cc --compile=./vendor/table/block_builder.cc --compile=./vendor/table/merger.cc --compile=./vendor/table/block.cc --compile=./vendor/table/filter_block.cc --compile=./vendor/table/iterator.cc --compile=./vendor/table/two_level_iterator.cc --compile=./vendor/helpers/memenv/memenv.cc --compile=./vendor/db/filename.cc --compile=./vendor/db/dbformat.cc --compile=./vendor/db/c.cc --compile=./vendor/db/memtable.cc --compile=./vendor/db/version_set.cc --compile=./vendor/db/repair.cc --compile=./vendor/db/builder.cc --compile=./vendor/db/write_batch.cc --compile=./vendor/db/version_edit.cc --compile=./vendor/db/dumpfile.cc --compile=./vendor/db/db_impl.cc --compile=./vendor/db/log_reader.cc --compile=./vendor/db/table_cache.cc --compile=./vendor/db/db_iter.cc --compile=./vendor/db/log_writer.cc --pnim --preprocess --noHeader --includeDirs=./vendor --includeDirs=./vendor/helpers --includeDirs=./vendor/helpers/memenv --includeDirs=./vendor/port --includeDirs=./vendor/include ./vendor/include/leveldb/c.h
|
||||
|
||||
{.push hint[ConvFromXtoItselfNotNeeded]: off.}
|
||||
import macros
|
||||
@ -79,45 +107,44 @@ macro defineEnum(typ: untyped): untyped =
|
||||
{.passc: "-I" & root & "/vendor/helpers/memenv".}
|
||||
{.passc: "-I" & root & "/vendor/port".}
|
||||
{.passc: "-I" & root & "/vendor/include".}
|
||||
{.passc: "-I" & root & "/build/include".}
|
||||
{.compile: root & "/vendor/db/log_writer.cc".}
|
||||
{.compile: root & "/vendor/db/db_impl.cc".}
|
||||
{.compile: root & "/vendor/db/db_iter.cc".}
|
||||
{.compile: root & "/vendor/db/dumpfile.cc".}
|
||||
{.compile: root & "/vendor/db/c.cc".}
|
||||
{.compile: root & "/vendor/db/builder.cc".}
|
||||
{.compile: root & "/vendor/util/bloom.cc".}
|
||||
{.compile: root & "/vendor/util/arena.cc".}
|
||||
{.compile: root & "/vendor/util/env.cc".}
|
||||
{.compile: root & "/vendor/util/filter_policy.cc".}
|
||||
{.compile: root & "/vendor/util/histogram.cc".}
|
||||
{.compile: root & "/vendor/util/hash.cc".}
|
||||
{.compile: root & "/vendor/util/comparator.cc".}
|
||||
{.compile: root & "/vendor/util/options.cc".}
|
||||
{.compile: root & "/vendor/util/logging.cc".}
|
||||
{.compile: root & "/vendor/util/status.cc".}
|
||||
{.compile: root & "/vendor/util/coding.cc".}
|
||||
{.compile: root & "/vendor/util/cache.cc".}
|
||||
{.compile: root & "/vendor/util/crc32c.cc".}
|
||||
{.compile: root & "/vendor/table/table.cc".}
|
||||
{.compile: root & "/vendor/table/format.cc".}
|
||||
{.compile: root & "/vendor/table/table_builder.cc".}
|
||||
{.compile: root & "/vendor/table/block_builder.cc".}
|
||||
{.compile: root & "/vendor/table/merger.cc".}
|
||||
{.compile: root & "/vendor/table/block.cc".}
|
||||
{.compile: root & "/vendor/table/filter_block.cc".}
|
||||
{.compile: root & "/vendor/table/iterator.cc".}
|
||||
{.compile: root & "/vendor/table/two_level_iterator.cc".}
|
||||
{.compile: root & "/vendor/helpers/memenv/memenv.cc".}
|
||||
{.compile: root & "/vendor/db/filename.cc".}
|
||||
{.compile: root & "/vendor/db/write_batch.cc".}
|
||||
{.compile: root & "/vendor/db/table_cache.cc".}
|
||||
{.compile: root & "/vendor/db/version_edit.cc".}
|
||||
{.compile: root & "/vendor/db/dbformat.cc".}
|
||||
{.compile: root & "/vendor/db/log_reader.cc".}
|
||||
{.compile: root & "/vendor/db/c.cc".}
|
||||
{.compile: root & "/vendor/db/memtable.cc".}
|
||||
{.compile: root & "/vendor/db/version_set.cc".}
|
||||
{.compile: root & "/vendor/db/repair.cc".}
|
||||
{.compile: root & "/vendor/table/block.cc".}
|
||||
{.compile: root & "/vendor/table/two_level_iterator.cc".}
|
||||
{.compile: root & "/vendor/table/table_builder.cc".}
|
||||
{.compile: root & "/vendor/table/iterator.cc".}
|
||||
{.compile: root & "/vendor/table/block_builder.cc".}
|
||||
{.compile: root & "/vendor/table/merger.cc".}
|
||||
{.compile: root & "/vendor/table/format.cc".}
|
||||
{.compile: root & "/vendor/table/filter_block.cc".}
|
||||
{.compile: root & "/vendor/table/table.cc".}
|
||||
{.compile: root & "/vendor/util/hash.cc".}
|
||||
{.compile: root & "/vendor/util/arena.cc".}
|
||||
{.compile: root & "/vendor/util/options.cc".}
|
||||
{.compile: root & "/vendor/util/histogram.cc".}
|
||||
{.compile: root & "/vendor/util/crc32c.cc".}
|
||||
{.compile: root & "/vendor/util/env.cc".}
|
||||
{.compile: root & "/vendor/util/filter_policy.cc".}
|
||||
{.compile: root & "/vendor/util/bloom.cc".}
|
||||
{.compile: root & "/vendor/util/logging.cc".}
|
||||
{.compile: root & "/vendor/util/coding.cc".}
|
||||
{.compile: root & "/vendor/util/status.cc".}
|
||||
{.compile: root & "/vendor/util/cache.cc".}
|
||||
{.compile: root & "/vendor/util/comparator.cc".}
|
||||
{.compile: root & "/vendor/helpers/memenv/memenv.cc".}
|
||||
{.compile: root & "/vendor/db/builder.cc".}
|
||||
{.compile: root & "/vendor/db/write_batch.cc".}
|
||||
{.compile: root & "/vendor/db/version_edit.cc".}
|
||||
{.compile: root & "/vendor/db/dumpfile.cc".}
|
||||
{.compile: root & "/vendor/db/db_impl.cc".}
|
||||
{.compile: root & "/vendor/db/log_reader.cc".}
|
||||
{.compile: root & "/vendor/db/table_cache.cc".}
|
||||
{.compile: root & "/vendor/db/db_iter.cc".}
|
||||
{.compile: root & "/vendor/db/log_writer.cc".}
|
||||
defineEnum(Enum_ch1)
|
||||
const
|
||||
leveldb_no_compression* = (0).cint
|
||||
|
||||
282
tests/test.nim
282
tests/test.nim
@ -21,7 +21,10 @@ proc execNimble(args: varargs[string]): tuple[output: string, exitCode: int] =
|
||||
quotedArgs.insert("-y")
|
||||
quotedArgs.insert("--nimbleDir:" & tmpNimbleDir)
|
||||
quotedArgs.insert("nimble")
|
||||
quotedArgs = quotedArgs.map(proc (x: string): string = "\"" & x & "\"")
|
||||
quotedArgs = quotedArgs.map(
|
||||
proc(x: string): string =
|
||||
"\"" & x & "\""
|
||||
)
|
||||
|
||||
let cmd = quotedArgs.join(" ")
|
||||
result = execCmdEx(cmd)
|
||||
@ -33,7 +36,10 @@ proc execTool(args: varargs[string]): tuple[output: string, exitCode: int] =
|
||||
quotedArgs.insert(tmpDbDir)
|
||||
quotedArgs.insert("--database")
|
||||
quotedArgs.insert(findExe(tmpNimbleDir / "bin" / "leveldbtool"))
|
||||
quotedArgs = quotedArgs.map(proc (x: string): string = "\"" & x & "\"")
|
||||
quotedArgs = quotedArgs.map(
|
||||
proc(x: string): string =
|
||||
"\"" & x & "\""
|
||||
)
|
||||
|
||||
if not dirExists(tmpDbDir):
|
||||
createDir(tmpDbDir)
|
||||
@ -44,7 +50,6 @@ proc execTool(args: varargs[string]): tuple[output: string, exitCode: int] =
|
||||
checkpoint(result.output)
|
||||
|
||||
suite "leveldb":
|
||||
|
||||
setup:
|
||||
let env = leveldb_create_default_env()
|
||||
let dbName = $(leveldb_env_get_test_directory(env))
|
||||
@ -97,33 +102,27 @@ suite "leveldb":
|
||||
|
||||
test "iter reverse":
|
||||
initData(db)
|
||||
check(toSeq(db.iter(reverse = true)) ==
|
||||
@[("bb", "3"), ("ba", "2"), ("aa", "1")])
|
||||
check(toSeq(db.iter(reverse = true)) == @[("bb", "3"), ("ba", "2"), ("aa", "1")])
|
||||
|
||||
test "iter seek":
|
||||
initData(db)
|
||||
check(toSeq(db.iter(seek = "ab")) ==
|
||||
@[("ba", "2"), ("bb", "3")])
|
||||
check(toSeq(db.iter(seek = "ab")) == @[("ba", "2"), ("bb", "3")])
|
||||
|
||||
test "iter seek reverse":
|
||||
initData(db)
|
||||
check(toSeq(db.iter(seek = "ab", reverse = true)) ==
|
||||
@[("ba", "2"), ("aa", "1")])
|
||||
check(toSeq(db.iter(seek = "ab", reverse = true)) == @[("ba", "2"), ("aa", "1")])
|
||||
|
||||
test "iter prefix":
|
||||
initData(db)
|
||||
check(toSeq(db.iterPrefix(prefix = "b")) ==
|
||||
@[("ba", "2"), ("bb", "3")])
|
||||
check(toSeq(db.iterPrefix(prefix = "b")) == @[("ba", "2"), ("bb", "3")])
|
||||
|
||||
test "iter range":
|
||||
initData(db)
|
||||
check(toSeq(db.iterRange(start = "a", limit = "ba")) ==
|
||||
@[("aa", "1"), ("ba", "2")])
|
||||
check(toSeq(db.iterRange(start = "a", limit = "ba")) == @[("aa", "1"), ("ba", "2")])
|
||||
|
||||
test "iter range reverse":
|
||||
initData(db)
|
||||
check(toSeq(db.iterRange(start = "bb", limit = "b")) ==
|
||||
@[("bb", "3"), ("ba", "2")])
|
||||
check(toSeq(db.iterRange(start = "bb", limit = "b")) == @[("bb", "3"), ("ba", "2")])
|
||||
|
||||
test "iter with 0x00":
|
||||
db.put("\0z1", "\0ff")
|
||||
@ -201,21 +200,265 @@ suite "leveldb":
|
||||
test "no compress":
|
||||
db.close()
|
||||
let nc = leveldb.open(dbName, compressionType = ctNoCompression)
|
||||
defer: nc.close()
|
||||
defer:
|
||||
nc.close()
|
||||
nc.put("a", "1")
|
||||
check(toSeq(nc.iter()) == @[("a", "1")])
|
||||
|
||||
suite "package":
|
||||
suite "leveldb queryIter":
|
||||
setup:
|
||||
let env = leveldb_create_default_env()
|
||||
let dbName = $(leveldb_env_get_test_directory(env))
|
||||
let db = leveldb.open(dbName)
|
||||
let
|
||||
k1 = "k1"
|
||||
k2 = "k2"
|
||||
k3 = "l3"
|
||||
v1 = "v1"
|
||||
v2 = "v2"
|
||||
v3 = "v3"
|
||||
empty = ("", "")
|
||||
|
||||
db.put(k1, v1)
|
||||
db.put(k2, v2)
|
||||
db.put(k3, v3)
|
||||
|
||||
teardown:
|
||||
db.close()
|
||||
removeDb(dbName)
|
||||
|
||||
test "iterates all keys and values":
|
||||
let iter = db.queryIter()
|
||||
check:
|
||||
not iter.finished
|
||||
iter.next() == (k1, v1)
|
||||
not iter.finished
|
||||
iter.next() == (k2, v2)
|
||||
not iter.finished
|
||||
iter.next() == (k3, v3)
|
||||
not iter.finished
|
||||
iter.next() == empty
|
||||
iter.finished
|
||||
|
||||
test "iterate until disposed":
|
||||
let iter = db.queryIter()
|
||||
check:
|
||||
not iter.finished
|
||||
iter.next() == (k1, v1)
|
||||
not iter.finished
|
||||
iter.next() == (k2, v2)
|
||||
not iter.finished
|
||||
|
||||
iter.dispose()
|
||||
|
||||
check:
|
||||
iter.finished
|
||||
iter.next() == empty
|
||||
iter.finished
|
||||
|
||||
test "skip":
|
||||
let iter = db.queryIter(skip = 1)
|
||||
check:
|
||||
not iter.finished
|
||||
iter.next() == (k2, v2)
|
||||
not iter.finished
|
||||
iter.next() == (k3, v3)
|
||||
not iter.finished
|
||||
iter.next() == empty
|
||||
iter.finished
|
||||
|
||||
test "limit":
|
||||
let iter = db.queryIter(limit = 2)
|
||||
check:
|
||||
not iter.finished
|
||||
iter.next() == (k1, v1)
|
||||
not iter.finished
|
||||
iter.next() == (k2, v2)
|
||||
not iter.finished
|
||||
iter.next() == empty
|
||||
iter.finished
|
||||
|
||||
test "iterates only keys":
|
||||
let iter = db.queryIter(keysOnly = true)
|
||||
check:
|
||||
not iter.finished
|
||||
iter.next() == (k1, "")
|
||||
not iter.finished
|
||||
iter.next() == (k2, "")
|
||||
not iter.finished
|
||||
iter.next() == (k3, "")
|
||||
not iter.finished
|
||||
iter.next() == empty
|
||||
iter.finished
|
||||
|
||||
test "iterates only 'k', both keys and values":
|
||||
let iter = db.queryIter(prefix = "k")
|
||||
check:
|
||||
not iter.finished
|
||||
iter.next() == (k1, v1)
|
||||
not iter.finished
|
||||
iter.next() == (k2, v2)
|
||||
not iter.finished
|
||||
iter.next() == empty
|
||||
iter.finished
|
||||
|
||||
test "iterates only 'k', skip":
|
||||
let iter = db.queryIter(prefix = "k", skip = 1)
|
||||
check:
|
||||
not iter.finished
|
||||
iter.next() == (k2, v2)
|
||||
not iter.finished
|
||||
iter.next() == empty
|
||||
iter.finished
|
||||
|
||||
test "iterate only 'k', limit":
|
||||
let iter = db.queryIter(prefix = "k", limit = 1)
|
||||
check:
|
||||
not iter.finished
|
||||
iter.next() == (k1, v1)
|
||||
not iter.finished
|
||||
iter.next() == empty
|
||||
iter.finished
|
||||
|
||||
test "iterates only 'k', only keys":
|
||||
let iter = db.queryIter(prefix = "k", keysOnly = true)
|
||||
check:
|
||||
not iter.finished
|
||||
iter.next() == (k1, "")
|
||||
not iter.finished
|
||||
iter.next() == (k2, "")
|
||||
not iter.finished
|
||||
iter.next() == empty
|
||||
iter.finished
|
||||
|
||||
test "concurrent iterators - 1":
|
||||
let
|
||||
iter1 = db.queryIter()
|
||||
iter2 = db.queryIter()
|
||||
|
||||
check:
|
||||
# 1, then 2
|
||||
not iter1.finished
|
||||
iter1.next() == (k1, v1)
|
||||
|
||||
not iter2.finished
|
||||
iter2.next() == (k1, v1)
|
||||
|
||||
# 1, 1, then 2, 2
|
||||
not iter1.finished
|
||||
iter1.next() == (k2, v2)
|
||||
not iter1.finished
|
||||
iter1.next() == (k3, v3)
|
||||
|
||||
not iter2.finished
|
||||
iter2.next() == (k2, v2)
|
||||
not iter2.finished
|
||||
iter2.next() == (k3, v3)
|
||||
|
||||
# finish 1, then finish 2
|
||||
not iter1.finished
|
||||
iter1.next() == empty
|
||||
|
||||
not iter2.finished
|
||||
iter2.next() == empty
|
||||
|
||||
iter1.finished
|
||||
iter2.finished
|
||||
|
||||
test "concurrent iterators - 2":
|
||||
let
|
||||
iter1 = db.queryIter()
|
||||
iter2 = db.queryIter()
|
||||
|
||||
check:
|
||||
# 1, then 2
|
||||
not iter1.finished
|
||||
iter1.next() == (k1, v1)
|
||||
|
||||
not iter2.finished
|
||||
iter2.next() == (k1, v1)
|
||||
|
||||
# finish 1
|
||||
not iter1.finished
|
||||
iter1.next() == (k2, v2)
|
||||
not iter1.finished
|
||||
iter1.next() == (k3, v3)
|
||||
not iter1.finished
|
||||
iter1.next() == empty
|
||||
iter1.finished
|
||||
|
||||
# finish 2
|
||||
not iter2.finished
|
||||
iter2.next() == (k2, v2)
|
||||
not iter2.finished
|
||||
iter2.next() == (k3, v3)
|
||||
not iter2.finished
|
||||
iter2.next() == empty
|
||||
iter2.finished
|
||||
|
||||
test "concurrent iterators - dispose":
|
||||
let
|
||||
iter1 = db.queryIter()
|
||||
iter2 = db.queryIter()
|
||||
|
||||
check:
|
||||
# 1, then 2
|
||||
not iter1.finished
|
||||
iter1.next() == (k1, v1)
|
||||
|
||||
not iter2.finished
|
||||
iter2.next() == (k1, v1)
|
||||
|
||||
# dispose 1
|
||||
iter1.dispose()
|
||||
|
||||
check:
|
||||
iter1.finished
|
||||
iter1.next() == empty
|
||||
iter1.finished
|
||||
|
||||
# finish 2
|
||||
not iter2.finished
|
||||
iter2.next() == (k2, v2)
|
||||
not iter2.finished
|
||||
iter2.next() == (k3, v3)
|
||||
not iter2.finished
|
||||
iter2.next() == empty
|
||||
iter2.finished
|
||||
|
||||
test "modify while iterating":
|
||||
let iter = db.queryIter()
|
||||
|
||||
check:
|
||||
not iter.finished
|
||||
iter.next() == (k1, v1)
|
||||
not iter.finished
|
||||
iter.next() == (k2, v2)
|
||||
|
||||
# insert
|
||||
let
|
||||
k4 = "k4"
|
||||
v4 = "v4"
|
||||
db.put(k4, v4)
|
||||
|
||||
check:
|
||||
not iter.finished
|
||||
iter.next() == (k3, v3)
|
||||
not iter.finished
|
||||
iter.next() == empty
|
||||
iter.finished
|
||||
|
||||
suite "package":
|
||||
setup:
|
||||
removeDir(tmpDir)
|
||||
|
||||
test "import as package":
|
||||
let (output, exitCode) = execNimble("install")
|
||||
check exitCode == QuitSuccess
|
||||
check output.contains("leveldbstatic installed successfully.")
|
||||
check output.contains("leveldbstatic installed successfully.") or
|
||||
output.contains("LevelDB already build")
|
||||
|
||||
cd "tests"/"packagetest":
|
||||
cd "tests" / "packagetest":
|
||||
var (output, exitCode) = execNimble("build")
|
||||
check exitCode == QuitSuccess
|
||||
check output.contains("Building")
|
||||
@ -226,7 +469,6 @@ suite "package":
|
||||
check output.contains("leveldb works.")
|
||||
|
||||
suite "tool":
|
||||
|
||||
setup:
|
||||
removeDir(tmpDir)
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user