Compare commits
No commits in common. "master" and "0.5.1" have entirely different histories.
@ -1,79 +0,0 @@
|
|||||||
name: Release to AUR
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
package-name:
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
version:
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
description:
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
depends:
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
package-name:
|
|
||||||
description: "The name under which the package is going to be packaged to AUR"
|
|
||||||
type: string
|
|
||||||
default: "lmdbal"
|
|
||||||
version:
|
|
||||||
description: "The version of the published package"
|
|
||||||
type: string
|
|
||||||
default: "1.0.0"
|
|
||||||
description:
|
|
||||||
description: "The description of the package"
|
|
||||||
type: string
|
|
||||||
default: "LMDB Abstraction Layer"
|
|
||||||
depends:
|
|
||||||
description: "Additional dependencies"
|
|
||||||
type: string
|
|
||||||
default: ""
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
aur:
|
|
||||||
name: Release ${{ inputs.package-name }} to AUR
|
|
||||||
runs-on: archlinux
|
|
||||||
steps:
|
|
||||||
- name: Download the release tarball
|
|
||||||
run: curl -sL ${{ gitea.server_url }}/${{ gitea.repository }}/archive/${{ gitea.event.release.tag_name }}.tar.gz --output tarball.tar.gz
|
|
||||||
|
|
||||||
- name: Calculate SHA256 for the tarball
|
|
||||||
run: echo "tbSum=$(sha256sum tarball.tar.gz | cut -d ' ' -f 1)" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Unarchive tarball
|
|
||||||
run: tar -xvzf tarball.tar.gz
|
|
||||||
|
|
||||||
- name: Clone the AUR repository
|
|
||||||
run: |
|
|
||||||
echo "${{ secrets.DEPLOY_TO_AUR_PRIVATE_KEY }}" > key
|
|
||||||
chmod 600 key
|
|
||||||
GIT_SSH_COMMAND="ssh -i key -o 'IdentitiesOnly yes' -o 'StrictHostKeyChecking no'" git clone ssh://aur@aur.archlinux.org/${{ inputs.package-name }}.git aur
|
|
||||||
chmod 777 -R aur
|
|
||||||
cd aur
|
|
||||||
git config user.name ${{ secrets.DEPLOY_TO_AUR_USER_NAME }}
|
|
||||||
git config user.email ${{ secrets.DEPLOY_TO_AUR_EMAIL }}
|
|
||||||
|
|
||||||
|
|
||||||
- name: Copy PKGBUILD to the directory
|
|
||||||
run: cp lmdbal/packaging/Archlinux/PKGBUILD aur/
|
|
||||||
|
|
||||||
- name: Patch PKGBUILD file, and generate .SRCINFO
|
|
||||||
working-directory: aur
|
|
||||||
run: |
|
|
||||||
sed -i "/sha256sums=/c\sha256sums=('${{ env.tbSum }}')" PKGBUILD
|
|
||||||
sed -i "/pkgname=lmdbal/c\pkgname=(${{ inputs.package-name }})" PKGBUILD
|
|
||||||
sed -i "/pkgver=1.0.0/c\pkgver=(${{ inputs.version }})" PKGBUILD
|
|
||||||
sed -i "/pkgdesc=\"LMDB Abstraction Layer\"/c\pkgdesc=(\"${{ inputs.description }}\")" PKGBUILD
|
|
||||||
sed -i "/depends=( 'lmdb' )/c\depends=( 'lmdb' ${{ inputs.depends }} ))" PKGBUILD
|
|
||||||
sudo -u build makepkg --printsrcinfo > .SRCINFO
|
|
||||||
|
|
||||||
- name: Commit package to aur
|
|
||||||
working-directory: aur
|
|
||||||
run: |
|
|
||||||
git add PKGBUILD .SRCINFO
|
|
||||||
git commit -m "${{ gitea.event.release.body }}"
|
|
||||||
GIT_SSH_COMMAND="ssh -i ../key -o 'IdentitiesOnly yes' -o 'StrictHostKeyChecking no'" git push
|
|
@ -17,7 +17,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Configure
|
- name: Configure
|
||||||
working-directory: ./build
|
working-directory: ./build
|
||||||
run: cmake .. -D BUILD_TESTS=True -D BUILD_DOC_HTML=True -D BUILD_DOC_XML=True -D BUILD_DOC_MAN=True -D BUILD_DOXYGEN_AWESOME=True -D QT_VERSION_MAJOR=5
|
run: cmake .. -D BUILD_TESTS=True -D BUILD_DOC=True -D BUILD_DOXYGEN_AWESOME=True -D QT_VERSION_MAJOR=5
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
working-directory: ./build
|
working-directory: ./build
|
||||||
@ -35,5 +35,5 @@ jobs:
|
|||||||
username: ${{ secrets.DEPLOY_USER_NAME }}
|
username: ${{ secrets.DEPLOY_USER_NAME }}
|
||||||
key: ${{ secrets.DEPLOY_PRIVATE_KEY }}
|
key: ${{ secrets.DEPLOY_PRIVATE_KEY }}
|
||||||
source: "build/doc/html/*,build/doc/xml/*,build/doc/man/*"
|
source: "build/doc/html/*,build/doc/xml/*,build/doc/man/*"
|
||||||
target: "/srv/lmdbal/doc"
|
target: ${{ secrets.LMDBAL_DOCS_DEPLOY_PATH }}
|
||||||
strip_components: 2
|
strip_components: 2
|
||||||
|
17
CHANGELOG.md
17
CHANGELOG.md
@ -1,24 +1,9 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
# LMDBAL 0.5.3 (November 14, 2023)
|
|
||||||
### Improvements
|
|
||||||
- Now you don't need to link agains lmdb, just linking against LMDBAL is enough
|
|
||||||
|
|
||||||
### Bug fixes
|
|
||||||
- transaction error in LMDBAL::Cache::readAll
|
|
||||||
|
|
||||||
## LMDBAL 0.5.2 (November 01, 2023)
|
|
||||||
### Improvements
|
|
||||||
- RAII cursors
|
|
||||||
- operation set for cursors
|
|
||||||
|
|
||||||
### Bug fixes
|
|
||||||
- error beginning transaction is now correctly handled and doesn't segfault
|
|
||||||
|
|
||||||
## LMDBAL 0.5.1 (October 21, 2023)
|
## LMDBAL 0.5.1 (October 21, 2023)
|
||||||
### Improvements
|
### Improvements
|
||||||
- RAII transactions
|
- RAII transactions
|
||||||
- reduced overhead for private transaction functions
|
- reduced overhead for private transaction finctions
|
||||||
|
|
||||||
### Bug fixes
|
### Bug fixes
|
||||||
- bug fix with cache fallthough
|
- bug fix with cache fallthough
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
project(LMDBAL
|
project(LMDBAL
|
||||||
VERSION 0.5.4
|
VERSION 0.5.1
|
||||||
DESCRIPTION "LMDB (Lightning Memory-Mapped Database Manager) Abstraction Layer"
|
DESCRIPTION "LMDB (Lightning Memory-Mapped Database Manager) Abstraction Layer"
|
||||||
LANGUAGES CXX
|
LANGUAGES CXX
|
||||||
)
|
)
|
||||||
@ -12,9 +12,7 @@ cmake_policy(SET CMP0079 NEW)
|
|||||||
|
|
||||||
option(BUILD_STATIC "Builds library as static library" OFF)
|
option(BUILD_STATIC "Builds library as static library" OFF)
|
||||||
option(BUILD_TESTS "Builds tests" OFF)
|
option(BUILD_TESTS "Builds tests" OFF)
|
||||||
option(BUILD_DOC_MAN "Builds man page documentation" OFF)
|
option(BUILD_DOC "Builds documentation" OFF)
|
||||||
option(BUILD_DOC_HTML "Builds html documentation" OFF)
|
|
||||||
option(BUILD_DOC_XML "Builds xml documentation" OFF)
|
|
||||||
option(BUILD_DOXYGEN_AWESOME "Builds documentation alternative style" OFF)
|
option(BUILD_DOXYGEN_AWESOME "Builds documentation alternative style" OFF)
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
@ -23,7 +21,7 @@ include(CMakePackageConfigHelpers)
|
|||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
if (NOT DEFINED QT_VERSION_MAJOR)
|
if (NOT DEFINED QT_VERSION_MAJOR)
|
||||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
|
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
|
||||||
@ -56,21 +54,14 @@ target_compile_options(${PROJECT_NAME} PRIVATE ${COMPILE_OPTIONS})
|
|||||||
|
|
||||||
set_property(TARGET ${PROJECT_NAME} PROPERTY VERSION ${version})
|
set_property(TARGET ${PROJECT_NAME} PROPERTY VERSION ${version})
|
||||||
set_property(TARGET ${PROJECT_NAME} PROPERTY SOVERSION 1)
|
set_property(TARGET ${PROJECT_NAME} PROPERTY SOVERSION 1)
|
||||||
set_property(TARGET ${PROJECT_NAME} PROPERTY EXPORT_NAME ${PROJECT_NAME})
|
set_property(TARGET ${PROJECT_NAME} PROPERTY
|
||||||
set_property(TARGET ${PROJECT_NAME} PROPERTY INTERFACE_${PROJECT_NAME}_MAJOR_VERSION 1)
|
INTERFACE_${PROJECT_NAME}_MAJOR_VERSION 1)
|
||||||
set_property(TARGET ${PROJECT_NAME} APPEND PROPERTY
|
set_property(TARGET ${PROJECT_NAME} APPEND PROPERTY
|
||||||
COMPATIBLE_INTERFACE_STRING ${PROJECT_NAME}_MAJOR_VERSION
|
COMPATIBLE_INTERFACE_STRING ${PROJECT_NAME}_MAJOR_VERSION
|
||||||
)
|
)
|
||||||
|
|
||||||
if (UNIX)
|
|
||||||
set_property(TARGET ${PROJECT_NAME} PROPERTY INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/${PROJECT_LOW}")
|
|
||||||
set_property(TARGET ${PROJECT_NAME} PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
|
||||||
set_property(TARGET ${PROJECT_NAME} PROPERTY SKIP_BUILD_RPATH FALSE)
|
|
||||||
set_property(TARGET ${PROJECT_NAME} PROPERTY BUILD_WITH_INSTALL_RPATH FALSE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
if (BUILD_DOC_MAN OR BUILD_DOC_HTML OR BUILD_DOC_XML)
|
if (BUILD_DOC)
|
||||||
find_package(Doxygen)
|
find_package(Doxygen)
|
||||||
if (DOXYGEN_FOUND)
|
if (DOXYGEN_FOUND)
|
||||||
add_subdirectory(doc)
|
add_subdirectory(doc)
|
||||||
@ -83,18 +74,11 @@ if (BUILD_TESTS)
|
|||||||
add_subdirectory(test)
|
add_subdirectory(test)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
target_include_directories(
|
target_include_directories(${PROJECT_NAME} PUBLIC "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_LOW}>")
|
||||||
${PROJECT_NAME}
|
|
||||||
PUBLIC
|
|
||||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_LOW}>
|
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
|
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/serializer>
|
|
||||||
)
|
|
||||||
target_include_directories(${PROJECT_NAME} PRIVATE ${Qt${QT_VERSION_MAJOR}_INCLUDE_DIRS})
|
target_include_directories(${PROJECT_NAME} PRIVATE ${Qt${QT_VERSION_MAJOR}_INCLUDE_DIRS})
|
||||||
target_include_directories(${PROJECT_NAME} PRIVATE ${Qt${QT_VERSION_MAJOR}Core_INCLUDE_DIRS})
|
target_include_directories(${PROJECT_NAME} PRIVATE ${Qt${QT_VERSION_MAJOR}Core_INCLUDE_DIRS})
|
||||||
|
|
||||||
target_link_libraries(
|
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||||
${PROJECT_NAME}
|
|
||||||
Qt${QT_VERSION_MAJOR}::Core
|
Qt${QT_VERSION_MAJOR}::Core
|
||||||
lmdb
|
lmdb
|
||||||
)
|
)
|
||||||
@ -113,7 +97,8 @@ write_basic_package_version_file(
|
|||||||
|
|
||||||
install(TARGETS ${PROJECT_NAME}
|
install(TARGETS ${PROJECT_NAME}
|
||||||
EXPORT ${PROJECT_LOW}Targets
|
EXPORT ${PROJECT_LOW}Targets
|
||||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_LOW}
|
||||||
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_LOW}
|
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_LOW}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
45
LICENSE.md
45
LICENSE.md
@ -1,4 +1,4 @@
|
|||||||
# GNU GENERAL PUBLIC LICENSE
|
### GNU GENERAL PUBLIC LICENSE
|
||||||
|
|
||||||
Version 3, 29 June 2007
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
@ -8,7 +8,7 @@ Copyright (C) 2007 Free Software Foundation, Inc.
|
|||||||
Everyone is permitted to copy and distribute verbatim copies of this
|
Everyone is permitted to copy and distribute verbatim copies of this
|
||||||
license document, but changing it is not allowed.
|
license document, but changing it is not allowed.
|
||||||
|
|
||||||
## Preamble
|
### Preamble
|
||||||
|
|
||||||
The GNU General Public License is a free, copyleft license for
|
The GNU General Public License is a free, copyleft license for
|
||||||
software and other kinds of works.
|
software and other kinds of works.
|
||||||
@ -73,9 +73,9 @@ assures that patents cannot be used to render the program non-free.
|
|||||||
The precise terms and conditions for copying, distribution and
|
The precise terms and conditions for copying, distribution and
|
||||||
modification follow.
|
modification follow.
|
||||||
|
|
||||||
## TERMS AND CONDITIONS
|
### TERMS AND CONDITIONS
|
||||||
|
|
||||||
### 0. Definitions.
|
#### 0. Definitions.
|
||||||
|
|
||||||
"This License" refers to version 3 of the GNU General Public License.
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ work under this License, and how to view a copy of this License. If
|
|||||||
the interface presents a list of user commands or options, such as a
|
the interface presents a list of user commands or options, such as a
|
||||||
menu, a prominent item in the list meets this criterion.
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
### 1. Source Code.
|
#### 1. Source Code.
|
||||||
|
|
||||||
The "source code" for a work means the preferred form of the work for
|
The "source code" for a work means the preferred form of the work for
|
||||||
making modifications to it. "Object code" means any non-source form of
|
making modifications to it. "Object code" means any non-source form of
|
||||||
@ -156,7 +156,7 @@ regenerate automatically from other parts of the Corresponding Source.
|
|||||||
The Corresponding Source for a work in source code form is that same
|
The Corresponding Source for a work in source code form is that same
|
||||||
work.
|
work.
|
||||||
|
|
||||||
### 2. Basic Permissions.
|
#### 2. Basic Permissions.
|
||||||
|
|
||||||
All rights granted under this License are granted for the term of
|
All rights granted under this License are granted for the term of
|
||||||
copyright on the Program, and are irrevocable provided the stated
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
@ -181,7 +181,7 @@ Conveying under any other circumstances is permitted solely under the
|
|||||||
conditions stated below. Sublicensing is not allowed; section 10 makes
|
conditions stated below. Sublicensing is not allowed; section 10 makes
|
||||||
it unnecessary.
|
it unnecessary.
|
||||||
|
|
||||||
### 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
#### 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
No covered work shall be deemed part of an effective technological
|
No covered work shall be deemed part of an effective technological
|
||||||
measure under any applicable law fulfilling obligations under article
|
measure under any applicable law fulfilling obligations under article
|
||||||
@ -197,7 +197,7 @@ operation or modification of the work as a means of enforcing, against
|
|||||||
the work's users, your or third parties' legal rights to forbid
|
the work's users, your or third parties' legal rights to forbid
|
||||||
circumvention of technological measures.
|
circumvention of technological measures.
|
||||||
|
|
||||||
### 4. Conveying Verbatim Copies.
|
#### 4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
You may convey verbatim copies of the Program's source code as you
|
You may convey verbatim copies of the Program's source code as you
|
||||||
receive it, in any medium, provided that you conspicuously and
|
receive it, in any medium, provided that you conspicuously and
|
||||||
@ -210,7 +210,7 @@ recipients a copy of this License along with the Program.
|
|||||||
You may charge any price or no price for each copy that you convey,
|
You may charge any price or no price for each copy that you convey,
|
||||||
and you may offer support or warranty protection for a fee.
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
### 5. Conveying Modified Source Versions.
|
#### 5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
You may convey a work based on the Program, or the modifications to
|
You may convey a work based on the Program, or the modifications to
|
||||||
produce it from the Program, in the form of source code under the
|
produce it from the Program, in the form of source code under the
|
||||||
@ -245,7 +245,7 @@ beyond what the individual works permit. Inclusion of a covered work
|
|||||||
in an aggregate does not cause this License to apply to the other
|
in an aggregate does not cause this License to apply to the other
|
||||||
parts of the aggregate.
|
parts of the aggregate.
|
||||||
|
|
||||||
### 6. Conveying Non-Source Forms.
|
#### 6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
You may convey a covered work in object code form under the terms of
|
You may convey a covered work in object code form under the terms of
|
||||||
sections 4 and 5, provided that you also convey the machine-readable
|
sections 4 and 5, provided that you also convey the machine-readable
|
||||||
@ -341,7 +341,7 @@ documented (and with an implementation available to the public in
|
|||||||
source code form), and must require no special password or key for
|
source code form), and must require no special password or key for
|
||||||
unpacking, reading or copying.
|
unpacking, reading or copying.
|
||||||
|
|
||||||
### 7. Additional Terms.
|
#### 7. Additional Terms.
|
||||||
|
|
||||||
"Additional permissions" are terms that supplement the terms of this
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
License by making exceptions from one or more of its conditions.
|
License by making exceptions from one or more of its conditions.
|
||||||
@ -400,7 +400,7 @@ Additional terms, permissive or non-permissive, may be stated in the
|
|||||||
form of a separately written license, or stated as exceptions; the
|
form of a separately written license, or stated as exceptions; the
|
||||||
above requirements apply either way.
|
above requirements apply either way.
|
||||||
|
|
||||||
### 8. Termination.
|
#### 8. Termination.
|
||||||
|
|
||||||
You may not propagate or modify a covered work except as expressly
|
You may not propagate or modify a covered work except as expressly
|
||||||
provided under this License. Any attempt otherwise to propagate or
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
@ -428,7 +428,7 @@ this License. If your rights have been terminated and not permanently
|
|||||||
reinstated, you do not qualify to receive new licenses for the same
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
material under section 10.
|
material under section 10.
|
||||||
|
|
||||||
### 9. Acceptance Not Required for Having Copies.
|
#### 9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
You are not required to accept this License in order to receive or run
|
You are not required to accept this License in order to receive or run
|
||||||
a copy of the Program. Ancillary propagation of a covered work
|
a copy of the Program. Ancillary propagation of a covered work
|
||||||
@ -439,7 +439,7 @@ modify any covered work. These actions infringe copyright if you do
|
|||||||
not accept this License. Therefore, by modifying or propagating a
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
covered work, you indicate your acceptance of this License to do so.
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
### 10. Automatic Licensing of Downstream Recipients.
|
#### 10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
Each time you convey a covered work, the recipient automatically
|
Each time you convey a covered work, the recipient automatically
|
||||||
receives a license from the original licensors, to run, modify and
|
receives a license from the original licensors, to run, modify and
|
||||||
@ -464,7 +464,7 @@ rights granted under this License, and you may not initiate litigation
|
|||||||
any patent claim is infringed by making, using, selling, offering for
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
sale, or importing the Program or any portion of it.
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
### 11. Patents.
|
#### 11. Patents.
|
||||||
|
|
||||||
A "contributor" is a copyright holder who authorizes use under this
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
License of the Program or a work on which the Program is based. The
|
License of the Program or a work on which the Program is based. The
|
||||||
@ -533,7 +533,7 @@ Nothing in this License shall be construed as excluding or limiting
|
|||||||
any implied license or other defenses to infringement that may
|
any implied license or other defenses to infringement that may
|
||||||
otherwise be available to you under applicable patent law.
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
### 12. No Surrender of Others' Freedom.
|
#### 12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
If conditions are imposed on you (whether by court order, agreement or
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
@ -546,7 +546,7 @@ from those to whom you convey the Program, the only way you could
|
|||||||
satisfy both those terms and this License would be to refrain entirely
|
satisfy both those terms and this License would be to refrain entirely
|
||||||
from conveying the Program.
|
from conveying the Program.
|
||||||
|
|
||||||
### 13. Use with the GNU Affero General Public License.
|
#### 13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, you have
|
Notwithstanding any other provision of this License, you have
|
||||||
permission to link or combine any covered work with a work licensed
|
permission to link or combine any covered work with a work licensed
|
||||||
@ -557,7 +557,7 @@ but the special requirements of the GNU Affero General Public License,
|
|||||||
section 13, concerning interaction through a network will apply to the
|
section 13, concerning interaction through a network will apply to the
|
||||||
combination as such.
|
combination as such.
|
||||||
|
|
||||||
### 14. Revised Versions of this License.
|
#### 14. Revised Versions of this License.
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions
|
The Free Software Foundation may publish revised and/or new versions
|
||||||
of the GNU General Public License from time to time. Such new versions
|
of the GNU General Public License from time to time. Such new versions
|
||||||
@ -583,7 +583,7 @@ permissions. However, no additional obligations are imposed on any
|
|||||||
author or copyright holder as a result of your choosing to follow a
|
author or copyright holder as a result of your choosing to follow a
|
||||||
later version.
|
later version.
|
||||||
|
|
||||||
### 15. Disclaimer of Warranty.
|
#### 15. Disclaimer of Warranty.
|
||||||
|
|
||||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
@ -595,7 +595,7 @@ PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
|
|||||||
DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
|
DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
|
||||||
CORRECTION.
|
CORRECTION.
|
||||||
|
|
||||||
### 16. Limitation of Liability.
|
#### 16. Limitation of Liability.
|
||||||
|
|
||||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR
|
||||||
@ -607,7 +607,7 @@ LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM
|
|||||||
TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER
|
TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER
|
||||||
PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
### 17. Interpretation of Sections 15 and 16.
|
#### 17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
If the disclaimer of warranty and limitation of liability provided
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
above cannot be given local legal effect according to their terms,
|
above cannot be given local legal effect according to their terms,
|
||||||
@ -618,7 +618,7 @@ copy of the Program in return for a fee.
|
|||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
## How to Apply These Terms to Your New Programs
|
### How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
If you develop a new program, and you want it to be of the greatest
|
||||||
possible use to the public, the best way to achieve this is to make it
|
possible use to the public, the best way to achieve this is to make it
|
||||||
@ -673,4 +673,3 @@ library, you may consider it more useful to permit linking proprietary
|
|||||||
applications with the library. If this is what you want to do, use the
|
applications with the library. If this is what you want to do, use the
|
||||||
GNU Lesser General Public License instead of this License. But first,
|
GNU Lesser General Public License instead of this License. But first,
|
||||||
please read <https://www.gnu.org/licenses/why-not-lgpl.html>.
|
please read <https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||||
|
|
||||||
|
@ -97,4 +97,4 @@ if you're in the same directory with it
|
|||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This project is available under the GPL-3.0 License or any later version. The file [cmake/FindLMDB.cmake](cmake/FindLMDB.cmake) is available under the GPL-3.0 License only, - see the [LICENSE.md](LICENSE.md) file for details
|
This project is licensed under the GPLv3 License - see the [LICENSE.md](LICENSE.md) file for details
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
if (BUILD_DOC_HTML)
|
|
||||||
set(DOXYGEN_GENERATE_HTML YES)
|
set(DOXYGEN_GENERATE_HTML YES)
|
||||||
endif()
|
|
||||||
if (BUILD_DOC_MAN)
|
|
||||||
set(DOXYGEN_GENERATE_MAN YES)
|
set(DOXYGEN_GENERATE_MAN YES)
|
||||||
endif()
|
|
||||||
if (BUILD_DOC_XML)
|
|
||||||
set(DOXYGEN_GENERATE_XML YES)
|
set(DOXYGEN_GENERATE_XML YES)
|
||||||
endif()
|
|
||||||
|
|
||||||
if (BUILD_DOXYGEN_AWESOME)
|
if (BUILD_DOXYGEN_AWESOME)
|
||||||
include(ExternalProject)
|
include(ExternalProject)
|
||||||
@ -42,24 +36,12 @@ doxygen_add_docs(
|
|||||||
ALL
|
ALL
|
||||||
COMMENT "Generate man and html pages"
|
COMMENT "Generate man and html pages"
|
||||||
)
|
)
|
||||||
if (BUILD_DOC_MAN)
|
|
||||||
install(DIRECTORY
|
install(DIRECTORY
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/man
|
${CMAKE_CURRENT_BINARY_DIR}/man
|
||||||
TYPE DOC
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
if (BUILD_DOC_HTML)
|
|
||||||
install(DIRECTORY
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/html
|
${CMAKE_CURRENT_BINARY_DIR}/html
|
||||||
TYPE DOC
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
if (BUILD_DOC_XML)
|
|
||||||
install(DIRECTORY
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/xml
|
${CMAKE_CURRENT_BINARY_DIR}/xml
|
||||||
TYPE DOC
|
TYPE DOC
|
||||||
)
|
)
|
||||||
endif()
|
|
||||||
|
|
||||||
if (BUILD_DOXYGEN_AWESOME)
|
if (BUILD_DOXYGEN_AWESOME)
|
||||||
add_dependencies(documentation doxygen-awesome-css)
|
add_dependencies(documentation doxygen-awesome-css)
|
||||||
|
@ -4,15 +4,6 @@
|
|||||||
* It repesents a collection of key-value storages that are going to be stored in a sigle data base directory.
|
* It repesents a collection of key-value storages that are going to be stored in a sigle data base directory.
|
||||||
* To create a LMDBAL::Base you need to pick up a name of a directory that is going to be created on your machine.
|
* To create a LMDBAL::Base you need to pick up a name of a directory that is going to be created on your machine.
|
||||||
*
|
*
|
||||||
* @code{.cpp}
|
|
||||||
*
|
|
||||||
* #include "base.h"
|
|
||||||
*
|
|
||||||
* //...
|
|
||||||
*
|
|
||||||
* LMDBAL::Base base("myDataBase");
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* LMDBAL::Base creates or opens existing directory with the given name in the location acquired with
|
* LMDBAL::Base creates or opens existing directory with the given name in the location acquired with
|
||||||
* <a class="el" href="https://doc.qt.io/qt-6/qstandardpaths.html">QStandardPaths</a>::<a class="el" href="https://doc.qt.io/qt-6/qstandardpaths.html#writableLocation">writableLocation</a>(<a class="el" href="https://doc.qt.io/qt-6/qstandardpaths.html">QStandardPaths</a>::<a class="el" href="https://doc.qt.io/qt-6/qstandardpaths.html#StandardLocation-enum">CacheLocation</a>)
|
* <a class="el" href="https://doc.qt.io/qt-6/qstandardpaths.html">QStandardPaths</a>::<a class="el" href="https://doc.qt.io/qt-6/qstandardpaths.html#writableLocation">writableLocation</a>(<a class="el" href="https://doc.qt.io/qt-6/qstandardpaths.html">QStandardPaths</a>::<a class="el" href="https://doc.qt.io/qt-6/qstandardpaths.html#StandardLocation-enum">CacheLocation</a>)
|
||||||
* so, the file system destination of your data depends on the
|
* so, the file system destination of your data depends on the
|
||||||
@ -24,55 +15,17 @@
|
|||||||
* <a class="el" href="https://en.cppreference.com/w/cpp/container/map">std::map</a>
|
* <a class="el" href="https://en.cppreference.com/w/cpp/container/map">std::map</a>
|
||||||
* to speed up the access.
|
* to speed up the access.
|
||||||
*
|
*
|
||||||
* @code{.cpp}
|
|
||||||
*
|
|
||||||
* #include "storage.h"
|
|
||||||
* #include "cache.h"
|
|
||||||
*
|
|
||||||
* //...
|
|
||||||
*
|
|
||||||
* LMDBAL::Storage<uint32_t, uint32_t> storage = base.addStorage<uint32_t, uint32_t>("storage");
|
|
||||||
* LMDBAL::Cache<int8_t, std::string> cache = base.addCache<int8_t, std::string>("cache");
|
|
||||||
*
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* You can obtain handlers by calling LMDBAL::Base::addStorage() or LMDBAL::Base::addCache().
|
* You can obtain handlers by calling LMDBAL::Base::addStorage() or LMDBAL::Base::addCache().
|
||||||
* Note that the handlers still belong to the LMDBAL::Base and it's his responsibility to destroy them.
|
* Note that the handlers still belong to the LMDBAL::Base and it's his responsibility to destroy them.
|
||||||
* You are not obliged to save those handlers,
|
* You are not obliged to save those handlers,
|
||||||
* you can obtain them at any time later using methods LMDBAL::Base::getStorage() or LMDBAL::Base::getCache()
|
* you can obtain them at any time later using methods LMDBAL::Base::getStorage() or LMDBAL::Base::getCache()
|
||||||
* calling them with the same template types and names.
|
* calling them with the same template types and names.
|
||||||
*
|
*
|
||||||
* @code{.cpp}
|
|
||||||
*
|
|
||||||
* //...
|
|
||||||
*
|
|
||||||
* base.open();
|
|
||||||
*
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* After you have added all the storages you wanted it's time to open the data base with LMDBAL::Base::open().
|
* After you have added all the storages you wanted it's time to open the data base with LMDBAL::Base::open().
|
||||||
* At this point you are not allowed to add any more storages, otherwise LMDBAL::Opened exception will be thrown.
|
* At this point you are not allowed to add any more storages, otherwise LMDBAL::Opened exception will be thrown.
|
||||||
* It's currently the limitation of this little library and I might solve it in the future.
|
* It's currently the limitation of this little library and I might solve it in the future.
|
||||||
* Database will throw no exception if you will try to close the closed LMDBAL::Base or open again already opened one.
|
* Database will throw no exception if you will try to close the closed LMDBAL::Base or open again already opened one.
|
||||||
* Also it will automatically close itself if you'll try to destoroy onpened LMDBAL::Base.
|
* Also it will automatically close itself if you'll try to destoroy onpened LMDBAL::Base.
|
||||||
*
|
*
|
||||||
* @code{.cpp}
|
|
||||||
*
|
|
||||||
* //...
|
|
||||||
*
|
|
||||||
* storage->addRecord(54, 75);
|
|
||||||
* cache->addRecord(9, "my value");
|
|
||||||
*
|
|
||||||
* uint32_t value1 = storage->getRecord(54); //75
|
|
||||||
* std::string value2 = cache->getRecord(9); //"myValue"
|
|
||||||
*
|
|
||||||
* uint32_t count1 = storage->count(); //1
|
|
||||||
* uint32_t count2 = cache->count(); //1
|
|
||||||
*
|
|
||||||
* storage->removeRecord(54);
|
|
||||||
* cache->removeRecord(9);
|
|
||||||
*
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* To discover how to store read and modify data take a look at LMDBAL::Storage and LMDBAL::Cache classes.
|
* To discover how to store read and modify data take a look at LMDBAL::Storage and LMDBAL::Cache classes.
|
||||||
*/
|
*/
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
# Maintainer: Yury Gubich <blue@macaw.me>
|
# Maintainer: Yury Gubich <blue@macaw.me>
|
||||||
pkgname=lmdbal
|
pkgname=lmdbal
|
||||||
pkgver=1.0.0
|
pkgver=0.5.1
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="LMDB Abstraction Layer"
|
pkgdesc="LMDB Abstraction Layer, qt5 version"
|
||||||
arch=('i686' 'x86_64')
|
arch=('i686' 'x86_64')
|
||||||
url="https://git.macaw.me/blue/lmdbal"
|
url="https://git.macaw.me/blue/lmdbal"
|
||||||
license=('GPL3')
|
license=('GPL3')
|
||||||
depends=( 'lmdb' )
|
depends=( 'lmdb' 'qt5-base')
|
||||||
makedepends=('cmake>=3.16' 'gcc')
|
makedepends=('cmake>=3.16' 'gcc')
|
||||||
optdepends=()
|
optdepends=()
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ set(HEADERS
|
|||||||
)
|
)
|
||||||
|
|
||||||
target_sources(${PROJECT_NAME} PRIVATE ${SOURCES})
|
target_sources(${PROJECT_NAME} PRIVATE ${SOURCES})
|
||||||
|
target_include_directories(${PROJECT_NAME} PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>")
|
||||||
|
|
||||||
add_subdirectory(serializer)
|
add_subdirectory(serializer)
|
||||||
|
|
||||||
|
@ -402,9 +402,10 @@ void LMDBAL::Base::commitTransaction(LMDBAL::TransactionID id, const std::string
|
|||||||
LMDBAL::TransactionID LMDBAL::Base::beginPrivateReadOnlyTransaction(const std::string& storageName) const {
|
LMDBAL::TransactionID LMDBAL::Base::beginPrivateReadOnlyTransaction(const std::string& storageName) const {
|
||||||
MDB_txn* txn;
|
MDB_txn* txn;
|
||||||
int rc = mdb_txn_begin(environment, NULL, MDB_RDONLY, &txn);
|
int rc = mdb_txn_begin(environment, NULL, MDB_RDONLY, &txn);
|
||||||
if (rc != MDB_SUCCESS)
|
if (rc != MDB_SUCCESS) {
|
||||||
|
mdb_txn_abort(txn);
|
||||||
throw Unknown(name, mdb_strerror(rc), storageName);
|
throw Unknown(name, mdb_strerror(rc), storageName);
|
||||||
|
}
|
||||||
return txn;
|
return txn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -549,7 +549,7 @@ void LMDBAL::Cache<K, V>::readAll(std::map<K, V>& out, TransactionID txn) const
|
|||||||
} else {
|
} else {
|
||||||
if (mode != Mode::full) { //there is a room for optimization
|
if (mode != Mode::full) { //there is a room for optimization
|
||||||
mode = Mode::full; //I can read and deserialize only those values
|
mode = Mode::full; //I can read and deserialize only those values
|
||||||
Storage<K, V>::readAll(out, txn); //that are missing in the cache
|
Storage<K, V>::readAll(out); //that are missing in the cache
|
||||||
*cache = out;
|
*cache = out;
|
||||||
abscent->clear();
|
abscent->clear();
|
||||||
sizeDifference = 0;
|
sizeDifference = 0;
|
||||||
|
48
src/cursor.h
48
src/cursor.h
@ -38,50 +38,37 @@ private:
|
|||||||
openedPrivate /**< - opened with private transaction, only current storage will be notified when cursor is closed*/
|
openedPrivate /**< - opened with private transaction, only current storage will be notified when cursor is closed*/
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
|
||||||
Cursor();
|
|
||||||
Cursor(Storage<K, V>* parent);
|
Cursor(Storage<K, V>* parent);
|
||||||
Cursor(const Cursor& other) = delete;
|
|
||||||
Cursor(Cursor&& other);
|
|
||||||
~Cursor();
|
~Cursor();
|
||||||
|
|
||||||
Cursor& operator = (const Cursor& other) = delete;
|
public:
|
||||||
Cursor& operator = (Cursor&& other);
|
void open() const;
|
||||||
|
void open(const Transaction& transaction) const;
|
||||||
void open();
|
void renew() const;
|
||||||
void open(const Transaction& transaction);
|
void renew(const Transaction& transaction) const;
|
||||||
void renew();
|
void close() const;
|
||||||
void renew(const Transaction& transaction);
|
|
||||||
void close();
|
|
||||||
bool opened() const;
|
bool opened() const;
|
||||||
bool empty() const;
|
|
||||||
|
|
||||||
void drop();
|
std::pair<K, V> first() const;
|
||||||
|
std::pair<K, V> last() const;
|
||||||
std::pair<K, V> first();
|
std::pair<K, V> next() const;
|
||||||
std::pair<K, V> last();
|
std::pair<K, V> prev() const;
|
||||||
std::pair<K, V> next();
|
|
||||||
std::pair<K, V> prev();
|
|
||||||
std::pair<K, V> current() const;
|
std::pair<K, V> current() const;
|
||||||
bool set(const K& target);
|
|
||||||
|
|
||||||
void first(K& key, V& value);
|
void first(K& key, V& value) const;
|
||||||
void last(K& key, V& value);
|
void last(K& key, V& value) const;
|
||||||
void next(K& key, V& value);
|
void next(K& key, V& value) const;
|
||||||
void prev(K& key, V& value);
|
void prev(K& key, V& value) const;
|
||||||
void current(K& key, V& value) const;
|
void current(K& key, V& value) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void dropped();
|
void terminated() const;
|
||||||
void freed();
|
|
||||||
void terminated();
|
|
||||||
void operateCursorRead(K& key, V& value, MDB_cursor_op operation, const std::string& methodName, const std::string& operationName) const;
|
void operateCursorRead(K& key, V& value, MDB_cursor_op operation, const std::string& methodName, const std::string& operationName) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Storage<K, V>* storage;
|
Storage<K, V>* storage;
|
||||||
MDB_cursor* cursor;
|
mutable MDB_cursor* cursor;
|
||||||
State state;
|
mutable State state;
|
||||||
uint32_t id;
|
|
||||||
|
|
||||||
inline static const std::string openCursorMethodName = "Cursor::open"; /**<\brief member function name, just for exceptions*/
|
inline static const std::string openCursorMethodName = "Cursor::open"; /**<\brief member function name, just for exceptions*/
|
||||||
inline static const std::string closeCursorMethodName = "Cursor::close"; /**<\brief member function name, just for exceptions*/
|
inline static const std::string closeCursorMethodName = "Cursor::close"; /**<\brief member function name, just for exceptions*/
|
||||||
@ -92,7 +79,6 @@ private:
|
|||||||
inline static const std::string nextMethodName = "next"; /**<\brief member function name, just for exceptions*/
|
inline static const std::string nextMethodName = "next"; /**<\brief member function name, just for exceptions*/
|
||||||
inline static const std::string prevMethodName = "prev"; /**<\brief member function name, just for exceptions*/
|
inline static const std::string prevMethodName = "prev"; /**<\brief member function name, just for exceptions*/
|
||||||
inline static const std::string currentMethodName = "current"; /**<\brief member function name, just for exceptions*/
|
inline static const std::string currentMethodName = "current"; /**<\brief member function name, just for exceptions*/
|
||||||
inline static const std::string setMethodName = "set"; /**<\brief member function name, just for exceptions*/
|
|
||||||
|
|
||||||
inline static const std::string firstOperationName = "Cursor::first"; /**<\brief member function name, just for exceptions*/
|
inline static const std::string firstOperationName = "Cursor::first"; /**<\brief member function name, just for exceptions*/
|
||||||
inline static const std::string lastOperationName = "Cursor::last"; /**<\brief member function name, just for exceptions*/
|
inline static const std::string lastOperationName = "Cursor::last"; /**<\brief member function name, just for exceptions*/
|
||||||
|
213
src/cursor.hpp
213
src/cursor.hpp
@ -41,8 +41,6 @@
|
|||||||
* You are not supposed to instantiate or destory instances of this class yourself!
|
* You are not supposed to instantiate or destory instances of this class yourself!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static uint32_t idCounter = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Creates a cursor
|
* \brief Creates a cursor
|
||||||
*
|
*
|
||||||
@ -52,70 +50,9 @@ template<class K, class V>
|
|||||||
LMDBAL::Cursor<K, V>::Cursor(Storage<K, V>* parent):
|
LMDBAL::Cursor<K, V>::Cursor(Storage<K, V>* parent):
|
||||||
storage(parent),
|
storage(parent),
|
||||||
cursor(nullptr),
|
cursor(nullptr),
|
||||||
state(closed),
|
state(closed)
|
||||||
id(++idCounter)
|
|
||||||
{
|
|
||||||
storage->cursors[id] = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Creates an empty cursor.
|
|
||||||
*
|
|
||||||
* It's not usable, but can exist just to be a target of moves
|
|
||||||
*/
|
|
||||||
template<class K, class V>
|
|
||||||
LMDBAL::Cursor<K, V>::Cursor():
|
|
||||||
storage(nullptr),
|
|
||||||
cursor(nullptr),
|
|
||||||
state(closed),
|
|
||||||
id(0)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Moves from another cursor
|
|
||||||
*/
|
|
||||||
template<class K, class V>
|
|
||||||
LMDBAL::Cursor<K, V>::Cursor(Cursor&& other):
|
|
||||||
storage(other.storage),
|
|
||||||
cursor(other.cursor),
|
|
||||||
state(other.state),
|
|
||||||
id(other.id)
|
|
||||||
{
|
|
||||||
other.terminated();
|
|
||||||
if (id != 0)
|
|
||||||
storage->cursors[id] = this;
|
|
||||||
|
|
||||||
other.freed();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief A private function that turns cursor into an empty one
|
|
||||||
*
|
|
||||||
* This function is called from LMDBAL::Storage, when it gets destroyed, but still has some valid.
|
|
||||||
* Those cursors will become empty, and can't be used anymore
|
|
||||||
*/
|
|
||||||
template<class K, class V>
|
|
||||||
LMDBAL::Cursor<K, V>& LMDBAL::Cursor<K, V>::operator = (Cursor&& other) {
|
|
||||||
terminated();
|
|
||||||
|
|
||||||
if (id != 0)
|
|
||||||
storage->cursors.erase(id);
|
|
||||||
|
|
||||||
storage = other.storage;
|
|
||||||
cursor = other.cursor;
|
|
||||||
state = other.state;
|
|
||||||
id = other.id;
|
|
||||||
|
|
||||||
if (id != 0) {
|
|
||||||
other.freed();
|
|
||||||
other.state = closed;
|
|
||||||
|
|
||||||
storage->cursors[id] = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Destroys a cursor
|
* \brief Destroys a cursor
|
||||||
*
|
*
|
||||||
@ -124,67 +61,13 @@ LMDBAL::Cursor<K, V>& LMDBAL::Cursor<K, V>::operator = (Cursor&& other) {
|
|||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
LMDBAL::Cursor<K, V>::~Cursor () {
|
LMDBAL::Cursor<K, V>::~Cursor () {
|
||||||
close();
|
close();
|
||||||
|
|
||||||
if (id != 0)
|
|
||||||
storage->cursors.erase(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Turns cursor into an empty one, releasing resources
|
|
||||||
*
|
|
||||||
* This function is called from LMDBAL::Storage, when it gets destroyed, but still has some valid.
|
|
||||||
* Those cursors will become empty, and can't be used anymore
|
|
||||||
*/
|
|
||||||
template<class K, class V>
|
|
||||||
void LMDBAL::Cursor<K, V>::drop () {
|
|
||||||
close();
|
|
||||||
|
|
||||||
if (id != 0)
|
|
||||||
storage->cursors.erase(id);
|
|
||||||
|
|
||||||
freed();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief A private method that turns cursor into an empty one
|
|
||||||
*
|
|
||||||
* This function is called from LMDBAL::Storage, when it gets destroyed, but still has some valid cursors.
|
|
||||||
* Those cursors will become empty, and can't be used anymore
|
|
||||||
*/
|
|
||||||
template<class K, class V>
|
|
||||||
void LMDBAL::Cursor<K, V>::dropped () {
|
|
||||||
terminated();
|
|
||||||
freed();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief A private method that turns cursor into an empty one (submethod)
|
|
||||||
*
|
|
||||||
* This function is called from LMDBAL::Storage, when the cursor is getting destoryed.
|
|
||||||
* Those cursors will become empty, and can't be used anymore
|
|
||||||
*/
|
|
||||||
template<class K, class V>
|
|
||||||
void LMDBAL::Cursor<K, V>::freed () {
|
|
||||||
cursor = nullptr;
|
|
||||||
storage = nullptr;
|
|
||||||
id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Returns true if the cursor is empty
|
|
||||||
*
|
|
||||||
* Empty cursors can't be used, they can be only targets of move operations
|
|
||||||
*/
|
|
||||||
template<class K, class V>
|
|
||||||
bool LMDBAL::Cursor<K, V>::empty () const {
|
|
||||||
return id == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief A private function the storage owning this cursor will call to inform this cursor that the thansaction needs to be aborted
|
* \brief A private function the storage owning this cursor will call to inform this cursor that the thansaction needs to be aborted
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void LMDBAL::Cursor<K, V>::terminated () {
|
void LMDBAL::Cursor<K, V>::terminated () const {
|
||||||
close(); //for now it's the same, but if I ever going to make writable cursor - here is where it's gonna be different
|
close(); //for now it's the same, but if I ever going to make writable cursor - here is where it's gonna be different
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,18 +82,14 @@ void LMDBAL::Cursor<K, V>::terminated () {
|
|||||||
*
|
*
|
||||||
* \exception LMDBAL::Closed thrown if you try to open the cursor on a closed database
|
* \exception LMDBAL::Closed thrown if you try to open the cursor on a closed database
|
||||||
* \exception LMDBAL::Unknown thrown if there was a problem opening the cursor by the lmdb, or to begin a transaction
|
* \exception LMDBAL::Unknown thrown if there was a problem opening the cursor by the lmdb, or to begin a transaction
|
||||||
* \exception LMDBAL::CursorEmpty thrown if the cursor was empty
|
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void LMDBAL::Cursor<K, V>::open () {
|
void LMDBAL::Cursor<K, V>::open () const {
|
||||||
if (empty())
|
|
||||||
throw CursorEmpty(openCursorMethodName);
|
|
||||||
|
|
||||||
storage->ensureOpened(openCursorMethodName);
|
storage->ensureOpened(openCursorMethodName);
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case closed: {
|
case closed: {
|
||||||
TransactionID txn = storage->beginReadOnlyTransaction();
|
TransactionID txn = storage->beginReadOnlyTransaction();
|
||||||
int result = storage->_mdbCursorOpen(txn, &cursor);
|
int result = mdb_cursor_open(txn, storage->dbi, &cursor);
|
||||||
if (result != MDB_SUCCESS)
|
if (result != MDB_SUCCESS)
|
||||||
storage->throwUnknown(result, txn);
|
storage->throwUnknown(result, txn);
|
||||||
|
|
||||||
@ -236,18 +115,14 @@ void LMDBAL::Cursor<K, V>::open () {
|
|||||||
* \exception LMDBAL::Closed thrown if you try to open the cursor on a closed database
|
* \exception LMDBAL::Closed thrown if you try to open the cursor on a closed database
|
||||||
* \exception LMDBAL::Unknown thrown if there was a problem opening the cursor by the lmdb
|
* \exception LMDBAL::Unknown thrown if there was a problem opening the cursor by the lmdb
|
||||||
* \exception LMDBAL::TransactionTerminated thrown if the passed transaction not active, any action with it's inner ID is an error
|
* \exception LMDBAL::TransactionTerminated thrown if the passed transaction not active, any action with it's inner ID is an error
|
||||||
* \exception LMDBAL::CursorEmpty thrown if the cursor was empty
|
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void LMDBAL::Cursor<K, V>::open (const Transaction& transaction) {
|
void LMDBAL::Cursor<K, V>::open (const Transaction& transaction) const {
|
||||||
if (empty())
|
|
||||||
throw CursorEmpty(openCursorMethodName);
|
|
||||||
|
|
||||||
storage->ensureOpened(openCursorMethodName);
|
storage->ensureOpened(openCursorMethodName);
|
||||||
TransactionID txn = storage->extractTransactionId(transaction, openCursorMethodName);
|
TransactionID txn = storage->extractTransactionId(transaction, openCursorMethodName);
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case closed: {
|
case closed: {
|
||||||
int result = storage->_mdbCursorOpen(txn, &cursor);
|
int result = mdb_cursor_open(txn, storage->dbi, &cursor);
|
||||||
if (result != MDB_SUCCESS)
|
if (result != MDB_SUCCESS)
|
||||||
storage->throwUnknown(result);
|
storage->throwUnknown(result);
|
||||||
|
|
||||||
@ -273,24 +148,20 @@ void LMDBAL::Cursor<K, V>::open (const Transaction& transaction) {
|
|||||||
*
|
*
|
||||||
* \exception LMDBAL::Closed thrown if you try to renew the cursor on a closed database
|
* \exception LMDBAL::Closed thrown if you try to renew the cursor on a closed database
|
||||||
* \exception LMDBAL::Unknown thrown if there was a problem beginning new transaction or if there was a problem renewing the cursor by lmdb
|
* \exception LMDBAL::Unknown thrown if there was a problem beginning new transaction or if there was a problem renewing the cursor by lmdb
|
||||||
* \exception LMDBAL::CursorEmpty thrown if the cursor was empty
|
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void LMDBAL::Cursor<K, V>::renew () {
|
void LMDBAL::Cursor<K, V>::renew () const {
|
||||||
if (empty())
|
|
||||||
throw CursorEmpty(openCursorMethodName);
|
|
||||||
|
|
||||||
storage->ensureOpened(renewCursorMethodName);
|
storage->ensureOpened(renewCursorMethodName);
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case openedPrivate: {
|
case openedPrivate: {
|
||||||
TransactionID txn = storage->_mdbCursorTxn(cursor);
|
TransactionID txn = mdb_cursor_txn(cursor);
|
||||||
storage->abortTransaction(txn);
|
storage->abortTransaction(txn);
|
||||||
storage->transactionAborted(txn);
|
storage->transactionAborted(txn);
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
}
|
}
|
||||||
case openedPublic: {
|
case openedPublic: {
|
||||||
TransactionID txn = storage->beginReadOnlyTransaction();
|
TransactionID txn = storage->beginReadOnlyTransaction();
|
||||||
int result = storage->_mdbCursorRenew(txn, cursor);
|
int result = mdb_cursor_renew(txn, cursor);
|
||||||
if (result != MDB_SUCCESS)
|
if (result != MDB_SUCCESS)
|
||||||
storage->throwUnknown(result, txn);
|
storage->throwUnknown(result, txn);
|
||||||
|
|
||||||
@ -320,24 +191,20 @@ void LMDBAL::Cursor<K, V>::renew () {
|
|||||||
* \exception LMDBAL::Closed thrown if you try to renew the cursor on a closed database
|
* \exception LMDBAL::Closed thrown if you try to renew the cursor on a closed database
|
||||||
* \exception LMDBAL::Unknown thrown if there was a problem renewing the cursor by lmdb
|
* \exception LMDBAL::Unknown thrown if there was a problem renewing the cursor by lmdb
|
||||||
* \exception LMDBAL::TransactionTerminated thrown if the passed transaction not active, any action with it's inner ID is an error
|
* \exception LMDBAL::TransactionTerminated thrown if the passed transaction not active, any action with it's inner ID is an error
|
||||||
* \exception LMDBAL::CursorEmpty thrown if the cursor was empty
|
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void LMDBAL::Cursor<K, V>::renew (const Transaction& transaction) {
|
void LMDBAL::Cursor<K, V>::renew (const Transaction& transaction) const {
|
||||||
if (empty())
|
|
||||||
throw CursorEmpty(openCursorMethodName);
|
|
||||||
|
|
||||||
storage->ensureOpened(renewCursorMethodName);
|
storage->ensureOpened(renewCursorMethodName);
|
||||||
TransactionID txn = storage->extractTransactionId(transaction, renewCursorMethodName);
|
TransactionID txn = storage->extractTransactionId(transaction, renewCursorMethodName);
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case openedPrivate: {
|
case openedPrivate: {
|
||||||
TransactionID txn = storage->_mdbCursorTxn(cursor);
|
TransactionID txn = mdb_cursor_txn(cursor);
|
||||||
storage->abortTransaction(txn);
|
storage->abortTransaction(txn);
|
||||||
storage->transactionAborted(txn);
|
storage->transactionAborted(txn);
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
}
|
}
|
||||||
case openedPublic: {
|
case openedPublic: {
|
||||||
int result = storage->_mdbCursorRenew(txn, cursor);
|
int result = mdb_cursor_renew(txn, cursor);
|
||||||
if (result != MDB_SUCCESS)
|
if (result != MDB_SUCCESS)
|
||||||
storage->throwUnknown(result);
|
storage->throwUnknown(result);
|
||||||
|
|
||||||
@ -359,16 +226,16 @@ void LMDBAL::Cursor<K, V>::renew (const Transaction& transaction) {
|
|||||||
* This function does nothing on a closed cursor.
|
* This function does nothing on a closed cursor.
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void LMDBAL::Cursor<K, V>::close () {
|
void LMDBAL::Cursor<K, V>::close () const {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case openedPublic: {
|
case openedPublic: {
|
||||||
storage->_mdbCursorClose(cursor);
|
mdb_cursor_close(cursor);
|
||||||
|
|
||||||
state = closed;
|
state = closed;
|
||||||
} break;
|
} break;
|
||||||
case openedPrivate: {
|
case openedPrivate: {
|
||||||
TransactionID txn = storage->_mdbCursorTxn(cursor);
|
TransactionID txn = mdb_cursor_txn(cursor);
|
||||||
storage->_mdbCursorClose(cursor);
|
mdb_cursor_close(cursor);
|
||||||
storage->abortTransaction(txn);
|
storage->abortTransaction(txn);
|
||||||
storage->transactionAborted(txn);
|
storage->transactionAborted(txn);
|
||||||
|
|
||||||
@ -400,7 +267,7 @@ bool LMDBAL::Cursor<K, V>::opened () const {
|
|||||||
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void LMDBAL::Cursor<K, V>::first (K& key, V& value) {
|
void LMDBAL::Cursor<K, V>::first (K& key, V& value) const {
|
||||||
operateCursorRead(key, value, MDB_FIRST, firstMethodName, firstOperationName);
|
operateCursorRead(key, value, MDB_FIRST, firstMethodName, firstOperationName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -417,7 +284,7 @@ void LMDBAL::Cursor<K, V>::first (K& key, V& value) {
|
|||||||
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void LMDBAL::Cursor<K, V>::last (K& key, V& value) {
|
void LMDBAL::Cursor<K, V>::last (K& key, V& value) const {
|
||||||
operateCursorRead(key, value, MDB_LAST, lastMethodName, lastOperationName);
|
operateCursorRead(key, value, MDB_LAST, lastMethodName, lastOperationName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,7 +307,7 @@ void LMDBAL::Cursor<K, V>::last (K& key, V& value) {
|
|||||||
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void LMDBAL::Cursor<K, V>::next (K& key, V& value) {
|
void LMDBAL::Cursor<K, V>::next (K& key, V& value) const {
|
||||||
operateCursorRead(key, value, MDB_NEXT, nextMethodName, nextOperationName);
|
operateCursorRead(key, value, MDB_NEXT, nextMethodName, nextOperationName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -463,7 +330,7 @@ void LMDBAL::Cursor<K, V>::next (K& key, V& value) {
|
|||||||
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void LMDBAL::Cursor<K, V>::prev (K& key, V& value) {
|
void LMDBAL::Cursor<K, V>::prev (K& key, V& value) const {
|
||||||
operateCursorRead(key, value, MDB_PREV, prevMethodName, prevOperationName);
|
operateCursorRead(key, value, MDB_PREV, prevMethodName, prevOperationName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -498,7 +365,7 @@ void LMDBAL::Cursor<K, V>::current (K& key, V& value) const {
|
|||||||
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
std::pair<K, V> LMDBAL::Cursor<K, V>::first () {
|
std::pair<K, V> LMDBAL::Cursor<K, V>::first () const {
|
||||||
std::pair<K, V> result;
|
std::pair<K, V> result;
|
||||||
operateCursorRead(result.first, result.second, MDB_FIRST, firstMethodName, firstOperationName);
|
operateCursorRead(result.first, result.second, MDB_FIRST, firstMethodName, firstOperationName);
|
||||||
return result;
|
return result;
|
||||||
@ -516,7 +383,7 @@ std::pair<K, V> LMDBAL::Cursor<K, V>::first () {
|
|||||||
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
std::pair<K, V> LMDBAL::Cursor<K, V>::last () {
|
std::pair<K, V> LMDBAL::Cursor<K, V>::last () const {
|
||||||
std::pair<K, V> result;
|
std::pair<K, V> result;
|
||||||
operateCursorRead(result.first, result.second, MDB_LAST, lastMethodName, lastOperationName);
|
operateCursorRead(result.first, result.second, MDB_LAST, lastMethodName, lastOperationName);
|
||||||
return result;
|
return result;
|
||||||
@ -540,7 +407,7 @@ std::pair<K, V> LMDBAL::Cursor<K, V>::last () {
|
|||||||
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
std::pair<K, V> LMDBAL::Cursor<K, V>::next () {
|
std::pair<K, V> LMDBAL::Cursor<K, V>::next () const {
|
||||||
std::pair<K, V> result;
|
std::pair<K, V> result;
|
||||||
operateCursorRead(result.first, result.second, MDB_NEXT, nextMethodName, nextOperationName);
|
operateCursorRead(result.first, result.second, MDB_NEXT, nextMethodName, nextOperationName);
|
||||||
return result;
|
return result;
|
||||||
@ -564,7 +431,7 @@ std::pair<K, V> LMDBAL::Cursor<K, V>::next () {
|
|||||||
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
std::pair<K, V> LMDBAL::Cursor<K, V>::prev () {
|
std::pair<K, V> LMDBAL::Cursor<K, V>::prev () const {
|
||||||
std::pair<K, V> result;
|
std::pair<K, V> result;
|
||||||
operateCursorRead(result.first, result.second, MDB_PREV, prevMethodName, prevOperationName);
|
operateCursorRead(result.first, result.second, MDB_PREV, prevMethodName, prevOperationName);
|
||||||
return result;
|
return result;
|
||||||
@ -590,34 +457,6 @@ std::pair<K, V> LMDBAL::Cursor<K, V>::current () const {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Sets cursors to the defined position
|
|
||||||
*
|
|
||||||
* If exactly the same element wasn't found it sets the cursor to the first
|
|
||||||
* element greater then the key and returns false
|
|
||||||
*
|
|
||||||
* \param[in] key a key of the element you would like the cursor to be
|
|
||||||
* \returns true if the exact value was found, false otherwise
|
|
||||||
*
|
|
||||||
* \exception LMDBAL::CursorNotReady thrown if you try to call this method on a closed cursor
|
|
||||||
* \exception LMDBAL::Unknown thrown if there was some unexpected problem
|
|
||||||
*/
|
|
||||||
template<class K, class V>
|
|
||||||
bool LMDBAL::Cursor<K, V>::set (const K& key) {
|
|
||||||
if (state == closed)
|
|
||||||
storage->throwCursorNotReady(setMethodName);
|
|
||||||
|
|
||||||
MDB_val mdbKey = storage->keySerializer.setData(key);
|
|
||||||
int result = storage->_mdbCursorSet(cursor, mdbKey);
|
|
||||||
if (result == MDB_SUCCESS)
|
|
||||||
return true;
|
|
||||||
else if (result == MDB_NOTFOUND)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
storage->throwUnknown(result);
|
|
||||||
return false; //unreachable, just to suppress the warning
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief a private mothod that actually doing all the reading
|
* \brief a private mothod that actually doing all the reading
|
||||||
*
|
*
|
||||||
@ -645,7 +484,7 @@ void LMDBAL::Cursor<K, V>::operateCursorRead(
|
|||||||
storage->throwCursorNotReady(methodName);
|
storage->throwCursorNotReady(methodName);
|
||||||
|
|
||||||
MDB_val mdbKey, mdbValue;
|
MDB_val mdbKey, mdbValue;
|
||||||
int result = storage->_mdbCursorGet(cursor, mdbKey, mdbValue, operation);
|
int result = mdb_cursor_get(cursor, &mdbKey, &mdbValue, operation);
|
||||||
if (result != MDB_SUCCESS)
|
if (result != MDB_SUCCESS)
|
||||||
storage->throwNotFoundOrUnknown(result, operationName);
|
storage->throwNotFoundOrUnknown(result, operationName);
|
||||||
|
|
||||||
@ -655,7 +494,7 @@ void LMDBAL::Cursor<K, V>::operateCursorRead(
|
|||||||
if (state == openedPrivate)
|
if (state == openedPrivate)
|
||||||
storage->discoveredRecord(key, value);
|
storage->discoveredRecord(key, value);
|
||||||
else
|
else
|
||||||
storage->discoveredRecord(key, value, storage->_mdbCursorTxn(cursor));
|
storage->discoveredRecord(key, value, mdb_cursor_txn(cursor));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //LMDBAL_CURSOR_HPP
|
#endif //LMDBAL_CURSOR_HPP
|
||||||
|
@ -72,14 +72,6 @@ std::string LMDBAL::CursorNotReady::getMessage() const {
|
|||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
LMDBAL::CursorEmpty::CursorEmpty(const std::string & operation):
|
|
||||||
Exception(),
|
|
||||||
operation(operation) {}
|
|
||||||
|
|
||||||
std::string LMDBAL::CursorEmpty::getMessage() const {
|
|
||||||
return "An attempt to perform an operation \"" + operation + "\" on an empty cursor";
|
|
||||||
}
|
|
||||||
|
|
||||||
LMDBAL::Opened::Opened(const std::string& p_dbName, const std::string& p_action):
|
LMDBAL::Opened::Opened(const std::string& p_dbName, const std::string& p_action):
|
||||||
Exception(),
|
Exception(),
|
||||||
dbName(p_dbName),
|
dbName(p_dbName),
|
||||||
|
@ -97,23 +97,6 @@ private:
|
|||||||
std::string tableName;
|
std::string tableName;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Thrown if an empty cursor was somehow operated
|
|
||||||
*/
|
|
||||||
class CursorEmpty : public Exception {
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* \brief Creates exception
|
|
||||||
*
|
|
||||||
* \param operation - text name of the method that was called on an empty cursor
|
|
||||||
*/
|
|
||||||
CursorEmpty(const std::string& operation);
|
|
||||||
|
|
||||||
std::string getMessage() const;
|
|
||||||
private:
|
|
||||||
std::string operation;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Thrown if something in the database was called on opened state and it is not supported
|
* \brief Thrown if something in the database was called on opened state and it is not supported
|
||||||
*/
|
*/
|
||||||
|
@ -16,4 +16,6 @@ set(HEADERS
|
|||||||
serializer_qbytearray.hpp
|
serializer_qbytearray.hpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
target_include_directories(${PROJECT_NAME} PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>")
|
||||||
|
|
||||||
install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_LOW})
|
install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_LOW})
|
||||||
|
@ -446,64 +446,3 @@ void LMDBAL::iStorage::transactionAborted(LMDBAL::TransactionID txn) const {
|
|||||||
* after the transaction is commited. Used just for optimisations.
|
* after the transaction is commited. Used just for optimisations.
|
||||||
*/
|
*/
|
||||||
void LMDBAL::iStorage::handleDrop() {}
|
void LMDBAL::iStorage::handleDrop() {}
|
||||||
|
|
||||||
int LMDBAL::iStorage::_mdbOpen(MDB_txn *txn, unsigned int flags) {
|
|
||||||
return mdb_dbi_open(txn, name.c_str(), flags, &dbi);
|
|
||||||
}
|
|
||||||
|
|
||||||
int LMDBAL::iStorage::_mdbPut(MDB_txn* txn, MDB_val& key, MDB_val& data, unsigned int flags) {
|
|
||||||
return mdb_put(txn, dbi, &key, &data, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
int LMDBAL::iStorage::_mdbGet(MDB_txn* txn, MDB_val& key, MDB_val& data) const {
|
|
||||||
return mdb_get(txn, dbi, &key, &data);
|
|
||||||
}
|
|
||||||
|
|
||||||
int LMDBAL::iStorage::_mdbDel(MDB_txn* txn, MDB_val& key) {
|
|
||||||
return mdb_del(txn, dbi, &key, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
int LMDBAL::iStorage::_mdbDel(MDB_txn* txn, MDB_val& key, MDB_val& data) {
|
|
||||||
return mdb_del(txn, dbi, &key, &data);
|
|
||||||
}
|
|
||||||
|
|
||||||
int LMDBAL::iStorage::_mdbStat(MDB_txn* txn, MDB_stat& stat) const {
|
|
||||||
return mdb_stat(txn, dbi, &stat);
|
|
||||||
}
|
|
||||||
|
|
||||||
int LMDBAL::iStorage::_mdbFlags(MDB_txn* txn, uint32_t& flags) const {
|
|
||||||
return mdb_dbi_flags(txn, dbi, &flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int LMDBAL::iStorage::_mdbCursorOpen(MDB_txn* txn, MDB_cursor** cursor) const {
|
|
||||||
return mdb_cursor_open(txn, dbi, cursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LMDBAL::iStorage::_mdbCursorClose(MDB_cursor *cursor) const {
|
|
||||||
mdb_cursor_close(cursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
int LMDBAL::iStorage::_mdbCursorGet(MDB_cursor* cursor, MDB_val& key, MDB_val& data, MDB_cursor_op operation) const {
|
|
||||||
return mdb_cursor_get(cursor, &key, &data, operation);
|
|
||||||
}
|
|
||||||
|
|
||||||
int LMDBAL::iStorage::_mdbCursorSet(MDB_cursor* cursor, MDB_val& key) const {
|
|
||||||
return mdb_cursor_get(cursor, &key, NULL, MDB_SET);
|
|
||||||
}
|
|
||||||
|
|
||||||
int LMDBAL::iStorage::_mdbCursorDel(MDB_cursor* cursor, unsigned int flags) {
|
|
||||||
return mdb_cursor_del(cursor, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
int LMDBAL::iStorage::_mdbCursorPut(MDB_cursor* cursor, MDB_val& key, MDB_val& data, unsigned int flags) {
|
|
||||||
return mdb_cursor_put(cursor, &key, &data, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
int LMDBAL::iStorage::_mdbCursorRenew(MDB_txn* txn, MDB_cursor* cursor) const {
|
|
||||||
return mdb_cursor_renew(txn, cursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
MDB_txn* LMDBAL::iStorage::_mdbCursorTxn(MDB_cursor* cursor) const {
|
|
||||||
return mdb_cursor_txn(cursor);
|
|
||||||
}
|
|
||||||
|
@ -29,8 +29,6 @@
|
|||||||
|
|
||||||
class BaseTest;
|
class BaseTest;
|
||||||
class DuplicatesTest;
|
class DuplicatesTest;
|
||||||
class CacheCursorTest;
|
|
||||||
class StorageCursorTest;
|
|
||||||
|
|
||||||
namespace LMDBAL {
|
namespace LMDBAL {
|
||||||
|
|
||||||
@ -77,26 +75,6 @@ protected:
|
|||||||
virtual int drop(TransactionID transaction);
|
virtual int drop(TransactionID transaction);
|
||||||
virtual SizeType count(TransactionID txn) const;
|
virtual SizeType count(TransactionID txn) const;
|
||||||
|
|
||||||
int _mdbOpen(MDB_txn* txn, unsigned int flags = 0);
|
|
||||||
|
|
||||||
int _mdbPut(MDB_txn* txn, MDB_val& key, MDB_val& data, unsigned int flags = 0);
|
|
||||||
int _mdbGet(MDB_txn* txn, MDB_val& key, MDB_val& data) const;
|
|
||||||
int _mdbDel(MDB_txn* txn, MDB_val& key);
|
|
||||||
int _mdbDel(MDB_txn* txn, MDB_val& key, MDB_val& data);
|
|
||||||
|
|
||||||
int _mdbStat(MDB_txn* txn, MDB_stat& stat) const;
|
|
||||||
int _mdbFlags(MDB_txn* txn, uint32_t& flags) const;
|
|
||||||
|
|
||||||
int _mdbCursorOpen(MDB_txn* txn, MDB_cursor** cursor) const;
|
|
||||||
void _mdbCursorClose(MDB_cursor* cursor) const;
|
|
||||||
int _mdbCursorGet(MDB_cursor* cursor, MDB_val& key, MDB_val& data, MDB_cursor_op operation) const;
|
|
||||||
int _mdbCursorSet(MDB_cursor* cursor, MDB_val& key) const;
|
|
||||||
int _mdbCursorDel(MDB_cursor* cursor, unsigned int flags = 0);
|
|
||||||
int _mdbCursorPut(MDB_cursor* cursor, MDB_val& key, MDB_val& data, unsigned int flags = 0);
|
|
||||||
|
|
||||||
int _mdbCursorRenew(MDB_txn* txn, MDB_cursor* cursor) const;
|
|
||||||
MDB_txn* _mdbCursorTxn(MDB_cursor* cursor) const;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void drop();
|
virtual void drop();
|
||||||
virtual int drop(const WriteTransaction& txn);
|
virtual int drop(const WriteTransaction& txn);
|
||||||
@ -135,8 +113,6 @@ template <class K, class V>
|
|||||||
class Storage : public iStorage {
|
class Storage : public iStorage {
|
||||||
friend class ::BaseTest;
|
friend class ::BaseTest;
|
||||||
friend class ::DuplicatesTest;
|
friend class ::DuplicatesTest;
|
||||||
friend class ::CacheCursorTest;
|
|
||||||
friend class ::StorageCursorTest;
|
|
||||||
friend class Base;
|
friend class Base;
|
||||||
friend class Cursor<K, V>;
|
friend class Cursor<K, V>;
|
||||||
protected:
|
protected:
|
||||||
@ -184,13 +160,13 @@ public:
|
|||||||
virtual uint32_t addRecords(const std::map<K, V>& data, bool overwrite = false);
|
virtual uint32_t addRecords(const std::map<K, V>& data, bool overwrite = false);
|
||||||
virtual uint32_t addRecords(const std::map<K, V>& data, const WriteTransaction& txn, bool overwrite = false);
|
virtual uint32_t addRecords(const std::map<K, V>& data, const WriteTransaction& txn, bool overwrite = false);
|
||||||
|
|
||||||
Cursor<K, V> createCursor();
|
Cursor<K, V>* createCursor();
|
||||||
void destroyCursor(Cursor<K, V>& cursor);
|
void destroyCursor(Cursor<K, V>* cursor);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
mutable Serializer<K> keySerializer; /**<\brief internal object that would serialize and deserialize keys*/
|
mutable Serializer<K> keySerializer; /**<\brief internal object that would serialize and deserialize keys*/
|
||||||
mutable Serializer<V> valueSerializer; /**<\brief internal object that would serialize and deserialize values*/
|
mutable Serializer<V> valueSerializer; /**<\brief internal object that would serialize and deserialize values*/
|
||||||
std::map<uint32_t, Cursor<K, V>*> cursors; /**<\brief a set of cursors that has been created under this storage*/
|
std::set<Cursor<K, V>*> cursors; /**<\brief a set of cursors that has been created under this storage*/
|
||||||
|
|
||||||
int open(MDB_txn* transaction) override;
|
int open(MDB_txn* transaction) override;
|
||||||
void close() override;
|
void close() override;
|
||||||
|
100
src/storage.hpp
100
src/storage.hpp
@ -58,8 +58,8 @@ LMDBAL::Storage<K, V>::Storage(Base* parent, const std::string& name, bool dupli
|
|||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
LMDBAL::Storage<K, V>::~Storage() {
|
LMDBAL::Storage<K, V>::~Storage() {
|
||||||
for (const std::pair<const uint32_t, Cursor<K, V>*>& pair : cursors)
|
for (Cursor<K, V>* cursor : cursors)
|
||||||
pair.second->dropped();
|
delete cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -115,7 +115,7 @@ void LMDBAL::Storage<K, V>::addRecord(const K& key, const V& value, TransactionI
|
|||||||
else
|
else
|
||||||
flags |= MDB_NOOVERWRITE;
|
flags |= MDB_NOOVERWRITE;
|
||||||
|
|
||||||
int rc = _mdbPut(txn, lmdbKey, lmdbData, flags);
|
int rc = mdb_put(txn, dbi, &lmdbKey, &lmdbData, flags);
|
||||||
if (rc != MDB_SUCCESS)
|
if (rc != MDB_SUCCESS)
|
||||||
throwDuplicateOrUnknown(rc, toString(key));
|
throwDuplicateOrUnknown(rc, toString(key));
|
||||||
}
|
}
|
||||||
@ -209,7 +209,7 @@ bool LMDBAL::Storage<K, V>::forceRecord(const K& key, const V& value, Transactio
|
|||||||
MDB_val lmdbKey = keySerializer.setData(key);
|
MDB_val lmdbKey = keySerializer.setData(key);
|
||||||
MDB_val lmdbData;
|
MDB_val lmdbData;
|
||||||
|
|
||||||
int rc = _mdbGet(txn, lmdbKey, lmdbData);
|
int rc = mdb_get(txn, dbi, &lmdbKey, &lmdbData);
|
||||||
switch (rc) {
|
switch (rc) {
|
||||||
case MDB_SUCCESS:
|
case MDB_SUCCESS:
|
||||||
added = false;
|
added = false;
|
||||||
@ -223,7 +223,7 @@ bool LMDBAL::Storage<K, V>::forceRecord(const K& key, const V& value, Transactio
|
|||||||
}
|
}
|
||||||
|
|
||||||
lmdbData = valueSerializer.setData(value);
|
lmdbData = valueSerializer.setData(value);
|
||||||
rc = _mdbPut(txn, lmdbKey, lmdbData);
|
rc = mdb_put(txn, dbi, &lmdbKey, &lmdbData, 0);
|
||||||
if (rc != MDB_SUCCESS)
|
if (rc != MDB_SUCCESS)
|
||||||
throwUnknown(rc);
|
throwUnknown(rc);
|
||||||
}
|
}
|
||||||
@ -314,13 +314,13 @@ void LMDBAL::Storage<K, V>::changeRecord(const K& key, const V& value) {
|
|||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void LMDBAL::Storage<K, V>::changeRecord(const K& key, const V& value, TransactionID txn) {
|
void LMDBAL::Storage<K, V>::changeRecord(const K& key, const V& value, TransactionID txn) {
|
||||||
MDB_cursor* cursor;
|
MDB_cursor* cursor;
|
||||||
int rc = _mdbCursorOpen(txn, &cursor);
|
int rc = mdb_cursor_open(txn, dbi, &cursor);
|
||||||
if (rc != MDB_SUCCESS)
|
if (rc != MDB_SUCCESS)
|
||||||
throwUnknown(rc);
|
throwUnknown(rc);
|
||||||
|
|
||||||
MDB_val lmdbKey = keySerializer.setData(key);
|
MDB_val lmdbKey = keySerializer.setData(key);
|
||||||
MDB_val lmdbData;
|
MDB_val lmdbData;
|
||||||
rc = _mdbCursorGet(cursor, lmdbKey, lmdbData, MDB_SET);
|
rc = mdb_cursor_get(cursor, &lmdbKey, &lmdbData, MDB_SET);
|
||||||
if (rc != MDB_SUCCESS)
|
if (rc != MDB_SUCCESS)
|
||||||
throwNotFoundOrUnknown(rc, toString(key));
|
throwNotFoundOrUnknown(rc, toString(key));
|
||||||
|
|
||||||
@ -330,21 +330,21 @@ void LMDBAL::Storage<K, V>::changeRecord(const K& key, const V& value, Transacti
|
|||||||
if (sameSize) { //can compare only if they are the same size
|
if (sameSize) { //can compare only if they are the same size
|
||||||
firstDifferentByte = memcmp(lmdbData.mv_data, lmdbNewData.mv_data, lmdbData.mv_size);
|
firstDifferentByte = memcmp(lmdbData.mv_data, lmdbNewData.mv_data, lmdbData.mv_size);
|
||||||
if (firstDifferentByte == 0) { //old and new is the same, nothing to do
|
if (firstDifferentByte == 0) { //old and new is the same, nothing to do
|
||||||
_mdbCursorClose(cursor);
|
mdb_cursor_close(cursor);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int flags = MDB_CURRENT;
|
unsigned int flags = MDB_CURRENT;
|
||||||
if (duplicates && (!sameSize || firstDifferentByte < 0)) { //if new value is greater than the old one
|
if (duplicates && (!sameSize || firstDifferentByte < 0)) { //if new value is greater than the old one
|
||||||
rc = _mdbCursorDel(cursor); //we need to initiate duplicates sort, for it to be in the correct place
|
rc = mdb_cursor_del(cursor, 0); //we need to initiate duplicates sort, for it to be in the correct place
|
||||||
flags = MDB_NODUPDATA;
|
flags = MDB_NODUPDATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc == MDB_SUCCESS)
|
if (rc == MDB_SUCCESS)
|
||||||
rc = _mdbCursorPut(cursor, lmdbKey, lmdbNewData, flags);
|
rc = mdb_cursor_put(cursor, &lmdbKey, &lmdbNewData, flags);
|
||||||
|
|
||||||
_mdbCursorClose(cursor);
|
mdb_cursor_close(cursor);
|
||||||
if (rc != MDB_SUCCESS)
|
if (rc != MDB_SUCCESS)
|
||||||
throwDuplicateOrUnknown(rc, toString(key));
|
throwDuplicateOrUnknown(rc, toString(key));
|
||||||
}
|
}
|
||||||
@ -517,7 +517,7 @@ void LMDBAL::Storage<K, V>::getRecord(const K& key, V& value, TransactionID txn)
|
|||||||
MDB_val lmdbKey = keySerializer.setData(key);
|
MDB_val lmdbKey = keySerializer.setData(key);
|
||||||
MDB_val lmdbData;
|
MDB_val lmdbData;
|
||||||
|
|
||||||
int rc = _mdbGet(txn, lmdbKey, lmdbData);
|
int rc = mdb_get(txn, dbi, &lmdbKey, &lmdbData);
|
||||||
if (rc != MDB_SUCCESS)
|
if (rc != MDB_SUCCESS)
|
||||||
throwNotFoundOrUnknown(rc, toString(key));
|
throwNotFoundOrUnknown(rc, toString(key));
|
||||||
|
|
||||||
@ -594,7 +594,7 @@ bool LMDBAL::Storage<K, V>::checkRecord(const K& key, TransactionID txn) const {
|
|||||||
MDB_val lmdbKey = keySerializer.setData(key);
|
MDB_val lmdbKey = keySerializer.setData(key);
|
||||||
MDB_val lmdbData;
|
MDB_val lmdbData;
|
||||||
|
|
||||||
int rc = _mdbGet(txn, lmdbKey, lmdbData);
|
int rc = mdb_get(txn, dbi, &lmdbKey, &lmdbData);
|
||||||
if (rc == MDB_SUCCESS)
|
if (rc == MDB_SUCCESS)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -729,11 +729,11 @@ void LMDBAL::Storage<K, V>::readAll(std::map<K, V>& result, TransactionID txn) c
|
|||||||
MDB_cursor* cursor;
|
MDB_cursor* cursor;
|
||||||
MDB_val lmdbKey, lmdbData;
|
MDB_val lmdbKey, lmdbData;
|
||||||
|
|
||||||
int rc = _mdbCursorOpen(txn, &cursor);
|
int rc = mdb_cursor_open(txn, dbi, &cursor);
|
||||||
if (rc != MDB_SUCCESS)
|
if (rc != MDB_SUCCESS)
|
||||||
throwUnknown(rc);
|
throwUnknown(rc);
|
||||||
|
|
||||||
rc = _mdbCursorGet(cursor, lmdbKey, lmdbData, MDB_FIRST);
|
rc = mdb_cursor_get(cursor, &lmdbKey, &lmdbData, MDB_FIRST);
|
||||||
while (rc == MDB_SUCCESS) {
|
while (rc == MDB_SUCCESS) {
|
||||||
K key;
|
K key;
|
||||||
keySerializer.deserialize(lmdbKey, key);
|
keySerializer.deserialize(lmdbKey, key);
|
||||||
@ -741,9 +741,9 @@ void LMDBAL::Storage<K, V>::readAll(std::map<K, V>& result, TransactionID txn) c
|
|||||||
if (probe.second) //I do this to avoid overwrites in case duplicates are enabled
|
if (probe.second) //I do this to avoid overwrites in case duplicates are enabled
|
||||||
valueSerializer.deserialize(lmdbData, probe.first->second);
|
valueSerializer.deserialize(lmdbData, probe.first->second);
|
||||||
|
|
||||||
rc = _mdbCursorGet(cursor, lmdbKey, lmdbData, MDB_NEXT);
|
rc = mdb_cursor_get(cursor, &lmdbKey, &lmdbData, MDB_NEXT);
|
||||||
}
|
}
|
||||||
_mdbCursorClose(cursor);
|
mdb_cursor_close(cursor);
|
||||||
if (rc != MDB_NOTFOUND)
|
if (rc != MDB_NOTFOUND)
|
||||||
throwUnknown(rc);
|
throwUnknown(rc);
|
||||||
}
|
}
|
||||||
@ -817,7 +817,7 @@ void LMDBAL::Storage<K, V>::replaceAll(const std::map<K, V>& data, TransactionID
|
|||||||
lmdbKey = keySerializer.setData(pair.first);
|
lmdbKey = keySerializer.setData(pair.first);
|
||||||
lmdbData = valueSerializer.setData(pair.second);
|
lmdbData = valueSerializer.setData(pair.second);
|
||||||
|
|
||||||
rc = _mdbPut(txn, lmdbKey, lmdbData, MDB_NOOVERWRITE); //TODO may be appending with cursor makes sence here?
|
rc = mdb_put(txn, dbi, &lmdbKey, &lmdbData, MDB_NOOVERWRITE); //TODO may be appending with cursor makes sence here?
|
||||||
if (rc != MDB_SUCCESS)
|
if (rc != MDB_SUCCESS)
|
||||||
throwUnknown(rc);
|
throwUnknown(rc);
|
||||||
}
|
}
|
||||||
@ -892,7 +892,7 @@ uint32_t LMDBAL::Storage<K, V>::addRecords(const std::map<K, V>& data, Transacti
|
|||||||
lmdbKey = keySerializer.setData(pair.first);
|
lmdbKey = keySerializer.setData(pair.first);
|
||||||
lmdbData = valueSerializer.setData(pair.second);
|
lmdbData = valueSerializer.setData(pair.second);
|
||||||
|
|
||||||
rc = _mdbPut(txn, lmdbKey, lmdbData, overwrite ? 0 : MDB_NOOVERWRITE);
|
rc = mdb_put(txn, dbi, &lmdbKey, &lmdbData, overwrite ? 0 : MDB_NOOVERWRITE);
|
||||||
if (rc == MDB_KEYEXIST)
|
if (rc == MDB_KEYEXIST)
|
||||||
throwDuplicate(toString(pair.first));
|
throwDuplicate(toString(pair.first));
|
||||||
|
|
||||||
@ -901,7 +901,7 @@ uint32_t LMDBAL::Storage<K, V>::addRecords(const std::map<K, V>& data, Transacti
|
|||||||
}
|
}
|
||||||
|
|
||||||
MDB_stat stat;
|
MDB_stat stat;
|
||||||
rc = _mdbStat(txn, stat);
|
rc = mdb_stat(txn, dbi, &stat);
|
||||||
if (rc != MDB_SUCCESS)
|
if (rc != MDB_SUCCESS)
|
||||||
throwUnknown(rc);
|
throwUnknown(rc);
|
||||||
|
|
||||||
@ -971,7 +971,7 @@ void LMDBAL::Storage<K, V>::removeRecord(const K& key) {
|
|||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void LMDBAL::Storage<K, V>::removeRecord(const K& key, TransactionID txn) {
|
void LMDBAL::Storage<K, V>::removeRecord(const K& key, TransactionID txn) {
|
||||||
MDB_val lmdbKey = keySerializer.setData(key);
|
MDB_val lmdbKey = keySerializer.setData(key);
|
||||||
int rc = _mdbDel(txn, lmdbKey);
|
int rc = mdb_del(txn, dbi, &lmdbKey, NULL);
|
||||||
if (rc != MDB_SUCCESS)
|
if (rc != MDB_SUCCESS)
|
||||||
throwNotFoundOrUnknown(rc, toString(key));
|
throwNotFoundOrUnknown(rc, toString(key));
|
||||||
}
|
}
|
||||||
@ -1013,8 +1013,8 @@ int LMDBAL::Storage<K, V>::open(MDB_txn* transaction) {
|
|||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void LMDBAL::Storage<K, V>::close() {
|
void LMDBAL::Storage<K, V>::close() {
|
||||||
for (const std::pair<const uint32_t, Cursor<K, V>*>& pair : cursors)
|
for (Cursor<K, V>* cursor : cursors)
|
||||||
pair.second->terminated();
|
cursor->terminated();
|
||||||
|
|
||||||
iStorage::close();
|
iStorage::close();
|
||||||
}
|
}
|
||||||
@ -1022,37 +1022,14 @@ void LMDBAL::Storage<K, V>::close() {
|
|||||||
/**
|
/**
|
||||||
* \brief Creates cursor
|
* \brief Creates cursor
|
||||||
*
|
*
|
||||||
* This is a legitimate way to aquire cursor to a storage.
|
|
||||||
* Aquired cursor is RAII safe, automatic destructor will free everything it occupied.
|
|
||||||
*
|
|
||||||
* \returns LMDBAL::Cursor for this storage and returs you a pointer to a created cursor
|
* \returns LMDBAL::Cursor for this storage and returs you a pointer to a created cursor
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
LMDBAL::Cursor<K, V> LMDBAL::Storage<K, V>::createCursor() {
|
LMDBAL::Cursor<K, V>* LMDBAL::Storage<K, V>::createCursor() {
|
||||||
return Cursor<K, V>(this);
|
Cursor<K, V>* cursor = new Cursor<K, V>(this);
|
||||||
}
|
cursors.insert(cursor);
|
||||||
|
|
||||||
/**
|
return cursor;
|
||||||
* \brief Frees cursor
|
|
||||||
*
|
|
||||||
* This is a legitimate way to free cursor.
|
|
||||||
* You don't actually need to do it manually,
|
|
||||||
* you can just reassign cursor, let it be destroyed by leaving the scope
|
|
||||||
* or call LMDBAL::Cursor<K, V>::drop, but you may if you wish.
|
|
||||||
*
|
|
||||||
* \param[in] cursor cursor you wish to destroy
|
|
||||||
*
|
|
||||||
* \exception LMDBAL::Unknown thrown if you try to destroy a cursor this storage didn't create
|
|
||||||
*/
|
|
||||||
template<class K, class V>
|
|
||||||
void LMDBAL::Storage<K, V>::destroyCursor(LMDBAL::Cursor<K, V>& cursor) {
|
|
||||||
typename std::map<uint32_t, Cursor<K, V>*>::iterator itr = cursors.find(cursor.id);
|
|
||||||
if (itr == cursors.end())
|
|
||||||
throwUnknown("An attempt to destroy a cursor the storage doesn't own");
|
|
||||||
|
|
||||||
cursor.close();
|
|
||||||
cursors.erase(itr);
|
|
||||||
cursor.freed();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1071,7 +1048,7 @@ uint32_t LMDBAL::Storage<K, V>::flags() const {
|
|||||||
uint32_t result;
|
uint32_t result;
|
||||||
TransactionID txn = beginReadOnlyTransaction();
|
TransactionID txn = beginReadOnlyTransaction();
|
||||||
|
|
||||||
int res = _mdbFlags(txn, result);
|
int res = mdb_dbi_flags(txn, dbi, &result);
|
||||||
abortTransaction(txn);
|
abortTransaction(txn);
|
||||||
if (res != MDB_SUCCESS)
|
if (res != MDB_SUCCESS)
|
||||||
throwUnknown(res);
|
throwUnknown(res);
|
||||||
@ -1079,6 +1056,25 @@ uint32_t LMDBAL::Storage<K, V>::flags() const {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Destroys cursor
|
||||||
|
*
|
||||||
|
* This a normal way to discard a cursor you don't need anymore
|
||||||
|
*
|
||||||
|
* \param[in] cursor a pointer to a cursor you want to destroy
|
||||||
|
*
|
||||||
|
* \exception LMDBAL::Unknown thrown if you try to destroy something that this storage didn't create
|
||||||
|
*/
|
||||||
|
template<class K, class V>
|
||||||
|
void LMDBAL::Storage<K, V>::destroyCursor(Cursor<K, V>* cursor) {
|
||||||
|
typename std::set<Cursor<K, V>*>::const_iterator itr = cursors.find(cursor);
|
||||||
|
if (itr == cursors.end())
|
||||||
|
throwUnknown("An attempt to destroy a cursor the storage doesn't own");
|
||||||
|
|
||||||
|
cursors.erase(itr);
|
||||||
|
delete cursor;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief A private virtual method that cursor calls when he reads a record, does nothing here but populates the LMDBAL::Cache
|
* \brief A private virtual method that cursor calls when he reads a record, does nothing here but populates the LMDBAL::Cache
|
||||||
*
|
*
|
||||||
@ -1140,7 +1136,7 @@ inline int LMDBAL::iStorage::makeStorage(MDB_txn* transaction, bool duplicates)
|
|||||||
flags |= MDB_INTEGERDUP;
|
flags |= MDB_INTEGERDUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _mdbOpen(transaction, flags);
|
return mdb_dbi_open(transaction, name.c_str(), flags, &dbi);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -14,6 +14,7 @@ add_executable(runUnitTests
|
|||||||
|
|
||||||
target_compile_options(runUnitTests PRIVATE -fPIC -Wall -Wextra -O0)
|
target_compile_options(runUnitTests PRIVATE -fPIC -Wall -Wextra -O0)
|
||||||
|
|
||||||
|
target_include_directories(runUnitTests PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
||||||
target_include_directories(runUnitTests PRIVATE ${Qt${QT_VERSION_MAJOR}_INCLUDE_DIRS})
|
target_include_directories(runUnitTests PRIVATE ${Qt${QT_VERSION_MAJOR}_INCLUDE_DIRS})
|
||||||
target_include_directories(runUnitTests PRIVATE ${Qt${QT_VERSION_MAJOR}Core_INCLUDE_DIRS})
|
target_include_directories(runUnitTests PRIVATE ${Qt${QT_VERSION_MAJOR}Core_INCLUDE_DIRS})
|
||||||
|
|
||||||
@ -22,6 +23,7 @@ target_link_libraries(
|
|||||||
GTest::gtest_main
|
GTest::gtest_main
|
||||||
${PROJECT_NAME}
|
${PROJECT_NAME}
|
||||||
Qt${QT_VERSION_MAJOR}::Core
|
Qt${QT_VERSION_MAJOR}::Core
|
||||||
|
lmdb
|
||||||
)
|
)
|
||||||
include(GoogleTest)
|
include(GoogleTest)
|
||||||
gtest_discover_tests(runUnitTests)
|
gtest_discover_tests(runUnitTests)
|
||||||
|
@ -113,9 +113,10 @@ TEST_F(BaseTest, AddingKeysToCache) {
|
|||||||
EXPECT_EQ(db->ready(), true);
|
EXPECT_EQ(db->ready(), true);
|
||||||
c1->addRecord(2, "blah balah");
|
c1->addRecord(2, "blah balah");
|
||||||
c1->addRecord(-4, "testing goes brrr");
|
c1->addRecord(-4, "testing goes brrr");
|
||||||
c1->addRecord(40, "whatever");
|
c1->addRecord(140, "whatever");
|
||||||
c1->addRecord(-37, "aaaaa tss tsss tsss tsss aaaaaaa");
|
c1->addRecord(-37, "aaaaa tss tsss tsss tsss aaaaaaa");
|
||||||
EXPECT_EQ(c1->getRecord(40), "whatever");
|
EXPECT_EQ(c1->getRecord(140), "whatever");
|
||||||
|
EXPECT_EQ(c1->getRecord(-116), "whatever");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BaseTest, AddingKeysToVariableCache) {
|
TEST_F(BaseTest, AddingKeysToVariableCache) {
|
||||||
@ -188,8 +189,8 @@ TEST_F(BaseTest, Persistence) {
|
|||||||
EXPECT_EQ(t2->count(), t2Size);
|
EXPECT_EQ(t2->count(), t2Size);
|
||||||
|
|
||||||
EXPECT_EQ(c1->count(), c1Size);
|
EXPECT_EQ(c1->count(), c1Size);
|
||||||
EXPECT_EQ(c1->checkRecord(40), true);
|
EXPECT_EQ(c1->checkRecord(-116), true);
|
||||||
EXPECT_EQ(c1->getRecord(40), "whatever");
|
EXPECT_EQ(c1->getRecord(-116), "whatever");
|
||||||
EXPECT_EQ(c1->checkRecord(-4), true);
|
EXPECT_EQ(c1->checkRecord(-4), true);
|
||||||
EXPECT_EQ(c1->getRecord(-4), "testing goes brrr");
|
EXPECT_EQ(c1->getRecord(-4), "testing goes brrr");
|
||||||
EXPECT_EQ(c1->getRecord(-4), "testing goes brrr");
|
EXPECT_EQ(c1->getRecord(-4), "testing goes brrr");
|
||||||
|
@ -23,21 +23,19 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int getCacheCursorsSize() const {
|
|
||||||
return cache->cursors.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void TearDownTestSuite() {
|
static void TearDownTestSuite() {
|
||||||
cursor.drop();
|
|
||||||
transaction.terminate();
|
transaction.terminate();
|
||||||
db->close();
|
db->close();
|
||||||
db->removeDirectory();
|
db->removeDirectory();
|
||||||
delete db;
|
delete db;
|
||||||
db = nullptr;
|
db = nullptr;
|
||||||
|
cursor = nullptr;
|
||||||
|
emptyCursor = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static LMDBAL::Base* db;
|
static LMDBAL::Base* db;
|
||||||
static LMDBAL::Cursor<uint64_t, std::string> cursor;
|
static LMDBAL::Cursor<uint64_t, std::string>* cursor;
|
||||||
|
static LMDBAL::Cursor<uint64_t, std::string>* emptyCursor;
|
||||||
static LMDBAL::Transaction transaction;
|
static LMDBAL::Transaction transaction;
|
||||||
|
|
||||||
LMDBAL::Cache<uint64_t, std::string>* cache;
|
LMDBAL::Cache<uint64_t, std::string>* cache;
|
||||||
@ -45,7 +43,8 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
LMDBAL::Base* CacheCursorTest::db = nullptr;
|
LMDBAL::Base* CacheCursorTest::db = nullptr;
|
||||||
LMDBAL::Cursor<uint64_t, std::string> CacheCursorTest::cursor;
|
LMDBAL::Cursor<uint64_t, std::string>* CacheCursorTest::cursor = nullptr;
|
||||||
|
LMDBAL::Cursor<uint64_t, std::string>* CacheCursorTest::emptyCursor = nullptr;
|
||||||
LMDBAL::Transaction CacheCursorTest::transaction;
|
LMDBAL::Transaction CacheCursorTest::transaction;
|
||||||
|
|
||||||
static const std::map<uint64_t, std::string> data({
|
static const std::map<uint64_t, std::string> data({
|
||||||
@ -67,24 +66,22 @@ TEST_F(CacheCursorTest, PopulatingTheTable) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CacheCursorTest, Creation) {
|
TEST_F(CacheCursorTest, Creation) {
|
||||||
EXPECT_EQ(getCacheCursorsSize(), 0);
|
|
||||||
cursor = cache->createCursor();
|
cursor = cache->createCursor();
|
||||||
EXPECT_EQ(getCacheCursorsSize(), 1);
|
emptyCursor = emptyCache->createCursor();
|
||||||
|
|
||||||
EXPECT_THROW(cursor.first(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor->first(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor.last(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor->last(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor.next(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor->next(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor.prev(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor->prev(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor.current(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor->current(), LMDBAL::CursorNotReady);
|
||||||
|
|
||||||
cursor.open();
|
cursor->open();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CacheCursorTest, FirstPrivate) {
|
TEST_F(CacheCursorTest, FirstPrivate) {
|
||||||
EXPECT_EQ(getCacheCursorsSize(), 1);
|
|
||||||
EXPECT_EQ(cache->count(), data.size());
|
EXPECT_EQ(cache->count(), data.size());
|
||||||
|
|
||||||
std::pair<uint64_t, std::string> element = cursor.first();
|
std::pair<uint64_t, std::string> element = cursor->first();
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -93,21 +90,20 @@ TEST_F(CacheCursorTest, FirstPrivate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CacheCursorTest, NextPrivate) {
|
TEST_F(CacheCursorTest, NextPrivate) {
|
||||||
EXPECT_EQ(getCacheCursorsSize(), 1);
|
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
||||||
|
|
||||||
reference++;
|
reference++;
|
||||||
for (; reference != data.end(); ++reference) {
|
for (; reference != data.end(); ++reference) {
|
||||||
std::pair<uint64_t, std::string> element = cursor.next();
|
std::pair<uint64_t, std::string> element = cursor->next();
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
EXPECT_EQ(cache->count(), data.size());
|
EXPECT_EQ(cache->count(), data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_THROW(cursor.next(), LMDBAL::NotFound);
|
EXPECT_THROW(cursor->next(), LMDBAL::NotFound);
|
||||||
EXPECT_EQ(cache->count(), data.size());
|
EXPECT_EQ(cache->count(), data.size());
|
||||||
|
|
||||||
std::pair<uint64_t, std::string> element = cursor.first();
|
std::pair<uint64_t, std::string> element = cursor->first();
|
||||||
reference = data.begin();
|
reference = data.begin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -116,10 +112,9 @@ TEST_F(CacheCursorTest, NextPrivate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CacheCursorTest, LastPrivate) {
|
TEST_F(CacheCursorTest, LastPrivate) {
|
||||||
EXPECT_EQ(getCacheCursorsSize(), 1);
|
|
||||||
EXPECT_EQ(cache->count(), data.size());
|
EXPECT_EQ(cache->count(), data.size());
|
||||||
|
|
||||||
std::pair<uint64_t, std::string> element = cursor.last();
|
std::pair<uint64_t, std::string> element = cursor->last();
|
||||||
std::map<uint64_t, std::string>::const_reverse_iterator reference = data.rbegin();
|
std::map<uint64_t, std::string>::const_reverse_iterator reference = data.rbegin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -128,21 +123,20 @@ TEST_F(CacheCursorTest, LastPrivate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CacheCursorTest, PrevPrivate) {
|
TEST_F(CacheCursorTest, PrevPrivate) {
|
||||||
EXPECT_EQ(getCacheCursorsSize(), 1);
|
|
||||||
std::map<uint64_t, std::string>::const_reverse_iterator reference = data.rbegin();
|
std::map<uint64_t, std::string>::const_reverse_iterator reference = data.rbegin();
|
||||||
|
|
||||||
reference++;
|
reference++;
|
||||||
for (; reference != data.rend(); ++reference) {
|
for (; reference != data.rend(); ++reference) {
|
||||||
std::pair<uint64_t, std::string> element = cursor.prev();
|
std::pair<uint64_t, std::string> element = cursor->prev();
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
EXPECT_EQ(cache->count(), data.size());
|
EXPECT_EQ(cache->count(), data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_THROW(cursor.prev(), LMDBAL::NotFound);
|
EXPECT_THROW(cursor->prev(), LMDBAL::NotFound);
|
||||||
EXPECT_EQ(cache->count(), data.size());
|
EXPECT_EQ(cache->count(), data.size());
|
||||||
|
|
||||||
std::pair<uint64_t, std::string> element = cursor.last();
|
std::pair<uint64_t, std::string> element = cursor->last();
|
||||||
reference = data.rbegin();
|
reference = data.rbegin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -151,30 +145,29 @@ TEST_F(CacheCursorTest, PrevPrivate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CacheCursorTest, CurrentPrivate) {
|
TEST_F(CacheCursorTest, CurrentPrivate) {
|
||||||
EXPECT_EQ(getCacheCursorsSize(), 1);
|
std::pair<uint64_t, std::string> element = cursor->first();
|
||||||
std::pair<uint64_t, std::string> element = cursor.first();
|
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
|
|
||||||
element = cursor.current();
|
element = cursor->current();
|
||||||
EXPECT_EQ(cache->count(), data.size());
|
EXPECT_EQ(cache->count(), data.size());
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
|
|
||||||
cursor.next();
|
cursor->next();
|
||||||
element = cursor.current();
|
element = cursor->current();
|
||||||
++reference;
|
++reference;
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
|
|
||||||
cursor.next();
|
cursor->next();
|
||||||
cursor.next();
|
cursor->next();
|
||||||
cursor.prev();
|
cursor->prev();
|
||||||
element = cursor.current();
|
element = cursor->current();
|
||||||
++reference;
|
++reference;
|
||||||
++reference;
|
++reference;
|
||||||
--reference;
|
--reference;
|
||||||
@ -184,62 +177,26 @@ TEST_F(CacheCursorTest, CurrentPrivate) {
|
|||||||
EXPECT_EQ(cache->count(), data.size());
|
EXPECT_EQ(cache->count(), data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CacheCursorTest, SettingPrivate) {
|
|
||||||
EXPECT_EQ(getCacheCursorsSize(), 1);
|
|
||||||
|
|
||||||
EXPECT_FALSE(cursor.set(6684));
|
|
||||||
EXPECT_EQ(cursor.current().second, "tanned inmate");
|
|
||||||
|
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
|
||||||
std::advance(reference, 5);
|
|
||||||
EXPECT_TRUE(cursor.set(reference->first));
|
|
||||||
EXPECT_EQ(cursor.current().second, reference->second);
|
|
||||||
|
|
||||||
++reference;
|
|
||||||
cursor.next();
|
|
||||||
EXPECT_EQ(cursor.current().second, reference->second);
|
|
||||||
|
|
||||||
++reference;
|
|
||||||
cursor.next();
|
|
||||||
EXPECT_EQ(cursor.current().second, reference->second);
|
|
||||||
|
|
||||||
--reference;
|
|
||||||
cursor.prev();
|
|
||||||
EXPECT_EQ(cursor.current().second, reference->second);
|
|
||||||
|
|
||||||
--reference;
|
|
||||||
cursor.prev();
|
|
||||||
EXPECT_EQ(cursor.current().second, reference->second);
|
|
||||||
|
|
||||||
--reference;
|
|
||||||
cursor.prev();
|
|
||||||
EXPECT_EQ(cursor.current().second, reference->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(CacheCursorTest, Destruction) {
|
TEST_F(CacheCursorTest, Destruction) {
|
||||||
EXPECT_EQ(getCacheCursorsSize(), 1);
|
cursor->close();
|
||||||
cursor.close();
|
|
||||||
EXPECT_EQ(getCacheCursorsSize(), 1);
|
|
||||||
|
|
||||||
EXPECT_THROW(cursor.first(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor->first(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor.last(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor->last(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor.next(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor->next(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor.prev(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor->prev(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor.current(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor->current(), LMDBAL::CursorNotReady);
|
||||||
|
|
||||||
cursor = LMDBAL::Cursor<uint64_t, std::string>();
|
EXPECT_THROW(emptyCache->destroyCursor(cursor), LMDBAL::Unknown);
|
||||||
EXPECT_EQ(getCacheCursorsSize(), 0);
|
cache->destroyCursor(cursor);
|
||||||
|
|
||||||
cursor = cache->createCursor();
|
cursor = cache->createCursor();
|
||||||
EXPECT_EQ(getCacheCursorsSize(), 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CacheCursorTest, FirstPublic) {
|
TEST_F(CacheCursorTest, FirstPublic) {
|
||||||
EXPECT_EQ(getCacheCursorsSize(), 1);
|
|
||||||
transaction = db->beginTransaction();
|
transaction = db->beginTransaction();
|
||||||
|
|
||||||
cursor.open(transaction);
|
cursor->open(transaction);
|
||||||
std::pair<uint64_t, std::string> element = cursor.first();
|
std::pair<uint64_t, std::string> element = cursor->first();
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -248,21 +205,20 @@ TEST_F(CacheCursorTest, FirstPublic) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CacheCursorTest, NextPublic) {
|
TEST_F(CacheCursorTest, NextPublic) {
|
||||||
EXPECT_EQ(getCacheCursorsSize(), 1);
|
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
||||||
|
|
||||||
reference++;
|
reference++;
|
||||||
for (; reference != data.end(); ++reference) {
|
for (; reference != data.end(); ++reference) {
|
||||||
std::pair<uint64_t, std::string> element = cursor.next();
|
std::pair<uint64_t, std::string> element = cursor->next();
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
EXPECT_EQ(cache->count(), data.size());
|
EXPECT_EQ(cache->count(), data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_THROW(cursor.next(), LMDBAL::NotFound);
|
EXPECT_THROW(cursor->next(), LMDBAL::NotFound);
|
||||||
EXPECT_EQ(cache->count(), data.size());
|
EXPECT_EQ(cache->count(), data.size());
|
||||||
|
|
||||||
std::pair<uint64_t, std::string> element = cursor.first();
|
std::pair<uint64_t, std::string> element = cursor->first();
|
||||||
reference = data.begin();
|
reference = data.begin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -270,8 +226,7 @@ TEST_F(CacheCursorTest, NextPublic) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CacheCursorTest, LastPublic) {
|
TEST_F(CacheCursorTest, LastPublic) {
|
||||||
EXPECT_EQ(getCacheCursorsSize(), 1);
|
std::pair<uint64_t, std::string> element = cursor->last();
|
||||||
std::pair<uint64_t, std::string> element = cursor.last();
|
|
||||||
std::map<uint64_t, std::string>::const_reverse_iterator reference = data.rbegin();
|
std::map<uint64_t, std::string>::const_reverse_iterator reference = data.rbegin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -280,20 +235,19 @@ TEST_F(CacheCursorTest, LastPublic) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CacheCursorTest, PrevPublic) {
|
TEST_F(CacheCursorTest, PrevPublic) {
|
||||||
EXPECT_EQ(getCacheCursorsSize(), 1);
|
|
||||||
std::map<uint64_t, std::string>::const_reverse_iterator reference = data.rbegin();
|
std::map<uint64_t, std::string>::const_reverse_iterator reference = data.rbegin();
|
||||||
|
|
||||||
reference++;
|
reference++;
|
||||||
for (; reference != data.rend(); ++reference) {
|
for (; reference != data.rend(); ++reference) {
|
||||||
std::pair<uint64_t, std::string> element = cursor.prev();
|
std::pair<uint64_t, std::string> element = cursor->prev();
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
EXPECT_EQ(cache->count(), data.size());
|
EXPECT_EQ(cache->count(), data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_THROW(cursor.prev(), LMDBAL::NotFound);
|
EXPECT_THROW(cursor->prev(), LMDBAL::NotFound);
|
||||||
|
|
||||||
std::pair<uint64_t, std::string> element = cursor.last();
|
std::pair<uint64_t, std::string> element = cursor->last();
|
||||||
reference = data.rbegin();
|
reference = data.rbegin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -302,30 +256,29 @@ TEST_F(CacheCursorTest, PrevPublic) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CacheCursorTest, CurrentPublic) {
|
TEST_F(CacheCursorTest, CurrentPublic) {
|
||||||
EXPECT_EQ(getCacheCursorsSize(), 1);
|
std::pair<uint64_t, std::string> element = cursor->first();
|
||||||
std::pair<uint64_t, std::string> element = cursor.first();
|
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
|
|
||||||
element = cursor.current();
|
element = cursor->current();
|
||||||
EXPECT_EQ(cache->count(), data.size());
|
EXPECT_EQ(cache->count(), data.size());
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
|
|
||||||
cursor.next();
|
cursor->next();
|
||||||
element = cursor.current();
|
element = cursor->current();
|
||||||
++reference;
|
++reference;
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
|
|
||||||
cursor.next();
|
cursor->next();
|
||||||
cursor.next();
|
cursor->next();
|
||||||
cursor.prev();
|
cursor->prev();
|
||||||
element = cursor.current();
|
element = cursor->current();
|
||||||
++reference;
|
++reference;
|
||||||
++reference;
|
++reference;
|
||||||
--reference;
|
--reference;
|
||||||
@ -335,106 +288,40 @@ TEST_F(CacheCursorTest, CurrentPublic) {
|
|||||||
EXPECT_EQ(cache->count(), data.size());
|
EXPECT_EQ(cache->count(), data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CacheCursorTest, SettingPublic) {
|
|
||||||
EXPECT_EQ(getCacheCursorsSize(), 1);
|
|
||||||
|
|
||||||
EXPECT_FALSE(cursor.set(557));
|
|
||||||
EXPECT_EQ(cursor.current().second, "resilent pick forefront");
|
|
||||||
|
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
|
||||||
std::advance(reference, 3);
|
|
||||||
EXPECT_TRUE(cursor.set(reference->first));
|
|
||||||
EXPECT_EQ(cursor.current().second, reference->second);
|
|
||||||
|
|
||||||
++reference;
|
|
||||||
cursor.next();
|
|
||||||
EXPECT_EQ(cursor.current().second, reference->second);
|
|
||||||
|
|
||||||
++reference;
|
|
||||||
cursor.next();
|
|
||||||
EXPECT_EQ(cursor.current().second, reference->second);
|
|
||||||
|
|
||||||
--reference;
|
|
||||||
cursor.prev();
|
|
||||||
EXPECT_EQ(cursor.current().second, reference->second);
|
|
||||||
|
|
||||||
--reference;
|
|
||||||
cursor.prev();
|
|
||||||
EXPECT_EQ(cursor.current().second, reference->second);
|
|
||||||
|
|
||||||
--reference;
|
|
||||||
cursor.prev();
|
|
||||||
EXPECT_EQ(cursor.current().second, reference->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(CacheCursorTest, CursorRAIIBehaviour) {
|
|
||||||
int initialiCursorsAmount = getCacheCursorsSize();
|
|
||||||
{
|
|
||||||
LMDBAL::Cursor<uint64_t, std::string> cur = cache->createCursor();
|
|
||||||
EXPECT_EQ(initialiCursorsAmount + 1, getCacheCursorsSize());
|
|
||||||
cur.open(transaction);
|
|
||||||
EXPECT_NO_THROW(cur.first());
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPECT_EQ(initialiCursorsAmount, getCacheCursorsSize());
|
|
||||||
LMDBAL::Cursor<uint64_t, std::string> cur;
|
|
||||||
EXPECT_EQ(initialiCursorsAmount, getCacheCursorsSize());
|
|
||||||
EXPECT_EQ(cur.empty(), true);
|
|
||||||
cur = cache->createCursor();
|
|
||||||
EXPECT_EQ(cur.empty(), false);
|
|
||||||
EXPECT_EQ(initialiCursorsAmount + 1, getCacheCursorsSize());
|
|
||||||
EXPECT_THROW(emptyCache->destroyCursor(cur), LMDBAL::Unknown);
|
|
||||||
cache->destroyCursor(cur);
|
|
||||||
EXPECT_EQ(cur.empty(), true);
|
|
||||||
EXPECT_EQ(initialiCursorsAmount, getCacheCursorsSize());
|
|
||||||
|
|
||||||
cur = cache->createCursor();
|
|
||||||
EXPECT_EQ(initialiCursorsAmount + 1, getCacheCursorsSize());
|
|
||||||
EXPECT_EQ(cur.empty(), false);
|
|
||||||
|
|
||||||
cur.drop();
|
|
||||||
EXPECT_EQ(cur.empty(), true);
|
|
||||||
EXPECT_EQ(initialiCursorsAmount, getCacheCursorsSize());
|
|
||||||
|
|
||||||
EXPECT_NO_THROW(cur.drop());
|
|
||||||
EXPECT_THROW(cache->destroyCursor(cur), LMDBAL::Unknown);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(CacheCursorTest, CornerCases) {
|
TEST_F(CacheCursorTest, CornerCases) {
|
||||||
transaction.terminate();
|
transaction.terminate();
|
||||||
EXPECT_THROW(cursor.current(), LMDBAL::Unknown);
|
EXPECT_THROW(cursor->current(), LMDBAL::Unknown);
|
||||||
cursor.close();
|
cursor->close();
|
||||||
|
|
||||||
LMDBAL::Cursor<uint64_t, std::string> emptyCursor = emptyCache->createCursor();
|
emptyCursor->open();
|
||||||
emptyCursor.open();
|
EXPECT_THROW(emptyCursor->first(), LMDBAL::NotFound);
|
||||||
EXPECT_THROW(emptyCursor.first(), LMDBAL::NotFound);
|
EXPECT_THROW(emptyCursor->last(), LMDBAL::NotFound);
|
||||||
EXPECT_THROW(emptyCursor.last(), LMDBAL::NotFound);
|
EXPECT_THROW(emptyCursor->next(), LMDBAL::NotFound);
|
||||||
EXPECT_THROW(emptyCursor.next(), LMDBAL::NotFound);
|
EXPECT_THROW(emptyCursor->prev(), LMDBAL::NotFound);
|
||||||
EXPECT_THROW(emptyCursor.prev(), LMDBAL::NotFound);
|
EXPECT_THROW(emptyCursor->current(), LMDBAL::Unknown);
|
||||||
EXPECT_THROW(emptyCursor.current(), LMDBAL::Unknown);
|
emptyCursor->close();
|
||||||
emptyCursor.close();
|
|
||||||
|
|
||||||
cursor.open();
|
cursor->open();
|
||||||
EXPECT_THROW(cursor.current(), LMDBAL::Unknown); //yeah, nice thing to write in the doc
|
EXPECT_THROW(cursor->current(), LMDBAL::Unknown); //yeah, nice thing to write in the doc
|
||||||
|
|
||||||
std::map<uint64_t, std::string>::const_reverse_iterator breference = data.rbegin();
|
std::map<uint64_t, std::string>::const_reverse_iterator breference = data.rbegin();
|
||||||
std::pair<uint64_t, std::string> element(cursor.prev());
|
std::pair<uint64_t, std::string> element(cursor->prev());
|
||||||
EXPECT_EQ(element.first, breference->first); //nice thing to write in the doc, again!
|
EXPECT_EQ(element.first, breference->first); //nice thing to write in the doc, again!
|
||||||
EXPECT_EQ(element.second, breference->second);
|
EXPECT_EQ(element.second, breference->second);
|
||||||
element = cursor.current();
|
element = cursor->current();
|
||||||
EXPECT_EQ(element.first, breference->first);
|
EXPECT_EQ(element.first, breference->first);
|
||||||
EXPECT_EQ(element.second, breference->second);
|
EXPECT_EQ(element.second, breference->second);
|
||||||
EXPECT_THROW(cursor.next(), LMDBAL::NotFound);
|
EXPECT_THROW(cursor->next(), LMDBAL::NotFound);
|
||||||
cursor.close();
|
cursor->close();
|
||||||
|
|
||||||
cursor.open();
|
cursor->open();
|
||||||
element = cursor.next();
|
element = cursor->next();
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
element = cursor.current();
|
element = cursor->current();
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
EXPECT_THROW(cursor.prev(), LMDBAL::NotFound);
|
EXPECT_THROW(cursor->prev(), LMDBAL::NotFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,10 +130,7 @@ TEST_F(DuplicatesTest, Adding) {
|
|||||||
tu3->addRecord(7.20001, 4.00000001); //not sure how exactly, but it works
|
tu3->addRecord(7.20001, 4.00000001); //not sure how exactly, but it works
|
||||||
|
|
||||||
EXPECT_EQ(tu3->count(), 7);
|
EXPECT_EQ(tu3->count(), 7);
|
||||||
|
EXPECT_EQ(tu3->getRecord(7.2), -113);
|
||||||
std::set<float> res72({-113, -53.5478, 697, 4, 4.00000001});
|
|
||||||
EXPECT_EQ(res72.count(tu3->getRecord(7.2)), 1);
|
|
||||||
|
|
||||||
float tu3dd = tu3->getRecord(5119);
|
float tu3dd = tu3->getRecord(5119);
|
||||||
EXPECT_TRUE(tu3ds == tu3dd);
|
EXPECT_TRUE(tu3ds == tu3dd);
|
||||||
EXPECT_EQ(tu3ds, tu3dd);
|
EXPECT_EQ(tu3ds, tu3dd);
|
||||||
@ -147,11 +144,8 @@ TEST_F(DuplicatesTest, Adding) {
|
|||||||
EXPECT_THROW(tu4->addRecord(327, 79.624923), LMDBAL::Exist);
|
EXPECT_THROW(tu4->addRecord(327, 79.624923), LMDBAL::Exist);
|
||||||
|
|
||||||
EXPECT_EQ(tu4->count(), 4);
|
EXPECT_EQ(tu4->count(), 4);
|
||||||
|
EXPECT_EQ(tu4->getRecord(172), 0.00000001);
|
||||||
std::set<double> res327({463.28348, 79.624923});
|
EXPECT_EQ(tu4->getRecord(327), 463.28348); //since they are not int's they are compared sort of lexicographically
|
||||||
std::set<double> res172({0.00001, 0.00000001});
|
|
||||||
EXPECT_EQ(res172.count(tu4->getRecord(172)), 1);
|
|
||||||
EXPECT_EQ(res327.count(tu4->getRecord(327)), 1);
|
|
||||||
|
|
||||||
tu5->addRecord(-84.7, 45656753);
|
tu5->addRecord(-84.7, 45656753);
|
||||||
EXPECT_THROW(tu5->addRecord(-84.7, 45656753), LMDBAL::Exist);
|
EXPECT_THROW(tu5->addRecord(-84.7, 45656753), LMDBAL::Exist);
|
||||||
@ -180,19 +174,13 @@ TEST_F(DuplicatesTest, Forcing) {
|
|||||||
tu1->addRecord(-56, 71);
|
tu1->addRecord(-56, 71);
|
||||||
tu1->addRecord(-56, 274);
|
tu1->addRecord(-56, 274);
|
||||||
tu1->addRecord(-56, 732);
|
tu1->addRecord(-56, 732);
|
||||||
|
|
||||||
std::set<uint16_t> res56({71, 274, 732});
|
|
||||||
EXPECT_EQ(tu1->count(), tu1Size += 3);
|
EXPECT_EQ(tu1->count(), tu1Size += 3);
|
||||||
EXPECT_TRUE(tu1->forceRecord(-56, 322));
|
EXPECT_TRUE(tu1->forceRecord(-56, 322));
|
||||||
res56.insert(322);
|
|
||||||
EXPECT_EQ(tu1->count(), tu1Size += 1);
|
EXPECT_EQ(tu1->count(), tu1Size += 1);
|
||||||
EXPECT_EQ(res56.count(tu1->getRecord(-56)), 1);
|
EXPECT_EQ(tu1->getRecord(-56), 274); //like yeah, it's really counterintuitive, since it's compared byte by byte
|
||||||
|
|
||||||
res56.insert(14);
|
|
||||||
EXPECT_TRUE(tu1->forceRecord(-56, 14));
|
EXPECT_TRUE(tu1->forceRecord(-56, 14));
|
||||||
EXPECT_EQ(tu1->count(), tu1Size += 1);
|
EXPECT_EQ(tu1->count(), tu1Size += 1);
|
||||||
EXPECT_EQ(res56.count(tu1->getRecord(-56)), 1);
|
EXPECT_EQ(tu1->getRecord(-56), 14);
|
||||||
|
|
||||||
EXPECT_FALSE(tu1->forceRecord(-56, 274));
|
EXPECT_FALSE(tu1->forceRecord(-56, 274));
|
||||||
EXPECT_EQ(tu1->count(), tu1Size);
|
EXPECT_EQ(tu1->count(), tu1Size);
|
||||||
|
|
||||||
@ -213,38 +201,26 @@ TEST_F(DuplicatesTest, Forcing) {
|
|||||||
tu3->addRecord(17.3, 93.21);
|
tu3->addRecord(17.3, 93.21);
|
||||||
tu3->addRecord(17.3, 6.6);
|
tu3->addRecord(17.3, 6.6);
|
||||||
tu3->addRecord(17.3, 105.1);
|
tu3->addRecord(17.3, 105.1);
|
||||||
std::set<float> res17({93.21, 6.6, 105.1});
|
|
||||||
|
|
||||||
EXPECT_EQ(tu3->count(), tu3Size += 3);
|
EXPECT_EQ(tu3->count(), tu3Size += 3);
|
||||||
EXPECT_TRUE(tu3->forceRecord(17.3, 74.9));
|
EXPECT_TRUE(tu3->forceRecord(17.3, 74.9));
|
||||||
res17.insert(74.9);
|
|
||||||
EXPECT_EQ(tu3->count(), tu3Size += 1);
|
EXPECT_EQ(tu3->count(), tu3Size += 1);
|
||||||
EXPECT_EQ(res17.count(tu3->getRecord(17.3)), 1);
|
EXPECT_EQ(tu3->getRecord(17.3), 105.1f); //here too, really one should not use this function with duplicates,
|
||||||
|
EXPECT_TRUE(tu3->forceRecord(17.3, 5.1)); //unless he wishes for kinda randomish result
|
||||||
EXPECT_TRUE(tu3->forceRecord(17.3, 5.1));
|
|
||||||
res17.insert(5.1);
|
|
||||||
EXPECT_EQ(tu3->count(), tu3Size += 1);
|
EXPECT_EQ(tu3->count(), tu3Size += 1);
|
||||||
EXPECT_EQ(res17.count(tu3->getRecord(17.3)), 1);
|
EXPECT_EQ(tu3->getRecord(17.3), 5.1f);
|
||||||
|
|
||||||
EXPECT_FALSE(tu3->forceRecord(17.3, 93.21));
|
EXPECT_FALSE(tu3->forceRecord(17.3, 93.21));
|
||||||
EXPECT_EQ(tu3->count(), tu3Size);
|
EXPECT_EQ(tu3->count(), tu3Size);
|
||||||
|
|
||||||
LMDBAL::SizeType tu4Size = tu4->count();
|
LMDBAL::SizeType tu4Size = tu4->count();
|
||||||
tu4->addRecord(84, -359.109);
|
tu4->addRecord(84, -359.109);
|
||||||
tu4->addRecord(84, 2879.654);
|
tu4->addRecord(84, 2879.654);
|
||||||
std::set<double> res84({-359.109, 2879.654});
|
|
||||||
|
|
||||||
EXPECT_EQ(tu4->count(), tu4Size += 2);
|
EXPECT_EQ(tu4->count(), tu4Size += 2);
|
||||||
EXPECT_TRUE(tu4->forceRecord(84, 72.9));
|
EXPECT_TRUE(tu4->forceRecord(84, 72.9));
|
||||||
res84.insert(72.9);
|
|
||||||
EXPECT_EQ(tu4->count(), tu4Size += 1);
|
EXPECT_EQ(tu4->count(), tu4Size += 1);
|
||||||
EXPECT_EQ(res84.count(tu4->getRecord(84)), 1);
|
EXPECT_EQ(tu4->getRecord(84), 2879.654);
|
||||||
|
|
||||||
EXPECT_TRUE(tu4->forceRecord(84, 2679.5));
|
EXPECT_TRUE(tu4->forceRecord(84, 2679.5));
|
||||||
res84.insert(2679.5);
|
|
||||||
EXPECT_EQ(tu4->count(), tu4Size += 1);
|
EXPECT_EQ(tu4->count(), tu4Size += 1);
|
||||||
EXPECT_EQ(res84.count(tu4->getRecord(84)), 1);
|
EXPECT_EQ(tu4->getRecord(84), 2679.5);
|
||||||
|
|
||||||
EXPECT_FALSE(tu4->forceRecord(84, -359.109));
|
EXPECT_FALSE(tu4->forceRecord(84, -359.109));
|
||||||
EXPECT_EQ(tu4->count(), tu4Size);
|
EXPECT_EQ(tu4->count(), tu4Size);
|
||||||
|
|
||||||
@ -310,7 +286,6 @@ TEST_F(DuplicatesTest, Changing) {
|
|||||||
EXPECT_THROW(tu2->changeRecord("jeremy spins", -7), LMDBAL::Exist);
|
EXPECT_THROW(tu2->changeRecord("jeremy spins", -7), LMDBAL::Exist);
|
||||||
|
|
||||||
LMDBAL::SizeType tu3Size = tu3->count();
|
LMDBAL::SizeType tu3Size = tu3->count();
|
||||||
std::set<float> res26;
|
|
||||||
EXPECT_THROW(tu3->changeRecord(26.7, 68.22), LMDBAL::NotFound);
|
EXPECT_THROW(tu3->changeRecord(26.7, 68.22), LMDBAL::NotFound);
|
||||||
EXPECT_EQ(tu3->count(), tu3Size);
|
EXPECT_EQ(tu3->count(), tu3Size);
|
||||||
tu3->addRecord(26.7, 68.22);
|
tu3->addRecord(26.7, 68.22);
|
||||||
@ -319,13 +294,11 @@ TEST_F(DuplicatesTest, Changing) {
|
|||||||
tu3->changeRecord(26.7, 68.22); //should just do nothing usefull, but work normally
|
tu3->changeRecord(26.7, 68.22); //should just do nothing usefull, but work normally
|
||||||
EXPECT_EQ(tu3->getRecord(26.7), 68.22f);
|
EXPECT_EQ(tu3->getRecord(26.7), 68.22f);
|
||||||
tu3->changeRecord(26.7, 23.18);
|
tu3->changeRecord(26.7, 23.18);
|
||||||
res26.insert(23.18);
|
|
||||||
EXPECT_EQ(tu3->count(), tu3Size);
|
EXPECT_EQ(tu3->count(), tu3Size);
|
||||||
EXPECT_EQ(tu3->getRecord(26.7), 23.18f);
|
EXPECT_EQ(tu3->getRecord(26.7), 23.18f);
|
||||||
tu3->addRecord(26.7, 22.16);
|
tu3->addRecord(26.7, 22.16);
|
||||||
res26.insert(22.16);
|
|
||||||
EXPECT_EQ(tu3->count(), tu3Size += 1);
|
EXPECT_EQ(tu3->count(), tu3Size += 1);
|
||||||
EXPECT_EQ(res26.count(tu3->getRecord(26.7)), 1);
|
EXPECT_EQ(tu3->getRecord(26.7), 23.18f);
|
||||||
tu3->changeRecord(26.7, 21.7);
|
tu3->changeRecord(26.7, 21.7);
|
||||||
EXPECT_EQ(tu3->count(), tu3Size);
|
EXPECT_EQ(tu3->count(), tu3Size);
|
||||||
EXPECT_EQ(tu3->getRecord(26.7), 21.7f);
|
EXPECT_EQ(tu3->getRecord(26.7), 21.7f);
|
||||||
@ -343,21 +316,17 @@ TEST_F(DuplicatesTest, Changing) {
|
|||||||
tu4->changeRecord(852, 6795.349); //should just do nothing usefull, but work normally
|
tu4->changeRecord(852, 6795.349); //should just do nothing usefull, but work normally
|
||||||
EXPECT_EQ(tu4->getRecord(852), 6795.349);
|
EXPECT_EQ(tu4->getRecord(852), 6795.349);
|
||||||
tu4->changeRecord(852, 13.54);
|
tu4->changeRecord(852, 13.54);
|
||||||
std::set<double> res852({13.54});
|
|
||||||
EXPECT_EQ(tu4->count(), tu4Size);
|
EXPECT_EQ(tu4->count(), tu4Size);
|
||||||
EXPECT_EQ(tu4->getRecord(852), 13.54);
|
EXPECT_EQ(tu4->getRecord(852), 13.54);
|
||||||
tu4->addRecord(852, 213.85);
|
tu4->addRecord(852, 213.85);
|
||||||
res852.insert(213.85);
|
|
||||||
EXPECT_EQ(tu4->count(), tu4Size += 1);
|
EXPECT_EQ(tu4->count(), tu4Size += 1);
|
||||||
EXPECT_EQ(res852.count(tu4->getRecord(852)), 1);
|
EXPECT_EQ(tu4->getRecord(852), 13.54);
|
||||||
tu4->changeRecord(852, 236.21);
|
tu4->changeRecord(852, 236.21);
|
||||||
res852.insert(236.21);
|
|
||||||
EXPECT_EQ(tu4->count(), tu4Size);
|
EXPECT_EQ(tu4->count(), tu4Size);
|
||||||
EXPECT_EQ(tu4->getRecord(852), 236.21);
|
EXPECT_EQ(tu4->getRecord(852), 236.21);
|
||||||
tu4->changeRecord(852, 46324.1135);
|
tu4->changeRecord(852, 46324.1135);
|
||||||
res852.insert(46324.1135);
|
|
||||||
EXPECT_EQ(tu4->count(), tu4Size);
|
EXPECT_EQ(tu4->count(), tu4Size);
|
||||||
EXPECT_EQ(res852.count(tu4->getRecord(852)), 1);
|
EXPECT_EQ(tu4->getRecord(852), 213.85);
|
||||||
EXPECT_THROW(tu4->changeRecord(852, 46324.1135), LMDBAL::Exist);
|
EXPECT_THROW(tu4->changeRecord(852, 46324.1135), LMDBAL::Exist);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,15 +337,15 @@ TEST_F(DuplicatesTest, GettingAllRecords) {
|
|||||||
|
|
||||||
std::map<int16_t, uint16_t> m1;
|
std::map<int16_t, uint16_t> m1;
|
||||||
std::set<int16_t> k1;
|
std::set<int16_t> k1;
|
||||||
LMDBAL::Cursor<int16_t, uint16_t> c1 = tu1->createCursor();
|
LMDBAL::Cursor<int16_t, uint16_t>* c1 = tu1->createCursor();
|
||||||
tu1->readAll(m1, txn);
|
tu1->readAll(m1, txn);
|
||||||
c1.open(txn);
|
c1->open(txn);
|
||||||
|
|
||||||
cycle = false;
|
cycle = false;
|
||||||
iterations = 0;
|
iterations = 0;
|
||||||
do {
|
do {
|
||||||
try {
|
try {
|
||||||
std::pair<int16_t, uint16_t> pair = c1.next();
|
std::pair<int16_t, uint16_t> pair = c1->next();
|
||||||
cycle = true;
|
cycle = true;
|
||||||
std::pair<std::set<int16_t>::const_iterator, bool> probe = k1.insert(pair.first);
|
std::pair<std::set<int16_t>::const_iterator, bool> probe = k1.insert(pair.first);
|
||||||
if (probe.second) {
|
if (probe.second) {
|
||||||
@ -390,25 +359,25 @@ TEST_F(DuplicatesTest, GettingAllRecords) {
|
|||||||
cycle = false;
|
cycle = false;
|
||||||
}
|
}
|
||||||
} while (cycle);
|
} while (cycle);
|
||||||
|
tu1->destroyCursor(c1);
|
||||||
|
|
||||||
EXPECT_EQ(iterations, tu1->count(txn));
|
EXPECT_EQ(iterations, tu1->count(txn));
|
||||||
EXPECT_EQ(k1.size(), m1.size());
|
EXPECT_EQ(k1.size(), m1.size());
|
||||||
EXPECT_NE(iterations, 0);
|
EXPECT_NE(iterations, 0);
|
||||||
EXPECT_NE(k1.size(), 0);
|
EXPECT_NE(k1.size(), 0);
|
||||||
c1.drop();
|
|
||||||
|
|
||||||
|
|
||||||
std::map<std::string, int8_t> m2;
|
std::map<std::string, int8_t> m2;
|
||||||
std::set<std::string> k2;
|
std::set<std::string> k2;
|
||||||
LMDBAL::Cursor<std::string, int8_t> c2 = tu2->createCursor();
|
LMDBAL::Cursor<std::string, int8_t>* c2 = tu2->createCursor();
|
||||||
tu2->readAll(m2, txn);
|
tu2->readAll(m2, txn);
|
||||||
c2.open(txn);
|
c2->open(txn);
|
||||||
|
|
||||||
cycle = false;
|
cycle = false;
|
||||||
iterations = 0;
|
iterations = 0;
|
||||||
do {
|
do {
|
||||||
try {
|
try {
|
||||||
std::pair<std::string, int8_t> pair = c2.next();
|
std::pair<std::string, int8_t> pair = c2->next();
|
||||||
cycle = true;
|
cycle = true;
|
||||||
std::pair<std::set<std::string>::const_iterator, bool> probe = k2.insert(pair.first);
|
std::pair<std::set<std::string>::const_iterator, bool> probe = k2.insert(pair.first);
|
||||||
if (probe.second) {
|
if (probe.second) {
|
||||||
@ -422,25 +391,25 @@ TEST_F(DuplicatesTest, GettingAllRecords) {
|
|||||||
cycle = false;
|
cycle = false;
|
||||||
}
|
}
|
||||||
} while (cycle);
|
} while (cycle);
|
||||||
|
tu2->destroyCursor(c2);
|
||||||
|
|
||||||
EXPECT_EQ(iterations, tu2->count(txn));
|
EXPECT_EQ(iterations, tu2->count(txn));
|
||||||
EXPECT_EQ(k2.size(), m2.size());
|
EXPECT_EQ(k2.size(), m2.size());
|
||||||
EXPECT_NE(iterations, 0);
|
EXPECT_NE(iterations, 0);
|
||||||
EXPECT_NE(k2.size(), 0);
|
EXPECT_NE(k2.size(), 0);
|
||||||
c2.drop();
|
|
||||||
|
|
||||||
|
|
||||||
std::map<float, float> m3;
|
std::map<float, float> m3;
|
||||||
std::set<float> k3;
|
std::set<float> k3;
|
||||||
LMDBAL::Cursor<float, float> c3 = tu3->createCursor();
|
LMDBAL::Cursor<float, float>* c3 = tu3->createCursor();
|
||||||
tu3->readAll(m3, txn);
|
tu3->readAll(m3, txn);
|
||||||
c3.open(txn);
|
c3->open(txn);
|
||||||
|
|
||||||
cycle = false;
|
cycle = false;
|
||||||
iterations = 0;
|
iterations = 0;
|
||||||
do {
|
do {
|
||||||
try {
|
try {
|
||||||
std::pair<float, float> pair = c3.next();
|
std::pair<float, float> pair = c3->next();
|
||||||
cycle = true;
|
cycle = true;
|
||||||
std::pair<std::set<float>::const_iterator, bool> probe = k3.insert(pair.first);
|
std::pair<std::set<float>::const_iterator, bool> probe = k3.insert(pair.first);
|
||||||
if (probe.second) {
|
if (probe.second) {
|
||||||
@ -454,25 +423,25 @@ TEST_F(DuplicatesTest, GettingAllRecords) {
|
|||||||
cycle = false;
|
cycle = false;
|
||||||
}
|
}
|
||||||
} while (cycle);
|
} while (cycle);
|
||||||
|
tu3->destroyCursor(c3);
|
||||||
|
|
||||||
EXPECT_EQ(iterations, tu3->count(txn));
|
EXPECT_EQ(iterations, tu3->count(txn));
|
||||||
EXPECT_EQ(k3.size(), m3.size());
|
EXPECT_EQ(k3.size(), m3.size());
|
||||||
EXPECT_NE(iterations, 0);
|
EXPECT_NE(iterations, 0);
|
||||||
EXPECT_NE(k3.size(), 0);
|
EXPECT_NE(k3.size(), 0);
|
||||||
c3.drop();
|
|
||||||
|
|
||||||
|
|
||||||
std::map<uint16_t, double> m4;
|
std::map<uint16_t, double> m4;
|
||||||
std::set<uint16_t> k4;
|
std::set<uint16_t> k4;
|
||||||
LMDBAL::Cursor<uint16_t, double> c4 = tu4->createCursor();
|
LMDBAL::Cursor<uint16_t, double>* c4 = tu4->createCursor();
|
||||||
tu4->readAll(m4, txn);
|
tu4->readAll(m4, txn);
|
||||||
c4.open(txn);
|
c4->open(txn);
|
||||||
|
|
||||||
cycle = false;
|
cycle = false;
|
||||||
iterations = 0;
|
iterations = 0;
|
||||||
do {
|
do {
|
||||||
try {
|
try {
|
||||||
std::pair<uint16_t, double> pair = c4.next();
|
std::pair<uint16_t, double> pair = c4->next();
|
||||||
cycle = true;
|
cycle = true;
|
||||||
std::pair<std::set<uint16_t>::const_iterator, bool> probe = k4.insert(pair.first);
|
std::pair<std::set<uint16_t>::const_iterator, bool> probe = k4.insert(pair.first);
|
||||||
if (probe.second) {
|
if (probe.second) {
|
||||||
@ -486,7 +455,7 @@ TEST_F(DuplicatesTest, GettingAllRecords) {
|
|||||||
cycle = false;
|
cycle = false;
|
||||||
}
|
}
|
||||||
} while (cycle);
|
} while (cycle);
|
||||||
c4.drop();
|
tu4->destroyCursor(c4);
|
||||||
|
|
||||||
EXPECT_EQ(iterations, tu4->count(txn));
|
EXPECT_EQ(iterations, tu4->count(txn));
|
||||||
EXPECT_EQ(k4.size(), m4.size());
|
EXPECT_EQ(k4.size(), m4.size());
|
||||||
|
@ -22,21 +22,19 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int getTableCursorsSize() const {
|
|
||||||
return table->cursors.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void TearDownTestSuite() {
|
static void TearDownTestSuite() {
|
||||||
cursor.drop();
|
|
||||||
transaction.terminate();
|
transaction.terminate();
|
||||||
db->close();
|
db->close();
|
||||||
db->removeDirectory();
|
db->removeDirectory();
|
||||||
delete db;
|
delete db;
|
||||||
db = nullptr;
|
db = nullptr;
|
||||||
|
cursor = nullptr;
|
||||||
|
emptyCursor = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static LMDBAL::Base* db;
|
static LMDBAL::Base* db;
|
||||||
static LMDBAL::Cursor<uint64_t, std::string> cursor;
|
static LMDBAL::Cursor<uint64_t, std::string>* cursor;
|
||||||
|
static LMDBAL::Cursor<uint64_t, std::string>* emptyCursor;
|
||||||
static LMDBAL::Transaction transaction;
|
static LMDBAL::Transaction transaction;
|
||||||
|
|
||||||
LMDBAL::Storage<uint64_t, std::string>* table;
|
LMDBAL::Storage<uint64_t, std::string>* table;
|
||||||
@ -44,7 +42,8 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
LMDBAL::Base* StorageCursorTest::db = nullptr;
|
LMDBAL::Base* StorageCursorTest::db = nullptr;
|
||||||
LMDBAL::Cursor<uint64_t, std::string> StorageCursorTest::cursor;
|
LMDBAL::Cursor<uint64_t, std::string>* StorageCursorTest::cursor = nullptr;
|
||||||
|
LMDBAL::Cursor<uint64_t, std::string>* StorageCursorTest::emptyCursor = nullptr;
|
||||||
LMDBAL::Transaction StorageCursorTest::transaction = LMDBAL::Transaction();
|
LMDBAL::Transaction StorageCursorTest::transaction = LMDBAL::Transaction();
|
||||||
|
|
||||||
static const std::map<uint64_t, std::string> data({
|
static const std::map<uint64_t, std::string> data({
|
||||||
@ -66,22 +65,20 @@ TEST_F(StorageCursorTest, PopulatingTheTable) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StorageCursorTest, Creation) {
|
TEST_F(StorageCursorTest, Creation) {
|
||||||
EXPECT_EQ(getTableCursorsSize(), 0);
|
|
||||||
cursor = table->createCursor();
|
cursor = table->createCursor();
|
||||||
EXPECT_EQ(getTableCursorsSize(), 1);
|
emptyCursor = emptyTable->createCursor();
|
||||||
|
|
||||||
EXPECT_THROW(cursor.first(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor->first(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor.last(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor->last(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor.next(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor->next(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor.prev(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor->prev(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor.current(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor->current(), LMDBAL::CursorNotReady);
|
||||||
|
|
||||||
cursor.open();
|
cursor->open();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StorageCursorTest, FirstPrivate) {
|
TEST_F(StorageCursorTest, FirstPrivate) {
|
||||||
EXPECT_EQ(getTableCursorsSize(), 1);
|
std::pair<uint64_t, std::string> element = cursor->first();
|
||||||
std::pair<uint64_t, std::string> element = cursor.first();
|
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -89,19 +86,18 @@ TEST_F(StorageCursorTest, FirstPrivate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StorageCursorTest, NextPrivate) {
|
TEST_F(StorageCursorTest, NextPrivate) {
|
||||||
EXPECT_EQ(getTableCursorsSize(), 1);
|
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
||||||
|
|
||||||
reference++;
|
reference++;
|
||||||
for (; reference != data.end(); ++reference) {
|
for (; reference != data.end(); ++reference) {
|
||||||
std::pair<uint64_t, std::string> element = cursor.next();
|
std::pair<uint64_t, std::string> element = cursor->next();
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_THROW(cursor.next(), LMDBAL::NotFound);
|
EXPECT_THROW(cursor->next(), LMDBAL::NotFound);
|
||||||
|
|
||||||
std::pair<uint64_t, std::string> element = cursor.first();
|
std::pair<uint64_t, std::string> element = cursor->first();
|
||||||
reference = data.begin();
|
reference = data.begin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -109,8 +105,7 @@ TEST_F(StorageCursorTest, NextPrivate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StorageCursorTest, LastPrivate) {
|
TEST_F(StorageCursorTest, LastPrivate) {
|
||||||
EXPECT_EQ(getTableCursorsSize(), 1);
|
std::pair<uint64_t, std::string> element = cursor->last();
|
||||||
std::pair<uint64_t, std::string> element = cursor.last();
|
|
||||||
std::map<uint64_t, std::string>::const_reverse_iterator reference = data.rbegin();
|
std::map<uint64_t, std::string>::const_reverse_iterator reference = data.rbegin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -118,19 +113,18 @@ TEST_F(StorageCursorTest, LastPrivate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StorageCursorTest, PrevPrivate) {
|
TEST_F(StorageCursorTest, PrevPrivate) {
|
||||||
EXPECT_EQ(getTableCursorsSize(), 1);
|
|
||||||
std::map<uint64_t, std::string>::const_reverse_iterator reference = data.rbegin();
|
std::map<uint64_t, std::string>::const_reverse_iterator reference = data.rbegin();
|
||||||
|
|
||||||
reference++;
|
reference++;
|
||||||
for (; reference != data.rend(); ++reference) {
|
for (; reference != data.rend(); ++reference) {
|
||||||
std::pair<uint64_t, std::string> element = cursor.prev();
|
std::pair<uint64_t, std::string> element = cursor->prev();
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_THROW(cursor.prev(), LMDBAL::NotFound);
|
EXPECT_THROW(cursor->prev(), LMDBAL::NotFound);
|
||||||
|
|
||||||
std::pair<uint64_t, std::string> element = cursor.last();
|
std::pair<uint64_t, std::string> element = cursor->last();
|
||||||
reference = data.rbegin();
|
reference = data.rbegin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -138,29 +132,28 @@ TEST_F(StorageCursorTest, PrevPrivate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StorageCursorTest, CurrentPrivate) {
|
TEST_F(StorageCursorTest, CurrentPrivate) {
|
||||||
EXPECT_EQ(getTableCursorsSize(), 1);
|
std::pair<uint64_t, std::string> element = cursor->first();
|
||||||
std::pair<uint64_t, std::string> element = cursor.first();
|
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
|
|
||||||
element = cursor.current();
|
element = cursor->current();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
|
|
||||||
cursor.next();
|
cursor->next();
|
||||||
element = cursor.current();
|
element = cursor->current();
|
||||||
++reference;
|
++reference;
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
|
|
||||||
cursor.next();
|
cursor->next();
|
||||||
cursor.next();
|
cursor->next();
|
||||||
cursor.prev();
|
cursor->prev();
|
||||||
element = cursor.current();
|
element = cursor->current();
|
||||||
++reference;
|
++reference;
|
||||||
++reference;
|
++reference;
|
||||||
--reference;
|
--reference;
|
||||||
@ -169,62 +162,26 @@ TEST_F(StorageCursorTest, CurrentPrivate) {
|
|||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StorageCursorTest, SettingPrivate) {
|
|
||||||
EXPECT_EQ(getTableCursorsSize(), 1);
|
|
||||||
|
|
||||||
EXPECT_FALSE(cursor.set(6684));
|
|
||||||
EXPECT_EQ(cursor.current().second, "tanned inmate");
|
|
||||||
|
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
|
||||||
std::advance(reference, 5);
|
|
||||||
EXPECT_TRUE(cursor.set(reference->first));
|
|
||||||
EXPECT_EQ(cursor.current().second, reference->second);
|
|
||||||
|
|
||||||
++reference;
|
|
||||||
cursor.next();
|
|
||||||
EXPECT_EQ(cursor.current().second, reference->second);
|
|
||||||
|
|
||||||
++reference;
|
|
||||||
cursor.next();
|
|
||||||
EXPECT_EQ(cursor.current().second, reference->second);
|
|
||||||
|
|
||||||
--reference;
|
|
||||||
cursor.prev();
|
|
||||||
EXPECT_EQ(cursor.current().second, reference->second);
|
|
||||||
|
|
||||||
--reference;
|
|
||||||
cursor.prev();
|
|
||||||
EXPECT_EQ(cursor.current().second, reference->second);
|
|
||||||
|
|
||||||
--reference;
|
|
||||||
cursor.prev();
|
|
||||||
EXPECT_EQ(cursor.current().second, reference->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(StorageCursorTest, Destruction) {
|
TEST_F(StorageCursorTest, Destruction) {
|
||||||
EXPECT_EQ(getTableCursorsSize(), 1);
|
cursor->close();
|
||||||
cursor.close();
|
|
||||||
EXPECT_EQ(getTableCursorsSize(), 1);
|
|
||||||
|
|
||||||
EXPECT_THROW(cursor.first(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor->first(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor.last(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor->last(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor.next(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor->next(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor.prev(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor->prev(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor.current(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor->current(), LMDBAL::CursorNotReady);
|
||||||
|
|
||||||
cursor = LMDBAL::Cursor<uint64_t, std::string>();
|
EXPECT_THROW(emptyTable->destroyCursor(cursor), LMDBAL::Unknown);
|
||||||
EXPECT_EQ(getTableCursorsSize(), 0);
|
table->destroyCursor(cursor);
|
||||||
|
|
||||||
cursor = table->createCursor();
|
cursor = table->createCursor();
|
||||||
EXPECT_EQ(getTableCursorsSize(), 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StorageCursorTest, FirstPublic) {
|
TEST_F(StorageCursorTest, FirstPublic) {
|
||||||
EXPECT_EQ(getTableCursorsSize(), 1);
|
|
||||||
transaction = db->beginReadOnlyTransaction();
|
transaction = db->beginReadOnlyTransaction();
|
||||||
|
|
||||||
cursor.open(transaction);
|
cursor->open(transaction);
|
||||||
std::pair<uint64_t, std::string> element = cursor.first();
|
std::pair<uint64_t, std::string> element = cursor->first();
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -232,19 +189,18 @@ TEST_F(StorageCursorTest, FirstPublic) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StorageCursorTest, NextPublic) {
|
TEST_F(StorageCursorTest, NextPublic) {
|
||||||
EXPECT_EQ(getTableCursorsSize(), 1);
|
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
||||||
|
|
||||||
reference++;
|
reference++;
|
||||||
for (; reference != data.end(); ++reference) {
|
for (; reference != data.end(); ++reference) {
|
||||||
std::pair<uint64_t, std::string> element = cursor.next();
|
std::pair<uint64_t, std::string> element = cursor->next();
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_THROW(cursor.next(), LMDBAL::NotFound);
|
EXPECT_THROW(cursor->next(), LMDBAL::NotFound);
|
||||||
|
|
||||||
std::pair<uint64_t, std::string> element = cursor.first();
|
std::pair<uint64_t, std::string> element = cursor->first();
|
||||||
reference = data.begin();
|
reference = data.begin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -252,8 +208,7 @@ TEST_F(StorageCursorTest, NextPublic) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StorageCursorTest, LastPublic) {
|
TEST_F(StorageCursorTest, LastPublic) {
|
||||||
EXPECT_EQ(getTableCursorsSize(), 1);
|
std::pair<uint64_t, std::string> element = cursor->last();
|
||||||
std::pair<uint64_t, std::string> element = cursor.last();
|
|
||||||
std::map<uint64_t, std::string>::const_reverse_iterator reference = data.rbegin();
|
std::map<uint64_t, std::string>::const_reverse_iterator reference = data.rbegin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -261,19 +216,18 @@ TEST_F(StorageCursorTest, LastPublic) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StorageCursorTest, PrevPublic) {
|
TEST_F(StorageCursorTest, PrevPublic) {
|
||||||
EXPECT_EQ(getTableCursorsSize(), 1);
|
|
||||||
std::map<uint64_t, std::string>::const_reverse_iterator reference = data.rbegin();
|
std::map<uint64_t, std::string>::const_reverse_iterator reference = data.rbegin();
|
||||||
|
|
||||||
reference++;
|
reference++;
|
||||||
for (; reference != data.rend(); ++reference) {
|
for (; reference != data.rend(); ++reference) {
|
||||||
std::pair<uint64_t, std::string> element = cursor.prev();
|
std::pair<uint64_t, std::string> element = cursor->prev();
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_THROW(cursor.prev(), LMDBAL::NotFound);
|
EXPECT_THROW(cursor->prev(), LMDBAL::NotFound);
|
||||||
|
|
||||||
std::pair<uint64_t, std::string> element = cursor.last();
|
std::pair<uint64_t, std::string> element = cursor->last();
|
||||||
reference = data.rbegin();
|
reference = data.rbegin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -281,29 +235,28 @@ TEST_F(StorageCursorTest, PrevPublic) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StorageCursorTest, CurrentPublic) {
|
TEST_F(StorageCursorTest, CurrentPublic) {
|
||||||
EXPECT_EQ(getTableCursorsSize(), 1);
|
std::pair<uint64_t, std::string> element = cursor->first();
|
||||||
std::pair<uint64_t, std::string> element = cursor.first();
|
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
|
|
||||||
element = cursor.current();
|
element = cursor->current();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
|
|
||||||
cursor.next();
|
cursor->next();
|
||||||
element = cursor.current();
|
element = cursor->current();
|
||||||
++reference;
|
++reference;
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
|
|
||||||
cursor.next();
|
cursor->next();
|
||||||
cursor.next();
|
cursor->next();
|
||||||
cursor.prev();
|
cursor->prev();
|
||||||
element = cursor.current();
|
element = cursor->current();
|
||||||
++reference;
|
++reference;
|
||||||
++reference;
|
++reference;
|
||||||
--reference;
|
--reference;
|
||||||
@ -312,106 +265,39 @@ TEST_F(StorageCursorTest, CurrentPublic) {
|
|||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StorageCursorTest, SettingPublic) {
|
|
||||||
EXPECT_EQ(getTableCursorsSize(), 1);
|
|
||||||
|
|
||||||
EXPECT_FALSE(cursor.set(557));
|
|
||||||
EXPECT_EQ(cursor.current().second, "resilent pick forefront");
|
|
||||||
|
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
|
||||||
std::advance(reference, 3);
|
|
||||||
EXPECT_TRUE(cursor.set(reference->first));
|
|
||||||
EXPECT_EQ(cursor.current().second, reference->second);
|
|
||||||
|
|
||||||
++reference;
|
|
||||||
cursor.next();
|
|
||||||
EXPECT_EQ(cursor.current().second, reference->second);
|
|
||||||
|
|
||||||
++reference;
|
|
||||||
cursor.next();
|
|
||||||
EXPECT_EQ(cursor.current().second, reference->second);
|
|
||||||
|
|
||||||
--reference;
|
|
||||||
cursor.prev();
|
|
||||||
EXPECT_EQ(cursor.current().second, reference->second);
|
|
||||||
|
|
||||||
--reference;
|
|
||||||
cursor.prev();
|
|
||||||
EXPECT_EQ(cursor.current().second, reference->second);
|
|
||||||
|
|
||||||
--reference;
|
|
||||||
cursor.prev();
|
|
||||||
EXPECT_EQ(cursor.current().second, reference->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(StorageCursorTest, CursorRAIIBehaviour) {
|
|
||||||
int initialiCursorsAmount = getTableCursorsSize();
|
|
||||||
{
|
|
||||||
LMDBAL::Cursor<uint64_t, std::string> cur = table->createCursor();
|
|
||||||
EXPECT_EQ(initialiCursorsAmount + 1, getTableCursorsSize());
|
|
||||||
cur.open(transaction);
|
|
||||||
EXPECT_NO_THROW(cur.first());
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPECT_EQ(initialiCursorsAmount, getTableCursorsSize());
|
|
||||||
LMDBAL::Cursor<uint64_t, std::string> cur;
|
|
||||||
EXPECT_EQ(initialiCursorsAmount, getTableCursorsSize());
|
|
||||||
EXPECT_EQ(cur.empty(), true);
|
|
||||||
cur = table->createCursor();
|
|
||||||
EXPECT_EQ(cur.empty(), false);
|
|
||||||
EXPECT_EQ(initialiCursorsAmount + 1, getTableCursorsSize());
|
|
||||||
EXPECT_THROW(emptyTable->destroyCursor(cur), LMDBAL::Unknown);
|
|
||||||
table->destroyCursor(cur);
|
|
||||||
EXPECT_EQ(cur.empty(), true);
|
|
||||||
EXPECT_EQ(initialiCursorsAmount, getTableCursorsSize());
|
|
||||||
|
|
||||||
cur = table->createCursor();
|
|
||||||
EXPECT_EQ(initialiCursorsAmount + 1, getTableCursorsSize());
|
|
||||||
EXPECT_EQ(cur.empty(), false);
|
|
||||||
|
|
||||||
cur.drop();
|
|
||||||
EXPECT_EQ(cur.empty(), true);
|
|
||||||
EXPECT_EQ(initialiCursorsAmount, getTableCursorsSize());
|
|
||||||
|
|
||||||
EXPECT_NO_THROW(cur.drop());
|
|
||||||
EXPECT_THROW(table->destroyCursor(cur), LMDBAL::Unknown);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(StorageCursorTest, CornerCases) {
|
TEST_F(StorageCursorTest, CornerCases) {
|
||||||
EXPECT_EQ(getTableCursorsSize(), 1);
|
|
||||||
transaction.terminate();
|
transaction.terminate();
|
||||||
EXPECT_THROW(cursor.current(), LMDBAL::Unknown);
|
EXPECT_THROW(cursor->current(), LMDBAL::Unknown);
|
||||||
cursor.close();
|
cursor->close();
|
||||||
|
|
||||||
LMDBAL::Cursor<uint64_t, std::string> emptyCursor = emptyTable->createCursor();
|
emptyCursor->open();
|
||||||
emptyCursor.open();
|
EXPECT_THROW(emptyCursor->first(), LMDBAL::NotFound);
|
||||||
EXPECT_THROW(emptyCursor.first(), LMDBAL::NotFound);
|
EXPECT_THROW(emptyCursor->last(), LMDBAL::NotFound);
|
||||||
EXPECT_THROW(emptyCursor.last(), LMDBAL::NotFound);
|
EXPECT_THROW(emptyCursor->next(), LMDBAL::NotFound);
|
||||||
EXPECT_THROW(emptyCursor.next(), LMDBAL::NotFound);
|
EXPECT_THROW(emptyCursor->prev(), LMDBAL::NotFound);
|
||||||
EXPECT_THROW(emptyCursor.prev(), LMDBAL::NotFound);
|
EXPECT_THROW(emptyCursor->current(), LMDBAL::Unknown);
|
||||||
EXPECT_THROW(emptyCursor.current(), LMDBAL::Unknown);
|
emptyCursor->close();
|
||||||
emptyCursor.close();
|
|
||||||
|
|
||||||
cursor.open();
|
cursor->open();
|
||||||
EXPECT_THROW(cursor.current(), LMDBAL::Unknown); //yeah, nice thing to write in the doc
|
EXPECT_THROW(cursor->current(), LMDBAL::Unknown); //yeah, nice thing to write in the doc
|
||||||
|
|
||||||
std::map<uint64_t, std::string>::const_reverse_iterator breference = data.rbegin();
|
std::map<uint64_t, std::string>::const_reverse_iterator breference = data.rbegin();
|
||||||
std::pair<uint64_t, std::string> element(cursor.prev());
|
std::pair<uint64_t, std::string> element(cursor->prev());
|
||||||
EXPECT_EQ(element.first, breference->first); //nice thing to write in the doc, again!
|
EXPECT_EQ(element.first, breference->first); //nice thing to write in the doc, again!
|
||||||
EXPECT_EQ(element.second, breference->second);
|
EXPECT_EQ(element.second, breference->second);
|
||||||
element = cursor.current();
|
element = cursor->current();
|
||||||
EXPECT_EQ(element.first, breference->first);
|
EXPECT_EQ(element.first, breference->first);
|
||||||
EXPECT_EQ(element.second, breference->second);
|
EXPECT_EQ(element.second, breference->second);
|
||||||
EXPECT_THROW(cursor.next(), LMDBAL::NotFound);
|
EXPECT_THROW(cursor->next(), LMDBAL::NotFound);
|
||||||
cursor.close();
|
cursor->close();
|
||||||
|
|
||||||
cursor.open();
|
cursor->open();
|
||||||
element = cursor.next();
|
element = cursor->next();
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
element = cursor.current();
|
element = cursor->current();
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
EXPECT_THROW(cursor.prev(), LMDBAL::NotFound);
|
EXPECT_THROW(cursor->prev(), LMDBAL::NotFound);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user