Description:[feature] add iowow

Signed-off-by: stesen <stesen.ma@huawei.com>
Change-Id: I9303d30deed6066005e21bb955e4f6b0d3035caa
This commit is contained in:
stesen
2021-08-18 22:11:58 +08:00
parent 91057f8c12
commit 70c12f3930
152 changed files with 39529 additions and 63 deletions
+103
View File
@@ -0,0 +1,103 @@
#Copyright (c) 2019-2021 Huawei Device Co., Ltd.
#Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
import("//build/ohos.gni")
config("iowow_config") {
include_dirs = [
"//third_party/iowow/src",
"//third_party/iowow/src/fs",
"//third_party/iowow/src/kv",
"//third_party/iowow/src/log",
"//third_party/iowow/src/platform",
"//third_party/iowow/src/rdb",
"//third_party/iowow/src/utils",
]
cflags = [
"-fPIC",
"-std=gnu11",
"-fsigned-char",
"-pedantic",
"-Wfatal-errors",
"-Wall",
"-Wextra",
"-Wno-int-conversion",
"-Wno-sign-compare",
"-Wno-unused-parameter",
"-Wno-unknown-pragmas",
"-Wno-unused-function",
"-Wno-missing-field-initializers",
"-Wno-missing-braces",
"-O3",
"-DNDEBUG",
"-U__ANDROID__"
]
defines = [
"IW_API_EXPORTS",
"IW_HAVE_CLOCK_MONOTONIC",
"IW_HAVE_PTHREAD_CONDATTR_SETCLOCK",
"IW_PTHREADS",
"PTHREAD_SPIN_LOCK_SHIM",
"_GNU_SOURCE",
"_LARGEFILE_SOURCE",
]
if (target_cpu == "x86" || target_cpu == "arm") {
defines += [
"IW_32",
"_FILE_OFFSET_BITS=64",
]
} else {
defines += [
"IW_64",
"_FILE_OFFSET_BITS=64",
]
}
}
ohos_shared_library("iowow") {
configs = [ ":iowow_config" ]
public_configs = [ ":iowow_config" ]
sources = [
"src/fs/iwexfile.c",
"src/fs/iwfile.c",
"src/fs/iwfs.c",
"src/fs/iwfsmfile.c",
"src/iowow.c",
"src/kv/iwal.c",
"src/kv/iwkv.c",
"src/log/iwlog.c",
"src/platform/iwp.c",
"src/rdb/iwrdb.c",
"src/utils/iwarr.c",
"src/utils/iwconv.c",
"src/utils/iwhmap.c",
"src/utils/iwpool.c",
"src/utils/iwsha2.c",
"src/utils/iwstree.c",
"src/utils/iwstw.c",
"src/utils/iwth.c",
"src/utils/iwutils.c",
"src/utils/iwuuid.c",
"src/utils/iwxstr.c",
"src/utils/mt19937ar.c",
"src/utils/murmur3.c",
]
part_name = "hiview"
subsystem_name = "hiviewdfx"
}
+148
View File
@@ -0,0 +1,148 @@
cmake_minimum_required(VERSION 3.0)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/")
include(CMakeToolsHelpers OPTIONAL)
set(DEB_CHANGELOG_REQUIRED ON)
set(DEB_CHANGELOG "${CMAKE_CURRENT_SOURCE_DIR}/Changelog")
unset(CHANGELOG_LAST_VERSION)
unset(CHANGELOG_LAST_MESSAGE)
include(DebChangelog)
set(PROJECT_NAME "iowow")
project(${PROJECT_NAME} C)
set(PROJECT_VENDOR "Softmotions (https://softmotions.com)")
set(PROJECT_WEBSITE "https://github.com/Softmotions/iowow")
set(PROJECT_MAINTAINER "Anton Adamansky <adamansky@gmail.com>")
set(PROJECT_DESCRIPTION_SUMMARY "The skiplist based persistent key/value storage engine")
set(PROJECT_DESCRIPTION "The skiplist based persistent key/value storage engine")
set(CHANGELOG_MESSAGE ${CHANGELOG_LAST_MESSAGE})
set(PROJECT_PPA "ppa:adamansky/iowow")
set(PROJECT_PPA_USER "adamansky")
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO")
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "")
set(PROJECT_VERSION_MAJOR ${CHANGELOG_LAST_VERSION_MAJOR})
set(PROJECT_VERSION_MINOR ${CHANGELOG_LAST_VERSION_MINOR})
set(PROJECT_VERSION_PATCH ${CHANGELOG_LAST_VERSION_PATCH})
set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH})
set(${PROJECT_NAME}_VERSION ${PROJECT_VERSION})
set(${PROJECT_NAME}_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
set(${PROJECT_NAME}_VERSION_MINOR ${PROJECT_VERSION_MINOR})
set(${PROJECT_NAME}_VERSION_PATCH ${PROJECT_VERSION_PATCH})
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
option(BUILD_TESTS "Build test cases" OFF)
option(ASAN "Turn on address sanitizer" OFF)
option(BUILD_EXAMPLES "Build example projects" ON)
option(BUILD_BENCHMARKS "Build benchmarks" OFF)
option(PACKAGE_DEB "Build .deb instalation packages" OFF)
option(PACKAGE_RPM "Build .rpm instalation packages" OFF)
option(PACKAGE_TGZ "Build .tgz package archive" ON)
option(PACKAGE_ZIP "Build .zip package archive" ON)
option(ENABLE_PPA "Enable PPA package build" OFF)
option(UPLOAD_PPA "Upload debian packages to the launchpad ppa repository" OFF)
set(PPA_DEBIAN_VERSION "ppa1" CACHE STRING "PPA version suffix for debian packages")
set(PROJECT_PPA_DISTRIB_TARGET "focal;bionic;xenial" CACHE STRING "Ubuntu PPA distrubutive names")
if(POLICY CMP0042)
cmake_policy(SET CMP0042 NEW)
endif(POLICY CMP0042)
include(GNUInstallDirs)
include(ProjectUtils)
macro_ensure_out_of_source_build(
"${CMAKE_PROJECT_NAME} requires an out of source build."
)
if(BUILD_TESTS)
include(CTest)
find_package(CUnit REQUIRED)
endif(BUILD_TESTS)
if(UPLOAD_PPA)
set(ENABLE_PPA ON)
endif(UPLOAD_PPA)
# add a target to generate API documentation with Doxygen
find_package(Doxygen)
option(BUILD_DOCUMENTATION "Create and install the HTML based API documentation (requires Doxygen)" OFF)
if(BUILD_DOCUMENTATION)
if(NOT DOXYGEN_FOUND)
message(FATAL_ERROR "Doxygen is needed to build the documentation.")
endif()
set(doxyfile_in ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in)
set(doxyfile ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
configure_file(${doxyfile_in} ${doxyfile} @ONLY)
add_custom_target(docs
COMMAND ${DOXYGEN_EXECUTABLE} ${doxyfile}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen"
VERBATIM)
install(CODE "execute_process(COMMAND ${CMAKE_BUILD_TOOL} docs)")
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html DESTINATION share/doc)
endif()
add_subdirectory(man)
if(NOT ENABLE_PPA)
add_subdirectory(src)
else()
set(PACKAGE_DEB ON)
endif()
set(CPACK_GENERATORS)
if(PACKAGE_TGZ)
list(APPEND CPACK_GENERATORS "TGZ")
endif()
if(PACKAGE_ZIP)
list(APPEND CPACK_GENERATORS "ZIP")
endif()
if(PACKAGE_DEB)
list(APPEND CPACK_GENERATORS "DEB")
endif()
if(PACKAGE_RPM)
list(APPEND CPACK_GENERATORS "RPM")
endif()
if(CPACK_GENERATORS)
set(CPACK_GENERATOR "${CPACK_GENERATORS}")
set(CPACK_SOURCE_IGNORE_FILES
"/mxe/"
"/\\\\.vscode/"
"/\\\\.codelite/"
"/\\\\.idea/"
"/cmake-.*/"
"\\\\.sh$"
"\\\\.project$"
"\\\\.workspace$"
"\\\\.iml$"
"\\\\.mk$"
"\\\\.astylerc$"
"\\\\.editorconfig$"
"/Makefile$"
)
set(PROJECT_ARCH "${CMAKE_SYSTEM_PROCESSOR}")
add_subdirectory(installer)
endif(CPACK_GENERATORS)
message("${PROJECT_NAME} CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}")
message("${PROJECT_NAME} CPACK_GENERATORS: ${CPACK_GENERATORS}")
message("${PROJECT_NAME} CMAKE_GENERATOR: ${CMAKE_GENERATOR}")
if (MXE_HOME)
message("${PROJECT_NAME} MXE_HOME: ${MXE_HOME}")
endif()
if(CMAKE_SYSTEM_NAME)
message("${PROJECT_NAME} CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}")
endif()
message("${PROJECT_NAME} CPU: ${CMAKE_SYSTEM_PROCESSOR}")
if(CMAKE_SIZEOF_VOID_P)
message("${PROJECT_NAME} SIZEOF *VOID: ${CMAKE_SIZEOF_VOID_P}")
endif()
message("${PROJECT_NAME} PROJECT: ${CHANGELOG_LAST_LINE}")
if(CHANGELOG_MESSAGE)
message("${PROJECT_NAME} CHANGELOG_MESSAGE:\n ${CHANGELOG_MESSAGE}")
endif()
+532
View File
@@ -0,0 +1,532 @@
iowow (1.4.10) testing; urgency=medium
* Tuned iwkv file resizing policy
* Fixed misuse of `IWKV_OPTS.file_lock_fail_fast` (#35)
* Correct handling of EINTR, EAGAIN in read/write functions (unix.c)
-- Anton Adamansky <adamansky@gmail.com> Tue, 22 Dec 2020 23:55:36 +0700
iowow (1.4.9) testing; urgency=medium
* Code review of iwkv cache keys comparison, related issue: https://github.com/Softmotions/ejdb/issues/291
* Added `bool iwu_uuid_valid(const char *uuid)` (iwuuid.h)
-- Anton Adamansky <adamansky@gmail.com> Wed, 18 Nov 2020 15:04:03 +0700
iowow (1.4.8) testing; urgency=medium
* Fixed serios bug concerning non-unique ejdb2 indexes, details: https://github.com/Softmotions/ejdb/issues/291
* Fixed potencial memory leak in `iwlist_create()` (iwarr.h)
* Fixed wrong `iwulist_clear()` behaviour (iwarr.h)
* Code cleanup
* Added `iwulist_at2()` (iwarr.h)
* Removed not needed assertion (iwstree.c)
-- Anton Adamansky <adamansky@gmail.com> Sun, 08 Nov 2020 21:51:49 +0700
iowow (1.4.7) testing; urgency=medium
* Correct handling of EINTR, EAGAIN in read/write functions (unix.c)
* Minor fixes on iwhmap
-- Anton Adamansky <adamansky@gmail.com> Mon, 21 Sep 2020 12:14:06 +0700
iowow (1.4.6) testing; urgency=medium
* Added `iwpool_user_data_detach()` (iwpool.h)
* Added `iwpool_create_empty()` (iwpool.h)
* Added simple hashmap implementation (iwhmap.h)
* `IWPOOL` is able to store associated user data (iwpool.h)
* `pthread_barrierattr` shim for android API < 24
* Added `iwsha256()` SHA-256 hash implementation (iwsha2.h)
* Added single thread worker (iwstw.h)
* Added `iwstree_clear()` (iwstree.h)
-- Anton Adamansky <adamansky@gmail.com> Wed, 24 Jun 2020 18:32:24 +0700
iowow (1.4.5) testing; urgency=medium
* Added `iwulist_clear` (iwarr.h)
* Added `RCIF` (basedefs.h)
* Fix assertion error in `iwstree_remove()` (iwstree.h)
* Allows zero key/value placeholders in `iwstree_iter_next()` (iwstree.h)
* Added `iwstree_put_overwrite` (iwstree.h)
* Added iwstree iteration API (iwstree.h)
* Added `iwpool_used_size` (iwpool.h)
* Added `iwstree_int64_cmp` (iwstree.h)
* Added `IW_DEPRECATED` (basedefs.h)
-- Anton Adamansky <adamansky@gmail.com> Thu, 18 Jun 2020 14:19:32 +0700
iowow (1.4.4) testing; urgency=medium
* Fixed incorrect copying of cursor key data in `IWDB_COMPOUND_KEYS` mode (iwkv.c)
* Adde compound key example code (compoundkeys1.c)
* Added `iwstree_visit` (iwstree.h)
-- Anton Adamansky <adamansky@gmail.com> Sat, 02 May 2020 19:38:31 +0700
iowow (1.4.3) testing; urgency=medium
* Fixed errors found by PVS studio
-- Anton Adamansky <adamansky@gmail.com> Fri, 24 Apr 2020 00:16:42 +0700
iowow (1.4.2) testing; urgency=medium
* Added IWULIST, IWLIST implementation (iwarr.h)
* Added iwpool_split_string (iwpool.h)
* Added iwpool_printf (iwpool.h)
* Added iwpool_printf_split (iwpool.h)
* Added iwxstr_shift (iwxstr.h)
* Added `#define RCHECK` (basedefs.h)
* Better error handling of `kh_put`
-- Anton Adamansky <adamansky@gmail.com> Mon, 20 Apr 2020 16:23:50 +0700
iowow (1.4.1) testing; urgency=medium
* Fixed possible data corruption in `_fsm_blk_allocate_aligned_lw` (iwfsmfile.c)
* Better new SBLK blocks locality (performance)
-- Anton Adamansky <adamansky@gmail.com> Sat, 07 Mar 2020 23:23:13 +0700
iowow (1.4.0) testing; urgency=medium
* Implemented new compact and performant data storage format v2
* Added WiredTiger v3.2.1 benchmarks
* Added BerkeleyDB v5.3.28 benchmarks
* Added TokyoCabinet v1.4.48 benchmarks
-- Anton Adamansky <adamansky@gmail.com> Fri, 06 Mar 2020 23:23:16 +0700
iowow (1.3.37) testing; urgency=medium
* Added iwrc iwp_mkdirs(const char *path) (iwp.h)
* Added uint32_t iwu_x31_u32_hash(const char *s) (iwutils.h)
* Added iwu_replace() (iwutils.h)
* Added RCA( macro definition
* Removed IW_EXPORT iwrc iwkv_db_last_access_time(IWDB db, uint64_t *ts)
for performance and simplicity reasons
* Added `IW_ERROR_INVALID_VALUE`
* Added iwstree - splay tree imlementation (iwstree.h)
* Pointers allocated by iwpool are now 8-byte aligned
-- Anton Adamansky <adamansky@gmail.com> Mon, 17 Feb 2020 23:16:31 +0700
iowow (1.3.36) testing; urgency=medium
* Safer iowow initialization bootstrap process.
-- Anton Adamansky <adamansky@gmail.com> Thu, 16 Jan 2020 12:44:31 +0700
iowow (1.3.35) testing; urgency=medium
* Added specific checks for TARGET_OS_IPHONE
* Ported to iOS
* Added wal locking interceptor to WAL opts
-- Anton Adamansky <adamansky@gmail.com> Wed, 15 Jan 2020 13:10:51 +0700
iowow (1.3.32) testing; urgency=medium
* Improved WAL durability
-- Anton Adamansky <adamansky@gmail.com> Thu, 19 Dec 2019 10:49:08 +0700
iowow (1.3.31) testing; urgency=medium
* Keys comparison refactoring
-- Anton Adamansky <adamansky@gmail.com> Wed, 20 Nov 2019 00:41:15 +0700
iowow (1.3.30) testing; urgency=medium
* Added check if __unused is already defined in `iwth.c`
* CRITICAL Comparsions keys fix #30
-- Anton Adamansky <adamansky@gmail.com> Tue, 19 Nov 2019 20:23:41 +0700
iowow (1.3.29) testing; urgency=medium
* FIXED iwkv_open assertion fail on opening garbage file #29
-- Anton Adamansky <adamansky@gmail.com> Wed, 13 Nov 2019 23:55:35 +0700
iowow (1.3.28) testing; urgency=medium
* iwlog now supports ANDROID NDK logging (iwlog.h)
-- Anton Adamansky <adamansky@gmail.com> Thu, 07 Nov 2019 14:44:59 +0700
iowow (1.3.27) testing; urgency=medium
* CRITICAL WAL durability fixes
* Support of online backups #24
* Windows platform functions fixes
* CLion project files added
* WAL recovering fixes
-- Anton Adamansky <adamansky@gmail.com> Mon, 28 Oct 2019 19:08:59 +0700
iowow (1.3.25) testing; urgency=medium
* CRITICAL Fixed heap corruption due incorrect usage of khash API in `_db_destroy_lw` (iwkv.c)
-- Anton Adamansky <adamansky@gmail.com> Thu, 29 Aug 2019 12:20:25 +0700
iowow (1.3.24) testing; urgency=medium
* CRITICAL Fixed race condition in WAL rollforward
-- Anton Adamansky <adamansky@gmail.com> Thu, 22 Aug 2019 02:04:08 +0700
iowow (1.3.23) testing; urgency=medium
* WAL refactoring, better stability
-- Anton Adamansky <adamansky@gmail.com> Sat, 17 Aug 2019 21:17:05 +0700
iowow (1.3.22) testing; urgency=medium
* Small optimizations in `iwfsmfile.c`
* Added `iwp_clock_get_time` as portable version of `clock_gettime`
* `static_assert` is set to `_Static_assert` if not defined
* Added `__USE_MINGW_ANSI_STDIO` for MinGW build
-- Anton Adamansky <adamansky@gmail.com> Thu, 18 Jul 2019 17:50:14 +0700
iowow (1.3.20) testing; urgency=medium
* CRITICAL Fixed incorrect keys allocation in IWDB_COMPOUND_KEYS mode
-- Anton Adamansky <adamansky@gmail.com> Thu, 13 Jun 2019 21:43:47 +0700
iowow (1.3.19) testing; urgency=medium
* CRITICAL: Fixed assertion fail in iwkv records cache
-- Anton Adamansky <adamansky@gmail.com> Thu, 13 Jun 2019 19:08:48 +0700
iowow (1.3.18) testing; urgency=medium
* Limit one time file allocation step to 2G
-- Anton Adamansky <adamansky@gmail.com> Wed, 12 Jun 2019 16:42:47 +0700
iowow (1.3.17) testing; urgency=medium
* CRITICAL: State of previously deleted database may have influence on newly created dbs
* BUG: Fixed database metadata blocks leak (db->meta_blk) on database destroy
-- Anton Adamansky <adamansky@gmail.com> Fri, 03 May 2019 18:20:39 +0700
iowow (1.3.16) testing; urgency=medium
* CRITICAL: Fixed deadlock on database removal
-- Anton Adamansky <adamansky@gmail.com> Fri, 03 May 2019 11:56:29 +0700
iowow (1.3.15) testing; urgency=medium
* CRITICAL: Fixed database file corruption during sequential records deletion with `iwkv_cursor_del` (iwkv.c)
-- Anton Adamansky <adamansky@gmail.com> Wed, 01 May 2019 23:29:18 +0700
iowow (1.3.14) testing; urgency=medium
* CRITICAL: Fixed unexpected database file truncation and data loss on close.
* Adjusted default WAL options for Android
-- Anton Adamansky <adamansky@gmail.com> Sat, 27 Apr 2019 01:04:28 +0700
iowow (1.3.13) testing; urgency=medium
* Performance impovements in Write Ahead Logging (iwal.c)
* BUG: WAL file was not truncated after `wal->checkpoint_timeout_sec` timeout (iwal.c)
-- Anton Adamansky <adamansky@gmail.com> Thu, 25 Apr 2019 17:43:06 +0700
iowow (1.3.12) testing; urgency=medium
* Android NDK support (#23)
* Pthreads `PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP` is used by default
-- Anton Adamansky <adamansky@gmail.com> Sun, 21 Apr 2019 12:18:16 +0700
iowow (1.3.11) testing; urgency=medium
* Added size_t iwpool_allocated_size(IWPOOL *pool) (iwpool.h)
* Added `file_lock_fail_fast` iwkv open option.
If `true` - do not wait and raise error if database is locked by another process
* Fixed meaningful PVP studio errors:
- kv/iwkv.c:593:1: error: V774
- kv/iwkv.c:1375:1: warning: V649
- kv/iwkv.c:3357:1: warning: V581
- utils/iwxstr.c:59:1: warning: V701
-- Anton Adamansky <adamansky@gmail.com> Mon, 08 Apr 2019 11:47:59 +0700
iowow (1.3.10) testing; urgency=medium
* Added cmake `OWNER_PROJECT_NAME` option used to install header files in `CMAKE_INSTALL_INCLUDEDIR}/OWNER_PROJECT_NAME/PROJECT_NAME`
* Removed `-fvisibility=hidden` C flag when building shared library
-- Anton Adamansky <adamansky@gmail.com> Fri, 05 Apr 2019 11:53:34 +0700
iowow (1.3.9) testing; urgency=medium
* BUG `IW_HAVE_PTHREAD_CONDATTR_SETCLOCK` was not properly set for `iwal.c` hence high CPU usage when `wal` mode is on.
-- Anton Adamansky <adamansky@gmail.com> Fri, 29 Mar 2019 23:56:25 +0700
iowow (1.3.8) testing; urgency=medium
* BUG Fixed incorrect call of `_kvblk_kv_get` in `iwkv_cursor_seth`.
See https://github.com/Softmotions/ejdb/issues/231
-- Anton Adamansky <adamansky@gmail.com> Wed, 27 Mar 2019 12:34:10 +0700
iowow (1.3.7) testing; urgency=medium
* Added `iwkv_cursor_del()` (#22)
* Fixed memory corruption during simultaneous cursor iteration and value updating
-- Anton Adamansky <adamansky@gmail.com> Tue, 26 Mar 2019 18:24:35 +0700
iowow (1.3.6) testing; urgency=medium
* BUG: Memory leak in `iwkv_cursor_open` on error (#21)
* BUG: `iwxstr_new2()` with zero size argument causes illegal memory write (#20)
* Added `iwkv_cursor_seth()` record update handle supported by `iwkv_cursor_set`
* Avoided deadlocks with `iwkv_del()` - now this function does't escalate exclusive lock on storage
* More consistent error reporting using cursor functions
-- Anton Adamansky <adamansky@gmail.com> Fri, 22 Mar 2019 16:29:32 +0700
iowow (1.3.5) testing; urgency=medium
* BUG: Data from deleted database can interfere with newly created db (#19)
-- Anton Adamansky <adamansky@gmail.com> Wed, 20 Mar 2019 20:26:22 +0700
iowow (1.3.4) testing; urgency=medium
* Code documentation improvements
-- Anton Adamansky <adamansky@gmail.com> Mon, 11 Mar 2019 22:42:51 +0700
iowow (1.3.3) testing; urgency=medium
* BUG: `iwkv_puth` called with incorrect previous value (iwkv.h)
* _kvblk_getvalue renamed to _kvblk_value_get (iwkv.c)
* _kvblk_peek_val renamed to _kvblk_value_peek (iwkv.c)
* _kvblk_getkey renamed to _kvblk_key_get (iwkv.c)
* _kvblk_getkv renamed to _kvblk_kv_get (iwkv.c)
-- Anton Adamansky <adamansky@gmail.com> Fri, 08 Mar 2019 17:02:46 +0700
iowow (1.3.2) testing; urgency=medium
* Added `iwkv_cursor_is_matched_key` (iwkv.h)
* `iwkv_cursor_copy_key` now aware of `IWDB_COMPOUND_KEYS` mode (iwkv.h)
* `iwkv_cursor_copy_key` can accept zero kbuf,kbufsz only compound part will returned in this case (iwkv.h)
-- Anton Adamansky <adamansky@gmail.com> Mon, 04 Mar 2019 20:50:03 +0700
iowow (1.3.1) testing; urgency=medium
* Eliminate adaptive `IWDB_VNUM64_KEYS` key sizing in `_unpack_effective_key` for the sake of API simplicity (iwkv.c)
* BUG: incorrect key handling in `iwkv_del` - key was not unpacked before. (iwkv.h)
-- Anton Adamansky <adamansky@gmail.com> Thu, 28 Feb 2019 10:40:11 +0700
iowow (1.3.0) testing; urgency=medium
* `IWKV_PUT_HANDLER` called for insert operations (not only for updates)
* Added `IWFS_OUNLINK` flag. Unlink(delete) file on close (iwfile.h)
* Added `IWFS_OTMP` flag. Create tmp file (iwfile.h)
* Added UUID v4 generation function (iwuuid.h)
* Added iwp_tmpdir() (iwp.h)
* Added iwp_allocate_tmpfile_path() (iwp.h)
* Added iwxstr_printf() (iwxstr.h)
* Added iwxstr_cat2() (iwxstr.h)
* Added `IWKV_VAL_INCREMENT` mode for `iwkv_put()` and test case (iwkv.h)
* Added support of variable-length encoded integer keys `IWDB_VNUM64_KEYS` (iwkv.h)
* Added support of compound keys (`IWDB_COMPOUND_KEYS`) (#18)
* Removed `dup` integer value routines
* Code cleanup and refactoring
-- Anton Adamansky <adamansky@gmail.com> Wed, 27 Feb 2019 12:11:48 +0700
iowow (1.2.14) testing; urgency=medium
* BUG: Fix WAL checkpoint workflow to avoid deadlocks with cursor threads
* BUG: Clang6 fatal error: variable 'cur' is used uninitialized (#15)
* Implemented new multithreaded stress test (iwkv_test6.c) used OMP stack
* Added iwkv_new_db(IWKV iwkv, iwdb_flags_t dbflg, uint32_t *odbid, IWDB *dbp) (iwkv.h)
* Removed unused `IWKV_NOLOCKS` option.
* Added `IW_EXPORT` to `iowow_version_*` API functions (iowow.h)
* Added iwrc iwkv_state(IWKV iwkv, IWFS_FSM_STATE *out) (iwkv.h)
* Do not check `IWKV_NO_OVERWRITE` for databases in `IWDB_DUP_UINTXX_VALS` mode
* Added iwkv_puth() with provided old value interceptor: `IWKV_PUT_HANDLER` (iwkv.h)
* Added `IWKV_RC_DUP_ARRAY_EMPTY` flag and `IWKV_DUP_REPORT_EMPTY` opflag for `iwkv_put()` (iwkv.h)
-- Anton Adamansky <adamansky@gmail.com> Tue, 06 Nov 2018 23:14:39 +0700
iowow (1.2.13) testing; urgency=medium
* BUG: Correct cursors adjustments during db update operations (#13)
* BUG: Fixed WAL integration for updates in IWDB_DUP_UINT32_VALS|IWDB_DUP_UINT64_VALS mode
* Store arbitrary data blocks associated with iwkv internal databases (#12)
* Checking of max key/value size (IWKV_MAX_KVSZ) for updates in IWDB_DUP_UINT32_VALS|IWDB_DUP_UINT64_VALS mode
* Minor allocation performance optimizations in _kvblk_addkv()
-- Anton Adamansky <adamansky@gmail.com> Thu, 02 Aug 2018 20:29:08 +0700
iowow (1.2.12) testing; urgency=medium
* Set terminating '\0' in iwitoa() (iwconv.h)
* Added MAP_NORESERVE option for PRIVATE mmaping on Linux (#11)
* Added iwu_file_read_as_buf() (iwutils.h)
* Optimized cmake config files generation
-- Anton Adamansky <adamansky@gmail.com> Sat, 21 Jul 2018 01:59:40 +0700
iowow (1.2.11) testing; urgency=medium
* iwpool refactoring fixed pool memory corruption (iwpool.h)
* Fixed set terminating `\0` in iwpool_strdup() (iwpool.h)
* Fixed wrong `if` in iwpool_calloc() (iwpool.h)
-- Anton Adamansky <adamansky@gmail.com> Fri, 15 Jun 2018 17:58:20 +0700
iowow (1.2.10) testing; urgency=medium
* Added iwpool_calloc() (iwpool.h)
* Added iwpool_strdup(), iwpool_strndup() (iwpool.h)
* Fixed memory leak in iwpool_destroy() (iwpool.h)
* Renamed platform/linux/linux.c to platform/unix/unix.c (#9)
* Added iwu_replace_char() (iwutils.h)
-- Anton Adamansky <adamansky@gmail.com> Mon, 11 Jun 2018 23:00:21 +0700
iowow (1.2.9) testing; urgency=medium
* Rewrite of iwftoa() (iwconv.h)
* Fixed typo: iwtoa renamed to iwitoa (iwconv.h)
* Added iwu_cmp_files (iwutils.h)
* Return type of iwxstr_ptr() changed to char* (iwxstr.h)
-- Anton Adamansky <adamansky@gmail.com> Tue, 29 May 2018 01:01:56 +0700
iowow (1.2.8) testing; urgency=medium
* IOWOW Ported to MIPS32 (big-endian) tested on Debian GNU/Linux 9.4
-- Anton Adamansky <adamansky@gmail.com> Sat, 19 May 2018 21:09:04 +0700
iowow (1.2.7) testing; urgency=medium
* Fixed incorrect exclusive locking in iwkv_del()"
-- Anton Adamansky <adamansky@gmail.com> Thu, 17 May 2018 11:27:58 +0700
iowow (1.2.6) testing; urgency=medium
* Fixed: database file is not created automatically if no open modes specified in opts
-- Anton Adamansky <adamansky@gmail.com> Wed, 16 May 2018 19:57:35 +0700
iowow (1.2.5) testing; urgency=medium
* Added iwkv_opflags opflags into iwkv_del
-- Anton Adamansky <adamansky@gmail.com> Wed, 16 May 2018 19:33:16 +0700
iowow (1.2.4) testing; urgency=medium
* Fixed race conditions in iwkv_cursor_to()
-- Anton Adamansky <adamansky@gmail.com> Mon, 14 May 2018 09:28:13 +0700
iowow (1.2.3) testing; urgency=medium
* Fixed race conditions in iwkv_cursor_set()
-- Anton Adamansky <adamansky@gmail.com> Fri, 11 May 2018 23:17:13 +0700
iowow (1.2.2) testing; urgency=medium
* Added static iowow_s libraries to the default CMake exports.
-- Anton Adamansky <adamansky@gmail.com> Tue, 08 May 2018 22:58:41 +0700
iowow (1.2.1) testing; urgency=medium
* Removed unistd.h from src/fs/iwdlsnr.h since it is not portable.
* C++ friendly header files
-- Anton Adamansky <adamansky@gmail.com> Mon, 07 May 2018 12:47:46 +0700
iowow (1.2.0) testing; urgency=medium
* IOWOW ported to Windows x86-64 platform #1
-- Anton Adamansky <adamansky@gmail.com> Sun, 06 May 2018 20:35:14 +0700
iowow (1.1.0) testing; urgency=medium
* Write Ahead Log (WAL) implemented #2
* Changed database block size to 128 bytes so max db size 512Gb
WARNING: Database format of version 1.1.x is incompatible with previous versions.
* Better basename/basename_r detection in iwlog.c #4
-- Anton Adamansky <adamansky@gmail.com> Wed, 02 May 2018 17:28:14 +0700
iowow (1.0.6) testing; urgency=medium
* src/CMakeLists.txt cleanups #3
* x86-specific code in src/platform/iwp.c is not guarded #7
* Database size limited to 2GB on 32 bit CPUs #5
* Database block size changed: 64 to 128 bytes #8
-- Anton Adamansky <adamansky@gmail.com> Mon, 16 Apr 2018 10:21:00 +0700
iowow (1.0.5) testing; urgency=medium
* iwextfile: do msync before munmap on file resizing
-- Anton Adamansky <adamansky@gmail.com> Thu, 12 Apr 2018 20:48:26 +0700
iowow (1.0.4) testing; urgency=medium
* Added IWFSM_SYNC_BMAP option to iwfs_fsm_aflags
* Removed IWFS_NO_MMASYNC since it does noop on many platforms
* Set exclusive iwkv write lock in iwkv_sync()
-- Anton Adamansky <adamansky@gmail.com> Thu, 12 Apr 2018 12:33:53 +0700
iowow (1.0.3) testing; urgency=medium
* Added basic iowow.3 man page to distribution archive
* Use posix_fallocate() to extend iwkv file instead of ftruncate() on Linux/FreeBSD
-- Anton Adamansky <adamansky@gmail.com> Tue, 10 Apr 2018 18:56:11 +0700
iowow (1.0.2) testing; urgency=medium
* Removed unneeded -D_LARGE_FILE_SOURCE from iowow.h
-- Anton Adamansky <adamansky@gmail.com> Mon, 09 Apr 2018 13:56:53 +0700
iowow (1.0.1) testing; urgency=medium
* Fix export flags iwlog2 method
-- Anton Adamansky <adamansky@gmail.com> Mon, 09 Apr 2018 12:44:23 +0700
iowow (1.0.0) testing; urgency=medium
* Initial release.
-- Anton Adamansky <adamansky@gmail.com> Sun, 08 Apr 2018 14:21:43 +0700
+1
View File
@@ -0,0 +1 @@
# TODO
+37
View File
@@ -0,0 +1,37 @@
PROJECT_NAME = "@CMAKE_PROJECT_NAME@"
PROJECT_NUMBER = @PROJECT_VERSION@
STRIP_FROM_PATH = @PROJECT_SOURCE_DIR@ \
@PROJECT_BINARY_DIR@
INPUT = @PROJECT_SOURCE_DIR@/src/DOXYMAIN.md \
@PROJECT_SOURCE_DIR@ \
@PROJECT_BINARY_DIR@/src/generated
FILE_PATTERNS = *.h \
*.md
EXCLUDE = @PROJECT_SOURCE_DIR@/src/utils/kbtree.h \
@PROJECT_SOURCE_DIR@/src/utils/khash.h \
@PROJECT_SOURCE_DIR@/README.md
RECURSIVE = YES
USE_MDFILE_AS_MAINPAGE = DOXYMAIN.md
MARKDOWN_SUPPORT = YES
GENERATE_LATEX = NO
WARNINGS = YES
WARN_IF_DOC_ERROR = YES
WARN_IF_UNDOCUMENTED = NO
SEARCHENGINE = NO
HTML_DYNAMIC_SECTIONS = NO
INLINE_SIMPLE_STRUCTS = NO
OPTIMIZE_OUTPUT_FOR_C = YES
TYPEDEF_HIDES_STRUCT = YES
HIDE_UNDOC_CLASSES = YES
HIDE_UNDOC_MEMBERS = YES
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = NO
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2012-2020 Softmotions Ltd <info@softmotions.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-36
View File
@@ -1,36 +0,0 @@
# third_party_iowow
#### Description
{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**}
#### Software Architecture
Software architecture description
#### Installation
1. xxxx
2. xxxx
3. xxxx
#### Instructions
1. xxxx
2. xxxx
3. xxxx
#### Contribution
1. Fork the repository
2. Create Feat_xxx branch
3. Commit your code
4. Create Pull Request
#### Gitee Feature
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
4. The most valuable open source project [GVP](https://gitee.com/gvp)
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
+331 -27
View File
@@ -1,39 +1,343 @@
# third_party_iowow
IOWOW - The C11 persistent key/value database engine based on [skip list](https://en.wikipedia.org/wiki/Skip_list)
==================================================================================================================
#### 介绍
{**以下是 Gitee 平台说明,您可以替换此简介**
Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN)。专为开发者提供稳定、高效、安全的云端软件开发协作平台
无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)}
![Build Status](https://dev.softmotions.com/jenkins/buildStatus/icon?job=iowow_test)
[![Join ejdb2 telegram](https://img.shields.io/badge/join-ejdb2%20telegram-0088cc.svg)](https://t.me/ejdb2)
[![license](https://img.shields.io/github/license/Softmotions/ejdb.svg)](https://github.com/Softmotions/iowow/blob/master/LICENSE)
![Maintained](https://img.shields.io/maintenance/yes/2020.svg)
#### 软件架构
软件架构说明
Website http://iowow.io
# Key components
* [iwkv.h](https://github.com/Softmotions/iowow/blob/master/src/kv/iwkv.h) Persistent key/value database engine
* [iwfsmfile.h](https://github.com/Softmotions/iowow/blob/master/src/fs/iwfsmfile.h) File blocks allocation manager like `malloc()` on files
# IWKV
## Features
* Support of multiple key-value databases within a single file
* Online database backups
* Native support of integer keys
* [Write Ahead Logging (WAL) support](http://iowow.io/wal)
* Ultra-fast traversal of database records
* Compound keys support
* Good performance comparing its main competitors: `lmdb`, `leveldb`, `kyoto cabinet`
* Tiny C11 library (200Kb) can be easily embedded into any software
[![Presentation](https://iowow.io/articles/iowow-presentation-cover-small.png)](https://iowow.io/articles/intro/)
#### 安装教程
## Used by
1. xxxx
2. xxxx
3. xxxx
* EJDB - Embeddable JSON database engine. http://ejdb.org
#### 使用说明
## Limitations
1. xxxx
2. xxxx
3. xxxx
* Maximum iwkv storage file size: `512 GB (0x7fffffff80)`
* Total size of a single key+value record must be not greater than `255Mb (0xfffffff)`
* In-memory cache for every opened database takes `~130Kb`, cache can be disposed by `iwkv_db_cache_release()`
#### 参与贡献
# Supported platforms
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
## Linux
### Ubuntu/Debian
#### PPA repository
```sh
sudo add-apt-repository ppa:adamansky/iwowow
sudo apt-get update
sudo apt-get install iowow
```
#### Building debian packages
```sh
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DPACKAGE_DEB=ON
make package
```
### RPM based Linux distributions
```sh
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DPACKAGE_RPM=ON
make package
```
## FreeBSD
Successfully tested on FreeBSD 10/11
## OSX
Successfully tested on OSX 10.12/10.13
## Windows
[Cross-compilation for windows](http://iowow.io/iw/win)
#### 特技
## MIPS based systems (+big-endian)
Successfully tested on Debian 9.4, MIPS 32, gcc 6.x compiler.
# Examples
[src/kv/examples](https://github.com/Softmotions/iowow/tree/master/src/kv/examples)
## Store and retrieve records
```c
#include <iowow/iwkv.h>
#include <string.h>
#include <stdlib.h>
int main() {
IWKV_OPTS opts = {
.path = "example1.db",
.oflags = IWKV_TRUNC // Cleanup database before open
};
IWKV iwkv;
IWDB mydb;
iwrc rc = iwkv_open(&opts, &iwkv);
if (rc) {
iwlog_ecode_error3(rc);
return 1;
}
// Now open mydb
// - Database id: 1
rc = iwkv_db(iwkv, 1, 0, &mydb);
if (rc) {
iwlog_ecode_error2(rc, "Failed to open mydb");
return 1;
}
// Work with db: put/get value
IWKV_val key, val;
key.data = "foo";
key.size = strlen(key.data);
val.data = "bar";
val.size = strlen(val.data);
fprintf(stdout, "put: %.*s => %.*s\n",
(int) key.size, (char *) key.data,
(int) val.size, (char *) val.data);
rc = iwkv_put(mydb, &key, &val, 0);
if (rc) {
iwlog_ecode_error3(rc);
return rc;
}
// Retrieve value associated with `foo` key
val.data = 0;
val.size = 0;
rc = iwkv_get(mydb, &key, &val);
if (rc) {
iwlog_ecode_error3(rc);
return rc;
}
fprintf(stdout, "get: %.*s => %.*s\n",
(int) key.size, (char *) key.data,
(int) val.size, (char *) val.data);
iwkv_val_dispose(&val);
iwkv_close(&iwkv);
return 0;
}
```
**Compile and run:**
```sh
gcc -std=gnu11 -Wall -pedantic -c -o example1.o example1.c
gcc -o example1 example1.o -liowow
./example1
put: foo => bar
get: foo => bar
```
## Cursor iteration example
```c
///
/// Fills database with a set of football table records
/// then traverse records according to club name in ascending and descending orders.
///
#include "iwkv.h"
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
static struct data_s {
const char *club;
uint8_t points;
} _points[] = {
{ "Aston Villa", 25 },
{ "Manchester City", 57 },
{ "Arsenal", 40 },
{ "Everton", 37 },
{ "West Ham United", 27 },
{ "Tottenham Hotspur", 41 },
{ "Wolverhampton Wanderers", 43 },
{ "Norwich City", 21 },
{ "Leicester City", 53 },
{ "Manchester United", 45 },
{ "Newcastle United", 35 },
{ "Brighton & Hove Albion", 29 },
{ "AFC Bournemouth", 27 },
{ "Crystal Palace", 39 },
{ "Sheffield United", 43 },
{ "Burnley", 39 },
{ "Southampton", 34 },
{ "Watford", 27 },
{ "Chelsea", 48 },
{ "Liverpool", 82 },
};
static iwrc run(void) {
IWKV_OPTS opts = {
.path = "cursor1.db",
.oflags = IWKV_TRUNC // Cleanup database before open
};
IWKV iwkv;
IWDB db;
IWKV_cursor cur = 0;
iwrc rc = iwkv_open(&opts, &iwkv);
RCRET(rc);
rc = iwkv_db(iwkv, 1, 0, &db);
RCGO(rc, finish);
for (int i = 0; i < sizeof(_points) / sizeof(_points[0]); ++i) {
struct data_s *n = &_points[i];
IWKV_val key = { .data = (void *) n->club, .size = strlen(n->club) };
IWKV_val val = { .data = &n->points, .size = sizeof(n->points) };
RCC(rc, finish, iwkv_put(db, &key, &val, 0));
}
fprintf(stdout, ">>>> Traverse in descending order\n");
RCC(rc, finish, iwkv_cursor_open(db, &cur, IWKV_CURSOR_BEFORE_FIRST, 0));
while ((rc = iwkv_cursor_to(cur, IWKV_CURSOR_NEXT)) == 0) {
IWKV_val key, val;
RCC(rc, finish, iwkv_cursor_get(cur, &key, &val));
fprintf(stdout, "%.*s: %u\n",
(int) key.size, (char *) key.data,
*(uint8_t *) val.data);
iwkv_kv_dispose(&key, &val);
}
rc = 0;
iwkv_cursor_close(&cur);
fprintf(stdout, "\n>>>> Traverse in ascending order\n");
RCC(rc, finish, iwkv_cursor_open(db, &cur, IWKV_CURSOR_AFTER_LAST, 0));
while ((rc = iwkv_cursor_to(cur, IWKV_CURSOR_PREV)) == 0) {
IWKV_val key, val;
RCC(rc, finish, iwkv_cursor_get(cur, &key, &val));
fprintf(stdout, "%.*s: %u\n",
(int) key.size, (char *) key.data,
*(uint8_t *) val.data);
iwkv_kv_dispose(&key, &val);
}
rc = 0;
iwkv_cursor_close(&cur);
// Select all keys greater or equal than: Manchester United
{
fprintf(stdout, "\n>>>> Records GE: %s\n", _points[9].club);
IWKV_val key = { .data = (void *) _points[9].club, .size = strlen(_points[9].club) }, val;
RCC(rc, finish, iwkv_cursor_open(db, &cur, IWKV_CURSOR_GE, &key));
do {
RCC(rc, finish, iwkv_cursor_get(cur, &key, &val));
fprintf(stdout, "%.*s: %u\n",
(int) key.size, (char *) key.data,
*(uint8_t *) val.data);
iwkv_kv_dispose(&key, &val);
} while ((rc = iwkv_cursor_to(cur, IWKV_CURSOR_NEXT)) == 0);
rc = 0;
}
iwkv_cursor_close(&cur);
finish:
if (cur) {
iwkv_cursor_close(&cur);
}
iwkv_close(&iwkv);
return rc;
}
int main() {
iwrc rc = run();
if (rc) {
iwlog_ecode_error3(rc);
return 1;
}
return 0;
}
```
Output:
```
>>>> Traverse in descending order
Wolverhampton Wanderers: 43
West Ham United: 27
Watford: 27
Tottenham Hotspur: 41
Southampton: 34
Sheffield United: 43
Norwich City: 21
Newcastle United: 35
Manchester United: 45
Manchester City: 57
Liverpool: 82
Leicester City: 53
Everton: 37
Crystal Palace: 39
Chelsea: 48
Burnley: 39
Brighton & Hove Albion: 29
Aston Villa: 25
Arsenal: 40
AFC Bournemouth: 27
>>>> Traverse in ascending order
AFC Bournemouth: 27
Arsenal: 40
Aston Villa: 25
Brighton & Hove Albion: 29
Burnley: 39
Chelsea: 48
Crystal Palace: 39
Everton: 37
Leicester City: 53
Liverpool: 82
Manchester City: 57
Manchester United: 45
Newcastle United: 35
Norwich City: 21
Sheffield United: 43
Southampton: 34
Tottenham Hotspur: 41
Watford: 27
West Ham United: 27
Wolverhampton Wanderers: 43
>>>> Records GE: Manchester United
Manchester United: 45
Manchester City: 57
Liverpool: 82
Leicester City: 53
Everton: 37
Crystal Palace: 39
Chelsea: 48
Burnley: 39
Brighton & Hove Albion: 29
Aston Villa: 25
Arsenal: 40
AFC Bournemouth: 27
```
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
+45
View File
@@ -0,0 +1,45 @@
# Cross compilation
## Prerequisites
```sh
sudo apt-get install bison flex libtool ruby scons intltool libtool-bin p7zip-full wine wine32
```
## Build
### Prepare MXE
```sh
git submodule update --init
```
`nano ./mxe/settings.mk`:
```
JOBS := 1
MXE_TARGETS := x86_64-w64-mingw32.static
LOCAL_PKG_LIST := cunit libiberty
.DEFAULT local-pkg-list:
local-pkg-list: $(LOCAL_PKG_LIST)
```
```
cd ./mxe
make
```
### Cross compilation
```
mkdir ./build
cd ./build
export MXE_HOME=<path to project>/mxe
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../win64-tc.cmake \
-DBUILD_TESTS=ON -DTEST_TOOL_CMD=wine
make package
```
+54
View File
@@ -0,0 +1,54 @@
## -*- mode:cmake; coding:utf-8; -*-
# Set output:
# CHANGELOG_LAST_LINE
# CHANGELOG_LAST_VERSION - Last changelog version
# CHANGELOG_LAST_VERSION_MAJOR - Last changelog major version
# CHANGELOG_LAST_VERSION_MINOR - Last changelog minor version
# CHANGELOG_LAST_VERSION_PATCH - Last changelog patch version
# CHANGELOG_LAST_MESSAGE - Last changelog description
if (NOT DEB_CHANGELOG)
set(DEB_CHANGELOG "${CMAKE_SOURCE_DIR}/Changelog")
endif()
if (NOT EXISTS ${DEB_CHANGELOG})
if (DEB_CHANGELOG_REQUIRED)
message(FATAL_ERROR "Missing required project changelog file: ${DEB_CHANGELOG}")
else()
message("Missing project changelog file: ${DEB_CHANGELOG}")
return()
endif()
endif()
message(STATUS "Using project changelog file: ${DEB_CHANGELOG}")
file(STRINGS "${DEB_CHANGELOG}" _DEBCHANGELOGN)
foreach(CLINE IN LISTS _DEBCHANGELOGN)
if (NOT CHANGELOG_LAST_VERSION)
#ejdb (1.2.6) testing; urgency=low
string(REGEX MATCH "^[A-Za-z0-9_].*[ \t]+\\((([0-9]+)\\.([0-9]+)\\.([0-9]+))\\)[ \t]+[A-Za-z]+;[ \t].*" _MATCHED "${CLINE}")
if (_MATCHED)
set(CHANGELOG_LAST_LINE "${_MATCHED}")
set(CHANGELOG_LAST_VERSION "${CMAKE_MATCH_1}")
set(CHANGELOG_LAST_VERSION_MAJOR "${CMAKE_MATCH_2}")
set(CHANGELOG_LAST_VERSION_MINOR "${CMAKE_MATCH_3}")
set(CHANGELOG_LAST_VERSION_PATCH "${CMAKE_MATCH_4}")
endif()
elseif(NOT CHANGELOG_LAST_MESSAGE)
string(REGEX MATCH "^[A-Za-z0-9_].*[ \t]+\\((([0-9]+)\\.([0-9]+)\\.([0-9]+))\\)[ \t]+[A-Za-z]+;[ \t].*" _MATCHED "${CLINE}")
if (_MATCHED)
string(STRIP "${_CDESC}" CHANGELOG_LAST_MESSAGE)
return()
endif()
if (CLINE)
string(REGEX MATCH "^[ \t]*\\-\\-[ \t]+" _MATCHED "${CLINE}")
if (_MATCHED)
string(STRIP "${_CDESC}" CHANGELOG_LAST_MESSAGE)
return()
endif()
set(_CDESC "${_CDESC}\n${CLINE}")
endif()
endif()
endforeach(CLINE)
message(FATAL_ERROR "Invalid changelog file: ${DEB_CHANGELOG}")
+7
View File
@@ -0,0 +1,7 @@
# - Try to find libatomic
# ATOMIC_FOUND - System has ATOMIC
# ATOMIC_LIBRARY
include(FindPackageHandleStandardArgs)
find_library(ATOMIC_LIBRARY NAMES atomic atomic.so.1 libatomic.so.1)
find_package_handle_standard_args(atomic DEFAULT_MSG ATOMIC_LIBRARY)
mark_as_advanced(ATOMIC_LIBRARY)
+24
View File
@@ -0,0 +1,24 @@
# Find the CUnit headers and libraries
#
# CUNIT_INCLUDE_DIRS - The CUnit include directory (directory where CUnit/CUnit.h was found)
# CUNIT_LIBRARIES - The libraries needed to use CUnit
# CUNIT_FOUND - True if CUnit found in system
FIND_PATH(CUNIT_INCLUDE_DIR NAMES CUnit/CUnit.h)
MARK_AS_ADVANCED(CUNIT_INCLUDE_DIR)
FIND_LIBRARY(CUNIT_LIBRARY NAMES
cunit
libcunit
cunitlib
)
MARK_AS_ADVANCED(CUNIT_LIBRARY)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(CUnit DEFAULT_MSG CUNIT_LIBRARY CUNIT_INCLUDE_DIR)
IF(CUNIT_FOUND)
SET(CUNIT_LIBRARIES ${CUNIT_LIBRARY})
SET(CUNIT_INCLUDE_DIRS ${CUNIT_INCLUDE_DIR})
ENDIF(CUNIT_FOUND)
+40
View File
@@ -0,0 +1,40 @@
# - Find Iberty
# This module finds libiberty.
#
# It sets the following variables:
# IBERTY_LIBRARIES - The libiberty library to link against.
# For Debian <= wheezy, use libiberty_pic.a from binutils-dev
# For Debian >= jessie, use libiberty.a from libiberty-dev
# For all RHEL/Fedora, use libiberty.a from binutils-devel
FIND_LIBRARY( IBERTY_LIBRARIES
NAMES iberty_pic iberty
HINTS ${IBERTY_LIBRARIES}
PATHS
/usr/lib
/usr/lib64
/usr/local/lib
/usr/local/lib64
/opt/local/lib
/opt/local/lib64
/sw/lib
ENV LIBRARY_PATH
ENV LD_LIBRARY_PATH
)
IF (IBERTY_LIBRARIES)
# show which libiberty was found only if not quiet
MESSAGE( STATUS "Found libiberty: ${IBERTY_LIBRARIES}")
SET(IBERTY_FOUND TRUE)
ELSE (IBERTY_LIBRARIES)
IF (IBERTY_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find libiberty. Try to install binutil-devel?")
ELSE()
MESSAGE(STATUS "Could not find libiberty; downloading binutils and building PIC libiberty.")
ENDIF (IBERTY_FIND_REQUIRED)
ENDIF (IBERTY_LIBRARIES)
+10
View File
@@ -0,0 +1,10 @@
macro(MACRO_ENSURE_OUT_OF_SOURCE_BUILD MSG)
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" insource)
get_filename_component(PARENTDIR ${CMAKE_SOURCE_DIR} PATH)
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${PARENTDIR}" insourcesubdir)
if(insource OR insourcesubdir)
message(FATAL_ERROR "${MSG}")
endif(insource OR insourcesubdir)
endmacro(MACRO_ENSURE_OUT_OF_SOURCE_BUILD)
+359
View File
@@ -0,0 +1,359 @@
## -*- mode:cmake; coding:utf-8; -*-
# Copyright (c) 2010 Daniel Pfeifer <daniel@pfeifer-mail.de>
# Changes Copyright (c) 2011 2012 Rüdiger Sonderfeld <ruediger@c-plusplus.de>
#
# UploadPPA.cmake is free software. It comes without any warranty,
# to the extent permitted by applicable law. You can redistribute it
# and/or modify it under the terms of the Do What The Fuck You Want
# To Public License, Version 2, as published by Sam Hocevar. See
# http://sam.zoy.org/wtfpl/COPYING for more details.
#
##
# Documentation
#
# This CMake module uploads a project to a PPA. It creates all the files
# necessary (similar to CPack) and uses debuild(1) and dput(1) to create the
# package and upload it to a PPA. A PPA is a Personal Package Archive and can
# be used by Debian/Ubuntu or other apt/deb based distributions to install and
# update packages from a remote repository.
# Canonicals Launchpad (http://launchpad.net) is usually used to host PPAs.
# See https://help.launchpad.net/Packaging/PPA for further information
# about PPAs.
#
# UploadPPA.cmake uses similar settings to CPack and the CPack DEB Generator.
# Additionally the following variables are used
#
# CPACK_DEBIAN_PACKAGE_BUILD_DEPENDS to specify build dependencies
# (cmake is added as default)
# CPACK_DEBIAN_RESOURCE_FILE_CHANGELOG should point to a file containing the
# changelog in debian format. If not set it checks whether a file
# debian/changelog exists in the source directory or creates a simply changelog
# file.
# CPACK_DEBIAN_UPDATE_CHANGELOG if set to True then UploadPPA.cmake adds a new
# entry to the changelog with the current version number and distribution name
# (lsb_release -c is used). This can be useful because debuild uses the latest
# version number from the changelog and the version number set in
# CPACK_PACKAGE_VERSION. If they mismatch the creation of the package fails.
#
## A.Hoarau : CHANGELOG_MESSAGE can be used to pass a custom changelog message
# Check packages
#
# ./configure -DENABLE_PPA=On
# make dput
# cd build/Debian/${DISTRI}
# dpkg-source -x vobsub2srt_1.0pre4-ppa1.dsc
# cd vobsub2srt-1.0pre4/
# debuild -i -us -uc -sa -b
#
# Check the lintian warnings!
#
##
# TODO
# I plan to add support for git dch (from git-buildpackage) to auto generate
# the changelog.
##
find_program(DEBUILD_EXECUTABLE debuild)
find_program(DPUT_EXECUTABLE dput)
if(NOT DEBUILD_EXECUTABLE OR NOT DPUT_EXECUTABLE)
message(WARNING "Debuild or dput not installed, please run sudo apt-get install devscripts")
return()
endif(NOT DEBUILD_EXECUTABLE OR NOT DPUT_EXECUTABLE)
if(NOT PROJECT_PPA_DISTRIB_TARGET)
execute_process(
COMMAND lsb_release -cs
OUTPUT_VARIABLE DISTRI
OUTPUT_STRIP_TRAILING_WHITESPACE)
set(PROJECT_PPA_DISTRIB_TARGET ${DISTRI})
message(STATUS "PROJECT_PPA_DISTRIB_TARGET NOT provided, so using system settings : ${DISTRI}")
endif()
foreach(DISTRI ${PROJECT_PPA_DISTRIB_TARGET})
message(STATUS "Building for ${DISTRI}")
# Strip "-dirty" flag from package version.
# It can be added by, e.g., git describe but it causes trouble with debuild etc.
string(REPLACE "-dirty" "" CPACK_PACKAGE_VERSION ${CPACK_PACKAGE_VERSION})
message(STATUS "version: ${CPACK_PACKAGE_VERSION}")
# DEBIAN/control
# debian policy enforce lower case for package name
# Package: (mandatory)
IF(NOT CPACK_DEBIAN_PACKAGE_NAME)
STRING(TOLOWER "${CPACK_PACKAGE_NAME}" CPACK_DEBIAN_PACKAGE_NAME)
ENDIF(NOT CPACK_DEBIAN_PACKAGE_NAME)
# Section: (recommended)
IF(NOT CPACK_DEBIAN_PACKAGE_SECTION)
SET(CPACK_DEBIAN_PACKAGE_SECTION "devel")
ENDIF(NOT CPACK_DEBIAN_PACKAGE_SECTION)
# Priority: (recommended)
IF(NOT CPACK_DEBIAN_PACKAGE_PRIORITY)
SET(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
ENDIF(NOT CPACK_DEBIAN_PACKAGE_PRIORITY)
if(NOT CPACK_DEBIAN_PACKAGE_MAINTAINER)
set(CPACK_DEBIAN_PACKAGE_MAINTAINER ${CPACK_PACKAGE_CONTACT})
endif()
if(NOT CPACK_PACKAGE_DESCRIPTION AND EXISTS ${CPACK_PACKAGE_DESCRIPTION_FILE})
file(STRINGS ${CPACK_PACKAGE_DESCRIPTION_FILE} DESC_LINES)
foreach(LINE ${DESC_LINES})
set(deb_long_description "${deb_long_description} ${LINE}\n")
endforeach(LINE ${DESC_LINES})
else()
# add space before each line
string(REPLACE "\n" "\n " deb_long_description " ${CPACK_PACKAGE_DESCRIPTION}")
endif()
if(PPA_DEBIAN_VERSION)
set(DEBIAN_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}-${PPA_DEBIAN_VERSION}~${DISTRI}1")
elseif(NOT PPA_DEBIAN_VERSION AND NOT PROJECT_PPA_DISTRIB_TARGET)
message(WARNING "Variable PPA_DEBIAN_VERSION not set! Building 'native' package!")
set(DEBIAN_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}")
else()
set(DEBIAN_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}~${DISTRI}1")
endif()
message(STATUS "Debian version: ${DEBIAN_PACKAGE_VERSION}")
set(DEBIAN_SOURCE_DIR ${CMAKE_BINARY_DIR}/Debian/${DISTRI}/${CPACK_DEBIAN_PACKAGE_NAME}_${DEBIAN_PACKAGE_VERSION})
##############################################################################
# debian/control
set(debian_control ${DEBIAN_SOURCE_DIR}/debian/control)
list(APPEND CPACK_DEBIAN_PACKAGE_BUILD_DEPENDS "cmake" "debhelper (>= 7.0.50)")
list(REMOVE_DUPLICATES CPACK_DEBIAN_PACKAGE_BUILD_DEPENDS)
list(SORT CPACK_DEBIAN_PACKAGE_BUILD_DEPENDS)
string(REPLACE ";" ", " build_depends "${CPACK_DEBIAN_PACKAGE_BUILD_DEPENDS}")
string(REPLACE ";" ", " bin_depends "${CPACK_DEBIAN_PACKAGE_DEPENDS}")
file(WRITE ${debian_control}
"Source: ${CPACK_DEBIAN_PACKAGE_NAME}\n"
"Section: ${CPACK_DEBIAN_PACKAGE_SECTION}\n"
"Priority: ${CPACK_DEBIAN_PACKAGE_PRIORITY}\n"
"Maintainer: ${CPACK_DEBIAN_PACKAGE_MAINTAINER}\n"
"Build-Depends: ${build_depends}\n"
"Standards-Version: 3.9.7\n"
"Homepage: ${CPACK_DEBIAN_PACKAGE_HOMEPAGE}\n"
"\n"
"Package: ${CPACK_DEBIAN_PACKAGE_NAME}\n"
"Architecture: ${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}\n"
"Depends: ${bin_depends}, \${shlibs:Depends}, \${misc:Depends}\n"
"Description: ${CPACK_PACKAGE_DESCRIPTION_SUMMARY}\n"
"${deb_long_description}"
)
file(APPEND ${debian_control}
"\n\n"
"Package: ${CPACK_DEBIAN_PACKAGE_NAME}-dbg\n"
"Priority: extra\n"
"Section: debug\n"
"Architecture: any\n"
"Depends: ${CPACK_DEBIAN_PACKAGE_NAME} (= \${binary:Version}), \${shlibs:Depends}, \${misc:Depends}\n"
"Description: ${CPACK_PACKAGE_DESCRIPTION_SUMMARY}\n"
"${deb_long_description}"
"\n .\n"
" This is the debugging symbols for the ${CPACK_DEBIAN_PACKAGE_NAME} library"
)
foreach(COMPONENT ${CPACK_COMPONENTS_ALL})
string(TOUPPER ${COMPONENT} UPPER_COMPONENT)
set(DEPENDS "${CPACK_DEBIAN_PACKAGE_NAME}")
foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS})
set(DEPENDS "${DEPENDS}, ${CPACK_DEBIAN_PACKAGE_NAME}-${DEP}")
endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS})
file(APPEND ${debian_control} "\n"
"Package: ${CPACK_DEBIAN_PACKAGE_NAME}-${COMPONENT}\n"
"Architecture: ${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}\n"
"Depends: ${DEPENDS}\n"
"Description: ${CPACK_PACKAGE_DESCRIPTION_SUMMARY}"
": ${CPACK_COMPONENT_${UPPER_COMPONENT}_DISPLAY_NAME}\n"
"${deb_long_description}"
"\n .\n"
" ${CPACK_COMPONENT_${UPPER_COMPONENT}_DESCRIPTION}\n"
)
endforeach(COMPONENT ${CPACK_COMPONENTS_ALL})
##############################################################################
# debian/copyright
set(debian_copyright ${DEBIAN_SOURCE_DIR}/debian/copyright)
configure_file(${CPACK_RESOURCE_FILE_LICENSE} ${debian_copyright} COPYONLY)
##############################################################################
# debian/rules
set(debian_rules ${DEBIAN_SOURCE_DIR}/debian/rules)
file(WRITE ${debian_rules}
"#!/usr/bin/make -f\n"
"\nexport DH_VERBOSE=1"
"\n\n%:\n"
"\tdh $@ --buildsystem=cmake\n"
"\noverride_dh_auto_configure:\n"
"\tDESTDIR=\"$(CURDIR)/debian/${CPACK_DEBIAN_PACKAGE_NAME}\" dh_auto_configure -- -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_SHARED_LIBS=ON -DPACKAGE_TGZ=OFF"
"\n\noverride_dh_auto_install:\n"
"\tdh_auto_install --destdir=\"$(CURDIR)/debian/${CPACK_DEBIAN_PACKAGE_NAME}\" --buildsystem=cmake"
"\n\noverride_dh_strip:\n"
"\tdh_strip --dbg-package=${CPACK_DEBIAN_PACKAGE_NAME}-dbg"
)
execute_process(COMMAND chmod +x ${debian_rules})
##############################################################################
# debian/compat
file(WRITE ${DEBIAN_SOURCE_DIR}/debian/compat "7")
##############################################################################
# debian/source/format
file(WRITE ${DEBIAN_SOURCE_DIR}/debian/source/format "3.0 (native)")
##############################################################################
# debian/changelog
set(debian_changelog ${DEBIAN_SOURCE_DIR}/debian/changelog)
if(NOT CPACK_DEBIAN_RESOURCE_FILE_CHANGELOG)
set(CPACK_DEBIAN_RESOURCE_FILE_CHANGELOG ${CMAKE_SOURCE_DIR}/debian/changelog)
endif()
# TODO add support for git dch (git-buildpackage)
if(CHANGELOG_MESSAGE)
set(output_changelog_msg ${CHANGELOG_MESSAGE})
else()
set(output_changelog_msg "* Package created with CMake")
endif(CHANGELOG_MESSAGE)
message(STATUS "Changelog message : \"${output_changelog_msg}\"")
if(EXISTS ${CPACK_DEBIAN_RESOURCE_FILE_CHANGELOG})
configure_file(${CPACK_DEBIAN_RESOURCE_FILE_CHANGELOG} ${debian_changelog} COPYONLY)
if(CPACK_DEBIAN_UPDATE_CHANGELOG)
file(READ ${debian_changelog} debian_changelog_content)
execute_process(
COMMAND date -R
OUTPUT_VARIABLE DATE_TIME
OUTPUT_STRIP_TRAILING_WHITESPACE)
file(WRITE ${debian_changelog}
"${CPACK_DEBIAN_PACKAGE_NAME} (${DEBIAN_PACKAGE_VERSION}) ${DISTRI}; urgency=low\n\n"
" ${output_changelog_msg}\n\n"
" -- ${CPACK_DEBIAN_PACKAGE_MAINTAINER} ${DATE_TIME}\n\n"
)
file(APPEND ${debian_changelog} ${debian_changelog_content})
endif()
else()
execute_process(
COMMAND date -R
OUTPUT_VARIABLE DATE_TIME
OUTPUT_STRIP_TRAILING_WHITESPACE)
file(WRITE ${debian_changelog}
"${CPACK_DEBIAN_PACKAGE_NAME} (${DEBIAN_PACKAGE_VERSION}) ${DISTRI}; urgency=low\n\n"
" ${output_changelog_msg}\n\n"
" -- ${CPACK_DEBIAN_PACKAGE_MAINTAINER} ${DATE_TIME}\n"
)
#configure_file(${debian_changelog} ${CPACK_DEBIAN_RESOURCE_FILE_CHANGELOG} COPYONLY)
endif()
##########################################################################
# Templates
if (CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA)
foreach(CF ${CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA})
get_filename_component(CF_NAME ${CF} NAME)
message("Writing debian/${CF_NAME}")
configure_file(${CF} ${DEBIAN_SOURCE_DIR}/debian/${CF_NAME} @ONLY)
endforeach()
endif(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA)
##########################################################################
# .orig.tar.gz
#execute_process(COMMAND date +%y%m%d
# OUTPUT_VARIABLE day_suffix
# OUTPUT_STRIP_TRAILING_WHITESPACE
# )
set(CPACK_SOURCE_IGNORE_FILES
${CPACK_SOURCE_IGNORE_FILES}
"/build.*/"
"/Testing/"
"/test/"
"/tmp/"
"/packaging/"
"/debian/"
"/\\\\.git.*"
"/\\\\.idea/"
"/\\\\.codelite/"
"*~$")
#set(package_file_name "${CPACK_DEBIAN_PACKAGE_NAME}_${DEBIAN_PACKAGE_VERSION}")
set(package_file_name "${CPACK_DEBIAN_PACKAGE_NAME}_${CPACK_PACKAGE_VERSION}")
file(WRITE "${CMAKE_BINARY_DIR}/Debian/${DISTRI}/cpack.cmake"
"set(CPACK_GENERATOR TGZ)\n"
"set(CPACK_PACKAGE_NAME \"${CPACK_DEBIAN_PACKAGE_NAME}\")\n"
"set(CPACK_PACKAGE_VERSION \"${CPACK_PACKAGE_VERSION}\")\n"
"set(CPACK_PACKAGE_FILE_NAME \"${package_file_name}.orig\")\n"
"set(CPACK_PACKAGE_DESCRIPTION \"${CPACK_PACKAGE_NAME} Source\")\n"
"set(CPACK_IGNORE_FILES \"${CPACK_SOURCE_IGNORE_FILES}\")\n"
"set(CPACK_INSTALLED_DIRECTORIES \"${CPACK_SOURCE_INSTALLED_DIRECTORIES}\")\n"
"set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF)\n"
)
set(orig_file "${CMAKE_BINARY_DIR}/Debian/${DISTRI}/${package_file_name}.orig.tar.gz")
add_custom_command(OUTPUT ${orig_file}
COMMAND cpack --config ${CMAKE_BINARY_DIR}/Debian/${DISTRI}/cpack.cmake
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/Debian/${DISTRI}
)
add_custom_command(OUTPUT ${DEBIAN_SOURCE_DIR}/CMakeLists.txt
COMMAND tar zxf ${orig_file}
WORKING_DIRECTORY ${DEBIAN_SOURCE_DIR}
DEPENDS ${orig_file}
)
##############################################################################
# debuild -S
set(DEB_SOURCE_CHANGES
${CPACK_DEBIAN_PACKAGE_NAME}_${DEBIAN_PACKAGE_VERSION}_source.changes
)
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/Debian/${DISTRI}/${DEB_SOURCE_CHANGES}
COMMAND ${DEBUILD_EXECUTABLE} --no-tgz-check -S
WORKING_DIRECTORY ${DEBIAN_SOURCE_DIR}
)
add_custom_target(debuild_${DISTRI} ALL
DEPENDS ${DEBIAN_SOURCE_DIR}/CMakeLists.txt
${CMAKE_BINARY_DIR}/Debian/${DISTRI}/${DEB_SOURCE_CHANGES}
)
##############################################################################
# dput ppa:your-lp-id/ppa <source.changes>
message(STATUS "Upload PPA is ${UPLOAD_PPA}")
if(UPLOAD_PPA)
if (EXISTS ${DPUT_CONFIG_IN})
set(DPUT_DIST ${DISTRI})
configure_file(
${DPUT_CONFIG_IN}
${CMAKE_BINARY_DIR}/Debian/${DISTRI}/dput.cf
@ONLY
)
add_custom_target(dput_${DISTRI} ALL
COMMAND ${DPUT_EXECUTABLE} -c ${CMAKE_BINARY_DIR}/Debian/${DISTRI}/dput.cf ${DPUT_HOST} ${DEB_SOURCE_CHANGES}
DEPENDS debuild_${DISTRI}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/Debian/${DISTRI}
)
else()
add_custom_target(dput_${DISTRI} ALL
COMMAND ${DPUT_EXECUTABLE} ${DPUT_HOST} ${DEB_SOURCE_CHANGES}
DEPENDS debuild_${DISTRI}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/Debian/${DISTRI}
)
endif()
endif()
endforeach(DISTRI)
+53
View File
@@ -0,0 +1,53 @@
if (NOT CMAKE_HOST_UNIX OR NOT WIN32)
return()
endif()
find_program(WINTOOLS_WINE_EXEC wine)
if (NOT WINTOOLS_WINE_EXEC)
message("Wine executable not found! Failed to initiate wintools staff.")
return()
endif()
find_program(WINTOOLS_WGET_EXEC wget)
if (NOT WINTOOLS_WGET_EXEC)
message("Wget executable not found! Failed to initiate wintools staff.")
return()
endif()
set(WINTOOLS_DIR ${CMAKE_BINARY_DIR}/WINTOOLS)
set(WINTOOLS_DL_ROOT "http://softmotions.com/windev")
if (NOT EXISTS ${WINTOOLS_DIR})
file(MAKE_DIRECTORY ${WINTOOLS_DIR})
endif()
set(WINTOOLS_EXECS)
foreach (WINTOOLS_EXEC link.exe lib.exe mspdb100.dll)
if (NOT EXISTS ${WINTOOLS_DIR}/${WINTOOLS_EXEC})
add_custom_command(OUTPUT ${WINTOOLS_DIR}/${WINTOOLS_EXEC}
COMMAND ${WINTOOLS_WGET_EXEC} ${WINTOOLS_DL_ROOT}/${WINTOOLS_EXEC} -nv -O${WINTOOLS_DIR}/${WINTOOLS_EXEC}
WORKING_DIRECTORY ${WINTOOLS_DIR})
list(APPEND WINTOOLS_EXECS ${WINTOOLS_DIR}/${WINTOOLS_EXEC})
endif()
endforeach(WINTOOLS_EXEC)
add_custom_target(wintools_init
DEPENDS ${WINTOOLS_EXECS})
if (CMAKE_SIZEOF_VOID_P MATCHES 8)
set(WINTOOLS_LIB_MACHINE "X64")
else()
set(WINTOOLS_LIB_MACHINE "X86")
endif()
message("-- WINTOOLS_LIB_MACHINE: ${WINTOOLS_LIB_MACHINE}")
macro(add_w32_importlib tgt libname wdir)
add_custom_command(
TARGET ${tgt}
POST_BUILD
COMMAND ${WINTOOLS_WINE_EXEC} ${WINTOOLS_DIR}/lib.exe /def:${libname}.def /machine:${WINTOOLS_LIB_MACHINE}
WORKING_DIRECTORY ${wdir}
)
endmacro(add_w32_importlib)
+59
View File
@@ -0,0 +1,59 @@
set(CPACK_PACKAGE_NAME "${CMAKE_PROJECT_NAME}")
set(CPACK_PACKAGE_CONTACT "${PROJECT_MAINTAINER}")
set(CPACK_PACKAGE_VERSION ${iowow_VERSION})
set(CPACK_PACKAGE_VERSION_MAJOR ${iowow_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${iowow_VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${iowow_VERSION_PATCH})
set(CPACK_PACKAGE_VENDOR ${PROJECT_VENDOR})
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${PROJECT_DESCRIPTION_SUMMARY})
set(CPACK_PACKAGE_DESCRIPTION ${PROJECT_DESCRIPTION})
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE")
set(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/README.md")
set(CPACK_RESOURCE_FILE_WELCOME "${CMAKE_SOURCE_DIR}/README.md")
set(CPACK_PACKAGE_FILE_NAME
"${PROJECT_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_BUILD_TYPE}-${CMAKE_SYSTEM_NAME}-${PROJECT_ARCH}")
if (CMAKE_BUILD_TYPE STREQUAL "Release")
set(CPACK_STRIP_FILES ON)
endif()
if (PACKAGE_DEB)
execute_process (
COMMAND /usr/bin/dpkg --print-architecture
OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE
RESULT_VARIABLE EXECUTE_RESULT
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
if (EXECUTE_RESULT)
message(FATAL_ERROR "dpkg not found: No package generation.")
endif()
set(CPACK_DEBIAN_PACKAGE_DESCRIPTION ${PROJECT_DESCRIPTION})
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE ${PROJECT_WEBSITE})
set(CPACK_DEBIAN_PACKAGE_SECTION libs)
set(CPACK_DEBIAN_PACKAGE_PRIORITY optional)
#set(CPACK_DEBIAN_PACKAGE_DEPENDS zlib1g)
set(CPACK_DEBIAN_PACKAGE_BUILD_DEPENDS pkg-config git devscripts dh-make)
if (NOT PPA_DEBIAN_VERSION)
set(PPA_DEBIAN_VERSION ppa1)
endif()
if (PROJECT_PPA)
set(DPUT_HOST ${PROJECT_PPA})
endif()
#set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "any")
set(CPACK_DEBIAN_RESOURCE_FILE_CHANGELOG ${CMAKE_SOURCE_DIR}/Changelog)
set(CPACK_DEBIAN_UPDATE_CHANGELOG ON)
endif(PACKAGE_DEB)
if (PACKAGE_TGZ)
set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF)
endif(PACKAGE_TGZ)
include(CPack)
if (ENABLE_PPA)
if (NOT PROJECT_PPA_DISTRIB_TARGET)
set(PROJECT_PPA_DISTRIB_TARGET xenial bionic)
endif()
set(DPUT_CONFIG_IN ${CMAKE_CURRENT_SOURCE_DIR}/debian/dput.cf.in)
include(UploadPPA)
endif()
+5
View File
@@ -0,0 +1,5 @@
[ppa]
fqdn = ppa.launchpad.net
method = sftp
login = @PROJECT_PPA_USER@
incoming = ~%(ppa)s/ubuntu/@DPUT_DIST@
+2
View File
@@ -0,0 +1,2 @@
install(FILES iowow.3 DESTINATION ${CMAKE_INSTALL_MANDIR}/man3
COMPONENT doc)
+13
View File
@@ -0,0 +1,13 @@
.TH "IOWOW" 3 "2018-04-08" "Man Page" "IOWOW"
.SH NAME
IOWOW \- The C11 persistent key/value database engine based on skip list
.SH DESCRIPTION
.PP
The C11 persistent key/value database engine based on skip list
.SH "SEE ALSO"
.I http://iowow.io
IOWOW project official web site.
+19
View File
@@ -0,0 +1,19 @@
#!/bin/bash
set -e
SCRIPTPATH="$(
cd "$(dirname "$0")"
pwd -P
)"
cd $SCRIPTPATH
if [ ! -d ./build ]; then
mkdir ./build
fi
cd ./build
cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Release \
&& make
pvs-studio-analyzer analyze -a 45 -l ${HOME}/.config/PVS-Studio/PVS-Studio.lic -j4 -o ./pvs.log
rm -rf ./pvs_report
plog-converter -a 'GA:1,2,3;64:1;OP:1,2,3;MISRA:1' -t fullhtml -o ./pvs_report ./pvs.log
Executable
+21
View File
@@ -0,0 +1,21 @@
#!/bin/sh
set -e
set -x
cd `readlink -f "$0" | xargs dirname`
git pull origin master
dch --distribution testing --no-force-save-on-release --release "" -c ./Changelog
VERSION=`dpkg-parsechangelog -l./Changelog -SVersion`
TAG="v${VERSION}"
CHANGESET=`dpkg-parsechangelog -l./Changelog -SChanges | sed '/^iowow.*/d' | sed '/^\s*$/d'`
git add ./Changelog
if ! git diff-index --quiet HEAD --; then
git commit -m"${TAG} landed"
git push origin master
fi
echo "${CHANGESET}" | git tag -f -a -F - "${TAG}"
git push origin -f --tags
+331
View File
@@ -0,0 +1,331 @@
include(CheckSymbolExists)
if (NOT CMAKE_BUILD_TYPE)
message(FATAL_ERROR "Please specify the build type -DCMAKE_BUILD_TYPE=Debug|Release|RelWithDebInfo")
endif()
set(MODULES log utils platform fs rdb kv)
set(PROJECT_LLIBRARIES)
set(PROJECT_INCLUDE_DIRS)
set(ALL_SRC)
set(ALL_HDRS)
set(PUB_HDRS)
set(PROJECT_GENERATED_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated)
list(APPEND PROJECT_INCLUDE_DIRS "${PROJECT_GENERATED_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}")
if(APPLE)
option(BUILD_FRAMEWORK "Build an OS X framework" OFF)
set(FRAMEWORK_INSTALL_DIR "/Library/Frameworks" CACHE STRING "Directory to install frameworks to.")
endif()
include(CheckIncludeFile)
include(CheckIncludeFiles)
include(CheckLibraryExists)
include(TestBigEndian)
if (OWNER_PROJECT_NAME)
set(IW_PUBLIC_HEADER_DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${OWNER_PROJECT_NAME}/${PROJECT_NAME})
else()
set(IW_PUBLIC_HEADER_DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME})
endif()
if ((CMAKE_BUILD_TYPE EQUAL Release) OR (CMAKE_BUILD_TYPE EQUAL RelWithDebInfo))
add_definition(-DIW_RELEASE)
endif()
TEST_BIG_ENDIAN(IS_BIG_ENDIAN)
if (IS_BIG_ENDIAN EQUAL 1)
add_definitions(-DIW_BIGENDIAN)
endif()
if(CMAKE_SIZEOF_VOID_P MATCHES 8)
add_definitions(-DIW_64)
else()
add_definitions(-DIW_32)
endif()
if (BUILD_TESTS)
add_definitions(-DIW_TESTS=1)
endif()
find_package(Threads REQUIRED CMAKE_THREAD_PREFER_PTHREAD)
if (CMAKE_USE_WIN32_THREADS_INIT)
add_definitions(-DIW_WIN32_THREADS)
elseif (CMAKE_USE_PTHREADS_INIT)
add_definitions(-DIW_PTHREADS)
check_library_exists(pthread pthread_condattr_setclock "" HAVE_PTHREAD_CONDATTR_SETCLOCK)
if (HAVE_PTHREAD_CONDATTR_SETCLOCK AND NOT IOS)
add_definitions(-DIW_HAVE_PTHREAD_CONDATTR_SETCLOCK)
endif()
else()
mesage(FATAL_ERROR "Unable to find suitable threading library")
endif(CMAKE_USE_WIN32_THREADS_INIT)
if (ANDROID)
find_library(LOG_LIB log)
if (NOT LOG_LIB)
message(FATAL_ERROR "Library 'log' not FOUND")
endif()
list(APPEND PROJECT_LLIBRARIES "${LOG_LIB}")
endif()
if (NOT WIN32)
list(APPEND PROJECT_LLIBRARIES ${CMAKE_THREAD_LIBS_INIT})
else()
include(Win32LIBTools)
check_include_file(windows.h HAVE_WINDOWS_H)
if (NOT HAVE_WINDOWS_H)
message(FATAL_ERROR "Unable to find windows.h include file")
endif()
set(IBERTY_FIND_REQUIRED ON)
include(FindLibIberty)
list(APPEND PROJECT_LLIBRARIES ${IBERTY_LIBRARIES})
check_library_exists(winpthread pthread_exit "" HAVE_WINPTHREAD)
if (NOT HAVE_WINPTHREAD)
message(FATAL_ERROR "Unable to winpthread lib")
endif()
list(INSERT PROJECT_LLIBRARIES 0 -lwinpthread)
add_definitions(-D_POSIX_THREAD_SAFE_FUNCTIONS)
endif()
if (CMAKE_SYSTEM_PROCESSOR MATCHES "mips")
include(FindAtomic)
if (ATOMIC_FOUND)
list(APPEND PROJECT_LLIBRARIES "${ATOMIC_LIBRARY}")
endif()
endif()
list(APPEND PROJECT_LLIBRARIES "-lm")
check_symbol_exists(CLOCK_MONOTONIC time.h HAVE_CLOCK_MONOTONIC)
if (HAVE_CLOCK_MONOTONIC)
add_definitions(-DIW_HAVE_CLOCK_MONOTONIC)
endif()
foreach(HF IN ITEMS stdlib stddef stdint stdbool stdatomic unistd dirent)
string(TOUPPER "${HF}" UHF)
check_include_file(${HF}.h "IW_HAVE_${UHF}")
if (NOT IW_HAVE_${UHF})
message(FATAL_ERROR "Include file '${HF}.h' not FOUND")
endif()
endforeach(HF)
add_definitions(-D_GNU_SOURCE)
add_definitions(-D_LARGEFILE_SOURCE)
add_definitions(-D_FILE_OFFSET_BITS=64)
list(APPEND ALL_SRC ${CMAKE_CURRENT_SOURCE_DIR}/iowow.c)
foreach(MODULE IN LISTS MODULES)
file(GLOB MODULE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/${MODULE}/*.c)
file(GLOB MODULE_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/${MODULE}/*.h)
list(APPEND ALL_SRC ${MODULE_SRC})
list(APPEND ALL_HDRS ${MODULE_HDRS})
list(APPEND PROJECT_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/${MODULE})
endforeach(MODULE)
list(APPEND PUB_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/basedefs.h
${CMAKE_CURRENT_SOURCE_DIR}/fs/iwdlsnr.h
${CMAKE_CURRENT_SOURCE_DIR}/fs/iwexfile.h
${CMAKE_CURRENT_SOURCE_DIR}/fs/iwfile.h
${CMAKE_CURRENT_SOURCE_DIR}/fs/iwfsmfile.h
${CMAKE_CURRENT_SOURCE_DIR}/iowow.h
${CMAKE_CURRENT_SOURCE_DIR}/kv/iwkv.h
${CMAKE_CURRENT_SOURCE_DIR}/log/iwlog.h
${CMAKE_CURRENT_SOURCE_DIR}/platform/iwp.h
${CMAKE_CURRENT_SOURCE_DIR}/rdb/iwrdb.h
${CMAKE_CURRENT_SOURCE_DIR}/utils/iwarr.h
${CMAKE_CURRENT_SOURCE_DIR}/utils/iwbits.h
${CMAKE_CURRENT_SOURCE_DIR}/utils/iwconv.h
${CMAKE_CURRENT_SOURCE_DIR}/utils/iwhmap.h
${CMAKE_CURRENT_SOURCE_DIR}/utils/iwpool.h
${CMAKE_CURRENT_SOURCE_DIR}/utils/iwsha2.h
${CMAKE_CURRENT_SOURCE_DIR}/utils/iwstree.h
${CMAKE_CURRENT_SOURCE_DIR}/utils/iwstw.h
${CMAKE_CURRENT_SOURCE_DIR}/utils/iwth.h
${CMAKE_CURRENT_SOURCE_DIR}/utils/iwutils.h
${CMAKE_CURRENT_SOURCE_DIR}/utils/iwuuid.h
${CMAKE_CURRENT_SOURCE_DIR}/utils/iwxstr.h
${CMAKE_CURRENT_SOURCE_DIR}/utils/murmur3.h
)
list(REMOVE_DUPLICATES PROJECT_LLIBRARIES)
list(REMOVE_DUPLICATES PROJECT_INCLUDE_DIRS)
include_directories(${PROJECT_INCLUDE_DIRS})
# -pg -no-pie
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} \
-std=gnu11 -fsigned-char -pedantic \
-Wfatal-errors -Wall -Wextra -Wno-sign-compare -Wno-unused-parameter \
-Wno-unknown-pragmas -Wno-unused-function -Wno-missing-field-initializers \
-Wno-missing-braces")
if (APPLE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-shorten-64-to-32")
endif()
if (NOT WIN32) ## todo review
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
else()
add_definitions(-D__USE_MINGW_ANSI_STDIO)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-pedantic-ms-format")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
endif()
if (ASAN)
set(CMAKE_C_ASAN "-fsanitize=address -fno-omit-frame-pointer")
endif()
set(CMAKE_C_FLAGS_DEBUG "-O0 -g -ggdb -Werror -DDEBUG -D_DEBUG -UNDEBUG \
-Wno-unused-variable ${CMAKE_C_ASAN}")
set(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG ${CMAKE_C_ASAN}")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELEASE} -g")
set(CMAKE_C_FLAGS_RELEASEWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
if (CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
endif()
if (CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
endif(CMAKE_COMPILER_IS_GNUCC)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/tmpl/iwcfg.h ${PROJECT_GENERATED_DIR}/iwcfg.h)
file(GLOB PROJECT_GENERATED_HDRS ${PROJECT_GENERATED_DIR}/*.h)
list(APPEND ALL_HDRS ${PROJECT_GENERATED_HDRS})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/tmpl/libiowow.pc.in ${PROJECT_GENERATED_DIR}/libiowow.pc @ONLY)
install(FILES ${PROJECT_GENERATED_DIR}/libiowow.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
foreach(MODULE IN LISTS MODULES)
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${MODULE}/CMakeLists.txt)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${MODULE})
endif()
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${MODULE}/tools/CMakeLists.txt)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${MODULE}/tools)
endif()
if (BUILD_TESTS AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${MODULE}/tests/CMakeLists.txt)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${MODULE}/tests)
endif()
if (BUILD_EXAMPLES AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${MODULE}/examples/CMakeLists.txt)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${MODULE}/examples)
endif()
if (BUILD_BENCHMARKS AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${MODULE}/benchmark/CMakeLists.txt)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${MODULE}/benchmark)
endif()
endforeach(MODULE)
if (NOT BUILD_SHARED_LIBS)
add_definitions(-DIW_NODLL)
add_library(iowow STATIC ${ALL_SRC})
add_library(iowow_s ALIAS iowow)
else()
add_library(iowow SHARED ${ALL_SRC})
add_library(iowow_s STATIC ${ALL_SRC})
endif()
target_link_libraries(iowow ${PROJECT_LLIBRARIES})
if (BUILD_SHARED_LIBS)
target_link_libraries(iowow_s ${PROJECT_LLIBRARIES})
endif()
if (BUILD_SHARED_LIBS)
if (WIN32)
add_dependencies(iowow wintools_init)
set_target_properties(iowow PROPERTIES LINK_FLAGS "-Wl,--output-def,libiowow.def")
add_w32_importlib(iowow libiowow ${CMAKE_CURRENT_BINARY_DIR})
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/libiowow.def
${CMAKE_CURRENT_BINARY_DIR}/libiowow.lib
${CMAKE_CURRENT_BINARY_DIR}/libiowow.exp
DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif(WIN32)
set_target_properties(iowow PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
PUBLIC_HEADER "${PUB_HDRS}"
DEFINE_SYMBOL IW_API_EXPORTS)
set_target_properties(iowow_s PROPERTIES
VERSION ${PROJECT_VERSION}
COMPILE_FLAGS "-DIW_NODLL"
OUTPUT_NAME iowow-${PROJECT_VERSION_MAJOR})
else()
set_target_properties(iowow PROPERTIES
VERSION ${PROJECT_VERSION}
PUBLIC_HEADER "${PUB_HDRS}"
COMPILE_FLAGS "-DIW_NODLL"
OUTPUT_NAME iowow-${PROJECT_VERSION_MAJOR})
endif(BUILD_SHARED_LIBS)
install(TARGETS iowow
EXPORT iowow-exports
FRAMEWORK DESTINATION ${FRAMEWORK_INSTALL_DIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${IW_PUBLIC_HEADER_DESTINATION})
install(EXPORT iowow-exports
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME})
if (BUILD_SHARED_LIBS)
install(TARGETS iowow_s
EXPORT iowow-static-exports
FRAMEWORK DESTINATION ${FRAMEWORK_INSTALL_DIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${IW_PUBLIC_HEADER_DESTINATION})
install(EXPORT iowow-static-exports
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME})
endif()
install(FILES
${CMAKE_SOURCE_DIR}/LICENSE
${CMAKE_SOURCE_DIR}/Changelog
DESTINATION ${CMAKE_INSTALL_DOCDIR})
install(FILES
${CMAKE_SOURCE_DIR}/README.md
RENAME README
DESTINATION ${CMAKE_INSTALL_DOCDIR})
if (CMAKE_VERSION VERSION_GREATER 3.0)
export(EXPORT iowow-exports)
if (BUILD_SHARED_LIBS)
export(EXPORT iowow-static-exports)
endif(BUILD_SHARED_LIBS)
else()
export(TARGETS iowow FILE iowow-exports.cmake)
if (BUILD_SHARED_LIBS)
export(TARGETS iowow_s FILE iowow-static-exports.cmake)
endif(BUILD_SHARED_LIBS)
endif()
include(InstallRequiredSystemLibraries)
set(${PROJECT_NAME}_PUB_HDRS ${PUB_HDRS}
CACHE INTERNAL "${PROJECT_NAME}: Public headers" FORCE)
set(${PROJECT_NAME}_INCLUDE_DIRS ${PROJECT_INCLUDE_DIRS}
CACHE INTERNAL "${PROJECT_NAME}: Include Directories" FORCE)
message("")
message("${PROJECT_NAME} LINK LIBS: ${PROJECT_LLIBRARIES}")
message("\n${PROJECT_NAME} INCLUDE DIRS: ${PROJECT_INCLUDE_DIRS}")
message("\n${PROJECT_NAME} SOURCES: ${ALL_SRC}")
message("\n${PROJECT_NAME} PUB_HDRS: ${PUB_HDRS}")
message("\n${PROJECT_NAME} CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
message("${PROJECT_NAME} BUILD_SHARED_LIBS: ${BUILD_SHARED_LIBS}")
message("${PROJECT_NAME} BUILD_TESTS: ${BUILD_TESTS}")
message("${PROJECT_NAME} BUILD_EXAMPLES: ${BUILD_EXAMPLES}")
message("${PROJECT_NAME} BUILD_BENCHMARKS: ${BUILD_BENCHMARKS}")
message("${PROJECT_NAME} BUILD_DOCUMENTATION: ${BUILD_DOCUMENTATION}")
message("${PROJECT_NAME} PUBLIC_HEADER_DESTINATION: ${IW_PUBLIC_HEADER_DESTINATION}")
+194
View File
@@ -0,0 +1,194 @@
#ifndef BASEDEFS_H
#define BASEDEFS_H
/**************************************************************************************************
* IOWOW library
*
* MIT License
*
* Copyright (c) 2012-2020 Softmotions Ltd <info@softmotions.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*************************************************************************************************/
/**
* @file
* @brief Very basic definitions.
* @author Anton Adamansky (adamansky@softmotions.com)
*/
#ifdef __cplusplus
#define IW_EXTERN_C_START extern "C" {
#define IW_EXTERN_C_END }
#else
#define IW_EXTERN_C_START
#define IW_EXTERN_C_END
#endif
#if (defined(_WIN32) || defined(_WIN64))
#if (defined(IW_NODLL) || defined(IW_STATIC))
#define IW_EXPORT
#else
#ifdef IW_API_EXPORTS
#define IW_EXPORT __declspec(dllexport)
#else
#define IW_EXPORT __declspec(dllimport)
#endif
#endif
#else
#if __GNUC__ >= 4
#define IW_EXPORT __attribute__((visibility("default")))
#else
#define IW_EXPORT
#endif
#endif
#if defined(__GNUC__)
#define IW_INLINE static inline __attribute__((always_inline))
#else
#define IW_INLINE static inline
#endif
#define IW_SOFT_INLINE static inline
#if __GNUC__ >= 4
#define WUR __attribute__((__warn_unused_result__))
#else
#define WUR
#endif
#define IW_ARR_STATIC static
#define IW_ARR_CONST const
#ifdef _WIN32
#include <windows.h>
#define INVALIDHANDLE(_HNDL) \
(((_HNDL) == INVALID_HANDLE_VALUE) || (_HNDL) == NULL)
#else
typedef int HANDLE;
#define INVALID_HANDLE_VALUE (-1)
#define INVALIDHANDLE(_HNDL) ((_HNDL) < 0 || (_HNDL) == UINT16_MAX)
#endif
#define IW_ERROR_START 70000
#ifdef _WIN32
#define IW_PATH_CHR '\\'
#define IW_PATH_STR "\\"
#define IW_LINE_SEP "\r\n"
#else
#define IW_PATH_CHR '/'
#define IW_PATH_STR "/"
#define IW_LINE_SEP "\n"
#endif
#ifdef __GNUC__
#define RCGO(rc__, label__) if (__builtin_expect((!!(rc__)), 0)) goto label__
#else
#define RCGO(rc__, label__) if (rc__) goto label__
#endif
#define RCIF(res__, rc__, rcv__, label__) \
if (res__) { \
rc__ = (rcv__); \
goto label__; \
}
#define RCHECK(rc__, label__, expr__) \
rc__ = expr__; \
RCGO(rc__, label__)
#define RCC(rc__, label__, expr__) RCHECK(rc__, label__, expr__)
#ifndef RCGA
#define RCGA(v__, label__) \
if (!(v__)) { \
rc = iwrc_set_errno(IW_ERROR_ALLOC, errno); \
goto label__; \
}
#endif
#ifndef RCA
#define RCA(v__, label__) RCGA(v__, label__)
#endif
#ifdef __GNUC__
#define RCRET(rc__) if (__builtin_expect((!!(rc__)), 0)) return (rc__)
#else
#define RCRET(rc__) if (rc__) return (rc__)
#endif
#ifdef __GNUC__
#define RCBREAK(rc__) if (__builtin_expect((!!(rc__)), 0)) break
#else
#define RCBREAK(rc__) if (rc__) break
#endif
#ifdef __GNUC__
#define RCONT(rc__) if (__builtin_expect((!!(rc__)), 0)) continue
#else
#define RCONT(rc__) if (rc__) continue
#endif
#ifndef MIN
#define MIN(a_, b_) ((a_) < (b_) ? (a_) : (b_))
#endif
#ifndef MAX
#define MAX(a_, b_) ((a_) > (b_) ? (a_) : (b_))
#endif
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#ifdef _WIN32
typedef _locale_t locale_t;
#endif
#if defined(__GNUC__) || defined(__clang__)
#define IW_DEPRECATED __attribute__((deprecated))
#elif defined(_MSC_VER)
#define IW_DEPRECATED __declspec(deprecated)
#else
#define IW_DEPRECATED
#endif
/**
* @brief The operation result status code.
*
* Zero status code `0` indicates <em>operation success</em>
*
* Status code can embed an `errno` code as operation result.
* In this case `uint32_t iwrc_strip_errno(iwrc *rc)` used
* to fetch embedded errno.
*
* @see iwlog.h
*/
typedef uint64_t iwrc;
/**
* @brief A rational number.
*/
typedef struct IW_RNUM {
int32_t n; /**< Numerator */
int32_t dn; /**< Denometator */
} IW_RNUM;
#endif
+61
View File
@@ -0,0 +1,61 @@
#pragma once
#ifndef IWDLSNR_H
#define IWDLSNR_H
#include "basedefs.h"
#include <stdbool.h>
IW_EXTERN_C_START
/**
* @brief File data events listener.
*/
typedef struct IWDLSNR {
/**
* @brief Before file open event.
*
* @param path File path
* @param mode File open mode same as in open(2)
*/
iwrc(*onopen)(struct IWDLSNR *self, const char *path, int mode);
/**
* @brief Before file been closed.
*/
iwrc(*onclosing)(struct IWDLSNR *self);
/**
* @brief Write @a val value starting at @a off @a len bytes
*/
iwrc(*onset)(struct IWDLSNR *self, off_t off, uint8_t val, off_t len, int flags);
/**
* @brief Copy @a len bytes from @a off offset to @a noff offset
*/
iwrc(*oncopy)(struct IWDLSNR *self, off_t off, off_t len, off_t noff, int flags);
/**
* @brief Write @buf of @a len bytes at @a off
*/
iwrc(*onwrite)(struct IWDLSNR *self, off_t off, const void *buf, off_t len, int flags);
/**
* @brief File need to be resized.
*
* @param osize Old file size
* @param nsize New file size
* @param [out] handled File resizing handled by llistener.
*/
iwrc(*onresize)(struct IWDLSNR *self, off_t osize, off_t nsize, int flags, bool *handled);
/**
* @brief File sync successful
*/
iwrc(*onsynced)(struct IWDLSNR *self, int flags);
} IWDLSNR;
IW_EXTERN_C_END
#endif // !IWDLSNR_H
+918
View File
@@ -0,0 +1,918 @@
/**************************************************************************************************
* IOWOW library
*
* MIT License
*
* Copyright (c) 2012-2020 Softmotions Ltd <info@softmotions.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*************************************************************************************************/
#include "iwcfg.h"
#include "iwutils.h"
#include "iwlog.h"
#include "iwexfile.h"
#include <pthread.h>
#ifdef _WIN32
#include "win32/mman/mman.h"
#else
#include <sys/mman.h>
#endif
struct MMAPSLOT;
typedef struct IWFS_EXT_IMPL {
IWFS_FILE file; /**< Underlying file */
IWDLSNR *dlsnr; /**< Data events listener */
pthread_rwlock_t *rwlock; /**< Thread RW lock */
struct MMAPSLOT *mmslots; /**< Memory mapping slots */
void *rspolicy_ctx; /**< Custom opaque data for policy functions */
IW_EXT_RSPOLICY rspolicy; /**< File resize policy function ptr */
uint64_t fsize; /**< Current file size */
uint64_t maxoff; /**< Maximum allowed file offset. Unlimited if zero.
If maximum offset is reached `IWFS_ERROR_MAXOFF` will be reported. */
size_t psize; /**< System page size */
HANDLE fh; /**< File handle */
iwfs_omode omode; /**< File open mode */
bool use_locks; /**< Use rwlocks to guard method access */
} EXF;
typedef struct MMAPSLOT {
off_t off; /**< Offset to a memory mapped region */
size_t len; /**< Actual size of memory mapped region. */
size_t maxlen; /**< Maximum length of memory mapped region */
iwfs_ext_mmap_opts_t mmopts;
struct MMAPSLOT *prev; /**< Previous mmap slot. */
struct MMAPSLOT *next; /**< Next mmap slot. */
uint8_t *mmap; /**< Pointer to a mmaped address space
in the case if file data is memory mapped. */
} MMAPSLOT;
IW_INLINE iwrc _exfile_wlock(IWFS_EXT *f) {
struct IWFS_EXT_IMPL *impl = f->impl;
if (impl) {
if (!impl->use_locks) return 0;
if (impl->rwlock) {
int rv = pthread_rwlock_wrlock(impl->rwlock);
return rv ? iwrc_set_errno(IW_ERROR_THREADING_ERRNO, rv) : 0;
}
}
return IW_ERROR_INVALID_STATE;
}
IW_INLINE iwrc _exfile_rlock(IWFS_EXT *f) {
struct IWFS_EXT_IMPL *impl = f->impl;
if (impl) {
if (!impl->use_locks) return 0;
if (impl->rwlock) {
int rv = pthread_rwlock_rdlock(impl->rwlock);
return rv ? iwrc_set_errno(IW_ERROR_THREADING_ERRNO, rv) : 0;
}
}
return IW_ERROR_INVALID_STATE;
}
IW_INLINE iwrc _exfile_unlock(IWFS_EXT *f) {
struct IWFS_EXT_IMPL *impl = f->impl;
if (impl) {
if (!impl->use_locks) return 0;
if (impl->rwlock) {
int rv = pthread_rwlock_unlock(impl->rwlock);
return rv ? iwrc_set_errno(IW_ERROR_THREADING_ERRNO, rv) : 0;
}
}
return IW_ERROR_INVALID_STATE;
}
IW_INLINE iwrc _exfile_unlock2(EXF *impl) {
if (impl) {
if (!impl->use_locks) return 0;
if (impl->rwlock) {
int rv = pthread_rwlock_unlock(impl->rwlock);
return rv ? iwrc_set_errno(IW_ERROR_THREADING_ERRNO, rv) : 0;
}
}
return IW_ERROR_INVALID_STATE;
}
static iwrc _exfile_destroylocks(EXF *impl) {
if (!impl) return IW_ERROR_INVALID_STATE;
if (!impl->rwlock) return 0;
int rv = pthread_rwlock_destroy(impl->rwlock);
free(impl->rwlock);
impl->rwlock = 0;
return rv ? iwrc_set_errno(IW_ERROR_THREADING_ERRNO, rv) : 0;
}
static iwrc _exfile_initmmap_slot_lw(struct IWFS_EXT *f, MMAPSLOT *s) {
assert(f && s);
size_t nlen;
EXF *impl = f->impl;
if (s->off >= impl->fsize) {
nlen = 0;
} else {
nlen = MIN(s->maxlen, impl->fsize - s->off);
}
if (nlen == s->len) {
return 0;
}
if (s->len) { // unmap me first
assert(s->mmap);
if (!(s->mmopts & IWFS_MMAP_PRIVATE) && msync(s->mmap, s->len, 0) == -1) {
s->len = 0;
return iwrc_set_errno(IW_ERROR_ERRNO, errno);
}
if (munmap(s->mmap, s->len) == -1) {
s->len = 0;
return iwrc_set_errno(IW_ERROR_ERRNO, errno);
}
s->len = 0;
}
if (nlen > 0) {
int flags = (s->mmopts & IWFS_MMAP_PRIVATE)
#ifdef MAP_NORESERVE
? (MAP_PRIVATE + MAP_NORESERVE)
#else
? MAP_PRIVATE
#endif
: MAP_SHARED;
int prot = (impl->omode & IWFS_OWRITE) ? (PROT_WRITE + PROT_READ) : (PROT_READ);
s->len = nlen;
s->mmap = mmap(s->mmap, s->len, prot, flags, impl->fh, s->off); // -V774
if (s->mmap == MAP_FAILED) {
iwrc rc = iwrc_set_errno(IW_ERROR_ERRNO, errno);
iwlog_ecode_error3(rc);
return rc;
}
}
return 0;
}
static iwrc _exfile_initmmap_lw(struct IWFS_EXT *f) {
assert(f);
iwrc rc = 0;
EXF *impl = f->impl;
assert(!(impl->fsize & (impl->psize - 1)));
MMAPSLOT *s = impl->mmslots;
while (s) {
rc = _exfile_initmmap_slot_lw(f, s);
if (rc) {
break;
}
s = s->next;
}
return rc;
}
static iwrc _exfile_truncate_lw(struct IWFS_EXT *f, off_t size) {
assert(f && f->impl);
iwrc rc = 0;
EXF *impl = f->impl;
iwfs_omode omode = impl->omode;
uint64_t old_size = impl->fsize;
bool rsh = false;
size = IW_ROUNDUP(size, impl->psize);
if (old_size == size) {
return 0;
}
if (old_size < size) {
if (!(omode & IWFS_OWRITE)) {
return IW_ERROR_READONLY;
}
if (impl->maxoff && size > impl->maxoff) {
return IWFS_ERROR_MAXOFF;
}
if (impl->dlsnr) {
rc = impl->dlsnr->onresize(impl->dlsnr, old_size, size, 0, &rsh);
RCGO(rc, truncfail);
}
if (!rsh) {
impl->fsize = (uint64_t) size;
rc = iwp_fallocate(impl->fh, size);
RCGO(rc, truncfail);
rc = _exfile_initmmap_lw(f);
}
} else if (old_size > size) {
if (!(omode & IWFS_OWRITE)) {
return IW_ERROR_READONLY;
}
if (impl->dlsnr) {
rc = impl->dlsnr->onresize(impl->dlsnr, old_size, size, 0, &rsh);
RCGO(rc, truncfail);
}
if (!rsh) {
impl->fsize = (uint64_t) size;
rc = _exfile_initmmap_lw(f);
RCGO(rc, truncfail);
rc = iwp_ftruncate(impl->fh, size);
RCGO(rc, truncfail);
}
}
return rc;
truncfail:
impl->fsize = old_size;
IWRC(_exfile_initmmap_lw(f), rc);
return rc;
}
static iwrc _exfile_ensure_size_lw(struct IWFS_EXT *f, off_t sz) {
EXF *impl = f->impl;
assert(impl && impl->rspolicy);
if (impl->fsize >= sz) {
return 0;
}
off_t nsz = impl->rspolicy(sz, impl->fsize, f, &impl->rspolicy_ctx);
if (nsz < sz || ((uint64_t) nsz & (impl->psize - 1))) {
return IWFS_ERROR_RESIZE_POLICY_FAIL;
}
if (impl->maxoff && nsz > impl->maxoff) {
nsz = impl->maxoff;
if (nsz < sz) {
return IWFS_ERROR_MAXOFF;
}
}
return _exfile_truncate_lw(f, nsz);
}
static iwrc _exfile_sync(struct IWFS_EXT *f, iwfs_sync_flags flags) {
iwrc rc = _exfile_rlock(f);
RCRET(rc);
EXF *impl = f->impl;
int mflags = MS_SYNC;
MMAPSLOT *s = impl->mmslots;
while (s) {
if (s->mmap && s->mmap != MAP_FAILED
&& !(s->mmopts & IWFS_MMAP_PRIVATE)
&& msync(s->mmap, s->len, mflags) == -1) {
rc = iwrc_set_errno(IW_ERROR_IO_ERRNO, errno);
}
s = s->next;
}
IWRC(impl->file.sync(&impl->file, flags), rc);
IWRC(_exfile_unlock2(impl), rc);
return rc;
}
static iwrc _exfile_write(struct IWFS_EXT *f, off_t off, const void *buf, size_t siz, size_t *sp) {
MMAPSLOT *s;
EXF *impl = f->impl;
off_t end = off + siz;
off_t wp = siz, len;
*sp = 0;
if (off < 0 || end < 0) {
return IW_ERROR_OUT_OF_BOUNDS;
}
if (impl->maxoff && off + siz > impl->maxoff) {
return IWFS_ERROR_MAXOFF;
}
iwrc rc = _exfile_rlock(f);
RCRET(rc);
if (end > impl->fsize) {
rc = _exfile_unlock2(impl);
RCGO(rc, end);
rc = _exfile_wlock(f);
RCGO(rc, end);
if (end > impl->fsize) {
rc = _exfile_ensure_size_lw(f, end);
RCGO(rc, finish);
}
}
s = impl->mmslots;
while (s && wp > 0) {
if (!s->len || wp + off <= s->off) {
break;
}
if (s->off > off) {
len = MIN(wp, s->off - off);
rc = impl->file.write(&impl->file, off, (const char *) buf + (siz - wp), (size_t) len, sp);
RCGO(rc, finish);
wp = wp - *sp;
off = off + *sp;
}
if (wp > 0 && s->off <= off && s->off + s->len > off) {
len = MIN(wp, s->off + s->len - off);
if (impl->dlsnr) {
rc = impl->dlsnr->onwrite(impl->dlsnr, off - s->off, (const char *) buf + (siz - wp), len, 0);
RCGO(rc, finish);
}
memcpy(s->mmap + (off - s->off), (const char *) buf + (siz - wp), (size_t) len);
wp -= len;
off += len;
}
s = s->next;
}
if (wp > 0) {
rc = impl->file.write(&impl->file, off, (const char *) buf + (siz - wp), (size_t) wp, sp);
RCGO(rc, finish);
wp = wp - *sp;
}
*sp = siz - wp;
finish:
IWRC(_exfile_unlock2(impl), rc);
end:
if (rc) {
*sp = 0;
}
return rc;
}
static iwrc _exfile_read(struct IWFS_EXT *f, off_t off, void *buf, size_t siz, size_t *sp) {
MMAPSLOT *s;
EXF *impl;
off_t end = off + siz;
off_t rp = siz, len;
*sp = 0;
if (off < 0 || end < 0) {
return IW_ERROR_OUT_OF_BOUNDS;
}
iwrc rc = _exfile_rlock(f);
RCRET(rc);
impl = f->impl;
s = impl->mmslots;
if (end > impl->fsize) {
siz = (size_t)(impl->fsize - off);
rp = siz;
}
while (s && rp > 0) {
if (!s->len || rp + off <= s->off) {
break;
}
if (s->off > off) {
len = MIN(rp, s->off - off);
rc = impl->file.read(&impl->file, off, (char *) buf + (siz - rp), (size_t) len, sp);
RCGO(rc, finish);
rp = rp - *sp;
off = off + *sp;
}
if (rp > 0 && s->off <= off && s->off + s->len > off) {
len = MIN(rp, s->off + s->len - off);
memcpy((char *) buf + (siz - rp), s->mmap + (off - s->off), (size_t) len);
rp -= len;
off += len;
}
s = s->next;
}
if (rp > 0) {
rc = impl->file.read(&impl->file, off, (char *) buf + (siz - rp), (size_t) rp, sp);
RCGO(rc, finish);
rp = rp - *sp;
}
*sp = siz - rp;
finish:
if (rc) {
*sp = 0;
}
IWRC(_exfile_unlock2(impl), rc);
return rc;
}
static iwrc _exfile_state(struct IWFS_EXT *f, IWFS_EXT_STATE *state) {
iwrc rc = _exfile_rlock(f);
RCRET(rc);
EXF *xf = f->impl;
IWRC(xf->file.state(&xf->file, &state->file), rc);
state->fsize = f->impl->fsize;
IWRC(_exfile_unlock(f), rc);
return rc;
}
static iwrc _exfile_copy(struct IWFS_EXT *f, off_t off, size_t siz, off_t noff) {
iwrc rc = _exfile_rlock(f);
RCRET(rc);
EXF *impl = f->impl;
MMAPSLOT *s = impl->mmslots;
if (s && s->mmap && s->off == 0 && s->len >= noff + siz) { // fully mmaped file
rc = _exfile_ensure_size_lw(f, noff + siz);
RCRET(rc);
if (impl->dlsnr) {
rc = impl->dlsnr->onwrite(impl->dlsnr, noff, s->mmap + off, siz, 0);
RCRET(rc);
}
memmove(s->mmap + noff, s->mmap + off, siz);
} else {
IWRC(impl->file.copy(&impl->file, off, siz, noff), rc);
}
IWRC(_exfile_unlock(f), rc);
return rc;
}
static iwrc _exfile_remove_mmap_lw(struct IWFS_EXT *f, off_t off) {
iwrc rc = 0;
EXF *impl = f->impl;
MMAPSLOT *s = impl->mmslots;
while (s) {
if (s->off == off) {
break;
}
s = s->next;
}
if (!s) {
rc = IWFS_ERROR_NOT_MMAPED;
goto finish;
}
if (impl->mmslots == s) {
if (s->next) {
s->next->prev = s->prev;
}
impl->mmslots = s->next;
} else if (impl->mmslots->prev == s) {
s->prev->next = 0;
impl->mmslots->prev = s->prev;
} else {
s->prev->next = s->next;
s->next->prev = s->prev;
}
if (s->len) {
if (munmap(s->mmap, s->len)) {
rc = iwrc_set_errno(IW_ERROR_ERRNO, errno);
goto finish;
}
}
finish:
free(s);
return rc;
}
static iwrc _exfile_close(struct IWFS_EXT *f) {
if (!f || !f->impl) {
return 0;
}
iwrc rc = _exfile_wlock(f);
RCRET(rc);
EXF *impl = f->impl;
if (impl->dlsnr) {
rc = impl->dlsnr->onclosing(impl->dlsnr);
}
MMAPSLOT *s = impl->mmslots, *next;
while (s) {
next = s->next;
IWRC(_exfile_remove_mmap_lw(f, s->off), rc);
s = next;
}
IWRC(impl->file.close(&impl->file), rc);
f->impl = 0;
if (impl->rspolicy) { // dispose resize policy function
impl->rspolicy(-1, impl->fsize, f, &impl->rspolicy_ctx);
}
IWRC(_exfile_unlock2(impl), rc);
IWRC(_exfile_destroylocks(impl), rc);
free(impl);
return rc;
}
static iwrc _exfile_ensure_size(struct IWFS_EXT *f, off_t sz) {
iwrc rc = _exfile_rlock(f);
RCRET(rc);
if (f->impl->fsize >= sz) {
return _exfile_unlock2(f->impl);
}
rc = _exfile_unlock2(f->impl);
RCRET(rc);
rc = _exfile_wlock(f);
RCRET(rc);
rc = _exfile_ensure_size_lw(f, sz);
IWRC(_exfile_unlock2(f->impl), rc);
return rc;
}
static iwrc _exfile_truncate(struct IWFS_EXT *f, off_t sz) {
iwrc rc = _exfile_wlock(f);
RCRET(rc);
rc = _exfile_truncate_lw(f, sz);
IWRC(_exfile_unlock(f), rc);
return rc;
}
static iwrc _exfile_add_mmap_lw(struct IWFS_EXT *f, off_t off, size_t maxlen, iwfs_ext_mmap_opts_t mmopts) {
size_t tmp;
iwrc rc = 0;
MMAPSLOT *ns = 0;
EXF *impl = f->impl;
if ((uint64_t) off & (impl->psize - 1)) {
rc = IW_ERROR_NOT_ALIGNED;
goto finish;
}
if (OFF_T_MAX - off < maxlen) {
maxlen = (size_t)(OFF_T_MAX - off);
}
tmp = IW_ROUNDUP(maxlen, impl->psize);
if (tmp < maxlen || OFF_T_MAX - off < tmp) {
maxlen = IW_ROUNDOWN(maxlen, impl->psize);
} else {
maxlen = tmp;
}
if (!maxlen) {
rc = IW_ERROR_OUT_OF_BOUNDS;
goto finish;
}
assert(!(maxlen & (impl->psize - 1)));
ns = calloc(1, sizeof(*ns));
if (!ns) {
rc = iwrc_set_errno(IW_ERROR_ALLOC, errno);
goto finish;
}
ns->off = off;
ns->len = 0;
ns->maxlen = maxlen;
ns->mmopts = mmopts;
rc = _exfile_initmmap_slot_lw(f, ns);
RCGO(rc, finish);
if (impl->mmslots == 0) {
ns->next = 0;
ns->prev = ns;
impl->mmslots = ns;
} else {
MMAPSLOT *s = impl->mmslots;
while (s) {
off_t e1 = s->off + s->maxlen;
off_t e2 = ns->off + ns->maxlen;
if (IW_RANGES_OVERLAP(s->off, e1, ns->off, e2)) {
rc = IWFS_ERROR_MMAP_OVERLAP;
goto finish;
}
if (ns->off < s->off) {
break;
}
s = s->next;
}
if (s) { // insert before
ns->next = s;
ns->prev = s->prev;
s->prev->next = ns;
s->prev = ns;
if (s == impl->mmslots) {
impl->mmslots = ns;
ns->prev->next = 0;
}
} else { // insert at the end
s = impl->mmslots;
ns->next = 0;
ns->prev = s->prev;
s->prev->next = ns;
s->prev = ns;
}
}
finish:
if (rc) {
if (ns) {
if (impl->mmslots == ns) {
impl->mmslots = 0;
}
free(ns);
}
}
return rc;
}
static iwrc _exfile_add_mmap(struct IWFS_EXT *f, off_t off, size_t maxlen, iwfs_ext_mmap_opts_t mmopts) {
assert(f && off >= 0);
iwrc rc = _exfile_wlock(f);
RCRET(rc);
rc = _exfile_add_mmap_lw(f, off, maxlen, mmopts);
IWRC(_exfile_unlock(f), rc);
return rc;
}
iwrc _exfile_acquire_mmap(struct IWFS_EXT *f, off_t off, uint8_t **mm, size_t *sp) {
assert(f && mm && off >= 0);
iwrc rc = _exfile_rlock(f);
if (IW_UNLIKELY(rc)) {
*mm = 0;
if (sp) {
*sp = 0;
}
return rc;
}
MMAPSLOT *s = f->impl->mmslots;
while (s) {
if (s->off == off) {
if (s->len) {
*mm = s->mmap;
if (sp) {
*sp = s->len;
}
return 0;
}
break;
}
s = s->next;
}
*mm = 0;
if (sp) {
*sp = 0;
}
return IWFS_ERROR_NOT_MMAPED;
}
iwrc _exfile_probe_mmap_lr(struct IWFS_EXT *f, off_t off, uint8_t **mm, size_t *sp) {
assert(f && mm && off >= 0);
if (sp) {
*sp = 0;
}
*mm = 0;
iwrc rc = 0;
EXF *impl = f->impl;
MMAPSLOT *s = impl->mmslots;
while (s) {
if (s->off == off) {
if (!s->len) {
rc = IWFS_ERROR_NOT_MMAPED;
break;
}
*mm = s->mmap;
if (sp) {
*sp = s->len;
}
break;
}
s = s->next;
}
if (!rc && !*mm) {
rc = IWFS_ERROR_NOT_MMAPED;
}
return rc;
}
iwrc _exfile_probe_mmap(struct IWFS_EXT *f, off_t off, uint8_t **mm, size_t *sp) {
iwrc rc = _exfile_rlock(f);
RCRET(rc);
rc = _exfile_probe_mmap_lr(f, off, mm, sp);
IWRC(_exfile_unlock(f), rc);
return rc;
}
iwrc _exfile_release_mmap(struct IWFS_EXT *f) {
assert(f);
return _exfile_unlock(f);
}
static iwrc _exfile_remove_mmap(struct IWFS_EXT *f, off_t off) {
assert(f && off >= 0);
iwrc rc = _exfile_wlock(f);
RCRET(rc);
rc = _exfile_remove_mmap_lw(f, off);
IWRC(_exfile_unlock(f), rc);
return rc;
}
static iwrc _exfile_sync_mmap_lr(struct IWFS_EXT *f, off_t off, iwfs_sync_flags flags) {
assert(f && off >= 0);
iwrc rc = 0;
EXF *impl = f->impl;
int mflags = MS_SYNC;
MMAPSLOT *s = impl->mmslots;
while (s) {
if (s->off == off) {
if (s->len == 0) {
rc = IWFS_ERROR_NOT_MMAPED;
break;
}
if (s->mmap && s->mmap != MAP_FAILED) {
if (!(s->mmopts & IWFS_MMAP_PRIVATE)
&& msync(s->mmap, s->len, mflags) == -1) {
rc = iwrc_set_errno(IW_ERROR_IO_ERRNO, errno);
}
break;
}
}
s = s->next;
}
if (!s) {
rc = IWFS_ERROR_NOT_MMAPED;
}
return rc;
}
static iwrc _exfile_sync_mmap(struct IWFS_EXT *f, off_t off, iwfs_sync_flags flags) {
iwrc rc = _exfile_rlock(f);
RCRET(rc);
rc = _exfile_sync_mmap_lr(f, off, flags);
IWRC(_exfile_unlock(f), rc);
return rc;
}
static iwrc _exfile_remap_all(struct IWFS_EXT *f) {
assert(f);
iwrc rc = _exfile_wlock(f);
RCRET(rc);
rc = _exfile_initmmap_lw(f);
IWRC(_exfile_unlock(f), rc);
return rc;
}
static off_t _exfile_default_szpolicy(off_t nsize, off_t csize, struct IWFS_EXT *f, void **ctx) {
if (nsize == -1) {
return 0;
}
return IW_ROUNDUP(nsize, f->impl->psize);
}
off_t iw_exfile_szpolicy_fibo(off_t nsize, off_t csize, struct IWFS_EXT *f, void **_ctx) {
struct _FIBO_CTX {
off_t prev_sz;
} *ctx = *_ctx;
if (nsize == -1) {
if (ctx) {
free(ctx);
*_ctx = 0;
}
return 0;
}
if (!ctx) {
*_ctx = ctx = calloc(1, sizeof(*ctx));
if (!ctx) {
return _exfile_default_szpolicy(nsize, csize, f, _ctx);
}
}
uint64_t res = (uint64_t) csize + ctx->prev_sz;
res = MAX(res, nsize);
res = IW_ROUNDUP(res, f->impl->psize);
if (res > OFF_T_MAX) {
res = OFF_T_MAX;
}
ctx->prev_sz = csize;
return res;
}
off_t iw_exfile_szpolicy_mul(off_t nsize, off_t csize, struct IWFS_EXT *f, void **_ctx) {
IW_RNUM *mul = *_ctx;
if (nsize == -1) {
return 0;
}
if (!mul || !mul->dn || mul->n < mul->dn) {
iwlog_error2(
"Invalid iw_exfile_szpolicy_mul context arguments, fallback to the "
"default resize policy");
return _exfile_default_szpolicy(nsize, csize, f, _ctx);
}
uint64_t ret = (uint64_t) nsize;
ret /= mul->dn;
ret *= mul->n;
ret = IW_ROUNDUP(ret, f->impl->psize);
if (ret > OFF_T_MAX) {
ret = OFF_T_MAX;
}
return ret;
}
static iwrc _exfile_initlocks(IWFS_EXT *f) {
assert(f && f->impl);
assert(!f->impl->rwlock);
EXF *impl = f->impl;
if (!impl->use_locks) {
return 0;
}
impl->rwlock = calloc(1, sizeof(*impl->rwlock));
if (!impl->rwlock) {
return iwrc_set_errno(IW_ERROR_ALLOC, errno);
}
int rv = pthread_rwlock_init(impl->rwlock, (void *) 0);
if (rv) {
free(impl->rwlock);
impl->rwlock = 0;
return iwrc_set_errno(IW_ERROR_THREADING_ERRNO, rv);
}
return 0;
}
iwrc iwfs_exfile_open(IWFS_EXT *f, const IWFS_EXT_OPTS *opts) {
assert(f);
assert(opts);
iwrc rc = 0;
const char *path = opts->file.path;
memset(f, 0, sizeof(*f));
rc = iwfs_exfile_init();
RCGO(rc, finish);
f->close = _exfile_close;
f->read = _exfile_read;
f->write = _exfile_write;
f->sync = _exfile_sync;
f->state = _exfile_state;
f->copy = _exfile_copy;
f->ensure_size = _exfile_ensure_size;
f->truncate = _exfile_truncate;
f->truncate_unsafe = _exfile_truncate_lw;
f->add_mmap = _exfile_add_mmap;
f->add_mmap_unsafe = _exfile_add_mmap_lw;
f->remove_mmap = _exfile_remove_mmap;
f->remove_mmap_unsafe = _exfile_remove_mmap_lw;
f->probe_mmap = _exfile_probe_mmap;
f->probe_mmap_unsafe = _exfile_probe_mmap_lr;
f->sync_mmap = _exfile_sync_mmap;
f->sync_mmap_unsafe = _exfile_sync_mmap_lr;
f->acquire_mmap = _exfile_acquire_mmap;
f->release_mmap = _exfile_release_mmap;
f->remap_all = _exfile_remap_all;
if (!path) {
return IW_ERROR_INVALID_ARGS;
}
EXF *impl = f->impl = calloc(1, sizeof(EXF));
if (!impl) {
return iwrc_set_errno(IW_ERROR_ALLOC, errno);
}
impl->dlsnr = opts->file.dlsnr;
impl->psize = iwp_alloc_unit();
impl->rspolicy = opts->rspolicy ? opts->rspolicy : _exfile_default_szpolicy;
impl->rspolicy_ctx = opts->rspolicy_ctx;
impl->use_locks = opts->use_locks;
if (opts->maxoff >= impl->psize) {
impl->maxoff = IW_ROUNDOWN(opts->maxoff, impl->psize);
}
rc = _exfile_initlocks(f);
RCGO(rc, finish);
rc = iwfs_file_open(&impl->file, &opts->file);
RCGO(rc, finish);
IWFS_FILE_STATE fstate;
rc = impl->file.state(&impl->file, &fstate);
RCGO(rc, finish);
IWP_FILE_STAT fstat;
rc = iwp_fstat(fstate.opts.path, &fstat);
RCGO(rc, finish);
impl->fsize = fstat.size;
impl->omode = fstate.opts.omode;
impl->fh = fstate.fh;
if (impl->fsize < opts->initial_size) {
rc = _exfile_truncate_lw(f, opts->initial_size);
} else if (impl->fsize & (impl->psize - 1)) { // not a page aligned
rc = _exfile_truncate_lw(f, impl->fsize);
}
finish:
if (rc) {
if (f->impl) {
_exfile_destroylocks(f->impl);
free(f->impl);
f->impl = 0;
}
}
return rc;
}
static const char *_exfile_ecodefn(locale_t locale, uint32_t ecode) {
if (!(ecode > _IWFS_EXT_ERROR_START && ecode < _IWFS_EXT_ERROR_END)) {
return 0;
}
switch (ecode) {
case IWFS_ERROR_MMAP_OVERLAP:
return "Region is mmaped already, mmaping overlaps. "
"(IWFS_ERROR_MMAP_OVERLAP)";
case IWFS_ERROR_NOT_MMAPED:
return "Region is not mmaped. (IWFS_ERROR_NOT_MMAPED)";
case IWFS_ERROR_RESIZE_POLICY_FAIL:
return "Invalid result of resize policy function. "
"(IWFS_ERROR_RESIZE_POLICY_FAIL)";
case IWFS_ERROR_MAXOFF:
return "Maximum file offset reached. (IWFS_ERROR_MAXOFF)";
default:
break;
}
return 0;
}
iwrc iwfs_exfile_init(void) {
static int _exfile_initialized = 0;
iwrc rc = iw_init();
RCRET(rc);
if (!__sync_bool_compare_and_swap(&_exfile_initialized, 0, 1)) {
return 0; // initialized already
}
return iwlog_register_ecodefn(_exfile_ecodefn);
}
+350
View File
@@ -0,0 +1,350 @@
#pragma once
#ifndef IWEXFILE_H
#define IWEXFILE_H
/**************************************************************************************************
* IOWOW library
*
* MIT License
*
* Copyright (c) 2012-2020 Softmotions Ltd <info@softmotions.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*************************************************************************************************/
/** @file
* @brief Auto-expandable file.
* @author Anton Adamansky (adamansky@softmotions.com)
*
* @note Before using API of this module you should call
*
* `iw_init(void)` iowow module initialization routine.
*
* <strong>Features:</strong>
* - Tuneable file expansion policies.
* Custom file resize policies supported by specifying
* `IWFS_EXT_OPTS::rspolicy` option value.
* The following policies are implemented:
* - Exact. File resizing fits exactly to the size required by `write`
* operation. This is the default behaviour.
* - Fibonacci policy. Next file size computed accourding to
* fibonacci sequence of previous file sizes:
`file_size(n+1) = MAX(file_size(n) + file_size(n-1), nsize)`
* - Multiplication resize policy. Next file size:
`file_size(n+1) = N * file_size(n)` where
* `N` is a rational number `IW_RNUM` greater than `1`
* - Read/write locking over a file's address space in multithreaded
* environment.
* - File shrinking/truncation support.
* - A number mmaped regions can be registered in the file's address space.
* These regions used in read/write operation and automatically maintained
* during file resize operations.
*
* File operations implemented as function pointers contained in `IWFS_EXT` `C`
* structure.
* The `iwrc iwfs_exfile_open(IWFS_EXT *f, const IWFS_EXT_OPTS *opts);` opens
* file and initializes a given `IWFS_EXT` structure.
*/
#include "iwfile.h"
IW_EXTERN_C_START
struct IWFS_EXT_OPTS;
struct IWFS_EXT;
/**
* @enum iwfs_ext_ecode
* @brief Error codes specific to this module.
*/
typedef enum {
_IWFS_EXT_ERROR_START = (IW_ERROR_START + 3000UL),
IWFS_ERROR_MMAP_OVERLAP, /**< Region is mmaped already, mmaping overlaps */
IWFS_ERROR_NOT_MMAPED, /**< Region is not mmaped */
IWFS_ERROR_RESIZE_POLICY_FAIL, /**< Invalid result of resize policy function.*/
IWFS_ERROR_MAXOFF, /**< Maximum file offset reached. */
_IWFS_EXT_ERROR_END
} iwfs_ext_ecode;
typedef uint8_t iwfs_ext_mmap_opts_t;
/** Use shared mmaping synchronized with file data */
#define IWFS_MMAP_SHARED ((iwfs_ext_mmap_opts_t) 0x00U)
/** Use private mmap */
#define IWFS_MMAP_PRIVATE ((iwfs_ext_mmap_opts_t) 0x01U)
/**
* @brief File resize policy function type.
*
* This function called in the following cases:
* - When a file needs to be resized. Returned new file size cannot
* be lesser than requested @a nsize and must be `page aligned`.
* - When a file is closed. In this case the first argument @a nsize
* will be set to `-1` and function should return `0`.
* This call can be used in order to release resources allocated for @a ctx
* private data used in function.
*
* @param nsize Desired file size.
* @param csize Current file size.
* @param f File reference.
* @param ctx Function context data pointer. A function is allowed to initialize
* this pointer by own private data stucture.
*
* @return Computed new file size.
*/
typedef off_t (*IW_EXT_RSPOLICY)(off_t nsize, off_t csize, struct IWFS_EXT *f,
void **ctx);
/**
* @brief Fibonacci resize file policy.
*
* New `file_size(n+1) = MAX(file_size(n) + file_size(n-1), nsize)`
*/
IW_EXPORT off_t iw_exfile_szpolicy_fibo(off_t nsize, off_t csize,
struct IWFS_EXT *f, void **ctx);
/**
* @brief Rational number `IW_RNUM` file size multiplication policy.
*
* New `file_size = MAX(file_size * (N/D), nsize)`
*/
IW_EXPORT off_t iw_exfile_szpolicy_mul(off_t nsize, off_t csize,
struct IWFS_EXT *f, void **ctx);
/**
* @brief `IWFS_EXT` file options.
* @see iwrc iwfs_exfile_open(IWFS_EXT *f, const IWFS_EXT_OPTS *opts)
*/
typedef struct IWFS_EXT_OPTS {
IWFS_FILE_OPTS file; /**< Underlying file options */
off_t initial_size; /**< Initial file size */
bool use_locks; /**< If `true` file operations will be guarded by rw lock. Default: `false` */
IW_EXT_RSPOLICY rspolicy; /**< File resize policy function ptr. Default:
`exact size policy` */
void *rspolicy_ctx; /**< Custom opaque data for policy functions.
Default: `0` */
uint64_t maxoff; /**< Maximum allowed file offset. Unlimited if zero.
If maximum offset is reached `IWFS_ERROR_MAXOFF` will be reported. */
} IWFS_EXT_OPTS;
/**
* @struct IWFS_EXT_STATE
* @brief `IWFS_EXT` file state info.
* @see IWFS_EXT::state
*/
typedef struct IWFS_EXT_STATE {
IWFS_FILE_STATE file; /**< Simple file state */
off_t fsize; /**< Current file size */
} IWFS_EXT_STATE;
/**
* @brief Auto-expandable file.
*/
typedef struct IWFS_EXT {
struct IWFS_EXT_IMPL *impl;
/**
* @brief Ensures that a file's physical address space contains a given offset
* @a off
*
* Various algorithms can be used for new space allocation,
* see the features section for further explanation.
*
* @param f `IWFS_EXT`
* @param off File offset what have to be within physically allocated file
* address space.
* @return `0` on success or error code.
*
* @see off_t iw_exfile_szpolicy_fibo(off_t nsize, off_t csize, struct
* IWFS_EXT *f, void **ctx)
* @see off_t iw_exfile_szpolicy_mul(off_t nsize, off_t csize, struct IWFS_EXT
* *f, void **ctx)
*/
iwrc(*ensure_size)(struct IWFS_EXT *f, off_t off);
/**
* @brief Set the end of this file to the specified offset @a off exactly.
*/
iwrc(*truncate)(struct IWFS_EXT *f, off_t off);
iwrc(*truncate_unsafe)(struct IWFS_EXT *f, off_t off);
/**
* @brief Register an address space specified by @a off and @a len as memory
* mmaped region
* within this file.
*
* It is not required for this region be physically represented in the file's
* address space.
* As soon as this region will be used for reading/writing it will be mmaped
* and direct mmaped memory access will be used for IO in this area.
*
* For example:
* @code {.c}
* f.add_mmap(&f, 10, 20);
* f.read(&f, 5, buf, 10, sp); // read [5-15) bytes
* // [5-10) bytes will be read using system `pread`
* // [10-15) bytes will be retrieved by direct `memcpy` from mmapped
* region
* @endcode
*
* Pointer to this region can be retrieved by `IWFS_EXT::acquire_mmap`
*
* @param f `IWFS_EXT`
* @param off Offset of mmaped region
* @param len Length of mmaped region
* @return `0` on success or error code.
*/
iwrc(*add_mmap)(struct IWFS_EXT *f, off_t off, size_t len, iwfs_ext_mmap_opts_t opts);
iwrc(*add_mmap_unsafe)(struct IWFS_EXT *f, off_t off, size_t len, iwfs_ext_mmap_opts_t opts);
/**
* @brief Retrieve mmaped region by its offset @a off and keep file as read locked.
*
* If region was not mmaped previously with IWFS_EXT::add_mmap
* the `IWFS_ERROR_NOT_MMAPED` error code will be returned.
*
* WARNING: Internal read lock will be acquired and
* must be released by subsequent `release_mmap()` call
* after all activity with mmaped region has finished.
*
* @param f `IWFS_EXT`
* @param off Region start offset
* @param [out] mm Pointer assigned to start of mmaped region of `NULL` if
* error occurred.
* @param [out] sp Length of region
* @return `0` on success or error code.
*/
iwrc(*acquire_mmap)(struct IWFS_EXT *f, off_t off, uint8_t **mm, size_t *sp);
/**
* @brief Retrieve mmaped region by its offset @a off
*/
iwrc(*probe_mmap)(struct IWFS_EXT *f, off_t off, uint8_t **mm, size_t *sp);
iwrc(*probe_mmap_unsafe)(struct IWFS_EXT *f, off_t off, uint8_t **mm, size_t *sp);
/**
* @brief Release the lock acquired by successfull call of `acquire_mmap()`
*/
iwrc(*release_mmap)(struct IWFS_EXT *f);
/**
* @brief Unmap mmaped region identified by @a off
*
* The `IWFS_ERROR_NOT_MMAPED` will returned
* if region was not previously mapped with IWFS_EXT::add_mmap
*
* @param f `IWFS_EXT`
* @param off Region start offset
* @return `0` on success or error code.
*/
iwrc(*remove_mmap)(struct IWFS_EXT *f, off_t off);
iwrc(*remove_mmap_unsafe)(struct IWFS_EXT *f, off_t off);
/**
* @brief Synchronize a file with a mmaped region identified by @a off offset.
*
* The `IWFS_ERROR_NOT_MMAPED` will returned
* if region was not previously mapped with IWFS_EXT::add_mmap
*
* @param f `IWFS_EXT`
* @param off Region start offset
* @param flags Sync flags.
* @return `0` on success or error code.
*/
iwrc(*sync_mmap)(struct IWFS_EXT *f, off_t off, iwfs_sync_flags flags);
iwrc(*sync_mmap_unsafe)(struct IWFS_EXT *f, off_t off, iwfs_sync_flags flags);
/**
* @brief Remap all mmaped regions.
*
* @param f `IWFS_EXT`
*/
iwrc(*remap_all)(struct IWFS_EXT *f);
/* See iwfile.h */
/** @see IWFS_FILE::write */
iwrc(*write)(struct IWFS_EXT *f, off_t off, const void *buf, size_t siz,
size_t *sp);
/** @see IWFS_FILE::read */
iwrc(*read)(struct IWFS_EXT *f, off_t off, void *buf, size_t siz,
size_t *sp);
/** @see IWFS_FILE::close */
iwrc(*close)(struct IWFS_EXT *f);
/** @see IWFS_FILE::sync */
iwrc(*sync)(struct IWFS_EXT *f, iwfs_sync_flags flags);
/** @see IWFS_FILE::state */
iwrc(*state)(struct IWFS_EXT *f, IWFS_EXT_STATE *state);
/** @see IWFS_FILE::copy */
iwrc(*copy)(struct IWFS_EXT *f, off_t off, size_t siz, off_t noff);
} IWFS_EXT;
/**
* @brief Open exfile.
*
* <strong>Example:</strong>
*
* Open a file for multithreaded env with fibonacci file resize policy and
* initial size to 4K
*
* @code {.c}
* IWFS_EXT_OPTS opts = {
* .file = {
* .path = "myfile.dat",
* .omode = IWFS_OWRITE | IWFS_OCREATE,
* .lock_mode = IWP_WLOCK
* },
* .initial_size = 4096,
* .use_locks = true,
* .rspolicy = iw_exfile_szpolicy_fibo
* };
* IWFS_EXT f;
* iwrc rc = iwfs_exfile_open(&f, &opts);
*
* rc = f.write(&f, ...);
* ...
* @endcode
*
*
* @param f Exfile handle. Simple memory placeholder.
* @param opts File open options. Initialized file options.
* @return Error code of `0` on success.
* @relatesalso IWFS_EXT
*/
IW_EXPORT WUR iwrc iwfs_exfile_open(IWFS_EXT *f, const IWFS_EXT_OPTS *opts);
/**
* @brief Init `iwexfile` submodule.
*/
IW_EXPORT WUR iwrc iwfs_exfile_init(void);
IW_EXTERN_C_END
#endif
+310
View File
@@ -0,0 +1,310 @@
/**************************************************************************************************
* IOWOW library
*
* MIT License
*
* Copyright (c) 2012-2020 Softmotions Ltd <info@softmotions.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*************************************************************************************************/
#include "iwcfg.h"
#include "log/iwlog.h"
#include "platform/iwp.h"
#include "iwfile.h"
#include "iwutils.h"
#include <fcntl.h>
#include <limits.h>
#include <unistd.h>
#ifdef _WIN32
#include <libiberty/libiberty.h>
#define strndup xstrndup
#endif
typedef struct IWFS_FILE_IMPL {
HANDLE fh; /**< File handle. */
iwfs_openstatus ostatus; /**< File open status. */
IWFS_FILE_OPTS opts; /**< File open options. */
} IWF;
static iwrc _iwfs_write(struct IWFS_FILE *f, off_t off, const void *buf, size_t siz, size_t *sp) {
assert(f);
IWF *impl = f->impl;
if (!impl) {
return IW_ERROR_INVALID_STATE;
}
if (!(impl->opts.omode & IWFS_OWRITE)) {
return IW_ERROR_READONLY;
}
iwrc rc = iwp_pwrite(impl->fh, off, buf, siz, sp);
if (!rc && impl->opts.dlsnr) {
rc = impl->opts.dlsnr->onwrite(impl->opts.dlsnr, off, buf, siz, 0);
}
return rc;
}
static iwrc _iwfs_read(struct IWFS_FILE *f, off_t off, void *buf, size_t siz, size_t *sp) {
assert(f);
IWF *impl = f->impl;
if (!impl) {
return IW_ERROR_INVALID_STATE;
}
return iwp_pread(impl->fh, off, buf, siz, sp);
}
static iwrc _iwfs_close(struct IWFS_FILE *f) {
if (!f || !f->impl) {
return 0;
}
iwrc rc = 0;
IWF *impl = f->impl;
IWFS_FILE_OPTS *opts = &impl->opts;
#ifndef _WIN32
if (opts->path && (opts->omode & IWFS_OUNLINK)) {
unlink(opts->path);
}
#endif
if (opts->lock_mode != IWP_NOLOCK) {
IWRC(iwp_unlock(impl->fh), rc);
}
IWRC(iwp_closefh(impl->fh), rc);
if (opts->path) {
free((char *) opts->path);
opts->path = 0;
}
free(f->impl);
f->impl = 0;
return rc;
}
static iwrc _iwfs_sync(struct IWFS_FILE *f, iwfs_sync_flags flags) {
assert(f);
iwrc rc = 0;
if (!f->impl) {
return IW_ERROR_INVALID_STATE;
}
IWF *impl = f->impl;
if (flags & IWFS_FDATASYNC) {
#ifdef __APPLE__
if (fcntl(impl->fh, F_FULLFSYNC) == -1) {
return iwrc_set_errno(IW_ERROR_IO_ERRNO, errno);
}
#else
if (iwp_fdatasync(impl->fh) == -1) {
return iwrc_set_errno(IW_ERROR_IO_ERRNO, errno);
}
#endif
} else if (iwp_fsync(impl->fh) == -1) {
return iwrc_set_errno(IW_ERROR_IO_ERRNO, errno);
}
if (impl->opts.dlsnr) {
rc = impl->opts.dlsnr->onsynced(impl->opts.dlsnr, 0);
}
return rc;
}
static iwrc _iwfs_state(struct IWFS_FILE *f, IWFS_FILE_STATE *state) {
assert(f);
assert(state);
memset(state, 0, sizeof(*state));
IWF *impl = f->impl;
state->is_open = (impl != 0);
if (!state->is_open) {
return 0;
}
state->ostatus = impl->ostatus;
state->opts = impl->opts;
state->fh = impl->fh;
return 0;
}
static iwrc _iwfs_copy(struct IWFS_FILE *f, off_t off, size_t siz, off_t noff) {
assert(f);
IWF *impl = f->impl;
if (!impl) {
return IW_ERROR_INVALID_STATE;
}
if (!(impl->opts.omode & IWFS_OWRITE)) {
return IW_ERROR_READONLY;
}
iwrc rc = iwp_copy_bytes(impl->fh, off, siz, noff);
if (!rc && impl->opts.dlsnr) {
rc = impl->opts.dlsnr->oncopy(impl->opts.dlsnr, off, siz, noff, 0);
}
return rc;
}
iwrc iwfs_file_open(IWFS_FILE *f, const IWFS_FILE_OPTS *_opts) {
if (!f || !_opts || !_opts->path) {
return IW_ERROR_INVALID_ARGS;
}
IWFS_FILE_OPTS *opts;
IWF *impl;
IWP_FILE_STAT fstat;
iwfs_omode omode;
iwrc rc;
int mode;
memset(f, 0, sizeof(*f));
rc = iwfs_file_init();
RCRET(rc);
f->write = _iwfs_write;
f->read = _iwfs_read;
f->close = _iwfs_close;
f->sync = _iwfs_sync;
f->state = _iwfs_state;
f->copy = _iwfs_copy;
impl = f->impl = calloc(sizeof(IWF), 1);
if (!impl) {
return iwrc_set_errno(IW_ERROR_ALLOC, errno);
}
impl->opts = *_opts;
opts = &impl->opts;
if (opts->dlsnr) {
IWDLSNR *l = opts->dlsnr;
if (!l->onopen || !l->onclosing || !l->oncopy || !l->onresize ||
!l->onset || !l->onsynced || !l->onwrite) {
iwlog_ecode_error2(IW_ERROR_INVALID_ARGS, "Invalid 'opts->dlsnr' specified");
return IW_ERROR_INVALID_ARGS;
}
}
if (opts->omode & IWFS_OTMP) {
opts->path = iwp_allocate_tmpfile_path(opts->path);
if (!opts->path) {
rc = iwrc_set_errno(IW_ERROR_ERRNO, errno);
goto finish;
}
} else {
opts->path = strndup(_opts->path, MAXPATHLEN);
if (!opts->path) {
rc = iwrc_set_errno(IW_ERROR_ALLOC, errno);
goto finish;
}
}
if (!opts->lock_mode) {
opts->lock_mode = IWFS_DEFAULT_LOCKMODE; // -V1048
}
if (!opts->omode) {
opts->omode = IWFS_DEFAULT_OMODE;
}
if (!opts->filemode) {
opts->filemode = IWFS_DEFAULT_FILEMODE;
}
opts->omode |= IWFS_OREAD;
if (opts->omode & IWFS_OTMP) {
opts->omode |= IWFS_OTRUNC;
opts->lock_mode |= IWP_WLOCK;
}
if (opts->omode & IWFS_OTRUNC) {
opts->omode |= IWFS_OWRITE;
opts->omode |= IWFS_OCREATE;
}
if (opts->omode & IWFS_OUNLINK) {
opts->omode |= IWFS_OWRITE;
}
if ((opts->omode & IWFS_OCREATE) || (opts->omode & IWFS_OTRUNC)) {
opts->omode |= IWFS_OWRITE;
}
omode = opts->omode;
if (!(opts->omode & IWFS_OWRITE) && (opts->lock_mode & IWP_WLOCK)) {
opts->lock_mode &= ~IWP_WLOCK;
}
rc = iwp_fstat(opts->path, &fstat);
if (!rc && !(opts->omode & IWFS_OTRUNC)) {
impl->ostatus = IWFS_OPEN_EXISTING;
} else {
impl->ostatus = IWFS_OPEN_NEW;
}
rc = 0;
mode = O_RDONLY;
if (omode & IWFS_OWRITE) {
mode = O_RDWR;
if (omode & IWFS_OCREATE) {
mode |= O_CREAT;
}
if (omode & IWFS_OTRUNC) {
mode |= O_TRUNC;
}
}
#ifndef _WIN32
impl->fh = open(opts->path, mode, opts->filemode);
if (INVALIDHANDLE(impl->fh)) {
if (errno == ENOENT) {
rc = IW_ERROR_NOT_EXISTS;
} else {
rc = iwrc_set_errno(IW_ERROR_IO_ERRNO, errno);
}
goto finish;
}
#else
DWORD womode = GENERIC_READ;
DWORD wcmode = OPEN_EXISTING;
if (omode & IWFS_OWRITE) {
womode |= GENERIC_WRITE;
if (omode & IWFS_OTRUNC) {
wcmode = CREATE_ALWAYS;
} else if (omode & IWFS_OCREATE) {
wcmode = OPEN_ALWAYS;
}
}
DWORD smode = FILE_SHARE_READ | FILE_SHARE_WRITE;
DWORD flags = FILE_ATTRIBUTE_NORMAL;
if (opts->omode & IWFS_OUNLINK) {
smode |= FILE_SHARE_DELETE;
flags |= FILE_FLAG_DELETE_ON_CLOSE;
}
impl->fh = CreateFile(opts->path, womode, smode, NULL, wcmode, flags, NULL);
if (INVALIDHANDLE(impl->fh)) {
uint32_t err = GetLastError();
if (err == ERROR_FILE_NOT_FOUND) {
rc = IW_ERROR_NOT_EXISTS;
} else {
rc = iwrc_set_werror(IW_ERROR_IO_ERRNO, err);
}
goto finish;
}
#endif
if (opts->lock_mode != IWP_NOLOCK) {
rc = iwp_flock(impl->fh, opts->lock_mode);
RCGO(rc, finish);
}
finish:
if (rc) {
impl->ostatus = IWFS_OPEN_FAIL;
if (opts->path) {
free((char *) opts->path);
}
f->impl = 0;
free(impl);
}
return rc;
}
iwrc iwfs_file_init(void) {
return iw_init();
}
+224
View File
@@ -0,0 +1,224 @@
#pragma once
#ifndef IW_FILE_H
#define IW_FILE_H
/**************************************************************************************************
* IOWOW library
*
* MIT License
*
* Copyright (c) 2012-2020 Softmotions Ltd <info@softmotions.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*************************************************************************************************/
/**
* @file
* @brief Simple read-write file abstraction implementation.
* @author Anton Adamansky (adamansky@softmotions.com)
*
* @note Before using API of this module you should call
* `iw_init(void)` iowow module initialization routine.
*
* File operations implemented as function pointers contained in `IWFS_FILE` `C`
* structure.
* The `iwfs_file_open(IWFS_FILE *f, const IWFS_FILE_OPTS *opts)` opens file and
* initializes a given `IWFS_FILE` structure.
*
* <strong>Common use case:</strong>.
* @code {.c}
*
* #include <iowow/iwfile.h>
*
* iw_init(); //Initialize iowoow library
*
* IWFS_FILE f;
* IWFS_FILE_OPTS opts = { //File options
* .path = "file path",
* ...
* };
* iwrc rc = iwfs_file_open(&f, &opts);
* if (!rc) {
* .. //read/write operations
* rc = f.close(&f);
* }
* @endcode
*/
#include "iowow.h"
#include "iwlog.h"
#include "iwp.h"
#include "iwdlsnr.h"
IW_EXTERN_C_START
/** File open mode */
typedef uint8_t iwfs_omode;
/** Open file as a reader.*/
#define IWFS_OREAD ((iwfs_omode) 0x01U)
/** Open file as a writer. */
#define IWFS_OWRITE ((iwfs_omode) 0x02U)
/** If file is missing it will be created on open. */
#define IWFS_OCREATE ((iwfs_omode) 0x04U)
/** Truncate file on open. */
#define IWFS_OTRUNC ((iwfs_omode) 0x08U)
/** Unlink(delete) file on close */
#define IWFS_OUNLINK ((iwfs_omode) 0x10U)
/** Temp file will be created, in this case specified file name will act as temp file name prefix */
#define IWFS_OTMP ((iwfs_omode) 0x20U)
/** Status of an open file operation */
typedef uint8_t iwfs_openstatus;
/** Open failed. */
#define IWFS_OPEN_FAIL ((iwfs_openstatus) 0x00U)
/** Open success, new file've been created. */
#define IWFS_OPEN_NEW ((iwfs_openstatus) 0x01U)
/** Open success, existing file've been opened. */
#define IWFS_OPEN_EXISTING ((iwfs_openstatus) 0x02U)
/** Sync file data options */
typedef uint8_t iwfs_sync_flags;
#define IWFS_SYNCDEFAULT ((iwfs_sync_flags) 0x00U)
#define IWFS_FDATASYNC ((iwfs_sync_flags) 0x01U)
#define IWFS_DEFAULT_OMODE (IWFS_OCREATE)
#define IWFS_DEFAULT_LOCKMODE (IWP_NOLOCK)
#define IWFS_DEFAULT_FILEMODE \
00666 /**< Default permission of created files */
/**
* @brief `IWFS_FILE` file options.
* @see iwrc iwfs_file_open(IWFS_FILE *f, const IWFS_FILE_OPTS *opts)
*/
typedef struct {
const char *path; /**< Required file path. */
iwfs_omode omode; /**< File open mode. */
iwp_lockmode lock_mode; /**< File locking mode. */
/**< Specifies the permissions to use in case a new file is created,
`int open(const char *pathname, int flags, mode_t mode)` */
int filemode;
IWDLSNR *dlsnr; /**< Optional data listener */
} IWFS_FILE_OPTS;
/**
* @brief `IWFS_FILE` file state info.
* @see IWFS_FILE::state
*/
typedef struct {
int is_open; /**< `1` if file in open state */
iwfs_openstatus ostatus; /**< File open status. */
IWFS_FILE_OPTS opts; /**< File open options. */
HANDLE fh; /**< File handle */
} IWFS_FILE_STATE;
/**
* @struct IWFS_FILE
* @brief Simple file implementation.
*/
typedef struct IWFS_FILE {
void *impl; /**< Implementation specific data */
/**
* @brief Write @a buf bytes into the file
*
* @param f `struct IWFS_FILE` pointer
* @param off Offset from start of the file where bytes will write.
* @param buf Buffer to write.
* @param siz Number of bytes to write.
* @param [out] sp Number of bytes actually written
* @return `0` on success or error code.
*/
iwrc(*write)(struct IWFS_FILE *f, off_t off, const void *buf, size_t siz, size_t *sp);
/**
* @brief Read @a siz bytes into @a buf at the specified offset @a off
*
* @param f `struct IWFS_FILE` pointer.
* @param off Offset from start of the file.
* @param buf Buffer to read into.
* @param siz Number of bytes to read.
* @param [out] sp Number of bytes actually read.
* @return `0` on success or error code.
*/
iwrc(*read)(struct IWFS_FILE *f, off_t off, void *buf, size_t siz, size_t *sp);
/**
* @brief Closes this file.
* @return `0` on success or error code.
*/
iwrc(*close)(struct IWFS_FILE *f);
/**
* @brief Sync file data with fs.
* @param f `struct IWFS_FILE` pointer.
* @param opts File sync options.
*/
iwrc(*sync)(struct IWFS_FILE *f, iwfs_sync_flags flags);
/**
* @brief Return current file state.
* @param f `struct IWFS_FILE` pointer.
* @param [out] state File state placeholder.
* @return `0` on success or error code.
*
* @see struct IWFS_FILE_STATE
*/
iwrc(*state)(struct IWFS_FILE *f, IWFS_FILE_STATE *state);
/**
* @brief Copy data within a file
* @param f `struct IWFS_FILE` pointer.
* @param off Data offset
* @param siz Data size
* @param noff New data offset
*/
iwrc(*copy)(struct IWFS_FILE *f, off_t off, size_t siz, off_t noff);
} IWFS_FILE;
/**
* @brief Open file and initialize a given @a f structure.
*
* <strong>File open options:</strong>
* @code {.c}
* opts = {
* .path = "file path", //File path. This options value is requied.
* .omode = ..., //File open mode.
* // Default: `IWFS_DEFAULT_OMODE`
* .lock_mode = ..., //File locking mode acquired by process opened this file.
* // Default: `IWP_NOLOCK`
* .filemode = .. //Specifies the permissions to use in case a new file is created.
* // Default: `00644`
* }
* @endcode
*
* @param f `struct IWFS_FILE` pointer.
* @param opts [in] File open options
* @return `0` on success or error code.
* @relatesalso IWFS_FILE
*/
IW_EXPORT WUR iwrc iwfs_file_open(IWFS_FILE *f, const IWFS_FILE_OPTS *opts);
/**
* @brief Init `iwfile` submodule.
*/
IW_EXPORT WUR iwrc iwfs_file_init(void);
IW_EXTERN_C_END
#endif
+37
View File
@@ -0,0 +1,37 @@
/**************************************************************************************************
* IOWOW library
*
* MIT License
*
* Copyright (c) 2012-2020 Softmotions Ltd <info@softmotions.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*************************************************************************************************/
#include "iwfile.h"
#include "iwexfile.h"
#include "iwfsmfile.h"
iwrc iwfs_init(void) {
iwrc rc = 0;
IWRC(iwfs_file_init(), rc);
IWRC(iwfs_exfile_init(), rc);
IWRC(iwfs_fsmfile_init(), rc);
return rc;
}
+2040
View File
File diff suppressed because it is too large Load Diff
+409
View File
@@ -0,0 +1,409 @@
#pragma once
#ifndef IWFSMFILE_H
#define IWFSMFILE_H
/**************************************************************************************************
* IOWOW library
*
* MIT License
*
* Copyright (c) 2012-2020 Softmotions Ltd <info@softmotions.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*************************************************************************************************/
/** @file
* @brief Auto-expandable file with support of reader/writer address space
locking and free space block management using bitmaps.
* @author Anton Adamansky (adamansky@softmotions.com)
*
* @note Before using API of this module you should call
* `iw_init(void)` iowow module initialization routine.
*
* <strong>Features:</strong>
*
* - Address blocks allocation and deallocation using bitmaps.
* - Read/write file address space locking.
* - Tunable file expansion policies.
* - Read/write methods locking option in multithreaded environment.
* - File shrinking/truncation support.
* - A number mmaped regions can be registered in the file's address space.
* These regions used in read/write operation and automatically maintained
* during file resize operations.
*
* File operations implemented as function pointers contained
* in `IWFS_FSM` `C` structure.
* The `iwfs_fsmfile_open(IWFS_FSM *f, const IWFS_FSM_OPTS *opts)` opens file
* and initializes a given `IWFS_FSM` structure.
*
* <strong>File format:</strong>
* @verbatim
[FSM_CTL_MAGICK u32][block pow u8]
[bmoffset u64][bmlength u64]
[crzsum u64][crznum u32][crszvar u64][reserved u256]
[custom header size u32][custom header data...]
[fsm data...] @endverbatim
*
* <strong>where:</strong>
*
* - <b>FSM_CTL_MAGICK:</b> Free-space file magic number (32 bit)
* - <b>block pow:</b> Block size as power of `2` Eg: `6` means `64` bit block
size. (8 bit)
* - <b>bmoffset:</b> Free space bitmap area offset in bytes (64 bit)
* - <b>bmlength:</b> Free space bitmap area length. (64 bit)
* - <b>crzsum:</b> Number of allocated blocks. (64 bit)
* - <b>crznum:</b> Number of all allocated continuous areas. (32 bit)
* - <b>crszvar</b> Allocated areas length standard variance (deviation^2 * N) (64 bit)
* - <b>reserved:</b> Reserved space.
* - <b>custom header size:</b> Length of custom header area. See
`IWFS_FSM::writehdr` and `IWFS_FSM::readhdr`
*/
#include "iwexfile.h"
#include <stdbool.h>
#include <math.h>
IW_EXTERN_C_START
/** Free space allocation flags
* @see IWFS_FSM::allocate
*/
typedef uint8_t iwfs_fsm_aflags;
/** Use default allocation settings */
#define IWFSM_ALLOC_DEFAULTS ((iwfs_fsm_aflags) 0x00U)
/** Do not @em overallocate a requested free space in order to reduce fragmentation */
#define IWFSM_ALLOC_NO_OVERALLOCATE ((iwfs_fsm_aflags) 0x01U)
/** Do not extend the file and its bitmap free space mapping in the case if
* file size expansion is required.
* In this case the `IWFS_ERROR_NO_FREE_SPACE` error will be raised.*/
#define IWFSM_ALLOC_NO_EXTEND ((iwfs_fsm_aflags) 0x02U)
/** Force offset of an allocated space to be page aligned. */
#define IWFSM_ALLOC_PAGE_ALIGNED ((iwfs_fsm_aflags) 0x04U)
/** Do not collect internal allocation stats for this allocation. */
#define IWFSM_ALLOC_NO_STATS ((iwfs_fsm_aflags) 0x08U)
/** Force all of the allocated address space backed by real file address space. */
#define IWFSM_SOLID_ALLOCATED_SPACE ((iwfs_fsm_aflags) 0x10U)
/** Do msync of bitmap allocation index. */
#define IWFSM_SYNC_BMAP ((iwfs_fsm_aflags) 0x20U)
#define IWFSM_MAGICK 0x19cc7cc
#define IWFSM_CUSTOM_HDR_DATA_OFFSET \
(4 /*magic*/ + 1 /*block pow*/ + 8 /*fsm bitmap block offset */ + 8 /*fsm bitmap block length*/ + \
8 /*all allocated block length sum */ + 4 /*number of all allocated areas */ + \
8 /* allocated areas length standard variance (deviation^2 * N) */ + 32 /*reserved*/ + \
4 /*custom hdr size*/)
/** File cleanup flags used in `IWFS_FSM::clear` */
typedef uint8_t iwfs_fsm_clrfalgs;
/** Perform file size trimming after cleanup */
#define IWFSM_CLEAR_TRIM ((iwfs_fsm_clrfalgs) 0x01U)
/** `IWFS_FSM` file open modes used in `IWFS_FSM_OPTS` */
typedef uint8_t iwfs_fsm_openflags;
/** Do not use threading locks */
#define IWFSM_NOLOCKS ((iwfs_fsm_openflags) 0x01U)
/** Strict block checking for alloc/dealloc operations. 10-15% performance overhead. */
#define IWFSM_STRICT ((iwfs_fsm_openflags) 0x02U)
/** Do not trim fsm file on close */
#define IWFSM_NO_TRIM_ON_CLOSE ((iwfs_fsm_openflags) 0x04U)
/**
* @brief Error codes specific to `IWFS_FSM`.
*/
typedef enum {
_IWFS_FSM_ERROR_START = (IW_ERROR_START + 4000UL),
IWFS_ERROR_NO_FREE_SPACE, /**< No free space. */
IWFS_ERROR_INVALID_BLOCK_SIZE, /**< Invalid block size specified */
IWFS_ERROR_RANGE_NOT_ALIGNED, /**< Specified range/offset is not aligned with
page/block */
IWFS_ERROR_FSM_SEGMENTATION, /**< Free-space map segmentation error */
IWFS_ERROR_INVALID_FILEMETA, /**< Invalid file-metadata */
IWFS_ERROR_PLATFORM_PAGE, /**< Platform page size incopatibility, data
migration required. */
IWFS_ERROR_RESIZE_FAIL, /**< Failed to resize file */
_IWFS_FSM_ERROR_END
} iwfs_fsm_ecode;
/**
* @brief `IWFS_FSM` file options.
* @see iwfs_fsmfile_open(IWFS_FSM *f, const IWFS_FSM_OPTS *opts)
*/
typedef struct IWFS_FSM_OPTS {
IWFS_EXT_OPTS exfile;
size_t bmlen; /**< Initial size of free-space bitmap */
uint32_t hdrlen; /**< Length of custom file header.*/
iwfs_fsm_openflags oflags; /**< Operation mode flags */
iwfs_ext_mmap_opts_t mmap_opts; /**< Defaul mmap options used in `add_mmap` */
uint8_t bpow; /**< Block size power for 2 */
bool mmap_all; /**< Mmap all file data */
} IWFS_FSM_OPTS;
/**
* @brief `IWFS_FSM` file state container.
* @see IWFS_FSM::state
*/
typedef struct IWFS_FSM_STATE {
IWFS_EXT_STATE exfile; /**< File pool state */
size_t block_size; /**< Size of data block in bytes. */
iwfs_fsm_openflags oflags; /**< Operation mode flags. */
uint32_t hdrlen; /**< Length of custom file header length in bytes */
uint64_t blocks_num; /**< Number of available data blocks. */
uint64_t free_segments_num; /**< Number of free (deallocated) continuous data
segments. */
double_t avg_alloc_size; /**< Average allocation number of blocks */
double_t alloc_dispersion; /**< Average allocation blocks dispersion */
} IWFS_FSM_STATE;
typedef struct IWFS_FSMDBG_STATE {
IWFS_FSM_STATE state;
uint64_t bmoff;
uint64_t bmlen;
uint64_t lfbklen;
uint64_t lfbkoff;
} IWFS_FSMDBG_STATE;
/**
* @brief Auto-expandable file with support of reader/writer address space
* locking
* and free space blocks management using bitmaps.
*/
typedef struct IWFS_FSM {
struct IWFS_FSM_IMPL *impl;
/**
* @brief Allocate a continuous address space within a file
* with length greater or equal to the desired @a len bytes.
*
* `Offset` and `length` allocated area will be block size aligned.
*
* @param f `IWFS_FSM` file.
* @param len Desired length of an allocated area in bytes.
* @param [in,out] oaddr Placeholder for the address of an allocated area.
* Value of @a oaddr passed to this function used as
* `hint` in order
* to allocate area located closely to the specified @a
* oaddr value.
* @param [out] olen Actual length of an allocated area in bytes.
* @param opts Allocation options bitmask flag @ref iwfs_fsm_aflags
* @return `0` on success or error code.
*/
iwrc(*allocate)(struct IWFS_FSM *f, off_t len, off_t *oaddr, off_t *olen,
iwfs_fsm_aflags opts);
/**
* @brief Reallocate and adjust a size of an allocated block.
*
* If the given @a nlen value lesser than actual length of segment @a olen in
* that case
* segment will be truncated.
*
* @param f `IWFS_FSM` file.
* @param nlen Desired length of segment in bytes.
* @param oaddr [in,out] Address of an allocated segment. Placeholder for new
* address of reallocated segment.
* @param olen [in,out] Length of an allocated segment. Placeholder for length
* of reallocated segment.
* @param opts Allocation options bitmask flag @ref iwfs_fsm_aflags
* @return `0` on success or error code.
*/
iwrc(*reallocate)(struct IWFS_FSM *f, off_t nlen, off_t *oaddr, off_t *olen,
iwfs_fsm_aflags opts);
/**
* @brief Free a previously allocated area.
* @param addr Address space offset in bytes <em>it must be block size
* aligned</em>.
* @param len Length of area to release.
* @return `0` on success or error code.
*/
iwrc(*deallocate)(struct IWFS_FSM *f, off_t addr, off_t len);
/**
* @brief Check allocation status of region specified by @a addr and @a len
* @return `0` on success or error code.
*/
iwrc(*check_allocation_status)(struct IWFS_FSM *f, off_t addr, off_t len, bool allocated);
/**
* @brief Write a data to the custom file header.
*
* A custom file header size specified in IWFS_FSM_OPTS::hdrlen options on
* file creation.
*
* @param off Offset position relative to custom header start offset.
* @param buf Data buffer to write
* @param siz Number of bytes of @a buf to write into header.
* @return `0` on success or error code.
*/
iwrc(*writehdr)(struct IWFS_FSM *f, off_t off, const void *buf, off_t siz);
/**
* @brief Read a data from the custom file header.
*
* A custom file header size specified in IWFS_FSM_OPTS::hdrlen options on
* file creation.
*
* @param off Offset position relative to custom header start offset.
* @param [out] buf Data buffer to read into
* @param Number of bytes to read
*/
iwrc(*readhdr)(struct IWFS_FSM *f, off_t off, void *buf, off_t siz);
/**
* @brief Cleanup all allocated data blocks and reset the file to the initial
* empty state.
*
* @param clrflags
* @return `0` on success or error code.
*/
iwrc(*clear)(struct IWFS_FSM *f, iwfs_fsm_clrfalgs clrflags);
/* See iwexfile.h */
/** @see IWFS_EXT::ensure_size */
iwrc(*ensure_size)(struct IWFS_FSM *f, off_t size);
/** @see IWFS_EXT::add_mmap */
iwrc(*add_mmap)(struct IWFS_FSM *f, off_t off, size_t maxlen, iwfs_ext_mmap_opts_t opts);
/** @see IWFS_EXT::remap_all */
iwrc(*remap_all)(struct IWFS_FSM *f);
/**
* @brief Get a pointer to the registered mmap area starting at `off`.
*
* WARNING: Internal read lock will be acquired and
* must be released by subsequent `release_mmap()` call
* after all activity with mmaped region has finished.
*
* @see IWFS_FSM::add_mmap
* @see IWFS_EXT::acquire_mmap
*/
iwrc(*acquire_mmap)(struct IWFS_FSM *f, off_t off, uint8_t **mm, size_t *sp);
/**
* @brief Retrieve mmaped region by its offset @a off
*/
iwrc(*probe_mmap)(struct IWFS_FSM *f, off_t off, uint8_t **mm, size_t *sp);
/**
* @brief Release the lock acquired by successfull call of `acquire_mmap()`
*/
iwrc(*release_mmap)(struct IWFS_FSM *f);
/** @see IWFS_EXT::remove_mmap */
iwrc(*remove_mmap)(struct IWFS_FSM *f, off_t off);
/** @see IWFS_EXT::sync_mmap */
iwrc(*sync_mmap)(struct IWFS_FSM *f, off_t off, iwfs_sync_flags flags);
/* See iwfile.h */
/** @see IWFS_FILE::write */
iwrc(*write)(struct IWFS_FSM *f, off_t off, const void *buf, size_t siz,
size_t *sp);
/** @see IWFS_FILE::read */
iwrc(*read)(struct IWFS_FSM *f, off_t off, void *buf, size_t siz,
size_t *sp);
/** @see IWFS_FILE::close */
iwrc(*close)(struct IWFS_FSM *f);
/** @see IWFS_FILE::sync */
iwrc(*sync)(struct IWFS_FSM *f, iwfs_sync_flags flags);
/** @see IWFS_FILE::state */
iwrc(*state)(struct IWFS_FSM *f, IWFS_FSM_STATE *state);
/** get access to the underlying iwextfile instance */
iwrc(*extfile)(struct IWFS_FSM *f, IWFS_EXT **ext);
} IWFS_FSM;
/**
* @brief Open `IWFS_FSM` file.
*
* <strong>Example:</strong>
*
* Open a buffer pool file for multithreaded env with fibonacci file resize
* policy with block size of 64 bytes and custom file header of 255 bytes
* length.
*
* @code {.c}
* IWFS_FSM_OPTS opts = {
* .exfile = {
* .file = {
* .path = "myfile.dat",
* .omode = IWFS_OWRITE | IWFS_OCREATE,
* .lock_mode = IWP_WLOCK
* },
* .rspolicy = iw_exfile_szpolicy_fibo
* },
* .bpow = 6, // 2^6 bytes block size
* .hdrlen = 255, // Size of custom file header
* .oflags = IWFSM_STRICT // Use verbose free-space bitmap checking for
* // allocations (10-15% overhead)
* };
*
* IWFS_FSM f;
* size_t sp;
* off_t space_len, space_addr = 0;
*
* iwrc rc = iwfs_fsmfile_open(&f, &opts);
*
* //Allocate 2 blocks of file space
* rc = f.allocate(&f, 128, &space_addr, &space_len, 0);
* if (!rc) {
* int data = 33;
* // Write some data to the allocated block with writer lock acquired on
* // `[space_addr, sizeof(data))`
* rc = f.lwrite(&f, space_addr, &data, sizeof(data), &sp);
* ...
* }
* ...
* @endcode
*
* @param f File handle
* @param opts File open options
* @relatesalso IWFS_FSM
*/
IW_EXPORT WUR iwrc iwfs_fsmfile_open(IWFS_FSM *f, const IWFS_FSM_OPTS *opts);
/**
* @brief Init `iwfsmfile` submodule.
*/
IW_EXPORT WUR iwrc iwfs_fsmfile_init(void);
IW_EXTERN_C_END
#endif
+13
View File
@@ -0,0 +1,13 @@
link_libraries(iowow_s ${CUNIT_LIBRARIES})
include_directories(${CUNIT_INCLUDE_DIRS})
set(TEST_DATA_DIR ${CMAKE_CURRENT_BINARY_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${TEST_DATA_DIR})
foreach(TN IN ITEMS iwfs_test1 iwfs_test2 iwfs_test3)
add_executable(${TN} ${TN}.c)
set_target_properties(${TN} PROPERTIES
COMPILE_FLAGS "-DIW_STATIC")
add_test(NAME ${TN} WORKING_DIRECTORY ${TEST_DATA_DIR}
COMMAND ${TEST_TOOL_CMD} $<TARGET_FILE:${TN}>)
endforeach()
+372
View File
@@ -0,0 +1,372 @@
//
/**************************************************************************************************
* IOWOW library
*
* MIT License
*
* Copyright (c) 2012-2020 Softmotions Ltd <info@softmotions.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*************************************************************************************************/
#include "iowow.h"
#include "log/iwlog.h"
#include "fs/iwexfile.h"
#include "utils/iwutils.h"
#include "iwcfg.h"
#include <CUnit/Basic.h>
#include <unistd.h>
#define UNLINK() \
unlink("iwfs_exfile_test1.dat"); \
unlink("iwfs_exfile_test1_2.dat"); \
unlink("test_mmap1.dat"); \
unlink("test_fibo_inc.dat")
int init_suite() {
int rc = iw_init();
UNLINK();
return rc;
}
int clean_suite() {
UNLINK();
return 0;
}
void iwfs_exfile_test1() {
iwrc rc = 0;
IWFS_EXT ef;
const char *path = "iwfs_exfile_test1.dat";
IWFS_EXT_OPTS opts = {
.file = {
.path = path,
.lock_mode = IWP_WLOCK,
.omode = IWFS_DEFAULT_OMODE | IWFS_OTRUNC
},
.use_locks = 1
};
IWRC(iwfs_exfile_open(&ef, &opts), rc);
CU_ASSERT_EQUAL_FATAL(rc, 0);
char data[] = "b069a540-bc92-49ba-95e9-d1a2ee9e8c8f";
size_t sp, sp2;
// iwrc(*write)(struct IWFS_EXT* f, off_t off, const void *buf, size_t siz,
// size_t *sp);
IWRC(ef.write(&ef, 0, 0, 0, &sp), rc);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL(sp, 0);
IWRC(ef.write(&ef, 1, 0, 0, &sp), rc);
CU_ASSERT_EQUAL_FATAL(rc, 0);
IWP_FILE_STAT fstat;
IWRC(iwp_fstat(path, &fstat), rc);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL(sp, 0);
CU_ASSERT_EQUAL(fstat.size, iwp_alloc_unit());
IWRC(ef.write(&ef, 1, data, sizeof(data), &sp), rc);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL(sp, 37);
IWRC(ef.close(&ef), rc);
CU_ASSERT_EQUAL(rc, 0);
// Now reopen the file
opts.file.omode = IWFS_OREAD;
IWRC(iwfs_exfile_open(&ef, &opts), rc);
CU_ASSERT_EQUAL_FATAL(rc, 0);
char rdata[37];
// iwrc(*read)(struct IWFS_EXT* f, off_t off, void *buf, size_t siz, size_t
// *sp);
IWRC(ef.read(&ef, 1, rdata, sp, &sp2), rc);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL(sp, sp2);
CU_ASSERT_FALSE(strncmp(rdata, data, sizeof(data)));
rc = ef.write(&ef, 1, data, sizeof(data), &sp);
CU_ASSERT_EQUAL(IW_ERROR_READONLY, rc);
size_t ps = iwp_alloc_unit();
rc = 0;
IWRC(ef.read(&ef, ps - 1, rdata, 2, &sp2), rc);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL(sp2, 1);
IWRC(ef.close(&ef), rc);
CU_ASSERT_EQUAL(rc, 0);
}
void iwfs_exfile_test1_2() {
iwrc rc = 0;
IWFS_EXT f;
const char *path = "exfile_test1_2-"; // Temp file prefix
IWFS_EXT_OPTS opts = {
.file = {
.path = path,
.omode = IWFS_OTMP | IWFS_OUNLINK
}
};
rc = iwfs_exfile_open(&f, &opts);
CU_ASSERT_EQUAL_FATAL(rc, 0);
IWFS_EXT_STATE state;
rc = f.state(&f, &state);
CU_ASSERT_EQUAL_FATAL(rc, 0);
char *tpath = strdup(state.file.opts.path);
fprintf(stderr, "\nTmp file: %s\n", tpath);
IWP_FILE_STAT fstat;
rc = iwp_fstat(tpath, &fstat);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = f.close(&f);
CU_ASSERT_EQUAL_FATAL(rc, 0);
memset(&fstat, 0, sizeof(fstat));
rc = iwp_fstat(tpath, &fstat);
CU_ASSERT_EQUAL_FATAL(rc, IW_ERROR_NOT_EXISTS);
free(tpath);
}
void test_fibo_inc(void) {
const char *path = "test_fibo_inc.dat";
IWFS_EXT ef;
IWFS_EXT_OPTS opts = {
.file = {
.path = path,
.lock_mode = IWP_WLOCK,
.omode = IWFS_DEFAULT_OMODE | IWFS_OTRUNC
},
.use_locks = 0,
.rspolicy = iw_exfile_szpolicy_fibo
};
iwrc rc = 0;
size_t sp;
uint64_t wd = (uint64_t)(-1);
IWRC(iwfs_exfile_open(&ef, &opts), rc);
CU_ASSERT_EQUAL_FATAL(rc, 0);
// iwrc(*write)(struct IWFS_EXT* f, off_t off, const void *buf, size_t siz,
// size_t *sp);
IWRC(ef.write(&ef, 0, &wd, 1, &sp), rc);
CU_ASSERT_EQUAL_FATAL(rc, 0);
size_t psize = iwp_alloc_unit();
IWP_FILE_STAT fstat;
IWRC(iwp_fstat(path, &fstat), rc);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL_FATAL(fstat.size, psize);
IWRC(ef.write(&ef, fstat.size, &wd, 1, &sp), rc);
CU_ASSERT_EQUAL_FATAL(rc, 0);
IWRC(iwp_fstat(path, &fstat), rc);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL_FATAL(fstat.size, 2 * psize);
IWRC(ef.write(&ef, fstat.size, &wd, 1, &sp), rc);
CU_ASSERT_EQUAL_FATAL(rc, 0);
IWRC(iwp_fstat(path, &fstat), rc);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL_FATAL(fstat.size, 3 * psize);
IWRC(ef.write(&ef, fstat.size, &wd, 1, &sp), rc);
CU_ASSERT_EQUAL_FATAL(rc, 0);
IWRC(iwp_fstat(path, &fstat), rc);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL_FATAL(fstat.size, 5 * psize);
IWRC(ef.close(&ef), rc);
CU_ASSERT_EQUAL(rc, 0);
}
void test_mmap1(void) {
iwrc rc = 0;
size_t psize = iwp_alloc_unit();
size_t sp;
const int dsize = psize * 4;
uint8_t *data = malloc(dsize);
uint8_t *cdata = malloc(dsize);
const char *path = "test_mmap1.dat";
IWFS_EXT ef;
IWFS_EXT_OPTS opts = {.file = {.path = path, .omode = IWFS_OTRUNC}, .use_locks = 0};
for (int i = 0; i < dsize; ++i) {
data[i] = iwu_rand_range(256);
}
rc = iwfs_exfile_open(&ef, &opts);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = ef.add_mmap(&ef, 2 * psize, psize, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = ef.add_mmap(&ef, psize, psize, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = ef.add_mmap(&ef, 0, psize, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = ef.add_mmap(&ef, psize, 2 * psize, 0);
CU_ASSERT_EQUAL_FATAL(rc, IWFS_ERROR_MMAP_OVERLAP);
#ifndef IW_32
rc = ef.add_mmap(&ef, 3 * psize, UINT64_MAX, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
#else
rc = ef.add_mmap(&ef, 3 * psize, UINT32_MAX >> 1, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
#endif
rc = ef.write(&ef, psize / 2, data, psize, &sp);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL_FATAL(sp, psize);
rc = ef.read(&ef, psize / 2, cdata, psize, &sp);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL_FATAL(sp, psize);
CU_ASSERT_EQUAL_FATAL(memcmp(data, cdata, psize), 0);
for (int i = 0; i < dsize; ++i) {
data[i] = iwu_rand_range(256);
}
// iwrc(*remove_mmap)(struct IWFS_EXT* f, off_t off);
rc = ef.remove_mmap(&ef, psize);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = ef.write(&ef, psize / 2, data, psize, &sp);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL_FATAL(psize, sp);
rc = ef.read(&ef, psize / 2, cdata, psize, &sp);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL_FATAL(psize, sp);
CU_ASSERT_EQUAL_FATAL(memcmp(data, cdata, psize), 0);
for (int i = 0; i < 10; ++i) {
rc = ef.write(&ef, psize * i, data, dsize, &sp);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL_FATAL(dsize, sp);
rc = ef.read(&ef, psize * i, cdata, dsize, &sp);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL_FATAL(dsize, sp);
CU_ASSERT_EQUAL_FATAL(memcmp(data, cdata, psize), 0);
}
for (int i = 0; i < dsize; ++i) {
data[i] = iwu_rand_range(256);
}
rc = ef.remove_mmap(&ef, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
for (int i = 0; i < 10; ++i) {
rc = ef.write(&ef, psize * i, data, dsize, &sp);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL_FATAL(dsize, sp);
rc = ef.read(&ef, psize * i, cdata, dsize, &sp);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL_FATAL(dsize, sp);
CU_ASSERT_EQUAL_FATAL(memcmp(data, cdata, psize), 0);
}
for (int i = 0; i < dsize; ++i) {
data[i] = iwu_rand_range(256);
}
rc = ef.remove_mmap(&ef, 2 * psize);
CU_ASSERT_EQUAL_FATAL(rc, 0);
for (int i = 0; i < 10; ++i) {
rc = ef.write(&ef, psize * i, data, dsize, &sp);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL_FATAL(dsize, sp);
rc = ef.read(&ef, psize * i, cdata, dsize, &sp);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL_FATAL(dsize, sp);
CU_ASSERT_EQUAL_FATAL(memcmp(data, cdata, psize), 0);
}
for (int i = 0; i < dsize; ++i) {
data[i] = iwu_rand_range(256);
}
rc = ef.remove_mmap(&ef, 3 * psize);
CU_ASSERT_EQUAL_FATAL(rc, 0);
for (int i = 0; i < 10; ++i) {
rc = ef.write(&ef, psize * i, data, dsize, &sp);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL_FATAL(dsize, sp);
rc = ef.read(&ef, psize * i, cdata, dsize, &sp);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL_FATAL(dsize, sp);
CU_ASSERT_EQUAL_FATAL(memcmp(data, cdata, psize), 0);
}
IWRC(ef.close(&ef), rc);
CU_ASSERT_EQUAL(rc, 0);
free(data);
free(cdata);
}
int main() {
CU_pSuite pSuite = NULL;
/* Initialize the CUnit test registry */
if (CUE_SUCCESS != CU_initialize_registry()) return CU_get_error();
/* Add a suite to the registry */
pSuite = CU_add_suite("iwfs_test1", init_suite, clean_suite);
if (NULL == pSuite) {
CU_cleanup_registry();
return CU_get_error();
}
/* Add the tests to the suite */
if ((NULL == CU_add_test(pSuite, "iwfs_exfile_test1", iwfs_exfile_test1)) ||
(NULL == CU_add_test(pSuite, "iwfs_exfile_test1_2", iwfs_exfile_test1_2)) ||
(NULL == CU_add_test(pSuite, "test_fibo_inc", test_fibo_inc)) ||
(NULL == CU_add_test(pSuite, "test_mmap1", test_mmap1))) {
CU_cleanup_registry();
return CU_get_error();
}
/* Run all tests using the CUnit Basic interface */
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
int ret = CU_get_error() || CU_get_number_of_failures();
CU_cleanup_registry();
return ret;
}
+777
View File
@@ -0,0 +1,777 @@
//
/**************************************************************************************************
* IOWOW library
*
* MIT License
*
* Copyright (c) 2012-2020 Softmotions Ltd <info@softmotions.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*************************************************************************************************/
#include "iowow.h"
#include "log/iwlog.h"
#include "fs/iwfsmfile.h"
#include "utils/iwutils.h"
#include "platform/iwp.h"
#include "iwcfg.h"
#include <CUnit/Basic.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pthread.h>
static pthread_mutex_t records_mtx;
#define UNLINK() \
unlink("test_fsm_open_close.fsm"); \
unlink("test_fsm_uniform_alloc.fsm"); \
unlink("test_block_allocation1.fsm"); \
unlink("test_block_allocation2.fsm")
int init_suite(void) {
pthread_mutex_init(&records_mtx, 0);
int rc = iw_init();
UNLINK();
return rc;
}
int clean_suite(void) {
pthread_mutex_destroy(&records_mtx);
UNLINK();
return 0;
}
uint64_t iwfs_fsmdbg_number_of_free_areas(IWFS_FSM *f);
uint64_t iwfs_fsmdbg_find_next_set_bit(const uint64_t *addr,
uint64_t offset_bit,
uint64_t max_offset_bit,
int *found);
uint64_t iwfs_fsmdbg_find_prev_set_bit(const uint64_t *addr,
uint64_t offset_bit,
uint64_t min_offset_bit,
int *found);
void iwfs_fsmdbg_dump_fsm_tree(IWFS_FSM *f, const char *hdr);
iwrc iwfs_fsmdbg_state(IWFS_FSM *f, IWFS_FSMDBG_STATE *d);
iwrc iwfs_fsmdb_dump_fsm_bitmap(IWFS_FSM *f, int blimit);
void test_fsm_bitmap(void) {
#define BMSZ1 16
uint64_t buf[BMSZ1];
memset(buf, 0, BMSZ1 * sizeof(uint64_t));
int found = 0;
uint64_t val = IW_HTOILL(0x3UL); /* 0000011 */
uint64_t res = iwfs_fsmdbg_find_next_set_bit(&val, 0, sizeof(uint64_t) * 8, &found);
CU_ASSERT_EQUAL(found, 1);
CU_ASSERT_EQUAL(res, 0);
res = iwfs_fsmdbg_find_next_set_bit(&val, 1, sizeof(uint64_t) * 8, &found);
CU_ASSERT_EQUAL(found, 1);
CU_ASSERT_EQUAL(res, 1);
res = iwfs_fsmdbg_find_next_set_bit(&val, 2, sizeof(uint64_t) * 8, &found);
CU_ASSERT_EQUAL(found, 0);
CU_ASSERT_EQUAL(res, 0);
val = 0x3UL << 2; /* 0001100 */
val = IW_HTOILL(val);
res = iwfs_fsmdbg_find_next_set_bit(&val, 0, sizeof(uint64_t) * 8, &found);
CU_ASSERT_EQUAL(found, 1);
CU_ASSERT_EQUAL(res, 2);
val = 0x3UL << 2; /* 0001100 */
val = IW_HTOILL(val);
res = iwfs_fsmdbg_find_next_set_bit(&val, 2, sizeof(uint64_t) * 8, &found);
CU_ASSERT_EQUAL(found, 1);
CU_ASSERT_EQUAL(res, 2);
val = 0x3UL << 2; /* 0001100 */
val = IW_HTOILL(val);
res = iwfs_fsmdbg_find_next_set_bit(&val, 3, sizeof(uint64_t) * 8, &found);
CU_ASSERT_EQUAL(found, 1);
CU_ASSERT_EQUAL(res, 3);
val = 0x3UL << 2; /* 0001100 */
val = IW_HTOILL(val);
res = iwfs_fsmdbg_find_next_set_bit(&val, 4, sizeof(uint64_t) * 8, &found);
CU_ASSERT_EQUAL(found, 0);
CU_ASSERT_EQUAL(res, 0);
val = 0x3UL << 2; /* 0001100 */
val = IW_HTOILL(val);
res = iwfs_fsmdbg_find_prev_set_bit(&val, 2, 0, &found);
CU_ASSERT_EQUAL(found, 0);
CU_ASSERT_EQUAL(res, 0);
val = 0x3UL << 2; /* 0001100 */
val = IW_HTOILL(val);
res = iwfs_fsmdbg_find_prev_set_bit(&val, 3, 0, &found);
CU_ASSERT_EQUAL(found, 1);
CU_ASSERT_EQUAL(res, 2);
val = 0x2UL; /* 00000010 */
val = IW_HTOILL(val);
res = iwfs_fsmdbg_find_next_set_bit(&val, 0, sizeof(uint64_t) * 8, &found);
CU_ASSERT_EQUAL(found, 1);
CU_ASSERT_EQUAL(res, 1);
val = 0x2UL; /* 00000010 */
val = IW_HTOILL(val);
res = iwfs_fsmdbg_find_next_set_bit(&val, 1, sizeof(uint64_t) * 8, &found);
CU_ASSERT_EQUAL(found, 1);
CU_ASSERT_EQUAL(res, 1);
val = 0x4UL; /* 00000100 */
val = IW_HTOILL(val);
res = iwfs_fsmdbg_find_next_set_bit(&val, 0, sizeof(uint64_t) * 8, &found);
CU_ASSERT_EQUAL(found, 1);
CU_ASSERT_EQUAL(res, 2);
val = 0x4UL; /* 00000100 */
val = IW_HTOILL(val);
res = iwfs_fsmdbg_find_next_set_bit(&val, 1, sizeof(uint64_t) * 8, &found);
CU_ASSERT_EQUAL(found, 1);
CU_ASSERT_EQUAL(res, 2);
val = 0x4UL; /* 00000100 */
val = IW_HTOILL(val);
res = iwfs_fsmdbg_find_next_set_bit(&val, 2, sizeof(uint64_t) * 8, &found);
CU_ASSERT_EQUAL(found, 1);
CU_ASSERT_EQUAL(res, 2);
val = ~0UL;
val = IW_HTOILL(val);
res = iwfs_fsmdbg_find_prev_set_bit(&val, 0, 0, &found);
CU_ASSERT_EQUAL(found, 0);
CU_ASSERT_EQUAL(res, 0);
val = 0x1UL; /* 00000001 */
val = IW_HTOILL(val);
res = iwfs_fsmdbg_find_prev_set_bit(&val, 1, 0, &found);
CU_ASSERT_EQUAL(found, 1);
CU_ASSERT_EQUAL(res, 0);
val = 0x2UL; /* 00000010 */
val = IW_HTOILL(val);
res = iwfs_fsmdbg_find_prev_set_bit(&val, 10, 0, &found);
CU_ASSERT_EQUAL(found, 1);
CU_ASSERT_EQUAL(res, 1);
buf[0] = IW_HTOILL(0x1UL);
res = iwfs_fsmdbg_find_prev_set_bit(buf, sizeof(uint64_t) * 8 + 15, 0, &found);
CU_ASSERT_EQUAL(found, 1);
CU_ASSERT_EQUAL(res, 0);
buf[0] = IW_HTOILL(0x2UL);
res = iwfs_fsmdbg_find_prev_set_bit(buf, sizeof(uint64_t) * 8 + 15, 0, &found);
CU_ASSERT_EQUAL(found, 1);
CU_ASSERT_EQUAL(res, 1);
buf[0] = IW_HTOILL(0x4UL);
res = iwfs_fsmdbg_find_prev_set_bit(buf, sizeof(uint64_t) * 8 + 15, 0, &found);
CU_ASSERT_EQUAL(found, 1);
CU_ASSERT_EQUAL(res, 2);
buf[0] = IW_HTOILL(0x8UL);
res = iwfs_fsmdbg_find_prev_set_bit(buf, sizeof(uint64_t) * 8 + 15, 0, &found);
CU_ASSERT_EQUAL(found, 1);
CU_ASSERT_EQUAL(res, 3);
buf[1] = IW_HTOILL(0x2UL);
res = iwfs_fsmdbg_find_prev_set_bit(buf, 2 * sizeof(uint64_t) * 8 + 17, 0, &found);
CU_ASSERT_EQUAL(found, 1);
CU_ASSERT_EQUAL(res, 64 + 1);
/* 0[0100000000000..|00]000 */
buf[0] = IW_HTOILL(0x4UL);
buf[1] = IW_HTOILL(0x0UL);
buf[2] = IW_HTOILL(0x0UL);
res = iwfs_fsmdbg_find_prev_set_bit(buf, (sizeof(uint64_t) * 8 + 2), 0, &found);
CU_ASSERT_EQUAL(found, 1);
CU_ASSERT_EQUAL(res, 2);
buf[0] = IW_HTOILL(0x4UL);
buf[1] = IW_HTOILL(0x4UL);
buf[2] = IW_HTOILL(0x0UL);
res = iwfs_fsmdbg_find_prev_set_bit(buf, sizeof(uint64_t) * 8 + 5, 0, &found);
CU_ASSERT_EQUAL(found, 1);
CU_ASSERT_EQUAL(res, 64 + 2);
}
void test_fsm_open_close(void) {
iwrc rc;
IWFS_FSM_OPTS opts = {
.exfile = {
.file = {.path = "test_fsm_open_close.fsm", .lock_mode = IWP_WLOCK},
.rspolicy = iw_exfile_szpolicy_fibo,
.initial_size = 0
},
.bpow = 6,
.hdrlen = 64,
.oflags = IWFSM_STRICT
};
size_t aunit = iwp_alloc_unit();
IWFS_FSMDBG_STATE state1, state2;
IWFS_FSM fsm;
rc = iwfs_fsmfile_open(&fsm, &opts);
CU_ASSERT_FALSE_FATAL(rc);
rc = iwfs_fsmdbg_state(&fsm, &state1);
CU_ASSERT_FALSE(rc);
CU_ASSERT_TRUE((aunit * 8 - state1.lfbklen) * 64 == 2 * aunit); // allocated first 2 pages
rc = fsm.close(&fsm);
CU_ASSERT_FALSE_FATAL(rc);
rc = iwfs_fsmfile_open(&fsm, &opts);
CU_ASSERT_FALSE_FATAL(rc);
rc = iwfs_fsmdbg_state(&fsm, &state2);
CU_ASSERT_FALSE(rc);
CU_ASSERT_TRUE((aunit * 8 - state2.lfbklen) * 64 == 2 * aunit);
CU_ASSERT_EQUAL(state1.bmlen, state2.bmlen);
CU_ASSERT_EQUAL(state1.bmoff, state2.bmoff);
CU_ASSERT_EQUAL(state1.lfbklen, state2.lfbklen);
CU_ASSERT_EQUAL(state1.lfbkoff, state2.lfbkoff);
CU_ASSERT_EQUAL(state1.state.block_size, state2.state.block_size);
CU_ASSERT_EQUAL(state1.state.blocks_num, state2.state.blocks_num);
CU_ASSERT_EQUAL(state1.state.hdrlen, state2.state.hdrlen);
CU_ASSERT_EQUAL(state1.state.oflags, state2.state.oflags);
CU_ASSERT_EQUAL(state1.state.exfile.fsize, state2.state.exfile.fsize);
CU_ASSERT_EQUAL(state1.state.exfile.fsize, 2 * aunit);
rc = fsm.close(&fsm);
CU_ASSERT_FALSE_FATAL(rc);
}
void test_fsm_uniform_alloc_impl(int mmap_all);
void test_fsm_uniform_alloc(void) {
test_fsm_uniform_alloc_impl(0);
}
void test_fsm_uniform_alloc_mmap_all(void) {
test_fsm_uniform_alloc_impl(1);
}
void test_fsm_uniform_alloc_impl(int mmap_all) {
iwrc rc;
IWFS_FSMDBG_STATE state1, state2;
IWFS_FSM_OPTS opts = {
.exfile = {
.file = {
.path = "test_fsm_uniform_alloc.fsm",
.lock_mode = IWP_WLOCK,
.omode = IWFS_OTRUNC
},
.rspolicy = iw_exfile_szpolicy_fibo
},
.bpow = 6,
.hdrlen = 64,
.oflags = IWFSM_STRICT,
.mmap_all = mmap_all
};
typedef struct {
off_t addr;
off_t len;
} ASLOT;
const int bsize = 512;
#define bcnt 4096
ASLOT aslots[bcnt];
IWFS_FSM fsm;
rc = iwfs_fsmfile_open(&fsm, &opts);
CU_ASSERT_FALSE_FATAL(rc);
rc = iwfs_fsmdbg_state(&fsm, &state1);
CU_ASSERT_FALSE_FATAL(rc);
CU_ASSERT_EQUAL_FATAL(state1.state.exfile.file.ostatus, IWFS_OPEN_NEW);
for (int i = 0; i < bcnt; ++i) {
aslots[i].addr = 0;
rc = fsm.allocate(&fsm, bsize, &aslots[i].addr, &aslots[i].len, 0);
CU_ASSERT_FALSE_FATAL(rc);
}
rc = iwfs_fsmdbg_state(&fsm, &state1);
CU_ASSERT_FALSE_FATAL(rc);
if (iwp_alloc_unit() == 4096) { // todo check for system with different alloc units
CU_ASSERT_EQUAL(state1.bmlen, 8192);
CU_ASSERT_EQUAL(state1.bmoff, 2097152);
CU_ASSERT_EQUAL(state1.lfbklen, 32632);
CU_ASSERT_EQUAL(state1.lfbkoff, 32904);
CU_ASSERT_EQUAL(state1.state.blocks_num, 65536);
CU_ASSERT_EQUAL(state1.state.free_segments_num, 2);
CU_ASSERT_EQUAL(state1.state.avg_alloc_size, 8);
CU_ASSERT_EQUAL(state1.state.alloc_dispersion, 0);
}
rc = fsm.close(&fsm);
CU_ASSERT_FALSE_FATAL(rc);
opts.exfile.file.omode = IWFS_OREAD;
rc = iwfs_fsmfile_open(&fsm, &opts);
CU_ASSERT_FALSE_FATAL(rc);
rc = iwfs_fsmdbg_state(&fsm, &state2);
CU_ASSERT_FALSE_FATAL(rc);
CU_ASSERT_EQUAL_FATAL(state2.state.exfile.file.ostatus, IWFS_OPEN_EXISTING);
CU_ASSERT_FALSE(state2.state.exfile.file.opts.omode & IWFS_OWRITE);
CU_ASSERT_EQUAL(state1.bmlen, state2.bmlen);
CU_ASSERT_EQUAL(state1.bmoff, state2.bmoff);
CU_ASSERT_EQUAL(state1.lfbklen, state2.lfbklen);
CU_ASSERT_EQUAL(state1.lfbkoff, state2.lfbkoff);
CU_ASSERT_EQUAL(state1.state.blocks_num, state2.state.blocks_num);
CU_ASSERT_EQUAL(state1.state.free_segments_num, state2.state.free_segments_num);
CU_ASSERT_EQUAL(state1.state.avg_alloc_size, state2.state.avg_alloc_size);
CU_ASSERT_EQUAL(state1.state.alloc_dispersion, state2.state.alloc_dispersion);
uint32_t ibuf;
off_t ilen;
rc = fsm.allocate(&fsm, sizeof(ibuf), (void *) &ibuf, &ilen, 0);
CU_ASSERT_EQUAL(rc, IW_ERROR_READONLY);
rc = fsm.close(&fsm);
CU_ASSERT_FALSE_FATAL(rc);
opts.exfile.file.omode = IWFS_OWRITE;
rc = iwfs_fsmfile_open(&fsm, &opts);
CU_ASSERT_FALSE_FATAL(rc);
rc = iwfs_fsmdbg_state(&fsm, &state1);
CU_ASSERT_FALSE_FATAL(rc);
if (iwp_alloc_unit() == 4096) { // todo check for system with different alloc units
CU_ASSERT_EQUAL(state1.bmlen, 8192);
CU_ASSERT_EQUAL(state1.bmoff, 2097152);
CU_ASSERT_EQUAL(state1.lfbklen, 32632);
CU_ASSERT_EQUAL(state1.lfbkoff, 32904);
CU_ASSERT_EQUAL(state1.state.blocks_num, 65536);
CU_ASSERT_EQUAL(state1.state.free_segments_num, 2);
CU_ASSERT_EQUAL(state1.state.avg_alloc_size, 8);
CU_ASSERT_EQUAL(state1.state.alloc_dispersion, 0);
}
int i = 0;
for (; i < bcnt; ++i) {
rc = fsm.deallocate(&fsm, aslots[i].addr, aslots[i].len);
if (rc) {
iwlog_ecode_error3(rc);
}
CU_ASSERT_FALSE_FATAL(rc);
}
rc = fsm.close(&fsm);
CU_ASSERT_FALSE_FATAL(rc);
if (iwp_alloc_unit() == 4096) {
IWP_FILE_STAT st;
rc = iwp_fstat("test_fsm_uniform_alloc.fsm", &st);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL(st.size, iwp_alloc_unit() * 3);
}
}
typedef struct FSMREC {
int64_t offset;
int64_t length;
int locked;
struct FSMREC *prev;
struct FSMREC *next;
} FSMREC;
typedef struct {
int maxrecs;
int avgrecsz;
IWFS_FSM *fsm;
volatile int numrecs;
FSMREC *reclist;
FSMREC *head;
int blkpow;
} FSMRECTASK;
//!!!! TODO this test is not good for multithreaded env, refactoring needed
static void *recordsthr(void *op) {
FSMRECTASK *task = op;
iwrc rc;
FSMREC *rec, *tmp;
IWFS_FSM *fsm = task->fsm;
size_t sp;
const int maxrsize = IW_ROUNDUP(task->avgrecsz * 3, 1 << task->blkpow);
char *rdata = malloc(maxrsize);
char *rdata2 = malloc(maxrsize);
int numrec;
int a, i = 0;
pthread_mutex_lock(&records_mtx);
numrec = task->numrecs;
pthread_mutex_unlock(&records_mtx);
while (numrec < task->maxrecs) {
++i;
rec = malloc(sizeof(*rec));
memset(rec, 0, sizeof(*rec));
rec->locked = 1;
do {
rec->length = iwu_rand_dnorm((double) task->avgrecsz, task->avgrecsz / 3.0);
} while (rec->length <= 0 || rec->length > maxrsize);
/* Allocate record */
rc = fsm->allocate(fsm, rec->length, &rec->offset, &rec->length, 0);
if (rc) {
iwlog_ecode_error3(rc);
}
CU_ASSERT_FALSE_FATAL(rc);
memset(rdata, (rec->offset >> task->blkpow), maxrsize);
CU_ASSERT_TRUE_FATAL(maxrsize >= rec->length);
rc = fsm->write(fsm, rec->offset, rdata, rec->length, &sp);
if (rc) {
iwlog_ecode_error3(rc);
}
CU_ASSERT_FALSE_FATAL(rc);
CU_ASSERT_EQUAL_FATAL(rec->length, sp);
pthread_mutex_lock(&records_mtx);
if (task->reclist != rec) {
tmp = task->reclist;
task->reclist = rec;
task->reclist->prev = tmp;
tmp->next = task->reclist;
rec->locked = 0;
}
++(task->numrecs);
numrec = task->numrecs;
pthread_mutex_unlock(&records_mtx);
}
rec = task->reclist;
i = 0;
while (rec && rec->prev) {
++i;
a = rand() % 3;
if (a == 0 || a == 1) { /* realloc */
pthread_mutex_lock(&records_mtx);
if (rec->locked) {
rec = rec->next;
pthread_mutex_unlock(&records_mtx);
continue;
}
rec->locked = 1;
pthread_mutex_unlock(&records_mtx);
rc = fsm->deallocate(fsm, rec->offset, rec->length);
if (rc) {
iwlog_ecode_error3(rc);
}
CU_ASSERT_FALSE_FATAL(rc);
/* allocate */
do {
rec->length = iwu_rand_dnorm((double) task->avgrecsz, task->avgrecsz / 3.0);
} while (rec->length <= 0 || rec->length > maxrsize);
rc = fsm->allocate(fsm, rec->length, &rec->offset, &rec->length, 0);
if (rc) {
iwlog_ecode_error3(rc);
CU_ASSERT_FALSE(rc);
break;
}
if (rec->length <= maxrsize) {
/* Write a record */
memset(rdata, (rec->offset >> task->blkpow), maxrsize);
rc = fsm->write(fsm, rec->offset, rdata, rec->length, &sp);
if (rc) {
iwlog_ecode_error3(rc);
}
CU_ASSERT_FALSE_FATAL(rc);
} else {
/* printf("Ops %lld %lld\n\n", rl >> task->blkpow, rec->length >>
* task->blkpow); */
CU_ASSERT_TRUE_FATAL(0);
assert(0);
}
pthread_mutex_lock(&records_mtx);
rec->locked = 0;
pthread_mutex_unlock(&records_mtx);
} else {
// TODO
// rc = fsm->lread(fsm, rec->offset, rdata, rec->length, &sp);
// CU_ASSERT_FALSE_FATAL(rc);
// CU_ASSERT_EQUAL_FATAL(sp, rec->length);
// memset(rdata2, (rec->offset >> task->blkpow), maxrsize);
// int cmp = memcmp(rdata, rdata2, rec->length);
// CU_ASSERT_FALSE_FATAL(cmp);
}
rec = rec->prev;
}
free(rdata);
free(rdata2);
return 0;
}
void test_block_allocation_impl(int mmap_all, int nthreads, int numrec, int avgrecsz, int blkpow, const char *path) {
iwrc rc;
pthread_t *tlist = malloc(nthreads * sizeof(pthread_t));
IWFS_FSM_OPTS opts = {
.exfile = {
.file = {.path = path, .omode = IWFS_OTRUNC},
.rspolicy = iw_exfile_szpolicy_fibo
},
.bpow = blkpow,
.oflags = IWFSM_STRICT,
.mmap_all = mmap_all
};
FSMRECTASK task;
FSMREC *rec, *prev;
IWFS_FSM fsm;
rc = iwfs_fsmfile_open(&fsm, &opts);
CU_ASSERT_FALSE_FATAL(rc);
memset(&task, 0, sizeof(task));
task.numrecs = 0;
task.maxrecs = numrec;
task.avgrecsz = avgrecsz;
task.fsm = &fsm;
task.reclist = malloc(sizeof(*task.reclist));
memset(task.reclist, 0, sizeof(*task.reclist));
task.head = task.reclist;
task.blkpow = opts.bpow;
for (int i = 0; i < nthreads; ++i) {
CU_ASSERT_EQUAL_FATAL(pthread_create(&tlist[i], 0, recordsthr, &task), 0);
}
for (int i = 0; i < nthreads; ++i) {
pthread_join(tlist[i], 0);
}
/* Cleanup */
rec = task.reclist;
while (rec) {
prev = rec->prev;
free(rec);
rec = prev;
}
rc = fsm.close(&fsm);
CU_ASSERT_FALSE_FATAL(rc);
free(tlist);
}
void test_block_allocation1_impl(int mmap_all);
void test_block_allocation1(void) {
test_block_allocation1_impl(0);
}
void test_block_allocation1_mmap_all(void) {
test_block_allocation1_impl(1);
}
void test_block_allocation1_impl(int mmap_all) {
iwrc rc;
IWFS_FSM fsm;
int psize = iwp_alloc_unit();
IWFS_FSM_OPTS opts = {
.exfile = {
.file = {
.path = "test_block_allocation1.fsm",
.omode = IWFS_OTRUNC
}
},
.hdrlen = psize - 2 * 64,
.bpow = 6,
.oflags = IWFSM_STRICT,
.mmap_all = mmap_all
};
off_t oaddr = 0;
off_t olen;
// off_t sp, sp2;
int bsize = (1 << opts.bpow); /* byte block */
const int hoff = (2 * psize);
rc = iwfs_fsmfile_open(&fsm, &opts);
CU_ASSERT_FALSE_FATAL(rc);
/* Next alloc status:
xxxxxxx */
rc = fsm.allocate(&fsm, 3 * bsize, &oaddr, &olen, 0);
CU_ASSERT_FALSE_FATAL(rc);
CU_ASSERT_EQUAL(oaddr, hoff + 0);
CU_ASSERT_EQUAL(olen, 3 * bsize);
rc = fsm.allocate(&fsm, 4 * bsize, &oaddr, &olen, 0);
CU_ASSERT_FALSE_FATAL(rc);
CU_ASSERT_EQUAL(oaddr, hoff + 3 * bsize);
CU_ASSERT_EQUAL(olen, 4 * bsize);
rc = fsm.deallocate(&fsm, 1 * bsize, 1 * bsize);
CU_ASSERT_EQUAL(rc, IWFS_ERROR_FSM_SEGMENTATION);
/* Next alloc status:
x*xxxxx */
rc = fsm.deallocate(&fsm, hoff + 1 * bsize, 1 * bsize);
CU_ASSERT_FALSE_FATAL(rc);
/* Next alloc status:
xxxxxxx */
rc = fsm.allocate(&fsm, 1 * bsize, &oaddr, &olen, 0);
CU_ASSERT_FALSE_FATAL(rc);
CU_ASSERT_EQUAL(oaddr, hoff + 1 * bsize);
CU_ASSERT_EQUAL(olen, 1 * bsize);
/* Next alloc status:
x**xxxx */
rc = fsm.deallocate(&fsm, oaddr, 2 * bsize);
CU_ASSERT_FALSE_FATAL(rc);
/* Next alloc status:
x**x**x */
rc = fsm.deallocate(&fsm, hoff + 4 * bsize, 2 * bsize);
CU_ASSERT_FALSE_FATAL(rc);
oaddr = hoff + 5 * bsize; /* Test a free block location suggestion */
rc = fsm.allocate(&fsm, 2 * bsize, &oaddr, &olen, 0);
CU_ASSERT_FALSE_FATAL(rc);
CU_ASSERT_EQUAL(oaddr, hoff + 4 * bsize);
CU_ASSERT_EQUAL(olen, 2 * bsize);
/* Next alloc status:
x**x**x */
rc = fsm.deallocate(&fsm, hoff + 4 * bsize, 2 * bsize);
CU_ASSERT_FALSE_FATAL(rc);
/* Next alloc status:
x*****x */
CU_ASSERT_EQUAL(iwfs_fsmdbg_number_of_free_areas(&fsm), 3);
rc = fsm.deallocate(&fsm, hoff + 3 * bsize, 1 * bsize);
CU_ASSERT_FALSE_FATAL(rc);
CU_ASSERT_EQUAL(iwfs_fsmdbg_number_of_free_areas(&fsm), 2);
/* Next alloc status:
xxxxxxx */
oaddr = hoff;
rc = fsm.allocate(&fsm, 5 * bsize, &oaddr, &olen, 0);
CU_ASSERT_FALSE_FATAL(rc);
CU_ASSERT_EQUAL(oaddr, hoff + 1 * bsize);
CU_ASSERT_EQUAL(olen, 5 * bsize);
CU_ASSERT_EQUAL(iwfs_fsmdbg_number_of_free_areas(&fsm), 1);
// Test reallocate
/* Next alloc status:
*xxx*** */
rc = fsm.deallocate(&fsm, hoff + 4 * bsize, 3 * bsize);
CU_ASSERT_FALSE_FATAL(rc);
rc = fsm.deallocate(&fsm, hoff, 1 * bsize);
CU_ASSERT_FALSE_FATAL(rc);
CU_ASSERT_EQUAL(iwfs_fsmdbg_number_of_free_areas(&fsm), 2);
/* Next alloc status:
*xx**** */
oaddr = hoff + 1 * bsize;
olen = 3 * bsize;
rc = fsm.reallocate(&fsm, 2 * bsize, &oaddr, &olen, 0);
CU_ASSERT_FALSE_FATAL(rc);
CU_ASSERT_EQUAL(oaddr, hoff + 1 * bsize);
CU_ASSERT_EQUAL(olen, 2 * bsize);
CU_ASSERT_EQUAL(iwfs_fsmdbg_number_of_free_areas(&fsm), 2);
/* Next alloc status:
*xxxxxx */
// rc = fsm.reallocate(&fsm, 6 * bsize, &oaddr, &olen, 0);
// CU_ASSERT_FALSE_FATAL(rc);
// CU_ASSERT_EQUAL(oaddr, hoff + 1 * bsize);
// CU_ASSERT_EQUAL(olen, 6 * bsize);
//
// /* Next alloc status:
// *xx***x */
// rc = fsm.deallocate(&fsm, hoff + 3 * bsize, 3 * bsize);
// CU_ASSERT_FALSE_FATAL(rc);
// todo
// oaddr = hoff + 1 * bsize;
// olen = 1 * bsize;
// rc = fsm.reallocate(&fsm, 2 * bsize, &oaddr, &olen, 0);
// CU_ASSERT_EQUAL(oaddr, hoff);
// CU_ASSERT_EQUAL(olen, 2 * bsize);
rc = fsm.close(&fsm);
CU_ASSERT_FALSE_FATAL(rc);
}
void test_block_allocation2_impl(int mmap_all);
void test_block_allocation2() {
test_block_allocation2_impl(0);
}
void test_block_allocation2_mmap_all() {
test_block_allocation2_impl(1);
}
void test_block_allocation2_impl(int mmap_all) {
test_block_allocation_impl(mmap_all, 4, 50000, 493, 6, "test_block_allocation2.fsm");
test_block_allocation_impl(mmap_all, 4, 50000, 5, 6, "test_block_allocation2.fsm");
}
int main() {
CU_pSuite pSuite = NULL;
/* Initialize the CUnit test registry */
if (CUE_SUCCESS != CU_initialize_registry())
return CU_get_error();
/* Add a suite to the registry */
pSuite = CU_add_suite("iwfs_test2", init_suite, clean_suite);
if (NULL == pSuite) {
CU_cleanup_registry();
return CU_get_error();
}
/* Add the tests to the suite */
if ((NULL == CU_add_test(pSuite, "test_fsm_bitmap", test_fsm_bitmap)) ||
(NULL == CU_add_test(pSuite, "test_fsm_open_close", test_fsm_open_close)) ||
(NULL == CU_add_test(pSuite, "test_fsm_uniform_alloc", test_fsm_uniform_alloc)) ||
(NULL == CU_add_test(pSuite, "test_fsm_uniform_alloc_mmap_all", test_fsm_uniform_alloc_mmap_all)) ||
(NULL == CU_add_test(pSuite, "test_block_allocation1", test_block_allocation1)) ||
(NULL == CU_add_test(pSuite, "test_block_allocation1_mmap_all", test_block_allocation1_mmap_all)) ||
(NULL == CU_add_test(pSuite, "test_block_allocation2", test_block_allocation2)) ||
NULL == CU_add_test(pSuite, "test_block_allocation2_mmap_all", test_block_allocation2_mmap_all)
) {
CU_cleanup_registry();
return CU_get_error();
}
/* Run all tests using the CUnit Basic interface */
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
int ret = CU_get_error() || CU_get_number_of_failures();
CU_cleanup_registry();
return ret;
}
+263
View File
@@ -0,0 +1,263 @@
#include "iowow.h"
#include "log/iwlog.h"
#include "fs/iwfsmfile.h"
#include "utils/iwutils.h"
#include "iwcfg.h"
#include <CUnit/Basic.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "utils/kbtree.h"
#define NRECS 10000
#define RECSZ (10*1024)
#define UNLINK() \
unlink("test_fsm_stress.data"); \
unlink("test_fsm_stress1.fsm"); \
unlink("test_fsm_stress2.fsm")
typedef struct SREC {
int id;
off_t addr;
off_t rsz;
off_t alc_addr;
off_t alc_len;
bool freed;
bool reallocated;
} SREC;
#define _srec_cmp(r1, r2) ((r1).id - (r2).id)
KBTREE_INIT(rt, SREC, _srec_cmp)
FILE *fstress1;
kbtree_t(rt) *rt;
int init_suite(void) {
UNLINK();
int rc = iw_init();
RCRET(rc);
rt = kb_init(rt, KB_DEFAULT_SIZE);
off_t addr = 0;
uint64_t ts;
rc = iwp_current_time_ms(&ts, false);
RCRET(rc);
ts = IW_SWAB64(ts);
ts >>= 32;
iwu_rand_seed(ts);
printf("Generating stress data file: test_fsm_stress1.data, random seed: %" PRIu64, ts);
fstress1 = fopen("test_fsm_stress.data", "w+");
char *buf = malloc(RECSZ + 1);
for (int i = 0, j; i < NRECS; ++i) {
int rsz = iwu_rand_range(RECSZ + 1);
if (rsz < 1) {
rsz = 1;
}
for (j = 0; j < rsz; ++j) {
buf[j] = ' ' + iwu_rand_range(95);
}
buf[j] = '\0';
fprintf(fstress1, "%08d:%s\n", i, buf);
SREC rec = {
.id = i,
.addr = addr,
.rsz = rsz,
.freed = false
};
addr += (8 + 1 + rsz + 1);
kb_putp(rt, rt, &rec);
}
free(buf);
return rc;
}
int clean_suite(void) {
if (fstress1) {
fclose(fstress1);
fstress1 = 0;
}
kb_destroy(rt, rt);
UNLINK();
return 0;
}
void test_stress(char *path, int bpow, bool mmap_all) {
IWFS_FSM fsm;
IWFS_FSM_OPTS opts = {
.exfile = {
.file = {
.path = path,
.omode = IWFS_OTRUNC
}
},
.hdrlen = 62,
.bpow = bpow,
.oflags = IWFSM_STRICT,
.mmap_all = mmap_all
};
iwrc rc = iwfs_fsmfile_open(&fsm, &opts);
CU_ASSERT_FALSE_FATAL(rc);
fprintf(stderr, "\nRunning allocations...\n");
char *buf = malloc(2 * RECSZ + 1);
for (int i = 0; i < NRECS; ++i) {
size_t sp;
SREC k = {.id = i};
iwfs_fsm_aflags aflags = IWFSM_SOLID_ALLOCATED_SPACE | IWFSM_ALLOC_NO_OVERALLOCATE;
uint32_t rop = iwu_rand_u32();
if (i > 0 && (!(rop % 3) || !(rop % 5))) {
k.id = iwu_rand_range(i);
SREC *pr = kb_getp(rt, rt, &k);
CU_ASSERT_PTR_NOT_NULL_FATAL(pr);
if (!pr->freed) {
if ((rop % 3)) { // deallocate previous
//fprintf(stderr, "%05d D %ld:%ld\n", pr->id, pr->alc_addr, pr->alc_len);
pr->freed = true;
rc = fsm.deallocate(&fsm, pr->alc_addr, pr->alc_len);
CU_ASSERT_FALSE_FATAL(rc);
} else if (!pr->reallocated && !(rop % 5)) { // reallocate previous
//fprintf(stderr, "%05d R %ld:%ld\n", pr->id, pr->alc_addr, pr->alc_len);
pr->reallocated = true;
uint32_t nlen = iwu_rand_range(2 * pr->rsz + 1);
if (nlen < 1) {
nlen = 1;
}
rc = fsm.reallocate(&fsm, nlen, &pr->alc_addr, &pr->alc_len, IWFSM_SOLID_ALLOCATED_SPACE);
CU_ASSERT_FALSE_FATAL(rc);
if (pr->alc_len > pr->rsz) {
rc = fsm.read(&fsm, pr->alc_addr, buf, pr->rsz, &sp);
CU_ASSERT_FALSE_FATAL(rc);
CU_ASSERT_EQUAL_FATAL(pr->rsz, sp);
off_t wsz = pr->alc_len - pr->rsz;
while (wsz > 0) {
int wc = MIN(wsz, pr->rsz);
rc = fsm.write(&fsm, pr->alc_addr + pr->alc_len - wsz, buf, wc, &sp);
CU_ASSERT_FALSE_FATAL(rc);
CU_ASSERT_EQUAL_FATAL(wc, sp);
wsz -= wc;
}
}
}
}
}
k.id = i;
SREC *r = kb_getp(rt, rt, &k);
CU_ASSERT_PTR_NOT_NULL_FATAL(r);
fseek(fstress1, r->addr + 8 + 1, SEEK_SET);
fread(buf, r->rsz, 1, fstress1);
buf[r->rsz + 1] = '\0';
rc = fsm.allocate(&fsm, r->rsz, &r->alc_addr, &r->alc_len, aflags);
//fprintf(stderr, "%05d A %ld:%ld\n", i, r->alc_addr, r->alc_len);
CU_ASSERT_FALSE_FATAL(rc);
CU_ASSERT_TRUE_FATAL(r->alc_len >= r->rsz);
rc = fsm.write(&fsm, r->alc_addr, buf, r->rsz, &sp);
CU_ASSERT_FALSE_FATAL(rc);
CU_ASSERT_EQUAL_FATAL(sp, r->rsz);
if (r->alc_len > r->rsz) {
off_t wsz = r->alc_len - r->rsz;
while (wsz > 0) {
int wc = MIN(wsz, r->rsz);
rc = fsm.write(&fsm, r->alc_addr + r->alc_len - wsz, buf, wc, &sp);
CU_ASSERT_FALSE_FATAL(rc);
CU_ASSERT_EQUAL_FATAL(wc, sp);
wsz -= wc;
}
}
}
CU_ASSERT_FALSE_FATAL(fsm.close(&fsm));
fprintf(stderr, "Checking data\n");
opts.exfile.file.omode = 0;
rc = iwfs_fsmfile_open(&fsm, &opts);
CU_ASSERT_FALSE_FATAL(rc);
char *buf2 = malloc(2 * RECSZ + 1);
for (int i = 0; i < NRECS; ++i) {
size_t sp;
SREC k = {.id = i};
SREC *r = kb_getp(rt, rt, &k);
CU_ASSERT_PTR_NOT_NULL_FATAL(r);
if (r->freed) {
continue;
}
CU_ASSERT_TRUE(r->alc_len <= 2 * RECSZ + 1);
fseek(fstress1, r->addr + 8 + 1, SEEK_SET);
fread(buf, r->rsz, 1, fstress1);
buf[r->rsz + 1] = '\0';
off_t rn = MIN(r->rsz, r->alc_len);
if (r->alc_len < r->rsz) {
CU_ASSERT_TRUE_FATAL(r->reallocated);
}
memset(buf2, 0, rn); // 20736
rc = fsm.read(&fsm, r->alc_addr, buf2, rn, &sp);
CU_ASSERT_FALSE_FATAL(rc);
CU_ASSERT_EQUAL_FATAL(rn, sp);
int ri = memcmp(buf, buf2, rn);
CU_ASSERT_EQUAL_FATAL(ri, 0);
if (rn < r->alc_len) {
while (rn < r->alc_len) {
off_t rz = MIN(r->alc_len - rn, r->rsz);
rc = fsm.read(&fsm, r->alc_addr + rn, buf2, rz, &sp);
CU_ASSERT_FALSE_FATAL(rc);
ri = memcmp(buf, buf2, rz);
CU_ASSERT_EQUAL_FATAL(ri, 0);
rn += rz;
}
}
}
free(buf2);
free(buf);
CU_ASSERT_FALSE_FATAL(fsm.close(&fsm));
}
static void test_stress1() {
test_stress("test_fsm_stress1.fsm", 6, true);
}
static void test_stress2() {
test_stress("test_fsm_stress2.fsm", 6, false);
}
int main() {
CU_pSuite pSuite = NULL;
/* Initialize the CUnit test registry */
if (CUE_SUCCESS != CU_initialize_registry())
return CU_get_error();
/* Add a suite to the registry */
pSuite = CU_add_suite("iwfs_test3", init_suite, clean_suite);
if (NULL == pSuite) {
CU_cleanup_registry();
return CU_get_error();
}
/* Add the tests to the suite */
if (
(NULL == CU_add_test(pSuite, "test_stress1", test_stress1)) ||
(NULL == CU_add_test(pSuite, "test_stress2", test_stress2))
) {
CU_cleanup_registry();
return CU_get_error();
}
/* Run all tests using the CUnit Basic interface */
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
int ret = CU_get_error() || CU_get_number_of_failures();
CU_cleanup_registry();
return ret;
}
+87
View File
@@ -0,0 +1,87 @@
//
/**************************************************************************************************
* IOWOW library
*
* MIT License
*
* Copyright (c) 2012-2020 Softmotions Ltd <info@softmotions.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*************************************************************************************************/
#include "iwcfg.h"
#include "log/iwlog.h"
#include "iwutils.h"
#include "iwp.h"
// Hardcoded requirements (fixme)
// CMakeLists.txt defines: -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64
static_assert(sizeof(off_t) == 8, "sizeof(off_t) == 8 bytes");
iwrc iwfs_init(void);
iwrc iwkv_init(void);
iwrc iw_init(void) {
iwrc rc;
static int _iw_initialized = 0;
if (!__sync_bool_compare_and_swap(&_iw_initialized, 0, 1)) {
return 0; // initialized already
}
rc = iwlog_init();
RCGO(rc, finish);
rc = iwu_init();
RCGO(rc, finish);
rc = iwp_init();
RCGO(rc, finish);
uint64_t ts;
rc = iwp_current_time_ms(&ts, false);
RCRET(rc);
ts = IW_SWAB64(ts);
ts >>= 32;
iwu_rand_seed(ts);
rc = iwfs_init();
RCGO(rc, finish);
rc = iwkv_init();
RCGO(rc, finish);
finish:
return rc;
}
const char *iowow_version_full(void) {
return IOWOW_VERSION;
}
unsigned int iowow_version_major(void) {
return IOWOW_VERSION_MAJOR;
}
unsigned int iowow_version_minor(void) {
return IOWOW_VERSION_MINOR;
}
unsigned int iowow_version_patch(void) {
return IOWOW_VERSION_PATCH;
}
+50
View File
@@ -0,0 +1,50 @@
#pragma once
#ifndef IOWOW_H
#define IOWOW_H
/**************************************************************************************************
* IOWOW library
*
* MIT License
*
* Copyright (c) 2012-2020 Softmotions Ltd <info@softmotions.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*************************************************************************************************/
#include "basedefs.h"
IW_EXTERN_C_START
/**
* @brief Init iowow subsystem.
* @return `0` on success or error code.
*/
IW_EXPORT WUR iwrc iw_init(void);
IW_EXPORT const char* iowow_version_full(void);
IW_EXPORT unsigned int iowow_version_major(void);
IW_EXPORT unsigned int iowow_version_minor(void);
IW_EXPORT unsigned int iowow_version_patch(void);
IW_EXTERN_C_END
#endif
+68
View File
@@ -0,0 +1,68 @@
#pragma once
#ifndef IW_CFG_H
#define IW_CFG_H
//
/**************************************************************************************************
* IOWOW library
*
* MIT License
*
* Copyright (c) 2012-2020 Softmotions Ltd <info@softmotions.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*************************************************************************************************/
#include "basedefs.h"
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#include <stddef.h>
#include <stdint.h>
#include <inttypes.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#ifndef MAXPATHLEN
#ifdef PATH_MAX
#define MAXPATHLEN PATH_MAX
#else
#define MAXPATHLEN 4096
#endif
#endif
#if !defined(IW_32) && !defined(IW_64)
#error Unknown CPU bits
#endif
#define IOWOW_VERSION "1.4.10"
#define IOWOW_VERSION_MAJOR 1
#define IOWOW_VERSION_MINOR 4
#define IOWOW_VERSION_PATCH 10
#ifndef static_assert
#define static_assert _Static_assert
#endif
#endif
+2
View File
@@ -0,0 +1,2 @@
[flake8]
ignore = F401,E501
+1
View File
@@ -0,0 +1 @@
+188
View File
@@ -0,0 +1,188 @@
include(ExternalProject)
include(ProcessorCount)
ProcessorCount(PROCESSOR_COUNT_VAL)
# IWKV benchmark
add_executable(iwkv_benchmark iwkv_benchmark.c)
target_link_libraries(iwkv_benchmark iowow_s)
set_target_properties(iwkv_benchmark PROPERTIES COMPILE_FLAGS "-DIW_STATIC")
enable_language(CXX)
### LevelDB
set(LEVELDB_SOURCE_DIR "${CMAKE_BINARY_DIR}/src/extern_leveldb")
set(LEVELDB_BINARY_DIR "${LEVELDB_SOURCE_DIR}")
ExternalProject_Add(
extern_leveldb
GIT_REPOSITORY https://github.com/google/leveldb.git
GIT_TAG v1.20
PREFIX ${CMAKE_BINARY_DIR}
BUILD_IN_SOURCE ON
GIT_PROGRESS ON
UPDATE_DISCONNECTED ON
BUILD_COMMAND make -j${PROCESSOR_COUNT_VAL}
CONFIGURE_COMMAND ""
INSTALL_COMMAND ""
LOG_DOWNLOAD ON
LOG_BUILD ON
BUILD_BYPRODUCTS "${LEVELDB_BINARY_DIR}/out-static/libleveldb.a"
)
add_library(libleveldb STATIC IMPORTED)
set_target_properties(
libleveldb
PROPERTIES
IMPORTED_LOCATION "${LEVELDB_BINARY_DIR}/out-static/libleveldb.a"
IMPORTED_LINK_INTERFACE_LANGUAGES CXX
)
add_dependencies(libleveldb extern_leveldb)
include_directories(AFTER "${LEVELDB_SOURCE_DIR}/include")
### !LevelDB
# LevelDB benchmark
add_executable(leveldb_benchmark leveldb_benchmark.c)
target_link_libraries(leveldb_benchmark libleveldb iowow_s)
set_target_properties(leveldb_benchmark
PROPERTIES COMPILE_FLAGS "-DIW_STATIC"
)
# LMDB
set(LMDB_SOURCE_DIR "${CMAKE_BINARY_DIR}/src/extern_lmdb")
set(LMDB_BINARY_DIR "${LMDB_SOURCE_DIR}")
ExternalProject_Add(
extern_lmdb
GIT_REPOSITORY https://github.com/LMDB/lmdb.git
GIT_TAG mdb.master
PREFIX ${CMAKE_BINARY_DIR}
BUILD_IN_SOURCE ON
GIT_PROGRESS ON
UPDATE_DISCONNECTED ON
BUILD_COMMAND make -C libraries/liblmdb
CONFIGURE_COMMAND ""
INSTALL_COMMAND ""
LOG_DOWNLOAD ON
LOG_BUILD ON
BUILD_BYPRODUCTS "${LMDB_BINARY_DIR}/libraries/liblmdb/liblmdb.a"
)
add_library(liblmdb STATIC IMPORTED)
set_target_properties(
liblmdb
PROPERTIES
IMPORTED_LOCATION "${LMDB_BINARY_DIR}/libraries/liblmdb/liblmdb.a"
)
add_dependencies(liblmdb extern_lmdb)
include_directories(AFTER "${LMDB_SOURCE_DIR}/libraries/liblmdb")
# LMDB benchmark
add_executable(lmdb_benchmark lmdb_benchmark.c)
target_link_libraries(lmdb_benchmark liblmdb iowow_s)
set_target_properties(lmdb_benchmark
PROPERTIES COMPILE_FLAGS "-DIW_STATIC"
)
# KyotoCabinet
set(KYC_SOURCE_DIR "${CMAKE_BINARY_DIR}/src/extern_kyc")
set(KYC_BINARY_DIR "${KYC_SOURCE_DIR}")
ExternalProject_Add(
extern_kyc
URL https://fallabs.com/kyotocabinet/pkg/kyotocabinet-1.2.77.tar.gz
PREFIX ${CMAKE_BINARY_DIR}
BUILD_IN_SOURCE ON
UPDATE_DISCONNECTED ON
BUILD_COMMAND make
CONFIGURE_COMMAND ./configure --disable-zlib --prefix=${CMAKE_BINARY_DIR}/src/extern_kyc/install
INSTALL_COMMAND make install
LOG_DOWNLOAD ON
LOG_BUILD OFF
LOG_CONFIGURE OFF
BUILD_BYPRODUCTS "${KYC_BINARY_DIR}/install/lib/libkyotocabinet.a"
)
add_library(libkyotocabinet STATIC IMPORTED)
set_target_properties(
libkyotocabinet
PROPERTIES
IMPORTED_LOCATION "${KYC_BINARY_DIR}/install/lib/libkyotocabinet.a"
IMPORTED_LINK_INTERFACE_LANGUAGES CXX
)
add_dependencies(libkyotocabinet extern_kyc)
include_directories(AFTER "${KYC_BINARY_DIR}/install/include")
add_executable(kyc_benchmark kyc_benchmark.c)
target_link_libraries(kyc_benchmark libkyotocabinet iowow_s)
set_target_properties(kyc_benchmark
PROPERTIES COMPILE_FLAGS "-DIW_STATIC"
)
# TokyoCabinet
set(TC_SOURCE_DIR "${CMAKE_BINARY_DIR}/src/extern_tc")
set(TC_BINARY_DIR "${TC_SOURCE_DIR}")
ExternalProject_Add(
extern_tc
URL https://fallabs.com/tokyocabinet/tokyocabinet-1.4.48.tar.gz
PREFIX ${CMAKE_BINARY_DIR}
BUILD_IN_SOURCE ON
UPDATE_DISCONNECTED ON
BUILD_COMMAND make
CONFIGURE_COMMAND ./configure --disable-bzip --disable-exlzo --disable-exlzma --disable-zlib --prefix=${CMAKE_BINARY_DIR}/src/extern_tc/install
INSTALL_COMMAND make install
LOG_DOWNLOAD ON
LOG_BUILD OFF
LOG_CONFIGURE OFF
BUILD_BYPRODUCTS "${TC_BINARY_DIR}/install/lib/libtokyocabinet.a"
)
add_library(libtokyocabinet STATIC IMPORTED)
set_target_properties(
libtokyocabinet
PROPERTIES
IMPORTED_LOCATION "${TC_BINARY_DIR}/install/lib/libtokyocabinet.a"
IMPORTED_LINK_INTERFACE_LANGUAGES C
)
add_dependencies(libtokyocabinet extern_tc)
include_directories(AFTER "${TC_BINARY_DIR}/install/include")
add_executable(tc_benchmark tc_benchmark.c)
target_link_libraries(tc_benchmark libtokyocabinet iowow_s)
set_target_properties(tc_benchmark
PROPERTIES COMPILE_FLAGS "-DIW_STATIC"
)
# Wiredtiger
set(WT_SOURCE_DIR "${CMAKE_BINARY_DIR}/src/extern_wt")
set(WT_BINARY_DIR "${WT_SOURCE_DIR}")
ExternalProject_Add(
extern_wt
GIT_REPOSITORY https://github.com/wiredtiger/wiredtiger.git
PREFIX ${WT_BINARY_DIR}
BUILD_IN_SOURCE ON
UPDATE_DISCONNECTED ON
CONFIGURE_COMMAND sh -c "test -f ${WT_BINARY_DIR}/install/include/wiredtiger.h || (./autogen.sh && ./configure --prefix=${WT_BINARY_DIR}/install)"
BUILD_COMMAND ""
INSTALL_COMMAND sh -c "test -f ${WT_BINARY_DIR}/install/include/wiredtiger.h || make install"
LOG_DOWNLOAD ON
LOG_BUILD OFF
LOG_CONFIGURE OFF
BUILD_BYPRODUCTS "${WT_BINARY_DIR}/install/lib/libwiredtiger.a"
)
add_library(libwiredtiger STATIC IMPORTED)
set_target_properties(
libwiredtiger
PROPERTIES
IMPORTED_LOCATION "${WT_BINARY_DIR}/install/lib/libwiredtiger.a"
IMPORTED_LINK_INTERFACE_LANGUAGES C
)
add_dependencies(libwiredtiger extern_wt)
include_directories(AFTER "${WT_BINARY_DIR}/install/include")
add_executable(wiredtiger_benchmark wiredtiger_benchmark.c)
target_link_libraries(wiredtiger_benchmark libwiredtiger iowow_s "-ldl")
set_target_properties(wiredtiger_benchmark
PROPERTIES COMPILE_FLAGS "-DIW_STATIC"
)
# BDB 5.3
find_library(BDB_LIBRARY NAMES db)
if (BDB_LIBRARY)
add_executable(bdb_benchmark bdb_benchmark.c)
target_link_libraries(bdb_benchmark db iowow_s)
endif()
+5
View File
@@ -0,0 +1,5 @@
```
pip3 install -U bokeh parse selenium --user
yarn global add phantomjs-prebuilt
```
+206
View File
@@ -0,0 +1,206 @@
#include "bmbase.c"
#include <db.h>
#define DEFAULT_DB "bdb_bench.db"
typedef struct BM_BDB {
DB *dbp;
} BM_BDB;
static void env_setup() {
fprintf(stderr, " engine: %s\n", DB_VERSION_STRING);
}
static uint64_t db_size_bytes(BMCTX *ctx) {
const char *path = bm.param_db ? bm.param_db : DEFAULT_DB;
IWP_FILE_STAT fst;
iwrc rc = iwp_fstat(path, &fst);
if (rc) {
iwlog_ecode_error3(rc);
return 0;
}
return fst.size;
}
static void val_free(void *data) {
free(data);
}
static void *db_open(BMCTX *ctx) {
if (ctx->db) {
return 0; // db is not closed properly
}
const char *path = bm.param_db ? bm.param_db : DEFAULT_DB;
BM_BDB *bmdb = malloc(sizeof(*bmdb));
int ret = db_create(&bmdb->dbp, 0, 0);
if (ret) {
fprintf(stderr, "db_create: %s\n", db_strerror(ret));
free(bmdb);
return 0;
}
int32_t mode = DB_CREATE;
if (ctx->freshdb) {
mode |= DB_TRUNCATE;
}
ret = bmdb->dbp->open(bmdb->dbp, 0, path, 0, DB_BTREE, mode, 0664);
if (ret) {
fprintf(stderr, "db_open: %s\n", db_strerror(ret));
free(bmdb);
return 0;
}
return bmdb;
}
static bool db_close(BMCTX *ctx) {
if (!ctx->db) {
return false;
}
BM_BDB *bmdb = ctx->db;
int ret = bmdb->dbp->close(bmdb->dbp, 0);
if (ret) {
fprintf(stderr, "db_close: %s\n", db_strerror(ret));
return false;
}
free(bmdb);
return true;
}
static bool db_put(BMCTX *ctx, const IWKV_val *key, const IWKV_val *val, bool sync) {
BM_BDB *bmdb = ctx->db;
DBT bkey = {.data = key->data, .size = key->size};
DBT bval = {.data = val->data, .size = val->size};
int ret = bmdb->dbp->put(bmdb->dbp, 0, &bkey, &bval, 0);
if (ret) {
fprintf(stderr, "db_put: %s\n", db_strerror(ret));
return false;
}
if (sync) {
ret = bmdb->dbp->sync(bmdb->dbp, 0);
if (ret) {
fprintf(stderr, "db_sync: %s\n", db_strerror(ret));
return false;
}
}
return true;
}
static bool db_get(BMCTX *ctx, const IWKV_val *key, IWKV_val *val, bool *found) {
BM_BDB *bmdb = ctx->db;
DBT bkey = {.data = key->data, .size = key->size};
DBT bval = {.flags = DB_DBT_MALLOC};
int ret = bmdb->dbp->get(bmdb->dbp, 0, &bkey, &bval, 0);
val->data = bval.data;
val->size = bval.size;
if (ret == DB_NOTFOUND) {
*found = false;
ret = 0;
} else if (ret) {
*found = false;
fprintf(stderr, "db_get: %s\n", db_strerror(ret));
} else {
*found = true;
}
return ret == 0;
}
static bool db_del(BMCTX *ctx, const IWKV_val *key, bool sync) {
BM_BDB *bmdb = ctx->db;
DBT bkey = {.data = key->data, .size = key->size};
int ret = bmdb->dbp->del(bmdb->dbp, 0, &bkey, 0);
if (ret == DB_NOTFOUND) {
ret = 0;
} else if (ret) {
fprintf(stderr, "db_del: %s\n", db_strerror(ret));
return false;
}
if (sync) {
ret = bmdb->dbp->sync(bmdb->dbp, 0);
if (ret) {
fprintf(stderr, "db_del: %s\n", db_strerror(ret));
return false;
}
}
return true;
}
static bool db_read_seq(BMCTX *ctx, bool reverse) {
BM_BDB *bmdb = ctx->db;
DBC *curp;
DBT bkey = {.flags = DB_DBT_MALLOC};
DBT bval = {.flags = DB_DBT_MALLOC};
int ret = bmdb->dbp->cursor(bmdb->dbp, 0, &curp, 0);
if (ret) {
fprintf(stderr, "db_read_seq: %s\n", db_strerror(ret));
return false;
}
ret = curp->get(curp, &bkey, &bval, reverse ? DB_LAST : DB_FIRST);
if (ret == DB_NOTFOUND) {
ret = 0;
}
if (bkey.data) free(bkey.data);
if (bval.data) free(bval.data);
for (int i = 0; i < bm.param_num - 1 && !ret; ++i) {
bkey.data = 0;
bval.data = 0;
ret = curp->get(curp, &bkey, &bval, reverse ? DB_PREV : DB_NEXT);
if (ret == DB_NOTFOUND) {
ret = 0;
break;
} else if (ret) {
fprintf(stderr, "db_read_seq: %s\n", db_strerror(ret));
}
if (bkey.data) free(bkey.data);
if (bval.data) free(bval.data);
}
curp->close(curp);
return ret == 0;
}
static bool db_cursor_to_key(BMCTX *ctx, const IWKV_val *key, IWKV_val *val, bool *found) {
BM_BDB *bmdb = ctx->db;
DBC *curp;
DBT bkey = {.data = key->data, .size = key->size};
DBT bval = {.flags = DB_DBT_MALLOC};
int ret = bmdb->dbp->cursor(bmdb->dbp, 0, &curp, 0);
if (ret) {
fprintf(stderr, "db_cursor_to_key: %s\n", db_strerror(ret));
return false;
}
ret = curp->get(curp, &bkey, &bval, DB_SET);
if (ret == DB_NOTFOUND) {
*found = false;
ret = 0;
} else if (ret) {
*found = false;
fprintf(stderr, "db_cursor_to_key: %s\n", db_strerror(ret));
} else {
*found = true;
val->data = bval.data;
val->size = bval.size;
}
curp->close(curp);
return ret == 0;
}
int main(int argc, char **argv) {
if (argc < 1) return -1;
g_program = argv[0];
bm.env_setup = env_setup;
bm.db_size_bytes = db_size_bytes;
bm.val_free = val_free;
bm.db_open = db_open;
bm.db_close = db_close;
bm.db_put = db_put;
bm.db_get = db_get;
bm.db_del = db_del;
bm.db_read_seq = db_read_seq;
bm.db_cursor_to_key = db_cursor_to_key;
if (!bm_bench_run(argc, argv)) {
return 1;
}
return 0;
}
File diff suppressed because one or more lines are too long
+642
View File
@@ -0,0 +1,642 @@
#include "iwkv.h"
#include "iwutils.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
char *g_program;
uint32_t _execsize();
typedef struct _BMCTX BMCTX;
typedef bool (bench_method(BMCTX *bmctx));
#define RND_DATA_SZ (10*1048576)
char RND_DATA[RND_DATA_SZ];
struct BM {
bool initiated;
int ksz;
int argc;
char **argv;
char *param_db;
int param_num;
int param_num_reads;
int param_value_size;
uint32_t param_seed;
char *param_benchmarks;
void (*val_free)(void *ptr);
void (*env_setup)(void);
void *(*db_open)(BMCTX *ctx);
bool (*db_close)(BMCTX *ctx);
bool (*db_put)(BMCTX *ctx, const IWKV_val *key, const IWKV_val *val, bool sync);
bool (*db_get)(BMCTX *ctx, const IWKV_val *key, IWKV_val *val, bool *found);
bool (*db_cursor_to_key)(BMCTX *ctx, const IWKV_val *key, IWKV_val *val, bool *found);
bool (*db_del)(BMCTX *ctx, const IWKV_val *key, bool sync);
bool (*db_read_seq)(BMCTX *ctx, bool reverse);
uint64_t (*db_size_bytes)(BMCTX *ctx);
} bm = {0};
struct _BMCTX {
bool success;
bool freshdb;
bool logdbsize;
char *name;
int num;
int value_size;
uint64_t start_ms;
uint64_t end_ms;
void *db;
void *extra;
bench_method *method;
int rnd_data_pos;
};
static void _val_dispose(IWKV_val *val) {
if (bm.val_free) {
if (val->data) {
bm.val_free(val->data);
val->size = 0;
}
} else {
iwkv_val_dispose(val);
}
}
static void _bmctx_dispose(BMCTX *ctx) {
free(ctx->name);
free(ctx);
}
static const char *_bmctx_rndbuf_nextptr(BMCTX *ctx, int len) {
if (len > RND_DATA_SZ) {
fprintf(stderr, "record value length exceeds maximum allowed: %d\n", RND_DATA_SZ);
exit(1);
}
if (ctx->rnd_data_pos + len > RND_DATA_SZ) {
ctx->rnd_data_pos = 0;
}
const char *ret = RND_DATA + ctx->rnd_data_pos;
ctx->rnd_data_pos += len;
return ret;
}
static bool _bm_check() {
if (!bm.env_setup) {
fprintf(stderr, "env_setup function is not set\n");
return false;
}
if (!bm.db_open) {
fprintf(stderr, "db_open function is not set\n");
return false;
}
if (!bm.db_close) {
fprintf(stderr, "db_close function is not set\n");
return false;
}
if (!bm.db_put) {
fprintf(stderr, "db_put function is not set\n");
return false;
}
if (!bm.db_get) {
fprintf(stderr, "db_get function is not set\n");
return false;
}
if (!bm.db_del) {
fprintf(stderr, "db_del function is not set\n");
return false;
}
if (!bm.db_read_seq) {
fprintf(stderr, "db_read_seq function is not set\n");
return false;
}
if (!bm.db_cursor_to_key) {
fprintf(stderr, "db_cursor_to_key function is not set\n");
return false;
}
return true;
}
static void _bm_help() {
fprintf(stderr, "\n");
fprintf(stderr, "Usage %s [options]\n\n", g_program);
fprintf(stderr, "Options:\n");
fprintf(stderr, " -h Show this help\n");
fprintf(stderr, " -w Write Ahead Log (WAL) enabled\n");
fprintf(stderr, " -n <num> Number of stored records\n");
fprintf(stderr,
" -r <num> Number of records to read (equals to number of stored records if not specified, not for readseq,readreverse)\n");
fprintf(stderr, " -vz <size> Size of a single record value in bytes\n");
fprintf(stderr, " -kz <16|192|1024> Size of record key. Either 16 (default) or 192 or 1024 bytes\n");
fprintf(stderr, " -b <comma separated benchmarks to run>\n\n");
fprintf(stderr, " -db <file/dir> Database file/directory\n\n");
fprintf(stderr, " -rs <random seed> Random seed used for iwu random generator\n\n");
fprintf(stderr, "Available benchmarks:\n");
fprintf(stderr, " fillseq write N fixed length values in sequential key order\n");
fprintf(stderr, " fillseq2 write N random length values in sequential key order\n");
fprintf(stderr, " fillrandom write N fixed length values in random key order\n");
fprintf(stderr, " fillrandom2 write N random length values in random key order\n");
fprintf(stderr, " overwrite overwrite N values in random key order\n");
fprintf(stderr, " fillsync write N/100 values in random key order in sync mode\n");
fprintf(stderr, " fill100K write N/100 100K values in random order\n");
fprintf(stderr, " deleteseq delete N keys in sequential order\n");
fprintf(stderr, " deleterandom delete N keys in random order\n");
fprintf(stderr, " readseq read all records sequentially\n");
fprintf(stderr, " readreverse read all records sequentially in reverse order\n");
fprintf(stderr, " readrandom read N times in random order\n");
fprintf(stderr, " readmissing read N missing keys in random order\n");
fprintf(stderr, " readhot read N times in random order from 1%% section of DB\n");
fprintf(stderr, " seekrandom N random seeks\n");
fprintf(stderr, "\n");
}
static bool _bm_init(int argc, char *argv[]) {
if (bm.initiated) {
fprintf(stderr, "Benchmark already initialized\n");
return false;
}
if (iw_init()) {
return false;
}
bm.argc = argc;
bm.argv = argv;
bm.param_num = 2000000; // 2M records
bm.param_num_reads = -1; // Same as param_num
bm.param_value_size = 400;
bm.param_benchmarks = "fillrandom2,"
"readrandom,"
"deleterandom,"
"fillseq2,"
"readrandom,"
"deleteseq,"
"fillseq,"
"overwrite,"
"readrandom,"
"readseq,"
"readreverse,"
"readhot,"
"readmissing,"
"deleteseq,"
"fill100K";
#ifndef NDEBUG
fprintf(stderr, "WARNING: Assertions are enabled, benchmarks can be slow\n");
#endif
for (int i = 1; i < argc; ++i) {
if (!strcmp(argv[i], "-h")) {
_bm_help();
return false;
}
if (!strcmp(argv[i], "-n")) {
if (++i >= argc) {
fprintf(stderr, "'-n <num records>' option has no value\n");
return false;
}
bm.param_num = atoi(argv[i]);
if (bm.param_num < 1) {
fprintf(stderr, "'-n <num records>' invalid option value\n");
return false;
}
} else if (!strcmp(argv[i], "-r")) {
if (++i >= argc) {
fprintf(stderr, "'-r <num read records>' option has no value\n");
return false;
}
bm.param_num_reads = atoi(argv[i]);
} else if (!strcmp(argv[i], "-vz")) {
if (++i >= argc) {
fprintf(stderr, "'-vz <value size>' option has not value\n");
return false;
}
bm.param_value_size = atoi(argv[i]);
if (bm.param_value_size <= 0) {
fprintf(stderr, "'-vz <value size>' invalid option value\n");
return false;
}
} else if (!strcmp(argv[i], "-b")) {
if (++i >= argc) {
fprintf(stderr, "'-b <benchmarks>' options has no value\n");
return false;
}
bm.param_benchmarks = argv[i];
} else if (!strcmp(argv[i], "-db")) {
if (++i >= argc) {
fprintf(stderr, "'-db <db file>' options has no value\n");
return false;
}
bm.param_db = argv[i];
} else if (!strcmp(argv[i], "-rs")) {
if (++i >= argc) {
fprintf(stderr, "'-rs <random seed>' options has no value\n");
return false;
}
bm.param_seed = atoll(argv[i]);
} else if (!strcmp(argv[i], "-kz")) {
if (++i >= argc) {
fprintf(stderr, "'-kz 16|192|1024' options has no value\n");
return false;
}
int ksz = atoi(argv[i]);
if (ksz == 192) {
bm.ksz = 192;
} else if (ksz == 1024) {
bm.ksz = 1024;
} else if (ksz != 16) {
fprintf(stderr, "'-kz 16|192|1024' options has invalid value %d\n", ksz);
return false;
}
}
}
if (bm.ksz == 0) {
bm.ksz = 16;
}
if (bm.param_num_reads < 0) {
bm.param_num_reads = bm.param_num;
}
if (!_bm_check()) {
fprintf(stderr, "Benchmark `bm` structure is not configured properly\n");
return false;
}
if (!bm.param_seed) {
uint64_t ts;
iwp_current_time_ms(&ts, false);
ts = IW_SWAB64(ts);
ts >>= 32;
bm.param_seed = ts;
}
iwu_rand_seed(bm.param_seed);
srandom(bm.param_seed);
fprintf(stderr,
"\n exec size: %u"
"\n random seed: %u"
"\n num records: %d\n read num records: %d\n value size: %d\n benchmarks: %s"
"\n key size: %d \n\n",
_execsize(),
bm.param_seed, bm.param_num, bm.param_num_reads, bm.param_value_size, bm.param_benchmarks,
bm.ksz);
// Fill up random data array
for (int i = 0; i < RND_DATA_SZ; ++i) {
RND_DATA[i] = ' ' + iwu_rand_range(95); // ascii space ... ~
}
return true;
}
static void _logdbsize(BMCTX *ctx) {
if (bm.db_size_bytes) {
uint64_t dbz = bm.db_size_bytes(ctx);
fprintf(stderr, " db size: %lu (%lu MB)\n", dbz, (dbz / 1024 / 1024));
}
}
uint32_t _execsize() {
const char *path = g_program;
IWP_FILE_STAT fst;
iwrc rc = iwp_fstat(path, &fst);
if (rc) {
iwlog_ecode_error3(rc);
return 0;
}
return fst.size;
}
static void _bm_run(BMCTX *ctx) {
assert(ctx->method);
uint64_t llv;
ctx->db = bm.db_open(ctx);
if (!ctx->db) {
ctx->success = false;
return;
}
iwp_current_time_ms(&llv, false);
ctx->start_ms = llv;
ctx->success = ctx->method(ctx);
if (!bm.db_close(ctx)) {
ctx->success = false;
}
iwp_current_time_ms(&llv, false);
ctx->end_ms = llv;
}
#define FILLKEY() snprintf(key.data, sizeof(kbuf), bm.ksz == 16 ? "%016d" : bm.ksz == 192 ? "%0192d" : "%01024d", k)
static bool _do_write(BMCTX *ctx, bool seq, bool sync, bool rvlen) {
char kbuf[1025];
IWKV_val key, val;
key.data = kbuf;
int value_size = ctx->value_size;
for (int i = 0; i < ctx->num; ++i) {
if (rvlen) {
value_size = iwu_rand_range(ctx->value_size + 1);
if (value_size == 0) {
value_size = 1;
}
}
const int k = seq ? i : iwu_rand_range(bm.param_num);
FILLKEY();
key.size = strlen(key.data);
val.data = (void *) _bmctx_rndbuf_nextptr(ctx, value_size);
val.size = value_size;
if (!bm.db_put(ctx, &key, &val, sync)) {
return false;
}
}
return true;
}
static bool _do_delete(BMCTX *ctx, bool sync, bool seq) {
char kbuf[1025];
IWKV_val key;
key.data = kbuf;
for (int i = 0; i < ctx->num; ++i) {
const int k = seq ? i : iwu_rand_range(bm.param_num);
FILLKEY();
key.size = strlen(key.data);
if (!bm.db_del(ctx, &key, sync)) {
return false;
}
}
return true;
}
static bool _do_read_seq(BMCTX *ctx) {
return bm.db_read_seq(ctx, false);
}
static bool _do_read_reverse(BMCTX *ctx) {
return bm.db_read_seq(ctx, true);
}
static bool _do_read_random(BMCTX *ctx) {
char kbuf[1025];
IWKV_val key, val;
bool found;
key.data = kbuf;
for (int i = 0; i < bm.param_num_reads; ++i) {
const int k = iwu_rand_range(bm.param_num);
FILLKEY();
key.size = strlen(key.data);
val.data = 0;
val.size = 0;
if (!bm.db_get(ctx, &key, &val, &found)) {
_val_dispose(&val);
return false;
}
_val_dispose(&val);
}
return true;
}
static bool _do_read_missing(BMCTX *ctx) {
char kbuf[1025];
IWKV_val key, val;
bool found;
key.data = kbuf;
for (int i = 0; i < bm.param_num_reads; ++i) {
const int k = iwu_rand_range(bm.param_num);
snprintf(key.data, sizeof(kbuf),
bm.ksz == 16 ? "%016d." : bm.ksz == 192 ? "%0192d." : "%01024d.", k);
key.size = strlen(key.data);
val.data = 0;
val.size = 0;
if (!bm.db_get(ctx, &key, &val, &found)) {
_val_dispose(&val);
return false;
}
_val_dispose(&val);
if (found) {
return false;
}
}
return true;
}
static bool _do_read_hot(BMCTX *ctx) {
char kbuf[1025];
IWKV_val key, val;
bool found;
key.data = kbuf;
const int range = (bm.param_num + 99) / 100;
for (int i = 0; i < bm.param_num_reads; ++i) {
const int k = iwu_rand_range(range);
FILLKEY();
key.size = strlen(key.data);
val.data = 0;
val.size = 0;
if (!bm.db_get(ctx, &key, &val, &found)) {
_val_dispose(&val);
return false;
}
_val_dispose(&val);
}
return true;
}
static bool _do_seek_random(BMCTX *ctx) {
char kbuf[1025];
IWKV_val key, val;
bool found;
key.data = kbuf;
for (int i = 0; i < bm.param_num_reads; ++i) {
const int k = iwu_rand_range(bm.param_num);
FILLKEY();
key.size = strlen(key.data);
val.data = 0;
val.size = 0;
if (!bm.db_cursor_to_key(ctx, &key, &val, &found)) {
_val_dispose(&val);
return false;
}
_val_dispose(&val);
}
return true;
}
static bool _bm_fillseq(BMCTX *ctx) {
if (!ctx->freshdb) return false;
return _do_write(ctx, true, false, false);
}
static bool _bm_fillseq2(BMCTX *ctx) {
if (!ctx->freshdb) return false;
return _do_write(ctx, true, false, true);
}
static bool _bm_fillrandom(BMCTX *ctx) {
if (!ctx->freshdb) return false;
return _do_write(ctx, false, false, false);
}
static bool _bm_fillrandom2(BMCTX *ctx) {
if (!ctx->freshdb) return false;
return _do_write(ctx, false, false, true);
}
static bool _bm_overwrite(BMCTX *ctx) {
if (ctx->freshdb) return false;
return _do_write(ctx, false, false, false);
}
static bool _bm_fillsync(BMCTX *ctx) {
if (!ctx->freshdb) return false;
ctx->num /= 100;
if (ctx->num < 1) ctx->num = 1;
fprintf(stderr, "\tfillsync num records: %d\n", ctx->num);
return _do_write(ctx, false, true, false);
}
static bool _bm_fill100K(BMCTX *ctx) {
if (!ctx->freshdb) return false;
ctx->num /= 100;
if (ctx->num < 1) ctx->num = 1;
fprintf(stderr, "\tfill100K num records: %d\n", ctx->num);
ctx->value_size = 100 * 1000;
return _do_write(ctx, false, false, false);
}
static bool _bm_deleteseq(BMCTX *ctx) {
if (ctx->freshdb) return false;
return _do_delete(ctx, false, true);
}
static bool _bm_deleterandom(BMCTX *ctx) {
if (ctx->freshdb) return false;
return _do_delete(ctx, false, false);
}
static bool _bm_readseq(BMCTX *ctx) {
if (ctx->freshdb) return false;
return _do_read_seq(ctx);
}
static bool _bm_readreverse(BMCTX *ctx) {
if (ctx->freshdb) return false;
return _do_read_reverse(ctx);
}
static bool _bm_readrandom(BMCTX *ctx) {
if (ctx->freshdb) return false;
return _do_read_random(ctx);
}
static bool _bm_readmissing(BMCTX *ctx) {
if (ctx->freshdb) return false;
return _do_read_missing(ctx);
}
static bool _bm_readhot(BMCTX *ctx) {
if (ctx->freshdb) return false;
return _do_read_hot(ctx);
}
static bool _bm_seekrandom(BMCTX *ctx) {
if (ctx->freshdb) return false;
return _do_seek_random(ctx);
}
static BMCTX *_bmctx_create(const char *name) {
bench_method *method = 0;
bool logdbsize = false;
bool freshdb = false;
if (!strcmp(name, "fillseq")) {
freshdb = true;
logdbsize = true;
method = _bm_fillseq;
} else if (!strcmp(name, "fillseq2")) {
freshdb = true;
logdbsize = true;
method = _bm_fillseq2;
} else if (!strcmp(name, "fillrandom")) {
freshdb = true;
logdbsize = true;
method = _bm_fillrandom;
} else if (!strcmp(name, "fillrandom2")) {
freshdb = true;
logdbsize = true;
method = _bm_fillrandom2;
} else if (!strcmp(name, "overwrite")) {
logdbsize = true;
method = _bm_overwrite;
} else if (!strcmp(name, "fillsync")) {
freshdb = true;
logdbsize = true;
method = _bm_fillsync;
} else if (!strcmp(name, "fill100K")) {
freshdb = true;
logdbsize = true;
method = _bm_fill100K;
} else if (!strcmp(name, "deleteseq")) {
logdbsize = true;
method = _bm_deleteseq;
} else if (!strcmp(name, "deleterandom")) {
logdbsize = true;
method = _bm_deleterandom;
} else if (!strcmp(name, "readseq")) {
method = _bm_readseq;
} else if (!strcmp(name, "readreverse")) {
method = _bm_readreverse;
} else if (!strcmp(name, "readrandom")) {
method = _bm_readrandom;
} else if (!strcmp(name, "readmissing")) {
method = _bm_readmissing;
} else if (!strcmp(name, "readhot")) {
method = _bm_readhot;
} else if (!strcmp(name, "seekrandom")) {
method = _bm_seekrandom;
} else {
fprintf(stderr, "Unknown benchmark: '%s'\n", name);
return 0;
}
BMCTX *bmctx = calloc(1, sizeof(*bmctx));
bmctx->name = strdup(name);
bmctx->method = method;
bmctx->num = bm.param_num;
bmctx->value_size = bm.param_value_size;
bmctx->freshdb = freshdb;
bmctx->logdbsize = logdbsize;
return bmctx;
}
static bool bm_bench_run(int argc, char *argv[]) {
if (!_bm_init(argc, argv)) {
fprintf(stderr, "Benchmark cannot be initialized\n");
exit(1);
}
bm.env_setup();
int c = 0;
const char *ptr = bm.param_benchmarks;
char bname[100];
bool bmres = true;
while (bmres) {
if (*ptr == ',' || *ptr == '\0' || c >= 99) {
bname[c] = '\0';
BMCTX *ctx = _bmctx_create(bname);
c = 0;
if (ctx) {
fprintf(stderr, " benchmark: %s\n", bname);
_bm_run(ctx);
bmres = ctx->success;
if (!bmres) {
fprintf(stderr, "Failed to run benchmark: %s\n", bname);
} else {
fprintf(stderr, " done: %s in %lu\n", bname, (ctx->end_ms - ctx->start_ms));
}
if (ctx->logdbsize) {
_logdbsize(ctx);
}
_bmctx_dispose(ctx);
}
if (*ptr == '\0' || !bmres) {
break;
}
} else if (!isspace(*ptr)) {
bname[c++] = *ptr;
}
ptr += 1;
}
return bmres;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

+185
View File
@@ -0,0 +1,185 @@
#include "bmbase.c"
#include "iowow.h"
#define DEFAULT_DB "iwkv_bench.db"
typedef struct BM_IWKVDB {
IWKV iwkv;
IWDB db;
} BM_IWKVDB;
static void env_setup() {
iwrc rc = iw_init();
if (rc) {
iwlog_ecode_error2(rc, "Failed to init iwkv: iwkv_init()");
exit(1);
}
fprintf(stderr, " engine: IWKV %s\n", iowow_version_full());
}
static uint64_t db_size_bytes(BMCTX *ctx) {
const char *path = bm.param_db ? bm.param_db : DEFAULT_DB;
IWP_FILE_STAT fst;
iwrc rc = iwp_fstat(path, &fst);
if (rc) {
iwlog_ecode_error3(rc);
return 0;
}
return fst.size;
}
static void *db_open(BMCTX *ctx) {
if (ctx->db) {
return 0; // db is not closed properly
}
bool wal_enabled = false;
for (int i = 0; i < bm.argc; ++i) {
if (!strcmp(bm.argv[i], "-w")) {
wal_enabled = true;
}
}
IWKV_OPTS opts = {
.wal = {
.enabled = wal_enabled,
.check_crc_on_checkpoint = false,
.savepoint_timeout_sec = 10, // 10 sec
.checkpoint_timeout_sec = 300, // 5 min
.wal_buffer_sz = 8 * 1024 * 1024, // 8M
.checkpoint_buffer_sz = 500ULL * 1024 * 1024 // 500MB
}
};
opts.path = bm.param_db ? bm.param_db : DEFAULT_DB;
if (ctx->freshdb) {
opts.oflags = IWKV_TRUNC;
}
BM_IWKVDB *bmdb = malloc(sizeof(*bmdb));
iwrc rc = iwkv_open(&opts, &bmdb->iwkv);
if (rc) {
iwlog_ecode_error2(rc, "Failed to open iwkv file");
return 0;
}
rc = iwkv_db(bmdb->iwkv, 1, 0, &bmdb->db);
if (rc) {
iwlog_ecode_error2(rc, "Failed to open iwkv db: 1");
return 0;
}
return bmdb;
}
static bool db_close(BMCTX *ctx) {
if (!ctx->db) {
return false;
}
BM_IWKVDB *bmdb = ctx->db;
iwrc rc = iwkv_close(&bmdb->iwkv);
if (rc) {
iwlog_ecode_error2(rc, "db_close");
return false;
}
free(bmdb);
return true;
}
static bool db_put(BMCTX *ctx, const IWKV_val *key, const IWKV_val *val, bool sync) {
BM_IWKVDB *bmdb = ctx->db;
iwrc rc = iwkv_put(bmdb->db, key, val, sync ? IWKV_SYNC : 0);
if (rc) {
iwlog_ecode_error2(rc, "db_put");
return false;
}
return true;
}
static bool db_get(BMCTX *ctx, const IWKV_val *key, IWKV_val *val, bool *found) {
BM_IWKVDB *bmdb = ctx->db;
*found = true;
iwrc rc = iwkv_get(bmdb->db, key, val);
if (rc == IWKV_ERROR_NOTFOUND) {
*found = false;
rc = 0;
}
if (rc) {
iwlog_ecode_error2(rc, "db_get");
return false;
}
return true;
}
static bool db_del(BMCTX *ctx, const IWKV_val *key, bool sync) {
BM_IWKVDB *bmdb = ctx->db;
iwrc rc = iwkv_del(bmdb->db, key, sync ? IWKV_SYNC : 0);
if (rc == IWKV_ERROR_NOTFOUND) {
rc = 0;
}
if (rc) {
iwlog_ecode_error2(rc, "db_del");
return false;
}
return true;
}
static bool db_read_seq(BMCTX *ctx, bool reverse) {
BM_IWKVDB *bmdb = ctx->db;
bool ret = true;
IWKV_cursor cur;
iwrc rc = iwkv_cursor_open(bmdb->db, &cur,
(reverse ? IWKV_CURSOR_AFTER_LAST : IWKV_CURSOR_BEFORE_FIRST), 0);
if (rc) {
iwlog_ecode_error2(rc, "db_read_seq::iwkv_cursor_open failed");
return false;
}
for (int i = 0; i < bm.param_num && !rc; ++i) {
rc = iwkv_cursor_to(cur, reverse ? IWKV_CURSOR_PREV : IWKV_CURSOR_NEXT);
}
iwkv_cursor_close(&cur);
if (rc == IWKV_ERROR_NOTFOUND) {
rc = 0;
}
if (rc) {
ret = false;
iwlog_ecode_error2(rc, "db_read_seq");
}
return ret;
}
static bool db_cursor_to_key(BMCTX *ctx, const IWKV_val *key, IWKV_val *val, bool *found) {
BM_IWKVDB *bmdb = ctx->db;
bool ret = true;
IWKV_cursor cur;
*found = true;
iwrc rc = iwkv_cursor_open(bmdb->db, &cur, IWKV_CURSOR_EQ, key);
if (!rc) {
rc = iwkv_cursor_val(cur, val);
if (rc) {
ret = false;
iwlog_ecode_error2(rc, "db_cursor_to_key::iwkv_cursor_val failed");
}
iwkv_cursor_close(&cur);
} else if (rc == IWKV_ERROR_NOTFOUND) {
*found = false;
iwkv_cursor_close(&cur);
} else {
iwlog_ecode_error2(rc, "db_cursor_to_key::iwkv_cursor_open failed");
ret = false;
}
return ret;
}
int main(int argc, char *argv[]) {
if (argc < 1) return -1;
g_program = argv[0];
bm.env_setup = env_setup;
bm.db_size_bytes = db_size_bytes;
bm.db_open = db_open;
bm.db_close = db_close;
bm.db_put = db_put;
bm.db_get = db_get;
bm.db_del = db_del;
bm.db_read_seq = db_read_seq;
bm.db_cursor_to_key = db_cursor_to_key;
if (!bm_bench_run(argc, argv)) {
return 1;
}
return 0;
}
+182
View File
@@ -0,0 +1,182 @@
#include "bmbase.c"
#include <kclangc.h>
#define DEFAULT_DB "kyc_bench.kct"
typedef struct BM_KYC {
KCDB *db;
} BM_KYC;
static void env_setup() {
fprintf(stderr, " engine: KyotoCabinet %s\n", KCVERSION);
}
uint64_t db_size_bytes(BMCTX *ctx) {
const char *path = bm.param_db ? bm.param_db : DEFAULT_DB;
IWP_FILE_STAT fst;
iwrc rc = iwp_fstat(path, &fst);
if (rc) {
iwlog_ecode_error3(rc);
return 0;
}
return fst.size;
}
static void *db_open(BMCTX *ctx) {
if (ctx->db) {
return 0; // db is not closed properly
}
bool wal_enabled = false;
for (int i = 0; i < bm.argc; ++i) {
if (!strcmp(bm.argv[i], "-w")) {
wal_enabled = true;
}
}
const char *path = bm.param_db ? bm.param_db : DEFAULT_DB;
BM_KYC *bmdb = malloc(sizeof(*bmdb));
bmdb->db = kcdbnew();
uint32_t mode = KCOWRITER | KCOCREATE;
if (ctx->freshdb) {
mode |= KCOTRUNCATE;
}
if (wal_enabled) {
mode |= KCOAUTOTRAN;
}
if (!kcdbopen(bmdb->db, path, mode)) {
kcdbdel(bmdb->db);
free(bmdb);
return 0;
}
return bmdb;
}
static bool db_close(BMCTX *ctx) {
if (!ctx->db) {
return false;
}
BM_KYC *bmdb = ctx->db;
int32_t rc = kcdbclose(bmdb->db);
if (!rc) {
fprintf(stderr, "db_close: %s\n", kcdbemsg(bmdb->db));
return false;
}
kcdbdel(bmdb->db);
free(bmdb);
return true;
}
static bool db_put(BMCTX *ctx, const IWKV_val *key, const IWKV_val *val, bool sync) {
BM_KYC *bmdb = ctx->db;
int32_t rc = kcdbset(bmdb->db, key->data, key->size, val->data, val->size);
if (!rc) {
fprintf(stderr, "db_put: %s\n", kcdbemsg(bmdb->db));
return false;
}
if (sync) {
rc = kcdbsync(bmdb->db, true, 0, 0);
if (!rc) {
fprintf(stderr, "db_put:kcdbsync: %s\n", kcdbemsg(bmdb->db));
return false;
}
}
return true;
}
static bool db_get(BMCTX *ctx, const IWKV_val *key, IWKV_val *val, bool *found) {
BM_KYC *bmdb = ctx->db;
size_t sp = 0;
char *vbuf = kcdbget(bmdb->db, key->data, key->size, &sp);
val->data = vbuf;
val->size = sp;
*found = (val->data != 0);
return true;
}
static bool db_del(BMCTX *ctx, const IWKV_val *key, bool sync) {
BM_KYC *bmdb = ctx->db;
kcdbremove(bmdb->db, key->data, key->size);
if (sync) {
int32_t rc = kcdbsync(bmdb->db, true, 0, 0);
if (!rc) {
fprintf(stderr, "db_del:kcdbsync: %s\n", kcdbemsg(bmdb->db));
return false;
}
}
return true;
}
static bool db_read_seq(BMCTX *ctx, bool reverse) {
int32_t rc = true;
BM_KYC *bmdb = ctx->db;
KCCUR *cur = kcdbcursor(bmdb->db);
if (!cur) {
return false;
}
if (reverse) {
rc = kccurjumpback(cur);
} else {
rc = kccurjump(cur);
}
if (!rc) {
if (kcdbecode(bmdb->db) == KCENOREC) {
kccurdel(cur);
return true;
}
}
if (!rc) {
fprintf(stderr, "db_read_seq: %s\n", kcdbemsg(bmdb->db));
kccurdel(cur);
return false;
}
for (int i = 0; i < bm.param_num && rc; ++i) {
if (reverse) {
rc = kccurstepback(cur);
} else {
rc = kccurstep(cur);
}
}
if (kcdbecode(bmdb->db) != KCENOREC) {
fprintf(stderr, "db_read_seq: %s\n", kcdbemsg(bmdb->db));
}
kccurdel(cur);
return true;
}
static bool db_cursor_to_key(BMCTX *ctx, const IWKV_val *key, IWKV_val *val, bool *found) {
int32_t rc = true;
BM_KYC *bmdb = ctx->db;
KCCUR *cur = kcdbcursor(bmdb->db);
*found = false;
rc = kccurjumpkey(cur, key->data, key->size);
if (rc) {
*found = true;
}
if (!rc && kcdbecode(bmdb->db) != KCENOREC) {
fprintf(stderr, "db_cursor_to_key: %s\n", kcdbemsg(bmdb->db));
kccurdel(cur);
return false;
}
val->data = kccurgetvalue(cur, &val->size, 0);
kccurdel(cur);
return true;
}
int main(int argc, char **argv) {
if (argc < 1) return -1;
g_program = argv[0];
bm.env_setup = env_setup;
bm.db_size_bytes = db_size_bytes;
bm.val_free = kcfree;
bm.db_open = db_open;
bm.db_close = db_close;
bm.db_put = db_put;
bm.db_get = db_get;
bm.db_del = db_del;
bm.db_read_seq = db_read_seq;
bm.db_cursor_to_key = db_cursor_to_key;
if (!bm_bench_run(argc, argv)) {
return 1;
}
return 0;
}
+198
View File
@@ -0,0 +1,198 @@
#include "bmbase.c"
#include <dirent.h>
#include <leveldb/c.h>
#define DEFAULT_DB "leveldb_bench.db"
typedef struct BM_LEVELDB {
leveldb_t *db;
leveldb_options_t *options;
} BM_LEVELDB;
static void env_setup() {
fprintf(stderr, " engine: LevelDB %d.%d\n", leveldb_major_version(), leveldb_minor_version());
}
uint64_t db_size_bytes(BMCTX *ctx) {
char buf[PATH_MAX + 1];
DIR *d;
uint64_t sz = 0;
struct dirent *dir;
const char *path = bm.param_db ? bm.param_db : DEFAULT_DB;
d = opendir(path);
if (d) {
while ((dir = readdir(d))) {
snprintf(buf, sizeof(buf), "%s/%s", path, dir->d_name);
IWP_FILE_STAT fst;
iwrc rc = iwp_fstat(buf, &fst);
if (rc) {
iwlog_ecode_error3(rc);
return 0;
}
if (fst.ftype == IWP_TYPE_FILE) {
sz += fst.size;
}
}
closedir(d);
}
return sz;
}
static void *db_open(BMCTX *ctx) {
if (ctx->db) {
return 0; // db is not closed properly
}
char *err = 0;
const char *path = bm.param_db ? bm.param_db : DEFAULT_DB;
BM_LEVELDB *bmdb = malloc(sizeof(*bmdb));
bmdb->options = leveldb_options_create();
leveldb_options_set_create_if_missing(bmdb->options, 1);
if (ctx->freshdb) {
leveldb_destroy_db(bmdb->options, path, &err);
if (err) {
leveldb_free(err);
err = 0;
}
iwp_removedir(path);
}
bmdb->db = leveldb_open(bmdb->options, path, &err);
if (err) {
leveldb_options_destroy(bmdb->options);
fprintf(stderr, "ERROR db_open: %s\n", err);
leveldb_free(err);
free(bmdb);
return 0;
}
return bmdb;
}
static bool db_close(BMCTX *ctx) {
if (!ctx->db) {
return false;
}
BM_LEVELDB *bmdb = ctx->db;
leveldb_close(bmdb->db);
leveldb_options_destroy(bmdb->options);
free(bmdb);
return true;
}
static bool db_put(BMCTX *ctx, const IWKV_val *key, const IWKV_val *val, bool sync) {
BM_LEVELDB *bmdb = ctx->db;
char *err = 0;
bool ret = true;
leveldb_writeoptions_t *wopt = leveldb_writeoptions_create();
if (sync) {
leveldb_writeoptions_set_sync(wopt, 1);
}
leveldb_put(bmdb->db, wopt, key->data, key->size, val->data, val->size, &err);
if (err) {
fprintf(stderr, "ERROR db_put: %s\n", err);
leveldb_free(err);
ret = false;
}
leveldb_writeoptions_destroy(wopt);
return ret;
}
static bool db_get(BMCTX *ctx, const IWKV_val *key, IWKV_val *val, bool *found) {
BM_LEVELDB *bmdb = ctx->db;
size_t sz;
char *data = 0;
char *err = 0;
bool ret = true;
leveldb_readoptions_t *ropt = leveldb_readoptions_create();
data = leveldb_get(bmdb->db, ropt, key->data, key->size, &sz, &err);
*found = (data != 0);
if (err) {
fprintf(stderr, "ERROR db_get: %s\n", err);
leveldb_free(err);
ret = false;
} else {
val->data = data;
val->size = sz;
}
leveldb_readoptions_destroy(ropt);
return ret;
}
static bool db_del(BMCTX *ctx, const IWKV_val *key, bool sync) {
BM_LEVELDB *bmdb = ctx->db;
char *err = 0;
bool ret = true;
leveldb_writeoptions_t *wopt = leveldb_writeoptions_create();
if (sync) {
leveldb_writeoptions_set_sync(wopt, 1);
}
leveldb_delete(bmdb->db, wopt, key->data, key->size, &err);
if (err) {
fprintf(stderr, "ERROR db_del: %s\n", err);
leveldb_free(err);
ret = false;
}
leveldb_writeoptions_destroy(wopt);
return ret;
}
static bool db_read_seq(BMCTX *ctx, bool reverse) {
BM_LEVELDB *bmdb = ctx->db;
bool ret = true;
leveldb_readoptions_t *ropt = leveldb_readoptions_create();
leveldb_iterator_t *it = leveldb_create_iterator(bmdb->db, ropt);
if (reverse) {
leveldb_iter_seek_to_last(it);
} else {
leveldb_iter_seek_to_first(it);
}
for (int i = 0; i < bm.param_num && leveldb_iter_valid(it); ++i) {
size_t vlen, klen;
leveldb_iter_value(it, &vlen);
leveldb_iter_key(it, &klen);
if (reverse) {
leveldb_iter_prev(it);
} else {
leveldb_iter_next(it);
}
}
leveldb_iter_destroy(it);
leveldb_readoptions_destroy(ropt);
return ret;
}
static bool db_cursor_to_key(BMCTX *ctx, const IWKV_val *key, IWKV_val *val, bool *found) {
BM_LEVELDB *bmdb = ctx->db;
bool ret = true;
leveldb_readoptions_t *ropt = leveldb_readoptions_create();
leveldb_iterator_t *it = leveldb_create_iterator(bmdb->db, ropt);
leveldb_iter_seek(it, key->data, key->size);
*found = leveldb_iter_valid(it);
val->data = 0;
val->size = 0;
if (*found) {
size_t vlen;
const char *v = leveldb_iter_value(it, &vlen);
val->data = malloc(vlen);
memcpy(val->data, v, vlen);
}
leveldb_iter_destroy(it);
leveldb_readoptions_destroy(ropt);
return ret;
}
int main(int argc, char **argv) {
if (argc < 1) return -1;
g_program = argv[0];
bm.env_setup = env_setup;
bm.db_size_bytes = db_size_bytes;
bm.db_open = db_open;
bm.db_close = db_close;
bm.db_put = db_put;
bm.db_get = db_get;
bm.db_del = db_del;
bm.db_read_seq = db_read_seq;
bm.db_cursor_to_key = db_cursor_to_key;
if (!bm_bench_run(argc, argv)) {
return 1;
}
return 0;
}
+201
View File
@@ -0,0 +1,201 @@
#include "bmbase.c"
#include <lmdb.h>
#include <unistd.h>
#include <errno.h>
static_assert(sizeof(size_t) == 8, "sizeof(size_t) == 8 bytes");
#define E(expr_, ret_) \
if ((rc = (expr_)) != MDB_SUCCESS) { \
fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, mdb_strerror(rc)); \
return ret_;\
}
#define B(expr_) E(expr_, 0)
#define DEFAULT_DB "lmdb_bench.db"
typedef struct BM_LEVELDB {
MDB_env *env;
MDB_dbi dbi;
} BM_LMDB;
static void env_setup() {
int major, minor, patch;
mdb_version(&major, &minor, &patch);
fprintf(stderr, " engine: LMDB %d.%d.%d\n", major, minor, patch);
}
uint64_t db_size_bytes(BMCTX *ctx) {
const char *path = bm.param_db ? bm.param_db : DEFAULT_DB;
IWP_FILE_STAT fst;
iwrc rc = iwp_fstat(path, &fst);
if (rc) {
iwlog_ecode_error3(rc);
return 0;
}
return fst.size;
}
static void *db_open(BMCTX *ctx) {
int rc;
if (ctx->db) {
return 0; // db is not closed properly
}
const char *path = bm.param_db ? bm.param_db : DEFAULT_DB;
if (ctx->freshdb) { // completely remove db folder
rc = unlink(path);
if (rc && errno != ENOENT) {
E(errno, 0);
}
}
MDB_txn *txn;
BM_LMDB *bmdb = malloc(sizeof(*bmdb));
E(mdb_env_create(&bmdb->env), 0);
E(mdb_env_set_maxreaders(bmdb->env, 1), 0);
E(mdb_env_set_mapsize(bmdb->env, 1024ULL * 1024 * 1024 * 100), 0); // 100 GB
E(mdb_env_open(bmdb->env, path, MDB_FIXEDMAP | MDB_NOSUBDIR | MDB_NOSYNC, 0664), 0);
E(mdb_txn_begin(bmdb->env, NULL, 0, &txn), 0);
E(mdb_dbi_open(txn, NULL, 0, &bmdb->dbi), 0);
E(mdb_txn_commit(txn), 0);
return bmdb;
}
static bool db_close(BMCTX *ctx) {
int rc;
if (!ctx->db) {
return false;
}
BM_LMDB *bmdb = ctx->db;
B(mdb_env_sync(bmdb->env, 1));
mdb_dbi_close(bmdb->env, bmdb->dbi);
mdb_env_close(bmdb->env);
free(bmdb);
return true;
}
static bool db_put(BMCTX *ctx, const IWKV_val *key, const IWKV_val *val, bool sync) {
int rc;
BM_LMDB *bmdb = ctx->db;
MDB_txn *txn;
MDB_val mkey, mval;
mkey.mv_data = key->data;
mkey.mv_size = key->size;
mval.mv_data = val->data;
mval.mv_size = val->size;
B(mdb_txn_begin(bmdb->env, NULL, 0, &txn));
B(mdb_put(txn, bmdb->dbi, &mkey, &mval, 0));
B(mdb_txn_commit(txn));
if (sync) {
B(mdb_env_sync(bmdb->env, 1));
}
return true;
}
static bool db_get(BMCTX *ctx, const IWKV_val *key, IWKV_val *val, bool *found) {
int rc;
MDB_txn *txn;
MDB_val mkey, mval;
BM_LMDB *bmdb = ctx->db;
mkey.mv_data = key->data;
mkey.mv_size = key->size;
B(mdb_txn_begin(bmdb->env, NULL, MDB_RDONLY, &txn));
rc = mdb_get(txn, bmdb->dbi, &mkey, &mval);
if (!rc) {
*found = true;
val->size = mval.mv_size;
val->data = malloc(val->size);
memcpy(val->data, mval.mv_data, mval.mv_size);
} else if (rc == MDB_NOTFOUND) {
*found = false;
rc = 0;
}
mdb_txn_abort(txn);
B(rc);
return true;
}
static bool db_del(BMCTX *ctx, const IWKV_val *key, bool sync) {
int rc;
MDB_txn *txn;
MDB_val mkey;
BM_LMDB *bmdb = ctx->db;
mkey.mv_data = key->data;
mkey.mv_size = key->size;
B(mdb_txn_begin(bmdb->env, NULL, 0, &txn));
rc = mdb_del(txn, bmdb->dbi, &mkey, 0);
if (rc == MDB_NOTFOUND) {
rc = 0;
}
B(mdb_txn_commit(txn));
if (sync) {
B(mdb_env_sync(bmdb->env, 1));
}
return true;
}
static bool db_read_seq(BMCTX *ctx, bool reverse) {
int rc = 0;
MDB_txn *txn;
MDB_cursor *cur;
MDB_val mkey, mval;
BM_LMDB *bmdb = ctx->db;
B(mdb_txn_begin(bmdb->env, NULL, MDB_RDONLY, &txn));
B(mdb_cursor_open(txn, bmdb->dbi, &cur));
B(mdb_cursor_get(cur, &mkey, &mval, reverse ? MDB_LAST : MDB_FIRST));
for (int i = 0; i < bm.param_num - 1 && !rc; ++i) {
rc = mdb_cursor_get(cur, &mkey, &mval, reverse ? MDB_PREV : MDB_NEXT);
}
if (rc == MDB_NOTFOUND) {
rc = 0;
}
mdb_cursor_close(cur);
mdb_txn_abort(txn);
B(rc);
return true;
}
static bool db_cursor_to_key(BMCTX *ctx, const IWKV_val *key, IWKV_val *val, bool *found) {
int rc = 0;
MDB_txn *txn;
MDB_cursor *cur;
MDB_val mkey, mval;
BM_LMDB *bmdb = ctx->db;
mkey.mv_data = key->data;
mkey.mv_size = key->size;
B(mdb_txn_begin(bmdb->env, NULL, MDB_RDONLY, &txn));
B(mdb_cursor_open(txn, bmdb->dbi, &cur));
rc = mdb_cursor_get(cur, &mkey, &mval, MDB_SET);
if (rc == MDB_NOTFOUND) {
*found = false;
val->data = 0;
val->size = 0;
rc = 0;
} else if (!rc) {
*found = true;
val->data = malloc(mval.mv_size);;
memcpy(val->data, mval.mv_data, mval.mv_size);
}
mdb_cursor_close(cur);
mdb_txn_abort(txn);
B(rc);
return true;
}
int main(int argc, char **argv) {
if (argc < 1) return -1;
g_program = argv[0];
bm.env_setup = env_setup;
bm.db_size_bytes = db_size_bytes;
bm.db_open = db_open;
bm.db_close = db_close;
bm.db_put = db_put;
bm.db_get = db_get;
bm.db_del = db_del;
bm.db_read_seq = db_read_seq;
bm.db_cursor_to_key = db_cursor_to_key;
if (!bm_bench_run(argc, argv)) {
return 1;
}
return 0;
}
+149
View File
@@ -0,0 +1,149 @@
import subprocess
import argparse
import os
import random
from collections import OrderedDict
from parse import parse
from bokeh.io import export_png
from bokeh.plotting import figure, output_file, show, save
from bokeh.models import ColumnDataSource, FactorRange
from bokeh.transform import factor_cmap
from bokeh.layouts import gridplot
from bokeh.embed import components
parser = argparse.ArgumentParser(description='IWKV Benchmarks')
parser.add_argument(
'-b', '--basedir', help='Base directory with benchmark executables', default='.', nargs='?')
args = parser.parse_args()
basedir = os.path.abspath(args.basedir)
print('Base directory:', basedir)
benchmarks = [
'iwkv',
'lmdb',
'bdb',
'wiredtiger',
'kyc',
'tc'
#'leveldb'
]
runs = []
runs += [{'b': 'fillrandom2', 'n': n, 'vz': vz, 'rs': 2853624176, 'sizestats': True}
for n in (int(1e6),)
for vz in (1000,)]
runs += [{'b': 'fillrandom2,readrandom,deleterandom', 'n': n, 'vz': vz, 'kz': kz, 'rs': 2105940112}
for n in (int(2e6),)
for vz in (40, 400,)
for kz in (16, 1024,)]
runs += [{'b': 'fillseq,overwrite,deleteseq', 'n': n, 'kz': kz, 'rs': 570078848}
for n in (int(2e6),)
for vz in (400,)
for kz in (16, 1024,)]
runs += [{'b': 'fillrandom2,readrandom,readseq,readreverse', 'n': n, 'vz': vz, 'rs': 1513135152}
for n in (int(10e6),)
for vz in (200,)]
runs += [{'b': 'fillrandom2', 'n': n, 'vz': vz, 'rs': 3434783568}
for n in (int(10e3),)
for vz in ((200 * 1024),)]
results = OrderedDict()
def fill_result(bm, run, sizestats, line):
key = ' '.join(['-{} {}'.format(a, v) for a, v in run.items()])
if key not in results:
results[key] = OrderedDict()
if bm not in results[key]:
results[key][bm] = OrderedDict()
res = results[key][bm]
pval = parse('done: {} in {}', line)
if sizestats:
pval = parse('db size: {} ({})', line)
if pval and 'db size' not in res:
print(line, flush=True)
res['db size'] = int(pval[0]) / (1024 * 1024)
elif pval:
print(line, flush=True)
res[pval[0]] = int(pval[1])
def run_benchmark_run(bm, run):
args = ['{}/{}_benchmark'.format(basedir, bm)]
sizestats = False
for a, v in run.items():
if a in ('sizestats',):
sizestats = True
continue
args.append('-{}'.format(a))
args.append(str(v))
print('Run {}'.format(' '.join(args)), flush=True)
with subprocess.Popen(args,
stderr=subprocess.STDOUT,
stdout=subprocess.PIPE,
universal_newlines=True,
cwd=basedir,
bufsize=1) as output:
for line in output.stdout:
fill_result(bm, run, sizestats, line.strip())
output.wait()
def run_benchmark(bm):
for run in runs:
run_benchmark_run(bm, run)
def run():
for b in benchmarks:
run_benchmark(b)
def main():
run()
plots = []
palette = ["#00B377", "#e84d60", "#0054AE", "#c9d9d3",
"#BFF500", "#555555", "#DFBFFF", "#B1D28F",
"#FFAA00", "#A18353", "#888888", "#718dbf"]
for bn, rmap in results.items():
pfactors = None
x = [(bm, brun) for bm in iter(rmap) for brun in iter(rmap[bm])]
if len([v for v in x if v[1] == 'db size']):
sizestats = True
else:
sizestats = False
if pfactors is None:
pfactors = [f[1] for f in x]
counts = [rmap[bm][brun]
for bm in iter(rmap) for brun in iter(rmap[bm])]
source = ColumnDataSource(data=dict(x=x, counts=counts))
p = figure(x_range=FactorRange(*x), plot_height=350, plot_width=750,
title=bn) # y_axis_type="log"
p.vbar(x='x', top='counts', width=0.9, source=source, line_color='white',
fill_color=factor_cmap('x', palette=palette, factors=pfactors, start=1, end=2))
p.y_range.start = 0
p.yaxis.axis_label = 'Time ms' if not sizestats else 'Database file size (MB)'
p.x_range.range_padding = 0.1
p.xaxis.major_label_orientation = 1
p.xgrid.grid_line_color = None
p.toolbar_location = None
plots.append(p)
os.makedirs("charts", exist_ok=True)
export_png(p, filename="charts/{}.png".format(bn))
p.toolbar_location = "right"
grid = gridplot(plots, ncols=1, merge_tools=False)
output_file('benchmark_results_raw.html')
save(grid)
show(grid)
if __name__ == '__main__':
main()
+151
View File
@@ -0,0 +1,151 @@
#include "bmbase.c"
#include <tcbdb.h>
#define DEFAULT_DB "tc_bench.tc"
struct BMTC {
TCBDB *db;
} btc;
typedef struct BMTC BMTC;
static void env_setup() {
fprintf(stderr, " engine: TokyoCabinet %s\n", _TC_VERSION);
}
uint64_t db_size_bytes(BMCTX *ctx) {
const char *path = bm.param_db ? bm.param_db : DEFAULT_DB;
IWP_FILE_STAT fst;
iwrc rc = iwp_fstat(path, &fst);
if (rc) {
iwlog_ecode_error3(rc);
return 0;
}
return fst.size;
}
static void *db_open(BMCTX *ctx) {
if (ctx->db || btc.db) {
return 0; // db is not closed properly
}
const char *path = bm.param_db ? bm.param_db : DEFAULT_DB;
int omode = BDBOWRITER | BDBOCREAT;
if (ctx->freshdb) {
omode |= BDBOTRUNC;
}
btc.db = tcbdbnew();
if (!btc.db) {
return 0;
}
tcbdbsetxmsiz(btc.db, 1024ULL * 1024 * 1024 * 10);
tcbdbtune(btc.db, 0, 0, 32749 * 4, 8, 10, BDBTLARGE);
if (!tcbdbopen(btc.db, path, omode)) {
tcbdbdel(btc.db);
btc.db = 0;
return 0;
}
return &btc;
}
static bool db_close(BMCTX *ctx) {
if (!ctx->db) {
return false;
}
BMTC *btc = ctx->db;
bool ret = tcbdbclose(btc->db);
tcbdbdel(btc->db);
btc->db = 0;
return ret;
}
static bool db_put(BMCTX *ctx, const IWKV_val *key, const IWKV_val *val, bool sync) {
BMTC *btc = ctx->db;
if (!tcbdbput(btc->db, key->data, key->size, val->data, val->size)) {
fprintf(stderr, "db_put: %s\n", tcbdberrmsg(tcbdbecode(btc->db)));
return false;
}
if (sync) {
return tcbdbsync(btc->db);
}
return true;
}
static bool db_get(BMCTX *ctx, const IWKV_val *key, IWKV_val *val, bool *found) {
BMTC *btc = ctx->db;
int sp = 0;
char *vbuf = tcbdbget(btc->db, key->data, key->size, &sp);
val->data = vbuf;
val->size = sp;
*found = (val->data != 0);
return true;
}
static bool db_del(BMCTX *ctx, const IWKV_val *key, bool sync) {
BMTC *btc = ctx->db;
tcbdbout(btc->db, key->data, key->size);
if (sync) {
if (!tcbdbsync(btc->db)) {
fprintf(stderr, "db_del: %s\n", tcbdberrmsg(tcbdbecode(btc->db)));
return false;
}
}
return true;
}
static bool db_read_seq(BMCTX *ctx, bool reverse) {
BMTC *btc = ctx->db;
BDBCUR *cur = tcbdbcurnew(btc->db);
if (!cur) {
return false;
}
if (reverse) {
tcbdbcurlast(cur);
} else {
tcbdbcurfirst(cur);
}
for (int i = 0; i < bm.param_num; ++i) {
if (reverse) {
tcbdbcurprev(cur);
} else {
tcbdbcurnext(cur);
}
}
tcbdbcurdel(cur);
return true;
}
static bool db_cursor_to_key(BMCTX *ctx, const IWKV_val *key, IWKV_val *val, bool *found) {
BMTC *btc = ctx->db;
BDBCUR *cur = tcbdbcurnew(btc->db);
if (!cur) {
return false;
}
if (!tcbdbcurjump(cur, key->data, key->size)) {
*found = false;
} else {
*found = true;
int sp;
val->data = tcbdbcurval(cur, &sp);
val->size = sp;
}
tcbdbcurdel(cur);
return true;
}
int main(int argc, char **argv) {
if (argc < 1) return -1;
g_program = argv[0];
bm.env_setup = env_setup;
bm.db_size_bytes = db_size_bytes;
bm.val_free = free;
bm.db_open = db_open;
bm.db_close = db_close;
bm.db_put = db_put;
bm.db_get = db_get;
bm.db_del = db_del;
bm.db_read_seq = db_read_seq;
bm.db_cursor_to_key = db_cursor_to_key;
if (!bm_bench_run(argc, argv)) {
return 1;
}
return 0;
}
+237
View File
@@ -0,0 +1,237 @@
#include "bmbase.c"
#include <dirent.h>
#include <wiredtiger.h>
#define DEFAULT_DB "wiretiger_bench.sb"
struct BMWT {
WT_CONNECTION *conn;
WT_SESSION *session;
WT_CURSOR *cursor;
} bmwt;
typedef struct BMWT BMWT;
static bool db_close(BMCTX *ctx);
static void env_setup() {
fprintf(stderr, " engine: %s\n", WIREDTIGER_VERSION_STRING);
}
uint64_t db_size_bytes(BMCTX *ctx) {
char buf[PATH_MAX + 1];
DIR *d;
uint64_t sz = 0;
struct dirent *dir;
const char *path = bm.param_db ? bm.param_db : DEFAULT_DB;
d = opendir(path);
if (d) {
while ((dir = readdir(d))) {
snprintf(buf, sizeof(buf), "%s/%s", path, dir->d_name);
IWP_FILE_STAT fst;
iwrc rc = iwp_fstat(buf, &fst);
if (rc) {
iwlog_ecode_error3(rc);
return 0;
}
if (fst.ftype == IWP_TYPE_FILE) {
sz += fst.size;
}
}
closedir(d);
}
return sz;
}
static void *db_open(BMCTX *ctx) {
if (ctx->db || bmwt.conn) {
return 0; // db is not closed properly
}
bool wal_enabled = false;
for (int i = 0; i < bm.argc; ++i) {
if (!strcmp(bm.argv[i], "-w")) {
wal_enabled = true;
}
}
const char *path = bm.param_db ? bm.param_db : DEFAULT_DB;
if (ctx->freshdb) {
iwp_removedir(path);
}
iwp_mkdirs(path);
const char *common_config = "create,cache_size=1Gb,transaction_sync=(enabled=false)";
const char *wal_config = "checkpoint_sync=false";
if (wal_enabled) {
wal_config = "log=(enabled,recover=on),checkpoint=(wait=300,log_size=1Gb),checkpoint_sync=true";
}
char config[512];
snprintf(config, sizeof(config), "%s,%s", common_config, wal_config);
// fprintf(stderr, "%s\n", config);
int rc = wiredtiger_open(path, 0, config, &bmwt.conn);
RCGO(rc, finish);
rc = bmwt.conn->open_session(bmwt.conn, 0, 0, &bmwt.session);
RCGO(rc, finish);
rc = bmwt.session->create(bmwt.session, "table:test",
"split_pct=100,leaf_item_max=1KB,"
"type=lsm,internal_page_max=4KB,leaf_page_max=4KB");
RCGO(rc, finish);
rc = bmwt.session->open_cursor(bmwt.session, "table:test", 0, 0, &bmwt.cursor);
finish:
if (rc) {
fprintf(stderr, "db_open %s\n", wiredtiger_strerror(rc));
ctx->db = &bmwt;
db_close(ctx);
ctx->db = 0;
return 0;
}
return &bmwt;
}
static bool db_close(BMCTX *ctx) {
if (!ctx->db) {
return false;
}
bool ret = true;
BMWT *bmwt = ctx->db;
if (bmwt->cursor) {
int rc = bmwt->cursor->close(bmwt->cursor);
if (rc) {
fprintf(stderr, "db_close cursor %s\n", wiredtiger_strerror(rc));
ret = false;
}
}
if (bmwt->session) {
int rc = bmwt->session->close(bmwt->session, 0);
if (rc) {
fprintf(stderr, "db_close session %s\n", wiredtiger_strerror(rc));
ret = false;
}
}
if (bmwt->conn) {
int rc = bmwt->conn->close(bmwt->conn, 0);
if (rc) {
fprintf(stderr, "db_close conn %s\n", wiredtiger_strerror(rc));
ret = false;
}
}
bmwt->conn = 0;
bmwt->session = 0;
bmwt->cursor = 0;
return ret;
}
static bool db_put(BMCTX *ctx, const IWKV_val *key, const IWKV_val *val, bool sync) {
BMWT *bmwt = ctx->db;
WT_ITEM k, v;
k.data = key->data;
k.size = key->size;
v.data = val->data;
v.size = val->size;
bmwt->cursor->set_key(bmwt->cursor, &k);
bmwt->cursor->set_value(bmwt->cursor, &v);
int rc = bmwt->cursor->insert(bmwt->cursor);
RCGO(rc, finish);
if (sync) {
rc = bmwt->session->log_flush(bmwt->session, "background=off");
}
finish:
if (rc) {
fprintf(stderr, "db_put %s\n", wiredtiger_strerror(rc));
}
return rc == 0;
}
static bool db_get(BMCTX *ctx, const IWKV_val *key, IWKV_val *val, bool *found) {
BMWT *bmwt = ctx->db;
WT_ITEM k, v;
k.data = key->data;
k.size = key->size;
bmwt->cursor->set_key(bmwt->cursor, &k);
int rc = bmwt->cursor->search(bmwt->cursor);
if (rc == WT_NOTFOUND) {
rc = 0;
*found = false;
} else if (!rc) {
*found = true;
rc = bmwt->cursor->get_value(bmwt->cursor, &v);
}
if (rc) {
fprintf(stderr, "db_get %s\n", wiredtiger_strerror(rc));
}
return rc == 0;
}
static bool db_del(BMCTX *ctx, const IWKV_val *key, bool sync) {
BMWT *bmwt = ctx->db;
WT_ITEM k;
k.data = key->data;
k.size = key->size;
bmwt->cursor->set_key(bmwt->cursor, &k);
int rc = bmwt->cursor->remove(bmwt->cursor);
if (rc == WT_NOTFOUND) {
rc = 0;
}
RCGO(rc, finish);
if (sync) {
rc = bmwt->session->log_flush(bmwt->session, "background=off");
}
finish:
if (rc) {
fprintf(stderr, "db_del %s\n", wiredtiger_strerror(rc));
}
return rc == 0;
}
static bool db_read_seq(BMCTX *ctx, bool reverse) {
BMWT *bmwt = ctx->db;
WT_ITEM v;
int rc = bmwt->cursor->reset(bmwt->cursor);
RCGO(rc, finish);
for (int i = 0; i < bm.param_num && !rc; ++i) {
if (reverse) {
rc = bmwt->cursor->prev(bmwt->cursor);
} else {
rc = bmwt->cursor->next(bmwt->cursor);
}
if (rc == WT_NOTFOUND) {
rc = 0;
break;
}
if (!rc) {
rc = bmwt->cursor->get_value(bmwt->cursor, &v);
}
}
finish:
if (rc) {
fprintf(stderr, "db_read_seq %s\n", wiredtiger_strerror(rc));
}
return rc == 0;
}
static bool db_cursor_to_key(BMCTX *ctx, const IWKV_val *key, IWKV_val *val, bool *found) {
return db_get(ctx, key, val, found);
}
int main(int argc, char **argv) {
if (argc < 1) return -1;
g_program = argv[0];
bm.env_setup = env_setup;
bm.db_size_bytes = db_size_bytes;
bm.db_open = db_open;
bm.db_close = db_close;
bm.db_put = db_put;
bm.db_get = db_get;
bm.db_del = db_del;
bm.db_read_seq = db_read_seq;
bm.db_cursor_to_key = db_cursor_to_key;
if (!bm_bench_run(argc, argv)) {
return 1;
}
return 0;
}
+81
View File
@@ -0,0 +1,81 @@
IWKV
block size: u128
max key+value size: 268435455 (~255Mb)
max data file size: 512G
SBLK - Skip list node with pointers to next nodes and pointer to KVBLK (key/value pairs block).
SBLK has fixed size (256 bytes). SBLK file position (block adress) within a file is
fixed and cannot be changed.
V1 SBLK layout:
[u1:flags,lvl:u1,lkl:u1,pnum:u1,p0:u4,kblk:u4,pi:u1[32],n:u4[24],lk:u116]:u256
V2 SBLK layout:
[flags:u1,lvl:u1,lkl:u1,pnum:u1,p0:u4,kblk:u4,pi:u1[32],n:u4[24],bpos:u1,lk:u115]:u256
\
KVBLK
flags - Persistent block flags (1 byte)
lvl - Skiplist level of this block (1 byte)
lkl - Length of the lower key in this block (1 byte)
pnum - Number of active kv indexes in `SBLK::pi`
p0 - Address of previous sblk block at zero level
kblk - Block number of associated KVBLK. (4 bytes)
pi[32] - Array of key/value pair indexes in KVBLK block.
Indexes are sorted by keys. (32 bytes)
n[24] - Pointers to next SBLK blocks in skiplist (96 bytes)
bpos - Position of SBLK in a page block starting with 1 (zero means SBLK deleted)
lk - Buffer for the lowest key among all key/value pairs stored in KVBLK
KVBLK - Data block stored a set of key/value pairs associated with SBLK
[szpow:u1,idxsz:u2,KVI[32] ___free space___ [[KV],...]]
szpow - KVBLK length as power of 2
idxsz - Length of KVI array in bytes
KVI[32] - [ps:vn, pl:vn]
ps: key/value pair block offset on i-th place variable length encoded number.
This offset is relative to end of KVBLK block
pl: key/value pair block length on i-th place variable length encoded number
KV - [klen:vn,key,value]
Key/value pair
klen: Key length as variable length encoded number
key: Key data buffer
value: Value data buffer
DB header block:
[magic:u4,dbflg:u1,dbid:u4,next_db_blk:u4,p0:u4,n[24]:u4,c[24]:u4,meta_blk:u4,meta_len:u4]:217
magic - DB magic number 0x69776462
dbflg - Database flags
next_db_blk - Next database meta block number or zero
dbid - Database ID
p0 - Last database block
n24 - Skiplist next pointers to `SBLK`
c24 - SBLK count per level,
/* since file format v1 */
meta_blk - Database metadata block number
meta_blkn - Database metadata block count
HEADER:
[magic:u4,u8:fistdb_addr]
magic - File magic number 0x69776b76
fistdb_addr - Address of the first db in the DB chain
------------------------------------------------------------
WAL
1. Extra rdb methods
+153
View File
@@ -0,0 +1,153 @@
//-------------------------- DEBUG STAFF
void iwkvd_trigger_xor(uint64_t val) {
g_trigger ^= val;
}
void iwkvd_kvblk(FILE *f, KVBLK *kb, int maxvlen) {
assert(f && kb && kb->addr);
uint8_t *mm, *vbuf, *kbuf;
uint32_t klen, vlen;
IWFS_FSM *fsm = &kb->db->iwkv->fsm;
blkn_t blkn = ADDR2BLK(kb->addr);
fprintf(f, "\n === KVBLK[%u] maxoff=%" PRIx64 ", zidx=%d, idxsz=%d, szpow=%u, flg=%x, db=%d\n", // -V576
blkn, (int64_t) kb->maxoff, kb->zidx, kb->idxsz, kb->szpow, kb->flags, kb->db->id);
iwrc rc = fsm->probe_mmap(fsm, 0, &mm, 0);
if (rc) {
iwlog_ecode_error3(rc);
return;
}
for (int i = 0; i < KVBLK_IDXNUM; ++i) {
KVP *kvp = &kb->pidx[i];
rc = _kvblk_key_peek(kb, i, mm, &kbuf, &klen);
if (rc) {
iwlog_ecode_error3(rc);
return;
}
_kvblk_value_peek(kb, i, mm, &vbuf, &vlen);
fprintf(f, "\n %02d: [%04" PRIx64 ", %02u, %02d]: %.*s:%.*s",
i, (int64_t) kvp->off, kvp->len, kvp->ridx,
klen, kbuf, MIN(vlen, maxvlen), vbuf);
}
fprintf(f, "\n");
}
#define IWKVD_MAX_VALSZ 96
iwrc iwkvd_sblk(FILE *f, IWLCTX *lx, SBLK *sb, int flags) {
assert(sb && sb->addr);
uint32_t lkl = 0;
char lkbuf[PREFIX_KEY_LEN_V1 + 1] = {0};
uint8_t *mm, *vbuf, *kbuf;
uint32_t klen, vlen;
IWFS_FSM *fsm = &sb->db->iwkv->fsm;
blkn_t blkn = ADDR2BLK(sb->addr);
iwrc rc = fsm->probe_mmap(fsm, 0, &mm, 0);
if (rc) {
iwlog_ecode_error3(rc);
return rc;
}
rc = _sblk_loadkvblk_mm(lx, sb, mm);
if (rc) {
iwlog_ecode_error3(rc);
return rc;
}
assert(sb->kvblk);
if (sb->flags & SBLK_DB) {
lkl = 0;
} else {
memcpy(&lkl, mm + sb->addr + SOFF_LKL_U1, 1);
lkl = IW_ITOHL(lkl);
if (lx->db->iwkv->fmt_version > 1) {
memcpy(lkbuf, mm + sb->addr + SOFF_LK_V2, lkl);
} else {
memcpy(lkbuf, mm + sb->addr + SOFF_LK_V1, lkl);
}
}
fprintf(f, "\n === SBLK[%u] lvl=%d, pnum=%d, flg=%x, kvzidx=%d, p0=%u, db=%u",
blkn,
((IWKVD_PRINT_NO_LEVEVELS & flags) ? -1 : sb->lvl),
sb->pnum, sb->flags, sb->kvblk->zidx,
sb->p0,
sb->kvblk->db->id);
fprintf(f, "\n === SBLK[%u] szpow=%d, lkl=%d, lk=%s\n", blkn, sb->kvblk->szpow, lkl, lkbuf); // -V576
for (int i = 0, j = 0; i < sb->pnum; ++i, ++j) {
if (j == 3) {
fputc('\n', f);
j = 0;
}
if (j == 0) {
fprintf(f, " === SBLK[%u]", blkn);
}
rc = _kvblk_key_peek(sb->kvblk, sb->pi[i], mm, &kbuf, &klen);
if (rc) {
iwlog_ecode_error3(rc);
return rc;
}
if (flags & IWKVD_PRINT_VALS) {
_kvblk_value_peek(sb->kvblk, sb->pi[i], mm, &vbuf, &vlen);
fprintf(f, " [%03d,%03d] %.*s:%.*s", i, sb->pi[i], klen, kbuf, MIN(vlen, IWKVD_MAX_VALSZ), vbuf);
} else {
fprintf(f, " [%03d,%03d] %.*s", i, sb->pi[i], klen, kbuf);
}
}
fprintf(f, "\n\n");
return rc;
}
IWFS_FSM *iwkvd_fsm(IWKV kv) {
return &kv->fsm;
}
void iwkvd_db(FILE *f, IWDB db, int flags, int plvl) {
assert(db);
SBLK *sb, *tail;
IWLCTX lx = {
.db = db,
.nlvl = -1
};
iwrc rc = _sblk_at(&lx, db->addr, 0, &sb);
if (rc) {
iwlog_ecode_error3(rc);
return;
}
rc = _sblk_at(&lx, 0, 0, &tail);
if (rc) {
iwlog_ecode_error3(rc);
return;
}
fprintf(f, "\n\n== DB[%u] lvl=%d, blk=%u, dbflg=%x, p0=%u",
db->id,
((IWKVD_PRINT_NO_LEVEVELS & flags) ? -1 : sb->lvl),
(unsigned int) ADDR2BLK(sb->addr),
db->dbflg,
tail->p0);
if (!(IWKVD_PRINT_NO_LEVEVELS & flags)) {
fprintf(f, "\n== DB[%u]->n=[", db->id);
for (int i = 0; i <= sb->lvl; ++i) {
if (i > 0) {
fprintf(f, ", %d:%u", i, sb->n[i]);
} else {
fprintf(f, "%d:%u", i, sb->n[i]);
}
}
fprintf(f, "]");
}
blkn_t blk = sb->n[plvl];
while (blk) {
rc = _sblk_at(&lx, BLK2ADDR(blk), 0, &sb);
if (rc) {
iwlog_ecode_error3(rc);
return;
}
iwkvd_sblk(f, &lx, sb, flags);
blk = sb->n[plvl];
_sblk_release(&lx, &sb);
}
fflush(f);
}
+5
View File
@@ -0,0 +1,5 @@
link_libraries(iowow_s)
foreach(EX IN ITEMS example1 cursors1 compoundkeys1)
add_executable(${EX} ${EX}.c)
set_target_properties(${EX} PROPERTIES COMPILE_FLAGS "-DIW_STATIC")
endforeach()
+121
View File
@@ -0,0 +1,121 @@
///
/// Compound keys demo.
///
/// Compound keys allows associate one `key value` with many references
/// represented as VNUM64 (eg.: Non unique table indexes).
///
/// Compound mainly used for non-unique indexes in ejdb2 database engine:
///
/// `<prefix key value>.<document id>`
///
#include "iwkv.h"
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
struct user_s {
uint32_t id;
char *name;
};
struct chat_root_s {
char *name;
struct user_s users[5];
};
static struct chat_root_s rooms[] = {
{
.name = "Meeting room",
.users = {
{ .id = 1, .name = "Joy Lynn" },
{ .id = 2, .name = "Aubrey Sparks" },
{ .id = 3, .name = "Vinnie Kaye"},
{ 0 }
}
},
{
.name = "Webinar room",
.users = {
{ .id = 4, .name = "Arda Payne" },
{ .id = 2, .name = "Joy Lynn" },
{ 0 }
}
}
};
static iwrc run(void) {
IWKV_OPTS opts = {
.path = "compoundkeys.db",
.oflags = IWKV_TRUNC
};
IWKV iwkv;
IWDB db;
IWKV_cursor cur = 0;
iwrc rc = iwkv_open(&opts, &iwkv);
RCRET(rc);
rc = iwkv_db(iwkv, 1, IWDB_COMPOUND_KEYS, &db);
RCGO(rc, finish);
// Persist all rooms with members
for (int i = 0; i < sizeof(rooms) / sizeof(rooms[0]); ++i) {
int j = 0;
struct chat_root_s *room = &rooms[i];
for (struct user_s *user = &room->users[0]; user->id; user = &room->users[++j]) {
IWKV_val key = { .data = room->name, .size = strlen(room->name), .compound = user->id };
IWKV_val val = { .data = user->name, .size = strlen(user->name) };
RCC(rc, finish, iwkv_put(db, &key, &val, 0));
}
}
// Get specific user from the room
{
IWKV_val key = { .data = "Webinar room", .size = sizeof("Webinar room") - 1, .compound = 2 };
IWKV_val val;
RCC(rc, finish, iwkv_get(db, &key, &val));
fprintf(stdout, "\n>>>> Found: '%.*s' in room '%s' by id: %d\n",
(int) val.size, (char *) val.data,
(char *) key.data, (int) key.compound);
iwkv_val_dispose(&val);
}
// Iterate over all members in `Meeting room`
{
size_t len = strlen(rooms[0].name);
fprintf(stdout, "\n>>>> Iterate over all members in %s\n", rooms[0].name);
IWKV_val val, key = { .data = rooms[0].name, .size = len };
RCC(rc, finish, iwkv_cursor_open(db, &cur, IWKV_CURSOR_GE, &key));
do {
RCC(rc, finish, iwkv_cursor_get(cur, &key, &val));
if (memcmp(key.data, rooms[0].name, MIN(key.size, len))) {
// We rolled to end of `Meeting room` room
iwkv_kv_dispose(&key, &val);
break;
}
fprintf(stdout, "%.*s: %d %.*s\n",
(int) key.size, (char *) key.data,
(int) key.compound,
(int) val.size,
(char *) val.data);
iwkv_kv_dispose(&key, &val);
} while ((rc = iwkv_cursor_to(cur, IWKV_CURSOR_PREV)) == 0);
rc = 0;
}
finish:
if (cur) {
iwkv_cursor_close(&cur);
}
iwkv_close(&iwkv);
return rc;
}
int main() {
iwrc rc = run();
if (rc) {
iwlog_ecode_error3(rc);
return 1;
}
return 0;
}
+116
View File
@@ -0,0 +1,116 @@
///
/// Fills database with a set of football table records
/// then traverse records according to club name in ascending and descending orders.
///
#include "iwkv.h"
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
static struct data_s {
const char *club;
uint8_t points;
} _points[] = {
{ "Aston Villa", 25 },
{ "Manchester City", 57 },
{ "Arsenal", 40 },
{ "Everton", 37 },
{ "West Ham United", 27 },
{ "Tottenham Hotspur", 41 },
{ "Wolverhampton Wanderers", 43 },
{ "Norwich City", 21 },
{ "Leicester City", 53 },
{ "Manchester United", 45 },
{ "Newcastle United", 35 },
{ "Brighton & Hove Albion", 29 },
{ "AFC Bournemouth", 27 },
{ "Crystal Palace", 39 },
{ "Sheffield United", 43 },
{ "Burnley", 39 },
{ "Southampton", 34 },
{ "Watford", 27 },
{ "Chelsea", 48 },
{ "Liverpool", 82 },
};
static iwrc run(void) {
IWKV_OPTS opts = {
.path = "cursor1.db",
.oflags = IWKV_TRUNC // Cleanup database before open
};
IWKV iwkv;
IWDB db;
IWKV_cursor cur = 0;
iwrc rc = iwkv_open(&opts, &iwkv);
RCRET(rc);
rc = iwkv_db(iwkv, 1, 0, &db);
RCGO(rc, finish);
for (int i = 0; i < sizeof(_points) / sizeof(_points[0]); ++i) {
struct data_s *n = &_points[i];
IWKV_val key = { .data = (void *) n->club, .size = strlen(n->club) };
IWKV_val val = { .data = &n->points, .size = sizeof(n->points) };
RCC(rc, finish, iwkv_put(db, &key, &val, 0));
}
fprintf(stdout, ">>>> Traverse in descending order\n");
RCC(rc, finish, iwkv_cursor_open(db, &cur, IWKV_CURSOR_BEFORE_FIRST, 0));
while ((rc = iwkv_cursor_to(cur, IWKV_CURSOR_NEXT)) == 0) {
IWKV_val key, val;
RCC(rc, finish, iwkv_cursor_get(cur, &key, &val));
fprintf(stdout, "%.*s: %u\n",
(int) key.size, (char *) key.data,
*(uint8_t *) val.data);
iwkv_kv_dispose(&key, &val);
}
rc = 0;
iwkv_cursor_close(&cur);
fprintf(stdout, "\n>>>> Traverse in ascending order\n");
RCC(rc, finish, iwkv_cursor_open(db, &cur, IWKV_CURSOR_AFTER_LAST, 0));
while ((rc = iwkv_cursor_to(cur, IWKV_CURSOR_PREV)) == 0) {
IWKV_val key, val;
RCC(rc, finish, iwkv_cursor_get(cur, &key, &val));
fprintf(stdout, "%.*s: %u\n",
(int) key.size, (char *) key.data,
*(uint8_t *) val.data);
iwkv_kv_dispose(&key, &val);
}
rc = 0;
iwkv_cursor_close(&cur);
// Select all keys greater or equal than: Manchester United
{
fprintf(stdout, "\n>>>> Records GE: %s\n", _points[9].club);
IWKV_val key = { .data = (void *) _points[9].club, .size = strlen(_points[9].club) }, val;
RCC(rc, finish, iwkv_cursor_open(db, &cur, IWKV_CURSOR_GE, &key));
do {
RCC(rc, finish, iwkv_cursor_get(cur, &key, &val));
fprintf(stdout, "%.*s: %u\n",
(int) key.size, (char *) key.data,
*(uint8_t *) val.data);
iwkv_kv_dispose(&key, &val);
} while ((rc = iwkv_cursor_to(cur, IWKV_CURSOR_NEXT)) == 0);
rc = 0;
}
iwkv_cursor_close(&cur);
finish:
if (cur) {
iwkv_cursor_close(&cur);
}
iwkv_close(&iwkv);
return rc;
}
int main() {
iwrc rc = run();
if (rc) {
iwlog_ecode_error3(rc);
return 1;
}
return 0;
}
+57
View File
@@ -0,0 +1,57 @@
#include "iwkv.h"
#include <string.h>
#include <stdlib.h>
int main() {
IWKV_OPTS opts = {
.path = "example1.db",
.oflags = IWKV_TRUNC // Cleanup database before open
};
IWKV iwkv;
IWDB mydb;
iwrc rc = iwkv_open(&opts, &iwkv);
if (rc) {
iwlog_ecode_error3(rc);
return 1;
}
// Now open mydb
// - Database id: 1
// - Using key/value as char data
rc = iwkv_db(iwkv, 1, 0, &mydb);
if (rc) {
iwlog_ecode_error2(rc, "Failed to open mydb");
return 1;
}
// Work with db: put/get value
IWKV_val key, val;
key.data = "foo";
key.size = strlen(key.data);
val.data = "bar";
val.size = strlen(val.data);
fprintf(stdout, "put: %.*s => %.*s\n",
(int) key.size, (char *) key.data,
(int) val.size, (char *) val.data);
rc = iwkv_put(mydb, &key, &val, 0);
if (rc) {
iwlog_ecode_error3(rc);
return rc;
}
// Retrive value associated with `foo` key
val.data = 0;
val.size = 0;
rc = iwkv_get(mydb, &key, &val);
if (rc) {
iwlog_ecode_error3(rc);
return rc;
}
fprintf(stdout, "get: %.*s => %.*s\n",
(int) key.size, (char *) key.data,
(int) val.size, (char *) val.data);
iwkv_val_dispose(&val);
iwkv_close(&iwkv);
return 0;
}
+1165
View File
File diff suppressed because it is too large Load Diff
+117
View File
@@ -0,0 +1,117 @@
#pragma once
#ifndef IWAL_H
#define IWAL_H
/**************************************************************************************************
* IOWOW library
*
* MIT License
*
* Copyright (c) 2012-2020 Softmotions Ltd <info@softmotions.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*************************************************************************************************/
/** @file
* @brief Write Ahead Logging (WAL) module.
*/
#include "iwkv.h"
#include "iwfsmfile.h"
IW_EXTERN_C_START
typedef enum {
WOP_SET = 1,
WOP_COPY,
WOP_WRITE,
WOP_RESIZE,
WOP_FIXPOINT,
WOP_RESET,
WOP_SEP = 127, /**< WAL file separator */
} wop_t;
#pragma pack(push, 1)
typedef struct WBSEP {
uint8_t id;
uint8_t pad[3];
uint32_t crc;
uint32_t len;
} WBSEP;
typedef struct WBRESET {
uint8_t id;
uint8_t pad[3];
} WBRESET;
typedef struct WBSET {
uint8_t id;
uint8_t pad[3];
uint32_t val;
off_t off;
off_t len;
} WBSET;
typedef struct WBCOPY {
uint8_t id;
uint8_t pad[3];
off_t off;
off_t len;
off_t noff;
} WBCOPY;
typedef struct WBWRITE {
uint8_t id;
uint8_t pad[3];
uint32_t crc;
uint32_t len;
off_t off;
} WBWRITE;
typedef struct WBRESIZE {
uint8_t id;
uint8_t pad[3];
off_t osize;
off_t nsize;
} WBRESIZE;
typedef struct WBFIXPOINT {
uint8_t id;
uint8_t pad[3];
uint64_t ts;
} WBFIXPOINT;
#pragma pack(pop)
iwrc iwal_create(IWKV iwkv, const IWKV_OPTS *opts, IWFS_FSM_OPTS *fsmopts, bool recover_backup);
iwrc iwal_sync(IWKV iwkv);
iwrc iwal_poke_checkpoint(IWKV iwkv, bool force);
iwrc iwal_poke_savepoint(IWKV iwkv);
iwrc iwal_savepoint_exl(IWKV iwkv, bool sync);
void iwal_shutdown(IWKV iwkv);
bool iwal_synched(IWKV iwkv);
iwrc iwal_online_backup(IWKV iwkv, uint64_t *ts, const char *target_file);
IW_EXTERN_C_END
#endif
+4526
View File
File diff suppressed because it is too large Load Diff
+542
View File
@@ -0,0 +1,542 @@
#pragma once
#ifndef IWKV_H
#define IWKV_H
/**************************************************************************************************
* IOWOW library
*
* MIT License
*
* Copyright (c) 2012-2020 Softmotions Ltd <info@softmotions.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*************************************************************************************************/
/** @file
* @brief Persistent key-value storage based on skiplist
* datastructure (https://en.wikipedia.org/wiki/Skip_list).
* @author Anton Adamansky (adamansky@softmotions.com)
*
* <strong>Features:<strong>
* - Simple design of key value storage
* - Lightweight shared/static library: 200Kb
* - Support of multiple key-value databases within a single file
* - Compound keys supported
* - Ultra-fast traversal of database records
* - Native support of integer keys
*
* <strong>Limitations:<strong>
* - Maximum iwkv storage file size: 512 GB (0x7fffffff80)
* - Total size of a single key+value record must be not greater than 255Mb (0xfffffff)
* - In-memory cache for every opened database takes ~130Kb, cache can be disposed by `iwkv_db_cache_release()`
*/
#include "iowow.h"
#include "iwfsmfile.h"
#include <stddef.h>
#include <stdbool.h>
IW_EXTERN_C_START
// Max key + value size: 255Mb
#define IWKV_MAX_KVSZ 0xfffffff
/**
* @brief IWKV error codes.
*/
typedef enum {
_IWKV_ERROR_START = (IW_ERROR_START + 5000UL),
IWKV_ERROR_NOTFOUND, /**< Key not found (IWKV_ERROR_NOTFOUND) */
IWKV_ERROR_KEY_EXISTS, /**< Key already exists (IWKV_ERROR_KEY_EXISTS) */
IWKV_ERROR_MAXKVSZ, /**< Size of Key+value must be not greater than 0xfffffff bytes (IWKV_ERROR_MAXKVSZ) */
IWKV_ERROR_CORRUPTED, /**< Database file invalid or corrupted (IWKV_ERROR_CORRUPTED) */
IWKV_ERROR_DUP_VALUE_SIZE, /**< Value size is not compatible for insertion into sorted values array (IWKV_ERROR_DUP_VALUE_SIZE) */
IWKV_ERROR_KEY_NUM_VALUE_SIZE, /**< Given key is not compatible to storage as number (IWKV_ERROR_KEY_NUM_VALUE_SIZE) */
IWKV_ERROR_INCOMPATIBLE_DB_MODE, /**< Incorpatible database open mode (IWKV_ERROR_INCOMPATIBLE_DB_MODE) */
IWKV_ERROR_INCOMPATIBLE_DB_FORMAT, /**< Incompatible database format version, please migrate database data (IWKV_ERROR_INCOMPATIBLE_DB_FORMAT) */
IWKV_ERROR_CORRUPTED_WAL_FILE, /**< Corrupted WAL file (IWKV_ERROR_CORRUPTED_WAL_FILE) */
IWKV_ERROR_VALUE_CANNOT_BE_INCREMENTED, /**< Stored value cannot be incremented/descremented (IWKV_ERROR_VALUE_CANNOT_BE_INCREMENTED) */
IWKV_ERROR_WAL_MODE_REQUIRED, /**< Operation requires WAL enabled database. (IWKV_ERROR_WAL_MODE_REQUIRED) */
IWKV_ERROR_BACKUP_IN_PROGRESS, /**< Backup operation in progress. (IWKV_ERROR_BACKUP_IN_PROGRESS) */
_IWKV_ERROR_END,
// Internal only
_IWKV_RC_KVBLOCK_FULL,
_IWKV_RC_REQUIRE_NLEVEL,
_IWKV_RC_END,
} iwkv_ecode;
/** Database file open modes. */
typedef uint8_t iwkv_openflags;
/** Open storage file in read-only mode */
#define IWKV_RDONLY ((iwkv_openflags) 0x02U)
/** Truncate storage file on open */
#define IWKV_TRUNC ((iwkv_openflags) 0x04U)
#define IWKV_NO_TRIM_ON_CLOSE ((iwkv_openflags) 0x08U)
/** Database initialization modes */
typedef uint8_t iwdb_flags_t;
/** Floating point number keys represented as string (char*) value. */
#define IWDB_REALNUM_KEYS ((iwdb_flags_t) 0x10U)
/** Variable-length number keys */
#define IWDB_VNUM64_KEYS ((iwdb_flags_t) 0x20U)
/**
* Enable compound database keys. Keys stored in the following format: `<key value prefix><numeric key suffix>`
* Allows associate one `key value` with many references represented as VNUM64 (eg.: Non unique table indexes).
* @see IWKV_val.compound
*/
#define IWDB_COMPOUND_KEYS ((iwdb_flags_t) 0x40U)
/** Record store modes used in `iwkv_put()` and `iwkv_cursor_set()` functions. */
typedef uint8_t iwkv_opflags;
/** Do not overwrite value for an existing key.
`IWKV_ERROR_KEY_EXISTS` will be returned in such cases. */
#define IWKV_NO_OVERWRITE ((iwkv_opflags) 0x01U)
/** Flush changes on disk after operation */
#define IWKV_SYNC ((iwkv_opflags) 0x04U)
/** Increment/decrement stored UINT32|UINT64 value by given INT32|INT64 number
`IWKV_ERROR_KEY_EXISTS` does not makes sense if this flag set. */
#define IWKV_VAL_INCREMENT ((iwkv_opflags) 0x10U)
struct _IWKV;
typedef struct _IWKV *IWKV;
struct _IWDB;
typedef struct _IWDB *IWDB;
/**
* @brief Write ahead log (WAL) options.
*/
typedef struct IWKV_WAL_OPTS {
bool enabled; /**< WAL enabled */
bool check_crc_on_checkpoint; /**< Check CRC32 sum of data blocks during checkpoint. Default: false */
uint32_t savepoint_timeout_sec; /**< Savepoint timeout seconds. Default: 10 sec */
uint32_t checkpoint_timeout_sec; /**< Checkpoint timeout seconds. Default: 300 sec (5 min); */
size_t wal_buffer_sz; /**< WAL file intermediate buffer size. Default: 8Mb */
uint64_t checkpoint_buffer_sz; /**< Checkpoint buffer size in bytes. Default: 1Gb */
iwrc(*wal_lock_interceptor)(bool, void *);
/**< Optional function called
- before acquiring
- after releasing
exclusive database lock by WAL checkpoint thread.
In the case of `before lock` first argument will be set to true */
void *wal_lock_interceptor_opaque;/**< Opaque data for `wal_lock_interceptor` */
} IWKV_WAL_OPTS;
/**
* @brief IWKV storage open options.
*/
typedef struct IWKV_OPTS {
const char *path; /**< Path to database file */
uint32_t random_seed; /**< Random seed used for iwu random generator */
/**
* Database storage format version.
* Leave it as zero for the latest supported format.
* Used only for newly created databases,
*/
int32_t fmt_version;
iwkv_openflags oflags; /**< Bitmask of database file open modes */
bool file_lock_fail_fast; /**< Do not wait and raise error if database is locked by another process */
IWKV_WAL_OPTS wal; /**< WAL options */
} IWKV_OPTS;
/**
* @brief Data container for key/value.
*/
typedef struct IWKV_val {
void *data; /**< Data buffer */
size_t size; /**< Data buffer size */
/** Extra key part used for key comparison.
* If set to non zero and database is created with `IWDB_COMPOUND_KEYS` mode
* keys will behave as compound: `<key value><compound>` consisting of two parts.
* `compound` field ignored if db not in `IWDB_COMPOUND_KEYS` mode.
*/
int64_t compound;
} IWKV_val;
/**
* @brief Cursor opaque handler.
*/
struct _IWKV_cursor;
typedef struct _IWKV_cursor *IWKV_cursor;
/**
* @brief Database cursor operations and position flags.
*/
typedef enum IWKV_cursor_op {
IWKV_CURSOR_BEFORE_FIRST = 1, /**< Set cursor to position before first record */
IWKV_CURSOR_AFTER_LAST, /**< Set cursor to position after last record */
IWKV_CURSOR_NEXT, /**< Move cursor to the next record */
IWKV_CURSOR_PREV, /**< Move cursor to the previous record */
IWKV_CURSOR_EQ, /**< Set cursor to the specified key value */
IWKV_CURSOR_GE /**< Set cursor to the key which greater or equal key specified */
} IWKV_cursor_op;
/**
* @brief Initialize iwkv storage.
* @details This method must be called before using of any iwkv public API function.
* @note iwkv implicitly initialized by iw_init()
*/
IW_EXPORT WUR iwrc iwkv_init(void);
/**
* @brief Open iwkv storage.
* @code {.c}
* IWKV iwkv;
* IWKV_OPTS opts = {
* .path = "mystore.db"
* };
* iwrc rc = iwkv_open(&opts, &iwkv);
* @endcode
* @note Any opened iwkv storage must be closed by `iwkv_close()` after usage.
* @param opts Database open options.
* @param [out] iwkvp Pointer to @ref IWKV structure.
*/
IW_EXPORT WUR iwrc iwkv_open(const IWKV_OPTS *opts, IWKV *iwkvp);
/**
* @brief Get iwkv database handler identified by specified `dbid` number.
* @details In the case if no database matched `dbid`
* a new database will be created using specified function arguments.
*
* @note Database handler doesn't require to be explicitly closed or freed.
* Although it may be usefull to release database cache memory of unused databases
* dependening on memory requirements of your application by `iwkv_db_cache_release()`.
* @note Database `flags` argument must be same for all subsequent
* calls after first call for particular database,
* otherwise `IWKV_ERROR_INCOMPATIBLE_DB_MODE` will be reported.
*
* @param iwkv Pointer to @ref IWKV handler
* @param dbid Database identifier
* @param flags Database initialization flags
* @param [out] dbp Pointer to database opaque structure
*/
IW_EXPORT WUR iwrc iwkv_db(IWKV iwkv, uint32_t dbid, iwdb_flags_t flags, IWDB *dbp);
/**
* @brief Create new database with next available database id.
* @see iwrc iwkv_db()
*
* @param flags Database initialization flags
* @param [out] dbidp Database identifier placeholder will be filled with next available id.
* @param [out] dbp Pointer to database opaque structure
*/
IW_EXPORT WUR iwrc iwkv_new_db(IWKV iwkv, iwdb_flags_t dbflg, uint32_t *dbidp, IWDB *dbp);
/**
* @brief Frees memory resources used by database cache
* until to next database access operation (get/put/cursor).
* Typicaly it will free ~130Kb of memory per database in use.
*
* @param db Database handler
*/
IW_EXPORT iwrc iwkv_db_cache_release(IWDB db);
/**
* @brief Destroy(drop) existing database and cleanup all of its data.
*
* @param dbp Pointer to database opened.
*/
IW_EXPORT iwrc iwkv_db_destroy(IWDB *dbp);
/**
* @brief Sync iwkv storage state with disk.
*
* @note It will cause deadlock if current thread holds opened cursors and WAL is enabled,
* use method with caution.
*
* @param iwkv IWKV handler.
* @param flags Sync flags.
*/
IW_EXPORT iwrc iwkv_sync(IWKV iwkv, iwfs_sync_flags flags);
/**
* @brief Close iwkv storage.
* @details Upon successfull call of iwkv_close()
* no farther operations on storage or any of its databases are allowed.
*
* @param iwkvp
*/
IW_EXPORT iwrc iwkv_close(IWKV *iwkvp);
/**
* @brief Store record in database.
*
* iwkv_opflags opflags:
* - `IWKV_NO_OVERWRITE` If a key is already exists the `IWKV_ERROR_KEY_EXISTS` error will returned.
* - `IWKV_SYNC` Flush changes on disk after operation
*
* @note `iwkv_put()` adds a new value to sorted values array for existing keys if
* database created with `IWDB_DUP_UINT32_VALS`|`IWDB_DUP_UINT64_VALS` flags
*
* @param db Database handler
* @param key Key data container
* @param val Value data container
* @param opflags Put options used
*/
IW_EXPORT iwrc iwkv_put(IWDB db, const IWKV_val *key, const IWKV_val *val, iwkv_opflags opflags);
/**
* @brief Intercepts old(replaced) value in put operation.
* @note If `oldval` is not zero IWKV_PUT_HANDLER responsive for releasing it using iwkv_val_dispose()
* @warning Use `IWKV_PUT_HANDLER` with caution: mind deadlocks.
*
* @param key Key used in put operation
* @param val Value used in put operation
* @param oldval Old value which will be replaced by `val` may be `NULL`
* @param op Arbitrary opaqued data passed to this handler
*/
typedef iwrc(*IWKV_PUT_HANDLER)(const IWKV_val *key, const IWKV_val *val, IWKV_val *oldval, void *op);
/**
* @brief Store record in database.
* @see iwkv_put()
*/
IW_EXPORT iwrc iwkv_puth(IWDB db, const IWKV_val *key, const IWKV_val *val,
iwkv_opflags opflags, IWKV_PUT_HANDLER ph, void *phop);
/**
* @brief Get value for given `key`.
*
* @note If not matching record found `IWKV_ERROR_NOTFOUND` will be returned.
* @note On success a returned value must be freed with `iwkv_val_dispose()`
*
* @param db Database handler
* @param key Key data
* @param [out] oval Value associated with `key` or `NULL`
*/
IW_EXPORT iwrc iwkv_get(IWDB db, const IWKV_val *key, IWKV_val *oval);
/**
* @brief Get value for given `key` and copy it into provided `vbuf` using up to `vbufsz` bytes.
*
* @param db Database handler
* @param key Key data
* @param vbuf Pointer to value buffer
* @param vbufsz Value buffer size
* @param [out] vsz Actual value size
*/
IW_EXPORT iwrc iwkv_get_copy(IWDB db, const IWKV_val *key, void *vbuf, size_t vbufsz, size_t *vsz);
/**
* @brief Set arbitrary data associated with database.
* Database write lock will acquired for this operation.
*
* @param db Database handler
* @param buf Data buffer
* @param sz Size of data buffer
*/
IW_EXPORT iwrc iwkv_db_set_meta(IWDB db, void *buf, size_t sz);
/**
* @brief Get arbitrary data associated with database.
* @param db Database handler
* @param buf Output buffer
* @param sz Size of target buffer
* @param [out] rsz Number of bytes read actually
*/
IW_EXPORT iwrc iwkv_db_get_meta(IWDB db, void *buf, size_t sz, size_t *rsz);
/**
* @brief Remove record identified by `key`.
*
* Returns `IWKV_ERROR_NOTFOUND` is no matching key found
* @param db Database handler
* @param key Key data container
*/
IW_EXPORT iwrc iwkv_del(IWDB db, const IWKV_val *key, iwkv_opflags opflags);
/**
* @brief Destroy key/value data container.
*
*/
IW_EXPORT void iwkv_val_dispose(IWKV_val *kval);
/**
* @brief Dispose data containers for key and value respectively.
*
* @note This method is shortland of:
* @code {.c}
* iwkv_kv_dispose(key);
* iwkv_kv_dispose(val);
* @endcode
*
* @param key Key data containers
* @param val Value data containers
*/
IW_EXPORT void iwkv_kv_dispose(IWKV_val *key, IWKV_val *val);
/**
* @brief Open database cursor.
*
* @param db Database handler
* @param cur Pointer to an allocated cursor structure to be initialized
* @param op Cursor open mode/initial positions flags
* @param key Optional key argument, required to point cursor to the given key.
*/
IW_EXPORT WUR iwrc iwkv_cursor_open(IWDB db,
IWKV_cursor *cur,
IWKV_cursor_op op,
const IWKV_val *key);
/**
* @brief Move cursor to the next position.
*
* @param cur Opened cursor object
* @param op Cursor position operation
*/
IW_EXPORT WUR iwrc iwkv_cursor_to(IWKV_cursor cur, IWKV_cursor_op op);
/**
* @brief Move cursor to the next position.
*
* @param cur Opened cursor object
* @param op Cursor position operation
* @param key Optional key argument used to move cursor to the given key.
*/
IW_EXPORT WUR iwrc iwkv_cursor_to_key(IWKV_cursor cur, IWKV_cursor_op op, const IWKV_val *key);
/**
* @brief Get key and value at current cursor position.
* @note Data stored in okey/oval containers must be freed with `iwkv_val_dispose()`.
*
* @param cur Opened cursor object
* @param okey Key container to be initialized by key at current position. Can be null.
* @param oval Value container to be initialized by value at current position. Can be null.
*/
IW_EXPORT iwrc iwkv_cursor_get(IWKV_cursor cur, IWKV_val *okey, IWKV_val *oval);
/**
* @brief Get value at current cursor position.
* @note Data stored in `oval` container must be freed with `iwkv_val_dispose()`.
* @param cur Opened cursor object
* @param oval Value holder to be initialized by value at current position
*/
IW_EXPORT iwrc iwkv_cursor_val(IWKV_cursor cur, IWKV_val *oval);
/**
* @brief Copy value data to the specified buffer at the current cursor position.
* @note At most of `bufsz` bytes will be copied into `vbuf`.
*
* @param cur Opened cursor object
* @param vbuf Pointer to value buffer
* @param vbufsz Value buffer size
* @param [out] vsz Actual value size
*/
IW_EXPORT iwrc iwkv_cursor_copy_val(IWKV_cursor cur, void *vbuf, size_t vbufsz, size_t *vsz);
/**
* @brief Get key at current cursor position.
* @note Data stored in okey container must be freed with `iwkv_val_dispose()`.
*
* @param cur Opened cursor object
* @param oval Key holder to be initialized by key at current position
*/
IW_EXPORT iwrc iwkv_cursor_key(IWKV_cursor cur, IWKV_val *okey);
/**
* @brief Copy key data to the specified buffer at the current cursor position.
* @note At most of `bufsz` bytes will be copied into `kbuf`.
*
* @param cur Opened cursor object
* @param kbuf Pointer to value buffer, can be zero if kbufsz is zero too.
* @param kbufsz Key buffer size, cab be zero.
* @param [out] ksz Actual key size
* @param [out] compound Compound key part value, can be zero.
*/
IW_EXPORT iwrc iwkv_cursor_copy_key(IWKV_cursor cur, void *kbuf, size_t kbufsz, size_t *ksz, int64_t *compound);
IW_EXPORT iwrc iwkv_cursor_is_matched_key(IWKV_cursor cur, const IWKV_val *key, bool *ores, int64_t *ocompound);
/**
* @brief Set record value at current cursor position.
* @note This is equivalent to `iwkv_put()` operation.
*
* iwkv_opflags opflags:
* - `IWKV_NO_OVERWRITE` If a key is already exists the `IWKV_ERROR_KEY_EXISTS` error will returned.
* - `IWKV_SYNC` Flush changes on disk after operation
*
* @note `iwkv_cursor_set()` adds a new value to sorted values array for existing keys if
* database created with `IWDB_DUP_UINT32_VALS`|`IWDB_DUP_UINT64_VALS` flags
*
* @param cur Opened cursor object
* @param val Value holder
* @param opflags Update value mode
*/
IW_EXPORT iwrc iwkv_cursor_set(IWKV_cursor cur, IWKV_val *val, iwkv_opflags opflags);
IW_EXPORT iwrc iwkv_cursor_seth(IWKV_cursor cur, IWKV_val *val, iwkv_opflags opflags,
IWKV_PUT_HANDLER ph, void *phop);
/**
* @brief Remove record value at current cursor position.
* @param cur Opened cursor object
*/
IW_EXPORT iwrc iwkv_cursor_del(IWKV_cursor cur, iwkv_opflags opflags);
/**
* @brief Close cursor object.
* @param cur Opened cursor
*/
IW_EXPORT iwrc iwkv_cursor_close(IWKV_cursor *cur);
/**
* Creates an online database backup image and copies it into the specified `target_file`.
* During online backup phase read/write database operations are not
* blocked for significant amount of time. Backup finish time is
* placed into `ts` as number of milliseconds since epoch.
* Online backup guaranties what all records before `ts` timestamp will
* be stored in backup image. Later, online backup image can be
* opened as ordinary database file.
*
* @note In order to avoid deadlocks: close all opened database cursors
* before calling this method.
*
* @param iwkv
* @param [out] ts Backup completion timestamp
* @param target_file backup file path
*/
IW_EXPORT iwrc iwkv_online_backup(IWKV iwkv, uint64_t *ts, const char *target_file);
/**
* @brief Get database file status info.
* @note Database should be in opened state.
*
* @see IWFS_FILE::state
* @param db Database handler
* @param [out] out IWFS_FSM_STATE placeholder iwkv file state
*/
IW_EXPORT iwrc iwkv_state(IWKV iwkv, IWFS_FSM_STATE *out);
// Do not print random levels of skiplist blocks
#define IWKVD_PRINT_NO_LEVEVELS 0x1
// Print record values
#define IWKVD_PRINT_VALS 0x2
void iwkvd_db(FILE *f, IWDB db, int flags, int plvl);
IW_EXTERN_C_END
#endif
+451
View File
@@ -0,0 +1,451 @@
#pragma once
#ifndef IWKV_INTERNAL_H
#define IWKV_INTERNAL_H
#include "iwkv.h"
#include "iwlog.h"
#include "iwarr.h"
#include "iwutils.h"
#include "iwfsmfile.h"
#include "iwdlsnr.h"
#include "iwal.h"
#include "khash.h"
#include "ksort.h"
#include <pthread.h>
#include <stdatomic.h>
#include <unistd.h>
#include "iwcfg.h"
#if defined(__APPLE__) || defined(__ANDROID__)
#include "pthread_spin_lock_shim.h"
#endif
// IWKV magic number
#define IWKV_MAGIC 0x69776b76U
// IWKV backup magic number
#define IWKV_BACKUP_MAGIC 0xBACBAC69U
// IWKV file format version
#define IWKV_FORMAT 2
// IWDB magic number
#define IWDB_MAGIC 0x69776462U
#ifdef IW_32
// Max database file size on 32 bit systems: 2Gb
#define IWKV_MAX_DBSZ 0x7fffffff
#else
// Max database file size: ~512Gb
#define IWKV_MAX_DBSZ 0x7fffffff80ULL
#endif
// Size of KV fsm block as power of 2
#define IWKV_FSM_BPOW 7U
#define IWKV_FSM_ALLOC_FLAGS (IWFSM_ALLOC_NO_OVERALLOCATE | IWFSM_SOLID_ALLOCATED_SPACE | IWFSM_ALLOC_NO_STATS)
// Length of KV fsm header in bytes
#define KVHDRSZ 255U
// [u1:flags,lvl:u1,lkl:u1,pnum:u1,p0:u4,kblk:u4,[pi0:u1,... pi32],n0-n23:u4,lk:u116]:u256 // SBLK
// Maximum length of prefix key to compare for v2 formst
#define PREFIX_KEY_LEN_V1 116U
#define PREFIX_KEY_LEN_V2 115U
// Number of skip list levels
#define SLEVELS 24U
#define AANUM (2U * SLEVELS + 2 /* levels + (new block created) + (db block may be updated) */)
// Lower key length in SBLK
#define SBLK_LKLEN PREFIX_KEY_LEN_V2
// Size of database start block in bytes
#define DB_SZ (2U * (1U << IWKV_FSM_BPOW))
// Size of `SBLK` in bytes
#define SBLK_SZ (2U * (1U << IWKV_FSM_BPOW))
// Number of SBLK blocks in one page
#define SBLK_PAGE_SBLK_NUM_V2 16U
// Size of page with adjacent SBLK blocks. 4096
// Data format version: v2
#define SBLK_PAGE_SZ_V2 (SBLK_PAGE_SBLK_NUM_V2 * SBLK_SZ)
// Number of `KV` blocks in KVBLK
#define KVBLK_IDXNUM 32U
// Initial `KVBLK` size power of 2
#define KVBLK_INISZPOW 9U
// KVBLK header size: blen:u1,idxsz:u2
#define KVBLK_HDRSZ 3U
// Max kvp offset bytes
#define KVP_MAX_OFF_VLEN 8U
// Max kvp len 0xfffffffULL bytes
#define KVP_MAX_LEN_VLEN 5U
#define KVBLK_MAX_IDX_SZ ((KVP_MAX_OFF_VLEN + KVP_MAX_LEN_VLEN) * KVBLK_IDXNUM)
// Max non KV size [blen:u1,idxsz:u2,[ps1:vn,pl1:vn,...,ps63,pl63]
#define KVBLK_MAX_NKV_SZ (KVBLK_HDRSZ + KVBLK_MAX_IDX_SZ)
#define ADDR2BLK(addr_) ((blkn_t) (((uint64_t)(addr_)) >> IWKV_FSM_BPOW))
#define BLK2ADDR(blk_) (((uint64_t) (blk_)) << IWKV_FSM_BPOW)
struct _IWKV;
struct _IWDB;
typedef uint32_t blkn_t;
typedef uint32_t dbid_t;
/* Key/Value pair stored in `KVBLK` */
typedef struct KV {
size_t keysz;
size_t valsz;
uint8_t *key;
uint8_t *val;
} KV;
/* Ket/Value (KV) index: Offset and length. */
typedef struct KVP {
off_t off; /**< KV block offset relative to `end` of KVBLK */
uint32_t len; /**< Length of kv pair block */
uint8_t ridx; /**< Position of the actually persisted slot in `KVBLK` */
} KVP;
typedef uint8_t kvblk_flags_t;
#define KVBLK_DEFAULT ((kvblk_flags_t) 0x00U)
/** KVBLK data is durty and should be flushed to mm */
#define KVBLK_DURTY ((kvblk_flags_t) 0x01U)
typedef uint8_t kvblk_rmkv_opts_t;
#define RMKV_SYNC ((kvblk_rmkv_opts_t) 0x01U)
#define RMKV_NO_RESIZE ((kvblk_rmkv_opts_t) 0x02U)
typedef uint8_t sblk_flags_t;
/** The lowest `SBLK` key is fully contained in `SBLK`. Persistent flag. */
#define SBLK_FULL_LKEY ((sblk_flags_t) 0x01U)
/** This block is the start database block. */
#define SBLK_DB ((sblk_flags_t) 0x08U)
/** Block data changed, block marked as durty and needs to be persisted */
#define SBLK_DURTY ((sblk_flags_t) 0x10U)
/** Put this `SBLK` into dbcache */
#define SBLK_CACHE_PUT ((sblk_flags_t) 0x20U)
#define SBLK_CACHE_UPDATE ((sblk_flags_t) 0x40U)
#define SBLK_CACHE_REMOVE ((sblk_flags_t) 0x80U)
typedef uint8_t iwlctx_op_t;
/** Put key value operation */
#define IWLCTX_PUT ((iwlctx_op_t) 0x01U)
/** Delete key operation */
#define IWLCTX_DEL ((iwlctx_op_t) 0x01U)
/* KVBLK: [szpow:u1,idxsz:u2,[ps0:vn,pl0:vn,..., ps32,pl32]____[[KV],...]] */
typedef struct KVBLK {
IWDB db;
off_t addr; /**< Block address */
off_t maxoff; /**< Max pair offset */
uint16_t idxsz; /**< Size of KV pairs index in bytes */
int8_t zidx; /**< Index of first empty pair slot (zero index), or -1 */
uint8_t szpow; /**< Block size as power of 2 */
kvblk_flags_t flags; /**< Flags */
KVP pidx[KVBLK_IDXNUM]; /**< KV pairs index */
} KVBLK;
#define SBLK_PERSISTENT_FLAGS (SBLK_FULL_LKEY)
#define SBLK_CACHE_FLAGS (SBLK_CACHE_UPDATE | SBLK_CACHE_PUT | SBLK_CACHE_REMOVE)
// Number of top levels to cache (~ (1<<DBCACHE_LEVELS) cached elements)
#define DBCACHE_LEVELS 10U
// Minimal cached level
#define DBCACHE_MIN_LEVEL 5U
// Single allocation step - number of DBCNODEs
#define DBCACHE_ALLOC_STEP 32U
/** Cached SBLK node */
typedef struct DBCNODE {
blkn_t sblkn; /**< SBLK block number or used to store key size (to keep DBCNODE compact) */
blkn_t kblkn; /**< KVBLK block number */
uint8_t lkl; /**< Lower key length */
uint8_t fullkey; /**< SBLK is full key */
uint8_t k0idx; /**< KVBLK Zero KVP index */
uint8_t pad; /**< 1 byte pad */
uint8_t lk[1]; /**< Lower key buffer */
} DBCNODE;
#define DBCNODE_VNUM_SZ 24
#define DBCNODE_STR_SZ 128
static_assert(DBCNODE_VNUM_SZ >= offsetof(DBCNODE, lk) + IW_VNUMBUFSZ,
"DBCNODE_VNUM_SZ >= offsetof(DBCNODE, lk) + IW_VNUMBUFSZ");
static_assert(DBCNODE_STR_SZ >= offsetof(DBCNODE, lk) + SBLK_LKLEN,
"DBCNODE_STR_SZ >= offsetof(DBCNODE, lk) + SBLK_LKLEN");
/** Tallest SBLK nodes cache */
typedef struct DBCACHE {
size_t asize; /**< Size of allocated cache buffer */
size_t num; /**< Actual number of nodes */
size_t nsize; /**< Cached node size */
uint8_t lvl; /**< Lowes cached level */
bool open; /**< Is cache open */
DBCNODE *nodes; /**< Sorted nodes array */
} DBCACHE;
struct _IWKV_cursor;
/* Database: [magic:u4,dbflg:u1,dbid:u4,next_db_blk:u4,p0:u4,n[24]:u4,c[24]:u4]:209 */
struct _IWDB {
// SBH
IWDB db; /**< Database ref */
off_t addr; /**< Database block address */
sblk_flags_t flags; /**< Flags */
// !SBH
IWKV iwkv;
DBCACHE cache; /**< SBLK nodes cache */
pthread_rwlock_t rwl; /**< Database API RW lock */
pthread_spinlock_t cursors_slk; /**< Cursors set guard lock */
off_t next_db_addr; /**< Next IWDB addr */
struct _IWKV_cursor *cursors; /**< Active (currently in-use) database cursors */
struct _IWDB *next; /**< Next IWDB meta */
struct _IWDB *prev; /**< Prev IWDB meta */
dbid_t id; /**< Database ID */
volatile int32_t wk_count; /**< Number of active database workers */
blkn_t meta_blk; /**< Database meta block number */
blkn_t meta_blkn; /**< Database meta length (number of blocks) */
iwdb_flags_t dbflg; /**< Database specific flags */
atomic_bool open; /**< True if DB is in OPEN state */
volatile bool wk_pending_exclusive; /**< If true someone wants to acquire exclusive lock on IWDB */
uint32_t lcnt[SLEVELS]; /**< SBLK count per level */
};
/* Skiplist block: [u1:flags,lvl:u1,lkl:u1,pnum:u1,p0:u4,kblk:u4,[pi0:u1,... pi32],n0-n23:u4,lk:u116]:u256 // SBLK */
typedef struct SBLK {
// SBH
IWDB db; /**< Database ref */
off_t addr; /**< Block address */
sblk_flags_t flags; /**< Flags */
uint8_t lvl; /**< Skip list node level */
uint8_t bpos; /**< Position of SBLK in a page block starting with 1 (zero means SBLK deleted) */
blkn_t p0; /**< Prev node, if IWDB it is the last node */
blkn_t n[SLEVELS]; /**< Next nodes */
// !SBH
KVBLK *kvblk; /**< Associated KVBLK */
blkn_t kvblkn; /**< Associated KVBLK block number */
int8_t pnum; /**< Number of active kv indexes in `SBLK::pi` */
uint8_t lkl; /**< Lower key length within a buffer */
uint8_t pi[KVBLK_IDXNUM]; /**< Sorted KV slots, value is an index of kv slot in `KVBLK` */
uint8_t lk[PREFIX_KEY_LEN_V1]; /**< Lower key buffer */
} SBLK;
// -V:KHASH_MAP_INIT_INT:522
KHASH_MAP_INIT_INT(DBS, IWDB)
/** IWKV instance */
struct _IWKV {
IWFS_FSM fsm; /**< FSM pool */
pthread_rwlock_t rwl; /**< API RW lock */
iwrc fatalrc; /**< Fatal error occuried, no farther operations can be performed */
IWDB first_db; /**< First database in chain */
IWDB last_db; /**< Last database in chain */
IWDLSNR *dlsnr; /**< WAL data events listener */
khash_t(DBS) *dbs; /**< Database id -> IWDB mapping */
iwkv_openflags oflags; /**< Open flags */
pthread_cond_t wk_cond; /**< Workers cond variable */
pthread_mutex_t wk_mtx; /**< Workers cond mutext */
int32_t fmt_version; /**< Database format version */
int32_t pklen; /**< Prefix key length in use */
volatile int32_t wk_count; /**< Number of active workers */
volatile bool wk_pending_exclusive; /**< If true someone wants to acquire exclusive lock on IWKV */
atomic_bool open; /**< True if kvstore is in OPEN state */
};
/** Database lookup context */
typedef struct IWLCTX {
IWDB db;
const IWKV_val *key; /**< Search key */
IWKV_val *val; /**< Update value */
SBLK *lower; /**< Next to upper bound block */
SBLK *upper; /**< Upper bound block */
SBLK *nb; /**< New block */
off_t destroy_addr; /**< Block to destroy address */
off_t upper_addr; /**< Upper block address used in `_lx_del_lr()` */
#ifndef NDEBUG
uint32_t num_cmps;
#endif
iwkv_opflags opflags; /**< Operation flags */
sblk_flags_t sbflags; /**< `SBLK` flags applied to all new/looked blocks in this context */
iwlctx_op_t op; /**< Context operation */
uint8_t saan; /**< Position of next free `SBLK` element in the `saa` area */
uint8_t kaan; /**< Position of next free `KVBLK` element in the `kaa` area */
int8_t nlvl; /**< Level of new inserted/deleted `SBLK` node. -1 if no new node inserted/deleted */
int8_t cache_reload; /**< If true dbcache should be refreshed after operation */
IWKV_PUT_HANDLER ph; /**< Optional put handler */
void *phop; /**< Put handler opaque data */
SBLK *plower[SLEVELS]; /**< Pinned lower nodes per level */
SBLK *pupper[SLEVELS]; /**< Pinned upper nodes per level */
IWKV_val ekey;
SBLK dblk; /**< First database block */
SBLK saa[AANUM]; /**< `SBLK` allocation area */
KVBLK kaa[AANUM]; /**< `KVBLK` allocation area */
uint8_t nbuf[IW_VNUMBUFSZ];
uint8_t incbuf[8]; /**< Buffer used to store incremented/decremented values `IWKV_VAL_INCREMENT` opflag */
} IWLCTX;
/** Cursor context */
struct _IWKV_cursor {
uint8_t cnpos; /**< Position in the current `SBLK` node */
bool closed; /**< Cursor closed */
int8_t skip_next; /**< When to skip next IWKV_CURSOR_NEXT|IWKV_CURSOR_PREV cursor move
due to the side effect of `iwkv_cursor_del()` call.
If `skip_next > 0` `IWKV_CURSOR_NEXT` will be skipped
If `skip_next < 0` `IWKV_CURSOR_PREV` will be skipped */
SBLK *cn; /**< Current `SBLK` node */
struct _IWKV_cursor *next; /**< Next cursor in active db cursors chain */
off_t dbaddr; /**< Database address used as `cn` */
IWLCTX lx; /**< Lookup context */
};
#define ENSURE_OPEN(iwkv_) \
if (!(iwkv_) || !((iwkv_)->open)) return IW_ERROR_INVALID_STATE; \
if ((iwkv_)->fatalrc) return (iwkv_)->fatalrc
#define ENSURE_OPEN_DB(db_) \
if (!(db_) || !(db_)->iwkv || !(db_)->open || !((db_)->iwkv->open)) return IW_ERROR_INVALID_STATE
#define API_RLOCK(iwkv_, rci_) \
ENSURE_OPEN(iwkv_); \
(rci_) = pthread_rwlock_rdlock(&(iwkv_)->rwl); \
if (rci_) return iwrc_set_errno(IW_ERROR_THREADING_ERRNO, rci_)
IW_INLINE iwrc _api_rlock(IWKV iwkv) {
int rci;
API_RLOCK(iwkv, rci);
return 0;
}
#define API_WLOCK(iwkv_, rci_) \
ENSURE_OPEN(iwkv_); \
(rci_) = pthread_rwlock_wrlock(&(iwkv_)->rwl); \
if (rci_) return iwrc_set_errno(IW_ERROR_THREADING_ERRNO, rci_)
IW_INLINE iwrc _api_wlock(IWKV iwkv) {
int rci;
API_WLOCK(iwkv, rci);
return 0;
}
#define API_UNLOCK(iwkv_, rci_, rc_) \
rci_ = pthread_rwlock_unlock(&(iwkv_)->rwl); \
if (rci_) IWRC(iwrc_set_errno(IW_ERROR_THREADING_ERRNO, rci_), rc_)
#define API_DB_RLOCK(db_, rci_) \
do { \
API_RLOCK((db_)->iwkv, rci_); \
(rci_) = pthread_rwlock_rdlock(&(db_)->rwl); \
if (rci_) { \
pthread_rwlock_unlock(&(db_)->iwkv->rwl); \
return iwrc_set_errno(IW_ERROR_THREADING_ERRNO, rci_); \
} \
} while(0)
IW_INLINE iwrc _api_db_rlock(IWDB db) {
int rci;
API_DB_RLOCK(db, rci);
return 0;
}
#define API_DB_WLOCK(db_, rci_) \
do { \
API_RLOCK((db_)->iwkv, rci_); \
(rci_) = pthread_rwlock_wrlock(&(db_)->rwl); \
if (rci_) { \
pthread_rwlock_unlock(&(db_)->iwkv->rwl); \
return iwrc_set_errno(IW_ERROR_THREADING_ERRNO, rci_); \
} \
} while(0)
IW_INLINE iwrc _api_db_wlock(IWDB db) {
int rci;
API_DB_WLOCK(db, rci);
return 0;
}
#define API_DB_UNLOCK(db_, rci_, rc_) \
do { \
(rci_) = pthread_rwlock_unlock(&(db_)->rwl); \
if (rci_) IWRC(iwrc_set_errno(IW_ERROR_THREADING_ERRNO, rci_), rc_); \
API_UNLOCK((db_)->iwkv, rci_, rc_); \
} while(0)
#define AAPOS_INC(aan_) \
do { \
if ((aan_) < AANUM - 1) { \
(aan_) = (aan_) + 1; \
} else { \
(aan_) = 0; \
} \
} while(0)
// SBLK
// [flags:u1,lvl:u1,lkl:u1,pnum:u1,p0:u4,kblk:u4,pi:u1[32],n:u4[24],bpos:u1,lk:u115]:u256
#define SOFF_FLAGS_U1 0
#define SOFF_LVL_U1 (SOFF_FLAGS_U1 + 1)
#define SOFF_LKL_U1 (SOFF_LVL_U1 + 1)
#define SOFF_PNUM_U1 (SOFF_LKL_U1 + 1)
#define SOFF_P0_U4 (SOFF_PNUM_U1 + 1)
#define SOFF_KBLK_U4 (SOFF_P0_U4 + 4)
#define SOFF_PI0_U1 (SOFF_KBLK_U4 + 4)
#define SOFF_N0_U4 (SOFF_PI0_U1 + 1 * KVBLK_IDXNUM)
#define SOFF_BPOS_U1_V2 (SOFF_N0_U4 + 4 * SLEVELS)
#define SOFF_LK_V2 (SOFF_BPOS_U1_V2 + 1)
#define SOFF_LK_V1 (SOFF_N0_U4 + 4 * SLEVELS)
#define SOFF_END (SOFF_LK_V2 + SBLK_LKLEN)
static_assert(SOFF_END == 256, "SOFF_END == 256");
static_assert(SBLK_SZ >= SOFF_END, "SBLK_SZ >= SOFF_END");
// DB
// [magic:u4,dbflg:u1,dbid:u4,next_db_blk:u4,p0:u4,n[24]:u4,c[24]:u4,meta_blk:u4,meta_blkn:u4]:217
#define DOFF_MAGIC_U4 0
#define DOFF_DBFLG_U1 (DOFF_MAGIC_U4 + 4)
#define DOFF_DBID_U4 (DOFF_DBFLG_U1 + 1)
#define DOFF_NEXTDB_U4 (DOFF_DBID_U4 + 4)
#define DOFF_P0_U4 (DOFF_NEXTDB_U4 + 4)
#define DOFF_N0_U4 (DOFF_P0_U4 + 4)
#define DOFF_C0_U4 (DOFF_N0_U4 + 4 * SLEVELS)
#define DOFF_METABLK_U4 (DOFF_C0_U4 + 4 * SLEVELS)
#define DOFF_METABLKN_U4 (DOFF_METABLK_U4 + 4)
#define DOFF_END (DOFF_METABLKN_U4 + 4)
static_assert(DOFF_END == 217, "DOFF_END == 217");
static_assert(DB_SZ >= DOFF_END, "DB_SZ >= DOFF_END");
// KVBLK
// [szpow:u1,idxsz:u2,[ps1:vn,pl1:vn,...,ps32,pl32]____[[_KV],...]] // KVBLK
#define KBLK_SZPOW_OFF 0
iwrc iwkv_exclusive_lock(IWKV iwkv);
iwrc iwkv_exclusive_unlock(IWKV iwkv);
void iwkvd_trigger_xor(uint64_t val);
void iwkvd_kvblk(FILE *f, KVBLK *kb, int maxvlen);
iwrc iwkvd_sblk(FILE *f, IWLCTX *lx, SBLK *sb, int flags);
void iwkvd_db(FILE *f, IWDB db, int flags, int plvl);
// IWKVD Trigger commands
#ifdef IW_TESTS
#define IWKVD_WAL_NO_CHECKPOINT_ON_CLOSE 1UL
#endif
#endif
+1
View File
@@ -0,0 +1 @@
*w.ref eol=crlf
+30
View File
@@ -0,0 +1,30 @@
include_directories(${CUNIT_INCLUDE_DIRS})
set(TEST_DATA_DIR ${CMAKE_CURRENT_BINARY_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${TEST_DATA_DIR})
file(GLOB datafiles RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.ref" "*.data")
foreach(file ${datafiles})
configure_file("${file}" "${file}" COPYONLY)
endforeach()
foreach(TN IN ITEMS iwkv_test1
iwkv_test2
iwkv_test3
iwkv_test4
iwkv_test5
iwkv_test6
iwkv_test7
iwkv_test8
iwkv_test9
iwkv_test10
)
add_executable(${TN} ${TN}.c)
target_link_libraries(${TN} iowow_s ${CUNIT_LIBRARIES})
set_target_properties(${TN} PROPERTIES
COMPILE_FLAGS "-DIW_STATIC")
add_test(NAME ${TN} WORKING_DIRECTORY ${TEST_DATA_DIR}
COMMAND ${TEST_TOOL_CMD} $<TARGET_FILE:${TN}>)
endforeach()
Binary file not shown.
+940
View File
@@ -0,0 +1,940 @@
#include "iwkv.h"
#include "iwlog.h"
#include "iwutils.h"
#include "iwcfg.h"
#include "iwkv_tests.h"
#define KBUFSZ 128
#define VBUFSZ 128
char kbuf[KBUFSZ];
char vbuf[VBUFSZ];
extern int8_t iwkv_next_level;
static int logstage(FILE *f, const char *name, IWDB db) {
int rci = fprintf(f, "\n#### Stage: %s\n", name);
iwkvd_db(f, db, IWKVD_PRINT_NO_LEVEVELS | IWKVD_PRINT_VALS, 0);
fflush(f);
return rci < 0 ? rci : 0;
}
static int logstage2(FILE *f, const char *name, IWDB db) {
int rci = fprintf(f, "\n#### Stage: %s\n", name);
iwkvd_db(f, db, IWKVD_PRINT_NO_LEVEVELS | IWKVD_PRINT_VALS, 0);
fflush(f);
return rci < 0 ? rci : 0;
}
int init_suite() {
iwrc rc = iwkv_init();
return rc;
}
int clean_suite() {
return 0;
}
// Test5 staff
struct Test5DUP1 {
bool _mv;
bool _1v;
bool _10v;
};
static int64_t _test5dup5visitor(uint64_t dv, int64_t idx, void *op) {
CU_ASSERT_PTR_NOT_NULL_FATAL(op);
struct Test5DUP1 *s = op;
switch (dv) {
case -1ULL:
s->_mv = true;
break;
case 1ULL:
s->_1v = true;
break;
case 10ULL:
s->_10v = true;
break;
default:
CU_FAIL("Invalid dup value");
break;
}
return 1;
}
// Test Slides
static void iwkv_test3_impl(int fmt_version) {
FILE *f = fmt_version > 1 ? fopen("iwkv_test1_3_v2.log", "w+") : fopen("iwkv_test1_3.log", "w+");
CU_ASSERT_PTR_NOT_NULL(f);
iwrc rc;
IWKV_val key = {0};
IWKV_val val = {0};
IWKV iwkv;
IWDB db1;
IWKV_OPTS opts = {
.path = "iwkv_test1_3.db",
.oflags = IWKV_TRUNC,
.fmt_version = fmt_version
};
rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 1, 0, &db1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
for (int i = -23, c = 0; i <= 23; ++i) {
for (int j = 0; j < 63; ++j, ++c) {
iwkv_next_level = i < 0 ? -i : i;
snprintf(kbuf, KBUFSZ, "%05dkkk", c);
snprintf(vbuf, VBUFSZ, "%05dval", c);
key.data = kbuf;
key.size = strlen(key.data);
val.data = vbuf;
val.size = strlen(val.data);
rc = iwkv_put(db1, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
}
// middle
// 23 \ | / 23
// \ | /
// 0 \__|__/ 0
iwkv_next_level = 23;
// put: 01858aaa in order to split middle zero sblk
snprintf(kbuf, KBUFSZ, "%05daaa", 1858);
snprintf(vbuf, VBUFSZ, "%05dval", 1858);
rc = iwkv_put(db1, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
logstage2(f, "iwkv_test3", db1);
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
// Compare logs with referenced
#ifndef _WIN32
FILE *r = fmt_version > 1 ? fopen("iwkv_test1_3_v2.ref", "r+") : fopen("iwkv_test1_3.ref", "r+");
#else
FILE *r = fmt_version > 1 ? fopen("iwkv_test1_3w_v2.ref", "r+") : fopen("iwkv_test1_3w.ref", "r+");
#endif
CU_ASSERT_PTR_NOT_NULL(r);
int rci = cmp_files(r, f);
CU_ASSERT_EQUAL_FATAL(rci, 0);
fclose(f);
fclose(r);
}
static void iwkv_test3_v1() {
iwkv_test3_impl(1);
}
static void iwkv_test3_v2() {
iwkv_test3_impl(2);
}
static void iwkv_test2_impl(int fmt_version) {
FILE *f = fmt_version > 1 ? fopen("iwkv_test1_2_v2.log", "w+") : fopen("iwkv_test1_2.log", "w+");
CU_ASSERT_PTR_NOT_NULL(f);
iwrc rc;
IWKV_val key = {0};
IWKV_val val = {0};
IWKV iwkv;
IWDB db1;
IWKV_OPTS opts = {
.path = "iwkv_test1_2.db",
.oflags = IWKV_TRUNC,
.fmt_version = fmt_version
};
rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 1, 0, &db1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
for (int i = 252 * 2; i >= 0; --i) { // 189
snprintf(kbuf, KBUFSZ, "%03dkkk", i);
snprintf(vbuf, VBUFSZ, "%03dval", i);
key.data = kbuf;
key.size = strlen(key.data);
val.data = vbuf;
val.size = strlen(val.data);
rc = iwkv_put(db1, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
logstage(f, "desc sorted keys inserted", db1);
for (int i = 0; i <= 252 * 2; ++i) {
int cret;
snprintf(kbuf, KBUFSZ, "%03dkkk", i);
snprintf(vbuf, VBUFSZ, "%03dval", i);
int vsize = strlen(vbuf);
key.data = kbuf;
key.size = strlen(key.data);
rc = iwkv_get(db1, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc, 0);
IW_CMP(cret, vbuf, vsize, val.data, val.size);
CU_ASSERT_EQUAL_FATAL(cret, 0);
iwkv_kv_dispose(0, &val);
}
// snprintf(kbuf, KBUFSZ, "%03dkkk", 64);
// key.data = kbuf;
// key.size = strlen(key.data);
// rc = iwkv_del(db1, &key);
// CU_ASSERT_EQUAL_FATAL(rc, 0);
// logstage(f, "removed 064kkk", db1);
//
//
// snprintf(kbuf, KBUFSZ, "%03dkkk", 126);
// key.data = kbuf;
// key.size = strlen(key.data);
// rc = iwkv_del(db1, &key);
// CU_ASSERT_EQUAL_FATAL(rc, 0);
// logstage(f, "removed 126kkk", db1);
//
//
// // Now delete more than half of block records
// // 126
// for (int i = 64; i <= 99; ++i) {
// snprintf(kbuf, KBUFSZ, "%03dkkk", i);
// key.data = kbuf;
// key.size = strlen(key.data);
// rc = iwkv_del(db1, &key);
// if (i == 64) {
// CU_ASSERT_EQUAL(rc, IWKV_ERROR_NOTFOUND);
// rc = 0;
// continue;
// }
// CU_ASSERT_EQUAL_FATAL(rc, 0);
// }
// logstage(f, "removed 065kkk - 099kkk", db1); // 125
//
// for (int i = 100; i <= 125; ++i) {
// snprintf(kbuf, KBUFSZ, "%03dkkk", i);
// key.data = kbuf;
// key.size = strlen(key.data);
// rc = iwkv_del(db1, &key);
// CU_ASSERT_EQUAL_FATAL(rc, 0);
// }
// logstage(f, "removed all keys in SBLK[54]", db1); // 125
rc = iwkv_db_destroy(&db1); // Destroy DB and remove all db blocks
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
// Reopen DB then check db1
rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 1, 0, &db1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
logstage(f, "db1 destroyed", db1);
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
// Compare logs with referenced
#ifndef _WIN32
FILE *r = fmt_version > 1 ? fopen("iwkv_test1_2_v2.ref", "r+") : fopen("iwkv_test1_2.ref", "r+");
#else
FILE *r = fmt_version > 1 ? fopen("iwkv_test1_2w_v2.ref", "r+") : fopen("iwkv_test1_2w.ref", "r+");
#endif
CU_ASSERT_PTR_NOT_NULL(r);
int rci = cmp_files(r, f);
CU_ASSERT_EQUAL_FATAL(rci, 0);
fclose(f);
fclose(r);
}
static void iwkv_test2_v1() {
iwkv_test2_impl(1);
}
static void iwkv_test2_v2() {
iwkv_test2_impl(2);
}
static void iwkv_test1_impl(int fmt_version) {
FILE *f = fmt_version > 1 ? fopen("iwkv_test1_1_v2.log", "w+") : fopen("iwkv_test1_1.log", "w+");
CU_ASSERT_PTR_NOT_NULL(f);
char buf[128];
size_t vsize;
IWKV_OPTS opts = {
.path = "iwkv_test1.db",
.oflags = IWKV_TRUNC,
.fmt_version = fmt_version
};
// Test open/close
IWKV iwkv;
IWDB db1, db2, db3;
iwrc rc;
IWKV_val key = {.data = "foo"};
key.size = strlen(key.data);
IWKV_val val = {.data = "bar"};
val.size = strlen(val.data);
rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
// Test open/close existing db
opts.oflags = 0;
rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
// Test create/destroy db
rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 1, 0, &db1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 2, 0, &db2); // destroyed
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 3, 0, &db3);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db_destroy(&db2); // destroyed
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
// Test one in read-only mode
opts.oflags = IWKV_RDONLY;
opts.path = "not-existing.db";
rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_TRUE_FATAL(rc);
iwrc_strip_errno(&rc);
#ifdef _WIN32
iwrc_strip_werror(&rc);
#endif
CU_ASSERT_EQUAL(rc, IW_ERROR_NOT_EXISTS);
// Open in read-only mode and acquire not existing db
opts.path = "iwkv_test1.db";
rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 2, 0, &db2);
CU_ASSERT_EQUAL(rc, IW_ERROR_READONLY);
rc = iwkv_db(iwkv, 1, 0, &db1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 3, 0, &db3);
CU_ASSERT_EQUAL_FATAL(rc, 0);
logstage(f, "empty db", db1);
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
// Open in write mode, then put a simple kv
opts.oflags = 0;
rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 1, 0, &db1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
// iwkv_next_level = 3;
rc = iwkv_put(db1, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
logstage(f, "put foo:bar", db1);
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
// Open db and get out single record
rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 1, 0, &db1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
val.size = 0;
val.data = 0;
rc = iwkv_get(db1, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_NSTRING_EQUAL(key.data, "foo", key.size);
CU_ASSERT_NSTRING_EQUAL(val.data, "bar", val.size);
iwkv_kv_dispose(0, &val);
rc = iwkv_get_copy(db1, &key, buf, sizeof(buf), &vsize);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL(3, vsize);
CU_ASSERT_NSTRING_EQUAL(buf, "bar", vsize);
rc = iwkv_get_copy(db1, &key, buf, 1, &vsize);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL(3, vsize);
CU_ASSERT_NSTRING_EQUAL(buf, "b", 1);
// put foo->bazzz
key.data = "foo";
key.size = strlen(key.data);
val.data = "bazzz";
val.size = strlen(val.data);
rc = iwkv_put(db1, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
// put foo->zzz with IWKV_NO_OVERWRITE
val.data = "zzz";
val.size = strlen(val.data);
rc = iwkv_put(db1, &key, &val, IWKV_NO_OVERWRITE);
CU_ASSERT_EQUAL_FATAL(rc, IWKV_ERROR_KEY_EXISTS);
rc = iwkv_get(db1, &key, &val);
CU_ASSERT_NSTRING_EQUAL(key.data, "foo", key.size);
CU_ASSERT_NSTRING_EQUAL(val.data, "bazzz", val.size);
iwkv_kv_dispose(0, &val);
logstage(f, "put foo:bazz", db1);
// put foo->''
val.data = "";
val.size = strlen(val.data);
rc = iwkv_put(db1, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_get(db1, &key, &val);
CU_ASSERT_NSTRING_EQUAL(key.data, "foo", key.size);
CU_ASSERT_NSTRING_EQUAL(val.data, "", val.size);
iwkv_kv_dispose(0, &val);
logstage(f, "put foo:", db1);
val.data = "bar";
val.size = strlen(val.data);
rc = iwkv_put(db1, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_get(db1, &key, &val);
CU_ASSERT_NSTRING_EQUAL(key.data, "foo", key.size);
CU_ASSERT_NSTRING_EQUAL(val.data, "bar", val.size);
iwkv_kv_dispose(0, &val);
logstage(f, "put foo:bar", db1);
// remove key/value
rc = iwkv_del(db1, &key, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_get(db1, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc, IWKV_ERROR_NOTFOUND);
logstage(f, "remove foo:bar", db1);
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 1, 0, &db1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_get(db1, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc, IWKV_ERROR_NOTFOUND);
// iwkv_next_level = 0;
for (int i = 0; i < 127 * 2; i += 2) {
snprintf(kbuf, KBUFSZ, "%03dkkk", i);
snprintf(vbuf, VBUFSZ, "%03dval", i);
key.data = kbuf;
key.size = strlen(key.data);
val.data = vbuf;
val.size = strlen(val.data);
rc = iwkv_put(db1, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
logstage(f, "fill up first block", db1);
// iwkv_next_level = 0;
for (int i = 0; i < 127 * 2; i += 2) {
snprintf(kbuf, KBUFSZ, "%03dkkk", i);
snprintf(vbuf, VBUFSZ, "%03dval", i);
key.data = kbuf;
key.size = strlen(key.data);
rc = iwkv_get(db1, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL_FATAL(strncmp(val.data, vbuf, val.size), 0);
iwkv_kv_dispose(0, &val);
}
for (int i = 1; i < 127 * 2; i += 2) {
snprintf(kbuf, KBUFSZ, "%03dkkk", i);
snprintf(vbuf, VBUFSZ, "%03dval", i);
key.data = kbuf;
key.size = strlen(key.data);
val.data = vbuf;
val.size = strlen(val.data);
//logstage(stderr, "!!!!!!", db1);
rc = iwkv_put(db1, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
//logstage(stderr, "??????", db1);
}
logstage(f, "fill up second block", db1);
// Check basic cursor operations
IWKV_cursor cur1;
rc = iwkv_cursor_open(db1, &cur1, IWKV_CURSOR_BEFORE_FIRST, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_cursor_to(cur1, IWKV_CURSOR_PREV);
CU_ASSERT_EQUAL(rc, IWKV_ERROR_NOTFOUND);
rc = iwkv_cursor_close(&cur1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_cursor_open(db1, &cur1, IWKV_CURSOR_AFTER_LAST, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_cursor_get(cur1, &key, &val);
CU_ASSERT_EQUAL(rc, IWKV_ERROR_NOTFOUND);
rc = iwkv_cursor_to(cur1, IWKV_CURSOR_NEXT);
CU_ASSERT_EQUAL(rc, IWKV_ERROR_NOTFOUND);
rc = iwkv_cursor_close(&cur1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_cursor_open(db1, &cur1, IWKV_CURSOR_AFTER_LAST, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_cursor_to(cur1, IWKV_CURSOR_PREV);
CU_ASSERT_EQUAL_FATAL(rc, 0);
int i = 0;
do {
IWKV_val key;
IWKV_val val;
iwrc rc2 = iwkv_cursor_get(cur1, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc2, 0);
snprintf(kbuf, KBUFSZ, "%03dkkk", i);
snprintf(vbuf, VBUFSZ, "%03dval", i);
CU_ASSERT_EQUAL(strncmp(key.data, kbuf, key.size), 0);
CU_ASSERT_EQUAL(strncmp(val.data, vbuf, val.size), 0);
iwkv_kv_dispose(&key, &val);
if (i == 2) {
rc2 = iwkv_cursor_to(cur1, IWKV_CURSOR_PREV);
CU_ASSERT_EQUAL_FATAL(rc2, 0);
rc2 = iwkv_cursor_get(cur1, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc2, 0);
snprintf(kbuf, KBUFSZ, "%03dkkk", i + 1);
snprintf(vbuf, VBUFSZ, "%03dval", i + 1);
CU_ASSERT_EQUAL(strncmp(key.data, kbuf, key.size), 0);
CU_ASSERT_EQUAL(strncmp(val.data, vbuf, val.size), 0);
rc2 = iwkv_cursor_to(cur1, IWKV_CURSOR_NEXT);
CU_ASSERT_EQUAL_FATAL(rc2, 0);
iwkv_kv_dispose(&key, &val);
}
++i;
} while (!(rc = iwkv_cursor_to(cur1, IWKV_CURSOR_PREV)));
CU_ASSERT_EQUAL(rc, IWKV_ERROR_NOTFOUND);
rc = iwkv_cursor_close(&cur1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
--i;
rc = iwkv_cursor_open(db1, &cur1, IWKV_CURSOR_BEFORE_FIRST, 0);
while (!(rc = iwkv_cursor_to(cur1, IWKV_CURSOR_NEXT))) {
IWKV_val key;
IWKV_val val;
iwrc rc2 = iwkv_cursor_get(cur1, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc2, 0);
snprintf(kbuf, KBUFSZ, "%03dkkk", i);
snprintf(vbuf, VBUFSZ, "%03dval", i);
--i;
CU_ASSERT_EQUAL(strncmp(key.data, kbuf, key.size), 0);
CU_ASSERT_EQUAL(strncmp(val.data, vbuf, val.size), 0);
iwkv_kv_dispose(&key, &val);
}
CU_ASSERT_EQUAL(rc, IWKV_ERROR_NOTFOUND);
rc = iwkv_cursor_close(&cur1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
// Set cursor to key
do {
IWKV_val key;
IWKV_val val;
snprintf(kbuf, KBUFSZ, "%03dkkk", 30);
snprintf(vbuf, VBUFSZ, "%03dval", 30);
key.data = kbuf;
key.size = strlen(kbuf);
rc = iwkv_cursor_open(db1, &cur1, IWKV_CURSOR_EQ, &key);
CU_ASSERT_EQUAL_FATAL(rc, 0);
iwrc rc2 = iwkv_cursor_get(cur1, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc2, 0);
CU_ASSERT_EQUAL(strncmp(key.data, kbuf, key.size), 0);
CU_ASSERT_EQUAL(strncmp(val.data, vbuf, val.size), 0);
iwkv_kv_dispose(&key, &val);
// Move to GE 000
snprintf(kbuf, KBUFSZ, "%03d", 0);
snprintf(vbuf, VBUFSZ, "%03dval", 0);
key.data = kbuf;
key.size = strlen(kbuf);
rc2 = iwkv_cursor_to_key(cur1, IWKV_CURSOR_GE, &key);
if (rc2) {
iwlog_ecode_error3(rc2);
}
CU_ASSERT_EQUAL_FATAL(rc2, 0);
rc2 = iwkv_cursor_get(cur1, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc2, 0);
snprintf(kbuf, KBUFSZ, "%03dkkk", 0);
snprintf(vbuf, VBUFSZ, "%03dval", 0);
CU_ASSERT_EQUAL(strncmp(key.data, kbuf, key.size), 0);
CU_ASSERT_EQUAL(strncmp(val.data, vbuf, val.size), 0);
iwkv_kv_dispose(&key, &val);
// Move to EQ 000
snprintf(kbuf, KBUFSZ, "%03d", 0);
snprintf(vbuf, VBUFSZ, "%03dval", 0);
key.data = kbuf;
key.size = strlen(kbuf);
rc2 = iwkv_cursor_to_key(cur1, IWKV_CURSOR_EQ, &key);
CU_ASSERT_EQUAL(rc2, IWKV_ERROR_NOTFOUND);
rc = iwkv_cursor_close(&cur1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
} while (0);
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 1, 0, &db1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
logstage(f, "state after reopen", db1);
// Put a big key
snprintf(kbuf, KBUFSZ, "abracadabrabracadabrabracadabrabracadabrabracadabrabracadabrabracadabr1");
key.size = strlen(kbuf);
snprintf(vbuf, VBUFSZ, "vabracadabrabracadabrabracadabrabracadabrabracadabrabracadabrabracadabr");
val.size = strlen(vbuf);
rc = iwkv_db(iwkv, 1, 0, &db1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_put(db1, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_get(db1, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL_FATAL(strncmp(val.data, vbuf, val.size), 0);
iwkv_kv_dispose(0, &val);
logstage(f, "a big key", db1);
// 061kkk:061val
// Set value with cursor
snprintf(kbuf, KBUFSZ, "%03dkkk", 61);
snprintf(vbuf, VBUFSZ, "%03dval2", 61);
key.data = kbuf;
key.size = strlen(kbuf);
val.data = vbuf;
val.size = strlen(vbuf);
// Cursor set
rc = iwkv_cursor_open(db1, &cur1, IWKV_CURSOR_EQ, &key);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_cursor_set(cur1, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
key.data = 0;
val.data = 0;
rc = iwkv_cursor_get(cur1, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL(strncmp(key.data, kbuf, key.size), 0);
CU_ASSERT_EQUAL(strncmp(val.data, vbuf, val.size), 0);
iwkv_kv_dispose(&key, &val);
rc = iwkv_cursor_close(&cur1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
// Set in write mode
snprintf(kbuf, KBUFSZ, "%03dkkk", 61);
snprintf(vbuf, VBUFSZ, "%03dval3", 61);
key.data = kbuf;
key.size = strlen(kbuf);
val.data = vbuf;
val.size = strlen(vbuf);
rc = iwkv_cursor_open(db1, &cur1, IWKV_CURSOR_EQ, &key);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_cursor_set(cur1, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
key.data = 0;
val.data = 0;
rc = iwkv_cursor_get(cur1, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL(strncmp(key.data, kbuf, key.size), 0);
CU_ASSERT_EQUAL(strncmp(val.data, vbuf, val.size), 0);
iwkv_kv_dispose(&key, &val);
rc = iwkv_cursor_close(&cur1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
// Compare logs with referenced
#ifndef _WIN32
FILE *r = fmt_version > 1 ? fopen("iwkv_test1_1_v2.ref", "r+") : fopen("iwkv_test1_1.ref", "r+");
#else
FILE *r = fmt_version > 1 ? fopen("iwkv_test1_1w_v2.ref", "r+") : fopen("iwkv_test1_1w.ref", "r+");
#endif
CU_ASSERT_PTR_NOT_NULL_FATAL(r);
int rci = cmp_files(r, f);
CU_ASSERT_EQUAL_FATAL(rci, 0);
fclose(r);
fclose(f);
}
static void iwkv_test1_v1() {
iwkv_test1_impl(1);
}
static void iwkv_test1_v2() {
iwkv_test1_impl(2);
}
static void iwkv_test8_impl(int fmt_version) {
IWKV_OPTS opts = {
.path = "iwkv_test1_8.db",
.oflags = IWKV_TRUNC,
.fmt_version = fmt_version
};
IWKV iwkv;
IWDB db1;
IWKV_cursor cur;
IWKV_val key;
IWKV_val val = {
.data = "foo",
.size = sizeof("foo") - 1
};
IWKV_val oval;
size_t ksz;
uint64_t llv = 1;
uint64_t llv2;
iwrc rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 1, IWDB_VNUM64_KEYS, &db1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
key.data = &llv;
key.size = sizeof(llv);
rc = iwkv_put(db1, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_get(db1, &key, &oval);
CU_ASSERT_EQUAL_FATAL(rc, 0);
iwkv_val_dispose(&oval);
llv = 0xffffffffffffffe;
key.data = &llv;
rc = iwkv_put(db1, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_get(db1, &key, &oval);
CU_ASSERT_EQUAL_FATAL(rc, 0);
iwkv_val_dispose(&oval);
rc = iwkv_get_copy(db1, &key, &llv2, sizeof(llv2), &ksz);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_cursor_open(db1, &cur, IWKV_CURSOR_EQ, &key);
CU_ASSERT_EQUAL_FATAL(rc, 0);
llv = 0xffffffffffffffffULL;
rc = iwkv_put(db1, &key, &val, 0);
CU_ASSERT_EQUAL(rc, IW_ERROR_OVERFLOW);
llv = 0;
int64_t compound;
rc = iwkv_cursor_copy_key(cur, &llv, sizeof(llv), &ksz, &compound);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL(llv, 0xffffffffffffffe);
llv = 0;
rc = iwkv_cursor_get(cur, &oval, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL_FATAL(oval.size, sizeof(llv));
memcpy(&llv, oval.data, sizeof(llv));
CU_ASSERT_EQUAL(llv, 0xffffffffffffffe);
iwkv_val_dispose(&oval);
rc = iwkv_cursor_to(cur, IWKV_CURSOR_NEXT);
CU_ASSERT_EQUAL_FATAL(rc, 0);
llv = 0;
rc = iwkv_cursor_copy_key(cur, &llv, sizeof(llv), &ksz, &compound);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL(llv, 1);
iwkv_cursor_close(&cur);
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
static void iwkv_test8_v1() {
iwkv_test1_impl(1);
}
static void iwkv_test8_v2() {
iwkv_test1_impl(2);
}
static void iwkv_test7_impl(int fmt_version) {
IWKV_OPTS opts = {
.path = "iwkv_test1_7.db",
.oflags = IWKV_TRUNC,
.fmt_version = fmt_version
};
IWKV iwkv;
IWDB db1;
IWKV_val key, val;
int64_t llv;
key.data = "foo";
key.size = strlen(key.data);
iwrc rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 1, 0, &db1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
llv = 1;
val.data = &llv;
val.size = sizeof(llv);
rc = iwkv_put(db1, &key, &val, IWKV_VAL_INCREMENT);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_put(db1, &key, &val, IWKV_VAL_INCREMENT);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_put(db1, &key, &val, IWKV_VAL_INCREMENT);
CU_ASSERT_EQUAL_FATAL(rc, 0);
llv = 0;
val.data = 0;
val.size = 0;
rc = iwkv_get(db1, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL_FATAL(val.size, sizeof(llv));
memcpy(&llv, val.data, sizeof(llv));
llv = IW_ITOHLL(llv);
CU_ASSERT_EQUAL(llv, 3);
iwkv_val_dispose(&val);
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
static void iwkv_test7_v1() {
iwkv_test7_impl(1) ;
}
static void iwkv_test7_v2() {
iwkv_test7_impl(2) ;
}
static void iwkv_test6_impl(int fmt_version) {
IWKV_OPTS opts = {
.path = "iwkv_test1_6.db",
.oflags = IWKV_TRUNC,
.fmt_version = fmt_version
};
const int vbsiz = 1000 * 1000;
// Test open/close
char kbuf[100];
char *vbuf = malloc(vbsiz);
IWKV iwkv;
IWDB db1;
IWKV_val key, val;
iwrc rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 1, 0, &db1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
key.data = kbuf;
val.data = vbuf;
val.size = vbsiz;
for (int i = 0; i < 20; ++i) {
memset(vbuf, ' ' + i + 1, vbsiz);
snprintf(kbuf, sizeof(kbuf), "%016d", i);
key.size = strlen(kbuf);
rc = iwkv_put(db1, &key, &val, 0);
if (rc) {
iwlog_ecode_error3(rc);
}
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
free(vbuf);
}
static void iwkv_test6_v1() {
iwkv_test6_impl(1);
}
static void iwkv_test6_v2() {
iwkv_test6_impl(2);
}
static void iwkv_test9(void) {
IWKV_OPTS opts = {
.path = "garbage.data",
};
// Test open/close
IWKV iwkv;
iwrc rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL(rc, IWFS_ERROR_INVALID_FILEMETA);
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL(rc, IW_ERROR_INVALID_STATE);
}
int main() {
CU_pSuite pSuite = NULL;
/* Initialize the CUnit test registry */
if (CUE_SUCCESS != CU_initialize_registry()) return CU_get_error();
/* Add a suite to the registry */
pSuite = CU_add_suite("iwkv_test1", init_suite, clean_suite);
if (NULL == pSuite) {
CU_cleanup_registry();
return CU_get_error();
}
/* Add the tests to the suite */
if (
(NULL == CU_add_test(pSuite, "iwkv_test1_v1", iwkv_test1_v1)) ||
(NULL == CU_add_test(pSuite, "iwkv_test1_v2", iwkv_test1_v2)) ||
(NULL == CU_add_test(pSuite, "iwkv_test2_v1", iwkv_test2_v1)) ||
(NULL == CU_add_test(pSuite, "iwkv_test2_v2", iwkv_test2_v2)) ||
(NULL == CU_add_test(pSuite, "iwkv_test3_v1", iwkv_test3_v1)) ||
(NULL == CU_add_test(pSuite, "iwkv_test3_v2", iwkv_test3_v2)) ||
//- (NULL == CU_add_test(pSuite, "iwkv_test4", iwkv_test4)) ||
//- (NULL == CU_add_test(pSuite, "iwkv_test5", iwkv_test5)) ||
(NULL == CU_add_test(pSuite, "iwkv_test6_v1", iwkv_test6_v1)) ||
(NULL == CU_add_test(pSuite, "iwkv_test6_v2", iwkv_test6_v2)) ||
(NULL == CU_add_test(pSuite, "iwkv_test7_v1", iwkv_test7_v1)) ||
(NULL == CU_add_test(pSuite, "iwkv_test7_v2", iwkv_test7_v2)) ||
(NULL == CU_add_test(pSuite, "iwkv_test8_v1", iwkv_test8_v1)) ||
(NULL == CU_add_test(pSuite, "iwkv_test8_v2", iwkv_test8_v2)) ||
(NULL == CU_add_test(pSuite, "iwkv_test9", iwkv_test9))
) {
CU_cleanup_registry();
return CU_get_error();
}
/* Run all tests using the CUnit Basic interface */
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
int ret = CU_get_error() || CU_get_number_of_failures();
CU_cleanup_registry();
return ret;
}
+147
View File
@@ -0,0 +1,147 @@
#include "iwkv.h"
#include "iwlog.h"
#include "iwutils.h"
#include "iwkv_tests.h"
#include "iwkv_internal.h"
#include "iwth.h"
#define KBUFSZ 1024
#define VBUFSZ 1024
static char kbuf[KBUFSZ];
static char vbuf[VBUFSZ];
int init_suite(void) {
return iwkv_init();
}
int clean_suite(void) {
return 0;
}
static void iwkv_test10_1_impl(int fmt_version) {
IWKV iwkv;
IWKV_OPTS opts = {
.path = fmt_version > 1 ? "iwkv_test10_1_v2.db" : "iwkv_test10_1_v1.db",
.oflags = IWKV_TRUNC,
.wal = {
.enabled = true
}
};
iwrc rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
for (int i = 0; i < 1024; ++i) {
IWDB db;
rc = iwkv_db(iwkv, i, 0, &db);
CU_ASSERT_EQUAL_FATAL(rc, 0);
for (int j = 0; j < 1024; ++j) {
IWKV_val key, val;
snprintf(kbuf, KBUFSZ, "%d", j);
snprintf(vbuf, VBUFSZ, "%03dval", j);
key.data = kbuf;
key.size = strlen(key.data);
val.data = vbuf;
val.size = strlen(val.data);
rc = iwkv_put(db, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
}
for (int i = 0; i < 1024; ++i) {
if ((i % 2)) {
IWDB db;
rc = iwkv_db(iwkv, i, 0, &db);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db_destroy(&db);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
}
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
opts.oflags = 0;
rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
for (int i = 0; i < 1024; ++i) {
if (!(i % 2)) {
IWDB db;
rc = iwkv_db(iwkv, i, 0, &db);
CU_ASSERT_EQUAL_FATAL(rc, 0);
for (int j = 0; j < 1024; ++j) {
IWKV_val key, val;
int cret = 0;
snprintf(kbuf, KBUFSZ, "%d", j);
snprintf(vbuf, VBUFSZ, "%03dval", j);
key.data = kbuf;
key.size = strlen(key.data);
int vlen = strlen(vbuf);
rc = iwkv_get(db, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc, 0);
IW_CMP(cret, vbuf, vlen, val.data, val.size);
CU_ASSERT_EQUAL_FATAL(cret, 0);
iwkv_val_dispose(&val);
}
}
}
for (int i = 0; i < 1024; ++i) {
if (!(i % 2)) {
IWDB db;
rc = iwkv_db(iwkv, i, 0, &db);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db_destroy(&db);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
}
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
// IWP_FILE_STAT fs;
// rc = iwp_fstat(opts.path, &fs);
// CU_ASSERT_EQUAL_FATAL(rc, 0);
// CU_ASSERT_TRUE(fs.size < 1024 * 1024);
}
static void iwkv_test10_1_v1() {
iwkv_test10_1_impl(1);
}
static void iwkv_test10_1_v2() {
iwkv_test10_1_impl(2);
}
int main() {
CU_pSuite pSuite = NULL;
/* Initialize the CUnit test registry */
if (CUE_SUCCESS != CU_initialize_registry()) return CU_get_error();
/* Add a suite to the registry */
pSuite = CU_add_suite("iwkv_test8", init_suite, clean_suite);
if (NULL == pSuite) {
CU_cleanup_registry();
return CU_get_error();
}
/* Add the tests to the suite */
if (
(NULL == CU_add_test(pSuite, "iwkv_test10_1_v1", iwkv_test10_1_v1)) ||
(NULL == CU_add_test(pSuite, "iwkv_test10_1_v2", iwkv_test10_1_v2))
) {
CU_cleanup_registry();
return CU_get_error();
}
/* Run all tests using the CUnit Basic interface */
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
int ret = CU_get_error() || CU_get_number_of_failures();
CU_cleanup_registry();
return ret;
}
+528
View File
@@ -0,0 +1,528 @@
#### Stage: empty db
== DB[1] lvl=-1, blk=3, dbflg=0, p0=3
#### Stage: put foo:bar
== DB[1] lvl=-1, blk=3, dbflg=0, p0=9
=== SBLK[9] lvl=-1, pnum=1, flg=1, kvzidx=1, p0=3, db=1
=== SBLK[9] szpow=9, lkl=3, lk=foo
=== SBLK[9] [000,000] foo:bar
#### Stage: put foo:bazz
== DB[1] lvl=-1, blk=3, dbflg=0, p0=9
=== SBLK[9] lvl=-1, pnum=1, flg=1, kvzidx=1, p0=3, db=1
=== SBLK[9] szpow=9, lkl=3, lk=foo
=== SBLK[9] [000,000] foo:bazzz
#### Stage: put foo:
== DB[1] lvl=-1, blk=3, dbflg=0, p0=9
=== SBLK[9] lvl=-1, pnum=1, flg=1, kvzidx=1, p0=3, db=1
=== SBLK[9] szpow=9, lkl=3, lk=foo
=== SBLK[9] [000,000] foo:
#### Stage: put foo:bar
== DB[1] lvl=-1, blk=3, dbflg=0, p0=9
=== SBLK[9] lvl=-1, pnum=1, flg=1, kvzidx=1, p0=3, db=1
=== SBLK[9] szpow=9, lkl=3, lk=foo
=== SBLK[9] [000,000] foo:bar
#### Stage: remove foo:bar
== DB[1] lvl=-1, blk=3, dbflg=0, p0=3
#### Stage: fill up first block
== DB[1] lvl=-1, blk=3, dbflg=0, p0=9
=== SBLK[64] lvl=-1, pnum=31, flg=1, kvzidx=31, p0=3, db=1
=== SBLK[64] szpow=9, lkl=6, lk=252kkk
=== SBLK[64] [000,030] 252kkk:252val [001,029] 250kkk:250val [002,028] 248kkk:248val
=== SBLK[64] [003,027] 246kkk:246val [004,026] 244kkk:244val [005,025] 242kkk:242val
=== SBLK[64] [006,024] 240kkk:240val [007,023] 238kkk:238val [008,022] 236kkk:236val
=== SBLK[64] [009,021] 234kkk:234val [010,020] 232kkk:232val [011,019] 230kkk:230val
=== SBLK[64] [012,018] 228kkk:228val [013,017] 226kkk:226val [014,016] 224kkk:224val
=== SBLK[64] [015,015] 222kkk:222val [016,014] 220kkk:220val [017,013] 218kkk:218val
=== SBLK[64] [018,012] 216kkk:216val [019,011] 214kkk:214val [020,010] 212kkk:212val
=== SBLK[64] [021,009] 210kkk:210val [022,008] 208kkk:208val [023,007] 206kkk:206val
=== SBLK[64] [024,006] 204kkk:204val [025,005] 202kkk:202val [026,004] 200kkk:200val
=== SBLK[64] [027,003] 198kkk:198val [028,002] 196kkk:196val [029,001] 194kkk:194val
=== SBLK[64] [030,000] 192kkk:192val
=== SBLK[21] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=64, db=1
=== SBLK[21] szpow=9, lkl=6, lk=190kkk
=== SBLK[21] [000,031] 190kkk:190val [001,030] 188kkk:188val [002,029] 186kkk:186val
=== SBLK[21] [003,028] 184kkk:184val [004,027] 182kkk:182val [005,026] 180kkk:180val
=== SBLK[21] [006,025] 178kkk:178val [007,024] 176kkk:176val [008,023] 174kkk:174val
=== SBLK[21] [009,022] 172kkk:172val [010,021] 170kkk:170val [011,020] 168kkk:168val
=== SBLK[21] [012,019] 166kkk:166val [013,018] 164kkk:164val [014,017] 162kkk:162val
=== SBLK[21] [015,016] 160kkk:160val [016,015] 158kkk:158val [017,014] 156kkk:156val
=== SBLK[21] [018,013] 154kkk:154val [019,012] 152kkk:152val [020,011] 150kkk:150val
=== SBLK[21] [021,010] 148kkk:148val [022,009] 146kkk:146val [023,008] 144kkk:144val
=== SBLK[21] [024,007] 142kkk:142val [025,006] 140kkk:140val [026,005] 138kkk:138val
=== SBLK[21] [027,004] 136kkk:136val [028,003] 134kkk:134val [029,002] 132kkk:132val
=== SBLK[21] [030,001] 130kkk:130val [031,000] 128kkk:128val
=== SBLK[15] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=21, db=1
=== SBLK[15] szpow=9, lkl=6, lk=126kkk
=== SBLK[15] [000,031] 126kkk:126val [001,030] 124kkk:124val [002,029] 122kkk:122val
=== SBLK[15] [003,028] 120kkk:120val [004,027] 118kkk:118val [005,026] 116kkk:116val
=== SBLK[15] [006,025] 114kkk:114val [007,024] 112kkk:112val [008,023] 110kkk:110val
=== SBLK[15] [009,022] 108kkk:108val [010,021] 106kkk:106val [011,020] 104kkk:104val
=== SBLK[15] [012,019] 102kkk:102val [013,018] 100kkk:100val [014,017] 098kkk:098val
=== SBLK[15] [015,016] 096kkk:096val [016,015] 094kkk:094val [017,014] 092kkk:092val
=== SBLK[15] [018,013] 090kkk:090val [019,012] 088kkk:088val [020,011] 086kkk:086val
=== SBLK[15] [021,010] 084kkk:084val [022,009] 082kkk:082val [023,008] 080kkk:080val
=== SBLK[15] [024,007] 078kkk:078val [025,006] 076kkk:076val [026,005] 074kkk:074val
=== SBLK[15] [027,004] 072kkk:072val [028,003] 070kkk:070val [029,002] 068kkk:068val
=== SBLK[15] [030,001] 066kkk:066val [031,000] 064kkk:064val
=== SBLK[9] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=15, db=1
=== SBLK[9] szpow=9, lkl=6, lk=062kkk
=== SBLK[9] [000,031] 062kkk:062val [001,030] 060kkk:060val [002,029] 058kkk:058val
=== SBLK[9] [003,028] 056kkk:056val [004,027] 054kkk:054val [005,026] 052kkk:052val
=== SBLK[9] [006,025] 050kkk:050val [007,024] 048kkk:048val [008,023] 046kkk:046val
=== SBLK[9] [009,022] 044kkk:044val [010,021] 042kkk:042val [011,020] 040kkk:040val
=== SBLK[9] [012,019] 038kkk:038val [013,018] 036kkk:036val [014,017] 034kkk:034val
=== SBLK[9] [015,016] 032kkk:032val [016,015] 030kkk:030val [017,014] 028kkk:028val
=== SBLK[9] [018,013] 026kkk:026val [019,012] 024kkk:024val [020,011] 022kkk:022val
=== SBLK[9] [021,010] 020kkk:020val [022,009] 018kkk:018val [023,008] 016kkk:016val
=== SBLK[9] [024,007] 014kkk:014val [025,006] 012kkk:012val [026,005] 010kkk:010val
=== SBLK[9] [027,004] 008kkk:008val [028,003] 006kkk:006val [029,002] 004kkk:004val
=== SBLK[9] [030,001] 002kkk:002val [031,000] 000kkk:000val
#### Stage: fill up second block
== DB[1] lvl=-1, blk=3, dbflg=0, p0=70
=== SBLK[64] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=3, db=1
=== SBLK[64] szpow=9, lkl=6, lk=253kkk
=== SBLK[64] [000,002] 253kkk:253val [001,030] 252kkk:252val [002,001] 251kkk:251val
=== SBLK[64] [003,029] 250kkk:250val [004,000] 249kkk:249val [005,028] 248kkk:248val
=== SBLK[64] [006,031] 247kkk:247val [007,027] 246kkk:246val [008,013] 245kkk:245val
=== SBLK[64] [009,026] 244kkk:244val [010,012] 243kkk:243val [011,025] 242kkk:242val
=== SBLK[64] [012,011] 241kkk:241val [013,024] 240kkk:240val [014,010] 239kkk:239val
=== SBLK[64] [015,023] 238kkk:238val [016,009] 237kkk:237val [017,022] 236kkk:236val
=== SBLK[64] [018,008] 235kkk:235val [019,021] 234kkk:234val
=== SBLK[140] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=64, db=1
=== SBLK[140] szpow=10, lkl=6, lk=233kkk
=== SBLK[140] [000,000] 233kkk:233val [001,001] 232kkk:232val [002,002] 231kkk:231val
=== SBLK[140] [003,003] 230kkk:230val [004,004] 229kkk:229val [005,005] 228kkk:228val
=== SBLK[140] [006,006] 227kkk:227val [007,007] 226kkk:226val [008,008] 225kkk:225val
=== SBLK[140] [009,009] 224kkk:224val [010,010] 223kkk:223val [011,011] 222kkk:222val
=== SBLK[140] [012,012] 221kkk:221val [013,013] 220kkk:220val [014,014] 219kkk:219val
=== SBLK[130] lvl=-1, pnum=28, flg=1, kvzidx=28, p0=140, db=1
=== SBLK[130] szpow=10, lkl=6, lk=218kkk
=== SBLK[130] [000,000] 218kkk:218val [001,027] 217kkk:217val [002,001] 216kkk:216val
=== SBLK[130] [003,026] 215kkk:215val [004,002] 214kkk:214val [005,025] 213kkk:213val
=== SBLK[130] [006,003] 212kkk:212val [007,024] 211kkk:211val [008,004] 210kkk:210val
=== SBLK[130] [009,023] 209kkk:209val [010,005] 208kkk:208val [011,022] 207kkk:207val
=== SBLK[130] [012,006] 206kkk:206val [013,021] 205kkk:205val [014,007] 204kkk:204val
=== SBLK[130] [015,020] 203kkk:203val [016,008] 202kkk:202val [017,019] 201kkk:201val
=== SBLK[130] [018,009] 200kkk:200val [019,018] 199kkk:199val [020,010] 198kkk:198val
=== SBLK[130] [021,017] 197kkk:197val [022,011] 196kkk:196val [023,016] 195kkk:195val
=== SBLK[130] [024,012] 194kkk:194val [025,015] 193kkk:193val [026,013] 192kkk:192val
=== SBLK[130] [027,014] 191kkk:191val
=== SBLK[21] lvl=-1, pnum=19, flg=1, kvzidx=2, p0=130, db=1
=== SBLK[21] szpow=9, lkl=6, lk=190kkk
=== SBLK[21] [000,031] 190kkk:190val [001,001] 189kkk:189val [002,030] 188kkk:188val
=== SBLK[21] [003,000] 187kkk:187val [004,029] 186kkk:186val [005,014] 185kkk:185val
=== SBLK[21] [006,028] 184kkk:184val [007,013] 183kkk:183val [008,027] 182kkk:182val
=== SBLK[21] [009,012] 181kkk:181val [010,026] 180kkk:180val [011,011] 179kkk:179val
=== SBLK[21] [012,025] 178kkk:178val [013,010] 177kkk:177val [014,024] 176kkk:176val
=== SBLK[21] [015,009] 175kkk:175val [016,023] 174kkk:174val [017,008] 173kkk:173val
=== SBLK[21] [018,022] 172kkk:172val
=== SBLK[120] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=21, db=1
=== SBLK[120] szpow=10, lkl=6, lk=171kkk
=== SBLK[120] [000,000] 171kkk:171val [001,001] 170kkk:170val [002,002] 169kkk:169val
=== SBLK[120] [003,003] 168kkk:168val [004,004] 167kkk:167val [005,005] 166kkk:166val
=== SBLK[120] [006,006] 165kkk:165val [007,007] 164kkk:164val [008,008] 163kkk:163val
=== SBLK[120] [009,009] 162kkk:162val [010,010] 161kkk:161val [011,011] 160kkk:160val
=== SBLK[120] [012,012] 159kkk:159val [013,013] 158kkk:158val [014,014] 157kkk:157val
=== SBLK[110] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=120, db=1
=== SBLK[110] szpow=10, lkl=6, lk=156kkk
=== SBLK[110] [000,000] 156kkk:156val [001,028] 155kkk:155val [002,001] 154kkk:154val
=== SBLK[110] [003,027] 153kkk:153val [004,002] 152kkk:152val [005,026] 151kkk:151val
=== SBLK[110] [006,003] 150kkk:150val [007,025] 149kkk:149val [008,004] 148kkk:148val
=== SBLK[110] [009,024] 147kkk:147val [010,005] 146kkk:146val [011,023] 145kkk:145val
=== SBLK[110] [012,006] 144kkk:144val [013,022] 143kkk:143val [014,007] 142kkk:142val
=== SBLK[110] [015,021] 141kkk:141val [016,008] 140kkk:140val [017,020] 139kkk:139val
=== SBLK[110] [018,009] 138kkk:138val [019,019] 137kkk:137val [020,010] 136kkk:136val
=== SBLK[110] [021,018] 135kkk:135val [022,011] 134kkk:134val [023,017] 133kkk:133val
=== SBLK[110] [024,012] 132kkk:132val [025,016] 131kkk:131val [026,013] 130kkk:130val
=== SBLK[110] [027,015] 129kkk:129val [028,014] 128kkk:128val
=== SBLK[15] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=110, db=1
=== SBLK[15] szpow=9, lkl=6, lk=127kkk
=== SBLK[15] [000,002] 127kkk:127val [001,031] 126kkk:126val [002,001] 125kkk:125val
=== SBLK[15] [003,030] 124kkk:124val [004,000] 123kkk:123val [005,029] 122kkk:122val
=== SBLK[15] [006,014] 121kkk:121val [007,028] 120kkk:120val [008,013] 119kkk:119val
=== SBLK[15] [009,027] 118kkk:118val [010,012] 117kkk:117val [011,026] 116kkk:116val
=== SBLK[15] [012,011] 115kkk:115val [013,025] 114kkk:114val [014,010] 113kkk:113val
=== SBLK[15] [015,024] 112kkk:112val [016,009] 111kkk:111val [017,023] 110kkk:110val
=== SBLK[15] [018,008] 109kkk:109val [019,022] 108kkk:108val
=== SBLK[100] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=15, db=1
=== SBLK[100] szpow=10, lkl=6, lk=107kkk
=== SBLK[100] [000,000] 107kkk:107val [001,001] 106kkk:106val [002,002] 105kkk:105val
=== SBLK[100] [003,003] 104kkk:104val [004,004] 103kkk:103val [005,005] 102kkk:102val
=== SBLK[100] [006,006] 101kkk:101val [007,007] 100kkk:100val [008,008] 099kkk:099val
=== SBLK[100] [009,009] 098kkk:098val [010,010] 097kkk:097val [011,011] 096kkk:096val
=== SBLK[100] [012,012] 095kkk:095val [013,013] 094kkk:094val [014,014] 093kkk:093val
=== SBLK[90] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=100, db=1
=== SBLK[90] szpow=10, lkl=6, lk=092kkk
=== SBLK[90] [000,000] 092kkk:092val [001,028] 091kkk:091val [002,001] 090kkk:090val
=== SBLK[90] [003,027] 089kkk:089val [004,002] 088kkk:088val [005,026] 087kkk:087val
=== SBLK[90] [006,003] 086kkk:086val [007,025] 085kkk:085val [008,004] 084kkk:084val
=== SBLK[90] [009,024] 083kkk:083val [010,005] 082kkk:082val [011,023] 081kkk:081val
=== SBLK[90] [012,006] 080kkk:080val [013,022] 079kkk:079val [014,007] 078kkk:078val
=== SBLK[90] [015,021] 077kkk:077val [016,008] 076kkk:076val [017,020] 075kkk:075val
=== SBLK[90] [018,009] 074kkk:074val [019,019] 073kkk:073val [020,010] 072kkk:072val
=== SBLK[90] [021,018] 071kkk:071val [022,011] 070kkk:070val [023,017] 069kkk:069val
=== SBLK[90] [024,012] 068kkk:068val [025,016] 067kkk:067val [026,013] 066kkk:066val
=== SBLK[90] [027,015] 065kkk:065val [028,014] 064kkk:064val
=== SBLK[9] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=90, db=1
=== SBLK[9] szpow=9, lkl=6, lk=063kkk
=== SBLK[9] [000,002] 063kkk:063val [001,031] 062kkk:062val [002,001] 061kkk:061val
=== SBLK[9] [003,030] 060kkk:060val [004,000] 059kkk:059val [005,029] 058kkk:058val
=== SBLK[9] [006,014] 057kkk:057val [007,028] 056kkk:056val [008,013] 055kkk:055val
=== SBLK[9] [009,027] 054kkk:054val [010,012] 053kkk:053val [011,026] 052kkk:052val
=== SBLK[9] [012,011] 051kkk:051val [013,025] 050kkk:050val [014,010] 049kkk:049val
=== SBLK[9] [015,024] 048kkk:048val [016,009] 047kkk:047val [017,023] 046kkk:046val
=== SBLK[9] [018,008] 045kkk:045val [019,022] 044kkk:044val
=== SBLK[80] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=9, db=1
=== SBLK[80] szpow=10, lkl=6, lk=043kkk
=== SBLK[80] [000,000] 043kkk:043val [001,001] 042kkk:042val [002,002] 041kkk:041val
=== SBLK[80] [003,003] 040kkk:040val [004,004] 039kkk:039val [005,005] 038kkk:038val
=== SBLK[80] [006,006] 037kkk:037val [007,007] 036kkk:036val [008,008] 035kkk:035val
=== SBLK[80] [009,009] 034kkk:034val [010,010] 033kkk:033val [011,011] 032kkk:032val
=== SBLK[80] [012,012] 031kkk:031val [013,013] 030kkk:030val [014,014] 029kkk:029val
=== SBLK[70] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=80, db=1
=== SBLK[70] szpow=10, lkl=6, lk=028kkk
=== SBLK[70] [000,000] 028kkk:028val [001,028] 027kkk:027val [002,001] 026kkk:026val
=== SBLK[70] [003,027] 025kkk:025val [004,002] 024kkk:024val [005,026] 023kkk:023val
=== SBLK[70] [006,003] 022kkk:022val [007,025] 021kkk:021val [008,004] 020kkk:020val
=== SBLK[70] [009,024] 019kkk:019val [010,005] 018kkk:018val [011,023] 017kkk:017val
=== SBLK[70] [012,006] 016kkk:016val [013,022] 015kkk:015val [014,007] 014kkk:014val
=== SBLK[70] [015,021] 013kkk:013val [016,008] 012kkk:012val [017,020] 011kkk:011val
=== SBLK[70] [018,009] 010kkk:010val [019,019] 009kkk:009val [020,010] 008kkk:008val
=== SBLK[70] [021,018] 007kkk:007val [022,011] 006kkk:006val [023,017] 005kkk:005val
=== SBLK[70] [024,012] 004kkk:004val [025,016] 003kkk:003val [026,013] 002kkk:002val
=== SBLK[70] [027,015] 001kkk:001val [028,014] 000kkk:000val
#### Stage: state after reopen
== DB[1] lvl=-1, blk=3, dbflg=0, p0=70
=== SBLK[64] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=3, db=1
=== SBLK[64] szpow=9, lkl=6, lk=253kkk
=== SBLK[64] [000,002] 253kkk:253val [001,030] 252kkk:252val [002,001] 251kkk:251val
=== SBLK[64] [003,029] 250kkk:250val [004,000] 249kkk:249val [005,028] 248kkk:248val
=== SBLK[64] [006,031] 247kkk:247val [007,027] 246kkk:246val [008,013] 245kkk:245val
=== SBLK[64] [009,026] 244kkk:244val [010,012] 243kkk:243val [011,025] 242kkk:242val
=== SBLK[64] [012,011] 241kkk:241val [013,024] 240kkk:240val [014,010] 239kkk:239val
=== SBLK[64] [015,023] 238kkk:238val [016,009] 237kkk:237val [017,022] 236kkk:236val
=== SBLK[64] [018,008] 235kkk:235val [019,021] 234kkk:234val
=== SBLK[140] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=64, db=1
=== SBLK[140] szpow=10, lkl=6, lk=233kkk
=== SBLK[140] [000,000] 233kkk:233val [001,001] 232kkk:232val [002,002] 231kkk:231val
=== SBLK[140] [003,003] 230kkk:230val [004,004] 229kkk:229val [005,005] 228kkk:228val
=== SBLK[140] [006,006] 227kkk:227val [007,007] 226kkk:226val [008,008] 225kkk:225val
=== SBLK[140] [009,009] 224kkk:224val [010,010] 223kkk:223val [011,011] 222kkk:222val
=== SBLK[140] [012,012] 221kkk:221val [013,013] 220kkk:220val [014,014] 219kkk:219val
=== SBLK[130] lvl=-1, pnum=28, flg=1, kvzidx=28, p0=140, db=1
=== SBLK[130] szpow=10, lkl=6, lk=218kkk
=== SBLK[130] [000,000] 218kkk:218val [001,027] 217kkk:217val [002,001] 216kkk:216val
=== SBLK[130] [003,026] 215kkk:215val [004,002] 214kkk:214val [005,025] 213kkk:213val
=== SBLK[130] [006,003] 212kkk:212val [007,024] 211kkk:211val [008,004] 210kkk:210val
=== SBLK[130] [009,023] 209kkk:209val [010,005] 208kkk:208val [011,022] 207kkk:207val
=== SBLK[130] [012,006] 206kkk:206val [013,021] 205kkk:205val [014,007] 204kkk:204val
=== SBLK[130] [015,020] 203kkk:203val [016,008] 202kkk:202val [017,019] 201kkk:201val
=== SBLK[130] [018,009] 200kkk:200val [019,018] 199kkk:199val [020,010] 198kkk:198val
=== SBLK[130] [021,017] 197kkk:197val [022,011] 196kkk:196val [023,016] 195kkk:195val
=== SBLK[130] [024,012] 194kkk:194val [025,015] 193kkk:193val [026,013] 192kkk:192val
=== SBLK[130] [027,014] 191kkk:191val
=== SBLK[21] lvl=-1, pnum=19, flg=1, kvzidx=2, p0=130, db=1
=== SBLK[21] szpow=9, lkl=6, lk=190kkk
=== SBLK[21] [000,031] 190kkk:190val [001,001] 189kkk:189val [002,030] 188kkk:188val
=== SBLK[21] [003,000] 187kkk:187val [004,029] 186kkk:186val [005,014] 185kkk:185val
=== SBLK[21] [006,028] 184kkk:184val [007,013] 183kkk:183val [008,027] 182kkk:182val
=== SBLK[21] [009,012] 181kkk:181val [010,026] 180kkk:180val [011,011] 179kkk:179val
=== SBLK[21] [012,025] 178kkk:178val [013,010] 177kkk:177val [014,024] 176kkk:176val
=== SBLK[21] [015,009] 175kkk:175val [016,023] 174kkk:174val [017,008] 173kkk:173val
=== SBLK[21] [018,022] 172kkk:172val
=== SBLK[120] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=21, db=1
=== SBLK[120] szpow=10, lkl=6, lk=171kkk
=== SBLK[120] [000,000] 171kkk:171val [001,001] 170kkk:170val [002,002] 169kkk:169val
=== SBLK[120] [003,003] 168kkk:168val [004,004] 167kkk:167val [005,005] 166kkk:166val
=== SBLK[120] [006,006] 165kkk:165val [007,007] 164kkk:164val [008,008] 163kkk:163val
=== SBLK[120] [009,009] 162kkk:162val [010,010] 161kkk:161val [011,011] 160kkk:160val
=== SBLK[120] [012,012] 159kkk:159val [013,013] 158kkk:158val [014,014] 157kkk:157val
=== SBLK[110] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=120, db=1
=== SBLK[110] szpow=10, lkl=6, lk=156kkk
=== SBLK[110] [000,000] 156kkk:156val [001,028] 155kkk:155val [002,001] 154kkk:154val
=== SBLK[110] [003,027] 153kkk:153val [004,002] 152kkk:152val [005,026] 151kkk:151val
=== SBLK[110] [006,003] 150kkk:150val [007,025] 149kkk:149val [008,004] 148kkk:148val
=== SBLK[110] [009,024] 147kkk:147val [010,005] 146kkk:146val [011,023] 145kkk:145val
=== SBLK[110] [012,006] 144kkk:144val [013,022] 143kkk:143val [014,007] 142kkk:142val
=== SBLK[110] [015,021] 141kkk:141val [016,008] 140kkk:140val [017,020] 139kkk:139val
=== SBLK[110] [018,009] 138kkk:138val [019,019] 137kkk:137val [020,010] 136kkk:136val
=== SBLK[110] [021,018] 135kkk:135val [022,011] 134kkk:134val [023,017] 133kkk:133val
=== SBLK[110] [024,012] 132kkk:132val [025,016] 131kkk:131val [026,013] 130kkk:130val
=== SBLK[110] [027,015] 129kkk:129val [028,014] 128kkk:128val
=== SBLK[15] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=110, db=1
=== SBLK[15] szpow=9, lkl=6, lk=127kkk
=== SBLK[15] [000,002] 127kkk:127val [001,031] 126kkk:126val [002,001] 125kkk:125val
=== SBLK[15] [003,030] 124kkk:124val [004,000] 123kkk:123val [005,029] 122kkk:122val
=== SBLK[15] [006,014] 121kkk:121val [007,028] 120kkk:120val [008,013] 119kkk:119val
=== SBLK[15] [009,027] 118kkk:118val [010,012] 117kkk:117val [011,026] 116kkk:116val
=== SBLK[15] [012,011] 115kkk:115val [013,025] 114kkk:114val [014,010] 113kkk:113val
=== SBLK[15] [015,024] 112kkk:112val [016,009] 111kkk:111val [017,023] 110kkk:110val
=== SBLK[15] [018,008] 109kkk:109val [019,022] 108kkk:108val
=== SBLK[100] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=15, db=1
=== SBLK[100] szpow=10, lkl=6, lk=107kkk
=== SBLK[100] [000,000] 107kkk:107val [001,001] 106kkk:106val [002,002] 105kkk:105val
=== SBLK[100] [003,003] 104kkk:104val [004,004] 103kkk:103val [005,005] 102kkk:102val
=== SBLK[100] [006,006] 101kkk:101val [007,007] 100kkk:100val [008,008] 099kkk:099val
=== SBLK[100] [009,009] 098kkk:098val [010,010] 097kkk:097val [011,011] 096kkk:096val
=== SBLK[100] [012,012] 095kkk:095val [013,013] 094kkk:094val [014,014] 093kkk:093val
=== SBLK[90] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=100, db=1
=== SBLK[90] szpow=10, lkl=6, lk=092kkk
=== SBLK[90] [000,000] 092kkk:092val [001,028] 091kkk:091val [002,001] 090kkk:090val
=== SBLK[90] [003,027] 089kkk:089val [004,002] 088kkk:088val [005,026] 087kkk:087val
=== SBLK[90] [006,003] 086kkk:086val [007,025] 085kkk:085val [008,004] 084kkk:084val
=== SBLK[90] [009,024] 083kkk:083val [010,005] 082kkk:082val [011,023] 081kkk:081val
=== SBLK[90] [012,006] 080kkk:080val [013,022] 079kkk:079val [014,007] 078kkk:078val
=== SBLK[90] [015,021] 077kkk:077val [016,008] 076kkk:076val [017,020] 075kkk:075val
=== SBLK[90] [018,009] 074kkk:074val [019,019] 073kkk:073val [020,010] 072kkk:072val
=== SBLK[90] [021,018] 071kkk:071val [022,011] 070kkk:070val [023,017] 069kkk:069val
=== SBLK[90] [024,012] 068kkk:068val [025,016] 067kkk:067val [026,013] 066kkk:066val
=== SBLK[90] [027,015] 065kkk:065val [028,014] 064kkk:064val
=== SBLK[9] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=90, db=1
=== SBLK[9] szpow=9, lkl=6, lk=063kkk
=== SBLK[9] [000,002] 063kkk:063val [001,031] 062kkk:062val [002,001] 061kkk:061val
=== SBLK[9] [003,030] 060kkk:060val [004,000] 059kkk:059val [005,029] 058kkk:058val
=== SBLK[9] [006,014] 057kkk:057val [007,028] 056kkk:056val [008,013] 055kkk:055val
=== SBLK[9] [009,027] 054kkk:054val [010,012] 053kkk:053val [011,026] 052kkk:052val
=== SBLK[9] [012,011] 051kkk:051val [013,025] 050kkk:050val [014,010] 049kkk:049val
=== SBLK[9] [015,024] 048kkk:048val [016,009] 047kkk:047val [017,023] 046kkk:046val
=== SBLK[9] [018,008] 045kkk:045val [019,022] 044kkk:044val
=== SBLK[80] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=9, db=1
=== SBLK[80] szpow=10, lkl=6, lk=043kkk
=== SBLK[80] [000,000] 043kkk:043val [001,001] 042kkk:042val [002,002] 041kkk:041val
=== SBLK[80] [003,003] 040kkk:040val [004,004] 039kkk:039val [005,005] 038kkk:038val
=== SBLK[80] [006,006] 037kkk:037val [007,007] 036kkk:036val [008,008] 035kkk:035val
=== SBLK[80] [009,009] 034kkk:034val [010,010] 033kkk:033val [011,011] 032kkk:032val
=== SBLK[80] [012,012] 031kkk:031val [013,013] 030kkk:030val [014,014] 029kkk:029val
=== SBLK[70] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=80, db=1
=== SBLK[70] szpow=10, lkl=6, lk=028kkk
=== SBLK[70] [000,000] 028kkk:028val [001,028] 027kkk:027val [002,001] 026kkk:026val
=== SBLK[70] [003,027] 025kkk:025val [004,002] 024kkk:024val [005,026] 023kkk:023val
=== SBLK[70] [006,003] 022kkk:022val [007,025] 021kkk:021val [008,004] 020kkk:020val
=== SBLK[70] [009,024] 019kkk:019val [010,005] 018kkk:018val [011,023] 017kkk:017val
=== SBLK[70] [012,006] 016kkk:016val [013,022] 015kkk:015val [014,007] 014kkk:014val
=== SBLK[70] [015,021] 013kkk:013val [016,008] 012kkk:012val [017,020] 011kkk:011val
=== SBLK[70] [018,009] 010kkk:010val [019,019] 009kkk:009val [020,010] 008kkk:008val
=== SBLK[70] [021,018] 007kkk:007val [022,011] 006kkk:006val [023,017] 005kkk:005val
=== SBLK[70] [024,012] 004kkk:004val [025,016] 003kkk:003val [026,013] 002kkk:002val
=== SBLK[70] [027,015] 001kkk:001val [028,014] 000kkk:000val
#### Stage: a big key
== DB[1] lvl=-1, blk=3, dbflg=0, p0=70
=== SBLK[64] lvl=-1, pnum=21, flg=1, kvzidx=4, p0=3, db=1
=== SBLK[64] szpow=9, lkl=71, lk=abracadabrabracadabrabracadabrabracadabrabracadabrabracadabrabracadabr1
=== SBLK[64] [000,003] abracadabrabracadabrabracadabrabracadabrabracadabrabracadabrabracadabr1:vabracadabrabracadabrabracadabrabracadabrabracadabrabracadabrabracadabr [001,002] 253kkk:253val [002,030] 252kkk:252val
=== SBLK[64] [003,001] 251kkk:251val [004,029] 250kkk:250val [005,000] 249kkk:249val
=== SBLK[64] [006,028] 248kkk:248val [007,031] 247kkk:247val [008,027] 246kkk:246val
=== SBLK[64] [009,013] 245kkk:245val [010,026] 244kkk:244val [011,012] 243kkk:243val
=== SBLK[64] [012,025] 242kkk:242val [013,011] 241kkk:241val [014,024] 240kkk:240val
=== SBLK[64] [015,010] 239kkk:239val [016,023] 238kkk:238val [017,009] 237kkk:237val
=== SBLK[64] [018,022] 236kkk:236val [019,008] 235kkk:235val [020,021] 234kkk:234val
=== SBLK[140] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=64, db=1
=== SBLK[140] szpow=10, lkl=6, lk=233kkk
=== SBLK[140] [000,000] 233kkk:233val [001,001] 232kkk:232val [002,002] 231kkk:231val
=== SBLK[140] [003,003] 230kkk:230val [004,004] 229kkk:229val [005,005] 228kkk:228val
=== SBLK[140] [006,006] 227kkk:227val [007,007] 226kkk:226val [008,008] 225kkk:225val
=== SBLK[140] [009,009] 224kkk:224val [010,010] 223kkk:223val [011,011] 222kkk:222val
=== SBLK[140] [012,012] 221kkk:221val [013,013] 220kkk:220val [014,014] 219kkk:219val
=== SBLK[130] lvl=-1, pnum=28, flg=1, kvzidx=28, p0=140, db=1
=== SBLK[130] szpow=10, lkl=6, lk=218kkk
=== SBLK[130] [000,000] 218kkk:218val [001,027] 217kkk:217val [002,001] 216kkk:216val
=== SBLK[130] [003,026] 215kkk:215val [004,002] 214kkk:214val [005,025] 213kkk:213val
=== SBLK[130] [006,003] 212kkk:212val [007,024] 211kkk:211val [008,004] 210kkk:210val
=== SBLK[130] [009,023] 209kkk:209val [010,005] 208kkk:208val [011,022] 207kkk:207val
=== SBLK[130] [012,006] 206kkk:206val [013,021] 205kkk:205val [014,007] 204kkk:204val
=== SBLK[130] [015,020] 203kkk:203val [016,008] 202kkk:202val [017,019] 201kkk:201val
=== SBLK[130] [018,009] 200kkk:200val [019,018] 199kkk:199val [020,010] 198kkk:198val
=== SBLK[130] [021,017] 197kkk:197val [022,011] 196kkk:196val [023,016] 195kkk:195val
=== SBLK[130] [024,012] 194kkk:194val [025,015] 193kkk:193val [026,013] 192kkk:192val
=== SBLK[130] [027,014] 191kkk:191val
=== SBLK[21] lvl=-1, pnum=19, flg=1, kvzidx=2, p0=130, db=1
=== SBLK[21] szpow=9, lkl=6, lk=190kkk
=== SBLK[21] [000,031] 190kkk:190val [001,001] 189kkk:189val [002,030] 188kkk:188val
=== SBLK[21] [003,000] 187kkk:187val [004,029] 186kkk:186val [005,014] 185kkk:185val
=== SBLK[21] [006,028] 184kkk:184val [007,013] 183kkk:183val [008,027] 182kkk:182val
=== SBLK[21] [009,012] 181kkk:181val [010,026] 180kkk:180val [011,011] 179kkk:179val
=== SBLK[21] [012,025] 178kkk:178val [013,010] 177kkk:177val [014,024] 176kkk:176val
=== SBLK[21] [015,009] 175kkk:175val [016,023] 174kkk:174val [017,008] 173kkk:173val
=== SBLK[21] [018,022] 172kkk:172val
=== SBLK[120] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=21, db=1
=== SBLK[120] szpow=10, lkl=6, lk=171kkk
=== SBLK[120] [000,000] 171kkk:171val [001,001] 170kkk:170val [002,002] 169kkk:169val
=== SBLK[120] [003,003] 168kkk:168val [004,004] 167kkk:167val [005,005] 166kkk:166val
=== SBLK[120] [006,006] 165kkk:165val [007,007] 164kkk:164val [008,008] 163kkk:163val
=== SBLK[120] [009,009] 162kkk:162val [010,010] 161kkk:161val [011,011] 160kkk:160val
=== SBLK[120] [012,012] 159kkk:159val [013,013] 158kkk:158val [014,014] 157kkk:157val
=== SBLK[110] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=120, db=1
=== SBLK[110] szpow=10, lkl=6, lk=156kkk
=== SBLK[110] [000,000] 156kkk:156val [001,028] 155kkk:155val [002,001] 154kkk:154val
=== SBLK[110] [003,027] 153kkk:153val [004,002] 152kkk:152val [005,026] 151kkk:151val
=== SBLK[110] [006,003] 150kkk:150val [007,025] 149kkk:149val [008,004] 148kkk:148val
=== SBLK[110] [009,024] 147kkk:147val [010,005] 146kkk:146val [011,023] 145kkk:145val
=== SBLK[110] [012,006] 144kkk:144val [013,022] 143kkk:143val [014,007] 142kkk:142val
=== SBLK[110] [015,021] 141kkk:141val [016,008] 140kkk:140val [017,020] 139kkk:139val
=== SBLK[110] [018,009] 138kkk:138val [019,019] 137kkk:137val [020,010] 136kkk:136val
=== SBLK[110] [021,018] 135kkk:135val [022,011] 134kkk:134val [023,017] 133kkk:133val
=== SBLK[110] [024,012] 132kkk:132val [025,016] 131kkk:131val [026,013] 130kkk:130val
=== SBLK[110] [027,015] 129kkk:129val [028,014] 128kkk:128val
=== SBLK[15] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=110, db=1
=== SBLK[15] szpow=9, lkl=6, lk=127kkk
=== SBLK[15] [000,002] 127kkk:127val [001,031] 126kkk:126val [002,001] 125kkk:125val
=== SBLK[15] [003,030] 124kkk:124val [004,000] 123kkk:123val [005,029] 122kkk:122val
=== SBLK[15] [006,014] 121kkk:121val [007,028] 120kkk:120val [008,013] 119kkk:119val
=== SBLK[15] [009,027] 118kkk:118val [010,012] 117kkk:117val [011,026] 116kkk:116val
=== SBLK[15] [012,011] 115kkk:115val [013,025] 114kkk:114val [014,010] 113kkk:113val
=== SBLK[15] [015,024] 112kkk:112val [016,009] 111kkk:111val [017,023] 110kkk:110val
=== SBLK[15] [018,008] 109kkk:109val [019,022] 108kkk:108val
=== SBLK[100] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=15, db=1
=== SBLK[100] szpow=10, lkl=6, lk=107kkk
=== SBLK[100] [000,000] 107kkk:107val [001,001] 106kkk:106val [002,002] 105kkk:105val
=== SBLK[100] [003,003] 104kkk:104val [004,004] 103kkk:103val [005,005] 102kkk:102val
=== SBLK[100] [006,006] 101kkk:101val [007,007] 100kkk:100val [008,008] 099kkk:099val
=== SBLK[100] [009,009] 098kkk:098val [010,010] 097kkk:097val [011,011] 096kkk:096val
=== SBLK[100] [012,012] 095kkk:095val [013,013] 094kkk:094val [014,014] 093kkk:093val
=== SBLK[90] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=100, db=1
=== SBLK[90] szpow=10, lkl=6, lk=092kkk
=== SBLK[90] [000,000] 092kkk:092val [001,028] 091kkk:091val [002,001] 090kkk:090val
=== SBLK[90] [003,027] 089kkk:089val [004,002] 088kkk:088val [005,026] 087kkk:087val
=== SBLK[90] [006,003] 086kkk:086val [007,025] 085kkk:085val [008,004] 084kkk:084val
=== SBLK[90] [009,024] 083kkk:083val [010,005] 082kkk:082val [011,023] 081kkk:081val
=== SBLK[90] [012,006] 080kkk:080val [013,022] 079kkk:079val [014,007] 078kkk:078val
=== SBLK[90] [015,021] 077kkk:077val [016,008] 076kkk:076val [017,020] 075kkk:075val
=== SBLK[90] [018,009] 074kkk:074val [019,019] 073kkk:073val [020,010] 072kkk:072val
=== SBLK[90] [021,018] 071kkk:071val [022,011] 070kkk:070val [023,017] 069kkk:069val
=== SBLK[90] [024,012] 068kkk:068val [025,016] 067kkk:067val [026,013] 066kkk:066val
=== SBLK[90] [027,015] 065kkk:065val [028,014] 064kkk:064val
=== SBLK[9] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=90, db=1
=== SBLK[9] szpow=9, lkl=6, lk=063kkk
=== SBLK[9] [000,002] 063kkk:063val [001,031] 062kkk:062val [002,001] 061kkk:061val
=== SBLK[9] [003,030] 060kkk:060val [004,000] 059kkk:059val [005,029] 058kkk:058val
=== SBLK[9] [006,014] 057kkk:057val [007,028] 056kkk:056val [008,013] 055kkk:055val
=== SBLK[9] [009,027] 054kkk:054val [010,012] 053kkk:053val [011,026] 052kkk:052val
=== SBLK[9] [012,011] 051kkk:051val [013,025] 050kkk:050val [014,010] 049kkk:049val
=== SBLK[9] [015,024] 048kkk:048val [016,009] 047kkk:047val [017,023] 046kkk:046val
=== SBLK[9] [018,008] 045kkk:045val [019,022] 044kkk:044val
=== SBLK[80] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=9, db=1
=== SBLK[80] szpow=10, lkl=6, lk=043kkk
=== SBLK[80] [000,000] 043kkk:043val [001,001] 042kkk:042val [002,002] 041kkk:041val
=== SBLK[80] [003,003] 040kkk:040val [004,004] 039kkk:039val [005,005] 038kkk:038val
=== SBLK[80] [006,006] 037kkk:037val [007,007] 036kkk:036val [008,008] 035kkk:035val
=== SBLK[80] [009,009] 034kkk:034val [010,010] 033kkk:033val [011,011] 032kkk:032val
=== SBLK[80] [012,012] 031kkk:031val [013,013] 030kkk:030val [014,014] 029kkk:029val
=== SBLK[70] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=80, db=1
=== SBLK[70] szpow=10, lkl=6, lk=028kkk
=== SBLK[70] [000,000] 028kkk:028val [001,028] 027kkk:027val [002,001] 026kkk:026val
=== SBLK[70] [003,027] 025kkk:025val [004,002] 024kkk:024val [005,026] 023kkk:023val
=== SBLK[70] [006,003] 022kkk:022val [007,025] 021kkk:021val [008,004] 020kkk:020val
=== SBLK[70] [009,024] 019kkk:019val [010,005] 018kkk:018val [011,023] 017kkk:017val
=== SBLK[70] [012,006] 016kkk:016val [013,022] 015kkk:015val [014,007] 014kkk:014val
=== SBLK[70] [015,021] 013kkk:013val [016,008] 012kkk:012val [017,020] 011kkk:011val
=== SBLK[70] [018,009] 010kkk:010val [019,019] 009kkk:009val [020,010] 008kkk:008val
=== SBLK[70] [021,018] 007kkk:007val [022,011] 006kkk:006val [023,017] 005kkk:005val
=== SBLK[70] [024,012] 004kkk:004val [025,016] 003kkk:003val [026,013] 002kkk:002val
=== SBLK[70] [027,015] 001kkk:001val [028,014] 000kkk:000val
+528
View File
@@ -0,0 +1,528 @@
#### Stage: empty db
== DB[1] lvl=-1, blk=3, dbflg=0, p0=3
#### Stage: put foo:bar
== DB[1] lvl=-1, blk=3, dbflg=0, p0=64
=== SBLK[64] lvl=-1, pnum=1, flg=1, kvzidx=1, p0=3, db=1
=== SBLK[64] szpow=9, lkl=3, lk=foo
=== SBLK[64] [000,000] foo:bar
#### Stage: put foo:bazz
== DB[1] lvl=-1, blk=3, dbflg=0, p0=64
=== SBLK[64] lvl=-1, pnum=1, flg=1, kvzidx=1, p0=3, db=1
=== SBLK[64] szpow=9, lkl=3, lk=foo
=== SBLK[64] [000,000] foo:bazzz
#### Stage: put foo:
== DB[1] lvl=-1, blk=3, dbflg=0, p0=64
=== SBLK[64] lvl=-1, pnum=1, flg=1, kvzidx=1, p0=3, db=1
=== SBLK[64] szpow=9, lkl=3, lk=foo
=== SBLK[64] [000,000] foo:
#### Stage: put foo:bar
== DB[1] lvl=-1, blk=3, dbflg=0, p0=64
=== SBLK[64] lvl=-1, pnum=1, flg=1, kvzidx=1, p0=3, db=1
=== SBLK[64] szpow=9, lkl=3, lk=foo
=== SBLK[64] [000,000] foo:bar
#### Stage: remove foo:bar
== DB[1] lvl=-1, blk=3, dbflg=0, p0=3
#### Stage: fill up first block
== DB[1] lvl=-1, blk=3, dbflg=0, p0=64
=== SBLK[70] lvl=-1, pnum=31, flg=1, kvzidx=31, p0=3, db=1
=== SBLK[70] szpow=9, lkl=6, lk=252kkk
=== SBLK[70] [000,030] 252kkk:252val [001,029] 250kkk:250val [002,028] 248kkk:248val
=== SBLK[70] [003,027] 246kkk:246val [004,026] 244kkk:244val [005,025] 242kkk:242val
=== SBLK[70] [006,024] 240kkk:240val [007,023] 238kkk:238val [008,022] 236kkk:236val
=== SBLK[70] [009,021] 234kkk:234val [010,020] 232kkk:232val [011,019] 230kkk:230val
=== SBLK[70] [012,018] 228kkk:228val [013,017] 226kkk:226val [014,016] 224kkk:224val
=== SBLK[70] [015,015] 222kkk:222val [016,014] 220kkk:220val [017,013] 218kkk:218val
=== SBLK[70] [018,012] 216kkk:216val [019,011] 214kkk:214val [020,010] 212kkk:212val
=== SBLK[70] [021,009] 210kkk:210val [022,008] 208kkk:208val [023,007] 206kkk:206val
=== SBLK[70] [024,006] 204kkk:204val [025,005] 202kkk:202val [026,004] 200kkk:200val
=== SBLK[70] [027,003] 198kkk:198val [028,002] 196kkk:196val [029,001] 194kkk:194val
=== SBLK[70] [030,000] 192kkk:192val
=== SBLK[68] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=70, db=1
=== SBLK[68] szpow=9, lkl=6, lk=190kkk
=== SBLK[68] [000,031] 190kkk:190val [001,030] 188kkk:188val [002,029] 186kkk:186val
=== SBLK[68] [003,028] 184kkk:184val [004,027] 182kkk:182val [005,026] 180kkk:180val
=== SBLK[68] [006,025] 178kkk:178val [007,024] 176kkk:176val [008,023] 174kkk:174val
=== SBLK[68] [009,022] 172kkk:172val [010,021] 170kkk:170val [011,020] 168kkk:168val
=== SBLK[68] [012,019] 166kkk:166val [013,018] 164kkk:164val [014,017] 162kkk:162val
=== SBLK[68] [015,016] 160kkk:160val [016,015] 158kkk:158val [017,014] 156kkk:156val
=== SBLK[68] [018,013] 154kkk:154val [019,012] 152kkk:152val [020,011] 150kkk:150val
=== SBLK[68] [021,010] 148kkk:148val [022,009] 146kkk:146val [023,008] 144kkk:144val
=== SBLK[68] [024,007] 142kkk:142val [025,006] 140kkk:140val [026,005] 138kkk:138val
=== SBLK[68] [027,004] 136kkk:136val [028,003] 134kkk:134val [029,002] 132kkk:132val
=== SBLK[68] [030,001] 130kkk:130val [031,000] 128kkk:128val
=== SBLK[66] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=68, db=1
=== SBLK[66] szpow=9, lkl=6, lk=126kkk
=== SBLK[66] [000,031] 126kkk:126val [001,030] 124kkk:124val [002,029] 122kkk:122val
=== SBLK[66] [003,028] 120kkk:120val [004,027] 118kkk:118val [005,026] 116kkk:116val
=== SBLK[66] [006,025] 114kkk:114val [007,024] 112kkk:112val [008,023] 110kkk:110val
=== SBLK[66] [009,022] 108kkk:108val [010,021] 106kkk:106val [011,020] 104kkk:104val
=== SBLK[66] [012,019] 102kkk:102val [013,018] 100kkk:100val [014,017] 098kkk:098val
=== SBLK[66] [015,016] 096kkk:096val [016,015] 094kkk:094val [017,014] 092kkk:092val
=== SBLK[66] [018,013] 090kkk:090val [019,012] 088kkk:088val [020,011] 086kkk:086val
=== SBLK[66] [021,010] 084kkk:084val [022,009] 082kkk:082val [023,008] 080kkk:080val
=== SBLK[66] [024,007] 078kkk:078val [025,006] 076kkk:076val [026,005] 074kkk:074val
=== SBLK[66] [027,004] 072kkk:072val [028,003] 070kkk:070val [029,002] 068kkk:068val
=== SBLK[66] [030,001] 066kkk:066val [031,000] 064kkk:064val
=== SBLK[64] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=66, db=1
=== SBLK[64] szpow=9, lkl=6, lk=062kkk
=== SBLK[64] [000,031] 062kkk:062val [001,030] 060kkk:060val [002,029] 058kkk:058val
=== SBLK[64] [003,028] 056kkk:056val [004,027] 054kkk:054val [005,026] 052kkk:052val
=== SBLK[64] [006,025] 050kkk:050val [007,024] 048kkk:048val [008,023] 046kkk:046val
=== SBLK[64] [009,022] 044kkk:044val [010,021] 042kkk:042val [011,020] 040kkk:040val
=== SBLK[64] [012,019] 038kkk:038val [013,018] 036kkk:036val [014,017] 034kkk:034val
=== SBLK[64] [015,016] 032kkk:032val [016,015] 030kkk:030val [017,014] 028kkk:028val
=== SBLK[64] [018,013] 026kkk:026val [019,012] 024kkk:024val [020,011] 022kkk:022val
=== SBLK[64] [021,010] 020kkk:020val [022,009] 018kkk:018val [023,008] 016kkk:016val
=== SBLK[64] [024,007] 014kkk:014val [025,006] 012kkk:012val [026,005] 010kkk:010val
=== SBLK[64] [027,004] 008kkk:008val [028,003] 006kkk:006val [029,002] 004kkk:004val
=== SBLK[64] [030,001] 002kkk:002val [031,000] 000kkk:000val
#### Stage: fill up second block
== DB[1] lvl=-1, blk=3, dbflg=0, p0=72
=== SBLK[70] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=3, db=1
=== SBLK[70] szpow=9, lkl=6, lk=253kkk
=== SBLK[70] [000,002] 253kkk:253val [001,030] 252kkk:252val [002,001] 251kkk:251val
=== SBLK[70] [003,029] 250kkk:250val [004,000] 249kkk:249val [005,028] 248kkk:248val
=== SBLK[70] [006,031] 247kkk:247val [007,027] 246kkk:246val [008,013] 245kkk:245val
=== SBLK[70] [009,026] 244kkk:244val [010,012] 243kkk:243val [011,025] 242kkk:242val
=== SBLK[70] [012,011] 241kkk:241val [013,024] 240kkk:240val [014,010] 239kkk:239val
=== SBLK[70] [015,023] 238kkk:238val [016,009] 237kkk:237val [017,022] 236kkk:236val
=== SBLK[70] [018,008] 235kkk:235val [019,021] 234kkk:234val
=== SBLK[86] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=70, db=1
=== SBLK[86] szpow=10, lkl=6, lk=233kkk
=== SBLK[86] [000,000] 233kkk:233val [001,001] 232kkk:232val [002,002] 231kkk:231val
=== SBLK[86] [003,003] 230kkk:230val [004,004] 229kkk:229val [005,005] 228kkk:228val
=== SBLK[86] [006,006] 227kkk:227val [007,007] 226kkk:226val [008,008] 225kkk:225val
=== SBLK[86] [009,009] 224kkk:224val [010,010] 223kkk:223val [011,011] 222kkk:222val
=== SBLK[86] [012,012] 221kkk:221val [013,013] 220kkk:220val [014,014] 219kkk:219val
=== SBLK[84] lvl=-1, pnum=28, flg=1, kvzidx=28, p0=86, db=1
=== SBLK[84] szpow=10, lkl=6, lk=218kkk
=== SBLK[84] [000,000] 218kkk:218val [001,027] 217kkk:217val [002,001] 216kkk:216val
=== SBLK[84] [003,026] 215kkk:215val [004,002] 214kkk:214val [005,025] 213kkk:213val
=== SBLK[84] [006,003] 212kkk:212val [007,024] 211kkk:211val [008,004] 210kkk:210val
=== SBLK[84] [009,023] 209kkk:209val [010,005] 208kkk:208val [011,022] 207kkk:207val
=== SBLK[84] [012,006] 206kkk:206val [013,021] 205kkk:205val [014,007] 204kkk:204val
=== SBLK[84] [015,020] 203kkk:203val [016,008] 202kkk:202val [017,019] 201kkk:201val
=== SBLK[84] [018,009] 200kkk:200val [019,018] 199kkk:199val [020,010] 198kkk:198val
=== SBLK[84] [021,017] 197kkk:197val [022,011] 196kkk:196val [023,016] 195kkk:195val
=== SBLK[84] [024,012] 194kkk:194val [025,015] 193kkk:193val [026,013] 192kkk:192val
=== SBLK[84] [027,014] 191kkk:191val
=== SBLK[68] lvl=-1, pnum=19, flg=1, kvzidx=2, p0=84, db=1
=== SBLK[68] szpow=9, lkl=6, lk=190kkk
=== SBLK[68] [000,031] 190kkk:190val [001,001] 189kkk:189val [002,030] 188kkk:188val
=== SBLK[68] [003,000] 187kkk:187val [004,029] 186kkk:186val [005,014] 185kkk:185val
=== SBLK[68] [006,028] 184kkk:184val [007,013] 183kkk:183val [008,027] 182kkk:182val
=== SBLK[68] [009,012] 181kkk:181val [010,026] 180kkk:180val [011,011] 179kkk:179val
=== SBLK[68] [012,025] 178kkk:178val [013,010] 177kkk:177val [014,024] 176kkk:176val
=== SBLK[68] [015,009] 175kkk:175val [016,023] 174kkk:174val [017,008] 173kkk:173val
=== SBLK[68] [018,022] 172kkk:172val
=== SBLK[82] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=68, db=1
=== SBLK[82] szpow=10, lkl=6, lk=171kkk
=== SBLK[82] [000,000] 171kkk:171val [001,001] 170kkk:170val [002,002] 169kkk:169val
=== SBLK[82] [003,003] 168kkk:168val [004,004] 167kkk:167val [005,005] 166kkk:166val
=== SBLK[82] [006,006] 165kkk:165val [007,007] 164kkk:164val [008,008] 163kkk:163val
=== SBLK[82] [009,009] 162kkk:162val [010,010] 161kkk:161val [011,011] 160kkk:160val
=== SBLK[82] [012,012] 159kkk:159val [013,013] 158kkk:158val [014,014] 157kkk:157val
=== SBLK[80] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=82, db=1
=== SBLK[80] szpow=10, lkl=6, lk=156kkk
=== SBLK[80] [000,000] 156kkk:156val [001,028] 155kkk:155val [002,001] 154kkk:154val
=== SBLK[80] [003,027] 153kkk:153val [004,002] 152kkk:152val [005,026] 151kkk:151val
=== SBLK[80] [006,003] 150kkk:150val [007,025] 149kkk:149val [008,004] 148kkk:148val
=== SBLK[80] [009,024] 147kkk:147val [010,005] 146kkk:146val [011,023] 145kkk:145val
=== SBLK[80] [012,006] 144kkk:144val [013,022] 143kkk:143val [014,007] 142kkk:142val
=== SBLK[80] [015,021] 141kkk:141val [016,008] 140kkk:140val [017,020] 139kkk:139val
=== SBLK[80] [018,009] 138kkk:138val [019,019] 137kkk:137val [020,010] 136kkk:136val
=== SBLK[80] [021,018] 135kkk:135val [022,011] 134kkk:134val [023,017] 133kkk:133val
=== SBLK[80] [024,012] 132kkk:132val [025,016] 131kkk:131val [026,013] 130kkk:130val
=== SBLK[80] [027,015] 129kkk:129val [028,014] 128kkk:128val
=== SBLK[66] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=80, db=1
=== SBLK[66] szpow=9, lkl=6, lk=127kkk
=== SBLK[66] [000,002] 127kkk:127val [001,031] 126kkk:126val [002,001] 125kkk:125val
=== SBLK[66] [003,030] 124kkk:124val [004,000] 123kkk:123val [005,029] 122kkk:122val
=== SBLK[66] [006,014] 121kkk:121val [007,028] 120kkk:120val [008,013] 119kkk:119val
=== SBLK[66] [009,027] 118kkk:118val [010,012] 117kkk:117val [011,026] 116kkk:116val
=== SBLK[66] [012,011] 115kkk:115val [013,025] 114kkk:114val [014,010] 113kkk:113val
=== SBLK[66] [015,024] 112kkk:112val [016,009] 111kkk:111val [017,023] 110kkk:110val
=== SBLK[66] [018,008] 109kkk:109val [019,022] 108kkk:108val
=== SBLK[78] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=66, db=1
=== SBLK[78] szpow=10, lkl=6, lk=107kkk
=== SBLK[78] [000,000] 107kkk:107val [001,001] 106kkk:106val [002,002] 105kkk:105val
=== SBLK[78] [003,003] 104kkk:104val [004,004] 103kkk:103val [005,005] 102kkk:102val
=== SBLK[78] [006,006] 101kkk:101val [007,007] 100kkk:100val [008,008] 099kkk:099val
=== SBLK[78] [009,009] 098kkk:098val [010,010] 097kkk:097val [011,011] 096kkk:096val
=== SBLK[78] [012,012] 095kkk:095val [013,013] 094kkk:094val [014,014] 093kkk:093val
=== SBLK[76] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=78, db=1
=== SBLK[76] szpow=10, lkl=6, lk=092kkk
=== SBLK[76] [000,000] 092kkk:092val [001,028] 091kkk:091val [002,001] 090kkk:090val
=== SBLK[76] [003,027] 089kkk:089val [004,002] 088kkk:088val [005,026] 087kkk:087val
=== SBLK[76] [006,003] 086kkk:086val [007,025] 085kkk:085val [008,004] 084kkk:084val
=== SBLK[76] [009,024] 083kkk:083val [010,005] 082kkk:082val [011,023] 081kkk:081val
=== SBLK[76] [012,006] 080kkk:080val [013,022] 079kkk:079val [014,007] 078kkk:078val
=== SBLK[76] [015,021] 077kkk:077val [016,008] 076kkk:076val [017,020] 075kkk:075val
=== SBLK[76] [018,009] 074kkk:074val [019,019] 073kkk:073val [020,010] 072kkk:072val
=== SBLK[76] [021,018] 071kkk:071val [022,011] 070kkk:070val [023,017] 069kkk:069val
=== SBLK[76] [024,012] 068kkk:068val [025,016] 067kkk:067val [026,013] 066kkk:066val
=== SBLK[76] [027,015] 065kkk:065val [028,014] 064kkk:064val
=== SBLK[64] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=76, db=1
=== SBLK[64] szpow=9, lkl=6, lk=063kkk
=== SBLK[64] [000,002] 063kkk:063val [001,031] 062kkk:062val [002,001] 061kkk:061val
=== SBLK[64] [003,030] 060kkk:060val [004,000] 059kkk:059val [005,029] 058kkk:058val
=== SBLK[64] [006,014] 057kkk:057val [007,028] 056kkk:056val [008,013] 055kkk:055val
=== SBLK[64] [009,027] 054kkk:054val [010,012] 053kkk:053val [011,026] 052kkk:052val
=== SBLK[64] [012,011] 051kkk:051val [013,025] 050kkk:050val [014,010] 049kkk:049val
=== SBLK[64] [015,024] 048kkk:048val [016,009] 047kkk:047val [017,023] 046kkk:046val
=== SBLK[64] [018,008] 045kkk:045val [019,022] 044kkk:044val
=== SBLK[74] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=64, db=1
=== SBLK[74] szpow=10, lkl=6, lk=043kkk
=== SBLK[74] [000,000] 043kkk:043val [001,001] 042kkk:042val [002,002] 041kkk:041val
=== SBLK[74] [003,003] 040kkk:040val [004,004] 039kkk:039val [005,005] 038kkk:038val
=== SBLK[74] [006,006] 037kkk:037val [007,007] 036kkk:036val [008,008] 035kkk:035val
=== SBLK[74] [009,009] 034kkk:034val [010,010] 033kkk:033val [011,011] 032kkk:032val
=== SBLK[74] [012,012] 031kkk:031val [013,013] 030kkk:030val [014,014] 029kkk:029val
=== SBLK[72] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=74, db=1
=== SBLK[72] szpow=10, lkl=6, lk=028kkk
=== SBLK[72] [000,000] 028kkk:028val [001,028] 027kkk:027val [002,001] 026kkk:026val
=== SBLK[72] [003,027] 025kkk:025val [004,002] 024kkk:024val [005,026] 023kkk:023val
=== SBLK[72] [006,003] 022kkk:022val [007,025] 021kkk:021val [008,004] 020kkk:020val
=== SBLK[72] [009,024] 019kkk:019val [010,005] 018kkk:018val [011,023] 017kkk:017val
=== SBLK[72] [012,006] 016kkk:016val [013,022] 015kkk:015val [014,007] 014kkk:014val
=== SBLK[72] [015,021] 013kkk:013val [016,008] 012kkk:012val [017,020] 011kkk:011val
=== SBLK[72] [018,009] 010kkk:010val [019,019] 009kkk:009val [020,010] 008kkk:008val
=== SBLK[72] [021,018] 007kkk:007val [022,011] 006kkk:006val [023,017] 005kkk:005val
=== SBLK[72] [024,012] 004kkk:004val [025,016] 003kkk:003val [026,013] 002kkk:002val
=== SBLK[72] [027,015] 001kkk:001val [028,014] 000kkk:000val
#### Stage: state after reopen
== DB[1] lvl=-1, blk=3, dbflg=0, p0=72
=== SBLK[70] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=3, db=1
=== SBLK[70] szpow=9, lkl=6, lk=253kkk
=== SBLK[70] [000,002] 253kkk:253val [001,030] 252kkk:252val [002,001] 251kkk:251val
=== SBLK[70] [003,029] 250kkk:250val [004,000] 249kkk:249val [005,028] 248kkk:248val
=== SBLK[70] [006,031] 247kkk:247val [007,027] 246kkk:246val [008,013] 245kkk:245val
=== SBLK[70] [009,026] 244kkk:244val [010,012] 243kkk:243val [011,025] 242kkk:242val
=== SBLK[70] [012,011] 241kkk:241val [013,024] 240kkk:240val [014,010] 239kkk:239val
=== SBLK[70] [015,023] 238kkk:238val [016,009] 237kkk:237val [017,022] 236kkk:236val
=== SBLK[70] [018,008] 235kkk:235val [019,021] 234kkk:234val
=== SBLK[86] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=70, db=1
=== SBLK[86] szpow=10, lkl=6, lk=233kkk
=== SBLK[86] [000,000] 233kkk:233val [001,001] 232kkk:232val [002,002] 231kkk:231val
=== SBLK[86] [003,003] 230kkk:230val [004,004] 229kkk:229val [005,005] 228kkk:228val
=== SBLK[86] [006,006] 227kkk:227val [007,007] 226kkk:226val [008,008] 225kkk:225val
=== SBLK[86] [009,009] 224kkk:224val [010,010] 223kkk:223val [011,011] 222kkk:222val
=== SBLK[86] [012,012] 221kkk:221val [013,013] 220kkk:220val [014,014] 219kkk:219val
=== SBLK[84] lvl=-1, pnum=28, flg=1, kvzidx=28, p0=86, db=1
=== SBLK[84] szpow=10, lkl=6, lk=218kkk
=== SBLK[84] [000,000] 218kkk:218val [001,027] 217kkk:217val [002,001] 216kkk:216val
=== SBLK[84] [003,026] 215kkk:215val [004,002] 214kkk:214val [005,025] 213kkk:213val
=== SBLK[84] [006,003] 212kkk:212val [007,024] 211kkk:211val [008,004] 210kkk:210val
=== SBLK[84] [009,023] 209kkk:209val [010,005] 208kkk:208val [011,022] 207kkk:207val
=== SBLK[84] [012,006] 206kkk:206val [013,021] 205kkk:205val [014,007] 204kkk:204val
=== SBLK[84] [015,020] 203kkk:203val [016,008] 202kkk:202val [017,019] 201kkk:201val
=== SBLK[84] [018,009] 200kkk:200val [019,018] 199kkk:199val [020,010] 198kkk:198val
=== SBLK[84] [021,017] 197kkk:197val [022,011] 196kkk:196val [023,016] 195kkk:195val
=== SBLK[84] [024,012] 194kkk:194val [025,015] 193kkk:193val [026,013] 192kkk:192val
=== SBLK[84] [027,014] 191kkk:191val
=== SBLK[68] lvl=-1, pnum=19, flg=1, kvzidx=2, p0=84, db=1
=== SBLK[68] szpow=9, lkl=6, lk=190kkk
=== SBLK[68] [000,031] 190kkk:190val [001,001] 189kkk:189val [002,030] 188kkk:188val
=== SBLK[68] [003,000] 187kkk:187val [004,029] 186kkk:186val [005,014] 185kkk:185val
=== SBLK[68] [006,028] 184kkk:184val [007,013] 183kkk:183val [008,027] 182kkk:182val
=== SBLK[68] [009,012] 181kkk:181val [010,026] 180kkk:180val [011,011] 179kkk:179val
=== SBLK[68] [012,025] 178kkk:178val [013,010] 177kkk:177val [014,024] 176kkk:176val
=== SBLK[68] [015,009] 175kkk:175val [016,023] 174kkk:174val [017,008] 173kkk:173val
=== SBLK[68] [018,022] 172kkk:172val
=== SBLK[82] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=68, db=1
=== SBLK[82] szpow=10, lkl=6, lk=171kkk
=== SBLK[82] [000,000] 171kkk:171val [001,001] 170kkk:170val [002,002] 169kkk:169val
=== SBLK[82] [003,003] 168kkk:168val [004,004] 167kkk:167val [005,005] 166kkk:166val
=== SBLK[82] [006,006] 165kkk:165val [007,007] 164kkk:164val [008,008] 163kkk:163val
=== SBLK[82] [009,009] 162kkk:162val [010,010] 161kkk:161val [011,011] 160kkk:160val
=== SBLK[82] [012,012] 159kkk:159val [013,013] 158kkk:158val [014,014] 157kkk:157val
=== SBLK[80] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=82, db=1
=== SBLK[80] szpow=10, lkl=6, lk=156kkk
=== SBLK[80] [000,000] 156kkk:156val [001,028] 155kkk:155val [002,001] 154kkk:154val
=== SBLK[80] [003,027] 153kkk:153val [004,002] 152kkk:152val [005,026] 151kkk:151val
=== SBLK[80] [006,003] 150kkk:150val [007,025] 149kkk:149val [008,004] 148kkk:148val
=== SBLK[80] [009,024] 147kkk:147val [010,005] 146kkk:146val [011,023] 145kkk:145val
=== SBLK[80] [012,006] 144kkk:144val [013,022] 143kkk:143val [014,007] 142kkk:142val
=== SBLK[80] [015,021] 141kkk:141val [016,008] 140kkk:140val [017,020] 139kkk:139val
=== SBLK[80] [018,009] 138kkk:138val [019,019] 137kkk:137val [020,010] 136kkk:136val
=== SBLK[80] [021,018] 135kkk:135val [022,011] 134kkk:134val [023,017] 133kkk:133val
=== SBLK[80] [024,012] 132kkk:132val [025,016] 131kkk:131val [026,013] 130kkk:130val
=== SBLK[80] [027,015] 129kkk:129val [028,014] 128kkk:128val
=== SBLK[66] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=80, db=1
=== SBLK[66] szpow=9, lkl=6, lk=127kkk
=== SBLK[66] [000,002] 127kkk:127val [001,031] 126kkk:126val [002,001] 125kkk:125val
=== SBLK[66] [003,030] 124kkk:124val [004,000] 123kkk:123val [005,029] 122kkk:122val
=== SBLK[66] [006,014] 121kkk:121val [007,028] 120kkk:120val [008,013] 119kkk:119val
=== SBLK[66] [009,027] 118kkk:118val [010,012] 117kkk:117val [011,026] 116kkk:116val
=== SBLK[66] [012,011] 115kkk:115val [013,025] 114kkk:114val [014,010] 113kkk:113val
=== SBLK[66] [015,024] 112kkk:112val [016,009] 111kkk:111val [017,023] 110kkk:110val
=== SBLK[66] [018,008] 109kkk:109val [019,022] 108kkk:108val
=== SBLK[78] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=66, db=1
=== SBLK[78] szpow=10, lkl=6, lk=107kkk
=== SBLK[78] [000,000] 107kkk:107val [001,001] 106kkk:106val [002,002] 105kkk:105val
=== SBLK[78] [003,003] 104kkk:104val [004,004] 103kkk:103val [005,005] 102kkk:102val
=== SBLK[78] [006,006] 101kkk:101val [007,007] 100kkk:100val [008,008] 099kkk:099val
=== SBLK[78] [009,009] 098kkk:098val [010,010] 097kkk:097val [011,011] 096kkk:096val
=== SBLK[78] [012,012] 095kkk:095val [013,013] 094kkk:094val [014,014] 093kkk:093val
=== SBLK[76] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=78, db=1
=== SBLK[76] szpow=10, lkl=6, lk=092kkk
=== SBLK[76] [000,000] 092kkk:092val [001,028] 091kkk:091val [002,001] 090kkk:090val
=== SBLK[76] [003,027] 089kkk:089val [004,002] 088kkk:088val [005,026] 087kkk:087val
=== SBLK[76] [006,003] 086kkk:086val [007,025] 085kkk:085val [008,004] 084kkk:084val
=== SBLK[76] [009,024] 083kkk:083val [010,005] 082kkk:082val [011,023] 081kkk:081val
=== SBLK[76] [012,006] 080kkk:080val [013,022] 079kkk:079val [014,007] 078kkk:078val
=== SBLK[76] [015,021] 077kkk:077val [016,008] 076kkk:076val [017,020] 075kkk:075val
=== SBLK[76] [018,009] 074kkk:074val [019,019] 073kkk:073val [020,010] 072kkk:072val
=== SBLK[76] [021,018] 071kkk:071val [022,011] 070kkk:070val [023,017] 069kkk:069val
=== SBLK[76] [024,012] 068kkk:068val [025,016] 067kkk:067val [026,013] 066kkk:066val
=== SBLK[76] [027,015] 065kkk:065val [028,014] 064kkk:064val
=== SBLK[64] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=76, db=1
=== SBLK[64] szpow=9, lkl=6, lk=063kkk
=== SBLK[64] [000,002] 063kkk:063val [001,031] 062kkk:062val [002,001] 061kkk:061val
=== SBLK[64] [003,030] 060kkk:060val [004,000] 059kkk:059val [005,029] 058kkk:058val
=== SBLK[64] [006,014] 057kkk:057val [007,028] 056kkk:056val [008,013] 055kkk:055val
=== SBLK[64] [009,027] 054kkk:054val [010,012] 053kkk:053val [011,026] 052kkk:052val
=== SBLK[64] [012,011] 051kkk:051val [013,025] 050kkk:050val [014,010] 049kkk:049val
=== SBLK[64] [015,024] 048kkk:048val [016,009] 047kkk:047val [017,023] 046kkk:046val
=== SBLK[64] [018,008] 045kkk:045val [019,022] 044kkk:044val
=== SBLK[74] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=64, db=1
=== SBLK[74] szpow=10, lkl=6, lk=043kkk
=== SBLK[74] [000,000] 043kkk:043val [001,001] 042kkk:042val [002,002] 041kkk:041val
=== SBLK[74] [003,003] 040kkk:040val [004,004] 039kkk:039val [005,005] 038kkk:038val
=== SBLK[74] [006,006] 037kkk:037val [007,007] 036kkk:036val [008,008] 035kkk:035val
=== SBLK[74] [009,009] 034kkk:034val [010,010] 033kkk:033val [011,011] 032kkk:032val
=== SBLK[74] [012,012] 031kkk:031val [013,013] 030kkk:030val [014,014] 029kkk:029val
=== SBLK[72] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=74, db=1
=== SBLK[72] szpow=10, lkl=6, lk=028kkk
=== SBLK[72] [000,000] 028kkk:028val [001,028] 027kkk:027val [002,001] 026kkk:026val
=== SBLK[72] [003,027] 025kkk:025val [004,002] 024kkk:024val [005,026] 023kkk:023val
=== SBLK[72] [006,003] 022kkk:022val [007,025] 021kkk:021val [008,004] 020kkk:020val
=== SBLK[72] [009,024] 019kkk:019val [010,005] 018kkk:018val [011,023] 017kkk:017val
=== SBLK[72] [012,006] 016kkk:016val [013,022] 015kkk:015val [014,007] 014kkk:014val
=== SBLK[72] [015,021] 013kkk:013val [016,008] 012kkk:012val [017,020] 011kkk:011val
=== SBLK[72] [018,009] 010kkk:010val [019,019] 009kkk:009val [020,010] 008kkk:008val
=== SBLK[72] [021,018] 007kkk:007val [022,011] 006kkk:006val [023,017] 005kkk:005val
=== SBLK[72] [024,012] 004kkk:004val [025,016] 003kkk:003val [026,013] 002kkk:002val
=== SBLK[72] [027,015] 001kkk:001val [028,014] 000kkk:000val
#### Stage: a big key
== DB[1] lvl=-1, blk=3, dbflg=0, p0=72
=== SBLK[70] lvl=-1, pnum=21, flg=1, kvzidx=4, p0=3, db=1
=== SBLK[70] szpow=9, lkl=71, lk=abracadabrabracadabrabracadabrabracadabrabracadabrabracadabrabracadabr1
=== SBLK[70] [000,003] abracadabrabracadabrabracadabrabracadabrabracadabrabracadabrabracadabr1:vabracadabrabracadabrabracadabrabracadabrabracadabrabracadabrabracadabr [001,002] 253kkk:253val [002,030] 252kkk:252val
=== SBLK[70] [003,001] 251kkk:251val [004,029] 250kkk:250val [005,000] 249kkk:249val
=== SBLK[70] [006,028] 248kkk:248val [007,031] 247kkk:247val [008,027] 246kkk:246val
=== SBLK[70] [009,013] 245kkk:245val [010,026] 244kkk:244val [011,012] 243kkk:243val
=== SBLK[70] [012,025] 242kkk:242val [013,011] 241kkk:241val [014,024] 240kkk:240val
=== SBLK[70] [015,010] 239kkk:239val [016,023] 238kkk:238val [017,009] 237kkk:237val
=== SBLK[70] [018,022] 236kkk:236val [019,008] 235kkk:235val [020,021] 234kkk:234val
=== SBLK[86] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=70, db=1
=== SBLK[86] szpow=10, lkl=6, lk=233kkk
=== SBLK[86] [000,000] 233kkk:233val [001,001] 232kkk:232val [002,002] 231kkk:231val
=== SBLK[86] [003,003] 230kkk:230val [004,004] 229kkk:229val [005,005] 228kkk:228val
=== SBLK[86] [006,006] 227kkk:227val [007,007] 226kkk:226val [008,008] 225kkk:225val
=== SBLK[86] [009,009] 224kkk:224val [010,010] 223kkk:223val [011,011] 222kkk:222val
=== SBLK[86] [012,012] 221kkk:221val [013,013] 220kkk:220val [014,014] 219kkk:219val
=== SBLK[84] lvl=-1, pnum=28, flg=1, kvzidx=28, p0=86, db=1
=== SBLK[84] szpow=10, lkl=6, lk=218kkk
=== SBLK[84] [000,000] 218kkk:218val [001,027] 217kkk:217val [002,001] 216kkk:216val
=== SBLK[84] [003,026] 215kkk:215val [004,002] 214kkk:214val [005,025] 213kkk:213val
=== SBLK[84] [006,003] 212kkk:212val [007,024] 211kkk:211val [008,004] 210kkk:210val
=== SBLK[84] [009,023] 209kkk:209val [010,005] 208kkk:208val [011,022] 207kkk:207val
=== SBLK[84] [012,006] 206kkk:206val [013,021] 205kkk:205val [014,007] 204kkk:204val
=== SBLK[84] [015,020] 203kkk:203val [016,008] 202kkk:202val [017,019] 201kkk:201val
=== SBLK[84] [018,009] 200kkk:200val [019,018] 199kkk:199val [020,010] 198kkk:198val
=== SBLK[84] [021,017] 197kkk:197val [022,011] 196kkk:196val [023,016] 195kkk:195val
=== SBLK[84] [024,012] 194kkk:194val [025,015] 193kkk:193val [026,013] 192kkk:192val
=== SBLK[84] [027,014] 191kkk:191val
=== SBLK[68] lvl=-1, pnum=19, flg=1, kvzidx=2, p0=84, db=1
=== SBLK[68] szpow=9, lkl=6, lk=190kkk
=== SBLK[68] [000,031] 190kkk:190val [001,001] 189kkk:189val [002,030] 188kkk:188val
=== SBLK[68] [003,000] 187kkk:187val [004,029] 186kkk:186val [005,014] 185kkk:185val
=== SBLK[68] [006,028] 184kkk:184val [007,013] 183kkk:183val [008,027] 182kkk:182val
=== SBLK[68] [009,012] 181kkk:181val [010,026] 180kkk:180val [011,011] 179kkk:179val
=== SBLK[68] [012,025] 178kkk:178val [013,010] 177kkk:177val [014,024] 176kkk:176val
=== SBLK[68] [015,009] 175kkk:175val [016,023] 174kkk:174val [017,008] 173kkk:173val
=== SBLK[68] [018,022] 172kkk:172val
=== SBLK[82] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=68, db=1
=== SBLK[82] szpow=10, lkl=6, lk=171kkk
=== SBLK[82] [000,000] 171kkk:171val [001,001] 170kkk:170val [002,002] 169kkk:169val
=== SBLK[82] [003,003] 168kkk:168val [004,004] 167kkk:167val [005,005] 166kkk:166val
=== SBLK[82] [006,006] 165kkk:165val [007,007] 164kkk:164val [008,008] 163kkk:163val
=== SBLK[82] [009,009] 162kkk:162val [010,010] 161kkk:161val [011,011] 160kkk:160val
=== SBLK[82] [012,012] 159kkk:159val [013,013] 158kkk:158val [014,014] 157kkk:157val
=== SBLK[80] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=82, db=1
=== SBLK[80] szpow=10, lkl=6, lk=156kkk
=== SBLK[80] [000,000] 156kkk:156val [001,028] 155kkk:155val [002,001] 154kkk:154val
=== SBLK[80] [003,027] 153kkk:153val [004,002] 152kkk:152val [005,026] 151kkk:151val
=== SBLK[80] [006,003] 150kkk:150val [007,025] 149kkk:149val [008,004] 148kkk:148val
=== SBLK[80] [009,024] 147kkk:147val [010,005] 146kkk:146val [011,023] 145kkk:145val
=== SBLK[80] [012,006] 144kkk:144val [013,022] 143kkk:143val [014,007] 142kkk:142val
=== SBLK[80] [015,021] 141kkk:141val [016,008] 140kkk:140val [017,020] 139kkk:139val
=== SBLK[80] [018,009] 138kkk:138val [019,019] 137kkk:137val [020,010] 136kkk:136val
=== SBLK[80] [021,018] 135kkk:135val [022,011] 134kkk:134val [023,017] 133kkk:133val
=== SBLK[80] [024,012] 132kkk:132val [025,016] 131kkk:131val [026,013] 130kkk:130val
=== SBLK[80] [027,015] 129kkk:129val [028,014] 128kkk:128val
=== SBLK[66] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=80, db=1
=== SBLK[66] szpow=9, lkl=6, lk=127kkk
=== SBLK[66] [000,002] 127kkk:127val [001,031] 126kkk:126val [002,001] 125kkk:125val
=== SBLK[66] [003,030] 124kkk:124val [004,000] 123kkk:123val [005,029] 122kkk:122val
=== SBLK[66] [006,014] 121kkk:121val [007,028] 120kkk:120val [008,013] 119kkk:119val
=== SBLK[66] [009,027] 118kkk:118val [010,012] 117kkk:117val [011,026] 116kkk:116val
=== SBLK[66] [012,011] 115kkk:115val [013,025] 114kkk:114val [014,010] 113kkk:113val
=== SBLK[66] [015,024] 112kkk:112val [016,009] 111kkk:111val [017,023] 110kkk:110val
=== SBLK[66] [018,008] 109kkk:109val [019,022] 108kkk:108val
=== SBLK[78] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=66, db=1
=== SBLK[78] szpow=10, lkl=6, lk=107kkk
=== SBLK[78] [000,000] 107kkk:107val [001,001] 106kkk:106val [002,002] 105kkk:105val
=== SBLK[78] [003,003] 104kkk:104val [004,004] 103kkk:103val [005,005] 102kkk:102val
=== SBLK[78] [006,006] 101kkk:101val [007,007] 100kkk:100val [008,008] 099kkk:099val
=== SBLK[78] [009,009] 098kkk:098val [010,010] 097kkk:097val [011,011] 096kkk:096val
=== SBLK[78] [012,012] 095kkk:095val [013,013] 094kkk:094val [014,014] 093kkk:093val
=== SBLK[76] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=78, db=1
=== SBLK[76] szpow=10, lkl=6, lk=092kkk
=== SBLK[76] [000,000] 092kkk:092val [001,028] 091kkk:091val [002,001] 090kkk:090val
=== SBLK[76] [003,027] 089kkk:089val [004,002] 088kkk:088val [005,026] 087kkk:087val
=== SBLK[76] [006,003] 086kkk:086val [007,025] 085kkk:085val [008,004] 084kkk:084val
=== SBLK[76] [009,024] 083kkk:083val [010,005] 082kkk:082val [011,023] 081kkk:081val
=== SBLK[76] [012,006] 080kkk:080val [013,022] 079kkk:079val [014,007] 078kkk:078val
=== SBLK[76] [015,021] 077kkk:077val [016,008] 076kkk:076val [017,020] 075kkk:075val
=== SBLK[76] [018,009] 074kkk:074val [019,019] 073kkk:073val [020,010] 072kkk:072val
=== SBLK[76] [021,018] 071kkk:071val [022,011] 070kkk:070val [023,017] 069kkk:069val
=== SBLK[76] [024,012] 068kkk:068val [025,016] 067kkk:067val [026,013] 066kkk:066val
=== SBLK[76] [027,015] 065kkk:065val [028,014] 064kkk:064val
=== SBLK[64] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=76, db=1
=== SBLK[64] szpow=9, lkl=6, lk=063kkk
=== SBLK[64] [000,002] 063kkk:063val [001,031] 062kkk:062val [002,001] 061kkk:061val
=== SBLK[64] [003,030] 060kkk:060val [004,000] 059kkk:059val [005,029] 058kkk:058val
=== SBLK[64] [006,014] 057kkk:057val [007,028] 056kkk:056val [008,013] 055kkk:055val
=== SBLK[64] [009,027] 054kkk:054val [010,012] 053kkk:053val [011,026] 052kkk:052val
=== SBLK[64] [012,011] 051kkk:051val [013,025] 050kkk:050val [014,010] 049kkk:049val
=== SBLK[64] [015,024] 048kkk:048val [016,009] 047kkk:047val [017,023] 046kkk:046val
=== SBLK[64] [018,008] 045kkk:045val [019,022] 044kkk:044val
=== SBLK[74] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=64, db=1
=== SBLK[74] szpow=10, lkl=6, lk=043kkk
=== SBLK[74] [000,000] 043kkk:043val [001,001] 042kkk:042val [002,002] 041kkk:041val
=== SBLK[74] [003,003] 040kkk:040val [004,004] 039kkk:039val [005,005] 038kkk:038val
=== SBLK[74] [006,006] 037kkk:037val [007,007] 036kkk:036val [008,008] 035kkk:035val
=== SBLK[74] [009,009] 034kkk:034val [010,010] 033kkk:033val [011,011] 032kkk:032val
=== SBLK[74] [012,012] 031kkk:031val [013,013] 030kkk:030val [014,014] 029kkk:029val
=== SBLK[72] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=74, db=1
=== SBLK[72] szpow=10, lkl=6, lk=028kkk
=== SBLK[72] [000,000] 028kkk:028val [001,028] 027kkk:027val [002,001] 026kkk:026val
=== SBLK[72] [003,027] 025kkk:025val [004,002] 024kkk:024val [005,026] 023kkk:023val
=== SBLK[72] [006,003] 022kkk:022val [007,025] 021kkk:021val [008,004] 020kkk:020val
=== SBLK[72] [009,024] 019kkk:019val [010,005] 018kkk:018val [011,023] 017kkk:017val
=== SBLK[72] [012,006] 016kkk:016val [013,022] 015kkk:015val [014,007] 014kkk:014val
=== SBLK[72] [015,021] 013kkk:013val [016,008] 012kkk:012val [017,020] 011kkk:011val
=== SBLK[72] [018,009] 010kkk:010val [019,019] 009kkk:009val [020,010] 008kkk:008val
=== SBLK[72] [021,018] 007kkk:007val [022,011] 006kkk:006val [023,017] 005kkk:005val
=== SBLK[72] [024,012] 004kkk:004val [025,016] 003kkk:003val [026,013] 002kkk:002val
=== SBLK[72] [027,015] 001kkk:001val [028,014] 000kkk:000val
+528
View File
@@ -0,0 +1,528 @@
#### Stage: empty db
== DB[1] lvl=-1, blk=3, dbflg=0, p0=3
#### Stage: put foo:bar
== DB[1] lvl=-1, blk=3, dbflg=0, p0=9
=== SBLK[9] lvl=-1, pnum=1, flg=1, kvzidx=1, p0=3, db=1
=== SBLK[9] szpow=9, lkl=3, lk=foo
=== SBLK[9] [000,000] foo:bar
#### Stage: put foo:bazz
== DB[1] lvl=-1, blk=3, dbflg=0, p0=9
=== SBLK[9] lvl=-1, pnum=1, flg=1, kvzidx=1, p0=3, db=1
=== SBLK[9] szpow=9, lkl=3, lk=foo
=== SBLK[9] [000,000] foo:bazzz
#### Stage: put foo:
== DB[1] lvl=-1, blk=3, dbflg=0, p0=9
=== SBLK[9] lvl=-1, pnum=1, flg=1, kvzidx=1, p0=3, db=1
=== SBLK[9] szpow=9, lkl=3, lk=foo
=== SBLK[9] [000,000] foo:
#### Stage: put foo:bar
== DB[1] lvl=-1, blk=3, dbflg=0, p0=9
=== SBLK[9] lvl=-1, pnum=1, flg=1, kvzidx=1, p0=3, db=1
=== SBLK[9] szpow=9, lkl=3, lk=foo
=== SBLK[9] [000,000] foo:bar
#### Stage: remove foo:bar
== DB[1] lvl=-1, blk=3, dbflg=0, p0=3
#### Stage: fill up first block
== DB[1] lvl=-1, blk=3, dbflg=0, p0=9
=== SBLK[27] lvl=-1, pnum=31, flg=1, kvzidx=31, p0=3, db=1
=== SBLK[27] szpow=9, lkl=6, lk=252kkk
=== SBLK[27] [000,030] 252kkk:252val [001,029] 250kkk:250val [002,028] 248kkk:248val
=== SBLK[27] [003,027] 246kkk:246val [004,026] 244kkk:244val [005,025] 242kkk:242val
=== SBLK[27] [006,024] 240kkk:240val [007,023] 238kkk:238val [008,022] 236kkk:236val
=== SBLK[27] [009,021] 234kkk:234val [010,020] 232kkk:232val [011,019] 230kkk:230val
=== SBLK[27] [012,018] 228kkk:228val [013,017] 226kkk:226val [014,016] 224kkk:224val
=== SBLK[27] [015,015] 222kkk:222val [016,014] 220kkk:220val [017,013] 218kkk:218val
=== SBLK[27] [018,012] 216kkk:216val [019,011] 214kkk:214val [020,010] 212kkk:212val
=== SBLK[27] [021,009] 210kkk:210val [022,008] 208kkk:208val [023,007] 206kkk:206val
=== SBLK[27] [024,006] 204kkk:204val [025,005] 202kkk:202val [026,004] 200kkk:200val
=== SBLK[27] [027,003] 198kkk:198val [028,002] 196kkk:196val [029,001] 194kkk:194val
=== SBLK[27] [030,000] 192kkk:192val
=== SBLK[21] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=27, db=1
=== SBLK[21] szpow=9, lkl=6, lk=190kkk
=== SBLK[21] [000,031] 190kkk:190val [001,030] 188kkk:188val [002,029] 186kkk:186val
=== SBLK[21] [003,028] 184kkk:184val [004,027] 182kkk:182val [005,026] 180kkk:180val
=== SBLK[21] [006,025] 178kkk:178val [007,024] 176kkk:176val [008,023] 174kkk:174val
=== SBLK[21] [009,022] 172kkk:172val [010,021] 170kkk:170val [011,020] 168kkk:168val
=== SBLK[21] [012,019] 166kkk:166val [013,018] 164kkk:164val [014,017] 162kkk:162val
=== SBLK[21] [015,016] 160kkk:160val [016,015] 158kkk:158val [017,014] 156kkk:156val
=== SBLK[21] [018,013] 154kkk:154val [019,012] 152kkk:152val [020,011] 150kkk:150val
=== SBLK[21] [021,010] 148kkk:148val [022,009] 146kkk:146val [023,008] 144kkk:144val
=== SBLK[21] [024,007] 142kkk:142val [025,006] 140kkk:140val [026,005] 138kkk:138val
=== SBLK[21] [027,004] 136kkk:136val [028,003] 134kkk:134val [029,002] 132kkk:132val
=== SBLK[21] [030,001] 130kkk:130val [031,000] 128kkk:128val
=== SBLK[15] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=21, db=1
=== SBLK[15] szpow=9, lkl=6, lk=126kkk
=== SBLK[15] [000,031] 126kkk:126val [001,030] 124kkk:124val [002,029] 122kkk:122val
=== SBLK[15] [003,028] 120kkk:120val [004,027] 118kkk:118val [005,026] 116kkk:116val
=== SBLK[15] [006,025] 114kkk:114val [007,024] 112kkk:112val [008,023] 110kkk:110val
=== SBLK[15] [009,022] 108kkk:108val [010,021] 106kkk:106val [011,020] 104kkk:104val
=== SBLK[15] [012,019] 102kkk:102val [013,018] 100kkk:100val [014,017] 098kkk:098val
=== SBLK[15] [015,016] 096kkk:096val [016,015] 094kkk:094val [017,014] 092kkk:092val
=== SBLK[15] [018,013] 090kkk:090val [019,012] 088kkk:088val [020,011] 086kkk:086val
=== SBLK[15] [021,010] 084kkk:084val [022,009] 082kkk:082val [023,008] 080kkk:080val
=== SBLK[15] [024,007] 078kkk:078val [025,006] 076kkk:076val [026,005] 074kkk:074val
=== SBLK[15] [027,004] 072kkk:072val [028,003] 070kkk:070val [029,002] 068kkk:068val
=== SBLK[15] [030,001] 066kkk:066val [031,000] 064kkk:064val
=== SBLK[9] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=15, db=1
=== SBLK[9] szpow=9, lkl=6, lk=062kkk
=== SBLK[9] [000,031] 062kkk:062val [001,030] 060kkk:060val [002,029] 058kkk:058val
=== SBLK[9] [003,028] 056kkk:056val [004,027] 054kkk:054val [005,026] 052kkk:052val
=== SBLK[9] [006,025] 050kkk:050val [007,024] 048kkk:048val [008,023] 046kkk:046val
=== SBLK[9] [009,022] 044kkk:044val [010,021] 042kkk:042val [011,020] 040kkk:040val
=== SBLK[9] [012,019] 038kkk:038val [013,018] 036kkk:036val [014,017] 034kkk:034val
=== SBLK[9] [015,016] 032kkk:032val [016,015] 030kkk:030val [017,014] 028kkk:028val
=== SBLK[9] [018,013] 026kkk:026val [019,012] 024kkk:024val [020,011] 022kkk:022val
=== SBLK[9] [021,010] 020kkk:020val [022,009] 018kkk:018val [023,008] 016kkk:016val
=== SBLK[9] [024,007] 014kkk:014val [025,006] 012kkk:012val [026,005] 010kkk:010val
=== SBLK[9] [027,004] 008kkk:008val [028,003] 006kkk:006val [029,002] 004kkk:004val
=== SBLK[9] [030,001] 002kkk:002val [031,000] 000kkk:000val
#### Stage: fill up second block
== DB[1] lvl=-1, blk=3, dbflg=0, p0=33
=== SBLK[27] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=3, db=1
=== SBLK[27] szpow=9, lkl=6, lk=253kkk
=== SBLK[27] [000,002] 253kkk:253val [001,030] 252kkk:252val [002,001] 251kkk:251val
=== SBLK[27] [003,029] 250kkk:250val [004,000] 249kkk:249val [005,028] 248kkk:248val
=== SBLK[27] [006,031] 247kkk:247val [007,027] 246kkk:246val [008,013] 245kkk:245val
=== SBLK[27] [009,026] 244kkk:244val [010,012] 243kkk:243val [011,025] 242kkk:242val
=== SBLK[27] [012,011] 241kkk:241val [013,024] 240kkk:240val [014,010] 239kkk:239val
=== SBLK[27] [015,023] 238kkk:238val [016,009] 237kkk:237val [017,022] 236kkk:236val
=== SBLK[27] [018,008] 235kkk:235val [019,021] 234kkk:234val
=== SBLK[103] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=27, db=1
=== SBLK[103] szpow=10, lkl=6, lk=233kkk
=== SBLK[103] [000,000] 233kkk:233val [001,001] 232kkk:232val [002,002] 231kkk:231val
=== SBLK[103] [003,003] 230kkk:230val [004,004] 229kkk:229val [005,005] 228kkk:228val
=== SBLK[103] [006,006] 227kkk:227val [007,007] 226kkk:226val [008,008] 225kkk:225val
=== SBLK[103] [009,009] 224kkk:224val [010,010] 223kkk:223val [011,011] 222kkk:222val
=== SBLK[103] [012,012] 221kkk:221val [013,013] 220kkk:220val [014,014] 219kkk:219val
=== SBLK[93] lvl=-1, pnum=28, flg=1, kvzidx=28, p0=103, db=1
=== SBLK[93] szpow=10, lkl=6, lk=218kkk
=== SBLK[93] [000,000] 218kkk:218val [001,027] 217kkk:217val [002,001] 216kkk:216val
=== SBLK[93] [003,026] 215kkk:215val [004,002] 214kkk:214val [005,025] 213kkk:213val
=== SBLK[93] [006,003] 212kkk:212val [007,024] 211kkk:211val [008,004] 210kkk:210val
=== SBLK[93] [009,023] 209kkk:209val [010,005] 208kkk:208val [011,022] 207kkk:207val
=== SBLK[93] [012,006] 206kkk:206val [013,021] 205kkk:205val [014,007] 204kkk:204val
=== SBLK[93] [015,020] 203kkk:203val [016,008] 202kkk:202val [017,019] 201kkk:201val
=== SBLK[93] [018,009] 200kkk:200val [019,018] 199kkk:199val [020,010] 198kkk:198val
=== SBLK[93] [021,017] 197kkk:197val [022,011] 196kkk:196val [023,016] 195kkk:195val
=== SBLK[93] [024,012] 194kkk:194val [025,015] 193kkk:193val [026,013] 192kkk:192val
=== SBLK[93] [027,014] 191kkk:191val
=== SBLK[21] lvl=-1, pnum=19, flg=1, kvzidx=2, p0=93, db=1
=== SBLK[21] szpow=9, lkl=6, lk=190kkk
=== SBLK[21] [000,031] 190kkk:190val [001,001] 189kkk:189val [002,030] 188kkk:188val
=== SBLK[21] [003,000] 187kkk:187val [004,029] 186kkk:186val [005,014] 185kkk:185val
=== SBLK[21] [006,028] 184kkk:184val [007,013] 183kkk:183val [008,027] 182kkk:182val
=== SBLK[21] [009,012] 181kkk:181val [010,026] 180kkk:180val [011,011] 179kkk:179val
=== SBLK[21] [012,025] 178kkk:178val [013,010] 177kkk:177val [014,024] 176kkk:176val
=== SBLK[21] [015,009] 175kkk:175val [016,023] 174kkk:174val [017,008] 173kkk:173val
=== SBLK[21] [018,022] 172kkk:172val
=== SBLK[83] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=21, db=1
=== SBLK[83] szpow=10, lkl=6, lk=171kkk
=== SBLK[83] [000,000] 171kkk:171val [001,001] 170kkk:170val [002,002] 169kkk:169val
=== SBLK[83] [003,003] 168kkk:168val [004,004] 167kkk:167val [005,005] 166kkk:166val
=== SBLK[83] [006,006] 165kkk:165val [007,007] 164kkk:164val [008,008] 163kkk:163val
=== SBLK[83] [009,009] 162kkk:162val [010,010] 161kkk:161val [011,011] 160kkk:160val
=== SBLK[83] [012,012] 159kkk:159val [013,013] 158kkk:158val [014,014] 157kkk:157val
=== SBLK[73] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=83, db=1
=== SBLK[73] szpow=10, lkl=6, lk=156kkk
=== SBLK[73] [000,000] 156kkk:156val [001,028] 155kkk:155val [002,001] 154kkk:154val
=== SBLK[73] [003,027] 153kkk:153val [004,002] 152kkk:152val [005,026] 151kkk:151val
=== SBLK[73] [006,003] 150kkk:150val [007,025] 149kkk:149val [008,004] 148kkk:148val
=== SBLK[73] [009,024] 147kkk:147val [010,005] 146kkk:146val [011,023] 145kkk:145val
=== SBLK[73] [012,006] 144kkk:144val [013,022] 143kkk:143val [014,007] 142kkk:142val
=== SBLK[73] [015,021] 141kkk:141val [016,008] 140kkk:140val [017,020] 139kkk:139val
=== SBLK[73] [018,009] 138kkk:138val [019,019] 137kkk:137val [020,010] 136kkk:136val
=== SBLK[73] [021,018] 135kkk:135val [022,011] 134kkk:134val [023,017] 133kkk:133val
=== SBLK[73] [024,012] 132kkk:132val [025,016] 131kkk:131val [026,013] 130kkk:130val
=== SBLK[73] [027,015] 129kkk:129val [028,014] 128kkk:128val
=== SBLK[15] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=73, db=1
=== SBLK[15] szpow=9, lkl=6, lk=127kkk
=== SBLK[15] [000,002] 127kkk:127val [001,031] 126kkk:126val [002,001] 125kkk:125val
=== SBLK[15] [003,030] 124kkk:124val [004,000] 123kkk:123val [005,029] 122kkk:122val
=== SBLK[15] [006,014] 121kkk:121val [007,028] 120kkk:120val [008,013] 119kkk:119val
=== SBLK[15] [009,027] 118kkk:118val [010,012] 117kkk:117val [011,026] 116kkk:116val
=== SBLK[15] [012,011] 115kkk:115val [013,025] 114kkk:114val [014,010] 113kkk:113val
=== SBLK[15] [015,024] 112kkk:112val [016,009] 111kkk:111val [017,023] 110kkk:110val
=== SBLK[15] [018,008] 109kkk:109val [019,022] 108kkk:108val
=== SBLK[63] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=15, db=1
=== SBLK[63] szpow=10, lkl=6, lk=107kkk
=== SBLK[63] [000,000] 107kkk:107val [001,001] 106kkk:106val [002,002] 105kkk:105val
=== SBLK[63] [003,003] 104kkk:104val [004,004] 103kkk:103val [005,005] 102kkk:102val
=== SBLK[63] [006,006] 101kkk:101val [007,007] 100kkk:100val [008,008] 099kkk:099val
=== SBLK[63] [009,009] 098kkk:098val [010,010] 097kkk:097val [011,011] 096kkk:096val
=== SBLK[63] [012,012] 095kkk:095val [013,013] 094kkk:094val [014,014] 093kkk:093val
=== SBLK[53] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=63, db=1
=== SBLK[53] szpow=10, lkl=6, lk=092kkk
=== SBLK[53] [000,000] 092kkk:092val [001,028] 091kkk:091val [002,001] 090kkk:090val
=== SBLK[53] [003,027] 089kkk:089val [004,002] 088kkk:088val [005,026] 087kkk:087val
=== SBLK[53] [006,003] 086kkk:086val [007,025] 085kkk:085val [008,004] 084kkk:084val
=== SBLK[53] [009,024] 083kkk:083val [010,005] 082kkk:082val [011,023] 081kkk:081val
=== SBLK[53] [012,006] 080kkk:080val [013,022] 079kkk:079val [014,007] 078kkk:078val
=== SBLK[53] [015,021] 077kkk:077val [016,008] 076kkk:076val [017,020] 075kkk:075val
=== SBLK[53] [018,009] 074kkk:074val [019,019] 073kkk:073val [020,010] 072kkk:072val
=== SBLK[53] [021,018] 071kkk:071val [022,011] 070kkk:070val [023,017] 069kkk:069val
=== SBLK[53] [024,012] 068kkk:068val [025,016] 067kkk:067val [026,013] 066kkk:066val
=== SBLK[53] [027,015] 065kkk:065val [028,014] 064kkk:064val
=== SBLK[9] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=53, db=1
=== SBLK[9] szpow=9, lkl=6, lk=063kkk
=== SBLK[9] [000,002] 063kkk:063val [001,031] 062kkk:062val [002,001] 061kkk:061val
=== SBLK[9] [003,030] 060kkk:060val [004,000] 059kkk:059val [005,029] 058kkk:058val
=== SBLK[9] [006,014] 057kkk:057val [007,028] 056kkk:056val [008,013] 055kkk:055val
=== SBLK[9] [009,027] 054kkk:054val [010,012] 053kkk:053val [011,026] 052kkk:052val
=== SBLK[9] [012,011] 051kkk:051val [013,025] 050kkk:050val [014,010] 049kkk:049val
=== SBLK[9] [015,024] 048kkk:048val [016,009] 047kkk:047val [017,023] 046kkk:046val
=== SBLK[9] [018,008] 045kkk:045val [019,022] 044kkk:044val
=== SBLK[43] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=9, db=1
=== SBLK[43] szpow=10, lkl=6, lk=043kkk
=== SBLK[43] [000,000] 043kkk:043val [001,001] 042kkk:042val [002,002] 041kkk:041val
=== SBLK[43] [003,003] 040kkk:040val [004,004] 039kkk:039val [005,005] 038kkk:038val
=== SBLK[43] [006,006] 037kkk:037val [007,007] 036kkk:036val [008,008] 035kkk:035val
=== SBLK[43] [009,009] 034kkk:034val [010,010] 033kkk:033val [011,011] 032kkk:032val
=== SBLK[43] [012,012] 031kkk:031val [013,013] 030kkk:030val [014,014] 029kkk:029val
=== SBLK[33] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=43, db=1
=== SBLK[33] szpow=10, lkl=6, lk=028kkk
=== SBLK[33] [000,000] 028kkk:028val [001,028] 027kkk:027val [002,001] 026kkk:026val
=== SBLK[33] [003,027] 025kkk:025val [004,002] 024kkk:024val [005,026] 023kkk:023val
=== SBLK[33] [006,003] 022kkk:022val [007,025] 021kkk:021val [008,004] 020kkk:020val
=== SBLK[33] [009,024] 019kkk:019val [010,005] 018kkk:018val [011,023] 017kkk:017val
=== SBLK[33] [012,006] 016kkk:016val [013,022] 015kkk:015val [014,007] 014kkk:014val
=== SBLK[33] [015,021] 013kkk:013val [016,008] 012kkk:012val [017,020] 011kkk:011val
=== SBLK[33] [018,009] 010kkk:010val [019,019] 009kkk:009val [020,010] 008kkk:008val
=== SBLK[33] [021,018] 007kkk:007val [022,011] 006kkk:006val [023,017] 005kkk:005val
=== SBLK[33] [024,012] 004kkk:004val [025,016] 003kkk:003val [026,013] 002kkk:002val
=== SBLK[33] [027,015] 001kkk:001val [028,014] 000kkk:000val
#### Stage: state after reopen
== DB[1] lvl=-1, blk=3, dbflg=0, p0=33
=== SBLK[27] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=3, db=1
=== SBLK[27] szpow=9, lkl=6, lk=253kkk
=== SBLK[27] [000,002] 253kkk:253val [001,030] 252kkk:252val [002,001] 251kkk:251val
=== SBLK[27] [003,029] 250kkk:250val [004,000] 249kkk:249val [005,028] 248kkk:248val
=== SBLK[27] [006,031] 247kkk:247val [007,027] 246kkk:246val [008,013] 245kkk:245val
=== SBLK[27] [009,026] 244kkk:244val [010,012] 243kkk:243val [011,025] 242kkk:242val
=== SBLK[27] [012,011] 241kkk:241val [013,024] 240kkk:240val [014,010] 239kkk:239val
=== SBLK[27] [015,023] 238kkk:238val [016,009] 237kkk:237val [017,022] 236kkk:236val
=== SBLK[27] [018,008] 235kkk:235val [019,021] 234kkk:234val
=== SBLK[103] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=27, db=1
=== SBLK[103] szpow=10, lkl=6, lk=233kkk
=== SBLK[103] [000,000] 233kkk:233val [001,001] 232kkk:232val [002,002] 231kkk:231val
=== SBLK[103] [003,003] 230kkk:230val [004,004] 229kkk:229val [005,005] 228kkk:228val
=== SBLK[103] [006,006] 227kkk:227val [007,007] 226kkk:226val [008,008] 225kkk:225val
=== SBLK[103] [009,009] 224kkk:224val [010,010] 223kkk:223val [011,011] 222kkk:222val
=== SBLK[103] [012,012] 221kkk:221val [013,013] 220kkk:220val [014,014] 219kkk:219val
=== SBLK[93] lvl=-1, pnum=28, flg=1, kvzidx=28, p0=103, db=1
=== SBLK[93] szpow=10, lkl=6, lk=218kkk
=== SBLK[93] [000,000] 218kkk:218val [001,027] 217kkk:217val [002,001] 216kkk:216val
=== SBLK[93] [003,026] 215kkk:215val [004,002] 214kkk:214val [005,025] 213kkk:213val
=== SBLK[93] [006,003] 212kkk:212val [007,024] 211kkk:211val [008,004] 210kkk:210val
=== SBLK[93] [009,023] 209kkk:209val [010,005] 208kkk:208val [011,022] 207kkk:207val
=== SBLK[93] [012,006] 206kkk:206val [013,021] 205kkk:205val [014,007] 204kkk:204val
=== SBLK[93] [015,020] 203kkk:203val [016,008] 202kkk:202val [017,019] 201kkk:201val
=== SBLK[93] [018,009] 200kkk:200val [019,018] 199kkk:199val [020,010] 198kkk:198val
=== SBLK[93] [021,017] 197kkk:197val [022,011] 196kkk:196val [023,016] 195kkk:195val
=== SBLK[93] [024,012] 194kkk:194val [025,015] 193kkk:193val [026,013] 192kkk:192val
=== SBLK[93] [027,014] 191kkk:191val
=== SBLK[21] lvl=-1, pnum=19, flg=1, kvzidx=2, p0=93, db=1
=== SBLK[21] szpow=9, lkl=6, lk=190kkk
=== SBLK[21] [000,031] 190kkk:190val [001,001] 189kkk:189val [002,030] 188kkk:188val
=== SBLK[21] [003,000] 187kkk:187val [004,029] 186kkk:186val [005,014] 185kkk:185val
=== SBLK[21] [006,028] 184kkk:184val [007,013] 183kkk:183val [008,027] 182kkk:182val
=== SBLK[21] [009,012] 181kkk:181val [010,026] 180kkk:180val [011,011] 179kkk:179val
=== SBLK[21] [012,025] 178kkk:178val [013,010] 177kkk:177val [014,024] 176kkk:176val
=== SBLK[21] [015,009] 175kkk:175val [016,023] 174kkk:174val [017,008] 173kkk:173val
=== SBLK[21] [018,022] 172kkk:172val
=== SBLK[83] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=21, db=1
=== SBLK[83] szpow=10, lkl=6, lk=171kkk
=== SBLK[83] [000,000] 171kkk:171val [001,001] 170kkk:170val [002,002] 169kkk:169val
=== SBLK[83] [003,003] 168kkk:168val [004,004] 167kkk:167val [005,005] 166kkk:166val
=== SBLK[83] [006,006] 165kkk:165val [007,007] 164kkk:164val [008,008] 163kkk:163val
=== SBLK[83] [009,009] 162kkk:162val [010,010] 161kkk:161val [011,011] 160kkk:160val
=== SBLK[83] [012,012] 159kkk:159val [013,013] 158kkk:158val [014,014] 157kkk:157val
=== SBLK[73] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=83, db=1
=== SBLK[73] szpow=10, lkl=6, lk=156kkk
=== SBLK[73] [000,000] 156kkk:156val [001,028] 155kkk:155val [002,001] 154kkk:154val
=== SBLK[73] [003,027] 153kkk:153val [004,002] 152kkk:152val [005,026] 151kkk:151val
=== SBLK[73] [006,003] 150kkk:150val [007,025] 149kkk:149val [008,004] 148kkk:148val
=== SBLK[73] [009,024] 147kkk:147val [010,005] 146kkk:146val [011,023] 145kkk:145val
=== SBLK[73] [012,006] 144kkk:144val [013,022] 143kkk:143val [014,007] 142kkk:142val
=== SBLK[73] [015,021] 141kkk:141val [016,008] 140kkk:140val [017,020] 139kkk:139val
=== SBLK[73] [018,009] 138kkk:138val [019,019] 137kkk:137val [020,010] 136kkk:136val
=== SBLK[73] [021,018] 135kkk:135val [022,011] 134kkk:134val [023,017] 133kkk:133val
=== SBLK[73] [024,012] 132kkk:132val [025,016] 131kkk:131val [026,013] 130kkk:130val
=== SBLK[73] [027,015] 129kkk:129val [028,014] 128kkk:128val
=== SBLK[15] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=73, db=1
=== SBLK[15] szpow=9, lkl=6, lk=127kkk
=== SBLK[15] [000,002] 127kkk:127val [001,031] 126kkk:126val [002,001] 125kkk:125val
=== SBLK[15] [003,030] 124kkk:124val [004,000] 123kkk:123val [005,029] 122kkk:122val
=== SBLK[15] [006,014] 121kkk:121val [007,028] 120kkk:120val [008,013] 119kkk:119val
=== SBLK[15] [009,027] 118kkk:118val [010,012] 117kkk:117val [011,026] 116kkk:116val
=== SBLK[15] [012,011] 115kkk:115val [013,025] 114kkk:114val [014,010] 113kkk:113val
=== SBLK[15] [015,024] 112kkk:112val [016,009] 111kkk:111val [017,023] 110kkk:110val
=== SBLK[15] [018,008] 109kkk:109val [019,022] 108kkk:108val
=== SBLK[63] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=15, db=1
=== SBLK[63] szpow=10, lkl=6, lk=107kkk
=== SBLK[63] [000,000] 107kkk:107val [001,001] 106kkk:106val [002,002] 105kkk:105val
=== SBLK[63] [003,003] 104kkk:104val [004,004] 103kkk:103val [005,005] 102kkk:102val
=== SBLK[63] [006,006] 101kkk:101val [007,007] 100kkk:100val [008,008] 099kkk:099val
=== SBLK[63] [009,009] 098kkk:098val [010,010] 097kkk:097val [011,011] 096kkk:096val
=== SBLK[63] [012,012] 095kkk:095val [013,013] 094kkk:094val [014,014] 093kkk:093val
=== SBLK[53] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=63, db=1
=== SBLK[53] szpow=10, lkl=6, lk=092kkk
=== SBLK[53] [000,000] 092kkk:092val [001,028] 091kkk:091val [002,001] 090kkk:090val
=== SBLK[53] [003,027] 089kkk:089val [004,002] 088kkk:088val [005,026] 087kkk:087val
=== SBLK[53] [006,003] 086kkk:086val [007,025] 085kkk:085val [008,004] 084kkk:084val
=== SBLK[53] [009,024] 083kkk:083val [010,005] 082kkk:082val [011,023] 081kkk:081val
=== SBLK[53] [012,006] 080kkk:080val [013,022] 079kkk:079val [014,007] 078kkk:078val
=== SBLK[53] [015,021] 077kkk:077val [016,008] 076kkk:076val [017,020] 075kkk:075val
=== SBLK[53] [018,009] 074kkk:074val [019,019] 073kkk:073val [020,010] 072kkk:072val
=== SBLK[53] [021,018] 071kkk:071val [022,011] 070kkk:070val [023,017] 069kkk:069val
=== SBLK[53] [024,012] 068kkk:068val [025,016] 067kkk:067val [026,013] 066kkk:066val
=== SBLK[53] [027,015] 065kkk:065val [028,014] 064kkk:064val
=== SBLK[9] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=53, db=1
=== SBLK[9] szpow=9, lkl=6, lk=063kkk
=== SBLK[9] [000,002] 063kkk:063val [001,031] 062kkk:062val [002,001] 061kkk:061val
=== SBLK[9] [003,030] 060kkk:060val [004,000] 059kkk:059val [005,029] 058kkk:058val
=== SBLK[9] [006,014] 057kkk:057val [007,028] 056kkk:056val [008,013] 055kkk:055val
=== SBLK[9] [009,027] 054kkk:054val [010,012] 053kkk:053val [011,026] 052kkk:052val
=== SBLK[9] [012,011] 051kkk:051val [013,025] 050kkk:050val [014,010] 049kkk:049val
=== SBLK[9] [015,024] 048kkk:048val [016,009] 047kkk:047val [017,023] 046kkk:046val
=== SBLK[9] [018,008] 045kkk:045val [019,022] 044kkk:044val
=== SBLK[43] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=9, db=1
=== SBLK[43] szpow=10, lkl=6, lk=043kkk
=== SBLK[43] [000,000] 043kkk:043val [001,001] 042kkk:042val [002,002] 041kkk:041val
=== SBLK[43] [003,003] 040kkk:040val [004,004] 039kkk:039val [005,005] 038kkk:038val
=== SBLK[43] [006,006] 037kkk:037val [007,007] 036kkk:036val [008,008] 035kkk:035val
=== SBLK[43] [009,009] 034kkk:034val [010,010] 033kkk:033val [011,011] 032kkk:032val
=== SBLK[43] [012,012] 031kkk:031val [013,013] 030kkk:030val [014,014] 029kkk:029val
=== SBLK[33] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=43, db=1
=== SBLK[33] szpow=10, lkl=6, lk=028kkk
=== SBLK[33] [000,000] 028kkk:028val [001,028] 027kkk:027val [002,001] 026kkk:026val
=== SBLK[33] [003,027] 025kkk:025val [004,002] 024kkk:024val [005,026] 023kkk:023val
=== SBLK[33] [006,003] 022kkk:022val [007,025] 021kkk:021val [008,004] 020kkk:020val
=== SBLK[33] [009,024] 019kkk:019val [010,005] 018kkk:018val [011,023] 017kkk:017val
=== SBLK[33] [012,006] 016kkk:016val [013,022] 015kkk:015val [014,007] 014kkk:014val
=== SBLK[33] [015,021] 013kkk:013val [016,008] 012kkk:012val [017,020] 011kkk:011val
=== SBLK[33] [018,009] 010kkk:010val [019,019] 009kkk:009val [020,010] 008kkk:008val
=== SBLK[33] [021,018] 007kkk:007val [022,011] 006kkk:006val [023,017] 005kkk:005val
=== SBLK[33] [024,012] 004kkk:004val [025,016] 003kkk:003val [026,013] 002kkk:002val
=== SBLK[33] [027,015] 001kkk:001val [028,014] 000kkk:000val
#### Stage: a big key
== DB[1] lvl=-1, blk=3, dbflg=0, p0=33
=== SBLK[27] lvl=-1, pnum=21, flg=1, kvzidx=4, p0=3, db=1
=== SBLK[27] szpow=9, lkl=71, lk=abracadabrabracadabrabracadabrabracadabrabracadabrabracadabrabracadabr1
=== SBLK[27] [000,003] abracadabrabracadabrabracadabrabracadabrabracadabrabracadabrabracadabr1:vabracadabrabracadabrabracadabrabracadabrabracadabrabracadabrabracadabr [001,002] 253kkk:253val [002,030] 252kkk:252val
=== SBLK[27] [003,001] 251kkk:251val [004,029] 250kkk:250val [005,000] 249kkk:249val
=== SBLK[27] [006,028] 248kkk:248val [007,031] 247kkk:247val [008,027] 246kkk:246val
=== SBLK[27] [009,013] 245kkk:245val [010,026] 244kkk:244val [011,012] 243kkk:243val
=== SBLK[27] [012,025] 242kkk:242val [013,011] 241kkk:241val [014,024] 240kkk:240val
=== SBLK[27] [015,010] 239kkk:239val [016,023] 238kkk:238val [017,009] 237kkk:237val
=== SBLK[27] [018,022] 236kkk:236val [019,008] 235kkk:235val [020,021] 234kkk:234val
=== SBLK[103] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=27, db=1
=== SBLK[103] szpow=10, lkl=6, lk=233kkk
=== SBLK[103] [000,000] 233kkk:233val [001,001] 232kkk:232val [002,002] 231kkk:231val
=== SBLK[103] [003,003] 230kkk:230val [004,004] 229kkk:229val [005,005] 228kkk:228val
=== SBLK[103] [006,006] 227kkk:227val [007,007] 226kkk:226val [008,008] 225kkk:225val
=== SBLK[103] [009,009] 224kkk:224val [010,010] 223kkk:223val [011,011] 222kkk:222val
=== SBLK[103] [012,012] 221kkk:221val [013,013] 220kkk:220val [014,014] 219kkk:219val
=== SBLK[93] lvl=-1, pnum=28, flg=1, kvzidx=28, p0=103, db=1
=== SBLK[93] szpow=10, lkl=6, lk=218kkk
=== SBLK[93] [000,000] 218kkk:218val [001,027] 217kkk:217val [002,001] 216kkk:216val
=== SBLK[93] [003,026] 215kkk:215val [004,002] 214kkk:214val [005,025] 213kkk:213val
=== SBLK[93] [006,003] 212kkk:212val [007,024] 211kkk:211val [008,004] 210kkk:210val
=== SBLK[93] [009,023] 209kkk:209val [010,005] 208kkk:208val [011,022] 207kkk:207val
=== SBLK[93] [012,006] 206kkk:206val [013,021] 205kkk:205val [014,007] 204kkk:204val
=== SBLK[93] [015,020] 203kkk:203val [016,008] 202kkk:202val [017,019] 201kkk:201val
=== SBLK[93] [018,009] 200kkk:200val [019,018] 199kkk:199val [020,010] 198kkk:198val
=== SBLK[93] [021,017] 197kkk:197val [022,011] 196kkk:196val [023,016] 195kkk:195val
=== SBLK[93] [024,012] 194kkk:194val [025,015] 193kkk:193val [026,013] 192kkk:192val
=== SBLK[93] [027,014] 191kkk:191val
=== SBLK[21] lvl=-1, pnum=19, flg=1, kvzidx=2, p0=93, db=1
=== SBLK[21] szpow=9, lkl=6, lk=190kkk
=== SBLK[21] [000,031] 190kkk:190val [001,001] 189kkk:189val [002,030] 188kkk:188val
=== SBLK[21] [003,000] 187kkk:187val [004,029] 186kkk:186val [005,014] 185kkk:185val
=== SBLK[21] [006,028] 184kkk:184val [007,013] 183kkk:183val [008,027] 182kkk:182val
=== SBLK[21] [009,012] 181kkk:181val [010,026] 180kkk:180val [011,011] 179kkk:179val
=== SBLK[21] [012,025] 178kkk:178val [013,010] 177kkk:177val [014,024] 176kkk:176val
=== SBLK[21] [015,009] 175kkk:175val [016,023] 174kkk:174val [017,008] 173kkk:173val
=== SBLK[21] [018,022] 172kkk:172val
=== SBLK[83] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=21, db=1
=== SBLK[83] szpow=10, lkl=6, lk=171kkk
=== SBLK[83] [000,000] 171kkk:171val [001,001] 170kkk:170val [002,002] 169kkk:169val
=== SBLK[83] [003,003] 168kkk:168val [004,004] 167kkk:167val [005,005] 166kkk:166val
=== SBLK[83] [006,006] 165kkk:165val [007,007] 164kkk:164val [008,008] 163kkk:163val
=== SBLK[83] [009,009] 162kkk:162val [010,010] 161kkk:161val [011,011] 160kkk:160val
=== SBLK[83] [012,012] 159kkk:159val [013,013] 158kkk:158val [014,014] 157kkk:157val
=== SBLK[73] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=83, db=1
=== SBLK[73] szpow=10, lkl=6, lk=156kkk
=== SBLK[73] [000,000] 156kkk:156val [001,028] 155kkk:155val [002,001] 154kkk:154val
=== SBLK[73] [003,027] 153kkk:153val [004,002] 152kkk:152val [005,026] 151kkk:151val
=== SBLK[73] [006,003] 150kkk:150val [007,025] 149kkk:149val [008,004] 148kkk:148val
=== SBLK[73] [009,024] 147kkk:147val [010,005] 146kkk:146val [011,023] 145kkk:145val
=== SBLK[73] [012,006] 144kkk:144val [013,022] 143kkk:143val [014,007] 142kkk:142val
=== SBLK[73] [015,021] 141kkk:141val [016,008] 140kkk:140val [017,020] 139kkk:139val
=== SBLK[73] [018,009] 138kkk:138val [019,019] 137kkk:137val [020,010] 136kkk:136val
=== SBLK[73] [021,018] 135kkk:135val [022,011] 134kkk:134val [023,017] 133kkk:133val
=== SBLK[73] [024,012] 132kkk:132val [025,016] 131kkk:131val [026,013] 130kkk:130val
=== SBLK[73] [027,015] 129kkk:129val [028,014] 128kkk:128val
=== SBLK[15] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=73, db=1
=== SBLK[15] szpow=9, lkl=6, lk=127kkk
=== SBLK[15] [000,002] 127kkk:127val [001,031] 126kkk:126val [002,001] 125kkk:125val
=== SBLK[15] [003,030] 124kkk:124val [004,000] 123kkk:123val [005,029] 122kkk:122val
=== SBLK[15] [006,014] 121kkk:121val [007,028] 120kkk:120val [008,013] 119kkk:119val
=== SBLK[15] [009,027] 118kkk:118val [010,012] 117kkk:117val [011,026] 116kkk:116val
=== SBLK[15] [012,011] 115kkk:115val [013,025] 114kkk:114val [014,010] 113kkk:113val
=== SBLK[15] [015,024] 112kkk:112val [016,009] 111kkk:111val [017,023] 110kkk:110val
=== SBLK[15] [018,008] 109kkk:109val [019,022] 108kkk:108val
=== SBLK[63] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=15, db=1
=== SBLK[63] szpow=10, lkl=6, lk=107kkk
=== SBLK[63] [000,000] 107kkk:107val [001,001] 106kkk:106val [002,002] 105kkk:105val
=== SBLK[63] [003,003] 104kkk:104val [004,004] 103kkk:103val [005,005] 102kkk:102val
=== SBLK[63] [006,006] 101kkk:101val [007,007] 100kkk:100val [008,008] 099kkk:099val
=== SBLK[63] [009,009] 098kkk:098val [010,010] 097kkk:097val [011,011] 096kkk:096val
=== SBLK[63] [012,012] 095kkk:095val [013,013] 094kkk:094val [014,014] 093kkk:093val
=== SBLK[53] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=63, db=1
=== SBLK[53] szpow=10, lkl=6, lk=092kkk
=== SBLK[53] [000,000] 092kkk:092val [001,028] 091kkk:091val [002,001] 090kkk:090val
=== SBLK[53] [003,027] 089kkk:089val [004,002] 088kkk:088val [005,026] 087kkk:087val
=== SBLK[53] [006,003] 086kkk:086val [007,025] 085kkk:085val [008,004] 084kkk:084val
=== SBLK[53] [009,024] 083kkk:083val [010,005] 082kkk:082val [011,023] 081kkk:081val
=== SBLK[53] [012,006] 080kkk:080val [013,022] 079kkk:079val [014,007] 078kkk:078val
=== SBLK[53] [015,021] 077kkk:077val [016,008] 076kkk:076val [017,020] 075kkk:075val
=== SBLK[53] [018,009] 074kkk:074val [019,019] 073kkk:073val [020,010] 072kkk:072val
=== SBLK[53] [021,018] 071kkk:071val [022,011] 070kkk:070val [023,017] 069kkk:069val
=== SBLK[53] [024,012] 068kkk:068val [025,016] 067kkk:067val [026,013] 066kkk:066val
=== SBLK[53] [027,015] 065kkk:065val [028,014] 064kkk:064val
=== SBLK[9] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=53, db=1
=== SBLK[9] szpow=9, lkl=6, lk=063kkk
=== SBLK[9] [000,002] 063kkk:063val [001,031] 062kkk:062val [002,001] 061kkk:061val
=== SBLK[9] [003,030] 060kkk:060val [004,000] 059kkk:059val [005,029] 058kkk:058val
=== SBLK[9] [006,014] 057kkk:057val [007,028] 056kkk:056val [008,013] 055kkk:055val
=== SBLK[9] [009,027] 054kkk:054val [010,012] 053kkk:053val [011,026] 052kkk:052val
=== SBLK[9] [012,011] 051kkk:051val [013,025] 050kkk:050val [014,010] 049kkk:049val
=== SBLK[9] [015,024] 048kkk:048val [016,009] 047kkk:047val [017,023] 046kkk:046val
=== SBLK[9] [018,008] 045kkk:045val [019,022] 044kkk:044val
=== SBLK[43] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=9, db=1
=== SBLK[43] szpow=10, lkl=6, lk=043kkk
=== SBLK[43] [000,000] 043kkk:043val [001,001] 042kkk:042val [002,002] 041kkk:041val
=== SBLK[43] [003,003] 040kkk:040val [004,004] 039kkk:039val [005,005] 038kkk:038val
=== SBLK[43] [006,006] 037kkk:037val [007,007] 036kkk:036val [008,008] 035kkk:035val
=== SBLK[43] [009,009] 034kkk:034val [010,010] 033kkk:033val [011,011] 032kkk:032val
=== SBLK[43] [012,012] 031kkk:031val [013,013] 030kkk:030val [014,014] 029kkk:029val
=== SBLK[33] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=43, db=1
=== SBLK[33] szpow=10, lkl=6, lk=028kkk
=== SBLK[33] [000,000] 028kkk:028val [001,028] 027kkk:027val [002,001] 026kkk:026val
=== SBLK[33] [003,027] 025kkk:025val [004,002] 024kkk:024val [005,026] 023kkk:023val
=== SBLK[33] [006,003] 022kkk:022val [007,025] 021kkk:021val [008,004] 020kkk:020val
=== SBLK[33] [009,024] 019kkk:019val [010,005] 018kkk:018val [011,023] 017kkk:017val
=== SBLK[33] [012,006] 016kkk:016val [013,022] 015kkk:015val [014,007] 014kkk:014val
=== SBLK[33] [015,021] 013kkk:013val [016,008] 012kkk:012val [017,020] 011kkk:011val
=== SBLK[33] [018,009] 010kkk:010val [019,019] 009kkk:009val [020,010] 008kkk:008val
=== SBLK[33] [021,018] 007kkk:007val [022,011] 006kkk:006val [023,017] 005kkk:005val
=== SBLK[33] [024,012] 004kkk:004val [025,016] 003kkk:003val [026,013] 002kkk:002val
=== SBLK[33] [027,015] 001kkk:001val [028,014] 000kkk:000val
+528
View File
@@ -0,0 +1,528 @@
#### Stage: empty db
== DB[1] lvl=-1, blk=3, dbflg=0, p0=3
#### Stage: put foo:bar
== DB[1] lvl=-1, blk=3, dbflg=0, p0=9
=== SBLK[9] lvl=-1, pnum=1, flg=1, kvzidx=1, p0=3, db=1
=== SBLK[9] szpow=9, lkl=3, lk=foo
=== SBLK[9] [000,000] foo:bar
#### Stage: put foo:bazz
== DB[1] lvl=-1, blk=3, dbflg=0, p0=9
=== SBLK[9] lvl=-1, pnum=1, flg=1, kvzidx=1, p0=3, db=1
=== SBLK[9] szpow=9, lkl=3, lk=foo
=== SBLK[9] [000,000] foo:bazzz
#### Stage: put foo:
== DB[1] lvl=-1, blk=3, dbflg=0, p0=9
=== SBLK[9] lvl=-1, pnum=1, flg=1, kvzidx=1, p0=3, db=1
=== SBLK[9] szpow=9, lkl=3, lk=foo
=== SBLK[9] [000,000] foo:
#### Stage: put foo:bar
== DB[1] lvl=-1, blk=3, dbflg=0, p0=9
=== SBLK[9] lvl=-1, pnum=1, flg=1, kvzidx=1, p0=3, db=1
=== SBLK[9] szpow=9, lkl=3, lk=foo
=== SBLK[9] [000,000] foo:bar
#### Stage: remove foo:bar
== DB[1] lvl=-1, blk=3, dbflg=0, p0=3
#### Stage: fill up first block
== DB[1] lvl=-1, blk=3, dbflg=0, p0=9
=== SBLK[15] lvl=-1, pnum=31, flg=1, kvzidx=31, p0=3, db=1
=== SBLK[15] szpow=9, lkl=6, lk=252kkk
=== SBLK[15] [000,030] 252kkk:252val [001,029] 250kkk:250val [002,028] 248kkk:248val
=== SBLK[15] [003,027] 246kkk:246val [004,026] 244kkk:244val [005,025] 242kkk:242val
=== SBLK[15] [006,024] 240kkk:240val [007,023] 238kkk:238val [008,022] 236kkk:236val
=== SBLK[15] [009,021] 234kkk:234val [010,020] 232kkk:232val [011,019] 230kkk:230val
=== SBLK[15] [012,018] 228kkk:228val [013,017] 226kkk:226val [014,016] 224kkk:224val
=== SBLK[15] [015,015] 222kkk:222val [016,014] 220kkk:220val [017,013] 218kkk:218val
=== SBLK[15] [018,012] 216kkk:216val [019,011] 214kkk:214val [020,010] 212kkk:212val
=== SBLK[15] [021,009] 210kkk:210val [022,008] 208kkk:208val [023,007] 206kkk:206val
=== SBLK[15] [024,006] 204kkk:204val [025,005] 202kkk:202val [026,004] 200kkk:200val
=== SBLK[15] [027,003] 198kkk:198val [028,002] 196kkk:196val [029,001] 194kkk:194val
=== SBLK[15] [030,000] 192kkk:192val
=== SBLK[13] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=15, db=1
=== SBLK[13] szpow=9, lkl=6, lk=190kkk
=== SBLK[13] [000,031] 190kkk:190val [001,030] 188kkk:188val [002,029] 186kkk:186val
=== SBLK[13] [003,028] 184kkk:184val [004,027] 182kkk:182val [005,026] 180kkk:180val
=== SBLK[13] [006,025] 178kkk:178val [007,024] 176kkk:176val [008,023] 174kkk:174val
=== SBLK[13] [009,022] 172kkk:172val [010,021] 170kkk:170val [011,020] 168kkk:168val
=== SBLK[13] [012,019] 166kkk:166val [013,018] 164kkk:164val [014,017] 162kkk:162val
=== SBLK[13] [015,016] 160kkk:160val [016,015] 158kkk:158val [017,014] 156kkk:156val
=== SBLK[13] [018,013] 154kkk:154val [019,012] 152kkk:152val [020,011] 150kkk:150val
=== SBLK[13] [021,010] 148kkk:148val [022,009] 146kkk:146val [023,008] 144kkk:144val
=== SBLK[13] [024,007] 142kkk:142val [025,006] 140kkk:140val [026,005] 138kkk:138val
=== SBLK[13] [027,004] 136kkk:136val [028,003] 134kkk:134val [029,002] 132kkk:132val
=== SBLK[13] [030,001] 130kkk:130val [031,000] 128kkk:128val
=== SBLK[11] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=13, db=1
=== SBLK[11] szpow=9, lkl=6, lk=126kkk
=== SBLK[11] [000,031] 126kkk:126val [001,030] 124kkk:124val [002,029] 122kkk:122val
=== SBLK[11] [003,028] 120kkk:120val [004,027] 118kkk:118val [005,026] 116kkk:116val
=== SBLK[11] [006,025] 114kkk:114val [007,024] 112kkk:112val [008,023] 110kkk:110val
=== SBLK[11] [009,022] 108kkk:108val [010,021] 106kkk:106val [011,020] 104kkk:104val
=== SBLK[11] [012,019] 102kkk:102val [013,018] 100kkk:100val [014,017] 098kkk:098val
=== SBLK[11] [015,016] 096kkk:096val [016,015] 094kkk:094val [017,014] 092kkk:092val
=== SBLK[11] [018,013] 090kkk:090val [019,012] 088kkk:088val [020,011] 086kkk:086val
=== SBLK[11] [021,010] 084kkk:084val [022,009] 082kkk:082val [023,008] 080kkk:080val
=== SBLK[11] [024,007] 078kkk:078val [025,006] 076kkk:076val [026,005] 074kkk:074val
=== SBLK[11] [027,004] 072kkk:072val [028,003] 070kkk:070val [029,002] 068kkk:068val
=== SBLK[11] [030,001] 066kkk:066val [031,000] 064kkk:064val
=== SBLK[9] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=11, db=1
=== SBLK[9] szpow=9, lkl=6, lk=062kkk
=== SBLK[9] [000,031] 062kkk:062val [001,030] 060kkk:060val [002,029] 058kkk:058val
=== SBLK[9] [003,028] 056kkk:056val [004,027] 054kkk:054val [005,026] 052kkk:052val
=== SBLK[9] [006,025] 050kkk:050val [007,024] 048kkk:048val [008,023] 046kkk:046val
=== SBLK[9] [009,022] 044kkk:044val [010,021] 042kkk:042val [011,020] 040kkk:040val
=== SBLK[9] [012,019] 038kkk:038val [013,018] 036kkk:036val [014,017] 034kkk:034val
=== SBLK[9] [015,016] 032kkk:032val [016,015] 030kkk:030val [017,014] 028kkk:028val
=== SBLK[9] [018,013] 026kkk:026val [019,012] 024kkk:024val [020,011] 022kkk:022val
=== SBLK[9] [021,010] 020kkk:020val [022,009] 018kkk:018val [023,008] 016kkk:016val
=== SBLK[9] [024,007] 014kkk:014val [025,006] 012kkk:012val [026,005] 010kkk:010val
=== SBLK[9] [027,004] 008kkk:008val [028,003] 006kkk:006val [029,002] 004kkk:004val
=== SBLK[9] [030,001] 002kkk:002val [031,000] 000kkk:000val
#### Stage: fill up second block
== DB[1] lvl=-1, blk=3, dbflg=0, p0=17
=== SBLK[15] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=3, db=1
=== SBLK[15] szpow=9, lkl=6, lk=253kkk
=== SBLK[15] [000,002] 253kkk:253val [001,030] 252kkk:252val [002,001] 251kkk:251val
=== SBLK[15] [003,029] 250kkk:250val [004,000] 249kkk:249val [005,028] 248kkk:248val
=== SBLK[15] [006,031] 247kkk:247val [007,027] 246kkk:246val [008,013] 245kkk:245val
=== SBLK[15] [009,026] 244kkk:244val [010,012] 243kkk:243val [011,025] 242kkk:242val
=== SBLK[15] [012,011] 241kkk:241val [013,024] 240kkk:240val [014,010] 239kkk:239val
=== SBLK[15] [015,023] 238kkk:238val [016,009] 237kkk:237val [017,022] 236kkk:236val
=== SBLK[15] [018,008] 235kkk:235val [019,021] 234kkk:234val
=== SBLK[31] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=15, db=1
=== SBLK[31] szpow=10, lkl=6, lk=233kkk
=== SBLK[31] [000,000] 233kkk:233val [001,001] 232kkk:232val [002,002] 231kkk:231val
=== SBLK[31] [003,003] 230kkk:230val [004,004] 229kkk:229val [005,005] 228kkk:228val
=== SBLK[31] [006,006] 227kkk:227val [007,007] 226kkk:226val [008,008] 225kkk:225val
=== SBLK[31] [009,009] 224kkk:224val [010,010] 223kkk:223val [011,011] 222kkk:222val
=== SBLK[31] [012,012] 221kkk:221val [013,013] 220kkk:220val [014,014] 219kkk:219val
=== SBLK[29] lvl=-1, pnum=28, flg=1, kvzidx=28, p0=31, db=1
=== SBLK[29] szpow=10, lkl=6, lk=218kkk
=== SBLK[29] [000,000] 218kkk:218val [001,027] 217kkk:217val [002,001] 216kkk:216val
=== SBLK[29] [003,026] 215kkk:215val [004,002] 214kkk:214val [005,025] 213kkk:213val
=== SBLK[29] [006,003] 212kkk:212val [007,024] 211kkk:211val [008,004] 210kkk:210val
=== SBLK[29] [009,023] 209kkk:209val [010,005] 208kkk:208val [011,022] 207kkk:207val
=== SBLK[29] [012,006] 206kkk:206val [013,021] 205kkk:205val [014,007] 204kkk:204val
=== SBLK[29] [015,020] 203kkk:203val [016,008] 202kkk:202val [017,019] 201kkk:201val
=== SBLK[29] [018,009] 200kkk:200val [019,018] 199kkk:199val [020,010] 198kkk:198val
=== SBLK[29] [021,017] 197kkk:197val [022,011] 196kkk:196val [023,016] 195kkk:195val
=== SBLK[29] [024,012] 194kkk:194val [025,015] 193kkk:193val [026,013] 192kkk:192val
=== SBLK[29] [027,014] 191kkk:191val
=== SBLK[13] lvl=-1, pnum=19, flg=1, kvzidx=2, p0=29, db=1
=== SBLK[13] szpow=9, lkl=6, lk=190kkk
=== SBLK[13] [000,031] 190kkk:190val [001,001] 189kkk:189val [002,030] 188kkk:188val
=== SBLK[13] [003,000] 187kkk:187val [004,029] 186kkk:186val [005,014] 185kkk:185val
=== SBLK[13] [006,028] 184kkk:184val [007,013] 183kkk:183val [008,027] 182kkk:182val
=== SBLK[13] [009,012] 181kkk:181val [010,026] 180kkk:180val [011,011] 179kkk:179val
=== SBLK[13] [012,025] 178kkk:178val [013,010] 177kkk:177val [014,024] 176kkk:176val
=== SBLK[13] [015,009] 175kkk:175val [016,023] 174kkk:174val [017,008] 173kkk:173val
=== SBLK[13] [018,022] 172kkk:172val
=== SBLK[27] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=13, db=1
=== SBLK[27] szpow=10, lkl=6, lk=171kkk
=== SBLK[27] [000,000] 171kkk:171val [001,001] 170kkk:170val [002,002] 169kkk:169val
=== SBLK[27] [003,003] 168kkk:168val [004,004] 167kkk:167val [005,005] 166kkk:166val
=== SBLK[27] [006,006] 165kkk:165val [007,007] 164kkk:164val [008,008] 163kkk:163val
=== SBLK[27] [009,009] 162kkk:162val [010,010] 161kkk:161val [011,011] 160kkk:160val
=== SBLK[27] [012,012] 159kkk:159val [013,013] 158kkk:158val [014,014] 157kkk:157val
=== SBLK[25] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=27, db=1
=== SBLK[25] szpow=10, lkl=6, lk=156kkk
=== SBLK[25] [000,000] 156kkk:156val [001,028] 155kkk:155val [002,001] 154kkk:154val
=== SBLK[25] [003,027] 153kkk:153val [004,002] 152kkk:152val [005,026] 151kkk:151val
=== SBLK[25] [006,003] 150kkk:150val [007,025] 149kkk:149val [008,004] 148kkk:148val
=== SBLK[25] [009,024] 147kkk:147val [010,005] 146kkk:146val [011,023] 145kkk:145val
=== SBLK[25] [012,006] 144kkk:144val [013,022] 143kkk:143val [014,007] 142kkk:142val
=== SBLK[25] [015,021] 141kkk:141val [016,008] 140kkk:140val [017,020] 139kkk:139val
=== SBLK[25] [018,009] 138kkk:138val [019,019] 137kkk:137val [020,010] 136kkk:136val
=== SBLK[25] [021,018] 135kkk:135val [022,011] 134kkk:134val [023,017] 133kkk:133val
=== SBLK[25] [024,012] 132kkk:132val [025,016] 131kkk:131val [026,013] 130kkk:130val
=== SBLK[25] [027,015] 129kkk:129val [028,014] 128kkk:128val
=== SBLK[11] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=25, db=1
=== SBLK[11] szpow=9, lkl=6, lk=127kkk
=== SBLK[11] [000,002] 127kkk:127val [001,031] 126kkk:126val [002,001] 125kkk:125val
=== SBLK[11] [003,030] 124kkk:124val [004,000] 123kkk:123val [005,029] 122kkk:122val
=== SBLK[11] [006,014] 121kkk:121val [007,028] 120kkk:120val [008,013] 119kkk:119val
=== SBLK[11] [009,027] 118kkk:118val [010,012] 117kkk:117val [011,026] 116kkk:116val
=== SBLK[11] [012,011] 115kkk:115val [013,025] 114kkk:114val [014,010] 113kkk:113val
=== SBLK[11] [015,024] 112kkk:112val [016,009] 111kkk:111val [017,023] 110kkk:110val
=== SBLK[11] [018,008] 109kkk:109val [019,022] 108kkk:108val
=== SBLK[23] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=11, db=1
=== SBLK[23] szpow=10, lkl=6, lk=107kkk
=== SBLK[23] [000,000] 107kkk:107val [001,001] 106kkk:106val [002,002] 105kkk:105val
=== SBLK[23] [003,003] 104kkk:104val [004,004] 103kkk:103val [005,005] 102kkk:102val
=== SBLK[23] [006,006] 101kkk:101val [007,007] 100kkk:100val [008,008] 099kkk:099val
=== SBLK[23] [009,009] 098kkk:098val [010,010] 097kkk:097val [011,011] 096kkk:096val
=== SBLK[23] [012,012] 095kkk:095val [013,013] 094kkk:094val [014,014] 093kkk:093val
=== SBLK[21] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=23, db=1
=== SBLK[21] szpow=10, lkl=6, lk=092kkk
=== SBLK[21] [000,000] 092kkk:092val [001,028] 091kkk:091val [002,001] 090kkk:090val
=== SBLK[21] [003,027] 089kkk:089val [004,002] 088kkk:088val [005,026] 087kkk:087val
=== SBLK[21] [006,003] 086kkk:086val [007,025] 085kkk:085val [008,004] 084kkk:084val
=== SBLK[21] [009,024] 083kkk:083val [010,005] 082kkk:082val [011,023] 081kkk:081val
=== SBLK[21] [012,006] 080kkk:080val [013,022] 079kkk:079val [014,007] 078kkk:078val
=== SBLK[21] [015,021] 077kkk:077val [016,008] 076kkk:076val [017,020] 075kkk:075val
=== SBLK[21] [018,009] 074kkk:074val [019,019] 073kkk:073val [020,010] 072kkk:072val
=== SBLK[21] [021,018] 071kkk:071val [022,011] 070kkk:070val [023,017] 069kkk:069val
=== SBLK[21] [024,012] 068kkk:068val [025,016] 067kkk:067val [026,013] 066kkk:066val
=== SBLK[21] [027,015] 065kkk:065val [028,014] 064kkk:064val
=== SBLK[9] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=21, db=1
=== SBLK[9] szpow=9, lkl=6, lk=063kkk
=== SBLK[9] [000,002] 063kkk:063val [001,031] 062kkk:062val [002,001] 061kkk:061val
=== SBLK[9] [003,030] 060kkk:060val [004,000] 059kkk:059val [005,029] 058kkk:058val
=== SBLK[9] [006,014] 057kkk:057val [007,028] 056kkk:056val [008,013] 055kkk:055val
=== SBLK[9] [009,027] 054kkk:054val [010,012] 053kkk:053val [011,026] 052kkk:052val
=== SBLK[9] [012,011] 051kkk:051val [013,025] 050kkk:050val [014,010] 049kkk:049val
=== SBLK[9] [015,024] 048kkk:048val [016,009] 047kkk:047val [017,023] 046kkk:046val
=== SBLK[9] [018,008] 045kkk:045val [019,022] 044kkk:044val
=== SBLK[19] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=9, db=1
=== SBLK[19] szpow=10, lkl=6, lk=043kkk
=== SBLK[19] [000,000] 043kkk:043val [001,001] 042kkk:042val [002,002] 041kkk:041val
=== SBLK[19] [003,003] 040kkk:040val [004,004] 039kkk:039val [005,005] 038kkk:038val
=== SBLK[19] [006,006] 037kkk:037val [007,007] 036kkk:036val [008,008] 035kkk:035val
=== SBLK[19] [009,009] 034kkk:034val [010,010] 033kkk:033val [011,011] 032kkk:032val
=== SBLK[19] [012,012] 031kkk:031val [013,013] 030kkk:030val [014,014] 029kkk:029val
=== SBLK[17] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=19, db=1
=== SBLK[17] szpow=10, lkl=6, lk=028kkk
=== SBLK[17] [000,000] 028kkk:028val [001,028] 027kkk:027val [002,001] 026kkk:026val
=== SBLK[17] [003,027] 025kkk:025val [004,002] 024kkk:024val [005,026] 023kkk:023val
=== SBLK[17] [006,003] 022kkk:022val [007,025] 021kkk:021val [008,004] 020kkk:020val
=== SBLK[17] [009,024] 019kkk:019val [010,005] 018kkk:018val [011,023] 017kkk:017val
=== SBLK[17] [012,006] 016kkk:016val [013,022] 015kkk:015val [014,007] 014kkk:014val
=== SBLK[17] [015,021] 013kkk:013val [016,008] 012kkk:012val [017,020] 011kkk:011val
=== SBLK[17] [018,009] 010kkk:010val [019,019] 009kkk:009val [020,010] 008kkk:008val
=== SBLK[17] [021,018] 007kkk:007val [022,011] 006kkk:006val [023,017] 005kkk:005val
=== SBLK[17] [024,012] 004kkk:004val [025,016] 003kkk:003val [026,013] 002kkk:002val
=== SBLK[17] [027,015] 001kkk:001val [028,014] 000kkk:000val
#### Stage: state after reopen
== DB[1] lvl=-1, blk=3, dbflg=0, p0=17
=== SBLK[15] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=3, db=1
=== SBLK[15] szpow=9, lkl=6, lk=253kkk
=== SBLK[15] [000,002] 253kkk:253val [001,030] 252kkk:252val [002,001] 251kkk:251val
=== SBLK[15] [003,029] 250kkk:250val [004,000] 249kkk:249val [005,028] 248kkk:248val
=== SBLK[15] [006,031] 247kkk:247val [007,027] 246kkk:246val [008,013] 245kkk:245val
=== SBLK[15] [009,026] 244kkk:244val [010,012] 243kkk:243val [011,025] 242kkk:242val
=== SBLK[15] [012,011] 241kkk:241val [013,024] 240kkk:240val [014,010] 239kkk:239val
=== SBLK[15] [015,023] 238kkk:238val [016,009] 237kkk:237val [017,022] 236kkk:236val
=== SBLK[15] [018,008] 235kkk:235val [019,021] 234kkk:234val
=== SBLK[31] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=15, db=1
=== SBLK[31] szpow=10, lkl=6, lk=233kkk
=== SBLK[31] [000,000] 233kkk:233val [001,001] 232kkk:232val [002,002] 231kkk:231val
=== SBLK[31] [003,003] 230kkk:230val [004,004] 229kkk:229val [005,005] 228kkk:228val
=== SBLK[31] [006,006] 227kkk:227val [007,007] 226kkk:226val [008,008] 225kkk:225val
=== SBLK[31] [009,009] 224kkk:224val [010,010] 223kkk:223val [011,011] 222kkk:222val
=== SBLK[31] [012,012] 221kkk:221val [013,013] 220kkk:220val [014,014] 219kkk:219val
=== SBLK[29] lvl=-1, pnum=28, flg=1, kvzidx=28, p0=31, db=1
=== SBLK[29] szpow=10, lkl=6, lk=218kkk
=== SBLK[29] [000,000] 218kkk:218val [001,027] 217kkk:217val [002,001] 216kkk:216val
=== SBLK[29] [003,026] 215kkk:215val [004,002] 214kkk:214val [005,025] 213kkk:213val
=== SBLK[29] [006,003] 212kkk:212val [007,024] 211kkk:211val [008,004] 210kkk:210val
=== SBLK[29] [009,023] 209kkk:209val [010,005] 208kkk:208val [011,022] 207kkk:207val
=== SBLK[29] [012,006] 206kkk:206val [013,021] 205kkk:205val [014,007] 204kkk:204val
=== SBLK[29] [015,020] 203kkk:203val [016,008] 202kkk:202val [017,019] 201kkk:201val
=== SBLK[29] [018,009] 200kkk:200val [019,018] 199kkk:199val [020,010] 198kkk:198val
=== SBLK[29] [021,017] 197kkk:197val [022,011] 196kkk:196val [023,016] 195kkk:195val
=== SBLK[29] [024,012] 194kkk:194val [025,015] 193kkk:193val [026,013] 192kkk:192val
=== SBLK[29] [027,014] 191kkk:191val
=== SBLK[13] lvl=-1, pnum=19, flg=1, kvzidx=2, p0=29, db=1
=== SBLK[13] szpow=9, lkl=6, lk=190kkk
=== SBLK[13] [000,031] 190kkk:190val [001,001] 189kkk:189val [002,030] 188kkk:188val
=== SBLK[13] [003,000] 187kkk:187val [004,029] 186kkk:186val [005,014] 185kkk:185val
=== SBLK[13] [006,028] 184kkk:184val [007,013] 183kkk:183val [008,027] 182kkk:182val
=== SBLK[13] [009,012] 181kkk:181val [010,026] 180kkk:180val [011,011] 179kkk:179val
=== SBLK[13] [012,025] 178kkk:178val [013,010] 177kkk:177val [014,024] 176kkk:176val
=== SBLK[13] [015,009] 175kkk:175val [016,023] 174kkk:174val [017,008] 173kkk:173val
=== SBLK[13] [018,022] 172kkk:172val
=== SBLK[27] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=13, db=1
=== SBLK[27] szpow=10, lkl=6, lk=171kkk
=== SBLK[27] [000,000] 171kkk:171val [001,001] 170kkk:170val [002,002] 169kkk:169val
=== SBLK[27] [003,003] 168kkk:168val [004,004] 167kkk:167val [005,005] 166kkk:166val
=== SBLK[27] [006,006] 165kkk:165val [007,007] 164kkk:164val [008,008] 163kkk:163val
=== SBLK[27] [009,009] 162kkk:162val [010,010] 161kkk:161val [011,011] 160kkk:160val
=== SBLK[27] [012,012] 159kkk:159val [013,013] 158kkk:158val [014,014] 157kkk:157val
=== SBLK[25] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=27, db=1
=== SBLK[25] szpow=10, lkl=6, lk=156kkk
=== SBLK[25] [000,000] 156kkk:156val [001,028] 155kkk:155val [002,001] 154kkk:154val
=== SBLK[25] [003,027] 153kkk:153val [004,002] 152kkk:152val [005,026] 151kkk:151val
=== SBLK[25] [006,003] 150kkk:150val [007,025] 149kkk:149val [008,004] 148kkk:148val
=== SBLK[25] [009,024] 147kkk:147val [010,005] 146kkk:146val [011,023] 145kkk:145val
=== SBLK[25] [012,006] 144kkk:144val [013,022] 143kkk:143val [014,007] 142kkk:142val
=== SBLK[25] [015,021] 141kkk:141val [016,008] 140kkk:140val [017,020] 139kkk:139val
=== SBLK[25] [018,009] 138kkk:138val [019,019] 137kkk:137val [020,010] 136kkk:136val
=== SBLK[25] [021,018] 135kkk:135val [022,011] 134kkk:134val [023,017] 133kkk:133val
=== SBLK[25] [024,012] 132kkk:132val [025,016] 131kkk:131val [026,013] 130kkk:130val
=== SBLK[25] [027,015] 129kkk:129val [028,014] 128kkk:128val
=== SBLK[11] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=25, db=1
=== SBLK[11] szpow=9, lkl=6, lk=127kkk
=== SBLK[11] [000,002] 127kkk:127val [001,031] 126kkk:126val [002,001] 125kkk:125val
=== SBLK[11] [003,030] 124kkk:124val [004,000] 123kkk:123val [005,029] 122kkk:122val
=== SBLK[11] [006,014] 121kkk:121val [007,028] 120kkk:120val [008,013] 119kkk:119val
=== SBLK[11] [009,027] 118kkk:118val [010,012] 117kkk:117val [011,026] 116kkk:116val
=== SBLK[11] [012,011] 115kkk:115val [013,025] 114kkk:114val [014,010] 113kkk:113val
=== SBLK[11] [015,024] 112kkk:112val [016,009] 111kkk:111val [017,023] 110kkk:110val
=== SBLK[11] [018,008] 109kkk:109val [019,022] 108kkk:108val
=== SBLK[23] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=11, db=1
=== SBLK[23] szpow=10, lkl=6, lk=107kkk
=== SBLK[23] [000,000] 107kkk:107val [001,001] 106kkk:106val [002,002] 105kkk:105val
=== SBLK[23] [003,003] 104kkk:104val [004,004] 103kkk:103val [005,005] 102kkk:102val
=== SBLK[23] [006,006] 101kkk:101val [007,007] 100kkk:100val [008,008] 099kkk:099val
=== SBLK[23] [009,009] 098kkk:098val [010,010] 097kkk:097val [011,011] 096kkk:096val
=== SBLK[23] [012,012] 095kkk:095val [013,013] 094kkk:094val [014,014] 093kkk:093val
=== SBLK[21] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=23, db=1
=== SBLK[21] szpow=10, lkl=6, lk=092kkk
=== SBLK[21] [000,000] 092kkk:092val [001,028] 091kkk:091val [002,001] 090kkk:090val
=== SBLK[21] [003,027] 089kkk:089val [004,002] 088kkk:088val [005,026] 087kkk:087val
=== SBLK[21] [006,003] 086kkk:086val [007,025] 085kkk:085val [008,004] 084kkk:084val
=== SBLK[21] [009,024] 083kkk:083val [010,005] 082kkk:082val [011,023] 081kkk:081val
=== SBLK[21] [012,006] 080kkk:080val [013,022] 079kkk:079val [014,007] 078kkk:078val
=== SBLK[21] [015,021] 077kkk:077val [016,008] 076kkk:076val [017,020] 075kkk:075val
=== SBLK[21] [018,009] 074kkk:074val [019,019] 073kkk:073val [020,010] 072kkk:072val
=== SBLK[21] [021,018] 071kkk:071val [022,011] 070kkk:070val [023,017] 069kkk:069val
=== SBLK[21] [024,012] 068kkk:068val [025,016] 067kkk:067val [026,013] 066kkk:066val
=== SBLK[21] [027,015] 065kkk:065val [028,014] 064kkk:064val
=== SBLK[9] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=21, db=1
=== SBLK[9] szpow=9, lkl=6, lk=063kkk
=== SBLK[9] [000,002] 063kkk:063val [001,031] 062kkk:062val [002,001] 061kkk:061val
=== SBLK[9] [003,030] 060kkk:060val [004,000] 059kkk:059val [005,029] 058kkk:058val
=== SBLK[9] [006,014] 057kkk:057val [007,028] 056kkk:056val [008,013] 055kkk:055val
=== SBLK[9] [009,027] 054kkk:054val [010,012] 053kkk:053val [011,026] 052kkk:052val
=== SBLK[9] [012,011] 051kkk:051val [013,025] 050kkk:050val [014,010] 049kkk:049val
=== SBLK[9] [015,024] 048kkk:048val [016,009] 047kkk:047val [017,023] 046kkk:046val
=== SBLK[9] [018,008] 045kkk:045val [019,022] 044kkk:044val
=== SBLK[19] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=9, db=1
=== SBLK[19] szpow=10, lkl=6, lk=043kkk
=== SBLK[19] [000,000] 043kkk:043val [001,001] 042kkk:042val [002,002] 041kkk:041val
=== SBLK[19] [003,003] 040kkk:040val [004,004] 039kkk:039val [005,005] 038kkk:038val
=== SBLK[19] [006,006] 037kkk:037val [007,007] 036kkk:036val [008,008] 035kkk:035val
=== SBLK[19] [009,009] 034kkk:034val [010,010] 033kkk:033val [011,011] 032kkk:032val
=== SBLK[19] [012,012] 031kkk:031val [013,013] 030kkk:030val [014,014] 029kkk:029val
=== SBLK[17] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=19, db=1
=== SBLK[17] szpow=10, lkl=6, lk=028kkk
=== SBLK[17] [000,000] 028kkk:028val [001,028] 027kkk:027val [002,001] 026kkk:026val
=== SBLK[17] [003,027] 025kkk:025val [004,002] 024kkk:024val [005,026] 023kkk:023val
=== SBLK[17] [006,003] 022kkk:022val [007,025] 021kkk:021val [008,004] 020kkk:020val
=== SBLK[17] [009,024] 019kkk:019val [010,005] 018kkk:018val [011,023] 017kkk:017val
=== SBLK[17] [012,006] 016kkk:016val [013,022] 015kkk:015val [014,007] 014kkk:014val
=== SBLK[17] [015,021] 013kkk:013val [016,008] 012kkk:012val [017,020] 011kkk:011val
=== SBLK[17] [018,009] 010kkk:010val [019,019] 009kkk:009val [020,010] 008kkk:008val
=== SBLK[17] [021,018] 007kkk:007val [022,011] 006kkk:006val [023,017] 005kkk:005val
=== SBLK[17] [024,012] 004kkk:004val [025,016] 003kkk:003val [026,013] 002kkk:002val
=== SBLK[17] [027,015] 001kkk:001val [028,014] 000kkk:000val
#### Stage: a big key
== DB[1] lvl=-1, blk=3, dbflg=0, p0=17
=== SBLK[15] lvl=-1, pnum=21, flg=1, kvzidx=4, p0=3, db=1
=== SBLK[15] szpow=9, lkl=71, lk=abracadabrabracadabrabracadabrabracadabrabracadabrabracadabrabracadabr1
=== SBLK[15] [000,003] abracadabrabracadabrabracadabrabracadabrabracadabrabracadabrabracadabr1:vabracadabrabracadabrabracadabrabracadabrabracadabrabracadabrabracadabr [001,002] 253kkk:253val [002,030] 252kkk:252val
=== SBLK[15] [003,001] 251kkk:251val [004,029] 250kkk:250val [005,000] 249kkk:249val
=== SBLK[15] [006,028] 248kkk:248val [007,031] 247kkk:247val [008,027] 246kkk:246val
=== SBLK[15] [009,013] 245kkk:245val [010,026] 244kkk:244val [011,012] 243kkk:243val
=== SBLK[15] [012,025] 242kkk:242val [013,011] 241kkk:241val [014,024] 240kkk:240val
=== SBLK[15] [015,010] 239kkk:239val [016,023] 238kkk:238val [017,009] 237kkk:237val
=== SBLK[15] [018,022] 236kkk:236val [019,008] 235kkk:235val [020,021] 234kkk:234val
=== SBLK[31] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=15, db=1
=== SBLK[31] szpow=10, lkl=6, lk=233kkk
=== SBLK[31] [000,000] 233kkk:233val [001,001] 232kkk:232val [002,002] 231kkk:231val
=== SBLK[31] [003,003] 230kkk:230val [004,004] 229kkk:229val [005,005] 228kkk:228val
=== SBLK[31] [006,006] 227kkk:227val [007,007] 226kkk:226val [008,008] 225kkk:225val
=== SBLK[31] [009,009] 224kkk:224val [010,010] 223kkk:223val [011,011] 222kkk:222val
=== SBLK[31] [012,012] 221kkk:221val [013,013] 220kkk:220val [014,014] 219kkk:219val
=== SBLK[29] lvl=-1, pnum=28, flg=1, kvzidx=28, p0=31, db=1
=== SBLK[29] szpow=10, lkl=6, lk=218kkk
=== SBLK[29] [000,000] 218kkk:218val [001,027] 217kkk:217val [002,001] 216kkk:216val
=== SBLK[29] [003,026] 215kkk:215val [004,002] 214kkk:214val [005,025] 213kkk:213val
=== SBLK[29] [006,003] 212kkk:212val [007,024] 211kkk:211val [008,004] 210kkk:210val
=== SBLK[29] [009,023] 209kkk:209val [010,005] 208kkk:208val [011,022] 207kkk:207val
=== SBLK[29] [012,006] 206kkk:206val [013,021] 205kkk:205val [014,007] 204kkk:204val
=== SBLK[29] [015,020] 203kkk:203val [016,008] 202kkk:202val [017,019] 201kkk:201val
=== SBLK[29] [018,009] 200kkk:200val [019,018] 199kkk:199val [020,010] 198kkk:198val
=== SBLK[29] [021,017] 197kkk:197val [022,011] 196kkk:196val [023,016] 195kkk:195val
=== SBLK[29] [024,012] 194kkk:194val [025,015] 193kkk:193val [026,013] 192kkk:192val
=== SBLK[29] [027,014] 191kkk:191val
=== SBLK[13] lvl=-1, pnum=19, flg=1, kvzidx=2, p0=29, db=1
=== SBLK[13] szpow=9, lkl=6, lk=190kkk
=== SBLK[13] [000,031] 190kkk:190val [001,001] 189kkk:189val [002,030] 188kkk:188val
=== SBLK[13] [003,000] 187kkk:187val [004,029] 186kkk:186val [005,014] 185kkk:185val
=== SBLK[13] [006,028] 184kkk:184val [007,013] 183kkk:183val [008,027] 182kkk:182val
=== SBLK[13] [009,012] 181kkk:181val [010,026] 180kkk:180val [011,011] 179kkk:179val
=== SBLK[13] [012,025] 178kkk:178val [013,010] 177kkk:177val [014,024] 176kkk:176val
=== SBLK[13] [015,009] 175kkk:175val [016,023] 174kkk:174val [017,008] 173kkk:173val
=== SBLK[13] [018,022] 172kkk:172val
=== SBLK[27] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=13, db=1
=== SBLK[27] szpow=10, lkl=6, lk=171kkk
=== SBLK[27] [000,000] 171kkk:171val [001,001] 170kkk:170val [002,002] 169kkk:169val
=== SBLK[27] [003,003] 168kkk:168val [004,004] 167kkk:167val [005,005] 166kkk:166val
=== SBLK[27] [006,006] 165kkk:165val [007,007] 164kkk:164val [008,008] 163kkk:163val
=== SBLK[27] [009,009] 162kkk:162val [010,010] 161kkk:161val [011,011] 160kkk:160val
=== SBLK[27] [012,012] 159kkk:159val [013,013] 158kkk:158val [014,014] 157kkk:157val
=== SBLK[25] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=27, db=1
=== SBLK[25] szpow=10, lkl=6, lk=156kkk
=== SBLK[25] [000,000] 156kkk:156val [001,028] 155kkk:155val [002,001] 154kkk:154val
=== SBLK[25] [003,027] 153kkk:153val [004,002] 152kkk:152val [005,026] 151kkk:151val
=== SBLK[25] [006,003] 150kkk:150val [007,025] 149kkk:149val [008,004] 148kkk:148val
=== SBLK[25] [009,024] 147kkk:147val [010,005] 146kkk:146val [011,023] 145kkk:145val
=== SBLK[25] [012,006] 144kkk:144val [013,022] 143kkk:143val [014,007] 142kkk:142val
=== SBLK[25] [015,021] 141kkk:141val [016,008] 140kkk:140val [017,020] 139kkk:139val
=== SBLK[25] [018,009] 138kkk:138val [019,019] 137kkk:137val [020,010] 136kkk:136val
=== SBLK[25] [021,018] 135kkk:135val [022,011] 134kkk:134val [023,017] 133kkk:133val
=== SBLK[25] [024,012] 132kkk:132val [025,016] 131kkk:131val [026,013] 130kkk:130val
=== SBLK[25] [027,015] 129kkk:129val [028,014] 128kkk:128val
=== SBLK[11] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=25, db=1
=== SBLK[11] szpow=9, lkl=6, lk=127kkk
=== SBLK[11] [000,002] 127kkk:127val [001,031] 126kkk:126val [002,001] 125kkk:125val
=== SBLK[11] [003,030] 124kkk:124val [004,000] 123kkk:123val [005,029] 122kkk:122val
=== SBLK[11] [006,014] 121kkk:121val [007,028] 120kkk:120val [008,013] 119kkk:119val
=== SBLK[11] [009,027] 118kkk:118val [010,012] 117kkk:117val [011,026] 116kkk:116val
=== SBLK[11] [012,011] 115kkk:115val [013,025] 114kkk:114val [014,010] 113kkk:113val
=== SBLK[11] [015,024] 112kkk:112val [016,009] 111kkk:111val [017,023] 110kkk:110val
=== SBLK[11] [018,008] 109kkk:109val [019,022] 108kkk:108val
=== SBLK[23] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=11, db=1
=== SBLK[23] szpow=10, lkl=6, lk=107kkk
=== SBLK[23] [000,000] 107kkk:107val [001,001] 106kkk:106val [002,002] 105kkk:105val
=== SBLK[23] [003,003] 104kkk:104val [004,004] 103kkk:103val [005,005] 102kkk:102val
=== SBLK[23] [006,006] 101kkk:101val [007,007] 100kkk:100val [008,008] 099kkk:099val
=== SBLK[23] [009,009] 098kkk:098val [010,010] 097kkk:097val [011,011] 096kkk:096val
=== SBLK[23] [012,012] 095kkk:095val [013,013] 094kkk:094val [014,014] 093kkk:093val
=== SBLK[21] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=23, db=1
=== SBLK[21] szpow=10, lkl=6, lk=092kkk
=== SBLK[21] [000,000] 092kkk:092val [001,028] 091kkk:091val [002,001] 090kkk:090val
=== SBLK[21] [003,027] 089kkk:089val [004,002] 088kkk:088val [005,026] 087kkk:087val
=== SBLK[21] [006,003] 086kkk:086val [007,025] 085kkk:085val [008,004] 084kkk:084val
=== SBLK[21] [009,024] 083kkk:083val [010,005] 082kkk:082val [011,023] 081kkk:081val
=== SBLK[21] [012,006] 080kkk:080val [013,022] 079kkk:079val [014,007] 078kkk:078val
=== SBLK[21] [015,021] 077kkk:077val [016,008] 076kkk:076val [017,020] 075kkk:075val
=== SBLK[21] [018,009] 074kkk:074val [019,019] 073kkk:073val [020,010] 072kkk:072val
=== SBLK[21] [021,018] 071kkk:071val [022,011] 070kkk:070val [023,017] 069kkk:069val
=== SBLK[21] [024,012] 068kkk:068val [025,016] 067kkk:067val [026,013] 066kkk:066val
=== SBLK[21] [027,015] 065kkk:065val [028,014] 064kkk:064val
=== SBLK[9] lvl=-1, pnum=20, flg=1, kvzidx=3, p0=21, db=1
=== SBLK[9] szpow=9, lkl=6, lk=063kkk
=== SBLK[9] [000,002] 063kkk:063val [001,031] 062kkk:062val [002,001] 061kkk:061val
=== SBLK[9] [003,030] 060kkk:060val [004,000] 059kkk:059val [005,029] 058kkk:058val
=== SBLK[9] [006,014] 057kkk:057val [007,028] 056kkk:056val [008,013] 055kkk:055val
=== SBLK[9] [009,027] 054kkk:054val [010,012] 053kkk:053val [011,026] 052kkk:052val
=== SBLK[9] [012,011] 051kkk:051val [013,025] 050kkk:050val [014,010] 049kkk:049val
=== SBLK[9] [015,024] 048kkk:048val [016,009] 047kkk:047val [017,023] 046kkk:046val
=== SBLK[9] [018,008] 045kkk:045val [019,022] 044kkk:044val
=== SBLK[19] lvl=-1, pnum=15, flg=1, kvzidx=15, p0=9, db=1
=== SBLK[19] szpow=10, lkl=6, lk=043kkk
=== SBLK[19] [000,000] 043kkk:043val [001,001] 042kkk:042val [002,002] 041kkk:041val
=== SBLK[19] [003,003] 040kkk:040val [004,004] 039kkk:039val [005,005] 038kkk:038val
=== SBLK[19] [006,006] 037kkk:037val [007,007] 036kkk:036val [008,008] 035kkk:035val
=== SBLK[19] [009,009] 034kkk:034val [010,010] 033kkk:033val [011,011] 032kkk:032val
=== SBLK[19] [012,012] 031kkk:031val [013,013] 030kkk:030val [014,014] 029kkk:029val
=== SBLK[17] lvl=-1, pnum=29, flg=1, kvzidx=29, p0=19, db=1
=== SBLK[17] szpow=10, lkl=6, lk=028kkk
=== SBLK[17] [000,000] 028kkk:028val [001,028] 027kkk:027val [002,001] 026kkk:026val
=== SBLK[17] [003,027] 025kkk:025val [004,002] 024kkk:024val [005,026] 023kkk:023val
=== SBLK[17] [006,003] 022kkk:022val [007,025] 021kkk:021val [008,004] 020kkk:020val
=== SBLK[17] [009,024] 019kkk:019val [010,005] 018kkk:018val [011,023] 017kkk:017val
=== SBLK[17] [012,006] 016kkk:016val [013,022] 015kkk:015val [014,007] 014kkk:014val
=== SBLK[17] [015,021] 013kkk:013val [016,008] 012kkk:012val [017,020] 011kkk:011val
=== SBLK[17] [018,009] 010kkk:010val [019,019] 009kkk:009val [020,010] 008kkk:008val
=== SBLK[17] [021,018] 007kkk:007val [022,011] 006kkk:006val [023,017] 005kkk:005val
=== SBLK[17] [024,012] 004kkk:004val [025,016] 003kkk:003val [026,013] 002kkk:002val
=== SBLK[17] [027,015] 001kkk:001val [028,014] 000kkk:000val
+247
View File
@@ -0,0 +1,247 @@
#### Stage: desc sorted keys inserted
== DB[1] lvl=-1, blk=3, dbflg=0, p0=130
=== SBLK[5] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=3, db=1
=== SBLK[5] szpow=9, lkl=6, lk=504kkk
=== SBLK[5] [000,000] 504kkk:504val [001,001] 503kkk:503val [002,002] 502kkk:502val
=== SBLK[5] [003,003] 501kkk:501val [004,004] 500kkk:500val [005,005] 499kkk:499val
=== SBLK[5] [006,006] 498kkk:498val [007,007] 497kkk:497val [008,008] 496kkk:496val
=== SBLK[5] [009,009] 495kkk:495val [010,010] 494kkk:494val [011,011] 493kkk:493val
=== SBLK[5] [012,012] 492kkk:492val [013,013] 491kkk:491val [014,014] 490kkk:490val
=== SBLK[5] [015,015] 489kkk:489val [016,016] 488kkk:488val [017,017] 487kkk:487val
=== SBLK[5] [018,018] 486kkk:486val [019,019] 485kkk:485val [020,020] 484kkk:484val
=== SBLK[5] [021,021] 483kkk:483val [022,022] 482kkk:482val [023,023] 481kkk:481val
=== SBLK[5] [024,024] 480kkk:480val [025,025] 479kkk:479val [026,026] 478kkk:478val
=== SBLK[5] [027,027] 477kkk:477val [028,028] 476kkk:476val [029,029] 475kkk:475val
=== SBLK[5] [030,030] 474kkk:474val [031,031] 473kkk:473val
=== SBLK[11] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=5, db=1
=== SBLK[11] szpow=9, lkl=6, lk=472kkk
=== SBLK[11] [000,000] 472kkk:472val [001,001] 471kkk:471val [002,002] 470kkk:470val
=== SBLK[11] [003,003] 469kkk:469val [004,004] 468kkk:468val [005,005] 467kkk:467val
=== SBLK[11] [006,006] 466kkk:466val [007,007] 465kkk:465val [008,008] 464kkk:464val
=== SBLK[11] [009,009] 463kkk:463val [010,010] 462kkk:462val [011,011] 461kkk:461val
=== SBLK[11] [012,012] 460kkk:460val [013,013] 459kkk:459val [014,014] 458kkk:458val
=== SBLK[11] [015,015] 457kkk:457val [016,016] 456kkk:456val [017,017] 455kkk:455val
=== SBLK[11] [018,018] 454kkk:454val [019,019] 453kkk:453val [020,020] 452kkk:452val
=== SBLK[11] [021,021] 451kkk:451val [022,022] 450kkk:450val [023,023] 449kkk:449val
=== SBLK[11] [024,024] 448kkk:448val [025,025] 447kkk:447val [026,026] 446kkk:446val
=== SBLK[11] [027,027] 445kkk:445val [028,028] 444kkk:444val [029,029] 443kkk:443val
=== SBLK[11] [030,030] 442kkk:442val [031,031] 441kkk:441val
=== SBLK[17] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=11, db=1
=== SBLK[17] szpow=9, lkl=6, lk=440kkk
=== SBLK[17] [000,000] 440kkk:440val [001,001] 439kkk:439val [002,002] 438kkk:438val
=== SBLK[17] [003,003] 437kkk:437val [004,004] 436kkk:436val [005,005] 435kkk:435val
=== SBLK[17] [006,006] 434kkk:434val [007,007] 433kkk:433val [008,008] 432kkk:432val
=== SBLK[17] [009,009] 431kkk:431val [010,010] 430kkk:430val [011,011] 429kkk:429val
=== SBLK[17] [012,012] 428kkk:428val [013,013] 427kkk:427val [014,014] 426kkk:426val
=== SBLK[17] [015,015] 425kkk:425val [016,016] 424kkk:424val [017,017] 423kkk:423val
=== SBLK[17] [018,018] 422kkk:422val [019,019] 421kkk:421val [020,020] 420kkk:420val
=== SBLK[17] [021,021] 419kkk:419val [022,022] 418kkk:418val [023,023] 417kkk:417val
=== SBLK[17] [024,024] 416kkk:416val [025,025] 415kkk:415val [026,026] 414kkk:414val
=== SBLK[17] [027,027] 413kkk:413val [028,028] 412kkk:412val [029,029] 411kkk:411val
=== SBLK[17] [030,030] 410kkk:410val [031,031] 409kkk:409val
=== SBLK[23] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=17, db=1
=== SBLK[23] szpow=9, lkl=6, lk=408kkk
=== SBLK[23] [000,000] 408kkk:408val [001,001] 407kkk:407val [002,002] 406kkk:406val
=== SBLK[23] [003,003] 405kkk:405val [004,004] 404kkk:404val [005,005] 403kkk:403val
=== SBLK[23] [006,006] 402kkk:402val [007,007] 401kkk:401val [008,008] 400kkk:400val
=== SBLK[23] [009,009] 399kkk:399val [010,010] 398kkk:398val [011,011] 397kkk:397val
=== SBLK[23] [012,012] 396kkk:396val [013,013] 395kkk:395val [014,014] 394kkk:394val
=== SBLK[23] [015,015] 393kkk:393val [016,016] 392kkk:392val [017,017] 391kkk:391val
=== SBLK[23] [018,018] 390kkk:390val [019,019] 389kkk:389val [020,020] 388kkk:388val
=== SBLK[23] [021,021] 387kkk:387val [022,022] 386kkk:386val [023,023] 385kkk:385val
=== SBLK[23] [024,024] 384kkk:384val [025,025] 383kkk:383val [026,026] 382kkk:382val
=== SBLK[23] [027,027] 381kkk:381val [028,028] 380kkk:380val [029,029] 379kkk:379val
=== SBLK[23] [030,030] 378kkk:378val [031,031] 377kkk:377val
=== SBLK[64] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=23, db=1
=== SBLK[64] szpow=9, lkl=6, lk=376kkk
=== SBLK[64] [000,000] 376kkk:376val [001,001] 375kkk:375val [002,002] 374kkk:374val
=== SBLK[64] [003,003] 373kkk:373val [004,004] 372kkk:372val [005,005] 371kkk:371val
=== SBLK[64] [006,006] 370kkk:370val [007,007] 369kkk:369val [008,008] 368kkk:368val
=== SBLK[64] [009,009] 367kkk:367val [010,010] 366kkk:366val [011,011] 365kkk:365val
=== SBLK[64] [012,012] 364kkk:364val [013,013] 363kkk:363val [014,014] 362kkk:362val
=== SBLK[64] [015,015] 361kkk:361val [016,016] 360kkk:360val [017,017] 359kkk:359val
=== SBLK[64] [018,018] 358kkk:358val [019,019] 357kkk:357val [020,020] 356kkk:356val
=== SBLK[64] [021,021] 355kkk:355val [022,022] 354kkk:354val [023,023] 353kkk:353val
=== SBLK[64] [024,024] 352kkk:352val [025,025] 351kkk:351val [026,026] 350kkk:350val
=== SBLK[64] [027,027] 349kkk:349val [028,028] 348kkk:348val [029,029] 347kkk:347val
=== SBLK[64] [030,030] 346kkk:346val [031,031] 345kkk:345val
=== SBLK[70] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=64, db=1
=== SBLK[70] szpow=9, lkl=6, lk=344kkk
=== SBLK[70] [000,000] 344kkk:344val [001,001] 343kkk:343val [002,002] 342kkk:342val
=== SBLK[70] [003,003] 341kkk:341val [004,004] 340kkk:340val [005,005] 339kkk:339val
=== SBLK[70] [006,006] 338kkk:338val [007,007] 337kkk:337val [008,008] 336kkk:336val
=== SBLK[70] [009,009] 335kkk:335val [010,010] 334kkk:334val [011,011] 333kkk:333val
=== SBLK[70] [012,012] 332kkk:332val [013,013] 331kkk:331val [014,014] 330kkk:330val
=== SBLK[70] [015,015] 329kkk:329val [016,016] 328kkk:328val [017,017] 327kkk:327val
=== SBLK[70] [018,018] 326kkk:326val [019,019] 325kkk:325val [020,020] 324kkk:324val
=== SBLK[70] [021,021] 323kkk:323val [022,022] 322kkk:322val [023,023] 321kkk:321val
=== SBLK[70] [024,024] 320kkk:320val [025,025] 319kkk:319val [026,026] 318kkk:318val
=== SBLK[70] [027,027] 317kkk:317val [028,028] 316kkk:316val [029,029] 315kkk:315val
=== SBLK[70] [030,030] 314kkk:314val [031,031] 313kkk:313val
=== SBLK[76] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=70, db=1
=== SBLK[76] szpow=9, lkl=6, lk=312kkk
=== SBLK[76] [000,000] 312kkk:312val [001,001] 311kkk:311val [002,002] 310kkk:310val
=== SBLK[76] [003,003] 309kkk:309val [004,004] 308kkk:308val [005,005] 307kkk:307val
=== SBLK[76] [006,006] 306kkk:306val [007,007] 305kkk:305val [008,008] 304kkk:304val
=== SBLK[76] [009,009] 303kkk:303val [010,010] 302kkk:302val [011,011] 301kkk:301val
=== SBLK[76] [012,012] 300kkk:300val [013,013] 299kkk:299val [014,014] 298kkk:298val
=== SBLK[76] [015,015] 297kkk:297val [016,016] 296kkk:296val [017,017] 295kkk:295val
=== SBLK[76] [018,018] 294kkk:294val [019,019] 293kkk:293val [020,020] 292kkk:292val
=== SBLK[76] [021,021] 291kkk:291val [022,022] 290kkk:290val [023,023] 289kkk:289val
=== SBLK[76] [024,024] 288kkk:288val [025,025] 287kkk:287val [026,026] 286kkk:286val
=== SBLK[76] [027,027] 285kkk:285val [028,028] 284kkk:284val [029,029] 283kkk:283val
=== SBLK[76] [030,030] 282kkk:282val [031,031] 281kkk:281val
=== SBLK[82] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=76, db=1
=== SBLK[82] szpow=9, lkl=6, lk=280kkk
=== SBLK[82] [000,000] 280kkk:280val [001,001] 279kkk:279val [002,002] 278kkk:278val
=== SBLK[82] [003,003] 277kkk:277val [004,004] 276kkk:276val [005,005] 275kkk:275val
=== SBLK[82] [006,006] 274kkk:274val [007,007] 273kkk:273val [008,008] 272kkk:272val
=== SBLK[82] [009,009] 271kkk:271val [010,010] 270kkk:270val [011,011] 269kkk:269val
=== SBLK[82] [012,012] 268kkk:268val [013,013] 267kkk:267val [014,014] 266kkk:266val
=== SBLK[82] [015,015] 265kkk:265val [016,016] 264kkk:264val [017,017] 263kkk:263val
=== SBLK[82] [018,018] 262kkk:262val [019,019] 261kkk:261val [020,020] 260kkk:260val
=== SBLK[82] [021,021] 259kkk:259val [022,022] 258kkk:258val [023,023] 257kkk:257val
=== SBLK[82] [024,024] 256kkk:256val [025,025] 255kkk:255val [026,026] 254kkk:254val
=== SBLK[82] [027,027] 253kkk:253val [028,028] 252kkk:252val [029,029] 251kkk:251val
=== SBLK[82] [030,030] 250kkk:250val [031,031] 249kkk:249val
=== SBLK[88] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=82, db=1
=== SBLK[88] szpow=9, lkl=6, lk=248kkk
=== SBLK[88] [000,000] 248kkk:248val [001,001] 247kkk:247val [002,002] 246kkk:246val
=== SBLK[88] [003,003] 245kkk:245val [004,004] 244kkk:244val [005,005] 243kkk:243val
=== SBLK[88] [006,006] 242kkk:242val [007,007] 241kkk:241val [008,008] 240kkk:240val
=== SBLK[88] [009,009] 239kkk:239val [010,010] 238kkk:238val [011,011] 237kkk:237val
=== SBLK[88] [012,012] 236kkk:236val [013,013] 235kkk:235val [014,014] 234kkk:234val
=== SBLK[88] [015,015] 233kkk:233val [016,016] 232kkk:232val [017,017] 231kkk:231val
=== SBLK[88] [018,018] 230kkk:230val [019,019] 229kkk:229val [020,020] 228kkk:228val
=== SBLK[88] [021,021] 227kkk:227val [022,022] 226kkk:226val [023,023] 225kkk:225val
=== SBLK[88] [024,024] 224kkk:224val [025,025] 223kkk:223val [026,026] 222kkk:222val
=== SBLK[88] [027,027] 221kkk:221val [028,028] 220kkk:220val [029,029] 219kkk:219val
=== SBLK[88] [030,030] 218kkk:218val [031,031] 217kkk:217val
=== SBLK[94] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=88, db=1
=== SBLK[94] szpow=9, lkl=6, lk=216kkk
=== SBLK[94] [000,000] 216kkk:216val [001,001] 215kkk:215val [002,002] 214kkk:214val
=== SBLK[94] [003,003] 213kkk:213val [004,004] 212kkk:212val [005,005] 211kkk:211val
=== SBLK[94] [006,006] 210kkk:210val [007,007] 209kkk:209val [008,008] 208kkk:208val
=== SBLK[94] [009,009] 207kkk:207val [010,010] 206kkk:206val [011,011] 205kkk:205val
=== SBLK[94] [012,012] 204kkk:204val [013,013] 203kkk:203val [014,014] 202kkk:202val
=== SBLK[94] [015,015] 201kkk:201val [016,016] 200kkk:200val [017,017] 199kkk:199val
=== SBLK[94] [018,018] 198kkk:198val [019,019] 197kkk:197val [020,020] 196kkk:196val
=== SBLK[94] [021,021] 195kkk:195val [022,022] 194kkk:194val [023,023] 193kkk:193val
=== SBLK[94] [024,024] 192kkk:192val [025,025] 191kkk:191val [026,026] 190kkk:190val
=== SBLK[94] [027,027] 189kkk:189val [028,028] 188kkk:188val [029,029] 187kkk:187val
=== SBLK[94] [030,030] 186kkk:186val [031,031] 185kkk:185val
=== SBLK[100] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=94, db=1
=== SBLK[100] szpow=9, lkl=6, lk=184kkk
=== SBLK[100] [000,000] 184kkk:184val [001,001] 183kkk:183val [002,002] 182kkk:182val
=== SBLK[100] [003,003] 181kkk:181val [004,004] 180kkk:180val [005,005] 179kkk:179val
=== SBLK[100] [006,006] 178kkk:178val [007,007] 177kkk:177val [008,008] 176kkk:176val
=== SBLK[100] [009,009] 175kkk:175val [010,010] 174kkk:174val [011,011] 173kkk:173val
=== SBLK[100] [012,012] 172kkk:172val [013,013] 171kkk:171val [014,014] 170kkk:170val
=== SBLK[100] [015,015] 169kkk:169val [016,016] 168kkk:168val [017,017] 167kkk:167val
=== SBLK[100] [018,018] 166kkk:166val [019,019] 165kkk:165val [020,020] 164kkk:164val
=== SBLK[100] [021,021] 163kkk:163val [022,022] 162kkk:162val [023,023] 161kkk:161val
=== SBLK[100] [024,024] 160kkk:160val [025,025] 159kkk:159val [026,026] 158kkk:158val
=== SBLK[100] [027,027] 157kkk:157val [028,028] 156kkk:156val [029,029] 155kkk:155val
=== SBLK[100] [030,030] 154kkk:154val [031,031] 153kkk:153val
=== SBLK[106] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=100, db=1
=== SBLK[106] szpow=9, lkl=6, lk=152kkk
=== SBLK[106] [000,000] 152kkk:152val [001,001] 151kkk:151val [002,002] 150kkk:150val
=== SBLK[106] [003,003] 149kkk:149val [004,004] 148kkk:148val [005,005] 147kkk:147val
=== SBLK[106] [006,006] 146kkk:146val [007,007] 145kkk:145val [008,008] 144kkk:144val
=== SBLK[106] [009,009] 143kkk:143val [010,010] 142kkk:142val [011,011] 141kkk:141val
=== SBLK[106] [012,012] 140kkk:140val [013,013] 139kkk:139val [014,014] 138kkk:138val
=== SBLK[106] [015,015] 137kkk:137val [016,016] 136kkk:136val [017,017] 135kkk:135val
=== SBLK[106] [018,018] 134kkk:134val [019,019] 133kkk:133val [020,020] 132kkk:132val
=== SBLK[106] [021,021] 131kkk:131val [022,022] 130kkk:130val [023,023] 129kkk:129val
=== SBLK[106] [024,024] 128kkk:128val [025,025] 127kkk:127val [026,026] 126kkk:126val
=== SBLK[106] [027,027] 125kkk:125val [028,028] 124kkk:124val [029,029] 123kkk:123val
=== SBLK[106] [030,030] 122kkk:122val [031,031] 121kkk:121val
=== SBLK[112] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=106, db=1
=== SBLK[112] szpow=9, lkl=6, lk=120kkk
=== SBLK[112] [000,000] 120kkk:120val [001,001] 119kkk:119val [002,002] 118kkk:118val
=== SBLK[112] [003,003] 117kkk:117val [004,004] 116kkk:116val [005,005] 115kkk:115val
=== SBLK[112] [006,006] 114kkk:114val [007,007] 113kkk:113val [008,008] 112kkk:112val
=== SBLK[112] [009,009] 111kkk:111val [010,010] 110kkk:110val [011,011] 109kkk:109val
=== SBLK[112] [012,012] 108kkk:108val [013,013] 107kkk:107val [014,014] 106kkk:106val
=== SBLK[112] [015,015] 105kkk:105val [016,016] 104kkk:104val [017,017] 103kkk:103val
=== SBLK[112] [018,018] 102kkk:102val [019,019] 101kkk:101val [020,020] 100kkk:100val
=== SBLK[112] [021,021] 099kkk:099val [022,022] 098kkk:098val [023,023] 097kkk:097val
=== SBLK[112] [024,024] 096kkk:096val [025,025] 095kkk:095val [026,026] 094kkk:094val
=== SBLK[112] [027,027] 093kkk:093val [028,028] 092kkk:092val [029,029] 091kkk:091val
=== SBLK[112] [030,030] 090kkk:090val [031,031] 089kkk:089val
=== SBLK[118] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=112, db=1
=== SBLK[118] szpow=9, lkl=6, lk=088kkk
=== SBLK[118] [000,000] 088kkk:088val [001,001] 087kkk:087val [002,002] 086kkk:086val
=== SBLK[118] [003,003] 085kkk:085val [004,004] 084kkk:084val [005,005] 083kkk:083val
=== SBLK[118] [006,006] 082kkk:082val [007,007] 081kkk:081val [008,008] 080kkk:080val
=== SBLK[118] [009,009] 079kkk:079val [010,010] 078kkk:078val [011,011] 077kkk:077val
=== SBLK[118] [012,012] 076kkk:076val [013,013] 075kkk:075val [014,014] 074kkk:074val
=== SBLK[118] [015,015] 073kkk:073val [016,016] 072kkk:072val [017,017] 071kkk:071val
=== SBLK[118] [018,018] 070kkk:070val [019,019] 069kkk:069val [020,020] 068kkk:068val
=== SBLK[118] [021,021] 067kkk:067val [022,022] 066kkk:066val [023,023] 065kkk:065val
=== SBLK[118] [024,024] 064kkk:064val [025,025] 063kkk:063val [026,026] 062kkk:062val
=== SBLK[118] [027,027] 061kkk:061val [028,028] 060kkk:060val [029,029] 059kkk:059val
=== SBLK[118] [030,030] 058kkk:058val [031,031] 057kkk:057val
=== SBLK[124] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=118, db=1
=== SBLK[124] szpow=9, lkl=6, lk=056kkk
=== SBLK[124] [000,000] 056kkk:056val [001,001] 055kkk:055val [002,002] 054kkk:054val
=== SBLK[124] [003,003] 053kkk:053val [004,004] 052kkk:052val [005,005] 051kkk:051val
=== SBLK[124] [006,006] 050kkk:050val [007,007] 049kkk:049val [008,008] 048kkk:048val
=== SBLK[124] [009,009] 047kkk:047val [010,010] 046kkk:046val [011,011] 045kkk:045val
=== SBLK[124] [012,012] 044kkk:044val [013,013] 043kkk:043val [014,014] 042kkk:042val
=== SBLK[124] [015,015] 041kkk:041val [016,016] 040kkk:040val [017,017] 039kkk:039val
=== SBLK[124] [018,018] 038kkk:038val [019,019] 037kkk:037val [020,020] 036kkk:036val
=== SBLK[124] [021,021] 035kkk:035val [022,022] 034kkk:034val [023,023] 033kkk:033val
=== SBLK[124] [024,024] 032kkk:032val [025,025] 031kkk:031val [026,026] 030kkk:030val
=== SBLK[124] [027,027] 029kkk:029val [028,028] 028kkk:028val [029,029] 027kkk:027val
=== SBLK[124] [030,030] 026kkk:026val [031,031] 025kkk:025val
=== SBLK[130] lvl=-1, pnum=25, flg=1, kvzidx=25, p0=124, db=1
=== SBLK[130] szpow=9, lkl=6, lk=024kkk
=== SBLK[130] [000,000] 024kkk:024val [001,001] 023kkk:023val [002,002] 022kkk:022val
=== SBLK[130] [003,003] 021kkk:021val [004,004] 020kkk:020val [005,005] 019kkk:019val
=== SBLK[130] [006,006] 018kkk:018val [007,007] 017kkk:017val [008,008] 016kkk:016val
=== SBLK[130] [009,009] 015kkk:015val [010,010] 014kkk:014val [011,011] 013kkk:013val
=== SBLK[130] [012,012] 012kkk:012val [013,013] 011kkk:011val [014,014] 010kkk:010val
=== SBLK[130] [015,015] 009kkk:009val [016,016] 008kkk:008val [017,017] 007kkk:007val
=== SBLK[130] [018,018] 006kkk:006val [019,019] 005kkk:005val [020,020] 004kkk:004val
=== SBLK[130] [021,021] 003kkk:003val [022,022] 002kkk:002val [023,023] 001kkk:001val
=== SBLK[130] [024,024] 000kkk:000val
#### Stage: db1 destroyed
== DB[1] lvl=-1, blk=3, dbflg=0, p0=3
+247
View File
@@ -0,0 +1,247 @@
#### Stage: desc sorted keys inserted
== DB[1] lvl=-1, blk=3, dbflg=0, p0=94
=== SBLK[64] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=3, db=1
=== SBLK[64] szpow=9, lkl=6, lk=504kkk
=== SBLK[64] [000,000] 504kkk:504val [001,001] 503kkk:503val [002,002] 502kkk:502val
=== SBLK[64] [003,003] 501kkk:501val [004,004] 500kkk:500val [005,005] 499kkk:499val
=== SBLK[64] [006,006] 498kkk:498val [007,007] 497kkk:497val [008,008] 496kkk:496val
=== SBLK[64] [009,009] 495kkk:495val [010,010] 494kkk:494val [011,011] 493kkk:493val
=== SBLK[64] [012,012] 492kkk:492val [013,013] 491kkk:491val [014,014] 490kkk:490val
=== SBLK[64] [015,015] 489kkk:489val [016,016] 488kkk:488val [017,017] 487kkk:487val
=== SBLK[64] [018,018] 486kkk:486val [019,019] 485kkk:485val [020,020] 484kkk:484val
=== SBLK[64] [021,021] 483kkk:483val [022,022] 482kkk:482val [023,023] 481kkk:481val
=== SBLK[64] [024,024] 480kkk:480val [025,025] 479kkk:479val [026,026] 478kkk:478val
=== SBLK[64] [027,027] 477kkk:477val [028,028] 476kkk:476val [029,029] 475kkk:475val
=== SBLK[64] [030,030] 474kkk:474val [031,031] 473kkk:473val
=== SBLK[66] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=64, db=1
=== SBLK[66] szpow=9, lkl=6, lk=472kkk
=== SBLK[66] [000,000] 472kkk:472val [001,001] 471kkk:471val [002,002] 470kkk:470val
=== SBLK[66] [003,003] 469kkk:469val [004,004] 468kkk:468val [005,005] 467kkk:467val
=== SBLK[66] [006,006] 466kkk:466val [007,007] 465kkk:465val [008,008] 464kkk:464val
=== SBLK[66] [009,009] 463kkk:463val [010,010] 462kkk:462val [011,011] 461kkk:461val
=== SBLK[66] [012,012] 460kkk:460val [013,013] 459kkk:459val [014,014] 458kkk:458val
=== SBLK[66] [015,015] 457kkk:457val [016,016] 456kkk:456val [017,017] 455kkk:455val
=== SBLK[66] [018,018] 454kkk:454val [019,019] 453kkk:453val [020,020] 452kkk:452val
=== SBLK[66] [021,021] 451kkk:451val [022,022] 450kkk:450val [023,023] 449kkk:449val
=== SBLK[66] [024,024] 448kkk:448val [025,025] 447kkk:447val [026,026] 446kkk:446val
=== SBLK[66] [027,027] 445kkk:445val [028,028] 444kkk:444val [029,029] 443kkk:443val
=== SBLK[66] [030,030] 442kkk:442val [031,031] 441kkk:441val
=== SBLK[68] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=66, db=1
=== SBLK[68] szpow=9, lkl=6, lk=440kkk
=== SBLK[68] [000,000] 440kkk:440val [001,001] 439kkk:439val [002,002] 438kkk:438val
=== SBLK[68] [003,003] 437kkk:437val [004,004] 436kkk:436val [005,005] 435kkk:435val
=== SBLK[68] [006,006] 434kkk:434val [007,007] 433kkk:433val [008,008] 432kkk:432val
=== SBLK[68] [009,009] 431kkk:431val [010,010] 430kkk:430val [011,011] 429kkk:429val
=== SBLK[68] [012,012] 428kkk:428val [013,013] 427kkk:427val [014,014] 426kkk:426val
=== SBLK[68] [015,015] 425kkk:425val [016,016] 424kkk:424val [017,017] 423kkk:423val
=== SBLK[68] [018,018] 422kkk:422val [019,019] 421kkk:421val [020,020] 420kkk:420val
=== SBLK[68] [021,021] 419kkk:419val [022,022] 418kkk:418val [023,023] 417kkk:417val
=== SBLK[68] [024,024] 416kkk:416val [025,025] 415kkk:415val [026,026] 414kkk:414val
=== SBLK[68] [027,027] 413kkk:413val [028,028] 412kkk:412val [029,029] 411kkk:411val
=== SBLK[68] [030,030] 410kkk:410val [031,031] 409kkk:409val
=== SBLK[70] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=68, db=1
=== SBLK[70] szpow=9, lkl=6, lk=408kkk
=== SBLK[70] [000,000] 408kkk:408val [001,001] 407kkk:407val [002,002] 406kkk:406val
=== SBLK[70] [003,003] 405kkk:405val [004,004] 404kkk:404val [005,005] 403kkk:403val
=== SBLK[70] [006,006] 402kkk:402val [007,007] 401kkk:401val [008,008] 400kkk:400val
=== SBLK[70] [009,009] 399kkk:399val [010,010] 398kkk:398val [011,011] 397kkk:397val
=== SBLK[70] [012,012] 396kkk:396val [013,013] 395kkk:395val [014,014] 394kkk:394val
=== SBLK[70] [015,015] 393kkk:393val [016,016] 392kkk:392val [017,017] 391kkk:391val
=== SBLK[70] [018,018] 390kkk:390val [019,019] 389kkk:389val [020,020] 388kkk:388val
=== SBLK[70] [021,021] 387kkk:387val [022,022] 386kkk:386val [023,023] 385kkk:385val
=== SBLK[70] [024,024] 384kkk:384val [025,025] 383kkk:383val [026,026] 382kkk:382val
=== SBLK[70] [027,027] 381kkk:381val [028,028] 380kkk:380val [029,029] 379kkk:379val
=== SBLK[70] [030,030] 378kkk:378val [031,031] 377kkk:377val
=== SBLK[72] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=70, db=1
=== SBLK[72] szpow=9, lkl=6, lk=376kkk
=== SBLK[72] [000,000] 376kkk:376val [001,001] 375kkk:375val [002,002] 374kkk:374val
=== SBLK[72] [003,003] 373kkk:373val [004,004] 372kkk:372val [005,005] 371kkk:371val
=== SBLK[72] [006,006] 370kkk:370val [007,007] 369kkk:369val [008,008] 368kkk:368val
=== SBLK[72] [009,009] 367kkk:367val [010,010] 366kkk:366val [011,011] 365kkk:365val
=== SBLK[72] [012,012] 364kkk:364val [013,013] 363kkk:363val [014,014] 362kkk:362val
=== SBLK[72] [015,015] 361kkk:361val [016,016] 360kkk:360val [017,017] 359kkk:359val
=== SBLK[72] [018,018] 358kkk:358val [019,019] 357kkk:357val [020,020] 356kkk:356val
=== SBLK[72] [021,021] 355kkk:355val [022,022] 354kkk:354val [023,023] 353kkk:353val
=== SBLK[72] [024,024] 352kkk:352val [025,025] 351kkk:351val [026,026] 350kkk:350val
=== SBLK[72] [027,027] 349kkk:349val [028,028] 348kkk:348val [029,029] 347kkk:347val
=== SBLK[72] [030,030] 346kkk:346val [031,031] 345kkk:345val
=== SBLK[74] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=72, db=1
=== SBLK[74] szpow=9, lkl=6, lk=344kkk
=== SBLK[74] [000,000] 344kkk:344val [001,001] 343kkk:343val [002,002] 342kkk:342val
=== SBLK[74] [003,003] 341kkk:341val [004,004] 340kkk:340val [005,005] 339kkk:339val
=== SBLK[74] [006,006] 338kkk:338val [007,007] 337kkk:337val [008,008] 336kkk:336val
=== SBLK[74] [009,009] 335kkk:335val [010,010] 334kkk:334val [011,011] 333kkk:333val
=== SBLK[74] [012,012] 332kkk:332val [013,013] 331kkk:331val [014,014] 330kkk:330val
=== SBLK[74] [015,015] 329kkk:329val [016,016] 328kkk:328val [017,017] 327kkk:327val
=== SBLK[74] [018,018] 326kkk:326val [019,019] 325kkk:325val [020,020] 324kkk:324val
=== SBLK[74] [021,021] 323kkk:323val [022,022] 322kkk:322val [023,023] 321kkk:321val
=== SBLK[74] [024,024] 320kkk:320val [025,025] 319kkk:319val [026,026] 318kkk:318val
=== SBLK[74] [027,027] 317kkk:317val [028,028] 316kkk:316val [029,029] 315kkk:315val
=== SBLK[74] [030,030] 314kkk:314val [031,031] 313kkk:313val
=== SBLK[76] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=74, db=1
=== SBLK[76] szpow=9, lkl=6, lk=312kkk
=== SBLK[76] [000,000] 312kkk:312val [001,001] 311kkk:311val [002,002] 310kkk:310val
=== SBLK[76] [003,003] 309kkk:309val [004,004] 308kkk:308val [005,005] 307kkk:307val
=== SBLK[76] [006,006] 306kkk:306val [007,007] 305kkk:305val [008,008] 304kkk:304val
=== SBLK[76] [009,009] 303kkk:303val [010,010] 302kkk:302val [011,011] 301kkk:301val
=== SBLK[76] [012,012] 300kkk:300val [013,013] 299kkk:299val [014,014] 298kkk:298val
=== SBLK[76] [015,015] 297kkk:297val [016,016] 296kkk:296val [017,017] 295kkk:295val
=== SBLK[76] [018,018] 294kkk:294val [019,019] 293kkk:293val [020,020] 292kkk:292val
=== SBLK[76] [021,021] 291kkk:291val [022,022] 290kkk:290val [023,023] 289kkk:289val
=== SBLK[76] [024,024] 288kkk:288val [025,025] 287kkk:287val [026,026] 286kkk:286val
=== SBLK[76] [027,027] 285kkk:285val [028,028] 284kkk:284val [029,029] 283kkk:283val
=== SBLK[76] [030,030] 282kkk:282val [031,031] 281kkk:281val
=== SBLK[78] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=76, db=1
=== SBLK[78] szpow=9, lkl=6, lk=280kkk
=== SBLK[78] [000,000] 280kkk:280val [001,001] 279kkk:279val [002,002] 278kkk:278val
=== SBLK[78] [003,003] 277kkk:277val [004,004] 276kkk:276val [005,005] 275kkk:275val
=== SBLK[78] [006,006] 274kkk:274val [007,007] 273kkk:273val [008,008] 272kkk:272val
=== SBLK[78] [009,009] 271kkk:271val [010,010] 270kkk:270val [011,011] 269kkk:269val
=== SBLK[78] [012,012] 268kkk:268val [013,013] 267kkk:267val [014,014] 266kkk:266val
=== SBLK[78] [015,015] 265kkk:265val [016,016] 264kkk:264val [017,017] 263kkk:263val
=== SBLK[78] [018,018] 262kkk:262val [019,019] 261kkk:261val [020,020] 260kkk:260val
=== SBLK[78] [021,021] 259kkk:259val [022,022] 258kkk:258val [023,023] 257kkk:257val
=== SBLK[78] [024,024] 256kkk:256val [025,025] 255kkk:255val [026,026] 254kkk:254val
=== SBLK[78] [027,027] 253kkk:253val [028,028] 252kkk:252val [029,029] 251kkk:251val
=== SBLK[78] [030,030] 250kkk:250val [031,031] 249kkk:249val
=== SBLK[80] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=78, db=1
=== SBLK[80] szpow=9, lkl=6, lk=248kkk
=== SBLK[80] [000,000] 248kkk:248val [001,001] 247kkk:247val [002,002] 246kkk:246val
=== SBLK[80] [003,003] 245kkk:245val [004,004] 244kkk:244val [005,005] 243kkk:243val
=== SBLK[80] [006,006] 242kkk:242val [007,007] 241kkk:241val [008,008] 240kkk:240val
=== SBLK[80] [009,009] 239kkk:239val [010,010] 238kkk:238val [011,011] 237kkk:237val
=== SBLK[80] [012,012] 236kkk:236val [013,013] 235kkk:235val [014,014] 234kkk:234val
=== SBLK[80] [015,015] 233kkk:233val [016,016] 232kkk:232val [017,017] 231kkk:231val
=== SBLK[80] [018,018] 230kkk:230val [019,019] 229kkk:229val [020,020] 228kkk:228val
=== SBLK[80] [021,021] 227kkk:227val [022,022] 226kkk:226val [023,023] 225kkk:225val
=== SBLK[80] [024,024] 224kkk:224val [025,025] 223kkk:223val [026,026] 222kkk:222val
=== SBLK[80] [027,027] 221kkk:221val [028,028] 220kkk:220val [029,029] 219kkk:219val
=== SBLK[80] [030,030] 218kkk:218val [031,031] 217kkk:217val
=== SBLK[82] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=80, db=1
=== SBLK[82] szpow=9, lkl=6, lk=216kkk
=== SBLK[82] [000,000] 216kkk:216val [001,001] 215kkk:215val [002,002] 214kkk:214val
=== SBLK[82] [003,003] 213kkk:213val [004,004] 212kkk:212val [005,005] 211kkk:211val
=== SBLK[82] [006,006] 210kkk:210val [007,007] 209kkk:209val [008,008] 208kkk:208val
=== SBLK[82] [009,009] 207kkk:207val [010,010] 206kkk:206val [011,011] 205kkk:205val
=== SBLK[82] [012,012] 204kkk:204val [013,013] 203kkk:203val [014,014] 202kkk:202val
=== SBLK[82] [015,015] 201kkk:201val [016,016] 200kkk:200val [017,017] 199kkk:199val
=== SBLK[82] [018,018] 198kkk:198val [019,019] 197kkk:197val [020,020] 196kkk:196val
=== SBLK[82] [021,021] 195kkk:195val [022,022] 194kkk:194val [023,023] 193kkk:193val
=== SBLK[82] [024,024] 192kkk:192val [025,025] 191kkk:191val [026,026] 190kkk:190val
=== SBLK[82] [027,027] 189kkk:189val [028,028] 188kkk:188val [029,029] 187kkk:187val
=== SBLK[82] [030,030] 186kkk:186val [031,031] 185kkk:185val
=== SBLK[84] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=82, db=1
=== SBLK[84] szpow=9, lkl=6, lk=184kkk
=== SBLK[84] [000,000] 184kkk:184val [001,001] 183kkk:183val [002,002] 182kkk:182val
=== SBLK[84] [003,003] 181kkk:181val [004,004] 180kkk:180val [005,005] 179kkk:179val
=== SBLK[84] [006,006] 178kkk:178val [007,007] 177kkk:177val [008,008] 176kkk:176val
=== SBLK[84] [009,009] 175kkk:175val [010,010] 174kkk:174val [011,011] 173kkk:173val
=== SBLK[84] [012,012] 172kkk:172val [013,013] 171kkk:171val [014,014] 170kkk:170val
=== SBLK[84] [015,015] 169kkk:169val [016,016] 168kkk:168val [017,017] 167kkk:167val
=== SBLK[84] [018,018] 166kkk:166val [019,019] 165kkk:165val [020,020] 164kkk:164val
=== SBLK[84] [021,021] 163kkk:163val [022,022] 162kkk:162val [023,023] 161kkk:161val
=== SBLK[84] [024,024] 160kkk:160val [025,025] 159kkk:159val [026,026] 158kkk:158val
=== SBLK[84] [027,027] 157kkk:157val [028,028] 156kkk:156val [029,029] 155kkk:155val
=== SBLK[84] [030,030] 154kkk:154val [031,031] 153kkk:153val
=== SBLK[86] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=84, db=1
=== SBLK[86] szpow=9, lkl=6, lk=152kkk
=== SBLK[86] [000,000] 152kkk:152val [001,001] 151kkk:151val [002,002] 150kkk:150val
=== SBLK[86] [003,003] 149kkk:149val [004,004] 148kkk:148val [005,005] 147kkk:147val
=== SBLK[86] [006,006] 146kkk:146val [007,007] 145kkk:145val [008,008] 144kkk:144val
=== SBLK[86] [009,009] 143kkk:143val [010,010] 142kkk:142val [011,011] 141kkk:141val
=== SBLK[86] [012,012] 140kkk:140val [013,013] 139kkk:139val [014,014] 138kkk:138val
=== SBLK[86] [015,015] 137kkk:137val [016,016] 136kkk:136val [017,017] 135kkk:135val
=== SBLK[86] [018,018] 134kkk:134val [019,019] 133kkk:133val [020,020] 132kkk:132val
=== SBLK[86] [021,021] 131kkk:131val [022,022] 130kkk:130val [023,023] 129kkk:129val
=== SBLK[86] [024,024] 128kkk:128val [025,025] 127kkk:127val [026,026] 126kkk:126val
=== SBLK[86] [027,027] 125kkk:125val [028,028] 124kkk:124val [029,029] 123kkk:123val
=== SBLK[86] [030,030] 122kkk:122val [031,031] 121kkk:121val
=== SBLK[88] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=86, db=1
=== SBLK[88] szpow=9, lkl=6, lk=120kkk
=== SBLK[88] [000,000] 120kkk:120val [001,001] 119kkk:119val [002,002] 118kkk:118val
=== SBLK[88] [003,003] 117kkk:117val [004,004] 116kkk:116val [005,005] 115kkk:115val
=== SBLK[88] [006,006] 114kkk:114val [007,007] 113kkk:113val [008,008] 112kkk:112val
=== SBLK[88] [009,009] 111kkk:111val [010,010] 110kkk:110val [011,011] 109kkk:109val
=== SBLK[88] [012,012] 108kkk:108val [013,013] 107kkk:107val [014,014] 106kkk:106val
=== SBLK[88] [015,015] 105kkk:105val [016,016] 104kkk:104val [017,017] 103kkk:103val
=== SBLK[88] [018,018] 102kkk:102val [019,019] 101kkk:101val [020,020] 100kkk:100val
=== SBLK[88] [021,021] 099kkk:099val [022,022] 098kkk:098val [023,023] 097kkk:097val
=== SBLK[88] [024,024] 096kkk:096val [025,025] 095kkk:095val [026,026] 094kkk:094val
=== SBLK[88] [027,027] 093kkk:093val [028,028] 092kkk:092val [029,029] 091kkk:091val
=== SBLK[88] [030,030] 090kkk:090val [031,031] 089kkk:089val
=== SBLK[90] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=88, db=1
=== SBLK[90] szpow=9, lkl=6, lk=088kkk
=== SBLK[90] [000,000] 088kkk:088val [001,001] 087kkk:087val [002,002] 086kkk:086val
=== SBLK[90] [003,003] 085kkk:085val [004,004] 084kkk:084val [005,005] 083kkk:083val
=== SBLK[90] [006,006] 082kkk:082val [007,007] 081kkk:081val [008,008] 080kkk:080val
=== SBLK[90] [009,009] 079kkk:079val [010,010] 078kkk:078val [011,011] 077kkk:077val
=== SBLK[90] [012,012] 076kkk:076val [013,013] 075kkk:075val [014,014] 074kkk:074val
=== SBLK[90] [015,015] 073kkk:073val [016,016] 072kkk:072val [017,017] 071kkk:071val
=== SBLK[90] [018,018] 070kkk:070val [019,019] 069kkk:069val [020,020] 068kkk:068val
=== SBLK[90] [021,021] 067kkk:067val [022,022] 066kkk:066val [023,023] 065kkk:065val
=== SBLK[90] [024,024] 064kkk:064val [025,025] 063kkk:063val [026,026] 062kkk:062val
=== SBLK[90] [027,027] 061kkk:061val [028,028] 060kkk:060val [029,029] 059kkk:059val
=== SBLK[90] [030,030] 058kkk:058val [031,031] 057kkk:057val
=== SBLK[92] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=90, db=1
=== SBLK[92] szpow=9, lkl=6, lk=056kkk
=== SBLK[92] [000,000] 056kkk:056val [001,001] 055kkk:055val [002,002] 054kkk:054val
=== SBLK[92] [003,003] 053kkk:053val [004,004] 052kkk:052val [005,005] 051kkk:051val
=== SBLK[92] [006,006] 050kkk:050val [007,007] 049kkk:049val [008,008] 048kkk:048val
=== SBLK[92] [009,009] 047kkk:047val [010,010] 046kkk:046val [011,011] 045kkk:045val
=== SBLK[92] [012,012] 044kkk:044val [013,013] 043kkk:043val [014,014] 042kkk:042val
=== SBLK[92] [015,015] 041kkk:041val [016,016] 040kkk:040val [017,017] 039kkk:039val
=== SBLK[92] [018,018] 038kkk:038val [019,019] 037kkk:037val [020,020] 036kkk:036val
=== SBLK[92] [021,021] 035kkk:035val [022,022] 034kkk:034val [023,023] 033kkk:033val
=== SBLK[92] [024,024] 032kkk:032val [025,025] 031kkk:031val [026,026] 030kkk:030val
=== SBLK[92] [027,027] 029kkk:029val [028,028] 028kkk:028val [029,029] 027kkk:027val
=== SBLK[92] [030,030] 026kkk:026val [031,031] 025kkk:025val
=== SBLK[94] lvl=-1, pnum=25, flg=1, kvzidx=25, p0=92, db=1
=== SBLK[94] szpow=9, lkl=6, lk=024kkk
=== SBLK[94] [000,000] 024kkk:024val [001,001] 023kkk:023val [002,002] 022kkk:022val
=== SBLK[94] [003,003] 021kkk:021val [004,004] 020kkk:020val [005,005] 019kkk:019val
=== SBLK[94] [006,006] 018kkk:018val [007,007] 017kkk:017val [008,008] 016kkk:016val
=== SBLK[94] [009,009] 015kkk:015val [010,010] 014kkk:014val [011,011] 013kkk:013val
=== SBLK[94] [012,012] 012kkk:012val [013,013] 011kkk:011val [014,014] 010kkk:010val
=== SBLK[94] [015,015] 009kkk:009val [016,016] 008kkk:008val [017,017] 007kkk:007val
=== SBLK[94] [018,018] 006kkk:006val [019,019] 005kkk:005val [020,020] 004kkk:004val
=== SBLK[94] [021,021] 003kkk:003val [022,022] 002kkk:002val [023,023] 001kkk:001val
=== SBLK[94] [024,024] 000kkk:000val
#### Stage: db1 destroyed
== DB[1] lvl=-1, blk=3, dbflg=0, p0=3
+247
View File
@@ -0,0 +1,247 @@
#### Stage: desc sorted keys inserted
== DB[1] lvl=-1, blk=3, dbflg=0, p0=95
=== SBLK[5] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=3, db=1
=== SBLK[5] szpow=9, lkl=6, lk=504kkk
=== SBLK[5] [000,000] 504kkk:504val [001,001] 503kkk:503val [002,002] 502kkk:502val
=== SBLK[5] [003,003] 501kkk:501val [004,004] 500kkk:500val [005,005] 499kkk:499val
=== SBLK[5] [006,006] 498kkk:498val [007,007] 497kkk:497val [008,008] 496kkk:496val
=== SBLK[5] [009,009] 495kkk:495val [010,010] 494kkk:494val [011,011] 493kkk:493val
=== SBLK[5] [012,012] 492kkk:492val [013,013] 491kkk:491val [014,014] 490kkk:490val
=== SBLK[5] [015,015] 489kkk:489val [016,016] 488kkk:488val [017,017] 487kkk:487val
=== SBLK[5] [018,018] 486kkk:486val [019,019] 485kkk:485val [020,020] 484kkk:484val
=== SBLK[5] [021,021] 483kkk:483val [022,022] 482kkk:482val [023,023] 481kkk:481val
=== SBLK[5] [024,024] 480kkk:480val [025,025] 479kkk:479val [026,026] 478kkk:478val
=== SBLK[5] [027,027] 477kkk:477val [028,028] 476kkk:476val [029,029] 475kkk:475val
=== SBLK[5] [030,030] 474kkk:474val [031,031] 473kkk:473val
=== SBLK[11] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=5, db=1
=== SBLK[11] szpow=9, lkl=6, lk=472kkk
=== SBLK[11] [000,000] 472kkk:472val [001,001] 471kkk:471val [002,002] 470kkk:470val
=== SBLK[11] [003,003] 469kkk:469val [004,004] 468kkk:468val [005,005] 467kkk:467val
=== SBLK[11] [006,006] 466kkk:466val [007,007] 465kkk:465val [008,008] 464kkk:464val
=== SBLK[11] [009,009] 463kkk:463val [010,010] 462kkk:462val [011,011] 461kkk:461val
=== SBLK[11] [012,012] 460kkk:460val [013,013] 459kkk:459val [014,014] 458kkk:458val
=== SBLK[11] [015,015] 457kkk:457val [016,016] 456kkk:456val [017,017] 455kkk:455val
=== SBLK[11] [018,018] 454kkk:454val [019,019] 453kkk:453val [020,020] 452kkk:452val
=== SBLK[11] [021,021] 451kkk:451val [022,022] 450kkk:450val [023,023] 449kkk:449val
=== SBLK[11] [024,024] 448kkk:448val [025,025] 447kkk:447val [026,026] 446kkk:446val
=== SBLK[11] [027,027] 445kkk:445val [028,028] 444kkk:444val [029,029] 443kkk:443val
=== SBLK[11] [030,030] 442kkk:442val [031,031] 441kkk:441val
=== SBLK[17] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=11, db=1
=== SBLK[17] szpow=9, lkl=6, lk=440kkk
=== SBLK[17] [000,000] 440kkk:440val [001,001] 439kkk:439val [002,002] 438kkk:438val
=== SBLK[17] [003,003] 437kkk:437val [004,004] 436kkk:436val [005,005] 435kkk:435val
=== SBLK[17] [006,006] 434kkk:434val [007,007] 433kkk:433val [008,008] 432kkk:432val
=== SBLK[17] [009,009] 431kkk:431val [010,010] 430kkk:430val [011,011] 429kkk:429val
=== SBLK[17] [012,012] 428kkk:428val [013,013] 427kkk:427val [014,014] 426kkk:426val
=== SBLK[17] [015,015] 425kkk:425val [016,016] 424kkk:424val [017,017] 423kkk:423val
=== SBLK[17] [018,018] 422kkk:422val [019,019] 421kkk:421val [020,020] 420kkk:420val
=== SBLK[17] [021,021] 419kkk:419val [022,022] 418kkk:418val [023,023] 417kkk:417val
=== SBLK[17] [024,024] 416kkk:416val [025,025] 415kkk:415val [026,026] 414kkk:414val
=== SBLK[17] [027,027] 413kkk:413val [028,028] 412kkk:412val [029,029] 411kkk:411val
=== SBLK[17] [030,030] 410kkk:410val [031,031] 409kkk:409val
=== SBLK[23] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=17, db=1
=== SBLK[23] szpow=9, lkl=6, lk=408kkk
=== SBLK[23] [000,000] 408kkk:408val [001,001] 407kkk:407val [002,002] 406kkk:406val
=== SBLK[23] [003,003] 405kkk:405val [004,004] 404kkk:404val [005,005] 403kkk:403val
=== SBLK[23] [006,006] 402kkk:402val [007,007] 401kkk:401val [008,008] 400kkk:400val
=== SBLK[23] [009,009] 399kkk:399val [010,010] 398kkk:398val [011,011] 397kkk:397val
=== SBLK[23] [012,012] 396kkk:396val [013,013] 395kkk:395val [014,014] 394kkk:394val
=== SBLK[23] [015,015] 393kkk:393val [016,016] 392kkk:392val [017,017] 391kkk:391val
=== SBLK[23] [018,018] 390kkk:390val [019,019] 389kkk:389val [020,020] 388kkk:388val
=== SBLK[23] [021,021] 387kkk:387val [022,022] 386kkk:386val [023,023] 385kkk:385val
=== SBLK[23] [024,024] 384kkk:384val [025,025] 383kkk:383val [026,026] 382kkk:382val
=== SBLK[23] [027,027] 381kkk:381val [028,028] 380kkk:380val [029,029] 379kkk:379val
=== SBLK[23] [030,030] 378kkk:378val [031,031] 377kkk:377val
=== SBLK[29] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=23, db=1
=== SBLK[29] szpow=9, lkl=6, lk=376kkk
=== SBLK[29] [000,000] 376kkk:376val [001,001] 375kkk:375val [002,002] 374kkk:374val
=== SBLK[29] [003,003] 373kkk:373val [004,004] 372kkk:372val [005,005] 371kkk:371val
=== SBLK[29] [006,006] 370kkk:370val [007,007] 369kkk:369val [008,008] 368kkk:368val
=== SBLK[29] [009,009] 367kkk:367val [010,010] 366kkk:366val [011,011] 365kkk:365val
=== SBLK[29] [012,012] 364kkk:364val [013,013] 363kkk:363val [014,014] 362kkk:362val
=== SBLK[29] [015,015] 361kkk:361val [016,016] 360kkk:360val [017,017] 359kkk:359val
=== SBLK[29] [018,018] 358kkk:358val [019,019] 357kkk:357val [020,020] 356kkk:356val
=== SBLK[29] [021,021] 355kkk:355val [022,022] 354kkk:354val [023,023] 353kkk:353val
=== SBLK[29] [024,024] 352kkk:352val [025,025] 351kkk:351val [026,026] 350kkk:350val
=== SBLK[29] [027,027] 349kkk:349val [028,028] 348kkk:348val [029,029] 347kkk:347val
=== SBLK[29] [030,030] 346kkk:346val [031,031] 345kkk:345val
=== SBLK[35] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=29, db=1
=== SBLK[35] szpow=9, lkl=6, lk=344kkk
=== SBLK[35] [000,000] 344kkk:344val [001,001] 343kkk:343val [002,002] 342kkk:342val
=== SBLK[35] [003,003] 341kkk:341val [004,004] 340kkk:340val [005,005] 339kkk:339val
=== SBLK[35] [006,006] 338kkk:338val [007,007] 337kkk:337val [008,008] 336kkk:336val
=== SBLK[35] [009,009] 335kkk:335val [010,010] 334kkk:334val [011,011] 333kkk:333val
=== SBLK[35] [012,012] 332kkk:332val [013,013] 331kkk:331val [014,014] 330kkk:330val
=== SBLK[35] [015,015] 329kkk:329val [016,016] 328kkk:328val [017,017] 327kkk:327val
=== SBLK[35] [018,018] 326kkk:326val [019,019] 325kkk:325val [020,020] 324kkk:324val
=== SBLK[35] [021,021] 323kkk:323val [022,022] 322kkk:322val [023,023] 321kkk:321val
=== SBLK[35] [024,024] 320kkk:320val [025,025] 319kkk:319val [026,026] 318kkk:318val
=== SBLK[35] [027,027] 317kkk:317val [028,028] 316kkk:316val [029,029] 315kkk:315val
=== SBLK[35] [030,030] 314kkk:314val [031,031] 313kkk:313val
=== SBLK[41] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=35, db=1
=== SBLK[41] szpow=9, lkl=6, lk=312kkk
=== SBLK[41] [000,000] 312kkk:312val [001,001] 311kkk:311val [002,002] 310kkk:310val
=== SBLK[41] [003,003] 309kkk:309val [004,004] 308kkk:308val [005,005] 307kkk:307val
=== SBLK[41] [006,006] 306kkk:306val [007,007] 305kkk:305val [008,008] 304kkk:304val
=== SBLK[41] [009,009] 303kkk:303val [010,010] 302kkk:302val [011,011] 301kkk:301val
=== SBLK[41] [012,012] 300kkk:300val [013,013] 299kkk:299val [014,014] 298kkk:298val
=== SBLK[41] [015,015] 297kkk:297val [016,016] 296kkk:296val [017,017] 295kkk:295val
=== SBLK[41] [018,018] 294kkk:294val [019,019] 293kkk:293val [020,020] 292kkk:292val
=== SBLK[41] [021,021] 291kkk:291val [022,022] 290kkk:290val [023,023] 289kkk:289val
=== SBLK[41] [024,024] 288kkk:288val [025,025] 287kkk:287val [026,026] 286kkk:286val
=== SBLK[41] [027,027] 285kkk:285val [028,028] 284kkk:284val [029,029] 283kkk:283val
=== SBLK[41] [030,030] 282kkk:282val [031,031] 281kkk:281val
=== SBLK[47] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=41, db=1
=== SBLK[47] szpow=9, lkl=6, lk=280kkk
=== SBLK[47] [000,000] 280kkk:280val [001,001] 279kkk:279val [002,002] 278kkk:278val
=== SBLK[47] [003,003] 277kkk:277val [004,004] 276kkk:276val [005,005] 275kkk:275val
=== SBLK[47] [006,006] 274kkk:274val [007,007] 273kkk:273val [008,008] 272kkk:272val
=== SBLK[47] [009,009] 271kkk:271val [010,010] 270kkk:270val [011,011] 269kkk:269val
=== SBLK[47] [012,012] 268kkk:268val [013,013] 267kkk:267val [014,014] 266kkk:266val
=== SBLK[47] [015,015] 265kkk:265val [016,016] 264kkk:264val [017,017] 263kkk:263val
=== SBLK[47] [018,018] 262kkk:262val [019,019] 261kkk:261val [020,020] 260kkk:260val
=== SBLK[47] [021,021] 259kkk:259val [022,022] 258kkk:258val [023,023] 257kkk:257val
=== SBLK[47] [024,024] 256kkk:256val [025,025] 255kkk:255val [026,026] 254kkk:254val
=== SBLK[47] [027,027] 253kkk:253val [028,028] 252kkk:252val [029,029] 251kkk:251val
=== SBLK[47] [030,030] 250kkk:250val [031,031] 249kkk:249val
=== SBLK[53] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=47, db=1
=== SBLK[53] szpow=9, lkl=6, lk=248kkk
=== SBLK[53] [000,000] 248kkk:248val [001,001] 247kkk:247val [002,002] 246kkk:246val
=== SBLK[53] [003,003] 245kkk:245val [004,004] 244kkk:244val [005,005] 243kkk:243val
=== SBLK[53] [006,006] 242kkk:242val [007,007] 241kkk:241val [008,008] 240kkk:240val
=== SBLK[53] [009,009] 239kkk:239val [010,010] 238kkk:238val [011,011] 237kkk:237val
=== SBLK[53] [012,012] 236kkk:236val [013,013] 235kkk:235val [014,014] 234kkk:234val
=== SBLK[53] [015,015] 233kkk:233val [016,016] 232kkk:232val [017,017] 231kkk:231val
=== SBLK[53] [018,018] 230kkk:230val [019,019] 229kkk:229val [020,020] 228kkk:228val
=== SBLK[53] [021,021] 227kkk:227val [022,022] 226kkk:226val [023,023] 225kkk:225val
=== SBLK[53] [024,024] 224kkk:224val [025,025] 223kkk:223val [026,026] 222kkk:222val
=== SBLK[53] [027,027] 221kkk:221val [028,028] 220kkk:220val [029,029] 219kkk:219val
=== SBLK[53] [030,030] 218kkk:218val [031,031] 217kkk:217val
=== SBLK[59] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=53, db=1
=== SBLK[59] szpow=9, lkl=6, lk=216kkk
=== SBLK[59] [000,000] 216kkk:216val [001,001] 215kkk:215val [002,002] 214kkk:214val
=== SBLK[59] [003,003] 213kkk:213val [004,004] 212kkk:212val [005,005] 211kkk:211val
=== SBLK[59] [006,006] 210kkk:210val [007,007] 209kkk:209val [008,008] 208kkk:208val
=== SBLK[59] [009,009] 207kkk:207val [010,010] 206kkk:206val [011,011] 205kkk:205val
=== SBLK[59] [012,012] 204kkk:204val [013,013] 203kkk:203val [014,014] 202kkk:202val
=== SBLK[59] [015,015] 201kkk:201val [016,016] 200kkk:200val [017,017] 199kkk:199val
=== SBLK[59] [018,018] 198kkk:198val [019,019] 197kkk:197val [020,020] 196kkk:196val
=== SBLK[59] [021,021] 195kkk:195val [022,022] 194kkk:194val [023,023] 193kkk:193val
=== SBLK[59] [024,024] 192kkk:192val [025,025] 191kkk:191val [026,026] 190kkk:190val
=== SBLK[59] [027,027] 189kkk:189val [028,028] 188kkk:188val [029,029] 187kkk:187val
=== SBLK[59] [030,030] 186kkk:186val [031,031] 185kkk:185val
=== SBLK[65] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=59, db=1
=== SBLK[65] szpow=9, lkl=6, lk=184kkk
=== SBLK[65] [000,000] 184kkk:184val [001,001] 183kkk:183val [002,002] 182kkk:182val
=== SBLK[65] [003,003] 181kkk:181val [004,004] 180kkk:180val [005,005] 179kkk:179val
=== SBLK[65] [006,006] 178kkk:178val [007,007] 177kkk:177val [008,008] 176kkk:176val
=== SBLK[65] [009,009] 175kkk:175val [010,010] 174kkk:174val [011,011] 173kkk:173val
=== SBLK[65] [012,012] 172kkk:172val [013,013] 171kkk:171val [014,014] 170kkk:170val
=== SBLK[65] [015,015] 169kkk:169val [016,016] 168kkk:168val [017,017] 167kkk:167val
=== SBLK[65] [018,018] 166kkk:166val [019,019] 165kkk:165val [020,020] 164kkk:164val
=== SBLK[65] [021,021] 163kkk:163val [022,022] 162kkk:162val [023,023] 161kkk:161val
=== SBLK[65] [024,024] 160kkk:160val [025,025] 159kkk:159val [026,026] 158kkk:158val
=== SBLK[65] [027,027] 157kkk:157val [028,028] 156kkk:156val [029,029] 155kkk:155val
=== SBLK[65] [030,030] 154kkk:154val [031,031] 153kkk:153val
=== SBLK[71] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=65, db=1
=== SBLK[71] szpow=9, lkl=6, lk=152kkk
=== SBLK[71] [000,000] 152kkk:152val [001,001] 151kkk:151val [002,002] 150kkk:150val
=== SBLK[71] [003,003] 149kkk:149val [004,004] 148kkk:148val [005,005] 147kkk:147val
=== SBLK[71] [006,006] 146kkk:146val [007,007] 145kkk:145val [008,008] 144kkk:144val
=== SBLK[71] [009,009] 143kkk:143val [010,010] 142kkk:142val [011,011] 141kkk:141val
=== SBLK[71] [012,012] 140kkk:140val [013,013] 139kkk:139val [014,014] 138kkk:138val
=== SBLK[71] [015,015] 137kkk:137val [016,016] 136kkk:136val [017,017] 135kkk:135val
=== SBLK[71] [018,018] 134kkk:134val [019,019] 133kkk:133val [020,020] 132kkk:132val
=== SBLK[71] [021,021] 131kkk:131val [022,022] 130kkk:130val [023,023] 129kkk:129val
=== SBLK[71] [024,024] 128kkk:128val [025,025] 127kkk:127val [026,026] 126kkk:126val
=== SBLK[71] [027,027] 125kkk:125val [028,028] 124kkk:124val [029,029] 123kkk:123val
=== SBLK[71] [030,030] 122kkk:122val [031,031] 121kkk:121val
=== SBLK[77] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=71, db=1
=== SBLK[77] szpow=9, lkl=6, lk=120kkk
=== SBLK[77] [000,000] 120kkk:120val [001,001] 119kkk:119val [002,002] 118kkk:118val
=== SBLK[77] [003,003] 117kkk:117val [004,004] 116kkk:116val [005,005] 115kkk:115val
=== SBLK[77] [006,006] 114kkk:114val [007,007] 113kkk:113val [008,008] 112kkk:112val
=== SBLK[77] [009,009] 111kkk:111val [010,010] 110kkk:110val [011,011] 109kkk:109val
=== SBLK[77] [012,012] 108kkk:108val [013,013] 107kkk:107val [014,014] 106kkk:106val
=== SBLK[77] [015,015] 105kkk:105val [016,016] 104kkk:104val [017,017] 103kkk:103val
=== SBLK[77] [018,018] 102kkk:102val [019,019] 101kkk:101val [020,020] 100kkk:100val
=== SBLK[77] [021,021] 099kkk:099val [022,022] 098kkk:098val [023,023] 097kkk:097val
=== SBLK[77] [024,024] 096kkk:096val [025,025] 095kkk:095val [026,026] 094kkk:094val
=== SBLK[77] [027,027] 093kkk:093val [028,028] 092kkk:092val [029,029] 091kkk:091val
=== SBLK[77] [030,030] 090kkk:090val [031,031] 089kkk:089val
=== SBLK[83] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=77, db=1
=== SBLK[83] szpow=9, lkl=6, lk=088kkk
=== SBLK[83] [000,000] 088kkk:088val [001,001] 087kkk:087val [002,002] 086kkk:086val
=== SBLK[83] [003,003] 085kkk:085val [004,004] 084kkk:084val [005,005] 083kkk:083val
=== SBLK[83] [006,006] 082kkk:082val [007,007] 081kkk:081val [008,008] 080kkk:080val
=== SBLK[83] [009,009] 079kkk:079val [010,010] 078kkk:078val [011,011] 077kkk:077val
=== SBLK[83] [012,012] 076kkk:076val [013,013] 075kkk:075val [014,014] 074kkk:074val
=== SBLK[83] [015,015] 073kkk:073val [016,016] 072kkk:072val [017,017] 071kkk:071val
=== SBLK[83] [018,018] 070kkk:070val [019,019] 069kkk:069val [020,020] 068kkk:068val
=== SBLK[83] [021,021] 067kkk:067val [022,022] 066kkk:066val [023,023] 065kkk:065val
=== SBLK[83] [024,024] 064kkk:064val [025,025] 063kkk:063val [026,026] 062kkk:062val
=== SBLK[83] [027,027] 061kkk:061val [028,028] 060kkk:060val [029,029] 059kkk:059val
=== SBLK[83] [030,030] 058kkk:058val [031,031] 057kkk:057val
=== SBLK[89] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=83, db=1
=== SBLK[89] szpow=9, lkl=6, lk=056kkk
=== SBLK[89] [000,000] 056kkk:056val [001,001] 055kkk:055val [002,002] 054kkk:054val
=== SBLK[89] [003,003] 053kkk:053val [004,004] 052kkk:052val [005,005] 051kkk:051val
=== SBLK[89] [006,006] 050kkk:050val [007,007] 049kkk:049val [008,008] 048kkk:048val
=== SBLK[89] [009,009] 047kkk:047val [010,010] 046kkk:046val [011,011] 045kkk:045val
=== SBLK[89] [012,012] 044kkk:044val [013,013] 043kkk:043val [014,014] 042kkk:042val
=== SBLK[89] [015,015] 041kkk:041val [016,016] 040kkk:040val [017,017] 039kkk:039val
=== SBLK[89] [018,018] 038kkk:038val [019,019] 037kkk:037val [020,020] 036kkk:036val
=== SBLK[89] [021,021] 035kkk:035val [022,022] 034kkk:034val [023,023] 033kkk:033val
=== SBLK[89] [024,024] 032kkk:032val [025,025] 031kkk:031val [026,026] 030kkk:030val
=== SBLK[89] [027,027] 029kkk:029val [028,028] 028kkk:028val [029,029] 027kkk:027val
=== SBLK[89] [030,030] 026kkk:026val [031,031] 025kkk:025val
=== SBLK[95] lvl=-1, pnum=25, flg=1, kvzidx=25, p0=89, db=1
=== SBLK[95] szpow=9, lkl=6, lk=024kkk
=== SBLK[95] [000,000] 024kkk:024val [001,001] 023kkk:023val [002,002] 022kkk:022val
=== SBLK[95] [003,003] 021kkk:021val [004,004] 020kkk:020val [005,005] 019kkk:019val
=== SBLK[95] [006,006] 018kkk:018val [007,007] 017kkk:017val [008,008] 016kkk:016val
=== SBLK[95] [009,009] 015kkk:015val [010,010] 014kkk:014val [011,011] 013kkk:013val
=== SBLK[95] [012,012] 012kkk:012val [013,013] 011kkk:011val [014,014] 010kkk:010val
=== SBLK[95] [015,015] 009kkk:009val [016,016] 008kkk:008val [017,017] 007kkk:007val
=== SBLK[95] [018,018] 006kkk:006val [019,019] 005kkk:005val [020,020] 004kkk:004val
=== SBLK[95] [021,021] 003kkk:003val [022,022] 002kkk:002val [023,023] 001kkk:001val
=== SBLK[95] [024,024] 000kkk:000val
#### Stage: db1 destroyed
== DB[1] lvl=-1, blk=3, dbflg=0, p0=3
+247
View File
@@ -0,0 +1,247 @@
#### Stage: desc sorted keys inserted
== DB[1] lvl=-1, blk=3, dbflg=0, p0=35
=== SBLK[5] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=3, db=1
=== SBLK[5] szpow=9, lkl=6, lk=504kkk
=== SBLK[5] [000,000] 504kkk:504val [001,001] 503kkk:503val [002,002] 502kkk:502val
=== SBLK[5] [003,003] 501kkk:501val [004,004] 500kkk:500val [005,005] 499kkk:499val
=== SBLK[5] [006,006] 498kkk:498val [007,007] 497kkk:497val [008,008] 496kkk:496val
=== SBLK[5] [009,009] 495kkk:495val [010,010] 494kkk:494val [011,011] 493kkk:493val
=== SBLK[5] [012,012] 492kkk:492val [013,013] 491kkk:491val [014,014] 490kkk:490val
=== SBLK[5] [015,015] 489kkk:489val [016,016] 488kkk:488val [017,017] 487kkk:487val
=== SBLK[5] [018,018] 486kkk:486val [019,019] 485kkk:485val [020,020] 484kkk:484val
=== SBLK[5] [021,021] 483kkk:483val [022,022] 482kkk:482val [023,023] 481kkk:481val
=== SBLK[5] [024,024] 480kkk:480val [025,025] 479kkk:479val [026,026] 478kkk:478val
=== SBLK[5] [027,027] 477kkk:477val [028,028] 476kkk:476val [029,029] 475kkk:475val
=== SBLK[5] [030,030] 474kkk:474val [031,031] 473kkk:473val
=== SBLK[7] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=5, db=1
=== SBLK[7] szpow=9, lkl=6, lk=472kkk
=== SBLK[7] [000,000] 472kkk:472val [001,001] 471kkk:471val [002,002] 470kkk:470val
=== SBLK[7] [003,003] 469kkk:469val [004,004] 468kkk:468val [005,005] 467kkk:467val
=== SBLK[7] [006,006] 466kkk:466val [007,007] 465kkk:465val [008,008] 464kkk:464val
=== SBLK[7] [009,009] 463kkk:463val [010,010] 462kkk:462val [011,011] 461kkk:461val
=== SBLK[7] [012,012] 460kkk:460val [013,013] 459kkk:459val [014,014] 458kkk:458val
=== SBLK[7] [015,015] 457kkk:457val [016,016] 456kkk:456val [017,017] 455kkk:455val
=== SBLK[7] [018,018] 454kkk:454val [019,019] 453kkk:453val [020,020] 452kkk:452val
=== SBLK[7] [021,021] 451kkk:451val [022,022] 450kkk:450val [023,023] 449kkk:449val
=== SBLK[7] [024,024] 448kkk:448val [025,025] 447kkk:447val [026,026] 446kkk:446val
=== SBLK[7] [027,027] 445kkk:445val [028,028] 444kkk:444val [029,029] 443kkk:443val
=== SBLK[7] [030,030] 442kkk:442val [031,031] 441kkk:441val
=== SBLK[9] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=7, db=1
=== SBLK[9] szpow=9, lkl=6, lk=440kkk
=== SBLK[9] [000,000] 440kkk:440val [001,001] 439kkk:439val [002,002] 438kkk:438val
=== SBLK[9] [003,003] 437kkk:437val [004,004] 436kkk:436val [005,005] 435kkk:435val
=== SBLK[9] [006,006] 434kkk:434val [007,007] 433kkk:433val [008,008] 432kkk:432val
=== SBLK[9] [009,009] 431kkk:431val [010,010] 430kkk:430val [011,011] 429kkk:429val
=== SBLK[9] [012,012] 428kkk:428val [013,013] 427kkk:427val [014,014] 426kkk:426val
=== SBLK[9] [015,015] 425kkk:425val [016,016] 424kkk:424val [017,017] 423kkk:423val
=== SBLK[9] [018,018] 422kkk:422val [019,019] 421kkk:421val [020,020] 420kkk:420val
=== SBLK[9] [021,021] 419kkk:419val [022,022] 418kkk:418val [023,023] 417kkk:417val
=== SBLK[9] [024,024] 416kkk:416val [025,025] 415kkk:415val [026,026] 414kkk:414val
=== SBLK[9] [027,027] 413kkk:413val [028,028] 412kkk:412val [029,029] 411kkk:411val
=== SBLK[9] [030,030] 410kkk:410val [031,031] 409kkk:409val
=== SBLK[11] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=9, db=1
=== SBLK[11] szpow=9, lkl=6, lk=408kkk
=== SBLK[11] [000,000] 408kkk:408val [001,001] 407kkk:407val [002,002] 406kkk:406val
=== SBLK[11] [003,003] 405kkk:405val [004,004] 404kkk:404val [005,005] 403kkk:403val
=== SBLK[11] [006,006] 402kkk:402val [007,007] 401kkk:401val [008,008] 400kkk:400val
=== SBLK[11] [009,009] 399kkk:399val [010,010] 398kkk:398val [011,011] 397kkk:397val
=== SBLK[11] [012,012] 396kkk:396val [013,013] 395kkk:395val [014,014] 394kkk:394val
=== SBLK[11] [015,015] 393kkk:393val [016,016] 392kkk:392val [017,017] 391kkk:391val
=== SBLK[11] [018,018] 390kkk:390val [019,019] 389kkk:389val [020,020] 388kkk:388val
=== SBLK[11] [021,021] 387kkk:387val [022,022] 386kkk:386val [023,023] 385kkk:385val
=== SBLK[11] [024,024] 384kkk:384val [025,025] 383kkk:383val [026,026] 382kkk:382val
=== SBLK[11] [027,027] 381kkk:381val [028,028] 380kkk:380val [029,029] 379kkk:379val
=== SBLK[11] [030,030] 378kkk:378val [031,031] 377kkk:377val
=== SBLK[13] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=11, db=1
=== SBLK[13] szpow=9, lkl=6, lk=376kkk
=== SBLK[13] [000,000] 376kkk:376val [001,001] 375kkk:375val [002,002] 374kkk:374val
=== SBLK[13] [003,003] 373kkk:373val [004,004] 372kkk:372val [005,005] 371kkk:371val
=== SBLK[13] [006,006] 370kkk:370val [007,007] 369kkk:369val [008,008] 368kkk:368val
=== SBLK[13] [009,009] 367kkk:367val [010,010] 366kkk:366val [011,011] 365kkk:365val
=== SBLK[13] [012,012] 364kkk:364val [013,013] 363kkk:363val [014,014] 362kkk:362val
=== SBLK[13] [015,015] 361kkk:361val [016,016] 360kkk:360val [017,017] 359kkk:359val
=== SBLK[13] [018,018] 358kkk:358val [019,019] 357kkk:357val [020,020] 356kkk:356val
=== SBLK[13] [021,021] 355kkk:355val [022,022] 354kkk:354val [023,023] 353kkk:353val
=== SBLK[13] [024,024] 352kkk:352val [025,025] 351kkk:351val [026,026] 350kkk:350val
=== SBLK[13] [027,027] 349kkk:349val [028,028] 348kkk:348val [029,029] 347kkk:347val
=== SBLK[13] [030,030] 346kkk:346val [031,031] 345kkk:345val
=== SBLK[15] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=13, db=1
=== SBLK[15] szpow=9, lkl=6, lk=344kkk
=== SBLK[15] [000,000] 344kkk:344val [001,001] 343kkk:343val [002,002] 342kkk:342val
=== SBLK[15] [003,003] 341kkk:341val [004,004] 340kkk:340val [005,005] 339kkk:339val
=== SBLK[15] [006,006] 338kkk:338val [007,007] 337kkk:337val [008,008] 336kkk:336val
=== SBLK[15] [009,009] 335kkk:335val [010,010] 334kkk:334val [011,011] 333kkk:333val
=== SBLK[15] [012,012] 332kkk:332val [013,013] 331kkk:331val [014,014] 330kkk:330val
=== SBLK[15] [015,015] 329kkk:329val [016,016] 328kkk:328val [017,017] 327kkk:327val
=== SBLK[15] [018,018] 326kkk:326val [019,019] 325kkk:325val [020,020] 324kkk:324val
=== SBLK[15] [021,021] 323kkk:323val [022,022] 322kkk:322val [023,023] 321kkk:321val
=== SBLK[15] [024,024] 320kkk:320val [025,025] 319kkk:319val [026,026] 318kkk:318val
=== SBLK[15] [027,027] 317kkk:317val [028,028] 316kkk:316val [029,029] 315kkk:315val
=== SBLK[15] [030,030] 314kkk:314val [031,031] 313kkk:313val
=== SBLK[17] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=15, db=1
=== SBLK[17] szpow=9, lkl=6, lk=312kkk
=== SBLK[17] [000,000] 312kkk:312val [001,001] 311kkk:311val [002,002] 310kkk:310val
=== SBLK[17] [003,003] 309kkk:309val [004,004] 308kkk:308val [005,005] 307kkk:307val
=== SBLK[17] [006,006] 306kkk:306val [007,007] 305kkk:305val [008,008] 304kkk:304val
=== SBLK[17] [009,009] 303kkk:303val [010,010] 302kkk:302val [011,011] 301kkk:301val
=== SBLK[17] [012,012] 300kkk:300val [013,013] 299kkk:299val [014,014] 298kkk:298val
=== SBLK[17] [015,015] 297kkk:297val [016,016] 296kkk:296val [017,017] 295kkk:295val
=== SBLK[17] [018,018] 294kkk:294val [019,019] 293kkk:293val [020,020] 292kkk:292val
=== SBLK[17] [021,021] 291kkk:291val [022,022] 290kkk:290val [023,023] 289kkk:289val
=== SBLK[17] [024,024] 288kkk:288val [025,025] 287kkk:287val [026,026] 286kkk:286val
=== SBLK[17] [027,027] 285kkk:285val [028,028] 284kkk:284val [029,029] 283kkk:283val
=== SBLK[17] [030,030] 282kkk:282val [031,031] 281kkk:281val
=== SBLK[19] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=17, db=1
=== SBLK[19] szpow=9, lkl=6, lk=280kkk
=== SBLK[19] [000,000] 280kkk:280val [001,001] 279kkk:279val [002,002] 278kkk:278val
=== SBLK[19] [003,003] 277kkk:277val [004,004] 276kkk:276val [005,005] 275kkk:275val
=== SBLK[19] [006,006] 274kkk:274val [007,007] 273kkk:273val [008,008] 272kkk:272val
=== SBLK[19] [009,009] 271kkk:271val [010,010] 270kkk:270val [011,011] 269kkk:269val
=== SBLK[19] [012,012] 268kkk:268val [013,013] 267kkk:267val [014,014] 266kkk:266val
=== SBLK[19] [015,015] 265kkk:265val [016,016] 264kkk:264val [017,017] 263kkk:263val
=== SBLK[19] [018,018] 262kkk:262val [019,019] 261kkk:261val [020,020] 260kkk:260val
=== SBLK[19] [021,021] 259kkk:259val [022,022] 258kkk:258val [023,023] 257kkk:257val
=== SBLK[19] [024,024] 256kkk:256val [025,025] 255kkk:255val [026,026] 254kkk:254val
=== SBLK[19] [027,027] 253kkk:253val [028,028] 252kkk:252val [029,029] 251kkk:251val
=== SBLK[19] [030,030] 250kkk:250val [031,031] 249kkk:249val
=== SBLK[21] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=19, db=1
=== SBLK[21] szpow=9, lkl=6, lk=248kkk
=== SBLK[21] [000,000] 248kkk:248val [001,001] 247kkk:247val [002,002] 246kkk:246val
=== SBLK[21] [003,003] 245kkk:245val [004,004] 244kkk:244val [005,005] 243kkk:243val
=== SBLK[21] [006,006] 242kkk:242val [007,007] 241kkk:241val [008,008] 240kkk:240val
=== SBLK[21] [009,009] 239kkk:239val [010,010] 238kkk:238val [011,011] 237kkk:237val
=== SBLK[21] [012,012] 236kkk:236val [013,013] 235kkk:235val [014,014] 234kkk:234val
=== SBLK[21] [015,015] 233kkk:233val [016,016] 232kkk:232val [017,017] 231kkk:231val
=== SBLK[21] [018,018] 230kkk:230val [019,019] 229kkk:229val [020,020] 228kkk:228val
=== SBLK[21] [021,021] 227kkk:227val [022,022] 226kkk:226val [023,023] 225kkk:225val
=== SBLK[21] [024,024] 224kkk:224val [025,025] 223kkk:223val [026,026] 222kkk:222val
=== SBLK[21] [027,027] 221kkk:221val [028,028] 220kkk:220val [029,029] 219kkk:219val
=== SBLK[21] [030,030] 218kkk:218val [031,031] 217kkk:217val
=== SBLK[23] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=21, db=1
=== SBLK[23] szpow=9, lkl=6, lk=216kkk
=== SBLK[23] [000,000] 216kkk:216val [001,001] 215kkk:215val [002,002] 214kkk:214val
=== SBLK[23] [003,003] 213kkk:213val [004,004] 212kkk:212val [005,005] 211kkk:211val
=== SBLK[23] [006,006] 210kkk:210val [007,007] 209kkk:209val [008,008] 208kkk:208val
=== SBLK[23] [009,009] 207kkk:207val [010,010] 206kkk:206val [011,011] 205kkk:205val
=== SBLK[23] [012,012] 204kkk:204val [013,013] 203kkk:203val [014,014] 202kkk:202val
=== SBLK[23] [015,015] 201kkk:201val [016,016] 200kkk:200val [017,017] 199kkk:199val
=== SBLK[23] [018,018] 198kkk:198val [019,019] 197kkk:197val [020,020] 196kkk:196val
=== SBLK[23] [021,021] 195kkk:195val [022,022] 194kkk:194val [023,023] 193kkk:193val
=== SBLK[23] [024,024] 192kkk:192val [025,025] 191kkk:191val [026,026] 190kkk:190val
=== SBLK[23] [027,027] 189kkk:189val [028,028] 188kkk:188val [029,029] 187kkk:187val
=== SBLK[23] [030,030] 186kkk:186val [031,031] 185kkk:185val
=== SBLK[25] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=23, db=1
=== SBLK[25] szpow=9, lkl=6, lk=184kkk
=== SBLK[25] [000,000] 184kkk:184val [001,001] 183kkk:183val [002,002] 182kkk:182val
=== SBLK[25] [003,003] 181kkk:181val [004,004] 180kkk:180val [005,005] 179kkk:179val
=== SBLK[25] [006,006] 178kkk:178val [007,007] 177kkk:177val [008,008] 176kkk:176val
=== SBLK[25] [009,009] 175kkk:175val [010,010] 174kkk:174val [011,011] 173kkk:173val
=== SBLK[25] [012,012] 172kkk:172val [013,013] 171kkk:171val [014,014] 170kkk:170val
=== SBLK[25] [015,015] 169kkk:169val [016,016] 168kkk:168val [017,017] 167kkk:167val
=== SBLK[25] [018,018] 166kkk:166val [019,019] 165kkk:165val [020,020] 164kkk:164val
=== SBLK[25] [021,021] 163kkk:163val [022,022] 162kkk:162val [023,023] 161kkk:161val
=== SBLK[25] [024,024] 160kkk:160val [025,025] 159kkk:159val [026,026] 158kkk:158val
=== SBLK[25] [027,027] 157kkk:157val [028,028] 156kkk:156val [029,029] 155kkk:155val
=== SBLK[25] [030,030] 154kkk:154val [031,031] 153kkk:153val
=== SBLK[27] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=25, db=1
=== SBLK[27] szpow=9, lkl=6, lk=152kkk
=== SBLK[27] [000,000] 152kkk:152val [001,001] 151kkk:151val [002,002] 150kkk:150val
=== SBLK[27] [003,003] 149kkk:149val [004,004] 148kkk:148val [005,005] 147kkk:147val
=== SBLK[27] [006,006] 146kkk:146val [007,007] 145kkk:145val [008,008] 144kkk:144val
=== SBLK[27] [009,009] 143kkk:143val [010,010] 142kkk:142val [011,011] 141kkk:141val
=== SBLK[27] [012,012] 140kkk:140val [013,013] 139kkk:139val [014,014] 138kkk:138val
=== SBLK[27] [015,015] 137kkk:137val [016,016] 136kkk:136val [017,017] 135kkk:135val
=== SBLK[27] [018,018] 134kkk:134val [019,019] 133kkk:133val [020,020] 132kkk:132val
=== SBLK[27] [021,021] 131kkk:131val [022,022] 130kkk:130val [023,023] 129kkk:129val
=== SBLK[27] [024,024] 128kkk:128val [025,025] 127kkk:127val [026,026] 126kkk:126val
=== SBLK[27] [027,027] 125kkk:125val [028,028] 124kkk:124val [029,029] 123kkk:123val
=== SBLK[27] [030,030] 122kkk:122val [031,031] 121kkk:121val
=== SBLK[29] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=27, db=1
=== SBLK[29] szpow=9, lkl=6, lk=120kkk
=== SBLK[29] [000,000] 120kkk:120val [001,001] 119kkk:119val [002,002] 118kkk:118val
=== SBLK[29] [003,003] 117kkk:117val [004,004] 116kkk:116val [005,005] 115kkk:115val
=== SBLK[29] [006,006] 114kkk:114val [007,007] 113kkk:113val [008,008] 112kkk:112val
=== SBLK[29] [009,009] 111kkk:111val [010,010] 110kkk:110val [011,011] 109kkk:109val
=== SBLK[29] [012,012] 108kkk:108val [013,013] 107kkk:107val [014,014] 106kkk:106val
=== SBLK[29] [015,015] 105kkk:105val [016,016] 104kkk:104val [017,017] 103kkk:103val
=== SBLK[29] [018,018] 102kkk:102val [019,019] 101kkk:101val [020,020] 100kkk:100val
=== SBLK[29] [021,021] 099kkk:099val [022,022] 098kkk:098val [023,023] 097kkk:097val
=== SBLK[29] [024,024] 096kkk:096val [025,025] 095kkk:095val [026,026] 094kkk:094val
=== SBLK[29] [027,027] 093kkk:093val [028,028] 092kkk:092val [029,029] 091kkk:091val
=== SBLK[29] [030,030] 090kkk:090val [031,031] 089kkk:089val
=== SBLK[31] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=29, db=1
=== SBLK[31] szpow=9, lkl=6, lk=088kkk
=== SBLK[31] [000,000] 088kkk:088val [001,001] 087kkk:087val [002,002] 086kkk:086val
=== SBLK[31] [003,003] 085kkk:085val [004,004] 084kkk:084val [005,005] 083kkk:083val
=== SBLK[31] [006,006] 082kkk:082val [007,007] 081kkk:081val [008,008] 080kkk:080val
=== SBLK[31] [009,009] 079kkk:079val [010,010] 078kkk:078val [011,011] 077kkk:077val
=== SBLK[31] [012,012] 076kkk:076val [013,013] 075kkk:075val [014,014] 074kkk:074val
=== SBLK[31] [015,015] 073kkk:073val [016,016] 072kkk:072val [017,017] 071kkk:071val
=== SBLK[31] [018,018] 070kkk:070val [019,019] 069kkk:069val [020,020] 068kkk:068val
=== SBLK[31] [021,021] 067kkk:067val [022,022] 066kkk:066val [023,023] 065kkk:065val
=== SBLK[31] [024,024] 064kkk:064val [025,025] 063kkk:063val [026,026] 062kkk:062val
=== SBLK[31] [027,027] 061kkk:061val [028,028] 060kkk:060val [029,029] 059kkk:059val
=== SBLK[31] [030,030] 058kkk:058val [031,031] 057kkk:057val
=== SBLK[33] lvl=-1, pnum=32, flg=1, kvzidx=-1, p0=31, db=1
=== SBLK[33] szpow=9, lkl=6, lk=056kkk
=== SBLK[33] [000,000] 056kkk:056val [001,001] 055kkk:055val [002,002] 054kkk:054val
=== SBLK[33] [003,003] 053kkk:053val [004,004] 052kkk:052val [005,005] 051kkk:051val
=== SBLK[33] [006,006] 050kkk:050val [007,007] 049kkk:049val [008,008] 048kkk:048val
=== SBLK[33] [009,009] 047kkk:047val [010,010] 046kkk:046val [011,011] 045kkk:045val
=== SBLK[33] [012,012] 044kkk:044val [013,013] 043kkk:043val [014,014] 042kkk:042val
=== SBLK[33] [015,015] 041kkk:041val [016,016] 040kkk:040val [017,017] 039kkk:039val
=== SBLK[33] [018,018] 038kkk:038val [019,019] 037kkk:037val [020,020] 036kkk:036val
=== SBLK[33] [021,021] 035kkk:035val [022,022] 034kkk:034val [023,023] 033kkk:033val
=== SBLK[33] [024,024] 032kkk:032val [025,025] 031kkk:031val [026,026] 030kkk:030val
=== SBLK[33] [027,027] 029kkk:029val [028,028] 028kkk:028val [029,029] 027kkk:027val
=== SBLK[33] [030,030] 026kkk:026val [031,031] 025kkk:025val
=== SBLK[35] lvl=-1, pnum=25, flg=1, kvzidx=25, p0=33, db=1
=== SBLK[35] szpow=9, lkl=6, lk=024kkk
=== SBLK[35] [000,000] 024kkk:024val [001,001] 023kkk:023val [002,002] 022kkk:022val
=== SBLK[35] [003,003] 021kkk:021val [004,004] 020kkk:020val [005,005] 019kkk:019val
=== SBLK[35] [006,006] 018kkk:018val [007,007] 017kkk:017val [008,008] 016kkk:016val
=== SBLK[35] [009,009] 015kkk:015val [010,010] 014kkk:014val [011,011] 013kkk:013val
=== SBLK[35] [012,012] 012kkk:012val [013,013] 011kkk:011val [014,014] 010kkk:010val
=== SBLK[35] [015,015] 009kkk:009val [016,016] 008kkk:008val [017,017] 007kkk:007val
=== SBLK[35] [018,018] 006kkk:006val [019,019] 005kkk:005val [020,020] 004kkk:004val
=== SBLK[35] [021,021] 003kkk:003val [022,022] 002kkk:002val [023,023] 001kkk:001val
=== SBLK[35] [024,024] 000kkk:000val
#### Stage: db1 destroyed
== DB[1] lvl=-1, blk=3, dbflg=0, p0=3
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+86
View File
@@ -0,0 +1,86 @@
#include "iwkv.h"
#include "iwlog.h"
#include "iwutils.h"
#include "iwcfg.h"
#include <CUnit/Basic.h>
#define RND_DATA_SZ (10*1048576)
char RND_DATA[RND_DATA_SZ];
int init_suite(void) {
iwrc rc = iwkv_init();
return rc;
}
int clean_suite(void) {
return 0;
}
static void iwkv_test2_1(void) {
IWKV_OPTS opts = {
.path = "iwkv_test2_1.db",
.oflags = IWKV_TRUNC
};
const uint64_t numrec = 1000000; // 1M
// Test open/close
IWKV iwkv;
IWDB db1;
IWKV_val key, val;
iwrc rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 1, IWDB_VNUM64_KEYS, &db1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
for (uint64_t i = 0; i < numrec; ++i) {
key.size = sizeof(uint64_t);
key.data = &i;
val.size = sizeof(uint64_t);
val.data = &i;
rc = iwkv_put(db1, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
for (uint64_t v = 0; v < numrec; ++v) {
uint64_t llv;
key.data = &v;
key.size = sizeof(uint64_t);
rc = iwkv_get(db1, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc, 0);
memcpy(&llv, val.data, sizeof(llv));
CU_ASSERT_EQUAL_FATAL(llv, v);
iwkv_val_dispose(&val);
}
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
int main() {
CU_pSuite pSuite = NULL;
/* Initialize the CUnit test registry */
if (CUE_SUCCESS != CU_initialize_registry()) return CU_get_error();
/* Add a suite to the registry */
pSuite = CU_add_suite("iwkv_test2", init_suite, clean_suite);
if (NULL == pSuite) {
CU_cleanup_registry();
return CU_get_error();
}
/* Add the tests to the suite */
if ((NULL == CU_add_test(pSuite, "iwkv_test2_1", iwkv_test2_1))
) {
CU_cleanup_registry();
return CU_get_error();
}
/* Run all tests using the CUnit Basic interface */
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
int ret = CU_get_error() || CU_get_number_of_failures();
CU_cleanup_registry();
return ret;
}
+202
View File
@@ -0,0 +1,202 @@
#include "iwkv.h"
#include "iwlog.h"
#include "iwutils.h"
#include "iwcfg.h"
#include <CUnit/Basic.h>
#include <pthread.h>
#include <stdatomic.h>
#include <unistd.h>
typedef struct VN {
int kn; // key number
int vs; // value seed
} VN;
typedef struct CTX {
VN *vn;
int vnsz;
pthread_cond_t cond;
pthread_mutex_t mtx;
int readynum;
const int thrnum;
IWDB db;
} CTX;
typedef struct TASK {
CTX *ctx;
int start;
int cnt;
pthread_t thr;
} TASK;
int init_suite(void) {
iwrc rc = iwkv_init();
return rc;
}
int clean_suite(void) {
return 0;
}
static int logstage(FILE *f, const char *name, IWDB db) {
int rci = fprintf(f, "\n#### Stage: %s\n", name);
iwkvd_db(f, db, /*IWKVD_PRINT_NO_LEVEVELS*/ 0, 0);
fflush(f);
return rci < 0 ? rci : 0;
}
static void *iwkv_test1_worker(void *op) {
TASK *t = op;
CTX *ctx = t->ctx;
int mynum;
int rci = pthread_mutex_lock(&ctx->mtx);
CU_ASSERT_EQUAL_FATAL(rci, 0);
++ctx->readynum;
mynum = ctx->readynum;
if (mynum == ctx->thrnum) {
pthread_cond_broadcast(&ctx->cond);
} else {
pthread_cond_wait(&ctx->cond, &ctx->mtx);
}
pthread_mutex_unlock(&ctx->mtx);
IWKV_val key, val;
for (int i = 0; i < t->cnt; ++i) {
uint64_t k = t->start + i;
uint64_t v = k;
key.size = sizeof(uint64_t);
key.data = &k;
val.size = sizeof(uint64_t);
val.data = &v;
iwrc rc = iwkv_put(ctx->db, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
return 0;
}
static void iwkv_test3_impl(int thrnum, int recth, bool wal) {
FILE *f = fopen("iwkv_test3_1.log", "w+");
CU_ASSERT_PTR_NOT_NULL(f);
const int nrecs = thrnum * recth;
TASK *tasks = calloc(thrnum, sizeof(*tasks));
VN *arr = calloc(nrecs, sizeof(*arr));
CTX ctx = {
.vn = arr,
.vnsz = nrecs,
.mtx = PTHREAD_MUTEX_INITIALIZER,
.cond = PTHREAD_COND_INITIALIZER,
.thrnum = thrnum
};
for (int i = 0; i < nrecs; ++i) {
arr[i].kn = i;
arr[i].vs = iwu_rand_range(256);
}
// shuffle
for (int i = 0; i < nrecs; ++i) {
uint32_t tgt = iwu_rand_range(nrecs);
int knt = arr[tgt].kn;
arr[tgt].kn = arr[i].kn;
arr[i].kn = knt;
}
for (int i = nrecs - 1; i >= 0; --i) {
uint32_t tgt = iwu_rand_range(nrecs);
int knt = arr[tgt].kn;
arr[tgt].kn = arr[i].kn;
arr[i].kn = knt;
}
IWKV_OPTS opts = {
.path = "iwkv_test3_1.db",
.oflags = IWKV_TRUNC,
.wal = {
.enabled = wal,
.checkpoint_buffer_sz = 1024 * 1024
}
};
IWKV iwkv;
IWKV_val key, val;
iwrc rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 1, IWDB_VNUM64_KEYS, &ctx.db);
CU_ASSERT_EQUAL_FATAL(rc, 0);
for (int i = 0; i < thrnum; ++i) {
tasks[i].ctx = &ctx;
tasks[i].start = i * recth;
tasks[i].cnt = recth;
int rci = pthread_create(&tasks[i].thr, 0, iwkv_test1_worker, &tasks[i]);
CU_ASSERT_EQUAL_FATAL(rci, 0);
}
for (int i = 0; i < thrnum; ++i) {
int rci = pthread_join(tasks[i].thr, 0);
CU_ASSERT_EQUAL_FATAL(rci, 0);
}
fprintf(stderr, "\nChecking DB....");
int ec = 0;
for (int i = 0; i < nrecs; ++i) {
uint64_t k = i, v;
key.data = &k;
key.size = sizeof(uint64_t);
rc = iwkv_get(ctx.db, &key, &val);
if (rc) {
ec++;
fprintf(stderr, "\nwk=%d\n", i);
iwlog_ecode_error3(rc);
//break;
} else {
CU_ASSERT_EQUAL_FATAL(val.size, sizeof(uint64_t));
memcpy(&v, val.data, sizeof(uint64_t));
CU_ASSERT_EQUAL_FATAL(v, i);
}
iwkv_val_dispose(&val);
}
pthread_cond_destroy(&ctx.cond);
pthread_mutex_destroy(&ctx.mtx);
free(arr);
free(tasks);
rc = iwkv_close(&iwkv);
fprintf(stderr, "ec=%d\n", ec);
CU_ASSERT_EQUAL_FATAL(rc, 0);
fclose(f);
}
static void iwkv_test3_1(void) {
iwkv_test3_impl(4, 30000, false);
}
static void iwkv_test3_2(void) {
iwkv_test3_impl(4, 30000, true);
}
int main() {
CU_pSuite pSuite = NULL;
/* Initialize the CUnit test registry */
if (CUE_SUCCESS != CU_initialize_registry()) return CU_get_error();
/* Add a suite to the registry */
pSuite = CU_add_suite("iwkv_test3", init_suite, clean_suite);
if (NULL == pSuite) {
CU_cleanup_registry();
return CU_get_error();
}
/* Add the tests to the suite */
if (
(NULL == CU_add_test(pSuite, "iwkv_test3_1", iwkv_test3_1)) ||
(NULL == CU_add_test(pSuite, "iwkv_test3_2", iwkv_test3_2))
) {
CU_cleanup_registry();
return CU_get_error();
}
/* Run all tests using the CUnit Basic interface */
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
int ret = CU_get_error() || CU_get_number_of_failures();
CU_cleanup_registry();
return ret;
}
+343
View File
@@ -0,0 +1,343 @@
#include "iwkv.h"
#include "iwlog.h"
#include "iwutils.h"
#include "iwcfg.h"
#include "iwkv_tests.h"
#include "iwkv_internal.h"
uint32_t g_seed;
uint32_t g_rnd_data_pos;
#define RND_DATA_SZ (10*1048576)
char RND_DATA[RND_DATA_SZ];
static void *rndbuf_next(uint32_t len) {
assert(len <= RND_DATA_SZ);
if (g_rnd_data_pos + len > RND_DATA_SZ) {
g_rnd_data_pos = 0;
}
const char *ret = RND_DATA + g_rnd_data_pos;
g_rnd_data_pos += len;
return (void *) ret;
}
int init_suite(void) {
iwrc rc = iwkv_init();
RCRET(rc);
uint64_t ts;
iwp_current_time_ms(&ts, false);
ts = IW_SWAB64(ts);
ts >>= 32;
g_seed = ts;
fprintf(stderr, "\nRandom seed: %u\n", g_seed);
iwu_rand_seed(g_seed);
for (int i = 0; i < RND_DATA_SZ; ++i) {
RND_DATA[i] = ' ' + iwu_rand_range(95); // ascii space ... ~
}
return rc;
}
int clean_suite(void) {
return 0;
}
static void iwkv_test4_4(void) {
char *path = "iwkv_test4_4.db";
IWKV iwkv;
IWDB db1;
IWKV_val key = {0};
IWKV_val val = {0};
IWKV_OPTS opts = {
.path = path,
.oflags = IWKV_TRUNC,
.random_seed = g_seed,
.wal = {
.enabled = true,
.savepoint_timeout_sec = 2,
.checkpoint_timeout_sec = 300
}
};
iwrc rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 1, 0, &db1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
key.data = "key00001";
key.size = strlen(key.data);
val.data = "value00001";
val.size = strlen(val.data);
rc = iwkv_put(db1, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_FALSE(iwal_synched(iwkv));
sleep(4);
CU_ASSERT_TRUE(iwal_synched(iwkv));
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
static void iwkv_test4_3_impl(int fmt_version) {
char *path = "iwkv_test4_3.db";
IWKV iwkv;
IWDB db1;
IWKV_val key = {0};
IWKV_val val = {0};
IWKV_OPTS opts = {
.path = path,
.oflags = IWKV_TRUNC | IWKV_NO_TRIM_ON_CLOSE,
.random_seed = g_seed,
.fmt_version = fmt_version,
.wal = {
.enabled = true,
.check_crc_on_checkpoint = true,
.savepoint_timeout_sec = UINT32_MAX
}
};
iwrc rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 1, 0, &db1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
key.data = "key00001";
key.size = strlen(key.data);
val.data = "value00001";
val.size = strlen(val.data);
rc = iwkv_put(db1, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_sync(iwkv, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
key.data = "key00002";
key.size = strlen(key.data);
val.data = "value00002";
val.size = strlen(val.data);
rc = iwkv_put(db1, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_sync(iwkv, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
key.data = "key00003";
key.size = strlen(key.data);
val.data = "value00003";
val.size = strlen(val.data);
rc = iwkv_put(db1, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
iwkvd_trigger_xor(IWKVD_WAL_NO_CHECKPOINT_ON_CLOSE);
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
// Now reopen and roll WAL log
iwkvd_trigger_xor(IWKVD_WAL_NO_CHECKPOINT_ON_CLOSE);
opts.oflags &= ~IWKV_TRUNC;
rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 1, 0, &db1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
key.data = "key00001";
key.size = strlen(key.data);
rc = iwkv_get(db1, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc, 0); // !!!!
CU_ASSERT_NSTRING_EQUAL(val.data, "value00001", val.size);
iwkv_kv_dispose(0, &val);
key.data = "key00002";
key.size = strlen(key.data);
rc = iwkv_get(db1, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_NSTRING_EQUAL(val.data, "value00002", val.size);
iwkv_kv_dispose(0, &val);
key.data = "key00003";
key.size = strlen(key.data);
rc = iwkv_get(db1, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc, IWKV_ERROR_NOTFOUND);
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
static void iwkv_test4_3_v1() {
iwkv_test4_3_impl(1);
}
static void iwkv_test4_3_v2() {
iwkv_test4_3_impl(2);
}
static void iwkv_test2_impl(char *path, const char *walpath, uint32_t num, uint32_t vrange) {
g_rnd_data_pos = 0;
char kbuf[100];
iwrc rc;
IWKV iwkv;
IWDB db1;
if (walpath) {
unlink(walpath);
}
IWKV_val key = {0};
IWKV_val val = {0};
IWKV_OPTS opts = {
.path = path,
.oflags = IWKV_TRUNC,
.random_seed = g_seed,
.wal = {
.enabled = (walpath != NULL),
.check_crc_on_checkpoint = true,
.savepoint_timeout_sec = UINT32_MAX,
.wal_buffer_sz = 64 * 1024,
.checkpoint_buffer_sz = 32 * 1024 * 1024
}
};
rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 1, 0, &db1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
key.data = kbuf;
for (int i = 0; i < num; ++i) {
int k = iwu_rand_range(num);
snprintf(key.data, sizeof(kbuf), "%016d", k);
key.size = strlen(key.data);
uint32_t value_size = iwu_rand_range(vrange + 1);
if (value_size == 0) {
value_size = 1;
}
val.data = rndbuf_next(value_size);
val.size = value_size;
rc = iwkv_put(db1, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
static void iwkv_test4_2(void) {
uint32_t num = 1000;
uint32_t vrange = 100000;
iwkv_test2_impl("iwkv_test4_2.db", NULL, num, vrange);
iwkv_test2_impl("iwkv_test4_2wal.db", "iwkv_test4_2wal.db-wal", num, vrange);
FILE *iw1 = fopen("iwkv_test4_2.db", "rb");
CU_ASSERT_PTR_NOT_NULL_FATAL(iw1);
FILE *iw2 = fopen("iwkv_test4_2wal.db", "rb");
CU_ASSERT_PTR_NOT_NULL_FATAL(iw2);
int ret = cmp_files(iw1, iw2);
CU_ASSERT_FALSE(ret);
fclose(iw1);
fclose(iw2);
}
static void iwkv_test1_impl(char *path, const char *walpath) {
iwrc rc;
IWKV iwkv;
IWDB db1, db2;
if (walpath) {
unlink(walpath);
}
IWKV_val key = {0};
IWKV_val val = {0};
IWKV_OPTS opts = {
.path = path,
.oflags = IWKV_TRUNC,
.wal = {
.enabled = (walpath != NULL),
.savepoint_timeout_sec = UINT32_MAX
}
};
rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 1, 0, &db1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 2, 0, &db2);
CU_ASSERT_EQUAL_FATAL(rc, 0);
key.data = "foo";
key.size = strlen(key.data);
val.data = "bar";
val.size = strlen(val.data);
rc = iwkv_put(db1, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
key.data = "foozz";
key.size = strlen(key.data);
val.data = "bazz";
val.size = strlen(val.data);
rc = iwkv_put(db2, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
key.data = "foozz2";
key.size = strlen(key.data);
val.data = "bazzbazzbazzbazz";
val.size = strlen(val.data);
rc = iwkv_put(db2, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
key.data = "foozz";
key.size = strlen(key.data);
rc = iwkv_del(db2, &key, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db_destroy(&db2);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
static void iwkv_test4_1(void) {
iwkv_test1_impl("iwkv_test4_1.db", NULL);
iwkv_test1_impl("iwkv_test4_1wal.db", "iwkv_test4_1wal.db-wal");
FILE *iw1 = fopen("iwkv_test4_1.db", "rb");
CU_ASSERT_PTR_NOT_NULL_FATAL(iw1);
FILE *iw2 = fopen("iwkv_test4_1wal.db", "rb");
CU_ASSERT_PTR_NOT_NULL_FATAL(iw2);
int ret = cmp_files(iw1, iw2);
CU_ASSERT_FALSE(ret);
fclose(iw1);
fclose(iw2);
}
int main() {
CU_pSuite pSuite = NULL;
/* Initialize the CUnit test registry */
if (CUE_SUCCESS != CU_initialize_registry()) return CU_get_error();
/* Add a suite to the registry */
pSuite = CU_add_suite("iwkv_test4", init_suite, clean_suite);
if (NULL == pSuite) {
CU_cleanup_registry();
return CU_get_error();
}
/* Add the tests to the suite */
if (
(NULL == CU_add_test(pSuite, "iwkv_test4_1", iwkv_test4_1)) ||
(NULL == CU_add_test(pSuite, "iwkv_test4_2", iwkv_test4_2)) ||
(NULL == CU_add_test(pSuite, "iwkv_test4_3_v1", iwkv_test4_3_v1)) ||
(NULL == CU_add_test(pSuite, "iwkv_test4_3_v2", iwkv_test4_3_v2)) ||
(NULL == CU_add_test(pSuite, "iwkv_test4_4", iwkv_test4_4))
) {
CU_cleanup_registry();
return CU_get_error();
}
/* Run all tests using the CUnit Basic interface */
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
int ret = CU_get_error() || CU_get_number_of_failures();
CU_cleanup_registry();
return ret;
}
+285
View File
@@ -0,0 +1,285 @@
#include "iwkv.h"
#include "iwlog.h"
#include "iwutils.h"
#include "iwcfg.h"
#include "iwkv_tests.h"
#include "iwkv_internal.h"
#define KBUFSZ 128
#define VBUFSZ 128
static char kbuf[KBUFSZ];
static char vbuf[VBUFSZ];
/**
* Test cursor consistency
*/
int init_suite(void) {
iwrc rc = iwkv_init();
return rc;
}
int clean_suite(void) {
return 0;
}
static void iwkv_test5_2() {
iwrc rc;
IWKV iwkv;
IWDB db;
IWKV_val key = {0};
IWKV_val val = {0};
IWKV_cursor cur1;
IWKV_OPTS opts = {
.path = "iwkv_test5_2.db",
.oflags = IWKV_TRUNC
};
rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 1, 0, &db);
CU_ASSERT_EQUAL_FATAL(rc, 0);
for (int i = 1; i <= 64; ++i) {
snprintf(kbuf, KBUFSZ, "%03dkkk", i);
snprintf(vbuf, VBUFSZ, "%03dval", i);
key.data = kbuf;
key.size = strlen(key.data);
val.data = vbuf;
val.size = strlen(val.data);
rc = iwkv_put(db, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
// Remove all data from start
rc = iwkv_cursor_open(db, &cur1, IWKV_CURSOR_BEFORE_FIRST, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
for (int i = 1; i <= 64; ++i) {
rc = iwkv_cursor_to(cur1, IWKV_CURSOR_NEXT);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_cursor_del(cur1, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
rc = iwkv_cursor_close(&cur1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_cursor_open(db, &cur1, IWKV_CURSOR_BEFORE_FIRST, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_cursor_to(cur1, IWKV_CURSOR_NEXT);
CU_ASSERT_EQUAL_FATAL(rc, IWKV_ERROR_NOTFOUND);
rc = iwkv_cursor_close(&cur1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
// Refill
for (int i = 1; i <= 64; ++i) {
snprintf(kbuf, KBUFSZ, "%03dkkk", i);
snprintf(vbuf, VBUFSZ, "%03dval", i);
key.data = kbuf;
key.size = strlen(key.data);
val.data = vbuf;
val.size = strlen(val.data);
rc = iwkv_put(db, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
// Remove all data from end
rc = iwkv_cursor_open(db, &cur1, IWKV_CURSOR_AFTER_LAST, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
for (int i = 1; i <= 64; ++i) {
rc = iwkv_cursor_to(cur1, IWKV_CURSOR_PREV);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_cursor_del(cur1, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
rc = iwkv_cursor_close(&cur1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_cursor_open(db, &cur1, IWKV_CURSOR_BEFORE_FIRST, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_cursor_to(cur1, IWKV_CURSOR_NEXT);
CU_ASSERT_EQUAL_FATAL(rc, IWKV_ERROR_NOTFOUND);
rc = iwkv_cursor_close(&cur1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
static void iwkv_test5_1(void) {
iwrc rc;
IWKV_val key = {0};
IWKV_val val = {0};
IWKV iwkv;
IWDB db;
IWKV_cursor cur1, cur2;
IWKV_OPTS opts = {
.path = "iwkv_test5_1.db",
.oflags = IWKV_TRUNC
};
rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 1, 0, &db);
CU_ASSERT_EQUAL_FATAL(rc, 0);
int c = 0;
for (int i = 1; i < 30 * 2; i = i + 2, ++c) {
snprintf(kbuf, KBUFSZ, "%03dkkk", i);
snprintf(vbuf, VBUFSZ, "%03dval", i);
key.data = kbuf;
key.size = strlen(key.data);
val.data = vbuf;
val.size = strlen(val.data);
rc = iwkv_put(db, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
//K: 023kkk
//K: 025kkk <--
//K: 027kkk
//K: 029kkk
snprintf(kbuf, KBUFSZ, "%03dkkk", 25);
key.data = kbuf;
key.size = strlen(key.data);
rc = iwkv_cursor_open(db, &cur1, IWKV_CURSOR_EQ, &key);
CU_ASSERT_EQUAL_FATAL(rc, 0);
//K: 023kkk
//K: 025kkk
//K: 027kkk
//K: 029kkk <--
//K: 031kkk
snprintf(kbuf, KBUFSZ, "%03dkkk", 29);
key.data = kbuf;
key.size = strlen(key.data);
rc = iwkv_cursor_open(db, &cur2, IWKV_CURSOR_EQ, &key);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL(cur1->cnpos, 17);
CU_ASSERT_EQUAL(cur2->cnpos, 15);
//K: 023kkk
//K: 025kkk <--
//K: 026kkk +
//K: 027kkk
//K: 029kkk <--
//K: 031kkk
snprintf(kbuf, KBUFSZ, "%03dkkk", 26);
snprintf(vbuf, VBUFSZ, "%03dval", 26);
key.data = kbuf;
key.size = strlen(key.data);
val.data = vbuf;
val.size = strlen(val.data);
rc = iwkv_put(db, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL(cur1->cnpos, 18);
CU_ASSERT_EQUAL(cur2->cnpos, 15);
snprintf(kbuf, KBUFSZ, "%03dkkk", 0);
snprintf(vbuf, VBUFSZ, "%03dval", 0);
key.data = kbuf;
key.size = strlen(key.data);
val.data = vbuf;
val.size = strlen(val.data);
rc = iwkv_put(db, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL(cur1->cnpos, 18);
CU_ASSERT_EQUAL(cur2->cnpos, 15);
//K: 023kkk
//K: 025kkk <--
//K: 026kkk +
//K: 027kkk
//K: 028kkk +
//K: 029kkk <--
//K: 031kkk
// FORCE SPLIT:
snprintf(kbuf, KBUFSZ, "%03dkkk", 28);
snprintf(vbuf, VBUFSZ, "%03dval", 28);
key.data = kbuf;
key.size = strlen(key.data);
val.data = vbuf;
val.size = strlen(val.data);
rc = iwkv_put(db, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL(cur1->cnpos, 1);
CU_ASSERT_EQUAL(cur2->cnpos, 15);
rc = iwkv_cursor_get(cur1, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_FALSE(strncmp((char *)key.data, "025kkk", strlen("025kkk")));
CU_ASSERT_FALSE(strncmp((char *)val.data, "025val", strlen("025val")));
iwkv_kv_dispose(&key, &val);
rc = iwkv_cursor_to(cur1, IWKV_CURSOR_NEXT);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_cursor_get(cur1, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_FALSE(strncmp((char *)key.data, "023kkk", strlen("023kkk")));
CU_ASSERT_FALSE(strncmp((char *)val.data, "023val", strlen("023val")));
iwkv_kv_dispose(&key, &val);
rc = iwkv_cursor_to(cur1, IWKV_CURSOR_PREV);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_cursor_to(cur1, IWKV_CURSOR_PREV);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_cursor_get(cur1, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_FALSE(strncmp((char *)key.data, "026kkk", strlen("026kkk")));
CU_ASSERT_FALSE(strncmp((char *)val.data, "026val", strlen("026val")));
iwkv_kv_dispose(&key, &val);
rc = iwkv_cursor_to(cur1, IWKV_CURSOR_PREV);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_cursor_get(cur1, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_FALSE(strncmp((char *)key.data, "027kkk", strlen("027kkk")));
CU_ASSERT_FALSE(strncmp((char *)val.data, "027val", strlen("027val")));
iwkv_kv_dispose(&key, &val);
CU_ASSERT_EQUAL(cur1->cnpos, 17);
rc = iwkv_cursor_close(&cur1);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_cursor_close(&cur2);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
int main() {
CU_pSuite pSuite = NULL;
/* Initialize the CUnit test registry */
if (CUE_SUCCESS != CU_initialize_registry()) return CU_get_error();
/* Add a suite to the registry */
pSuite = CU_add_suite("iwkv_test5", init_suite, clean_suite);
if (NULL == pSuite) {
CU_cleanup_registry();
return CU_get_error();
}
/* Add the tests to the suite */
if (
(NULL == CU_add_test(pSuite, "iwkv_test5_1", iwkv_test5_1)) ||
(NULL == CU_add_test(pSuite, "iwkv_test5_2", iwkv_test5_2))
) {
CU_cleanup_registry();
return CU_get_error();
}
/* Run all tests using the CUnit Basic interface */
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
int ret = CU_get_error() || CU_get_number_of_failures();
CU_cleanup_registry();
return ret;
}
+158
View File
@@ -0,0 +1,158 @@
#include "iwkv.h"
#include "iwlog.h"
#include "iwutils.h"
#include "iwcfg.h"
#include "iwkv_tests.h"
#include "iwkv_internal.h"
int init_suite(void) {
iwrc rc = iwkv_init();
return rc;
}
int clean_suite(void) {
return 0;
}
static void iwkv_test6_1_impl(int fmt_version) {
iwrc rc;
IWKV_val key = {0};
IWKV_val val = {0};
IWKV iwkv;
IWDB db;
IWKV_cursor cur;
IWKV_OPTS opts = {
.path = "iwkv_test6_1.db",
.oflags = IWKV_TRUNC,
.fmt_version = fmt_version
};
rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 1, IWDB_VNUM64_KEYS | IWDB_COMPOUND_KEYS, &db);
CU_ASSERT_EQUAL_FATAL(rc, 0);
for (uint32_t i = 0; i < 100; ++i) {
key.data = &i;
key.size = sizeof(i);
for (uint32_t j = 0; j < 1000; ++j) {
key.compound = j;
val.data = &j;
val.size = sizeof(j);
rc = iwkv_put(db, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_get(db, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_EQUAL_FATAL(key.size, sizeof(i));
CU_ASSERT_TRUE_FATAL(!memcmp(key.data, &i, sizeof(i)));
CU_ASSERT_TRUE_FATAL(val.size == 4 && val.compound == 0 && !memcmp(val.data, &j, sizeof(j)));
iwkv_val_dispose(&val);
}
}
for (uint32_t i = 0; i < 10; ++i) {
key.data = &i;
key.size = sizeof(i);
for (uint32_t j = 0; j < 10; ++j) {
key.compound = j;
IWKV_val ckey;
rc = iwkv_cursor_open(db, &cur, IWKV_CURSOR_EQ, &key);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_cursor_key(cur, &ckey);
CU_ASSERT_EQUAL_FATAL(rc, 0);
int64_t llv;
CU_ASSERT_TRUE_FATAL(ckey.size == 8);
memcpy(&llv, ckey.data, sizeof(llv));
CU_ASSERT_TRUE_FATAL(ckey.compound == j && llv == i);
iwkv_val_dispose(&ckey);
rc = iwkv_cursor_close(&cur);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
}
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
void iwkv_test6_1_v1() {
iwkv_test6_1_impl(1);
}
void iwkv_test6_1_v2() {
iwkv_test6_1_impl(2);
}
static void iwkv_test6_2_impl(int fmt_version) {
iwrc rc;
IWKV iwkv;
IWDB db;
IWKV_val key = {0};
IWKV_val val = {0};
char kbuf[PREFIX_KEY_LEN_V1];
IWKV_OPTS opts = {
.path = "iwkv_test6_2.db",
.oflags = IWKV_TRUNC,
.fmt_version = fmt_version
};
rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
for (int i = 0; i < iwkv->pklen - 1; ++i) {
kbuf[i] = (i % 94) + 33;
}
rc = iwkv_db(iwkv, 1, IWDB_COMPOUND_KEYS, &db);
CU_ASSERT_EQUAL_FATAL(rc, 0);
for (uint32_t i = 0; i < 1000; ++i) {
key.data = kbuf;
key.size = iwkv->pklen - 1;
key.compound = i;
rc = iwkv_put(db, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_get(db, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
static void iwkv_test6_2_v1() {
iwkv_test6_2_impl(1);
}
static void iwkv_test6_2_v2() {
iwkv_test6_2_impl(2);
}
int main() {
CU_pSuite pSuite = NULL;
/* Initialize the CUnit test registry */
if (CUE_SUCCESS != CU_initialize_registry()) return CU_get_error();
/* Add a suite to the registry */
pSuite = CU_add_suite("iwkv_test6", init_suite, clean_suite);
if (NULL == pSuite) {
CU_cleanup_registry();
return CU_get_error();
}
/* Add the tests to the suite */
if (
(NULL == CU_add_test(pSuite, "iwkv_test6_1_v1", iwkv_test6_1_v1)) ||
(NULL == CU_add_test(pSuite, "iwkv_test6_1_v2", iwkv_test6_1_v2)) ||
(NULL == CU_add_test(pSuite, "iwkv_test6_2_v1", iwkv_test6_2_v1)) ||
(NULL == CU_add_test(pSuite, "iwkv_test6_2_v2", iwkv_test6_2_v2))
) {
CU_cleanup_registry();
return CU_get_error();
}
/* Run all tests using the CUnit Basic interface */
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
int ret = CU_get_error() || CU_get_number_of_failures();
CU_cleanup_registry();
return ret;
}
+111
View File
@@ -0,0 +1,111 @@
#include "iwkv.h"
#include "iwlog.h"
#include "iwutils.h"
#include "iwcfg.h"
#include "iwkv_tests.h"
#include "iwkv_internal.h"
#define KBUFSZ 1024
#define VBUFSZ 1024
char kbuf[KBUFSZ];
char vbuf[VBUFSZ];
uint32_t g_seed;
int init_suite(void) {
iwrc rc = iwkv_init();
RCRET(rc);
g_seed = 2681089616;
return rc;
}
int clean_suite(void) {
return 0;
}
static void iwkv_test7_1_impl(int direction) {
iwrc rc;
IWKV iwkv;
IWDB db;
IWKV_val key = {0};
IWKV_val val = {0};
IWKV_OPTS opts = {
.path = direction > 0 ? "iwkv_test7_2_fwd.db" : "iwkv_test7_2_back.db",
.oflags = IWKV_TRUNC,
.random_seed = g_seed
};
rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 1, IWDB_COMPOUND_KEYS, &db);
CU_ASSERT_EQUAL_FATAL(rc, 0);
const int nrecords = 50000;
for (int i = 0; i < nrecords; ++i) {
snprintf(kbuf, KBUFSZ, "5368fce5-c138-4f0d-bfee-dbce07eb28e1%d", i);
snprintf(vbuf, VBUFSZ, "%04d", i);
key.data = kbuf;
key.size = strlen(key.data);
key.compound = direction > 0 ? i + 1 : nrecords - i;
val.data = vbuf;
val.size = strlen(val.data);
rc = iwkv_put(db, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
for (int i = 0; i < nrecords; ++i) {
snprintf(kbuf, KBUFSZ, "5368fce5-c138-4f0d-bfee-dbce07eb28e1%d", i);
snprintf(vbuf, VBUFSZ, "%04d", i);
key.data = kbuf;
key.size = strlen(key.data);
key.compound = direction > 0 ? i + 1 : nrecords - i;
rc = iwkv_get(db, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc, 0);
iwkv_val_dispose(&val);
}
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
static void iwkv_test7_1() {
iwkv_test7_1_impl(1);
iwkv_test7_1_impl(-1);
IWP_FILE_STAT fwd_s = {0};
IWP_FILE_STAT back_s = {0};
iwrc rc = iwp_fstat("iwkv_test7_2_fwd.db", &fwd_s);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwp_fstat("iwkv_test7_2_back.db", &back_s);
CU_ASSERT_EQUAL_FATAL(rc, 0);
CU_ASSERT_TRUE((double)fwd_s.size / back_s.size < 1.1);
}
int main() {
CU_pSuite pSuite = NULL;
/* Initialize the CUnit test registry */
if (CUE_SUCCESS != CU_initialize_registry()) return CU_get_error();
/* Add a suite to the registry */
pSuite = CU_add_suite("iwkv_test7", init_suite, clean_suite);
if (NULL == pSuite) {
CU_cleanup_registry();
return CU_get_error();
}
/* Add the tests to the suite */
if (
(NULL == CU_add_test(pSuite, "iwkv_test7_1", iwkv_test7_1))
) {
CU_cleanup_registry();
return CU_get_error();
}
/* Run all tests using the CUnit Basic interface */
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
int ret = CU_get_error() || CU_get_number_of_failures();
CU_cleanup_registry();
return ret;
}
+295
View File
@@ -0,0 +1,295 @@
#include "iwkv.h"
#include "iwlog.h"
#include "iwutils.h"
#include "iwkv_tests.h"
#include "iwkv_internal.h"
#include "iwth.h"
iwrc iwal_test_checkpoint(IWKV iwkv);
#define KBUFSZ 1024
#define VBUFSZ 1024
static char kbuf[KBUFSZ];
static char vbuf[VBUFSZ];
int init_suite(void) {
unlink("./iwkv_test8_1_bkp.db-wal");
unlink("./iwkv_test8_1.db-wal");
unlink("./iwkv_test8_2_bkp.db-wal");
unlink("./iwkv_test8_2_check.db-wal");
unlink("./iwkv_test8_2.db-wal");
unlink("./iwkv_test8_1_bkp.db");
unlink("./iwkv_test8_2_bkp.db");
unlink("./iwkv_test8_2_check.db");
unlink("./iwkv_test8_2.db");
return iwkv_init();
}
int clean_suite(void) {
return 0;
}
static void iwkv_test8_1() {
IWKV iwkv;
IWDB db;
IWKV_val key = {0};
IWKV_val val = {0};
IWKV_OPTS opts = {
.path = "iwkv_test8_1.db",
.oflags = IWKV_TRUNC,
.wal = {
.enabled = true
}
};
uint64_t ts;
iwrc rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 1, 0, &db);
CU_ASSERT_EQUAL_FATAL(rc, 0);
for (int i = 0; i < 1000; ++i) {
snprintf(kbuf, KBUFSZ, "%d", i);
snprintf(vbuf, VBUFSZ, "%03dval", i);
key.data = kbuf;
key.size = strlen(key.data);
val.data = vbuf;
val.size = strlen(val.data);
rc = iwkv_put(db, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
// Now reopen
opts.oflags &= ~IWKV_TRUNC;
rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_online_backup(iwkv, &ts, "iwkv_test8_1_bkp.db");
if (rc) iwlog_ecode_error3(rc);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
// Open backup
opts.path = "iwkv_test8_1_bkp.db";
rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 1, 0, &db);
CU_ASSERT_EQUAL_FATAL(rc, 0);
for (int i = 0; i < 1000; ++i) {
int cret = 0;
snprintf(kbuf, KBUFSZ, "%d", i);
snprintf(vbuf, VBUFSZ, "%03dval", i);
key.data = kbuf;
key.size = strlen(key.data);
int vlen = strlen(vbuf);
rc = iwkv_get(db, &key, &val);
CU_ASSERT_EQUAL_FATAL(rc, 0);
IW_CMP(cret, vbuf, vlen, val.data, val.size);
CU_ASSERT_EQUAL_FATAL(cret, 0);
iwkv_val_dispose(&val);
}
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
typedef struct T82 {
pthread_t t;
pthread_barrier_t barrier;
pthread_cond_t cond;
pthread_mutex_t mtx;
IWKV iwkv;
IWKV iwkvcheck;
} T82;
static void *t82(void *ctx_) {
T82 *ctx = ctx_;
IWKV_val key = {0};
IWKV_val val = {0};
iwrc rc = iwkv_open(&(IWKV_OPTS) {
.path = "iwkv_test8_2_check.db",
.oflags = IWKV_TRUNC,
}, &ctx->iwkvcheck);
CU_ASSERT_EQUAL_FATAL(rc, 0);
IWDB db, dbc;
rc = iwkv_db(ctx->iwkv, 1, 0, &db);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(ctx->iwkvcheck, 1, 0, &dbc);
CU_ASSERT_EQUAL_FATAL(rc, 0);
int i = 0;
for (; i < 500000; ++i) {
snprintf(kbuf, KBUFSZ, "%dkey", i);
key.data = kbuf;
key.size = strlen(key.data);
uint64_t ts;
rc = iwp_current_time_ms(&ts, false);
CU_ASSERT_EQUAL_FATAL(rc, 0);
val.data = &ts;
val.size = sizeof(ts);
rc = iwkv_put(db, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_put(dbc, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
pthread_barrier_wait(&ctx->barrier);
int c = i + 10000;
for (; i < c; ++i) {
if (i == c - 9800) { // Force checkpoint during online-backup
rc = iwal_test_checkpoint(ctx->iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
snprintf(kbuf, KBUFSZ, "%dkey", i);
key.data = kbuf;
key.size = strlen(key.data);
uint64_t ts;
rc = iwp_current_time_ms(&ts, false);
CU_ASSERT_EQUAL_FATAL(rc, 0);
val.data = &ts;
val.size = sizeof(ts);
rc = iwkv_put(db, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_put(dbc, &key, &val, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
}
rc = iwkv_close(&ctx->iwkvcheck);
CU_ASSERT_EQUAL_FATAL(rc, 0);
return 0;
}
static void iwkv_test8_2() {
IWKV_OPTS opts = {
.path = "iwkv_test8_2.db",
.oflags = IWKV_TRUNC,
.wal = {
.enabled = true
}
};
T82 ctx = {0};
iwrc rc = iwkv_open(&opts, &ctx.iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
int rci = pthread_barrier_init(&ctx.barrier, 0, 2);
CU_ASSERT_EQUAL_FATAL(rci, 0);
rci = pthread_create(&ctx.t, 0, t82, &ctx);
CU_ASSERT_EQUAL_FATAL(rci, 0);
pthread_barrier_wait(&ctx.barrier);
uint64_t bkts = 0, ts = 0;
rc = iwkv_online_backup(ctx.iwkv, &bkts, "iwkv_test8_2_bkp.db");
CU_ASSERT_EQUAL_FATAL(rc, 0);
pthread_join(ctx.t, 0);
rc = iwkv_close(&ctx.iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
size_t sp;
int cnt1 = 0, cnt2 = 0;
IWKV iwkv;
IWKV_cursor cur;
IWDB db;
// Now restore our backup
opts.path = "iwkv_test8_2_bkp.db";
opts.oflags &= ~IWKV_TRUNC;
rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 1, 0, &db);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_cursor_open(db, &cur, IWKV_CURSOR_BEFORE_FIRST, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
do {
rc = iwkv_cursor_to(cur, IWKV_CURSOR_NEXT);
if (!rc) {
iwkv_cursor_copy_val(cur, &ts, sizeof(ts), &sp);
CU_ASSERT_EQUAL_FATAL(sp, sizeof(ts));
if (ts < bkts) {
cnt1++;
}
}
} while (!rc);
CU_ASSERT_EQUAL_FATAL(rc, IWKV_ERROR_NOTFOUND);
iwkv_cursor_close(&cur);
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
// Check DB
opts.path = "iwkv_test8_2_check.db";
rc = iwkv_open(&opts, &iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_db(iwkv, 1, 0, &db);
CU_ASSERT_EQUAL_FATAL(rc, 0);
rc = iwkv_cursor_open(db, &cur, IWKV_CURSOR_BEFORE_FIRST, 0);
CU_ASSERT_EQUAL_FATAL(rc, 0);
do {
rc = iwkv_cursor_to(cur, IWKV_CURSOR_NEXT);
if (!rc) {
iwkv_cursor_copy_val(cur, &ts, sizeof(ts), &sp);
CU_ASSERT_EQUAL_FATAL(sp, sizeof(ts));
if (ts < bkts) {
cnt2++;
}
}
} while (!rc);
CU_ASSERT_EQUAL_FATAL(rc, IWKV_ERROR_NOTFOUND);
iwkv_cursor_close(&cur);
rc = iwkv_close(&iwkv);
CU_ASSERT_EQUAL_FATAL(rc, 0);
fprintf(stderr, "\n%d", cnt1);
fprintf(stderr, "\n%d\n", cnt2);
CU_ASSERT_TRUE(cnt1 > 500000);
CU_ASSERT_EQUAL(cnt1, cnt2);
pthread_barrier_destroy(&ctx.barrier);
}
int main() {
CU_pSuite pSuite = NULL;
/* Initialize the CUnit test registry */
if (CUE_SUCCESS != CU_initialize_registry()) return CU_get_error();
/* Add a suite to the registry */
pSuite = CU_add_suite("iwkv_test8", init_suite, clean_suite);
if (NULL == pSuite) {
CU_cleanup_registry();
return CU_get_error();
}
/* Add the tests to the suite */
if (
(NULL == CU_add_test(pSuite, "iwkv_test8_1", iwkv_test8_1)) ||
(NULL == CU_add_test(pSuite, "iwkv_test8_2", iwkv_test8_2))
) {
CU_cleanup_registry();
return CU_get_error();
}
/* Run all tests using the CUnit Basic interface */
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
int ret = CU_get_error() || CU_get_number_of_failures();
CU_cleanup_registry();
return ret;
}
+84
View File
@@ -0,0 +1,84 @@
#include "iwkv.h"
#include "iwlog.h"
#include "iwutils.h"
#include "iwcfg.h"
#include "iwkv_tests.h"
int init_suite() {
iwrc rc = iwkv_init();
return rc;
}
int clean_suite() {
return 0;
}
static void iwkv_test9_1() {
IWKV_OPTS opts = {
.path = "iwkv_test9_1.db",
.oflags = IWKV_TRUNC
};
IWKV kv = NULL;
iwrc rc = iwkv_open(&opts, &kv);
assert(rc == 0);
IWDB db = NULL;
rc = iwkv_db(kv, 1, 0, &db);
assert(rc == 0);
{
unsigned char ip1[4] = { 1, 0, 142, 235 };
IWKV_val ikey, ival;
ikey.data = ip1;
ikey.size = 4;
ival.data = (void *)"";
ival.size = 0;
iwkv_opflags opflags = IWKV_NO_OVERWRITE;
iwrc rc = iwkv_put(db, &ikey, &ival, opflags);
CU_ASSERT_EQUAL(rc, 0);
}
{
unsigned char ip2[4] = { 1, 0, 145, 2 };
IWKV_val ikey, ival;
ikey.data = ip2;
ikey.size = 4;
ival.data = (void *)"";
ival.size = 0;
iwkv_opflags opflags = IWKV_NO_OVERWRITE;
iwrc rc = iwkv_put(db, &ikey, &ival, opflags);
CU_ASSERT_EQUAL(rc, 0);
}
iwkv_close(&kv);
}
int main() {
CU_pSuite pSuite = NULL;
/* Initialize the CUnit test registry */
if (CUE_SUCCESS != CU_initialize_registry()) return CU_get_error();
/* Add a suite to the registry */
pSuite = CU_add_suite("iwkv_test9", init_suite, clean_suite);
if (NULL == pSuite) {
CU_cleanup_registry();
return CU_get_error();
}
/* Add the tests to the suite */
if (
(NULL == CU_add_test(pSuite, "iwkv_test9_1", iwkv_test9_1))
) {
CU_cleanup_registry();
return CU_get_error();
}
/* Run all tests using the CUnit Basic interface */
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
int ret = CU_get_error() || CU_get_number_of_failures();
CU_cleanup_registry();
return ret;
}
+30
View File
@@ -0,0 +1,30 @@
#include <stdio.h>
#include <CUnit/Basic.h>
void iwkvd_trigger_xor(uint64_t val);
static int cmp_files(FILE *f1, FILE *f2) {
CU_ASSERT_TRUE_FATAL(f1 && f2);
fseek(f1, 0, SEEK_SET);
fseek(f2, 0, SEEK_SET);
char c1 = getc(f1);
char c2 = getc(f2);
int pos = 0, line = 1;
while (c1 != EOF && c2 != EOF) {
pos++;
if (c1 == '\n' && c2 == '\n') {
line++;
pos = 0;
} else if (c1 != c2) {
fprintf(stderr, "\nDiff at: %d:%d\n", line, pos);
return (c1 - c2);
}
c1 = getc(f1);
c2 = getc(f2);
}
if (c1 - c2) {
fprintf(stderr, "\nDiff at: %d:%d\n", line, pos);
}
return (c1 - c2);
}
+4
View File
@@ -0,0 +1,4 @@
check_symbol_exists(basename_r libgen.h HAVE_BASENAME_R)
if (HAVE_BASENAME_R)
set_source_files_properties(iwlog.c PROPERTIES COMPILE_FLAGS -DIW_HAVE_BASENAME_R)
endif()

Some files were not shown because too many files have changed in this diff Show More