Description:[feature] add iowow
Signed-off-by: stesen <stesen.ma@huawei.com> Change-Id: I9303d30deed6066005e21bb955e4f6b0d3035caa
@@ -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"
|
||||
}
|
||||
@@ -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()
|
||||
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
# TODO
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -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/)
|
||||
@@ -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)}
|
||||

|
||||
[](https://t.me/ejdb2)
|
||||
[](https://github.com/Softmotions/iowow/blob/master/LICENSE)
|
||||

|
||||
|
||||
#### 软件架构
|
||||
软件架构说明
|
||||
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
|
||||
|
||||
[](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/)
|
||||
|
||||
@@ -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
|
||||
```
|
||||
@@ -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}")
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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()
|
||||
@@ -0,0 +1,5 @@
|
||||
[ppa]
|
||||
fqdn = ppa.launchpad.net
|
||||
method = sftp
|
||||
login = @PROJECT_PPA_USER@
|
||||
incoming = ~%(ppa)s/ubuntu/@DPUT_DIST@
|
||||
@@ -0,0 +1,2 @@
|
||||
install(FILES iowow.3 DESTINATION ${CMAKE_INSTALL_MANDIR}/man3
|
||||
COMPONENT doc)
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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}")
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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()
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,2 @@
|
||||
[flake8]
|
||||
ignore = F401,E501
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
```
|
||||
pip3 install -U bokeh parse selenium --user
|
||||
yarn global add phantomjs-prebuilt
|
||||
```
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 20 KiB |
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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()
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
*w.ref eol=crlf
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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()
|
||||