Merge lp:~jamesh/thumbnailer/landing-20150622 into lp:thumbnailer

Proposed by James Henstridge
Status: Merged
Approved by: Michi Henning
Approved revision: 131
Merged at revision: 122
Proposed branch: lp:~jamesh/thumbnailer/landing-20150622
Merge into: lp:thumbnailer
Diff against target: 30725 lines (+25175/-3830)
203 files modified
CMakeLists.txt (+105/-31)
COPYING.GPL (+674/-0)
CTestCustom.cmake.in (+17/-0)
HACKING (+121/-0)
cmake/coverage.cmake (+0/-34)
data/CMakeLists.txt (+0/-1)
data/com.canonical.Unity.Thumbnailer.gschema.xml (+67/-0)
debian/changelog (+49/-0)
debian/control (+13/-28)
debian/copyright (+22/-2)
debian/libthumbnailer-dev.install (+0/-3)
debian/libthumbnailer0.install (+0/-2)
debian/libthumbnailer0.symbols (+0/-7)
debian/rules (+3/-0)
debian/thumbnailer-service.install (+2/-0)
include/CMakeLists.txt (+0/-11)
include/core/cache_codec.h (+50/-0)
include/core/cache_discard_policy.h (+41/-0)
include/core/cache_events.h (+103/-0)
include/core/internal/cache_event_indexes.h (+46/-0)
include/core/internal/persistent_string_cache_impl.h (+191/-0)
include/core/internal/persistent_string_cache_stats.h (+237/-0)
include/core/optional.h (+35/-0)
include/core/persistent_cache.h (+3104/-0)
include/core/persistent_cache_stats.h (+230/-0)
include/core/persistent_string_cache.h (+730/-0)
include/internal/artdownloader.h (+44/-16)
include/internal/artreply.h (+60/-0)
include/internal/audioimageextractor.h (+0/-41)
include/internal/check_access.h (+42/-0)
include/internal/config.h.in (+4/-7)
include/internal/file_io.h (+51/-0)
include/internal/gobj_memory.h (+170/-65)
include/internal/httpdownloader.h (+25/-13)
include/internal/image.h (+82/-0)
include/internal/imageextractor.h (+59/-22)
include/internal/imagescaler.h (+0/-55)
include/internal/lastfmdownloader.h (+0/-45)
include/internal/make_directories.h (+44/-0)
include/internal/mediaartcache.h (+0/-61)
include/internal/raii.h (+55/-0)
include/internal/safe_strerror.h (+38/-0)
include/internal/settings.h (+72/-0)
include/internal/soupdownloader.h (+0/-40)
include/internal/thumbnailcache.h (+0/-50)
include/internal/thumbnailer.h (+128/-47)
include/internal/trace.h (+45/-0)
include/internal/ubuntuserverdownloader.h (+49/-21)
include/service/dbus_names.h (+40/-0)
include/thumbnailer.pc.in (+0/-10)
plugins/Ubuntu/Thumbnailer.0.1/CMakeLists.txt (+11/-2)
plugins/Ubuntu/Thumbnailer.0.1/albumartgenerator.cpp (+56/-52)
plugins/Ubuntu/Thumbnailer.0.1/albumartgenerator.h (+15/-8)
plugins/Ubuntu/Thumbnailer.0.1/artgeneratorcommon.cpp (+45/-19)
plugins/Ubuntu/Thumbnailer.0.1/artgeneratorcommon.h (+12/-6)
plugins/Ubuntu/Thumbnailer.0.1/artistartgenerator.cpp (+56/-52)
plugins/Ubuntu/Thumbnailer.0.1/artistartgenerator.h (+18/-11)
plugins/Ubuntu/Thumbnailer.0.1/plugin.cpp (+65/-24)
plugins/Ubuntu/Thumbnailer.0.1/plugin.h (+14/-7)
plugins/Ubuntu/Thumbnailer.0.1/thumbnailerimageresponse.cpp (+117/-0)
plugins/Ubuntu/Thumbnailer.0.1/thumbnailerimageresponse.h (+68/-0)
plugins/Ubuntu/Thumbnailer.0.1/thumbnailgenerator.cpp (+77/-77)
plugins/Ubuntu/Thumbnailer.0.1/thumbnailgenerator.h (+25/-16)
src/CMakeLists.txt (+43/-36)
src/artdownloader.cpp (+40/-0)
src/audioimageextractor.cpp (+0/-58)
src/check_access.cpp (+83/-0)
src/core/CMakeLists.txt (+13/-0)
src/core/internal/CMakeLists.txt (+5/-0)
src/core/internal/persistent_string_cache_impl.cpp (+1649/-0)
src/core/persistent_cache_stats.cpp (+219/-0)
src/core/persistent_string_cache.cpp (+239/-0)
src/file_io.cpp (+183/-0)
src/image.cpp (+484/-0)
src/imageextractor.cpp (+149/-89)
src/imagescaler.cpp (+0/-163)
src/lastfmdownloader.cpp (+0/-95)
src/libthumbnailer.map (+0/-15)
src/make_directories.cpp (+51/-0)
src/mediaartcache.cpp (+0/-225)
src/safe_strerror.cpp (+72/-0)
src/service/CMakeLists.txt (+20/-17)
src/service/admininterface.cpp (+141/-0)
src/service/admininterface.h (+65/-0)
src/service/admininterface.xml (+41/-0)
src/service/bus.xml (+9/-0)
src/service/com.canonical.Thumbnailer.service.in (+0/-1)
src/service/credentialscache.cpp (+187/-0)
src/service/credentialscache.h (+81/-0)
src/service/dbusinterface.cpp (+333/-237)
src/service/dbusinterface.h (+71/-27)
src/service/dbusinterface.xml (+14/-11)
src/service/handler.cpp (+454/-0)
src/service/handler.h (+91/-0)
src/service/inactivityhandler.cpp (+63/-0)
src/service/inactivityhandler.h (+49/-0)
src/service/main.cpp (+80/-43)
src/service/ratelimiter.cpp (+69/-0)
src/service/ratelimiter.h (+63/-0)
src/service/stats.cpp (+105/-0)
src/service/stats.h (+75/-0)
src/settings.cpp (+170/-0)
src/soupdownloader.cpp (+0/-46)
src/thumbnailcache.cpp (+0/-371)
src/thumbnailer-admin/CMakeLists.txt (+33/-0)
src/thumbnailer-admin/action.h (+66/-0)
src/thumbnailer-admin/clear.cpp (+115/-0)
src/thumbnailer-admin/clear.h (+50/-0)
src/thumbnailer-admin/dbus_connection.cpp (+58/-0)
src/thumbnailer-admin/dbus_connection.h (+57/-0)
src/thumbnailer-admin/get_local_thumbnail.cpp (+113/-0)
src/thumbnailer-admin/get_local_thumbnail.h (+52/-0)
src/thumbnailer-admin/get_remote_thumbnail.cpp (+129/-0)
src/thumbnailer-admin/get_remote_thumbnail.h (+53/-0)
src/thumbnailer-admin/parse_size.cpp (+62/-0)
src/thumbnailer-admin/parse_size.h (+39/-0)
src/thumbnailer-admin/show_stats.cpp (+223/-0)
src/thumbnailer-admin/show_stats.h (+55/-0)
src/thumbnailer-admin/shutdown.cpp (+74/-0)
src/thumbnailer-admin/shutdown.h (+47/-0)
src/thumbnailer-admin/thumbnailer-admin.cpp (+143/-0)
src/thumbnailer-admin/util.cpp (+79/-0)
src/thumbnailer-admin/util.h (+49/-0)
src/thumbnailer.cpp (+735/-303)
src/trace.cpp (+103/-0)
src/ubuntuserverdownloader.cpp (+302/-74)
src/vs-thumb/CMakeLists.txt (+13/-0)
src/vs-thumb/thumbnailextractor.cpp (+430/-0)
src/vs-thumb/thumbnailextractor.h (+56/-0)
src/vs-thumb/vs-thumb.cpp (+90/-207)
tests/CMakeLists.txt (+52/-30)
tests/basic.cpp (+0/-212)
tests/check_access/CMakeLists.txt (+4/-0)
tests/check_access/check_access_test.cpp (+64/-0)
tests/copyright/CMakeLists.txt (+6/-0)
tests/copyright/check_copyright.sh (+53/-0)
tests/core/CMakeLists.txt (+8/-0)
tests/core/internal/CMakeLists.txt (+1/-0)
tests/core/internal/persistent_string_cache_impl/CMakeLists.txt (+5/-0)
tests/core/internal/persistent_string_cache_impl/persistent_string_cache_impl_test.cpp (+1986/-0)
tests/core/persistent_cache/CMakeLists.txt (+5/-0)
tests/core/persistent_cache/persistent_cache_test.cpp (+1413/-0)
tests/core/persistent_string_cache/CMakeLists.txt (+11/-0)
tests/core/persistent_string_cache/persistent_string_cache_test.cpp (+469/-0)
tests/core/persistent_string_cache/speed_test.cpp (+212/-0)
tests/dbus/CMakeLists.txt (+12/-0)
tests/dbus/dbus_test.cpp (+558/-0)
tests/download/CMakeLists.txt (+11/-0)
tests/download/download_test.cpp (+216/-135)
tests/file_io/CMakeLists.txt (+4/-0)
tests/file_io/file_io_test.cpp (+155/-0)
tests/gobj_ptr/CMakeLists.txt (+3/-0)
tests/gobj_ptr/gobj_ptr_test.cpp (+166/-129)
tests/headers/CMakeLists.txt (+45/-0)
tests/headers/compile_headers.py (+169/-0)
tests/image/CMakeLists.txt (+4/-0)
tests/image/image_test.cpp (+368/-0)
tests/media/bad_image.jpg (+1/-0)
tests/mediaartcachetest.cpp (+0/-169)
tests/qml/CMakeLists.txt (+11/-0)
tests/qml/Fixture.qml (+109/-0)
tests/qml/qml_test.cpp (+78/-0)
tests/qml/tst_albumart.qml (+41/-66)
tests/qml/tst_embedded_albumart.qml (+10/-0)
tests/qml/tst_photo.qml (+61/-0)
tests/safe_strerror/CMakeLists.txt (+4/-0)
tests/safe_strerror/safe_strerror_test.cpp (+29/-0)
tests/server/images/artist_album.png (+1/-0)
tests/server/images/sia_fear.txt (+1/-0)
tests/server/images/sia_fear_album.txt (+1/-0)
tests/server/server.py (+96/-0)
tests/settings/CMakeLists.txt (+4/-0)
tests/settings/settings_test.cpp (+146/-0)
tests/slow-vs-thumb/CMakeLists.txt (+11/-0)
tests/slow-vs-thumb/slow-vs-thumb_test.cpp (+63/-0)
tests/slow-vs-thumb/slow/vs-thumb (+3/-0)
tests/testsetup.h.in (+29/-3)
tests/thumbnailer-admin/CMakeLists.txt (+16/-0)
tests/thumbnailer-admin/thumbnailer-admin_test.cpp (+616/-0)
tests/thumbnailer/CMakeLists.txt (+14/-0)
tests/thumbnailer/thumbnailer_test.cpp (+902/-0)
tests/thumbnailer/vs-thumb-crash/vs-thumb (+3/-0)
tests/thumbnailer/vs-thumb-exit-1/vs-thumb (+3/-0)
tests/thumbnailer/vs-thumb-exit-2/vs-thumb (+3/-0)
tests/thumbnailer/vs-thumb-exit-99/vs-thumb (+3/-0)
tests/utils/CMakeLists.txt (+34/-0)
tests/utils/artserver.cpp (+59/-0)
tests/utils/artserver.h (+34/-0)
tests/utils/dbusserver.cpp (+64/-0)
tests/utils/dbusserver.h (+48/-0)
tests/vs-thumb/CMakeLists.txt (+9/-0)
tests/vs-thumb/vs-thumb_test.cpp (+223/-0)
tests/whitespace/CMakeLists.txt (+9/-0)
tests/whitespace/check_whitespace.py (+114/-0)
tools/CMakeLists.txt (+0/-14)
tools/cachetool.cpp (+0/-37)
tools/imdump.cpp (+0/-34)
tools/lastfmtest.cpp (+0/-31)
tools/parse-settings.py (+123/-0)
tools/scaler.cpp (+0/-38)
tools/ubuntuservertest.cpp (+0/-28)
tsan-suppress (+2/-0)
valgrind-suppress (+133/-0)
To merge this branch: bzr merge lp:~jamesh/thumbnailer/landing-20150622
Reviewer Review Type Date Requested Status
Michi Henning (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+262567@code.launchpad.net

Commit message

Merge lp:thumbnailer/devel r240 into trunk.

Description of the change

Merge lp:thumbnailer/devel r231 into trunk.

I've used lp:~ci-train-bot/thumbnailer/thumbnailer-ubuntu-wily-proposed as a base for this branch, since the last landing doesn't seem to have made it to trunk. I've also integrated Adam Conrad's packaging fix that was made on top of wily-proposed outside of CI prior to the merge.

I've summarised the most visible changes in the Debian changelog (I can add more if you want).

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Michi Henning (michihenning) wrote :

Looking good to me. Works well on the phone, aside from gstreamer problems. But, even when gstreamer does something stupid, we recover well.

review: Approve
127. By James Henstridge

Merge from devel

128. By James Henstridge

Update Debian changelog.

Revision history for this message
Victor Thompson (vthompson) wrote :

I'm still seeing the same issue with regard to thumbnails timing out [1]

Music app log [2]

Syslog [3]

1 - https://www.youtube.com/watch?v=LBwUGe8n1Hs
2 - http://paste.ubuntu.com/11767442/
3 - http://paste.ubuntu.com/11767445/

Revision history for this message
Victor Thompson (vthompson) wrote :

Actually, disregard my last comment. Upon restarting the device the thumbnails are starting to show up without immediately timing out. Once the thumbnails are generated the first time, they appear to re-generate from cache (I assume) immediately--whereas the version in the device images would slowly generate them each time and seemingly block on something being processed.

Revision history for this message
James Henstridge (jamesh) wrote :

My guess is that your app was running with the new QML plugin but talking to the old thumbnailer-service. There were some changes to the API as part of the rewrite (to support requesting thumbnails of arbitrary size rather than the fixed set of sizes), so the placeholder images would be due to the broken D-Bus method calls. Rebooting would have made sure you were on the new code.

One of the main causes of the old serialised behaviour was due to the old QQuickImageProvider API, which requested thumbnails one by one on a single worker thread. With this branch, we're using the new QQuickAsyncImageProvider API so we can start multiple thumbnail jobs in parallel.

Revision history for this message
Michi Henning (michihenning) wrote :

Hi Victor, thanks heaps for helping to test this!

If you want to see what's going on with the cache, you can run a tail -f on ~/.cache/upstart/dbus.log. All the thumbnailer messages end up in there. If you want to test with an empty cache, you can run

thumbnailer-admin clear

This completely wipes the cached thumbnails. You can pull out to lots of statistics for the three internal caches with

thumbnailer-admin stats -v

129. By James Henstridge

Merge from devel

Revision history for this message
Michi Henning (michihenning) wrote :

Yes, thank you!

review: Approve
130. By James Henstridge

Merge lp:thumbnailer/devel r240

Revision history for this message
Michi Henning (michihenning) wrote :

Yes, definitely!

review: Approve
131. By James Henstridge

Merge lp:thumbnailer/devel r241

Revision history for this message
Michi Henning (michihenning) wrote :

LGTM!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2014-09-25 09:47:05 +0000
+++ CMakeLists.txt 2015-07-14 06:30:34 +0000
@@ -1,27 +1,82 @@
1project(thumbnailer C CXX)1project(thumbnailer C CXX)
2cmake_minimum_required(VERSION 2.8.7)2
3set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -Wextra")3set(CMAKE_INCLUDE_CURRENT_DIR ON)
44
5include(CheckCXXCompilerFlag)5cmake_minimum_required(VERSION 2.8.11)
6check_cxx_compiler_flag(-std=c++11 HAS_C11)6
7# Precise's GCC is too old to have -std=c++117# Suppress complaints by cmake about COMPILE_DEFINITIONS_<Config> caused by qt5 cmake macros.
8if(HAS_C11)8cmake_policy(SET CMP0043 OLD)
9set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")9
10else()10string(TOLOWER "${CMAKE_BUILD_TYPE}" cmake_build_type_lower) # Build types should always be lower case
11set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Dfinal=")11
12endif()12set(ACCEPTED_BUILD_TYPES "" none release debug relwithdebinfo coverage)
1313list(FIND ACCEPTED_BUILD_TYPES "${cmake_build_type_lower}" IS_BUILD_TYPE_ACCEPTED)
14set(SO_VERSION_MAJOR "1")14if(${IS_BUILD_TYPE_ACCEPTED} EQUAL -1)
15set(SO_VERSION_MINOR "1")15 message(FATAL_ERROR "Invalid CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}\nValid types are: ${ACCEPTED_BUILD_TYPES}")
16set(SO_VERSION_PATCH "0")16endif()
1717
18set(SO_VERSION "${SO_VERSION_MAJOR}.${SO_VERSION_MINOR}.${SO_VERSION_PATCH}")18set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
1919
20# Increment this manually whenever breaking ABI.20set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11 -Wall -pedantic -Wextra")
21# http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html#AEN13521
22set(ABI_VERSION 0)22# Some additional warnings not included by the general flags set above.
2323set(EXTRA_C_WARNINGS "-Wcast-align -Wcast-qual -Wformat -Wredundant-decls -Wswitch-default")
24include(cmake/coverage.cmake)24set(EXTRA_CXX_WARNINGS "-Wnon-virtual-dtor -Wctor-dtor-privacy -Wold-style-cast")
25set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_C_WARNINGS} ${EXTRA_CXX_WARNINGS}")
26
27# By default, for release builds, warnings become hard errors.
28if ("${cmake_build_type_lower}" STREQUAL "release" OR "${cmake_build_type_lower}" STREQUAL "relwithdebinfo")
29 option(Werror "Treat warnings as errors" ON)
30else()
31 option(Werror "Treat warnings as errors" OFF)
32endif()
33
34# If warnings are errors, don't error on deprecated declarations.
35if (${Werror})
36 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
37 if ("${cmake_build_type_lower}" STREQUAL "release" OR "${cmake_build_type_lower}" STREQUAL "relwithdebinfo")
38 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=deprecated-declarations")
39 endif()
40endif()
41
42add_definitions(-DQT_NO_KEYWORDS)
43
44# Flags for thread/address sanitizer
45set(SANITIZER "" CACHE STRING "Build with -fsanitize=<value> (legal values: thread, address)")
46
47if ("${SANITIZER}" STREQUAL "")
48 # Do nothing
49elseif (${SANITIZER} STREQUAL "thread")
50 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread -fno-omit-frame-pointer -g")
51elseif (${SANITIZER} STREQUAL "address")
52 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer -g")
53else()
54 message(FATAL_ERROR "Invalid SANITIZER setting: ${SANITIZER}")
55endif()
56
57# Some tests are slow, so make it possible not to run them
58# during day-to-day development.
59option(slowtests "Run slow tests" ON)
60
61# Definitions for testing with valgrind.
62
63configure_file(CTestCustom.cmake.in CTestCustom.cmake) # Tests in CTestCustom.cmake are skipped for valgrind
64
65find_program(MEMORYCHECK_COMMAND NAMES valgrind)
66if (MEMORYCHECK_COMMAND)
67 set(MEMORYCHECK_COMMAND_OPTIONS
68 "--suppressions=${CMAKE_SOURCE_DIR}/valgrind-suppress --errors-for-leak-kinds=definite --show-leak-kinds=definite --leak-check=full --num-callers=50 --error-exitcode=3"
69 )
70 add_custom_target(valgrind DEPENDS NightlyMemCheck)
71else()
72 message(WARNING "Cannot find valgrind: valgrind target will not be available")
73endif()
74
75include(CTest)
76enable_testing()
77
78include(EnableCoverageReport)
79
25include(cmake/UseGSettings.cmake)80include(cmake/UseGSettings.cmake)
2681
27include(GNUInstallDirs)82include(GNUInstallDirs)
@@ -29,27 +84,46 @@
29set(SHARE_PRIV_DIR ${CMAKE_INSTALL_LIBDIR}/thumbnailer)84set(SHARE_PRIV_DIR ${CMAKE_INSTALL_LIBDIR}/thumbnailer)
30set(SHARE_PRIV_ABS ${CMAKE_INSTALL_PREFIX}/${SHARE_PRIV_DIR})85set(SHARE_PRIV_ABS ${CMAKE_INSTALL_PREFIX}/${SHARE_PRIV_DIR})
3186
87find_package(Boost COMPONENTS filesystem regex system REQUIRED)
32find_package(Threads REQUIRED)88find_package(Threads REQUIRED)
33find_package(Qt5Core REQUIRED)89find_package(Qt5Core REQUIRED)
90find_package(Qt5DBus REQUIRED)
91
34include(FindPkgConfig)92include(FindPkgConfig)
35pkg_check_modules(GST_DEPS REQUIRED gstreamer-1.0 gstreamer-plugins-base-1.0 gstreamer-pbutils-1.0 gstreamer-app-1.0)93pkg_check_modules(GST_DEPS REQUIRED gstreamer-1.0 gstreamer-plugins-base-1.0 gstreamer-tag-1.0)
94pkg_check_modules(GOBJ_DEPS REQUIRED gobject-2.0)
36pkg_check_modules(GIO_DEPS REQUIRED gio-2.0 gio-unix-2.0)95pkg_check_modules(GIO_DEPS REQUIRED gio-2.0 gio-unix-2.0)
37pkg_check_modules(IMG_DEPS REQUIRED gdk-pixbuf-2.0 libexif)96pkg_check_modules(IMG_DEPS REQUIRED gdk-pixbuf-2.0 libexif)
38pkg_check_modules(SOUP_DEPS REQUIRED libsoup-2.4)97pkg_check_modules(UNITY_API_DEPS REQUIRED libunity-api)
39pkg_check_modules(XML_DEPS REQUIRED libxml-2.0)98pkg_check_modules(APPARMOR_DEPS REQUIRED libapparmor)
4099
41include_directories(${GST_DEPS_INCLUDE_DIRS})100include_directories(${GST_DEPS_INCLUDE_DIRS})
101include_directories(${GOBJ_DEPS_INCLUDE_DIRS})
42include_directories(${GIO_DEPS_INCLUDE_DIRS})102include_directories(${GIO_DEPS_INCLUDE_DIRS})
43include_directories(${IMG_DEPS_INCLUDE_DIRS})103include_directories(${IMG_DEPS_INCLUDE_DIRS})
44include_directories(${SOUP_DEPS_INCLUDE_DIRS})104include_directories(${UNITY_API_DEPS_INCLUDE_DIRS})
45include_directories(${XML_DEPS_INCLUDE_DIRS})105include_directories(${APPARMOR_DEPS_INCLUDE_DIRS})
46include_directories(include)106include_directories(include)
47include_directories(${CMAKE_CURRENT_BINARY_DIR}/include)107include_directories(${CMAKE_CURRENT_BINARY_DIR}/include)
48108
49enable_testing()
50add_subdirectory(src)109add_subdirectory(src)
51add_subdirectory(data)110add_subdirectory(data)
52add_subdirectory(plugins/Ubuntu/Thumbnailer)111add_subdirectory(plugins/Ubuntu/Thumbnailer.0.1)
53add_subdirectory(tests)112add_subdirectory(tests)
54add_subdirectory(tools)
55add_subdirectory(include)113add_subdirectory(include)
114
115enable_coverage_report(
116 TARGETS
117 thumbnailer
118 thumbnailer-admin
119 thumbnailer-service
120 thumbnailer-qml
121 vs-thumb
122 testutils
123 FILTER
124 ${CMAKE_SOURCE_DIR}/include/core/*
125 ${CMAKE_SOURCE_DIR}/tests/*
126 ${CMAKE_BINARY_DIR}/*
127 TESTS
128 ${UNIT_TEST_TARGETS}
129)
56130
=== added file 'COPYING.GPL'
--- COPYING.GPL 1970-01-01 00:00:00 +0000
+++ COPYING.GPL 2015-07-14 06:30:34 +0000
@@ -0,0 +1,674 @@
1 GNU GENERAL PUBLIC LICENSE
2 Version 3, 29 June 2007
3
4 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5 Everyone is permitted to copy and distribute verbatim copies
6 of this license document, but changing it is not allowed.
7
8 Preamble
9
10 The GNU General Public License is a free, copyleft license for
11software and other kinds of works.
12
13 The licenses for most software and other practical works are designed
14to take away your freedom to share and change the works. By contrast,
15the GNU General Public License is intended to guarantee your freedom to
16share and change all versions of a program--to make sure it remains free
17software for all its users. We, the Free Software Foundation, use the
18GNU General Public License for most of our software; it applies also to
19any other work released this way by its authors. You can apply it to
20your programs, too.
21
22 When we speak of free software, we are referring to freedom, not
23price. Our General Public Licenses are designed to make sure that you
24have the freedom to distribute copies of free software (and charge for
25them if you wish), that you receive source code or can get it if you
26want it, that you can change the software or use pieces of it in new
27free programs, and that you know you can do these things.
28
29 To protect your rights, we need to prevent others from denying you
30these rights or asking you to surrender the rights. Therefore, you have
31certain responsibilities if you distribute copies of the software, or if
32you modify it: responsibilities to respect the freedom of others.
33
34 For example, if you distribute copies of such a program, whether
35gratis or for a fee, you must pass on to the recipients the same
36freedoms that you received. You must make sure that they, too, receive
37or can get the source code. And you must show them these terms so they
38know their rights.
39
40 Developers that use the GNU GPL protect your rights with two steps:
41(1) assert copyright on the software, and (2) offer you this License
42giving you legal permission to copy, distribute and/or modify it.
43
44 For the developers' and authors' protection, the GPL clearly explains
45that there is no warranty for this free software. For both users' and
46authors' sake, the GPL requires that modified versions be marked as
47changed, so that their problems will not be attributed erroneously to
48authors of previous versions.
49
50 Some devices are designed to deny users access to install or run
51modified versions of the software inside them, although the manufacturer
52can do so. This is fundamentally incompatible with the aim of
53protecting users' freedom to change the software. The systematic
54pattern of such abuse occurs in the area of products for individuals to
55use, which is precisely where it is most unacceptable. Therefore, we
56have designed this version of the GPL to prohibit the practice for those
57products. If such problems arise substantially in other domains, we
58stand ready to extend this provision to those domains in future versions
59of the GPL, as needed to protect the freedom of users.
60
61 Finally, every program is threatened constantly by software patents.
62States should not allow patents to restrict development and use of
63software on general-purpose computers, but in those that do, we wish to
64avoid the special danger that patents applied to a free program could
65make it effectively proprietary. To prevent this, the GPL assures that
66patents cannot be used to render the program non-free.
67
68 The precise terms and conditions for copying, distribution and
69modification follow.
70
71 TERMS AND CONDITIONS
72
73 0. Definitions.
74
75 "This License" refers to version 3 of the GNU General Public License.
76
77 "Copyright" also means copyright-like laws that apply to other kinds of
78works, such as semiconductor masks.
79
80 "The Program" refers to any copyrightable work licensed under this
81License. Each licensee is addressed as "you". "Licensees" and
82"recipients" may be individuals or organizations.
83
84 To "modify" a work means to copy from or adapt all or part of the work
85in a fashion requiring copyright permission, other than the making of an
86exact copy. The resulting work is called a "modified version" of the
87earlier work or a work "based on" the earlier work.
88
89 A "covered work" means either the unmodified Program or a work based
90on the Program.
91
92 To "propagate" a work means to do anything with it that, without
93permission, would make you directly or secondarily liable for
94infringement under applicable copyright law, except executing it on a
95computer or modifying a private copy. Propagation includes copying,
96distribution (with or without modification), making available to the
97public, and in some countries other activities as well.
98
99 To "convey" a work means any kind of propagation that enables other
100parties to make or receive copies. Mere interaction with a user through
101a computer network, with no transfer of a copy, is not conveying.
102
103 An interactive user interface displays "Appropriate Legal Notices"
104to the extent that it includes a convenient and prominently visible
105feature that (1) displays an appropriate copyright notice, and (2)
106tells the user that there is no warranty for the work (except to the
107extent that warranties are provided), that licensees may convey the
108work under this License, and how to view a copy of this License. If
109the interface presents a list of user commands or options, such as a
110menu, a prominent item in the list meets this criterion.
111
112 1. Source Code.
113
114 The "source code" for a work means the preferred form of the work
115for making modifications to it. "Object code" means any non-source
116form of a work.
117
118 A "Standard Interface" means an interface that either is an official
119standard defined by a recognized standards body, or, in the case of
120interfaces specified for a particular programming language, one that
121is widely used among developers working in that language.
122
123 The "System Libraries" of an executable work include anything, other
124than the work as a whole, that (a) is included in the normal form of
125packaging a Major Component, but which is not part of that Major
126Component, and (b) serves only to enable use of the work with that
127Major Component, or to implement a Standard Interface for which an
128implementation is available to the public in source code form. A
129"Major Component", in this context, means a major essential component
130(kernel, window system, and so on) of the specific operating system
131(if any) on which the executable work runs, or a compiler used to
132produce the work, or an object code interpreter used to run it.
133
134 The "Corresponding Source" for a work in object code form means all
135the source code needed to generate, install, and (for an executable
136work) run the object code and to modify the work, including scripts to
137control those activities. However, it does not include the work's
138System Libraries, or general-purpose tools or generally available free
139programs which are used unmodified in performing those activities but
140which are not part of the work. For example, Corresponding Source
141includes interface definition files associated with source files for
142the work, and the source code for shared libraries and dynamically
143linked subprograms that the work is specifically designed to require,
144such as by intimate data communication or control flow between those
145subprograms and other parts of the work.
146
147 The Corresponding Source need not include anything that users
148can regenerate automatically from other parts of the Corresponding
149Source.
150
151 The Corresponding Source for a work in source code form is that
152same work.
153
154 2. Basic Permissions.
155
156 All rights granted under this License are granted for the term of
157copyright on the Program, and are irrevocable provided the stated
158conditions are met. This License explicitly affirms your unlimited
159permission to run the unmodified Program. The output from running a
160covered work is covered by this License only if the output, given its
161content, constitutes a covered work. This License acknowledges your
162rights of fair use or other equivalent, as provided by copyright law.
163
164 You may make, run and propagate covered works that you do not
165convey, without conditions so long as your license otherwise remains
166in force. You may convey covered works to others for the sole purpose
167of having them make modifications exclusively for you, or provide you
168with facilities for running those works, provided that you comply with
169the terms of this License in conveying all material for which you do
170not control copyright. Those thus making or running the covered works
171for you must do so exclusively on your behalf, under your direction
172and control, on terms that prohibit them from making any copies of
173your copyrighted material outside their relationship with you.
174
175 Conveying under any other circumstances is permitted solely under
176the conditions stated below. Sublicensing is not allowed; section 10
177makes it unnecessary.
178
179 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180
181 No covered work shall be deemed part of an effective technological
182measure under any applicable law fulfilling obligations under article
18311 of the WIPO copyright treaty adopted on 20 December 1996, or
184similar laws prohibiting or restricting circumvention of such
185measures.
186
187 When you convey a covered work, you waive any legal power to forbid
188circumvention of technological measures to the extent such circumvention
189is effected by exercising rights under this License with respect to
190the covered work, and you disclaim any intention to limit operation or
191modification of the work as a means of enforcing, against the work's
192users, your or third parties' legal rights to forbid circumvention of
193technological measures.
194
195 4. Conveying Verbatim Copies.
196
197 You may convey verbatim copies of the Program's source code as you
198receive it, in any medium, provided that you conspicuously and
199appropriately publish on each copy an appropriate copyright notice;
200keep intact all notices stating that this License and any
201non-permissive terms added in accord with section 7 apply to the code;
202keep intact all notices of the absence of any warranty; and give all
203recipients a copy of this License along with the Program.
204
205 You may charge any price or no price for each copy that you convey,
206and you may offer support or warranty protection for a fee.
207
208 5. Conveying Modified Source Versions.
209
210 You may convey a work based on the Program, or the modifications to
211produce it from the Program, in the form of source code under the
212terms of section 4, provided that you also meet all of these conditions:
213
214 a) The work must carry prominent notices stating that you modified
215 it, and giving a relevant date.
216
217 b) The work must carry prominent notices stating that it is
218 released under this License and any conditions added under section
219 7. This requirement modifies the requirement in section 4 to
220 "keep intact all notices".
221
222 c) You must license the entire work, as a whole, under this
223 License to anyone who comes into possession of a copy. This
224 License will therefore apply, along with any applicable section 7
225 additional terms, to the whole of the work, and all its parts,
226 regardless of how they are packaged. This License gives no
227 permission to license the work in any other way, but it does not
228 invalidate such permission if you have separately received it.
229
230 d) If the work has interactive user interfaces, each must display
231 Appropriate Legal Notices; however, if the Program has interactive
232 interfaces that do not display Appropriate Legal Notices, your
233 work need not make them do so.
234
235 A compilation of a covered work with other separate and independent
236works, which are not by their nature extensions of the covered work,
237and which are not combined with it such as to form a larger program,
238in or on a volume of a storage or distribution medium, is called an
239"aggregate" if the compilation and its resulting copyright are not
240used to limit the access or legal rights of the compilation's users
241beyond what the individual works permit. Inclusion of a covered work
242in an aggregate does not cause this License to apply to the other
243parts of the aggregate.
244
245 6. Conveying Non-Source Forms.
246
247 You may convey a covered work in object code form under the terms
248of sections 4 and 5, provided that you also convey the
249machine-readable Corresponding Source under the terms of this License,
250in one of these ways:
251
252 a) Convey the object code in, or embodied in, a physical product
253 (including a physical distribution medium), accompanied by the
254 Corresponding Source fixed on a durable physical medium
255 customarily used for software interchange.
256
257 b) Convey the object code in, or embodied in, a physical product
258 (including a physical distribution medium), accompanied by a
259 written offer, valid for at least three years and valid for as
260 long as you offer spare parts or customer support for that product
261 model, to give anyone who possesses the object code either (1) a
262 copy of the Corresponding Source for all the software in the
263 product that is covered by this License, on a durable physical
264 medium customarily used for software interchange, for a price no
265 more than your reasonable cost of physically performing this
266 conveying of source, or (2) access to copy the
267 Corresponding Source from a network server at no charge.
268
269 c) Convey individual copies of the object code with a copy of the
270 written offer to provide the Corresponding Source. This
271 alternative is allowed only occasionally and noncommercially, and
272 only if you received the object code with such an offer, in accord
273 with subsection 6b.
274
275 d) Convey the object code by offering access from a designated
276 place (gratis or for a charge), and offer equivalent access to the
277 Corresponding Source in the same way through the same place at no
278 further charge. You need not require recipients to copy the
279 Corresponding Source along with the object code. If the place to
280 copy the object code is a network server, the Corresponding Source
281 may be on a different server (operated by you or a third party)
282 that supports equivalent copying facilities, provided you maintain
283 clear directions next to the object code saying where to find the
284 Corresponding Source. Regardless of what server hosts the
285 Corresponding Source, you remain obligated to ensure that it is
286 available for as long as needed to satisfy these requirements.
287
288 e) Convey the object code using peer-to-peer transmission, provided
289 you inform other peers where the object code and Corresponding
290 Source of the work are being offered to the general public at no
291 charge under subsection 6d.
292
293 A separable portion of the object code, whose source code is excluded
294from the Corresponding Source as a System Library, need not be
295included in conveying the object code work.
296
297 A "User Product" is either (1) a "consumer product", which means any
298tangible personal property which is normally used for personal, family,
299or household purposes, or (2) anything designed or sold for incorporation
300into a dwelling. In determining whether a product is a consumer product,
301doubtful cases shall be resolved in favor of coverage. For a particular
302product received by a particular user, "normally used" refers to a
303typical or common use of that class of product, regardless of the status
304of the particular user or of the way in which the particular user
305actually uses, or expects or is expected to use, the product. A product
306is a consumer product regardless of whether the product has substantial
307commercial, industrial or non-consumer uses, unless such uses represent
308the only significant mode of use of the product.
309
310 "Installation Information" for a User Product means any methods,
311procedures, authorization keys, or other information required to install
312and execute modified versions of a covered work in that User Product from
313a modified version of its Corresponding Source. The information must
314suffice to ensure that the continued functioning of the modified object
315code is in no case prevented or interfered with solely because
316modification has been made.
317
318 If you convey an object code work under this section in, or with, or
319specifically for use in, a User Product, and the conveying occurs as
320part of a transaction in which the right of possession and use of the
321User Product is transferred to the recipient in perpetuity or for a
322fixed term (regardless of how the transaction is characterized), the
323Corresponding Source conveyed under this section must be accompanied
324by the Installation Information. But this requirement does not apply
325if neither you nor any third party retains the ability to install
326modified object code on the User Product (for example, the work has
327been installed in ROM).
328
329 The requirement to provide Installation Information does not include a
330requirement to continue to provide support service, warranty, or updates
331for a work that has been modified or installed by the recipient, or for
332the User Product in which it has been modified or installed. Access to a
333network may be denied when the modification itself materially and
334adversely affects the operation of the network or violates the rules and
335protocols for communication across the network.
336
337 Corresponding Source conveyed, and Installation Information provided,
338in accord with this section must be in a format that is publicly
339documented (and with an implementation available to the public in
340source code form), and must require no special password or key for
341unpacking, reading or copying.
342
343 7. Additional Terms.
344
345 "Additional permissions" are terms that supplement the terms of this
346License by making exceptions from one or more of its conditions.
347Additional permissions that are applicable to the entire Program shall
348be treated as though they were included in this License, to the extent
349that they are valid under applicable law. If additional permissions
350apply only to part of the Program, that part may be used separately
351under those permissions, but the entire Program remains governed by
352this License without regard to the additional permissions.
353
354 When you convey a copy of a covered work, you may at your option
355remove any additional permissions from that copy, or from any part of
356it. (Additional permissions may be written to require their own
357removal in certain cases when you modify the work.) You may place
358additional permissions on material, added by you to a covered work,
359for which you have or can give appropriate copyright permission.
360
361 Notwithstanding any other provision of this License, for material you
362add to a covered work, you may (if authorized by the copyright holders of
363that material) supplement the terms of this License with terms:
364
365 a) Disclaiming warranty or limiting liability differently from the
366 terms of sections 15 and 16 of this License; or
367
368 b) Requiring preservation of specified reasonable legal notices or
369 author attributions in that material or in the Appropriate Legal
370 Notices displayed by works containing it; or
371
372 c) Prohibiting misrepresentation of the origin of that material, or
373 requiring that modified versions of such material be marked in
374 reasonable ways as different from the original version; or
375
376 d) Limiting the use for publicity purposes of names of licensors or
377 authors of the material; or
378
379 e) Declining to grant rights under trademark law for use of some
380 trade names, trademarks, or service marks; or
381
382 f) Requiring indemnification of licensors and authors of that
383 material by anyone who conveys the material (or modified versions of
384 it) with contractual assumptions of liability to the recipient, for
385 any liability that these contractual assumptions directly impose on
386 those licensors and authors.
387
388 All other non-permissive additional terms are considered "further
389restrictions" within the meaning of section 10. If the Program as you
390received it, or any part of it, contains a notice stating that it is
391governed by this License along with a term that is a further
392restriction, you may remove that term. If a license document contains
393a further restriction but permits relicensing or conveying under this
394License, you may add to a covered work material governed by the terms
395of that license document, provided that the further restriction does
396not survive such relicensing or conveying.
397
398 If you add terms to a covered work in accord with this section, you
399must place, in the relevant source files, a statement of the
400additional terms that apply to those files, or a notice indicating
401where to find the applicable terms.
402
403 Additional terms, permissive or non-permissive, may be stated in the
404form of a separately written license, or stated as exceptions;
405the above requirements apply either way.
406
407 8. Termination.
408
409 You may not propagate or modify a covered work except as expressly
410provided under this License. Any attempt otherwise to propagate or
411modify it is void, and will automatically terminate your rights under
412this License (including any patent licenses granted under the third
413paragraph of section 11).
414
415 However, if you cease all violation of this License, then your
416license from a particular copyright holder is reinstated (a)
417provisionally, unless and until the copyright holder explicitly and
418finally terminates your license, and (b) permanently, if the copyright
419holder fails to notify you of the violation by some reasonable means
420prior to 60 days after the cessation.
421
422 Moreover, your license from a particular copyright holder is
423reinstated permanently if the copyright holder notifies you of the
424violation by some reasonable means, this is the first time you have
425received notice of violation of this License (for any work) from that
426copyright holder, and you cure the violation prior to 30 days after
427your receipt of the notice.
428
429 Termination of your rights under this section does not terminate the
430licenses of parties who have received copies or rights from you under
431this License. If your rights have been terminated and not permanently
432reinstated, you do not qualify to receive new licenses for the same
433material under section 10.
434
435 9. Acceptance Not Required for Having Copies.
436
437 You are not required to accept this License in order to receive or
438run a copy of the Program. Ancillary propagation of a covered work
439occurring solely as a consequence of using peer-to-peer transmission
440to receive a copy likewise does not require acceptance. However,
441nothing other than this License grants you permission to propagate or
442modify any covered work. These actions infringe copyright if you do
443not accept this License. Therefore, by modifying or propagating a
444covered work, you indicate your acceptance of this License to do so.
445
446 10. Automatic Licensing of Downstream Recipients.
447
448 Each time you convey a covered work, the recipient automatically
449receives a license from the original licensors, to run, modify and
450propagate that work, subject to this License. You are not responsible
451for enforcing compliance by third parties with this License.
452
453 An "entity transaction" is a transaction transferring control of an
454organization, or substantially all assets of one, or subdividing an
455organization, or merging organizations. If propagation of a covered
456work results from an entity transaction, each party to that
457transaction who receives a copy of the work also receives whatever
458licenses to the work the party's predecessor in interest had or could
459give under the previous paragraph, plus a right to possession of the
460Corresponding Source of the work from the predecessor in interest, if
461the predecessor has it or can get it with reasonable efforts.
462
463 You may not impose any further restrictions on the exercise of the
464rights granted or affirmed under this License. For example, you may
465not impose a license fee, royalty, or other charge for exercise of
466rights granted under this License, and you may not initiate litigation
467(including a cross-claim or counterclaim in a lawsuit) alleging that
468any patent claim is infringed by making, using, selling, offering for
469sale, or importing the Program or any portion of it.
470
471 11. Patents.
472
473 A "contributor" is a copyright holder who authorizes use under this
474License of the Program or a work on which the Program is based. The
475work thus licensed is called the contributor's "contributor version".
476
477 A contributor's "essential patent claims" are all patent claims
478owned or controlled by the contributor, whether already acquired or
479hereafter acquired, that would be infringed by some manner, permitted
480by this License, of making, using, or selling its contributor version,
481but do not include claims that would be infringed only as a
482consequence of further modification of the contributor version. For
483purposes of this definition, "control" includes the right to grant
484patent sublicenses in a manner consistent with the requirements of
485this License.
486
487 Each contributor grants you a non-exclusive, worldwide, royalty-free
488patent license under the contributor's essential patent claims, to
489make, use, sell, offer for sale, import and otherwise run, modify and
490propagate the contents of its contributor version.
491
492 In the following three paragraphs, a "patent license" is any express
493agreement or commitment, however denominated, not to enforce a patent
494(such as an express permission to practice a patent or covenant not to
495sue for patent infringement). To "grant" such a patent license to a
496party means to make such an agreement or commitment not to enforce a
497patent against the party.
498
499 If you convey a covered work, knowingly relying on a patent license,
500and the Corresponding Source of the work is not available for anyone
501to copy, free of charge and under the terms of this License, through a
502publicly available network server or other readily accessible means,
503then you must either (1) cause the Corresponding Source to be so
504available, or (2) arrange to deprive yourself of the benefit of the
505patent license for this particular work, or (3) arrange, in a manner
506consistent with the requirements of this License, to extend the patent
507license to downstream recipients. "Knowingly relying" means you have
508actual knowledge that, but for the patent license, your conveying the
509covered work in a country, or your recipient's use of the covered work
510in a country, would infringe one or more identifiable patents in that
511country that you have reason to believe are valid.
512
513 If, pursuant to or in connection with a single transaction or
514arrangement, you convey, or propagate by procuring conveyance of, a
515covered work, and grant a patent license to some of the parties
516receiving the covered work authorizing them to use, propagate, modify
517or convey a specific copy of the covered work, then the patent license
518you grant is automatically extended to all recipients of the covered
519work and works based on it.
520
521 A patent license is "discriminatory" if it does not include within
522the scope of its coverage, prohibits the exercise of, or is
523conditioned on the non-exercise of one or more of the rights that are
524specifically granted under this License. You may not convey a covered
525work if you are a party to an arrangement with a third party that is
526in the business of distributing software, under which you make payment
527to the third party based on the extent of your activity of conveying
528the work, and under which the third party grants, to any of the
529parties who would receive the covered work from you, a discriminatory
530patent license (a) in connection with copies of the covered work
531conveyed by you (or copies made from those copies), or (b) primarily
532for and in connection with specific products or compilations that
533contain the covered work, unless you entered into that arrangement,
534or that patent license was granted, prior to 28 March 2007.
535
536 Nothing in this License shall be construed as excluding or limiting
537any implied license or other defenses to infringement that may
538otherwise be available to you under applicable patent law.
539
540 12. No Surrender of Others' Freedom.
541
542 If conditions are imposed on you (whether by court order, agreement or
543otherwise) that contradict the conditions of this License, they do not
544excuse you from the conditions of this License. If you cannot convey a
545covered work so as to satisfy simultaneously your obligations under this
546License and any other pertinent obligations, then as a consequence you may
547not convey it at all. For example, if you agree to terms that obligate you
548to collect a royalty for further conveying from those to whom you convey
549the Program, the only way you could satisfy both those terms and this
550License would be to refrain entirely from conveying the Program.
551
552 13. Use with the GNU Affero General Public License.
553
554 Notwithstanding any other provision of this License, you have
555permission to link or combine any covered work with a work licensed
556under version 3 of the GNU Affero General Public License into a single
557combined work, and to convey the resulting work. The terms of this
558License will continue to apply to the part which is the covered work,
559but the special requirements of the GNU Affero General Public License,
560section 13, concerning interaction through a network will apply to the
561combination as such.
562
563 14. Revised Versions of this License.
564
565 The Free Software Foundation may publish revised and/or new versions of
566the GNU General Public License from time to time. Such new versions will
567be similar in spirit to the present version, but may differ in detail to
568address new problems or concerns.
569
570 Each version is given a distinguishing version number. If the
571Program specifies that a certain numbered version of the GNU General
572Public License "or any later version" applies to it, you have the
573option of following the terms and conditions either of that numbered
574version or of any later version published by the Free Software
575Foundation. If the Program does not specify a version number of the
576GNU General Public License, you may choose any version ever published
577by the Free Software Foundation.
578
579 If the Program specifies that a proxy can decide which future
580versions of the GNU General Public License can be used, that proxy's
581public statement of acceptance of a version permanently authorizes you
582to choose that version for the Program.
583
584 Later license versions may give you additional or different
585permissions. However, no additional obligations are imposed on any
586author or copyright holder as a result of your choosing to follow a
587later version.
588
589 15. Disclaimer of Warranty.
590
591 THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599
600 16. Limitation of Liability.
601
602 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610SUCH DAMAGES.
611
612 17. Interpretation of Sections 15 and 16.
613
614 If the disclaimer of warranty and limitation of liability provided
615above cannot be given local legal effect according to their terms,
616reviewing courts shall apply local law that most closely approximates
617an absolute waiver of all civil liability in connection with the
618Program, unless a warranty or assumption of liability accompanies a
619copy of the Program in return for a fee.
620
621 END OF TERMS AND CONDITIONS
622
623 How to Apply These Terms to Your New Programs
624
625 If you develop a new program, and you want it to be of the greatest
626possible use to the public, the best way to achieve this is to make it
627free software which everyone can redistribute and change under these terms.
628
629 To do so, attach the following notices to the program. It is safest
630to attach them to the start of each source file to most effectively
631state the exclusion of warranty; and each file should have at least
632the "copyright" line and a pointer to where the full notice is found.
633
634 <one line to give the program's name and a brief idea of what it does.>
635 Copyright (C) <year> <name of author>
636
637 This program is free software: you can redistribute it and/or modify
638 it under the terms of the GNU General Public License as published by
639 the Free Software Foundation, either version 3 of the License, or
640 (at your option) any later version.
641
642 This program is distributed in the hope that it will be useful,
643 but WITHOUT ANY WARRANTY; without even the implied warranty of
644 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 GNU General Public License for more details.
646
647 You should have received a copy of the GNU General Public License
648 along with this program. If not, see <http://www.gnu.org/licenses/>.
649
650Also add information on how to contact you by electronic and paper mail.
651
652 If the program does terminal interaction, make it output a short
653notice like this when it starts in an interactive mode:
654
655 <program> Copyright (C) <year> <name of author>
656 This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 This is free software, and you are welcome to redistribute it
658 under certain conditions; type `show c' for details.
659
660The hypothetical commands `show w' and `show c' should show the appropriate
661parts of the General Public License. Of course, your program's commands
662might be different; for a GUI interface, you would use an "about box".
663
664 You should also get your employer (if you work as a programmer) or school,
665if any, to sign a "copyright disclaimer" for the program, if necessary.
666For more information on this, and how to apply and follow the GNU GPL, see
667<http://www.gnu.org/licenses/>.
668
669 The GNU General Public License does not permit incorporating your program
670into proprietary programs. If your program is a subroutine library, you
671may consider it more useful to permit linking proprietary applications with
672the library. If this is what you want to do, use the GNU Lesser General
673Public License instead of this License. But first, please read
674<http://www.gnu.org/philosophy/why-not-lgpl.html>.
0675
=== renamed file 'COPYING' => 'COPYING.LGPL'
=== added file 'CTestCustom.cmake.in'
--- CTestCustom.cmake.in 1970-01-01 00:00:00 +0000
+++ CTestCustom.cmake.in 2015-07-14 06:30:34 +0000
@@ -0,0 +1,17 @@
1#
2# Tests listed here will not be run by the valgrind target,
3# either because there is not point (we don't want to
4# test that a python script doesn't leak), or because,
5# under valgrind, the test runs too slowly to meet
6# its timing constraints (or crashes valgrind).
7#
8
9SET(CTEST_CUSTOM_MEMCHECK_IGNORE
10 test_qml # Too many bugs in QML to suppress them selectively
11 speed
12 copyright
13 stand-alone-internal-headers
14 stand-alone-core-headers
15 stand-alone-core-internal-headers
16 whitespace
17)
018
=== added file 'HACKING'
--- HACKING 1970-01-01 00:00:00 +0000
+++ HACKING 2015-07-14 06:30:34 +0000
@@ -0,0 +1,121 @@
1Building the code
2-----------------
3
4By default, the code is built in release mode. To build a debug version, use
5
6 $ mkdir builddebug
7 $ cd builddebug
8 $ cmake -DCMAKE_BUILD_TYPE=debug ..
9 $ make
10
11For a release version, use -DCMAKE_BUILD_TYPE=release
12
13Running the tests
14-----------------
15
16 $ make
17 $ make test
18
19Note that "make test" alone is dangerous because it does not rebuild
20any tests if either the library or the test files themselves need
21rebuilding. It's not possible to fix this with cmake because cmake cannot
22add build dependencies to built-in targets. To make sure that everything
23is up-to-date, run "make" before running "make test"!
24
25To run the tests with valgrind:
26
27 $ make valgrind
28
29It doesn't make sense for some tests to run them with valgrind. For
30example, the header compilation tests don't need valgrind because
31we'd just be testing that Python doesn't leak. There are also some
32tests that run too slow and time out under valgrind and, occasionally,
33valgrind crashes for a particular test.
34
35There are two ways to suppress tests:
36
37You can add a test name to CTestCustom.cmake.in to suppress that
38test completely. That makes sense for the header compilation tests,
39for example.
40
41If a specific test case in a test program causes a valgrind problem,
42you can selectively disable a section of code like this:
43
44 #include <valgrind/valgrind.h>
45
46 if (!RUNNING_ON_VALGRIND)
47 {
48 // Code here crashes valgrind...
49 }
50
51That way, the test will still be run as part of the normal "make test"
52target, but will be ommitted when running "make valgrind".
53
54Coverage
55--------
56
57To build with the flags for coverage testing enabled and get coverage:
58
59 $ mkdir buildcoverage
60 $ cd buildcoverage
61 $ cmake -DCMAKE_BUILD_TYPE=coverage
62 $ make
63 $ make test
64 $ make coverage
65
66Unfortunately, it is not possible to get 100% coverage for some files,
67mainly due to gcc's generation of two destructors for dynamic and non-
68dynamic instances. For abstract base classes and for classes that
69prevent stack and static allocation, this causes one of the destructors
70to be reported as uncovered.
71
72There are also issues with some functions in header files that are
73incorrectly reported as uncovered due to inlining, as well as
74the impossibility of covering defensive assert(false) statements,
75such as an assert in the default branch of a switch, where the
76switch is meant to handle all possible cases explicitly.
77
78If you run a binary and get lots of warnings about a "merge mismatch for summaries",
79this is caused by having made changes to the source that add or remove code
80that was previously run, so the new coverage output cannot sensibly be merged
81into the old coverage output. You can get rid of this problem by running
82
83 $ make clean-coverage
84
85This deletes all the .gcda files, allowing the merge to (sometimes) succeed again.
86If this doesn't work either, the only remedy is to do a clean build.
87
88Code style
89----------
90
91Please maintain the existing coding style. For details
92on the style, see lp:canonical-client-development-guidelines.
93
94We use a format tool that fixes a whole lot of issues
95regarding code style. See the HACKING file of lp:unity-scopes-api
96for details on the tool.
97
98Thread and address sanitizer
99----------------------------
100
101Set SANITIZER to "thread" or "address" to build with the
102corresponding sanitizer enabled.
103
104Some libraries cause a cause a large number of warnings from
105thread sanitizer. The tsan-suppress file supresses the benign
106race conditions we currently know about. To run the tests
107(from the build directory) with these suppressions
108enabled, use:
109
110 $ TSAN_OPTIONS="suppressions=../tsan-suppress" make test
111
112If a test runs too slowly under address sanitizer, you can
113hide a section of code from address sanitzer with:
114
115#if defined(__has_feature)
116 #if !__has_feature(address_sanitizer)
117
118 // Code here takes forever under address sanitizer...
119
120 #endif
121#endif
0122
=== removed file 'cmake/coverage.cmake'
--- cmake/coverage.cmake 2013-09-30 12:17:23 +0000
+++ cmake/coverage.cmake 1970-01-01 00:00:00 +0000
@@ -1,34 +0,0 @@
1if (CMAKE_BUILD_TYPE MATCHES coverage)
2 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage")
3 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage")
4 set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} --coverage")
5 set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --coverage")
6
7 find_program(GCOVR_EXECUTABLE gcovr HINTS ${GCOVR_ROOT} "${GCOVR_ROOT}/bin")
8 if (NOT GCOVR_EXECUTABLE)
9 message(STATUS "Gcovr binary was not found, can not generate XML coverage info.")
10 else ()
11 message(STATUS "Gcovr found, can generate XML coverage info.")
12 add_custom_target (coverage-xml
13 WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
14 COMMAND "${GCOVR_EXECUTABLE}" --exclude="test.*" -x -r "${CMAKE_SOURCE_DIR}"
15 --object-directory=${CMAKE_BINARY_DIR} -o coverage.xml)
16 endif()
17
18 find_program(LCOV_EXECUTABLE lcov HINTS ${LCOV_ROOT} "${GCOVR_ROOT}/bin")
19 find_program(GENHTML_EXECUTABLE genhtml HINTS ${GENHTML_ROOT})
20 if (NOT LCOV_EXECUTABLE)
21 message(STATUS "Lcov binary was not found, can not generate HTML coverage info.")
22 else ()
23 if(NOT GENHTML_EXECUTABLE)
24 message(STATUS "Genthml binary not found, can not generate HTML coverage info.")
25 else()
26 message(STATUS "Lcov and genhtml found, can generate HTML coverage info.")
27 add_custom_target (coverage-html
28 WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
29 COMMAND "${LCOV_EXECUTABLE}" --directory ${CMAKE_BINARY_DIR} --capture --output-file coverage.info --no-checksum
30 COMMAND "${GENHTML_EXECUTABLE}" --prefix ${CMAKE_BINARY_DIR} --output-directory coveragereport --title "Code Coverage" --legend --show-details coverage.info
31 )
32 endif()
33 endif()
34endif()
350
=== modified file 'data/CMakeLists.txt'
--- data/CMakeLists.txt 2014-09-26 11:24:27 +0000
+++ data/CMakeLists.txt 2015-07-14 06:30:34 +0000
@@ -22,4 +22,3 @@
22 "${CMAKE_CURRENT_BINARY_DIR}/thumbnailer"22 "${CMAKE_CURRENT_BINARY_DIR}/thumbnailer"
23 DESTINATION "${CMAKE_INSTALL_SYSCONFDIR}/apport/blacklist.d"23 DESTINATION "${CMAKE_INSTALL_SYSCONFDIR}/apport/blacklist.d"
24)24)
25
2625
=== modified file 'data/com.canonical.Unity.Thumbnailer.gschema.xml'
--- data/com.canonical.Unity.Thumbnailer.gschema.xml 2014-09-16 13:00:17 +0000
+++ data/com.canonical.Unity.Thumbnailer.gschema.xml 2015-07-14 06:30:34 +0000
@@ -6,5 +6,72 @@
6 <summary>API key for dash.ubuntu.com service</summary>6 <summary>API key for dash.ubuntu.com service</summary>
7 <description>API key for dash.ubuntu.com service</description>7 <description>API key for dash.ubuntu.com service</description>
8 </key>8 </key>
9
10 <key type="i" name="full-size-cache-size">
11 <default>50</default>
12 <summary>Size of the full-size image cache in megabytes</summary>
13 <description>The full-size cache is used to store full-size extracted media artwork and downloaded album art.</description>
14 </key>
15
16 <key type="i" name="thumbnail-cache-size">
17 <default>100</default>
18 <summary>Size of the thumbnail image cache in megabytes</summary>
19 <description>The thumbnail image cache stores scaled thumbnail images.</description>
20 </key>
21
22 <key type="i" name="failure-cache-size">
23 <default>2</default>
24 <summary>Size of the failure cache in megabytes</summary>
25 <description>The failure cache records information about failed downloads or failed thumbnail extractions.</description>
26 </key>
27
28 <key type="i" name="max-thumbnail-size">
29 <default>1920</default>
30 <summary>Maximum size in pixels for a thumbnail</summary>
31 <description>
32 Requests for thumbnails larger than this will automatically reduce the thumbnail to max-thumbnail-size in the larger dimension. An exception are requests for local thumbnails with size 0x0, which are returned in their original size.
33 </description>
34 </key>
35
36 <key type="i" name="retry-not-found-hours">
37 <default>168</default>
38 <summary>Time to wait before re-trying for remote artwork that did not exist</summary>
39 <description>
40 If artwork cannot be retrieved because the remote server authoritavely confirmed that no artwork exists for an artist and album, this parameter defines how long the thumbnailer waits before trying to download the same image again. The default is 168 hours (one week).
41 </description>
42 </key>
43
44 <key type="i" name="retry-error-hours">
45 <default>2</default>
46 <summary>Time to wait before re-trying remote artwork that failed to download</summary>
47 <description>
48 If artwork cannot be retrieved from the remote server due to an unexpected error (such as the server not responding), this parameter defines how long the thumbnailer waits before trying to download the same image again. The default is two hours.
49 </description>
50 </key>
51
52 <key type="i" name="max-downloads">
53 <default>2</default>
54 <summary>Maximum number of concurrent downloads</summary>
55 <description>
56 This parameter sets the maximum number of concurrent downloads for remote artwork.
57 </description>
58 </key>
59
60 <key type="i" name="max-extractions">
61 <default>0</default>
62 <summary>Maximum number of concurrent image extractions</summary>
63 <description>
64 This parameter sets the maximum number of concurrent image extractions from local media files. The default value is zero, which sets the value according to the number of CPU cores.
65 </description>
66 </key>
67
68 <key type="i" name="extraction-timeout">
69 <default>10</default>
70 <summary>Maximum amount of time to wait for an image extraction or download (in seconds)</summary>
71 <description>
72 This parameter sets the amount of time (in seconds) to wait for a remote image download or
73 a thumbnail extraction before giving up.
74 </description>
75 </key>
9 </schema>76 </schema>
10</schemalist>77</schemalist>
1178
=== modified file 'debian/changelog'
--- debian/changelog 2015-03-12 08:38:44 +0000
+++ debian/changelog 2015-07-14 06:30:34 +0000
@@ -1,3 +1,52 @@
1thumbnailer (2.1-0ubuntu1) UNRELEASED; urgency=medium
2
3 [ James Henstridge ]
4 * Expose more settings for the thumbnailer daemon via GSettings.
5 * Change the security policy implementation to use aa_query_label()
6 for file access checks rather than relying on file descriptor
7 passing. This avoids the file descriptor exhaustion bugs with the
8 previous implementation. (LP: #1381713)
9
10 [ Michi Henning ]
11 * Add thumbnailer-admin tool, which can be used to check the status
12 of the cache and generate thumbnails via the command line.
13 * Add time stamps to log messages.
14 * Reduce the memory footprint of small caches, which in turn reduces
15 the footprint of thumbnailer-service.
16 * Don't implicitly compact the cache on service shutdown, as this
17 can take some time.
18 * Persist the cache stats over restarts of thumbnailer-service.
19 * Don't save JPEG thumbnails at quality=100, since the quality
20 improvement isn't justified by the extra storage.
21 * Don't retry downloads when we have a hit from the failure cache.
22 * Warn if an app requests an unsized thumbnail.
23
24 -- James Henstridge <james.henstridge@canonical.com> Mon, 22 Jun 2015 17:31:39 +0800
25
26thumbnailer (2.0+15.10.20150527-0ubuntu2) wily; urgency=medium
27
28 * Switch to unversioned Conflicts/Replaces on libthumbnailer0 to force
29 removal of the obsolete package on upgrade from the previous version.
30
31 -- Adam Conrad <adconrad@ubuntu.com> Wed, 17 Jun 2015 05:15:54 -0600
32
33thumbnailer (2.0+15.10.20150527-0ubuntu1) wily; urgency=medium
34
35 [ James Henstridge ]
36 * New upstream version with many changes:
37 - Switch to new cache implementation based on leveldb.
38 - Move local file thumbnailing to the central D-Bus daemon,
39 allowing for the cache to be shared between apps and its size
40 kept under control.
41 - The libthumbnailer library has been removed, since all clients
42 of the cache rely on the D-Bus interface now.
43 - The QML plugin now uses the QQuickAsyncImageProvider interface,
44 enabling multiple thumbnails to be loaded simultaneously.
45 - Improved test coverage.
46 * Remove the libthumbnailer0 and libthumbnailer-dev binary packages.
47
48 -- CI Train Bot <ci-train-bot@canonical.com> Wed, 27 May 2015 05:36:31 +0000
49
1thumbnailer (1.3+15.04.20150312-0ubuntu1) vivid; urgency=medium50thumbnailer (1.3+15.04.20150312-0ubuntu1) vivid; urgency=medium
251
3 [ Albert Astals Cid ]52 [ Albert Astals Cid ]
453
=== modified file 'debian/control'
--- debian/control 2014-09-25 07:23:54 +0000
+++ debian/control 2015-07-14 06:30:34 +0000
@@ -4,57 +4,43 @@
4Maintainer: Ubuntu Core Developers <ubuntu-devel-discuss@lists.ubuntu.com>4Maintainer: Ubuntu Core Developers <ubuntu-devel-discuss@lists.ubuntu.com>
5Standards-Version: 3.9.45Standards-Version: 3.9.4
6Build-Depends: cmake,6Build-Depends: cmake,
7 cmake-extras (>= 0.4),
7 debhelper (>= 9),8 debhelper (>= 9),
8 gstreamer1.0-plugins-good,9 gstreamer1.0-plugins-good,
10 libapparmor-dev,
11 libboost-filesystem-dev,
12 libboost-regex-dev,
9 libexif-dev,13 libexif-dev,
10 libgdk-pixbuf2.0-dev,14 libgdk-pixbuf2.0-dev,
11 libgstreamer1.0-dev,15 libgstreamer1.0-dev,
12 libgstreamer-plugins-base1.0-dev,16 libgstreamer-plugins-base1.0-dev,
13 libgtest-dev,17 libgtest-dev,
14 libsoup2.4-dev,18 libleveldb-dev,
15 libxml2-dev,19 libqtdbustest1-dev,
20 libunity-api-dev,
21 python3-tornado,
22 qml-module-qtquick2,
23 qml-module-qttest,
16 qt5-default,24 qt5-default,
17 qtbase5-dev,25 qtbase5-dev,
18 qtbase5-dev-tools,26 qtbase5-dev-tools,
19 qtdeclarative5-dev,27 qtdeclarative5-dev,
20 shared-mime-info,28 shared-mime-info,
29 xvfb,
21Homepage: https://launchpad.net/thumbnailer30Homepage: https://launchpad.net/thumbnailer
22# if you don't have have commit access to this branch but would like to upload31# if you don't have have commit access to this branch but would like to upload
23# directly to Ubuntu, don't worry: your changes will be merged back into the32# directly to Ubuntu, don't worry: your changes will be merged back into the
24# upstream branch33# upstream branch
25Vcs-Bzr: lp:thumbnailer34Vcs-Bzr: lp:thumbnailer
2635
27Package: libthumbnailer0
28Architecture: any
29Multi-Arch: same
30Pre-Depends: ${misc:Pre-Depends},
31Depends: ${misc:Depends},
32 ${shlibs:Depends},
33Description: generate thumbnails from files
34 Thumbnailer is a shared library that generates
35 thumbnail images for multiple file types such
36 as video and audio files.
37
38Package: libthumbnailer-dev
39Architecture: any
40Multi-Arch: same
41Pre-Depends: ${misc:Pre-Depends},
42Depends: ${misc:Depends},
43 ${shlibs:Depends},
44 gstreamer1.0-plugins-base,
45 gstreamer1.0-plugins-good,
46 libthumbnailer0 (= ${binary:Version}),
47Description: development files for thumbnailer
48 This package contains development files
49 for the thumbnailer package.
50
51Package: thumbnailer-service36Package: thumbnailer-service
52Architecture: any37Architecture: any
53Multi-Arch: foreign38Multi-Arch: foreign
54Pre-Depends: ${misc:Pre-Depends},39Pre-Depends: ${misc:Pre-Depends},
55Depends: ${misc:Depends},40Depends: ${misc:Depends},
56 ${shlibs:Depends},41 ${shlibs:Depends},
57 libthumbnailer0 (= ${binary:Version}),42Conflicts: libthumbnailer0
43Replaces: libthumbnailer0
58Description: D-Bus service for out of process thumbnailing44Description: D-Bus service for out of process thumbnailing
59 This package provides a D-Bus service that can provide thumbnails on45 This package provides a D-Bus service that can provide thumbnails on
60 behalf of another process.46 behalf of another process.
@@ -66,7 +52,6 @@
66Depends: ${misc:Depends},52Depends: ${misc:Depends},
67 ${shlibs:Depends},53 ${shlibs:Depends},
68 thumbnailer-common (= ${binary:Version}),54 thumbnailer-common (= ${binary:Version}),
69 libthumbnailer0 (= ${binary:Version}),
70Provides: ubuntu-thumbnailer-impl,55Provides: ubuntu-thumbnailer-impl,
71 ubuntu-thumbnailer-impl-0,56 ubuntu-thumbnailer-impl-0,
72Recommends: thumbnailer-service (= ${binary:Version}),57Recommends: thumbnailer-service (= ${binary:Version}),
7358
=== modified file 'debian/copyright'
--- debian/copyright 2013-09-30 15:55:07 +0000
+++ debian/copyright 2015-07-14 06:30:34 +0000
@@ -3,7 +3,27 @@
3Source: https://launchpad.net/thumbnailer3Source: https://launchpad.net/thumbnailer
44
5Files: *5Files: *
6Copyright: 2013 Canonical ltd6Copyright: 2015 Canonical Ltd.
7License: GPL-3
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License version 3 as
10 published by the Free Software Foundation.
11 .
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 .
17 On Debian/Ubuntu systems, the full text of the GPL v3 can be found in
18 `/usr/share/common-licenses/GPL-3'
19
20Files: plugins/*
21 src/core/*
22 include/core/*
23 tests/core/* include/internal/gobj_memory.h
24 include/internal/safe_strerror.h
25 src/safe_strerror.cpp
26Copyright: 2015 Canonical ltd
7License: LGPL-327License: LGPL-3
8 This program is free software: you can redistribute it and/or modify28 This program is free software: you can redistribute it and/or modify
9 it under the terms of version 3 of the GNU Lesser General Public29 it under the terms of version 3 of the GNU Lesser General Public
@@ -12,7 +32,7 @@
12 This program is distributed in the hope that it will be useful,32 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of33 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the34 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.35 GNU Lesser General Public License for more details.
16 .36 .
17 On Debian systems, the full text of the GNU Lesser General Public37 On Debian systems, the full text of the GNU Lesser General Public
18 License version 3 can be found in the file38 License version 3 can be found in the file
1939
=== removed file 'debian/libthumbnailer-dev.install'
--- debian/libthumbnailer-dev.install 2013-09-25 12:45:32 +0000
+++ debian/libthumbnailer-dev.install 1970-01-01 00:00:00 +0000
@@ -1,3 +0,0 @@
1usr/include/*
2usr/lib/*/lib*.so
3usr/lib/*/pkgconfig/*
40
=== removed file 'debian/libthumbnailer0.install'
--- debian/libthumbnailer0.install 2014-09-26 11:24:27 +0000
+++ debian/libthumbnailer0.install 1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
1usr/lib/*/libthumb*.so.*
2usr/lib/*/thumbnailer/vs-thumb
30
=== removed file 'debian/libthumbnailer0.symbols'
--- debian/libthumbnailer0.symbols 2014-08-11 14:20:31 +0000
+++ debian/libthumbnailer0.symbols 1970-01-01 00:00:00 +0000
@@ -1,7 +0,0 @@
1libthumbnailer.so.0 libthumbnailer0 #MINVER#
2 (c++)"Thumbnailer::get_thumbnail(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, ThumbnailSize)@Base" 1.0
3 (c++)"Thumbnailer::get_thumbnail(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, ThumbnailSize, ThumbnailPolicy)@Base" 1.0
4 (c++)"Thumbnailer::get_album_art(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, ThumbnailSize, ThumbnailPolicy)@Base" 1.0
5 (c++)"Thumbnailer::Thumbnailer()@Base" 1.0
6 (c++)"Thumbnailer::~Thumbnailer()@Base" 1.0
7 (c++)"Thumbnailer::get_artist_art(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, ThumbnailSize, ThumbnailPolicy)@Base" 1.1+14.10.20140811
80
=== modified file 'debian/rules'
--- debian/rules 2014-09-25 08:54:10 +0000
+++ debian/rules 2015-07-14 06:30:34 +0000
@@ -15,3 +15,6 @@
15override_dh_auto_configure:15override_dh_auto_configure:
16 dh_auto_configure -- -DCMAKE_INSTALL_SYSCONFDIR=/etc16 dh_auto_configure -- -DCMAKE_INSTALL_SYSCONFDIR=/etc
1717
18# Tests are not written to be run in parallel.
19override_dh_auto_test:
20 dh_auto_test --max-parallel=1 -- ARGS="--verbose"
1821
=== modified file 'debian/thumbnailer-service.install'
--- debian/thumbnailer-service.install 2014-09-16 12:12:21 +0000
+++ debian/thumbnailer-service.install 2015-07-14 06:30:34 +0000
@@ -1,3 +1,5 @@
1usr/bin/thumbnailer-admin
1usr/lib/*/thumbnailer/thumbnailer-service2usr/lib/*/thumbnailer/thumbnailer-service
3usr/lib/*/thumbnailer/vs-thumb
2usr/share/dbus-1/services/com.canonical.Thumbnailer.service4usr/share/dbus-1/services/com.canonical.Thumbnailer.service
3usr/share/glib-2.0/schemas/*5usr/share/glib-2.0/schemas/*
46
=== modified file 'include/CMakeLists.txt'
--- include/CMakeLists.txt 2013-10-02 09:43:16 +0000
+++ include/CMakeLists.txt 2015-07-14 06:30:34 +0000
@@ -1,12 +1,1 @@
1add_subdirectory(internal)1add_subdirectory(internal)
2
3install(FILES thumbnailer.h DESTINATION include)
4
5# Build and install a pkg-config file
6set(prefix ${CMAKE_INSTALL_PREFIX})
7set(exec_prefix ${prefix}/bin)
8set(libdir ${prefix}/${LIBDIR})
9set(includedir ${prefix}/include)
10set(pkg-name "lib${COL_LIB_BASENAME}")
11configure_file(thumbnailer.pc.in thumbnailer.pc @ONLY)
12install(FILES ${CMAKE_CURRENT_BINARY_DIR}/thumbnailer.pc DESTINATION ${LIBDIR}/pkgconfig)
132
=== added directory 'include/core'
=== added file 'include/core/CMakeLists.txt'
=== added file 'include/core/cache_codec.h'
--- include/core/cache_codec.h 1970-01-01 00:00:00 +0000
+++ include/core/cache_codec.h 2015-07-14 06:30:34 +0000
@@ -0,0 +1,50 @@
1/*
2 * Copyright (C) 2015 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Michi Henning <michi.henning@canonical.com>
17 */
18
19#pragma once
20
21#include <string>
22
23namespace core
24{
25
26/**
27Traits for serialization and deserialization of cache custom types.
28To use custom types, specialize this template
29for each custom type (other than string) in the `core` namespace.
30
31\warning Do _not_ specialize this struct for `std::string`!
32Doing so has no effect.
33
34\see PersistentCache
35*/
36
37template <typename T>
38struct CacheCodec
39{
40 /**
41 \brief Converts a value of custom type T into a string.
42 */
43 static std::string encode(T const& value);
44 /**
45 \brief Converts a string into a value of custom type T.
46 */
47 static T decode(std::string const& s);
48};
49
50} // namespace core
051
=== added file 'include/core/cache_discard_policy.h'
--- include/core/cache_discard_policy.h 1970-01-01 00:00:00 +0000
+++ include/core/cache_discard_policy.h 2015-07-14 06:30:34 +0000
@@ -0,0 +1,41 @@
1/*
2 * Copyright (C) 2015 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Michi Henning <michi.henning@canonical.com>
17 */
18
19#pragma once
20
21namespace core
22{
23
24/**
25\brief Indicates the discard policy to make room for entries when the cache is full.
26
27Once the cache is full and another entry is added,
28`lru_ttl` unconditionally deletes all entries that have expired and then,
29if deleting these entries did not create sufficient free space, deletes entries
30in least-recently-used order until enough space is available.
31
32If the discard policy is set to `lru_only`, entries do not maintain an expiry time and
33are therefore discarded strictly in LRU order.
34*/
35enum class CacheDiscardPolicy
36{
37 lru_ttl, ///< Evict expired entries first, followed by eviction in LRU order
38 lru_only ///< Evict in LRU order
39};
40
41} // namespace core
042
=== added file 'include/core/cache_events.h'
--- include/core/cache_events.h 1970-01-01 00:00:00 +0000
+++ include/core/cache_events.h 2015-07-14 06:30:34 +0000
@@ -0,0 +1,103 @@
1/*
2 * Copyright (C) 2015 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Michi Henning <michi.henning@canonical.com>
17 */
18
19#pragma once
20
21#include <cstdint>
22#include <type_traits>
23
24/**
25\brief Top-level namespace for core functionality.
26*/
27
28namespace core
29{
30
31/**
32\brief Event types that can be monitored.
33*/
34
35// Note: Any change here must have a corresponding change to
36// CacheEventIndex in core/internal/cache_event_indexes.h!
37
38enum class CacheEvent : uint32_t
39{
40 get = 1 << 0, ///< An entry was returned by a call to `get()`, `get_or_put()`, `take()`, or `take_data()`.
41 put = 1 << 1, ///< An entry was added by a call to `put()` or `get_or_put()`.
42 invalidate = 1 << 2, ///< An entry was removed by a call to `invalidate()`, `take()`, or `take_data()`.
43 touch = 1 << 3, ///< An entry was refreshed by a call to `touch()`.
44 miss = 1 << 4, ///< A call to `get()`, `get_or_put()`, `take()`, or `take_data()` failed to return an entry.
45 evict_ttl = 1 << 5, ///< An expired entry was evicted due to a call to `put()`,
46 ///< `get_or_put()`, `trim_to()`, or `resize()`.
47 evict_lru = 1 << 6, ///< The oldest entry was evicted due to a call to `put()`,
48 ///< `get_or_put()`, `trim_to()`, or `resize()`.
49 END_ = 1 << 7 ///< End marker
50};
51
52/**
53\brief Returns the bitwise OR of two event types.
54*/
55inline CacheEvent operator|(CacheEvent left, CacheEvent right)
56{
57 auto l = std::underlying_type<CacheEvent>::type(left);
58 auto r = std::underlying_type<CacheEvent>::type(right);
59 return CacheEvent(l | r);
60}
61
62/**
63\brief Assigns the bitwise OR of `left` and `right` to `left`.
64*/
65inline CacheEvent& operator|=(CacheEvent& left, CacheEvent right)
66{
67 return left = left | right;
68}
69
70/**
71\brief Returns the bitwise AND of two event types.
72*/
73inline CacheEvent operator&(CacheEvent left, CacheEvent right)
74{
75 auto l = std::underlying_type<CacheEvent>::type(left);
76 auto r = std::underlying_type<CacheEvent>::type(right);
77 return CacheEvent(l & r);
78}
79
80/**
81\brief Assigns the bitwise AND of `left` and `right` to `left`.
82*/
83inline CacheEvent& operator&=(CacheEvent& left, CacheEvent right)
84{
85 return left = left & right;
86}
87
88/**
89\brief Returns the bitwise NOT of `ev`. Unused bits are set to zero.
90*/
91inline CacheEvent operator~(CacheEvent ev)
92{
93 auto mask = std::underlying_type<CacheEvent>::type(CacheEvent::END_) - 1;
94 auto event = std::underlying_type<CacheEvent>::type(ev);
95 return CacheEvent(~event & mask);
96}
97
98/**
99\brief Convenience definition for all event types.
100*/
101static constexpr auto AllCacheEvents = CacheEvent(std::underlying_type<CacheEvent>::type(CacheEvent::END_) - 1);
102
103} // namespace core
0104
=== added directory 'include/core/internal'
=== added file 'include/core/internal/cache_event_indexes.h'
--- include/core/internal/cache_event_indexes.h 1970-01-01 00:00:00 +0000
+++ include/core/internal/cache_event_indexes.h 2015-07-14 06:30:34 +0000
@@ -0,0 +1,46 @@
1/*
2 * Copyright (C) 2015 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Michi Henning <michi.henning@canonical.com>
17 */
18
19#pragma once
20
21#include <cstdint>
22
23namespace core
24{
25
26namespace internal
27{
28
29// Note: Any change here must have a corresponding change to
30// CacheEvent in core/cache_events.h!
31
32enum class CacheEventIndex : uint32_t
33{
34 get = 0,
35 put = 1,
36 invalidate = 2,
37 touch = 3,
38 miss = 4,
39 evict_ttl = 5,
40 evict_lru = 6,
41 END_ = 7
42};
43
44} // namespace internal
45
46} // namespace core
047
=== added file 'include/core/internal/persistent_string_cache_impl.h'
--- include/core/internal/persistent_string_cache_impl.h 1970-01-01 00:00:00 +0000
+++ include/core/internal/persistent_string_cache_impl.h 2015-07-14 06:30:34 +0000
@@ -0,0 +1,191 @@
1/*
2 * Copyright (C) 2015 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Michi Henning <michi.henning@canonical.com>
17 */
18
19#pragma once
20
21#include <core/internal/cache_event_indexes.h>
22#include <core/persistent_string_cache.h>
23
24#include <leveldb/db.h>
25
26#include <mutex>
27#include <sstream>
28
29namespace core
30{
31
32namespace internal
33{
34
35class PersistentStringCacheStats;
36
37class PersistentStringCacheImpl
38{
39public:
40 PersistentStringCacheImpl(std::string const& cache_path,
41 int64_t max_size_in_bytes,
42 core::CacheDiscardPolicy policy,
43 PersistentStringCache* pimpl = nullptr);
44 PersistentStringCacheImpl(std::string const& cache_path, PersistentStringCache* pimpl = nullptr);
45
46 PersistentStringCacheImpl(PersistentStringCacheImpl const&) = delete;
47 PersistentStringCacheImpl& operator=(PersistentStringCacheImpl const&) = delete;
48
49 PersistentStringCacheImpl(PersistentStringCacheImpl&&) = delete;
50 PersistentStringCacheImpl& operator=(PersistentStringCacheImpl&&) = delete;
51
52 ~PersistentStringCacheImpl();
53
54 bool get(std::string const& key, std::string& value) const;
55 bool get(std::string const& key, std::string& value, std::string* metadata) const;
56 bool get_metadata(std::string const& key, std::string& metadata) const;
57 bool contains_key(std::string const& key) const;
58 int64_t size() const noexcept;
59 int64_t size_in_bytes() const noexcept;
60 int64_t max_size_in_bytes() const noexcept;
61 int64_t disk_size_in_bytes() const;
62 CacheDiscardPolicy discard_policy() const noexcept;
63 core::PersistentCacheStats stats() const;
64
65 bool put(std::string const& key,
66 std::string const& value,
67 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
68 bool put(std::string const& key,
69 char const* value,
70 int64_t size,
71 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
72 bool put(std::string const& key,
73 std::string const& value,
74 std::string const* metadata,
75 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
76 bool put(std::string const& key,
77 char const* value_data,
78 int64_t value_size,
79 char const* metadata_data,
80 int64_t metadata_size,
81 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
82 bool get_or_put(std::string const& key, std::string& value, PersistentStringCache::Loader load_func);
83 bool get_or_put(std::string const& key,
84 std::string& value,
85 std::string* metadata,
86 PersistentStringCache::Loader load_func);
87 bool put_metadata(std::string const& key, std::string const& metadata);
88 bool put_metadata(std::string const& key, char const* metadata, int64_t metadata_size);
89 bool take(std::string const& key, std::string& value);
90 bool take(std::string const& key, std::string& value, std::string* metadata);
91 bool invalidate(std::string const& key);
92 void invalidate(std::vector<std::string> const& keys);
93 template<typename It>
94 void invalidate(It begin, It end);
95 void invalidate(std::initializer_list<std::string> const& keys);
96 void invalidate();
97 bool touch(
98 std::string const& key,
99 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
100 void clear_stats() noexcept;
101 void resize(int64_t size_in_bytes);
102 void trim_to(int64_t used_size_in_bytes);
103 void compact();
104 void set_handler(CacheEvent events, PersistentStringCache::EventCallback cb);
105
106private:
107 // Simple struct to serialize/deserialize a data tuple.
108 // For the stringified representation, fields are separated
109 // by a space.
110
111 struct DataTuple
112 {
113 int64_t atime; // Last access time, msec since the epoch
114 int64_t etime; // Expiry time, msec since the epoch
115 int64_t size; // Size in bytes
116
117 DataTuple(int64_t at, int64_t et, int64_t s) noexcept
118 : atime(at)
119 , etime(et)
120 , size(s)
121 {
122 }
123
124 DataTuple() noexcept
125 : DataTuple(0, 0, 0)
126 {
127 }
128
129 DataTuple(std::string const& s) noexcept
130 {
131 std::istringstream is(s);
132 is >> atime >> etime >> size;
133 assert(!is.bad());
134 }
135
136 DataTuple(DataTuple const&) = default;
137 DataTuple(DataTuple&&) = default;
138
139 DataTuple& operator=(DataTuple const&) = default;
140 DataTuple& operator=(DataTuple&&) = default;
141
142 std::string to_string() const
143 {
144 std::ostringstream os;
145 os << atime << " " << etime << " " << size;
146 return os.str();
147 }
148 };
149
150 void init_stats();
151 void init_db(leveldb::Options options);
152 bool cache_is_new() const;
153 void write_version();
154 void check_version();
155 void read_settings();
156 void write_settings();
157 void read_stats();
158 void write_stats();
159 bool read_dirty_flag() const;
160 void write_dirty_flag(bool is_dirty);
161 DataTuple get_data(std::string const& key, bool& found) const;
162 bool get_value_and_metadata(std::string const& key,
163 DataTuple& data,
164 std::string& value,
165 std::string* metadata) const;
166 void batch_delete(std::string const& key, DataTuple const& data, leveldb::WriteBatch& batch);
167 void delete_entry(std::string const& key, DataTuple const& data);
168 void delete_at_least(int64_t bytes_needed, std::string const& skip_key = "");
169 void call_handler(std::string const& key, core::internal::CacheEventIndex event) const;
170
171 std::string make_message(leveldb::Status const& s, std::string const& msg) const;
172 std::string make_message(std::string const& msg) const;
173 void throw_if_error(leveldb::Status const& s, std::string const& msg) const;
174 void throw_logic_error(std::string const& msg) const;
175 void throw_invalid_argument(std::string const& msg) const;
176 void throw_corrupt_error(std::string const& msg) const;
177
178 PersistentStringCache* pimpl_; // Back-pointer to owning pimpl.
179 std::unique_ptr<leveldb::Cache> block_cache_; // Must be defined *before* db_!
180 std::unique_ptr<leveldb::DB> db_;
181 std::shared_ptr<PersistentStringCacheStats> stats_;
182
183 std::array<PersistentStringCache::EventCallback, static_cast<unsigned>(CacheEventIndex::END_)>
184 handlers_;
185
186 mutable std::recursive_mutex mutex_;
187};
188
189} // namespace internal
190
191} // namespace core
0192
=== added file 'include/core/internal/persistent_string_cache_stats.h'
--- include/core/internal/persistent_string_cache_stats.h 1970-01-01 00:00:00 +0000
+++ include/core/internal/persistent_string_cache_stats.h 2015-07-14 06:30:34 +0000
@@ -0,0 +1,237 @@
1/*
2 * Copyright (C) 2015 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Michi Henning <michi.henning@canonical.com>
17 */
18
19#pragma once
20
21#include <core/cache_discard_policy.h>
22#include <core/persistent_cache_stats.h>
23
24#include <cassert>
25#include <cmath>
26#include <cstring>
27#include <sstream>
28
29namespace core
30{
31
32namespace internal
33{
34
35// Simple stats class to keep track of accesses.
36
37class PersistentStringCacheStats
38{
39public:
40 PersistentStringCacheStats() noexcept
41 : policy_(CacheDiscardPolicy::lru_only)
42 , max_cache_size_(0)
43 , num_entries_(0)
44 , cache_size_(0)
45 , state_(Initialized)
46 {
47 clear();
48 hist_.resize(PersistentCacheStats::NUM_BINS, 0);
49 }
50
51 PersistentStringCacheStats(PersistentStringCacheStats const&) = default;
52 PersistentStringCacheStats(PersistentStringCacheStats&&) = default;
53 PersistentStringCacheStats& operator=(PersistentStringCacheStats const&) = default;
54 PersistentStringCacheStats& operator=(PersistentStringCacheStats&&) = default;
55
56 std::string cache_path_; // Immutable
57 core::CacheDiscardPolicy policy_; // Immutable
58 int64_t max_cache_size_;
59
60 int64_t num_entries_;
61 int64_t cache_size_;
62 PersistentCacheStats::Histogram hist_;
63
64 // Values below are reset by a call to clear().
65 int64_t hits_;
66 int64_t misses_;
67 int64_t hits_since_last_miss_;
68 int64_t misses_since_last_hit_;
69 int64_t longest_hit_run_;
70 int64_t longest_miss_run_;
71 int64_t ttl_evictions_;
72 int64_t lru_evictions_;
73 std::chrono::system_clock::time_point most_recent_hit_time_;
74 std::chrono::system_clock::time_point most_recent_miss_time_;
75 std::chrono::system_clock::time_point longest_hit_run_time_;
76 std::chrono::system_clock::time_point longest_miss_run_time_;
77
78 enum State
79 {
80 Initialized,
81 LastAccessWasHit,
82 LastAccessWasMiss
83 };
84 State state_;
85
86 void inc_hits() noexcept
87 {
88 ++hits_since_last_miss_;
89 ++hits_;
90 most_recent_hit_time_ = std::chrono::system_clock::now();
91 misses_since_last_hit_ = 0;
92 if (state_ != LastAccessWasHit)
93 {
94 state_ = LastAccessWasHit;
95 misses_since_last_hit_ = 0;
96 }
97 if (state_ != LastAccessWasMiss && hits_since_last_miss_ > longest_hit_run_)
98 {
99 longest_hit_run_ = hits_since_last_miss_;
100 longest_hit_run_time_ = most_recent_hit_time_;
101 }
102 }
103
104 void inc_misses() noexcept
105 {
106 ++misses_since_last_hit_;
107 ++misses_;
108 most_recent_miss_time_ = std::chrono::system_clock::now();
109 hits_since_last_miss_ = 0;
110 if (state_ != LastAccessWasMiss)
111 {
112 state_ = LastAccessWasMiss;
113 hits_since_last_miss_ = 0;
114 }
115 if (state_ != LastAccessWasHit && misses_since_last_hit_ > longest_miss_run_)
116 {
117 longest_miss_run_ = misses_since_last_hit_;
118 longest_miss_run_time_ = most_recent_miss_time_;
119 }
120 }
121
122 void hist_decrement(int64_t size) noexcept
123 {
124 assert(size > 0);
125 --hist_[size_to_index(size)];
126 }
127
128 void hist_increment(int64_t size) noexcept
129 {
130 assert(size > 0);
131 ++hist_[size_to_index(size)];
132 }
133
134 void hist_clear() noexcept
135 {
136 memset(&hist_[0], 0, hist_.size() * sizeof(PersistentCacheStats::Histogram::value_type));
137 }
138
139 void clear() noexcept
140 {
141 hits_ = 0;
142 misses_ = 0;
143 hits_since_last_miss_ = 0;
144 misses_since_last_hit_ = 0;
145 longest_hit_run_ = 0;
146 longest_miss_run_ = 0;
147 ttl_evictions_ = 0;
148 lru_evictions_ = 0;
149 most_recent_hit_time_ = std::chrono::system_clock::time_point();
150 most_recent_miss_time_ = std::chrono::system_clock::time_point();
151 longest_hit_run_time_ = std::chrono::system_clock::time_point();
152 longest_miss_run_time_ = std::chrono::system_clock::time_point();
153 }
154
155 // Serialize the stats.
156
157 std::string serialize() const
158 {
159 using namespace std;
160 using namespace std::chrono;
161
162 ostringstream os;
163 os << num_entries_ << " "
164 << cache_size_ << " "
165 << hits_ << " "
166 << misses_ << " "
167 << hits_since_last_miss_ << " "
168 << misses_since_last_hit_ << " "
169 << longest_hit_run_ << " "
170 << longest_miss_run_ << " "
171 << ttl_evictions_ << " "
172 << lru_evictions_ << " "
173 << duration_cast<milliseconds>(most_recent_hit_time_.time_since_epoch()).count() << " "
174 << duration_cast<milliseconds>(most_recent_miss_time_.time_since_epoch()).count() << " "
175 << duration_cast<milliseconds>(longest_hit_run_time_.time_since_epoch()).count() << " "
176 << duration_cast<milliseconds>(longest_miss_run_time_.time_since_epoch()).count();
177 for (auto d : hist_)
178 {
179 os << " " << d;
180 }
181 return os.str();
182 }
183
184 // De-serialize the stats.
185
186 void deserialize(const std::string& s) noexcept
187 {
188 using namespace std;
189 using namespace std::chrono;
190
191 istringstream is(s);
192 int64_t mrht;
193 int64_t mrmt;
194 int64_t lhrt;
195 int64_t lmrt;
196 is >> num_entries_
197 >> cache_size_
198 >> hits_
199 >> misses_
200 >> hits_since_last_miss_
201 >> misses_since_last_hit_
202 >> longest_hit_run_
203 >> longest_miss_run_
204 >> ttl_evictions_
205 >> lru_evictions_
206 >> mrht
207 >> mrmt
208 >> lhrt
209 >> lmrt;
210 for (unsigned i = 0; i < PersistentCacheStats::NUM_BINS; ++i)
211 {
212 is >> hist_[i];
213 }
214 assert(!is.bad());
215 most_recent_hit_time_ = system_clock::time_point(milliseconds(mrht));
216 most_recent_miss_time_ = system_clock::time_point(milliseconds(mrmt));
217 longest_hit_run_time_ = system_clock::time_point(milliseconds(lhrt));
218 longest_miss_run_time_ = system_clock::time_point(milliseconds(lmrt));
219 }
220
221private:
222 unsigned size_to_index(int64_t size) const noexcept
223 {
224 using namespace std;
225 assert(size > 0);
226 unsigned log = floor(log10(size)); // 0..9 = 0, 10..99 = 1, 100..199 = 2, etc.
227 unsigned exp = pow(10, log); // 0..9 = 1, 10..99 = 10, 100..199 = 100, etc.
228 unsigned div = size / exp; // Extracts first decimal digit of size.
229 int index = log * 10 + div - log - 1; // Partition each power of 10 into 9 bins.
230 index -= 8; // Sizes < 10 all go into bin 0;
231 return index < 0 ? 0 : (index > int(hist_.size()) - 1 ? hist_.size() - 1 : index);
232 }
233};
234
235} // namespace internal
236
237} // namespace core
0238
=== added file 'include/core/optional.h'
--- include/core/optional.h 1970-01-01 00:00:00 +0000
+++ include/core/optional.h 2015-07-14 06:30:34 +0000
@@ -0,0 +1,35 @@
1/*
2 * Copyright (C) 2015 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Michi Henning <michi.henning@canonical.com>
17 */
18
19#pragma once
20
21#include <boost/optional.hpp>
22
23namespace core
24{
25
26/**
27\brief Convenience typedef for nullable values.
28
29\note You should use `core::Optional` in preference to `boost::optional`
30in your code. This will ease an eventual transition to `std::optional`.
31*/
32template <typename T>
33using Optional = boost::optional<T>;
34
35} // namespace core
036
=== added file 'include/core/persistent_cache.h'
--- include/core/persistent_cache.h 1970-01-01 00:00:00 +0000
+++ include/core/persistent_cache.h 2015-07-14 06:30:34 +0000
@@ -0,0 +1,3104 @@
1/*
2 * Copyright (C) 2015 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Michi Henning <michi.henning@canonical.com>
17 */
18
19#pragma once
20
21#include <core/cache_codec.h>
22#include <core/persistent_string_cache.h>
23
24namespace core
25{
26
27/**
28\brief A persistent cache of key-value pairs and metadata of user-defined type.
29
30`K`, `V`, and `M` are the key type, value type, and metadata type, respectively.
31
32\note This template is a simple type adapter that forwards to
33core::PersistentStringCache. See the documentation there for details
34on cache operations and semantics.
35
36In order to use the cache with custom types (other than `std::string`),
37you must provide methods to encode the type to `string`, and decode
38from `string` back to the type.
39
40For example, suppose we have the following structure that we want to use
41as the key type of the cache:
42
43\code{.cpp}
44struct Person
45{
46 string name;
47 int age;
48};
49\endcode
50
51In order to use the cache with the `Person` struct as the key, you must specialize
52the CacheCodec struct in namespace `core`:
53
54\code{.cpp}
55namespace core // Specializations must be placed into namespace core.
56{
57
58template <>
59string CacheCodec<Person>::encode(Person const& p)
60{
61 ostringstream s;
62 s << p.age << ' ' << p.name;
63 return s.str();
64}
65
66template <>
67Person CacheCodec<Person>::decode(string const& str)
68{
69 istringstream s;
70 Person p;
71 s >> p.age >> p.name;
72 return p;
73}
74
75} // namespace core
76\endcode
77
78For this example, it is convenient to stream the age first because this
79guarantees that `decode()` will work correctly even if the name contains
80a space. The order in which you stream the fields does not matter, only that
81(for custom _key_ types) the string representation of each value is unique.
82
83With these two methods defined, we can now use the cache with `Person` instances
84as the key. For example:
85
86\code{.cpp}
87// Custom cache using Person as the key, and string as the value and metadata.
88using PersonCache = core::PersistentCache<Person, string>;
89
90auto c = PersonCache::open("my_cache", 1024 * 1024 * 1024, CacheDiscardPolicy::LRU_only);
91
92Person bjarne{"Bjarne Stroustrup", 65};
93c->put(bjarne, "C++ inventor");
94auto value = c->get(bjarne);
95if (value)
96{
97 cout << bjarne.name << ": " << *value << endl;
98}
99Person person{"no such person", 0};
100value = c->get(person);
101assert(!value);
102\endcode
103
104Running this code produces the output:
105
106\code
107Bjarne Stroustrup: C++ inventor
108\endcode
109
110You can use a custom type for the cache's value and metadata as well by simply providing
111CacheCodec specializations as needed.
112
113\see core::CacheCodec
114\see core::PersistentStringCache
115*/
116
117template <typename K, typename V, typename M = std::string>
118class PersistentCache
119{
120public:
121 /**
122 Convenience typedef for the return type of open().
123 */
124 typedef std::unique_ptr<PersistentCache<K, V, M>> UPtr;
125
126 /**
127 \brief Simple pair of value and metadata.
128 */
129 struct Data
130 {
131 /**
132 \brief Stores the value of an entry.
133 */
134 V value;
135
136 /**
137 \brief Stores the metadata of an entry. If no metadata exists for an entry,
138 `metadata` is returned as the empty string when it is retrieved.
139 */
140 M metadata;
141 };
142
143 /** @name Typedefs for nullable keys, values, and metadata.
144 */
145
146 //{@
147
148 /**
149 \brief Convenience typedefs for returning nullable values.
150
151 \note You should use `OptionalKey`, `OptionalValue`, and `OptionalMetadata` in
152 your code in preference to `boost::optional`. This will ease an eventual
153 transition to `std::optional`.
154 */
155 typedef Optional<K> OptionalKey;
156 typedef Optional<V> OptionalValue;
157 typedef Optional<M> OptionalMetadata;
158 typedef Optional<Data> OptionalData;
159
160 //@}
161
162 /** @name Copy and Assignment
163 */
164
165 //{@
166 PersistentCache(PersistentCache const&) = delete;
167 PersistentCache& operator=(PersistentCache const&) = delete;
168
169 PersistentCache(PersistentCache&&) = default;
170 PersistentCache& operator=(PersistentCache&&) = default;
171 //@}
172
173 /**
174 Destroys the instance.
175
176 The destructor compacts the database. This ensures that, while a cache is
177 not in use, it comsumes as little disk space as possible.
178 */
179 ~PersistentCache() = default;
180
181 /** @name Creation Methods
182 */
183
184 //{@
185
186 /**
187 \brief Creates or opens a PersistentCache.
188 */
189 static UPtr open(std::string const& cache_path, int64_t max_size_in_bytes, CacheDiscardPolicy policy);
190
191 /**
192 \brief Opens an existing PersistentCache.
193 */
194 static UPtr open(std::string const& cache_path);
195
196 //@}
197
198 /** @name Accessors
199 */
200
201 //{@
202
203 /**
204 \brief Returns the value of an entry in the cache, provided the entry has not expired.
205 */
206 OptionalValue get(K const& key) const;
207
208 /**
209 \brief Returns the data for an entry in the cache, provided the entry has not expired.
210 */
211 OptionalData get_data(K const& key) const;
212
213 /**
214 \brief Returns the metadata for an entry in the cache, provided the entry has not expired.
215 */
216 OptionalMetadata get_metadata(K const& key) const;
217
218 /**
219 \brief Tests if an (unexpired) entry is in the cache.
220 */
221 bool contains_key(K const& key) const;
222
223 /**
224 \brief Returns the number of entries in the cache.
225 */
226 int64_t size() const noexcept;
227
228 /**
229 \brief Returns the number of bytes consumed by entries in the cache.
230 */
231 int64_t size_in_bytes() const noexcept;
232
233 /**
234 \brief Returns the maximum size of the cache in bytes.
235 */
236 int64_t max_size_in_bytes() const noexcept;
237
238 /**
239 \brief Returns an estimate of the disk space consumed by the cache.
240 */
241 int64_t disk_size_in_bytes() const;
242
243 /**
244 \brief Returns the discard policy of the cache.
245 */
246 CacheDiscardPolicy discard_policy() const noexcept;
247
248 /**
249 \brief Returns statistics for the cache.
250 */
251 PersistentCacheStats stats() const;
252
253 //@}
254
255 /** @name Modifiers
256 */
257
258 //{@
259
260 /**
261 \brief Adds or updates an entry. If `V` = `std::string`, the method is also overloaded to
262 to accept `char const*` and `size`.
263 */
264 bool put(K const& key,
265 V const& value,
266 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
267
268 /**
269 \brief Adds or updates an entry and its metadata. If 'V' or `M` = `std::string`,
270 the method is also overloaded to accept `char const*` and `size`.
271 */
272 bool put(K const& key,
273 V const& value,
274 M const& metadata,
275 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
276
277 /**
278 \brief Function called by the cache to load an entry after a cache miss.
279 */
280 typedef std::function<void(K const& key, PersistentCache<K, V, M>& cache)> Loader;
281
282 /**
283 \brief Atomically retrieves or stores a cache entry.
284 */
285 OptionalValue get_or_put(K const& key, Loader const& load_func);
286
287 /**
288 \brief Atomically retrieves or stores a cache entry.
289 */
290 OptionalData get_or_put_data(K const& key, Loader const& load_func);
291
292 /**
293 \brief Adds or replaces the metadata for an entry. If `M` = `std::string`, an overload that accepts
294 `const char*` and `size` is provided as well.
295 */
296 bool put_metadata(K const& key, M const& metadata);
297
298 /**
299 \brief Removes an entry and returns its value.
300 */
301 OptionalValue take(K const& key);
302
303 /**
304 \brief Removes an entry and returns its value and metadata.
305 */
306 OptionalData take_data(K const& key);
307
308 /**
309 \brief Removes an entry and its associated metadata (if any).
310 */
311 bool invalidate(K const& key);
312
313 /**
314 \brief Atomically removes the specified entries from the cache.
315 */
316 void invalidate(std::vector<K> const& keys);
317
318 /**
319 \brief Atomically removes the specified entries from the cache.
320 */
321 template <typename It>
322 void invalidate(It begin, It end);
323
324 /**
325 \brief Atomically removes the specified entries from the cache.
326 */
327 void invalidate(std::initializer_list<K> const& keys);
328
329 /**
330 \brief Deletes all entries from the cache.
331 */
332 void invalidate();
333
334 /**
335 \brief Updates the access time of an entry.
336 */
337 bool touch(
338 K const& key,
339 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
340
341 /**
342 \brief Resets all statistics counters.
343 */
344 void clear_stats();
345
346 /**
347 \brief Changes the maximum size of the cache.
348 */
349 void resize(int64_t size_in_bytes);
350
351 /**
352 \brief Expires entries.
353 */
354 void trim_to(int64_t used_size_in_bytes);
355
356 /**
357 \brief Compacts the database.
358 */
359 void compact();
360
361 //@}
362
363 /** @name Monitoring cache activity
364 */
365
366 //{@
367
368 /**
369 \brief The type of a handler function.
370 */
371 typedef std::function<void(K const& key, CacheEvent ev, PersistentCacheStats const& stats)> EventCallback;
372
373 /**
374 \brief Installs a handler for one or more events.
375 */
376 void set_handler(CacheEvent events, EventCallback cb);
377
378 //@}
379
380private:
381 // @cond
382 PersistentCache(std::string const& cache_path, int64_t max_size_in_bytes, CacheDiscardPolicy policy);
383 PersistentCache(std::string const& cache_path);
384
385 std::unique_ptr<PersistentStringCache> p_;
386 // @endcond
387};
388
389// @cond
390
391// Method implementations. Out-of-line because, otherwise, things become completely unreadable.
392
393template <typename K, typename V, typename M>
394PersistentCache<K, V, M>::PersistentCache(std::string const& cache_path,
395 int64_t max_size_in_bytes,
396 CacheDiscardPolicy policy)
397 : p_(PersistentStringCache::open(cache_path, max_size_in_bytes, policy))
398{
399}
400
401template <typename K, typename V, typename M>
402PersistentCache<K, V, M>::PersistentCache(std::string const& cache_path)
403 : p_(PersistentStringCache::open(cache_path))
404{
405}
406
407template <typename K, typename V, typename M>
408typename PersistentCache<K, V, M>::UPtr PersistentCache<K, V, M>::open(std::string const& cache_path,
409 int64_t max_size_in_bytes,
410 CacheDiscardPolicy policy)
411{
412 return PersistentCache<K, V, M>::UPtr(new PersistentCache<K, V, M>(cache_path, max_size_in_bytes, policy));
413}
414
415template <typename K, typename V, typename M>
416typename PersistentCache<K, V, M>::UPtr PersistentCache<K, V, M>::open(std::string const& cache_path)
417{
418 return PersistentCache<K, V, M>::UPtr(new PersistentCache<K, V, M>(cache_path));
419}
420
421template <typename K, typename V, typename M>
422typename PersistentCache<K, V, M>::OptionalValue PersistentCache<K, V, M>::get(K const& key) const
423{
424 auto const& svalue = p_->get(CacheCodec<K>::encode(key));
425 return svalue ? OptionalValue(CacheCodec<V>::decode(*svalue)) : OptionalValue();
426}
427
428template <typename K, typename V, typename M>
429typename PersistentCache<K, V, M>::OptionalData PersistentCache<K, V, M>::get_data(K const& key) const
430{
431 auto sdata = p_->get_data(CacheCodec<K>::encode(key));
432 if (!sdata)
433 {
434 return OptionalData();
435 }
436 return OptionalData({CacheCodec<V>::decode(sdata->value), CacheCodec<M>::decode(sdata->metadata)});
437}
438
439template <typename K, typename V, typename M>
440typename PersistentCache<K, V, M>::OptionalMetadata PersistentCache<K, V, M>::get_metadata(K const& key) const
441{
442 auto smeta = p_->get_metadata(CacheCodec<K>::encode(key));
443 return smeta ? OptionalMetadata(CacheCodec<M>::decode(*smeta)) : OptionalMetadata();
444}
445
446template <typename K, typename V, typename M>
447bool PersistentCache<K, V, M>::contains_key(K const& key) const
448{
449 return p_->contains_key(CacheCodec<K>::encode(key));
450}
451
452template <typename K, typename V, typename M>
453int64_t PersistentCache<K, V, M>::size() const noexcept
454{
455 return p_->size();
456}
457
458template <typename K, typename V, typename M>
459int64_t PersistentCache<K, V, M>::size_in_bytes() const noexcept
460{
461 return p_->size_in_bytes();
462}
463
464template <typename K, typename V, typename M>
465int64_t PersistentCache<K, V, M>::max_size_in_bytes() const noexcept
466{
467 return p_->max_size_in_bytes();
468}
469
470template <typename K, typename V, typename M>
471int64_t PersistentCache<K, V, M>::disk_size_in_bytes() const
472{
473 return p_->disk_size_in_bytes();
474}
475
476template <typename K, typename V, typename M>
477CacheDiscardPolicy PersistentCache<K, V, M>::discard_policy() const noexcept
478{
479 return p_->discard_policy();
480}
481
482template <typename K, typename V, typename M>
483PersistentCacheStats PersistentCache<K, V, M>::stats() const
484{
485 return p_->stats();
486}
487
488template <typename K, typename V, typename M>
489bool PersistentCache<K, V, M>::put(K const& key,
490 V const& value,
491 std::chrono::time_point<std::chrono::system_clock> expiry_time)
492{
493 return p_->put(CacheCodec<K>::encode(key), CacheCodec<V>::encode(value), expiry_time);
494}
495
496template <typename K, typename V, typename M>
497bool PersistentCache<K, V, M>::put(K const& key,
498 V const& value,
499 M const& metadata,
500 std::chrono::time_point<std::chrono::system_clock> expiry_time)
501{
502 return p_->put(CacheCodec<K>::encode(key), CacheCodec<V>::encode(value), CacheCodec<M>::encode(metadata),
503 expiry_time);
504}
505
506template <typename K, typename V, typename M>
507typename PersistentCache<K, V, M>::OptionalValue PersistentCache<K, V, M>::get_or_put(
508 K const& key, PersistentCache<K, V, M>::Loader const& load_func)
509{
510 std::string const& skey = CacheCodec<K>::encode(key);
511 auto sload_func = [&](std::string const&, PersistentStringCache const&)
512 {
513 load_func(key, *this);
514 };
515 auto svalue = p_->get_or_put(skey, sload_func);
516 return svalue ? OptionalValue(CacheCodec<V>::decode(*svalue)) : OptionalValue();
517}
518
519template <typename K, typename V, typename M>
520typename PersistentCache<K, V, M>::OptionalData PersistentCache<K, V, M>::get_or_put_data(
521 K const& key, PersistentCache<K, V, M>::Loader const& load_func)
522{
523 std::string const& skey = CacheCodec<K>::encode(key);
524 auto sload_func = [&](std::string const&, PersistentStringCache const&)
525 {
526 load_func(key, *this);
527 };
528 auto sdata = p_->get_or_put_data(skey, sload_func);
529 if (!sdata)
530 {
531 return OptionalData();
532 }
533 return OptionalData({CacheCodec<V>::decode(sdata->value), CacheCodec<M>::decode(sdata->metadata)});
534}
535
536template <typename K, typename V, typename M>
537bool PersistentCache<K, V, M>::put_metadata(K const& key, M const& metadata)
538{
539 return p_->put_metadata(CacheCodec<K>::encode(key), CacheCodec<M>::encode(metadata));
540}
541
542template <typename K, typename V, typename M>
543typename PersistentCache<K, V, M>::OptionalValue PersistentCache<K, V, M>::take(K const& key)
544{
545 auto svalue = p_->take(CacheCodec<K>::encode(key));
546 return svalue ? OptionalValue(CacheCodec<V>::decode(*svalue)) : OptionalValue();
547}
548
549template <typename K, typename V, typename M>
550typename PersistentCache<K, V, M>::OptionalData PersistentCache<K, V, M>::take_data(K const& key)
551{
552 auto sdata = p_->take_data(CacheCodec<K>::encode(key));
553 if (!sdata)
554 {
555 return OptionalData();
556 }
557 return OptionalData({CacheCodec<V>::decode(sdata->value), CacheCodec<M>::decode(sdata->metadata)});
558}
559
560template <typename K, typename V, typename M>
561bool PersistentCache<K, V, M>::invalidate(K const& key)
562{
563 return p_->invalidate(CacheCodec<K>::encode(key));
564}
565
566template <typename K, typename V, typename M>
567void PersistentCache<K, V, M>::invalidate(std::vector<K> const& keys)
568{
569 invalidate(keys.begin(), keys.end());
570}
571
572template <typename K, typename V, typename M>
573template <typename It>
574void PersistentCache<K, V, M>::invalidate(It begin, It end)
575{
576 std::vector<std::string> skeys;
577 for (auto&& it = begin; it < end; ++it)
578 {
579 skeys.push_back(CacheCodec<K>::encode(*it));
580 }
581 p_->invalidate(skeys.begin(), skeys.end());
582}
583
584template <typename K, typename V, typename M>
585void PersistentCache<K, V, M>::invalidate(std::initializer_list<K> const& keys)
586{
587 invalidate(keys.begin(), keys.end());
588}
589
590template <typename K, typename V, typename M>
591void PersistentCache<K, V, M>::invalidate()
592{
593 p_->invalidate();
594}
595
596template <typename K, typename V, typename M>
597bool PersistentCache<K, V, M>::touch(K const& key, std::chrono::time_point<std::chrono::system_clock> expiry_time)
598{
599 return p_->touch(CacheCodec<K>::encode(key), expiry_time);
600}
601
602template <typename K, typename V, typename M>
603void PersistentCache<K, V, M>::clear_stats()
604{
605 p_->clear_stats();
606}
607
608template <typename K, typename V, typename M>
609void PersistentCache<K, V, M>::resize(int64_t size_in_bytes)
610{
611 p_->resize(size_in_bytes);
612}
613
614template <typename K, typename V, typename M>
615void PersistentCache<K, V, M>::trim_to(int64_t used_size_in_bytes)
616{
617 p_->trim_to(used_size_in_bytes);
618}
619
620template <typename K, typename V, typename M>
621void PersistentCache<K, V, M>::compact()
622{
623 p_->compact();
624}
625
626template <typename K, typename V, typename M>
627void PersistentCache<K, V, M>::set_handler(CacheEvent events, EventCallback cb)
628{
629 auto scb = [cb](std::string const& key, CacheEvent ev, PersistentCacheStats const& c)
630 {
631 cb(CacheCodec<K>::decode(key), ev, c);
632 };
633 p_->set_handler(events, scb);
634}
635
636// Below are specializations for the various combinations of one or more of K, V, and M
637// being of type std::string. Without this, we would end up calling through a string-to-string
638// codec, which would force a copy for everything of type string, which is brutally inefficient.
639//
640// This is verbose because we must specialize the class template in order to avoid
641// calling the CacheCodec methods for type string. The combinations that follow are
642// <s,V,M>, <K,s,M>, <K,V,s>, <s,s,M>, <s,V,s>, <K,s,s>, and <s,s,s>.
643// The code is identical, except that, where we know that K, V, or M are std::string,
644// it avoids calling the encode()/decode() methods.
645
646// Specialization for K = std::string.
647
648template <typename V, typename M>
649class PersistentCache<std::string, V, M>
650{
651public:
652 typedef std::unique_ptr<PersistentCache<std::string, V, M>> UPtr;
653
654 typedef Optional<std::string> OptionalKey;
655 typedef Optional<V> OptionalValue;
656 typedef Optional<M> OptionalMetadata;
657
658 struct Data
659 {
660 V value;
661 M metadata;
662 };
663 typedef Optional<Data> OptionalData;
664
665 PersistentCache(PersistentCache const&) = delete;
666 PersistentCache& operator=(PersistentCache const&) = delete;
667
668 PersistentCache(PersistentCache&&) = default;
669 PersistentCache& operator=(PersistentCache&&) = default;
670
671 ~PersistentCache() = default;
672
673 static UPtr open(std::string const& cache_path, int64_t max_size_in_bytes, CacheDiscardPolicy policy);
674 static UPtr open(std::string const& cache_path);
675
676 OptionalValue get(std::string const& key) const;
677 OptionalData get_data(std::string const& key) const;
678 OptionalMetadata get_metadata(std::string const& key) const;
679 bool contains_key(std::string const& key) const;
680 int64_t size() const noexcept;
681 int64_t size_in_bytes() const noexcept;
682 int64_t max_size_in_bytes() const noexcept;
683 int64_t disk_size_in_bytes() const;
684 CacheDiscardPolicy discard_policy() const noexcept;
685 PersistentCacheStats stats() const;
686
687 bool put(std::string const& key,
688 V const& value,
689 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
690 bool put(std::string const& key,
691 V const& value,
692 M const& metadata,
693 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
694
695 typedef std::function<void(std::string const& key, PersistentCache<std::string, V, M>& cache)> Loader;
696
697 OptionalValue get_or_put(std::string const& key, Loader const& load_func);
698 OptionalData get_or_put_data(std::string const& key, Loader const& load_func);
699
700 bool put_metadata(std::string const& key, M const& metadata);
701 OptionalValue take(std::string const& key);
702 OptionalData take_data(std::string const& key);
703 bool invalidate(std::string const& key);
704 void invalidate(std::vector<std::string> const& keys);
705 template <typename It>
706 void invalidate(It begin, It end);
707 void invalidate(std::initializer_list<std::string> const& keys);
708 void invalidate();
709 bool touch(
710 std::string const& key,
711 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
712 void clear_stats();
713 void resize(int64_t size_in_bytes);
714 void trim_to(int64_t used_size_in_bytes);
715 void compact();
716
717 typedef std::function<void(std::string const& key, CacheEvent ev, PersistentCacheStats const& stats)> EventCallback;
718
719 void set_handler(CacheEvent events, EventCallback cb);
720
721private:
722 PersistentCache(std::string const& cache_path, int64_t max_size_in_bytes, CacheDiscardPolicy policy);
723 PersistentCache(std::string const& cache_path);
724
725 std::unique_ptr<PersistentStringCache> p_;
726};
727
728template <typename V, typename M>
729PersistentCache<std::string, V, M>::PersistentCache(std::string const& cache_path,
730 int64_t max_size_in_bytes,
731 CacheDiscardPolicy policy)
732 : p_(PersistentStringCache::open(cache_path, max_size_in_bytes, policy))
733{
734}
735
736template <typename V, typename M>
737PersistentCache<std::string, V, M>::PersistentCache(std::string const& cache_path)
738 : p_(PersistentStringCache::open(cache_path))
739{
740}
741
742template <typename V, typename M>
743typename PersistentCache<std::string, V, M>::UPtr PersistentCache<std::string, V, M>::open(
744 std::string const& cache_path, int64_t max_size_in_bytes, CacheDiscardPolicy policy)
745{
746 return PersistentCache<std::string, V, M>::UPtr(
747 new PersistentCache<std::string, V, M>(cache_path, max_size_in_bytes, policy));
748}
749
750template <typename V, typename M>
751typename PersistentCache<std::string, V, M>::UPtr PersistentCache<std::string, V, M>::open(
752 std::string const& cache_path)
753{
754 return PersistentCache<std::string, V, M>::UPtr(new PersistentCache<std::string, V, M>(cache_path));
755}
756
757template <typename V, typename M>
758typename PersistentCache<std::string, V, M>::OptionalValue PersistentCache<std::string, V, M>::get(
759 std::string const& key) const
760{
761 auto const& svalue = p_->get(key);
762 return svalue ? OptionalValue(CacheCodec<V>::decode(*svalue)) : OptionalValue();
763}
764
765template <typename V, typename M>
766typename PersistentCache<std::string, V, M>::OptionalData PersistentCache<std::string, V, M>::get_data(
767 std::string const& key) const
768{
769 auto sdata = p_->get_data(key);
770 if (!sdata)
771 {
772 return OptionalData();
773 }
774 return OptionalData({CacheCodec<V>::decode(sdata->value), CacheCodec<M>::decode(sdata->metadata)});
775}
776
777template <typename V, typename M>
778typename PersistentCache<std::string, V, M>::OptionalMetadata PersistentCache<std::string, V, M>::get_metadata(
779 std::string const& key) const
780{
781 auto smeta = p_->get_metadata(key);
782 return smeta ? OptionalMetadata(CacheCodec<M>::decode(*smeta)) : OptionalMetadata();
783}
784
785template <typename V, typename M>
786bool PersistentCache<std::string, V, M>::contains_key(std::string const& key) const
787{
788 return p_->contains_key(key);
789}
790
791template <typename V, typename M>
792int64_t PersistentCache<std::string, V, M>::size() const noexcept
793{
794 return p_->size();
795}
796
797template <typename V, typename M>
798int64_t PersistentCache<std::string, V, M>::size_in_bytes() const noexcept
799{
800 return p_->size_in_bytes();
801}
802
803template <typename V, typename M>
804int64_t PersistentCache<std::string, V, M>::max_size_in_bytes() const noexcept
805{
806 return p_->max_size_in_bytes();
807}
808
809template <typename V, typename M>
810int64_t PersistentCache<std::string, V, M>::disk_size_in_bytes() const
811{
812 return p_->disk_size_in_bytes();
813}
814
815template <typename V, typename M>
816CacheDiscardPolicy PersistentCache<std::string, V, M>::discard_policy() const noexcept
817{
818 return p_->discard_policy();
819}
820
821template <typename V, typename M>
822PersistentCacheStats PersistentCache<std::string, V, M>::stats() const
823{
824 return p_->stats();
825}
826
827template <typename V, typename M>
828bool PersistentCache<std::string, V, M>::put(std::string const& key,
829 V const& value,
830 std::chrono::time_point<std::chrono::system_clock> expiry_time)
831{
832 return p_->put(key, CacheCodec<V>::encode(value), expiry_time);
833}
834
835template <typename V, typename M>
836bool PersistentCache<std::string, V, M>::put(std::string const& key,
837 V const& value,
838 M const& metadata,
839 std::chrono::time_point<std::chrono::system_clock> expiry_time)
840{
841 return p_->put(key, CacheCodec<V>::encode(value), CacheCodec<M>::encode(metadata), expiry_time);
842}
843
844template <typename V, typename M>
845typename PersistentCache<std::string, V, M>::OptionalValue PersistentCache<std::string, V, M>::get_or_put(
846 std::string const& key, PersistentCache<std::string, V, M>::Loader const& load_func)
847{
848 auto sload_func = [&](std::string const&, PersistentStringCache const&)
849 {
850 load_func(key, *this);
851 };
852 auto svalue = p_->get_or_put(key, sload_func);
853 return svalue ? OptionalValue(CacheCodec<V>::decode(*svalue)) : OptionalValue();
854}
855
856template <typename V, typename M>
857typename PersistentCache<std::string, V, M>::OptionalData PersistentCache<std::string, V, M>::get_or_put_data(
858 std::string const& key, PersistentCache<std::string, V, M>::Loader const& load_func)
859{
860 auto sload_func = [&](std::string const&, PersistentStringCache const&)
861 {
862 load_func(key, *this);
863 };
864 auto sdata = p_->get_or_put_data(key, sload_func);
865 if (!sdata)
866 {
867 return OptionalData();
868 }
869 return OptionalData({CacheCodec<V>::decode(sdata->value), CacheCodec<M>::decode(sdata->metadata)});
870}
871
872template <typename V, typename M>
873bool PersistentCache<std::string, V, M>::put_metadata(std::string const& key, M const& metadata)
874{
875 return p_->put_metadata(key, CacheCodec<M>::encode(metadata));
876}
877
878template <typename V, typename M>
879typename PersistentCache<std::string, V, M>::OptionalValue PersistentCache<std::string, V, M>::take(
880 std::string const& key)
881{
882 auto svalue = p_->take(key);
883 return svalue ? OptionalValue(CacheCodec<V>::decode(*svalue)) : OptionalValue();
884}
885
886template <typename V, typename M>
887typename PersistentCache<std::string, V, M>::OptionalData PersistentCache<std::string, V, M>::take_data(
888 std::string const& key)
889{
890 auto sdata = p_->take_data(key);
891 if (!sdata)
892 {
893 return OptionalData();
894 }
895 return OptionalData({CacheCodec<V>::decode(sdata->value), CacheCodec<M>::decode(sdata->metadata)});
896}
897
898template <typename V, typename M>
899bool PersistentCache<std::string, V, M>::invalidate(std::string const& key)
900{
901 return p_->invalidate(key);
902}
903
904template <typename V, typename M>
905void PersistentCache<std::string, V, M>::invalidate(std::vector<std::string> const& keys)
906{
907 invalidate(keys.begin(), keys.end());
908}
909
910template <typename V, typename M>
911template <typename It>
912void PersistentCache<std::string, V, M>::invalidate(It begin, It end)
913{
914 std::vector<std::string> skeys;
915 for (auto&& it = begin; it < end; ++it)
916 {
917 skeys.push_back(*it);
918 }
919 p_->invalidate(skeys.begin(), skeys.end());
920}
921
922template <typename V, typename M>
923void PersistentCache<std::string, V, M>::invalidate(std::initializer_list<std::string> const& keys)
924{
925 invalidate(keys.begin(), keys.end());
926}
927
928template <typename V, typename M>
929void PersistentCache<std::string, V, M>::invalidate()
930{
931 p_->invalidate();
932}
933
934template <typename V, typename M>
935bool PersistentCache<std::string, V, M>::touch(std::string const& key,
936 std::chrono::time_point<std::chrono::system_clock> expiry_time)
937{
938 return p_->touch(key, expiry_time);
939}
940
941template <typename V, typename M>
942void PersistentCache<std::string, V, M>::clear_stats()
943{
944 p_->clear_stats();
945}
946
947template <typename V, typename M>
948void PersistentCache<std::string, V, M>::resize(int64_t size_in_bytes)
949{
950 p_->resize(size_in_bytes);
951}
952
953template <typename V, typename M>
954void PersistentCache<std::string, V, M>::trim_to(int64_t used_size_in_bytes)
955{
956 p_->trim_to(used_size_in_bytes);
957}
958
959template <typename V, typename M>
960void PersistentCache<std::string, V, M>::compact()
961{
962 p_->compact();
963}
964
965template <typename V, typename M>
966void PersistentCache<std::string, V, M>::set_handler(CacheEvent events, EventCallback cb)
967{
968 p_->set_handler(events, cb);
969}
970
971// Specialization for V = std::string.
972
973template <typename K, typename M>
974class PersistentCache<K, std::string, M>
975{
976public:
977 typedef std::unique_ptr<PersistentCache<K, std::string, M>> UPtr;
978
979 typedef Optional<K> OptionalKey;
980 typedef Optional<std::string> OptionalValue;
981 typedef Optional<M> OptionalMetadata;
982
983 struct Data
984 {
985 std::string value;
986 M metadata;
987 };
988 typedef Optional<Data> OptionalData;
989
990 PersistentCache(PersistentCache const&) = delete;
991 PersistentCache& operator=(PersistentCache const&) = delete;
992
993 PersistentCache(PersistentCache&&) = default;
994 PersistentCache& operator=(PersistentCache&&) = default;
995
996 ~PersistentCache() = default;
997
998 static UPtr open(std::string const& cache_path, int64_t max_size_in_bytes, CacheDiscardPolicy policy);
999 static UPtr open(std::string const& cache_path);
1000
1001 OptionalValue get(K const& key) const;
1002 OptionalData get_data(K const& key) const;
1003 OptionalMetadata get_metadata(K const& key) const;
1004 bool contains_key(K const& key) const;
1005 int64_t size() const noexcept;
1006 int64_t size_in_bytes() const noexcept;
1007 int64_t max_size_in_bytes() const noexcept;
1008 int64_t disk_size_in_bytes() const;
1009 CacheDiscardPolicy discard_policy() const noexcept;
1010 PersistentCacheStats stats() const;
1011
1012 bool put(K const& key,
1013 std::string const& value,
1014 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
1015 bool put(K const& key,
1016 char const* value,
1017 int64_t size,
1018 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
1019 bool put(K const& key,
1020 std::string const& value,
1021 M const& metadata,
1022 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
1023 bool put(K const& key,
1024 char const* value,
1025 int64_t value_size,
1026 M const& metadata,
1027 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
1028
1029 typedef std::function<void(K const& key, PersistentCache<K, std::string, M>& cache)> Loader;
1030
1031 OptionalValue get_or_put(K const& key, Loader const& load_func);
1032 OptionalData get_or_put_data(K const& key, Loader const& load_func);
1033
1034 bool put_metadata(K const& key, M const& metadata);
1035 OptionalValue take(K const& key);
1036 OptionalData take_data(K const& key);
1037 bool invalidate(K const& key);
1038 void invalidate(std::vector<K> const& keys);
1039 template <typename It>
1040 void invalidate(It begin, It end);
1041 void invalidate(std::initializer_list<K> const& keys);
1042 void invalidate();
1043 bool touch(
1044 K const& key,
1045 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
1046 void clear_stats();
1047 void resize(int64_t size_in_bytes);
1048 void trim_to(int64_t used_size_in_bytes);
1049 void compact();
1050
1051 typedef std::function<void(K const& key, CacheEvent ev, PersistentCacheStats const& stats)> EventCallback;
1052
1053 void set_handler(CacheEvent events, EventCallback cb);
1054
1055private:
1056 PersistentCache(std::string const& cache_path, int64_t max_size_in_bytes, CacheDiscardPolicy policy);
1057 PersistentCache(std::string const& cache_path);
1058
1059 std::unique_ptr<PersistentStringCache> p_;
1060};
1061
1062template <typename K, typename M>
1063PersistentCache<K, std::string, M>::PersistentCache(std::string const& cache_path,
1064 int64_t max_size_in_bytes,
1065 CacheDiscardPolicy policy)
1066 : p_(PersistentStringCache::open(cache_path, max_size_in_bytes, policy))
1067{
1068}
1069
1070template <typename K, typename M>
1071PersistentCache<K, std::string, M>::PersistentCache(std::string const& cache_path)
1072 : p_(PersistentStringCache::open(cache_path))
1073{
1074}
1075
1076template <typename K, typename M>
1077typename PersistentCache<K, std::string, M>::UPtr PersistentCache<K, std::string, M>::open(
1078 std::string const& cache_path, int64_t max_size_in_bytes, CacheDiscardPolicy policy)
1079{
1080 return PersistentCache<K, std::string, M>::UPtr(
1081 new PersistentCache<K, std::string, M>(cache_path, max_size_in_bytes, policy));
1082}
1083
1084template <typename K, typename M>
1085typename PersistentCache<K, std::string, M>::UPtr PersistentCache<K, std::string, M>::open(
1086 std::string const& cache_path)
1087{
1088 return PersistentCache<K, std::string, M>::UPtr(new PersistentCache<K, std::string, M>(cache_path));
1089}
1090
1091template <typename K, typename M>
1092typename PersistentCache<K, std::string, M>::OptionalValue PersistentCache<K, std::string, M>::get(K const& key) const
1093{
1094 auto const& svalue = p_->get(CacheCodec<K>::encode(key));
1095 return svalue ? OptionalValue(*svalue) : OptionalValue();
1096}
1097
1098template <typename K, typename M>
1099typename PersistentCache<K, std::string, M>::OptionalData PersistentCache<K, std::string, M>::get_data(
1100 K const& key) const
1101{
1102 auto sdata = p_->get_data(CacheCodec<K>::encode(key));
1103 if (!sdata)
1104 {
1105 return OptionalData();
1106 }
1107 return OptionalData({sdata->value, CacheCodec<M>::decode(sdata->metadata)});
1108}
1109
1110template <typename K, typename M>
1111typename PersistentCache<K, std::string, M>::OptionalMetadata PersistentCache<K, std::string, M>::get_metadata(
1112 K const& key) const
1113{
1114 auto smeta = p_->get_metadata(CacheCodec<K>::encode(key));
1115 return smeta ? OptionalMetadata(CacheCodec<M>::decode(*smeta)) : OptionalMetadata();
1116}
1117
1118template <typename K, typename M>
1119bool PersistentCache<K, std::string, M>::contains_key(K const& key) const
1120{
1121 return p_->contains_key(CacheCodec<K>::encode(key));
1122}
1123
1124template <typename K, typename M>
1125int64_t PersistentCache<K, std::string, M>::size() const noexcept
1126{
1127 return p_->size();
1128}
1129
1130template <typename K, typename M>
1131int64_t PersistentCache<K, std::string, M>::size_in_bytes() const noexcept
1132{
1133 return p_->size_in_bytes();
1134}
1135
1136template <typename K, typename M>
1137int64_t PersistentCache<K, std::string, M>::max_size_in_bytes() const noexcept
1138{
1139 return p_->max_size_in_bytes();
1140}
1141
1142template <typename K, typename M>
1143int64_t PersistentCache<K, std::string, M>::disk_size_in_bytes() const
1144{
1145 return p_->disk_size_in_bytes();
1146}
1147
1148template <typename K, typename M>
1149CacheDiscardPolicy PersistentCache<K, std::string, M>::discard_policy() const noexcept
1150{
1151 return p_->discard_policy();
1152}
1153
1154template <typename K, typename M>
1155PersistentCacheStats PersistentCache<K, std::string, M>::stats() const
1156{
1157 return p_->stats();
1158}
1159
1160template <typename K, typename M>
1161bool PersistentCache<K, std::string, M>::put(K const& key,
1162 std::string const& value,
1163 std::chrono::time_point<std::chrono::system_clock> expiry_time)
1164{
1165 return p_->put(CacheCodec<K>::encode(key), value, expiry_time);
1166}
1167
1168template <typename K, typename M>
1169bool PersistentCache<K, std::string, M>::put(K const& key,
1170 char const* value,
1171 int64_t size,
1172 std::chrono::time_point<std::chrono::system_clock> expiry_time)
1173{
1174 return p_->put(CacheCodec<K>::encode(key), value, size, expiry_time);
1175}
1176
1177template <typename K, typename M>
1178bool PersistentCache<K, std::string, M>::put(K const& key,
1179 std::string const& value,
1180 M const& metadata,
1181 std::chrono::time_point<std::chrono::system_clock> expiry_time)
1182{
1183 return p_->put(CacheCodec<K>::encode(key), value, CacheCodec<M>::encode(metadata), expiry_time);
1184}
1185
1186template <typename K, typename M>
1187bool PersistentCache<K, std::string, M>::put(K const& key,
1188 char const* value,
1189 int64_t size,
1190 M const& metadata,
1191 std::chrono::time_point<std::chrono::system_clock> expiry_time)
1192{
1193 std::string md = CacheCodec<M>::encode(metadata);
1194 return p_->put(CacheCodec<K>::encode(key), value, size, md.data(), md.size(), expiry_time);
1195}
1196
1197template <typename K, typename M>
1198typename PersistentCache<K, std::string, M>::OptionalValue PersistentCache<K, std::string, M>::get_or_put(
1199 K const& key, PersistentCache<K, std::string, M>::Loader const& load_func)
1200{
1201 std::string const& skey = CacheCodec<K>::encode(key);
1202 auto sload_func = [&](std::string const&, PersistentStringCache const&)
1203 {
1204 load_func(key, *this);
1205 };
1206 auto svalue = p_->get_or_put(skey, sload_func);
1207 return svalue ? OptionalValue(*svalue) : OptionalValue();
1208}
1209
1210template <typename K, typename M>
1211typename PersistentCache<K, std::string, M>::OptionalData PersistentCache<K, std::string, M>::get_or_put_data(
1212 K const& key, PersistentCache<K, std::string, M>::Loader const& load_func)
1213{
1214 std::string const& skey = CacheCodec<K>::encode(key);
1215 auto sload_func = [&](std::string const&, PersistentStringCache const&)
1216 {
1217 load_func(key, *this);
1218 };
1219 auto sdata = p_->get_or_put_data(skey, sload_func);
1220 if (!sdata)
1221 {
1222 return OptionalData();
1223 }
1224 return OptionalData({sdata->value, CacheCodec<M>::decode(sdata->metadata)});
1225}
1226
1227template <typename K, typename M>
1228bool PersistentCache<K, std::string, M>::put_metadata(K const& key, M const& metadata)
1229{
1230 return p_->put_metadata(CacheCodec<K>::encode(key), CacheCodec<M>::encode(metadata));
1231}
1232
1233template <typename K, typename M>
1234typename PersistentCache<K, std::string, M>::OptionalValue PersistentCache<K, std::string, M>::take(K const& key)
1235{
1236 auto svalue = p_->take(CacheCodec<K>::encode(key));
1237 return svalue ? OptionalValue(*svalue) : OptionalValue();
1238}
1239
1240template <typename K, typename M>
1241typename PersistentCache<K, std::string, M>::OptionalData PersistentCache<K, std::string, M>::take_data(
1242 K const& key)
1243{
1244 auto sdata = p_->take_data(CacheCodec<K>::encode(key));
1245 if (!sdata)
1246 {
1247 return OptionalData();
1248 }
1249 return OptionalData({sdata->value, CacheCodec<M>::decode(sdata->metadata)});
1250}
1251
1252template <typename K, typename M>
1253bool PersistentCache<K, std::string, M>::invalidate(K const& key)
1254{
1255 return p_->invalidate(CacheCodec<K>::encode(key));
1256}
1257
1258template <typename K, typename M>
1259void PersistentCache<K, std::string, M>::invalidate(std::vector<K> const& keys)
1260{
1261 invalidate(keys.begin(), keys.end());
1262}
1263
1264template <typename K, typename M>
1265template <typename It>
1266void PersistentCache<K, std::string, M>::invalidate(It begin, It end)
1267{
1268 std::vector<std::string> skeys;
1269 for (auto&& it = begin; it < end; ++it)
1270 {
1271 skeys.push_back(CacheCodec<K>::encode(*it));
1272 }
1273 p_->invalidate(skeys.begin(), skeys.end());
1274}
1275
1276template <typename K, typename M>
1277void PersistentCache<K, std::string, M>::invalidate(std::initializer_list<K> const& keys)
1278{
1279 invalidate(keys.begin(), keys.end());
1280}
1281
1282template <typename K, typename M>
1283void PersistentCache<K, std::string, M>::invalidate()
1284{
1285 p_->invalidate();
1286}
1287
1288template <typename K, typename M>
1289bool PersistentCache<K, std::string, M>::touch(K const& key,
1290 std::chrono::time_point<std::chrono::system_clock> expiry_time)
1291{
1292 return p_->touch(CacheCodec<K>::encode(key), expiry_time);
1293}
1294
1295template <typename K, typename M>
1296void PersistentCache<K, std::string, M>::clear_stats()
1297{
1298 p_->clear_stats();
1299}
1300
1301template <typename K, typename M>
1302void PersistentCache<K, std::string, M>::resize(int64_t size_in_bytes)
1303{
1304 p_->resize(size_in_bytes);
1305}
1306
1307template <typename K, typename M>
1308void PersistentCache<K, std::string, M>::trim_to(int64_t used_size_in_bytes)
1309{
1310 p_->trim_to(used_size_in_bytes);
1311}
1312
1313template <typename K, typename M>
1314void PersistentCache<K, std::string, M>::compact()
1315{
1316 p_->compact();
1317}
1318
1319template <typename K, typename M>
1320void PersistentCache<K, std::string, M>::set_handler(CacheEvent events, EventCallback cb)
1321{
1322 auto scb = [cb](std::string const& key, CacheEvent ev, PersistentCacheStats const& c)
1323 {
1324 cb(CacheCodec<K>::decode(key), ev, c);
1325 };
1326 p_->set_handler(events, scb);
1327}
1328
1329// Specialization for M = std::string.
1330
1331template <typename K, typename V>
1332class PersistentCache<K, V, std::string>
1333{
1334public:
1335 typedef std::unique_ptr<PersistentCache<K, V, std::string>> UPtr;
1336
1337 typedef Optional<K> OptionalKey;
1338 typedef Optional<V> OptionalValue;
1339 typedef Optional<std::string> OptionalMetadata;
1340
1341 struct Data
1342 {
1343 V value;
1344 std::string metadata;
1345 };
1346 typedef Optional<Data> OptionalData;
1347
1348 PersistentCache(PersistentCache const&) = delete;
1349 PersistentCache& operator=(PersistentCache const&) = delete;
1350
1351 PersistentCache(PersistentCache&&) = default;
1352 PersistentCache& operator=(PersistentCache&&) = default;
1353
1354 ~PersistentCache() = default;
1355
1356 static UPtr open(std::string const& cache_path, int64_t max_size_in_bytes, CacheDiscardPolicy policy);
1357 static UPtr open(std::string const& cache_path);
1358
1359 OptionalValue get(K const& key) const;
1360 OptionalData get_data(K const& key) const;
1361 OptionalMetadata get_metadata(K const& key) const;
1362 bool contains_key(K const& key) const;
1363 int64_t size() const noexcept;
1364 int64_t size_in_bytes() const noexcept;
1365 int64_t max_size_in_bytes() const noexcept;
1366 int64_t disk_size_in_bytes() const;
1367 CacheDiscardPolicy discard_policy() const noexcept;
1368 PersistentCacheStats stats() const;
1369
1370 bool put(K const& key,
1371 V const& value,
1372 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
1373 bool put(K const& key,
1374 V const& value,
1375 std::string const& metadata,
1376 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
1377 bool put(K const& key,
1378 V const& value,
1379 char const* metadata,
1380 int64_t size,
1381 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
1382
1383 typedef std::function<void(K const& key, PersistentCache<K, V, std::string>& cache)> Loader;
1384
1385 OptionalValue get_or_put(K const& key, Loader const& load_func);
1386 OptionalData get_or_put_data(K const& key, Loader const& load_func);
1387
1388 bool put_metadata(K const& key, std::string const& metadata);
1389 bool put_metadata(K const& key, char const* metadata, int64_t size);
1390 OptionalValue take(K const& key);
1391 OptionalData take_data(K const& key);
1392 bool invalidate(K const& key);
1393 void invalidate(std::vector<K> const& keys);
1394 template <typename It>
1395 void invalidate(It begin, It end);
1396 void invalidate(std::initializer_list<K> const& keys);
1397 void invalidate();
1398 bool touch(
1399 K const& key,
1400 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
1401 void clear_stats();
1402 void resize(int64_t size_in_bytes);
1403 void trim_to(int64_t used_size_in_bytes);
1404 void compact();
1405
1406 typedef std::function<void(K const& key, CacheEvent ev, PersistentCacheStats const& stats)> EventCallback;
1407
1408 void set_handler(CacheEvent events, EventCallback cb);
1409
1410private:
1411 PersistentCache(std::string const& cache_path, int64_t max_size_in_bytes, CacheDiscardPolicy policy);
1412 PersistentCache(std::string const& cache_path);
1413
1414 std::unique_ptr<PersistentStringCache> p_;
1415};
1416
1417template <typename K, typename V>
1418PersistentCache<K, V, std::string>::PersistentCache(std::string const& cache_path,
1419 int64_t max_size_in_bytes,
1420 CacheDiscardPolicy policy)
1421 : p_(PersistentStringCache::open(cache_path, max_size_in_bytes, policy))
1422{
1423}
1424
1425template <typename K, typename V>
1426PersistentCache<K, V, std::string>::PersistentCache(std::string const& cache_path)
1427 : p_(PersistentStringCache::open(cache_path))
1428{
1429}
1430
1431template <typename K, typename V>
1432typename PersistentCache<K, V, std::string>::UPtr PersistentCache<K, V, std::string>::open(
1433 std::string const& cache_path, int64_t max_size_in_bytes, CacheDiscardPolicy policy)
1434{
1435 return PersistentCache<K, V, std::string>::UPtr(
1436 new PersistentCache<K, V, std::string>(cache_path, max_size_in_bytes, policy));
1437}
1438
1439template <typename K, typename V>
1440typename PersistentCache<K, V, std::string>::UPtr PersistentCache<K, V, std::string>::open(
1441 std::string const& cache_path)
1442{
1443 return PersistentCache<K, V, std::string>::UPtr(new PersistentCache<K, V, std::string>(cache_path));
1444}
1445
1446template <typename K, typename V>
1447typename PersistentCache<K, V, std::string>::OptionalValue PersistentCache<K, V, std::string>::get(K const& key) const
1448{
1449 auto const& svalue = p_->get(CacheCodec<K>::encode(key));
1450 return svalue ? OptionalValue(CacheCodec<V>::decode(*svalue)) : OptionalValue();
1451}
1452
1453template <typename K, typename V>
1454typename PersistentCache<K, V, std::string>::OptionalData PersistentCache<K, V, std::string>::get_data(
1455 K const& key) const
1456{
1457 auto sdata = p_->get_data(CacheCodec<K>::encode(key));
1458 if (!sdata)
1459 {
1460 return OptionalData();
1461 }
1462 return OptionalData({CacheCodec<V>::decode(sdata->value), sdata->metadata});
1463}
1464
1465template <typename K, typename V>
1466typename PersistentCache<K, V, std::string>::OptionalMetadata PersistentCache<K, V, std::string>::get_metadata(
1467 K const& key) const
1468{
1469 auto smeta = p_->get_metadata(CacheCodec<K>::encode(key));
1470 return smeta ? OptionalMetadata(*smeta) : OptionalMetadata();
1471}
1472
1473template <typename K, typename V>
1474bool PersistentCache<K, V, std::string>::contains_key(K const& key) const
1475{
1476 return p_->contains_key(CacheCodec<K>::encode(key));
1477}
1478
1479template <typename K, typename V>
1480int64_t PersistentCache<K, V, std::string>::size() const noexcept
1481{
1482 return p_->size();
1483}
1484
1485template <typename K, typename V>
1486int64_t PersistentCache<K, V, std::string>::size_in_bytes() const noexcept
1487{
1488 return p_->size_in_bytes();
1489}
1490
1491template <typename K, typename V>
1492int64_t PersistentCache<K, V, std::string>::max_size_in_bytes() const noexcept
1493{
1494 return p_->max_size_in_bytes();
1495}
1496
1497template <typename K, typename V>
1498int64_t PersistentCache<K, V, std::string>::disk_size_in_bytes() const
1499{
1500 return p_->disk_size_in_bytes();
1501}
1502
1503template <typename K, typename V>
1504CacheDiscardPolicy PersistentCache<K, V, std::string>::discard_policy() const noexcept
1505{
1506 return p_->discard_policy();
1507}
1508
1509template <typename K, typename V>
1510PersistentCacheStats PersistentCache<K, V, std::string>::stats() const
1511{
1512 return p_->stats();
1513}
1514
1515template <typename K, typename V>
1516bool PersistentCache<K, V, std::string>::put(K const& key,
1517 V const& value,
1518 std::chrono::time_point<std::chrono::system_clock> expiry_time)
1519{
1520 return p_->put(CacheCodec<K>::encode(key), CacheCodec<V>::encode(value), expiry_time);
1521}
1522
1523template <typename K, typename V>
1524bool PersistentCache<K, V, std::string>::put(K const& key,
1525 V const& value,
1526 std::string const& metadata,
1527 std::chrono::time_point<std::chrono::system_clock> expiry_time)
1528{
1529 std::string v = CacheCodec<V>::encode(value);
1530 return p_->put(CacheCodec<K>::encode(key), v.data(), v.size(), metadata.data(), metadata.size(), expiry_time);
1531}
1532
1533template <typename K, typename V>
1534bool PersistentCache<K, V, std::string>::put(K const& key,
1535 V const& value,
1536 char const* metadata,
1537 int64_t size,
1538 std::chrono::time_point<std::chrono::system_clock> expiry_time)
1539{
1540 std::string v = CacheCodec<V>::encode(value);
1541 return p_->put(CacheCodec<K>::encode(key), v.data(), v.size(), metadata, size, expiry_time);
1542}
1543
1544template <typename K, typename V>
1545typename PersistentCache<K, V, std::string>::OptionalValue PersistentCache<K, V, std::string>::get_or_put(
1546 K const& key, PersistentCache<K, V, std::string>::Loader const& load_func)
1547{
1548 std::string const& skey = CacheCodec<K>::encode(key);
1549 auto sload_func = [&](std::string const&, PersistentStringCache const&)
1550 {
1551 load_func(key, *this);
1552 };
1553 auto svalue = p_->get_or_put(skey, sload_func);
1554 return svalue ? OptionalValue(CacheCodec<V>::decode(*svalue)) : OptionalValue();
1555}
1556
1557template <typename K, typename V>
1558typename PersistentCache<K, V, std::string>::OptionalData PersistentCache<K, V, std::string>::get_or_put_data(
1559 K const& key, PersistentCache<K, V, std::string>::Loader const& load_func)
1560{
1561 std::string const& skey = CacheCodec<K>::encode(key);
1562 auto sload_func = [&](std::string const&, PersistentStringCache const&)
1563 {
1564 load_func(key, *this);
1565 };
1566 auto sdata = p_->get_or_put_data(skey, sload_func);
1567 if (!sdata)
1568 {
1569 return OptionalData();
1570 }
1571 return OptionalData({CacheCodec<V>::decode(sdata->value), sdata->metadata});
1572}
1573
1574template <typename K, typename V>
1575bool PersistentCache<K, V, std::string>::put_metadata(K const& key, std::string const& metadata)
1576{
1577 return p_->put_metadata(CacheCodec<K>::encode(key), metadata);
1578}
1579
1580template <typename K, typename V>
1581bool PersistentCache<K, V, std::string>::put_metadata(K const& key, char const* metadata, int64_t size)
1582{
1583 return p_->put_metadata(CacheCodec<K>::encode(key), metadata, size);
1584}
1585
1586template <typename K, typename V>
1587typename PersistentCache<K, V, std::string>::OptionalValue PersistentCache<K, V, std::string>::take(K const& key)
1588{
1589 auto svalue = p_->take(CacheCodec<K>::encode(key));
1590 return svalue ? OptionalValue(CacheCodec<V>::decode(*svalue)) : OptionalValue();
1591}
1592
1593template <typename K, typename V>
1594typename PersistentCache<K, V, std::string>::OptionalData PersistentCache<K, V, std::string>::take_data(
1595 K const& key)
1596{
1597 auto sdata = p_->take_data(CacheCodec<K>::encode(key));
1598 if (!sdata)
1599 {
1600 return OptionalData();
1601 }
1602 return OptionalData({CacheCodec<V>::decode(sdata->value), sdata->metadata});
1603}
1604
1605template <typename K, typename V>
1606bool PersistentCache<K, V, std::string>::invalidate(K const& key)
1607{
1608 return p_->invalidate(CacheCodec<K>::encode(key));
1609}
1610
1611template <typename K, typename V>
1612void PersistentCache<K, V, std::string>::invalidate(std::vector<K> const& keys)
1613{
1614 invalidate(keys.begin(), keys.end());
1615}
1616
1617template <typename K, typename V>
1618template <typename It>
1619void PersistentCache<K, V, std::string>::invalidate(It begin, It end)
1620{
1621 std::vector<std::string> skeys;
1622 for (auto&& it = begin; it < end; ++it)
1623 {
1624 skeys.push_back(CacheCodec<K>::encode(*it));
1625 }
1626 p_->invalidate(skeys.begin(), skeys.end());
1627}
1628
1629template <typename K, typename V>
1630void PersistentCache<K, V, std::string>::invalidate(std::initializer_list<K> const& keys)
1631{
1632 invalidate(keys.begin(), keys.end());
1633}
1634
1635template <typename K, typename V>
1636void PersistentCache<K, V, std::string>::invalidate()
1637{
1638 p_->invalidate();
1639}
1640
1641template <typename K, typename V>
1642bool PersistentCache<K, V, std::string>::touch(K const& key,
1643 std::chrono::time_point<std::chrono::system_clock> expiry_time)
1644{
1645 return p_->touch(CacheCodec<K>::encode(key), expiry_time);
1646}
1647
1648template <typename K, typename V>
1649void PersistentCache<K, V, std::string>::clear_stats()
1650{
1651 p_->clear_stats();
1652}
1653
1654template <typename K, typename V>
1655void PersistentCache<K, V, std::string>::resize(int64_t size_in_bytes)
1656{
1657 p_->resize(size_in_bytes);
1658}
1659
1660template <typename K, typename V>
1661void PersistentCache<K, V, std::string>::trim_to(int64_t used_size_in_bytes)
1662{
1663 p_->trim_to(used_size_in_bytes);
1664}
1665
1666template <typename K, typename V>
1667void PersistentCache<K, V, std::string>::compact()
1668{
1669 p_->compact();
1670}
1671
1672template <typename K, typename V>
1673void PersistentCache<K, V, std::string>::set_handler(CacheEvent events, EventCallback cb)
1674{
1675 auto scb = [cb](std::string const& key, CacheEvent ev, PersistentCacheStats const& c)
1676 {
1677 cb(CacheCodec<K>::decode(key), ev, c);
1678 };
1679 p_->set_handler(events, scb);
1680}
1681
1682// Specialization for K and V = std::string.
1683
1684template <typename M>
1685class PersistentCache<std::string, std::string, M>
1686{
1687public:
1688 typedef std::unique_ptr<PersistentCache<std::string, std::string, M>> UPtr;
1689
1690 typedef Optional<std::string> OptionalKey;
1691 typedef Optional<std::string> OptionalValue;
1692 typedef Optional<M> OptionalMetadata;
1693
1694 struct Data
1695 {
1696 std::string value;
1697 M metadata;
1698 };
1699 typedef Optional<Data> OptionalData;
1700
1701 PersistentCache(PersistentCache const&) = delete;
1702 PersistentCache& operator=(PersistentCache const&) = delete;
1703
1704 PersistentCache(PersistentCache&&) = default;
1705 PersistentCache& operator=(PersistentCache&&) = default;
1706
1707 ~PersistentCache() = default;
1708
1709 static UPtr open(std::string const& cache_path, int64_t max_size_in_bytes, CacheDiscardPolicy policy);
1710 static UPtr open(std::string const& cache_path);
1711
1712 OptionalValue get(std::string const& key) const;
1713 OptionalData get_data(std::string const& key) const;
1714 OptionalMetadata get_metadata(std::string const& key) const;
1715 bool contains_key(std::string const& key) const;
1716 int64_t size() const noexcept;
1717 int64_t size_in_bytes() const noexcept;
1718 int64_t max_size_in_bytes() const noexcept;
1719 int64_t disk_size_in_bytes() const;
1720 CacheDiscardPolicy discard_policy() const noexcept;
1721 PersistentCacheStats stats() const;
1722
1723 bool put(std::string const& key,
1724 std::string const& value,
1725 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
1726 bool put(std::string const& key,
1727 char const* value,
1728 int64_t size,
1729 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
1730 bool put(std::string const& key,
1731 std::string const& value,
1732 M const& metadata,
1733 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
1734 bool put(std::string const& key,
1735 char const* value,
1736 int64_t value_size,
1737 M const& metadata,
1738 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
1739
1740 typedef std::function<void(std::string const& key, PersistentCache<std::string, std::string, M>& cache)> Loader;
1741
1742 OptionalValue get_or_put(std::string const& key, Loader const& load_func);
1743 OptionalData get_or_put_data(std::string const& key, Loader const& load_func);
1744
1745 bool put_metadata(std::string const& key, M const& metadata);
1746 OptionalValue take(std::string const& key);
1747 OptionalData take_data(std::string const& key);
1748 bool invalidate(std::string const& key);
1749 void invalidate(std::vector<std::string> const& keys);
1750 template <typename It>
1751 void invalidate(It begin, It end);
1752 void invalidate(std::initializer_list<std::string> const& keys);
1753 void invalidate();
1754 bool touch(
1755 std::string const& key,
1756 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
1757 void clear_stats();
1758 void resize(int64_t size_in_bytes);
1759 void trim_to(int64_t used_size_in_bytes);
1760 void compact();
1761
1762 typedef std::function<void(std::string const& key, CacheEvent ev, PersistentCacheStats const& stats)> EventCallback;
1763
1764 void set_handler(CacheEvent events, EventCallback cb);
1765
1766private:
1767 PersistentCache(std::string const& cache_path, int64_t max_size_in_bytes, CacheDiscardPolicy policy);
1768 PersistentCache(std::string const& cache_path);
1769
1770 std::unique_ptr<PersistentStringCache> p_;
1771};
1772
1773template <typename M>
1774PersistentCache<std::string, std::string, M>::PersistentCache(std::string const& cache_path,
1775 int64_t max_size_in_bytes,
1776 CacheDiscardPolicy policy)
1777 : p_(PersistentStringCache::open(cache_path, max_size_in_bytes, policy))
1778{
1779}
1780
1781template <typename M>
1782PersistentCache<std::string, std::string, M>::PersistentCache(std::string const& cache_path)
1783 : p_(PersistentStringCache::open(cache_path))
1784{
1785}
1786
1787template <typename M>
1788typename PersistentCache<std::string, std::string, M>::UPtr PersistentCache<std::string, std::string, M>::open(
1789 std::string const& cache_path, int64_t max_size_in_bytes, CacheDiscardPolicy policy)
1790{
1791 return PersistentCache<std::string, std::string, M>::UPtr(
1792 new PersistentCache<std::string, std::string, M>(cache_path, max_size_in_bytes, policy));
1793}
1794
1795template <typename M>
1796typename PersistentCache<std::string, std::string, M>::UPtr PersistentCache<std::string, std::string, M>::open(
1797 std::string const& cache_path)
1798{
1799 return PersistentCache<std::string, std::string, M>::UPtr(
1800 new PersistentCache<std::string, std::string, M>(cache_path));
1801}
1802
1803template <typename M>
1804typename PersistentCache<std::string, std::string, M>::OptionalValue PersistentCache<std::string, std::string, M>::get(
1805 std::string const& key) const
1806{
1807 auto const& svalue = p_->get(key);
1808 return svalue ? OptionalValue(*svalue) : OptionalValue();
1809}
1810
1811template <typename M>
1812typename PersistentCache<std::string, std::string, M>::OptionalData
1813 PersistentCache<std::string, std::string, M>::get_data(std::string const& key) const
1814{
1815 auto sdata = p_->get_data(key);
1816 if (!sdata)
1817 {
1818 return OptionalData();
1819 }
1820 return OptionalData({sdata->value, CacheCodec<M>::decode(sdata->metadata)});
1821}
1822
1823template <typename M>
1824typename PersistentCache<std::string, std::string, M>::OptionalMetadata
1825 PersistentCache<std::string, std::string, M>::get_metadata(std::string const& key) const
1826{
1827 auto smeta = p_->get_metadata(key);
1828 return smeta ? OptionalMetadata(CacheCodec<M>::decode(*smeta)) : OptionalMetadata();
1829}
1830
1831template <typename M>
1832bool PersistentCache<std::string, std::string, M>::contains_key(std::string const& key) const
1833{
1834 return p_->contains_key(key);
1835}
1836
1837template <typename M>
1838int64_t PersistentCache<std::string, std::string, M>::size() const noexcept
1839{
1840 return p_->size();
1841}
1842
1843template <typename M>
1844int64_t PersistentCache<std::string, std::string, M>::size_in_bytes() const noexcept
1845{
1846 return p_->size_in_bytes();
1847}
1848
1849template <typename M>
1850int64_t PersistentCache<std::string, std::string, M>::max_size_in_bytes() const noexcept
1851{
1852 return p_->max_size_in_bytes();
1853}
1854
1855template <typename M>
1856int64_t PersistentCache<std::string, std::string, M>::disk_size_in_bytes() const
1857{
1858 return p_->disk_size_in_bytes();
1859}
1860
1861template <typename M>
1862CacheDiscardPolicy PersistentCache<std::string, std::string, M>::discard_policy() const noexcept
1863{
1864 return p_->discard_policy();
1865}
1866
1867template <typename M>
1868PersistentCacheStats PersistentCache<std::string, std::string, M>::stats() const
1869{
1870 return p_->stats();
1871}
1872
1873template <typename M>
1874bool PersistentCache<std::string, std::string, M>::put(std::string const& key,
1875 std::string const& value,
1876 std::chrono::time_point<std::chrono::system_clock> expiry_time)
1877{
1878 return p_->put(key, value, expiry_time);
1879}
1880
1881template <typename M>
1882bool PersistentCache<std::string, std::string, M>::put(std::string const& key,
1883 char const* value,
1884 int64_t size,
1885 std::chrono::time_point<std::chrono::system_clock> expiry_time)
1886{
1887 return p_->put(key, value, size, nullptr, 0, expiry_time);
1888}
1889
1890template <typename M>
1891bool PersistentCache<std::string, std::string, M>::put(std::string const& key,
1892 std::string const& value,
1893 M const& metadata,
1894 std::chrono::time_point<std::chrono::system_clock> expiry_time)
1895{
1896 return p_->put(key, value, CacheCodec<M>::encode(metadata), expiry_time);
1897}
1898
1899template <typename M>
1900bool PersistentCache<std::string, std::string, M>::put(std::string const& key,
1901 char const* value,
1902 int64_t size,
1903 M const& metadata,
1904 std::chrono::time_point<std::chrono::system_clock> expiry_time)
1905{
1906 std::string md = CacheCodec<M>::encode(metadata);
1907 return p_->put(key, value, size, md.data(), md.size(), expiry_time);
1908}
1909
1910template <typename M>
1911typename PersistentCache<std::string, std::string, M>::OptionalValue
1912 PersistentCache<std::string, std::string, M>::get_or_put(
1913 std::string const& key, PersistentCache<std::string, std::string, M>::Loader const& load_func)
1914{
1915 auto sload_func = [&](std::string const&, PersistentStringCache const&)
1916 {
1917 load_func(key, *this);
1918 };
1919 auto svalue = p_->get_or_put(key, sload_func);
1920 return svalue ? OptionalValue(*svalue) : OptionalValue();
1921}
1922
1923template <typename M>
1924typename PersistentCache<std::string, std::string, M>::OptionalData
1925 PersistentCache<std::string, std::string, M>::get_or_put_data(
1926 std::string const& key, PersistentCache<std::string, std::string, M>::Loader const& load_func)
1927{
1928 auto sload_func = [&](std::string const&, PersistentStringCache const&)
1929 {
1930 load_func(key, *this);
1931 };
1932 auto sdata = p_->get_or_put_data(key, sload_func);
1933 if (!sdata)
1934 {
1935 return OptionalData();
1936 }
1937 return OptionalData({sdata->value, CacheCodec<M>::decode(sdata->metadata)});
1938}
1939
1940template <typename M>
1941bool PersistentCache<std::string, std::string, M>::put_metadata(std::string const& key, M const& metadata)
1942{
1943 return p_->put_metadata(key, CacheCodec<M>::encode(metadata));
1944}
1945
1946template <typename M>
1947typename PersistentCache<std::string, std::string, M>::OptionalValue PersistentCache<std::string, std::string, M>::take(
1948 std::string const& key)
1949{
1950 auto svalue = p_->take(key);
1951 return svalue ? OptionalValue(*svalue) : OptionalValue();
1952}
1953
1954template <typename M>
1955typename PersistentCache<std::string, std::string, M>::OptionalData
1956 PersistentCache<std::string, std::string, M>::take_data(std::string const& key)
1957{
1958 auto sdata = p_->take_data(key);
1959 if (!sdata)
1960 {
1961 return OptionalData();
1962 }
1963 return OptionalData({sdata->value, CacheCodec<M>::decode(sdata->metadata)});
1964}
1965
1966template <typename M>
1967bool PersistentCache<std::string, std::string, M>::invalidate(std::string const& key)
1968{
1969 return p_->invalidate(key);
1970}
1971
1972template <typename M>
1973void PersistentCache<std::string, std::string, M>::invalidate(std::vector<std::string> const& keys)
1974{
1975 invalidate(keys.begin(), keys.end());
1976}
1977
1978template <typename M>
1979template <typename It>
1980void PersistentCache<std::string, std::string, M>::invalidate(It begin, It end)
1981{
1982 std::vector<std::string> skeys;
1983 for (auto&& it = begin; it < end; ++it)
1984 {
1985 skeys.push_back(*it);
1986 }
1987 p_->invalidate(skeys.begin(), skeys.end());
1988}
1989
1990template <typename M>
1991void PersistentCache<std::string, std::string, M>::invalidate(std::initializer_list<std::string> const& keys)
1992{
1993 invalidate(keys.begin(), keys.end());
1994}
1995
1996template <typename M>
1997void PersistentCache<std::string, std::string, M>::invalidate()
1998{
1999 p_->invalidate();
2000}
2001
2002template <typename M>
2003bool PersistentCache<std::string, std::string, M>::touch(std::string const& key,
2004 std::chrono::time_point<std::chrono::system_clock> expiry_time)
2005{
2006 return p_->touch(key, expiry_time);
2007}
2008
2009template <typename M>
2010void PersistentCache<std::string, std::string, M>::clear_stats()
2011{
2012 p_->clear_stats();
2013}
2014
2015template <typename M>
2016void PersistentCache<std::string, std::string, M>::resize(int64_t size_in_bytes)
2017{
2018 p_->resize(size_in_bytes);
2019}
2020
2021template <typename M>
2022void PersistentCache<std::string, std::string, M>::trim_to(int64_t used_size_in_bytes)
2023{
2024 p_->trim_to(used_size_in_bytes);
2025}
2026
2027template <typename M>
2028void PersistentCache<std::string, std::string, M>::compact()
2029{
2030 p_->compact();
2031}
2032
2033template <typename M>
2034void PersistentCache<std::string, std::string, M>::set_handler(CacheEvent events, EventCallback cb)
2035{
2036 p_->set_handler(events, cb);
2037}
2038
2039// Specialization for K and M = std::string.
2040
2041template <typename V>
2042class PersistentCache<std::string, V, std::string>
2043{
2044public:
2045 typedef std::unique_ptr<PersistentCache<std::string, V, std::string>> UPtr;
2046
2047 typedef Optional<std::string> OptionalKey;
2048 typedef Optional<V> OptionalValue;
2049 typedef Optional<std::string> OptionalMetadata;
2050
2051 struct Data
2052 {
2053 V value;
2054 std::string metadata;
2055 };
2056 typedef Optional<Data> OptionalData;
2057
2058 PersistentCache(PersistentCache const&) = delete;
2059 PersistentCache& operator=(PersistentCache const&) = delete;
2060
2061 PersistentCache(PersistentCache&&) = default;
2062 PersistentCache& operator=(PersistentCache&&) = default;
2063
2064 ~PersistentCache() = default;
2065
2066 static UPtr open(std::string const& cache_path, int64_t max_size_in_bytes, CacheDiscardPolicy policy);
2067 static UPtr open(std::string const& cache_path);
2068
2069 OptionalValue get(std::string const& key) const;
2070 OptionalData get_data(std::string const& key) const;
2071 OptionalMetadata get_metadata(std::string const& key) const;
2072 bool contains_key(std::string const& key) const;
2073 int64_t size() const noexcept;
2074 int64_t size_in_bytes() const noexcept;
2075 int64_t max_size_in_bytes() const noexcept;
2076 int64_t disk_size_in_bytes() const;
2077 CacheDiscardPolicy discard_policy() const noexcept;
2078 PersistentCacheStats stats() const;
2079
2080 bool put(std::string const& key,
2081 V const& value,
2082 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
2083 bool put(std::string const& key,
2084 V const& value,
2085 std::string const& metadata,
2086 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
2087 bool put(std::string const& key,
2088 V const& value,
2089 char const* metadata,
2090 int64_t size,
2091 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
2092
2093 typedef std::function<void(std::string const& key, PersistentCache<std::string, V, std::string>& cache)> Loader;
2094
2095 OptionalValue get_or_put(std::string const& key, Loader const& load_func);
2096 OptionalData get_or_put_data(std::string const& key, Loader const& load_func);
2097
2098 bool put_metadata(std::string const& key, std::string const& metadata);
2099 bool put_metadata(std::string const& key, char const* metadata, int64_t size);
2100 OptionalValue take(std::string const& key);
2101 OptionalData take_data(std::string const& key);
2102 bool invalidate(std::string const& key);
2103 void invalidate(std::vector<std::string> const& keys);
2104 template <typename It>
2105 void invalidate(It begin, It end);
2106 void invalidate(std::initializer_list<std::string> const& keys);
2107 void invalidate();
2108 bool touch(
2109 std::string const& key,
2110 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
2111 void clear_stats();
2112 void resize(int64_t size_in_bytes);
2113 void trim_to(int64_t used_size_in_bytes);
2114 void compact();
2115
2116 typedef std::function<void(std::string const& key, CacheEvent ev, PersistentCacheStats const& stats)> EventCallback;
2117
2118 void set_handler(CacheEvent events, EventCallback cb);
2119
2120private:
2121 PersistentCache(std::string const& cache_path, int64_t max_size_in_bytes, CacheDiscardPolicy policy);
2122 PersistentCache(std::string const& cache_path);
2123
2124 std::unique_ptr<PersistentStringCache> p_;
2125};
2126
2127template <typename V>
2128PersistentCache<std::string, V, std::string>::PersistentCache(std::string const& cache_path,
2129 int64_t max_size_in_bytes,
2130 CacheDiscardPolicy policy)
2131 : p_(PersistentStringCache::open(cache_path, max_size_in_bytes, policy))
2132{
2133}
2134
2135template <typename V>
2136PersistentCache<std::string, V, std::string>::PersistentCache(std::string const& cache_path)
2137 : p_(PersistentStringCache::open(cache_path))
2138{
2139}
2140
2141template <typename V>
2142typename PersistentCache<std::string, V, std::string>::UPtr PersistentCache<std::string, V, std::string>::open(
2143 std::string const& cache_path, int64_t max_size_in_bytes, CacheDiscardPolicy policy)
2144{
2145 return PersistentCache<std::string, V, std::string>::UPtr(
2146 new PersistentCache<std::string, V, std::string>(cache_path, max_size_in_bytes, policy));
2147}
2148
2149template <typename V>
2150typename PersistentCache<std::string, V, std::string>::UPtr PersistentCache<std::string, V, std::string>::open(
2151 std::string const& cache_path)
2152{
2153 return PersistentCache<std::string, V, std::string>::UPtr(
2154 new PersistentCache<std::string, V, std::string>(cache_path));
2155}
2156
2157template <typename V>
2158typename PersistentCache<std::string, V, std::string>::OptionalValue PersistentCache<std::string, V, std::string>::get(
2159 std::string const& key) const
2160{
2161 auto const& svalue = p_->get(key);
2162 return svalue ? OptionalValue(CacheCodec<V>::decode(*svalue)) : OptionalValue();
2163}
2164
2165template <typename V>
2166typename PersistentCache<std::string, V, std::string>::OptionalData
2167 PersistentCache<std::string, V, std::string>::get_data(std::string const& key) const
2168{
2169 auto sdata = p_->get_data(key);
2170 if (!sdata)
2171 {
2172 return OptionalData();
2173 }
2174 return OptionalData({CacheCodec<V>::decode(sdata->value), sdata->metadata});
2175}
2176
2177template <typename V>
2178typename PersistentCache<std::string, V, std::string>::OptionalMetadata
2179 PersistentCache<std::string, V, std::string>::get_metadata(std::string const& key) const
2180{
2181 auto smeta = p_->get_metadata(key);
2182 return smeta ? OptionalMetadata(*smeta) : OptionalMetadata();
2183}
2184
2185template <typename V>
2186bool PersistentCache<std::string, V, std::string>::contains_key(std::string const& key) const
2187{
2188 return p_->contains_key(key);
2189}
2190
2191template <typename V>
2192int64_t PersistentCache<std::string, V, std::string>::size() const noexcept
2193{
2194 return p_->size();
2195}
2196
2197template <typename V>
2198int64_t PersistentCache<std::string, V, std::string>::size_in_bytes() const noexcept
2199{
2200 return p_->size_in_bytes();
2201}
2202
2203template <typename V>
2204int64_t PersistentCache<std::string, V, std::string>::max_size_in_bytes() const noexcept
2205{
2206 return p_->max_size_in_bytes();
2207}
2208
2209template <typename V>
2210int64_t PersistentCache<std::string, V, std::string>::disk_size_in_bytes() const
2211{
2212 return p_->disk_size_in_bytes();
2213}
2214
2215template <typename V>
2216CacheDiscardPolicy PersistentCache<std::string, V, std::string>::discard_policy() const noexcept
2217{
2218 return p_->discard_policy();
2219}
2220
2221template <typename V>
2222PersistentCacheStats PersistentCache<std::string, V, std::string>::stats() const
2223{
2224 return p_->stats();
2225}
2226
2227template <typename V>
2228bool PersistentCache<std::string, V, std::string>::put(std::string const& key,
2229 V const& value,
2230 std::chrono::time_point<std::chrono::system_clock> expiry_time)
2231{
2232 return p_->put(key, CacheCodec<V>::encode(value), expiry_time);
2233}
2234
2235template <typename V>
2236bool PersistentCache<std::string, V, std::string>::put(std::string const& key,
2237 V const& value,
2238 std::string const& metadata,
2239 std::chrono::time_point<std::chrono::system_clock> expiry_time)
2240{
2241 std::string v = CacheCodec<V>::encode(value);
2242 return p_->put(key, v.data(), v.size(), metadata.data(), metadata.size(), expiry_time);
2243}
2244
2245template <typename V>
2246bool PersistentCache<std::string, V, std::string>::put(std::string const& key,
2247 V const& value,
2248 char const* metadata,
2249 int64_t size,
2250 std::chrono::time_point<std::chrono::system_clock> expiry_time)
2251{
2252 std::string v = CacheCodec<V>::encode(value);
2253 return p_->put(key, v.data(), v.size(), metadata, size, expiry_time);
2254}
2255
2256template <typename V>
2257typename PersistentCache<std::string, V, std::string>::OptionalValue
2258 PersistentCache<std::string, V, std::string>::get_or_put(
2259 std::string const& key, PersistentCache<std::string, V, std::string>::Loader const& load_func)
2260{
2261 auto sload_func = [&](std::string const&, PersistentStringCache const&)
2262 {
2263 load_func(key, *this);
2264 };
2265 auto svalue = p_->get_or_put(key, sload_func);
2266 return svalue ? OptionalValue(CacheCodec<V>::decode(*svalue)) : OptionalValue();
2267}
2268
2269template <typename V>
2270typename PersistentCache<std::string, V, std::string>::OptionalData
2271 PersistentCache<std::string, V, std::string>::get_or_put_data(
2272 std::string const& key, PersistentCache<std::string, V, std::string>::Loader const& load_func)
2273{
2274 auto sload_func = [&](std::string const&, PersistentStringCache const&)
2275 {
2276 load_func(key, *this);
2277 };
2278 auto sdata = p_->get_or_put_data(key, sload_func);
2279 if (!sdata)
2280 {
2281 return OptionalData();
2282 }
2283 return OptionalData({CacheCodec<V>::decode(sdata->value), sdata->metadata});
2284}
2285
2286template <typename V>
2287bool PersistentCache<std::string, V, std::string>::put_metadata(std::string const& key, std::string const& metadata)
2288{
2289 return p_->put_metadata(key, metadata);
2290}
2291
2292template <typename V>
2293bool PersistentCache<std::string, V, std::string>::put_metadata(std::string const& key,
2294 char const* metadata,
2295 int64_t size)
2296{
2297 return p_->put_metadata(key, metadata, size);
2298}
2299
2300template <typename V>
2301typename PersistentCache<std::string, V, std::string>::OptionalValue PersistentCache<std::string, V, std::string>::take(
2302 std::string const& key)
2303{
2304 auto svalue = p_->take(key);
2305 return svalue ? OptionalValue(CacheCodec<V>::decode(*svalue)) : OptionalValue();
2306}
2307
2308template <typename V>
2309typename PersistentCache<std::string, V, std::string>::OptionalData
2310 PersistentCache<std::string, V, std::string>::take_data(std::string const& key)
2311{
2312 auto sdata = p_->take_data(key);
2313 if (!sdata)
2314 {
2315 return OptionalData();
2316 }
2317 return OptionalData({CacheCodec<V>::decode(sdata->value), sdata->metadata});
2318}
2319
2320template <typename V>
2321bool PersistentCache<std::string, V, std::string>::invalidate(std::string const& key)
2322{
2323 return p_->invalidate(key);
2324}
2325
2326template <typename V>
2327void PersistentCache<std::string, V, std::string>::invalidate(std::vector<std::string> const& keys)
2328{
2329 invalidate(keys.begin(), keys.end());
2330}
2331
2332template <typename V>
2333template <typename It>
2334void PersistentCache<std::string, V, std::string>::invalidate(It begin, It end)
2335{
2336 std::vector<std::string> skeys;
2337 for (auto&& it = begin; it < end; ++it)
2338 {
2339 skeys.push_back(*it);
2340 }
2341 p_->invalidate(skeys.begin(), skeys.end());
2342}
2343
2344template <typename V>
2345void PersistentCache<std::string, V, std::string>::invalidate(std::initializer_list<std::string> const& keys)
2346{
2347 invalidate(keys.begin(), keys.end());
2348}
2349
2350template <typename V>
2351void PersistentCache<std::string, V, std::string>::invalidate()
2352{
2353 p_->invalidate();
2354}
2355
2356template <typename V>
2357bool PersistentCache<std::string, V, std::string>::touch(std::string const& key,
2358 std::chrono::time_point<std::chrono::system_clock> expiry_time)
2359{
2360 return p_->touch(key, expiry_time);
2361}
2362
2363template <typename V>
2364void PersistentCache<std::string, V, std::string>::clear_stats()
2365{
2366 p_->clear_stats();
2367}
2368
2369template <typename V>
2370void PersistentCache<std::string, V, std::string>::resize(int64_t size_in_bytes)
2371{
2372 p_->resize(size_in_bytes);
2373}
2374
2375template <typename V>
2376void PersistentCache<std::string, V, std::string>::trim_to(int64_t used_size_in_bytes)
2377{
2378 p_->trim_to(used_size_in_bytes);
2379}
2380
2381template <typename V>
2382void PersistentCache<std::string, V, std::string>::compact()
2383{
2384 p_->compact();
2385}
2386
2387template <typename V>
2388void PersistentCache<std::string, V, std::string>::set_handler(CacheEvent events, EventCallback cb)
2389{
2390 p_->set_handler(events, cb);
2391}
2392
2393// Specialization for V and M = std::string.
2394
2395template <typename K>
2396class PersistentCache<K, std::string, std::string>
2397{
2398public:
2399 typedef std::unique_ptr<PersistentCache<K, std::string, std::string>> UPtr;
2400
2401 typedef Optional<K> OptionalKey;
2402 typedef Optional<std::string> OptionalValue;
2403 typedef Optional<std::string> OptionalMetadata;
2404
2405 struct Data
2406 {
2407 std::string value;
2408 std::string metadata;
2409 };
2410 typedef Optional<Data> OptionalData;
2411
2412 PersistentCache(PersistentCache const&) = delete;
2413 PersistentCache& operator=(PersistentCache const&) = delete;
2414
2415 PersistentCache(PersistentCache&&) = default;
2416 PersistentCache& operator=(PersistentCache&&) = default;
2417
2418 ~PersistentCache() = default;
2419
2420 static UPtr open(std::string const& cache_path, int64_t max_size_in_bytes, CacheDiscardPolicy policy);
2421 static UPtr open(std::string const& cache_path);
2422
2423 OptionalValue get(K const& key) const;
2424 OptionalData get_data(K const& key) const;
2425 OptionalMetadata get_metadata(K const& key) const;
2426 bool contains_key(K const& key) const;
2427 int64_t size() const noexcept;
2428 int64_t size_in_bytes() const noexcept;
2429 int64_t max_size_in_bytes() const noexcept;
2430 int64_t disk_size_in_bytes() const;
2431 CacheDiscardPolicy discard_policy() const noexcept;
2432 PersistentCacheStats stats() const;
2433
2434 bool put(K const& key,
2435 std::string const& value,
2436 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
2437 bool put(K const& key,
2438 char const* value,
2439 int64_t size,
2440 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
2441 bool put(K const& key,
2442 std::string const& value,
2443 std::string const& metadata,
2444 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
2445 bool put(K const& key,
2446 char const* value,
2447 int64_t value_size,
2448 char const* metadata,
2449 int64_t metadata_size,
2450 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
2451
2452 typedef std::function<void(K const& key, PersistentCache<K, std::string, std::string>& cache)> Loader;
2453
2454 OptionalValue get_or_put(K const& key, Loader const& load_func);
2455 OptionalData get_or_put_data(K const& key, Loader const& load_func);
2456
2457 bool put_metadata(K const& key, std::string const& metadata);
2458 bool put_metadata(K const& key, char const* metadata, int64_t size);
2459 OptionalValue take(K const& key);
2460 OptionalData take_data(K const& key);
2461 bool invalidate(K const& key);
2462 void invalidate(std::vector<K> const& keys);
2463 template <typename It>
2464 void invalidate(It begin, It end);
2465 void invalidate(std::initializer_list<K> const& keys);
2466 void invalidate();
2467 bool touch(
2468 K const& key,
2469 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
2470 void clear_stats();
2471 void resize(int64_t size_in_bytes);
2472 void trim_to(int64_t used_size_in_bytes);
2473 void compact();
2474
2475 typedef std::function<void(K const& key, CacheEvent ev, PersistentCacheStats const& stats)> EventCallback;
2476
2477 void set_handler(CacheEvent events, EventCallback cb);
2478
2479private:
2480 PersistentCache(std::string const& cache_path, int64_t max_size_in_bytes, CacheDiscardPolicy policy);
2481 PersistentCache(std::string const& cache_path);
2482
2483 std::unique_ptr<PersistentStringCache> p_;
2484};
2485
2486template <typename K>
2487PersistentCache<K, std::string, std::string>::PersistentCache(std::string const& cache_path,
2488 int64_t max_size_in_bytes,
2489 CacheDiscardPolicy policy)
2490 : p_(PersistentStringCache::open(cache_path, max_size_in_bytes, policy))
2491{
2492}
2493
2494template <typename K>
2495PersistentCache<K, std::string, std::string>::PersistentCache(std::string const& cache_path)
2496 : p_(PersistentStringCache::open(cache_path))
2497{
2498}
2499
2500template <typename K>
2501typename PersistentCache<K, std::string, std::string>::UPtr PersistentCache<K, std::string, std::string>::open(
2502 std::string const& cache_path, int64_t max_size_in_bytes, CacheDiscardPolicy policy)
2503{
2504 return PersistentCache<K, std::string, std::string>::UPtr(
2505 new PersistentCache<K, std::string, std::string>(cache_path, max_size_in_bytes, policy));
2506}
2507
2508template <typename K>
2509typename PersistentCache<K, std::string, std::string>::UPtr PersistentCache<K, std::string, std::string>::open(
2510 std::string const& cache_path)
2511{
2512 return PersistentCache<K, std::string, std::string>::UPtr(
2513 new PersistentCache<K, std::string, std::string>(cache_path));
2514}
2515
2516template <typename K>
2517typename PersistentCache<K, std::string, std::string>::OptionalValue PersistentCache<K, std::string, std::string>::get(
2518 K const& key) const
2519{
2520 auto const& svalue = p_->get(CacheCodec<K>::encode(key));
2521 return svalue ? OptionalValue(*svalue) : OptionalValue();
2522}
2523
2524template <typename K>
2525typename PersistentCache<K, std::string, std::string>::OptionalData
2526 PersistentCache<K, std::string, std::string>::get_data(K const& key) const
2527{
2528 auto sdata = p_->get_data(CacheCodec<K>::encode(key));
2529 if (!sdata)
2530 {
2531 return OptionalData();
2532 }
2533 return OptionalData({sdata->value, sdata->metadata});
2534}
2535
2536template <typename K>
2537typename PersistentCache<K, std::string, std::string>::OptionalMetadata
2538 PersistentCache<K, std::string, std::string>::get_metadata(K const& key) const
2539{
2540 auto smeta = p_->get_metadata(CacheCodec<K>::encode(key));
2541 return smeta ? OptionalMetadata(*smeta) : OptionalMetadata();
2542}
2543
2544template <typename K>
2545bool PersistentCache<K, std::string, std::string>::contains_key(K const& key) const
2546{
2547 return p_->contains_key(CacheCodec<K>::encode(key));
2548}
2549
2550template <typename K>
2551int64_t PersistentCache<K, std::string, std::string>::size() const noexcept
2552{
2553 return p_->size();
2554}
2555
2556template <typename K>
2557int64_t PersistentCache<K, std::string, std::string>::size_in_bytes() const noexcept
2558{
2559 return p_->size_in_bytes();
2560}
2561
2562template <typename K>
2563int64_t PersistentCache<K, std::string, std::string>::max_size_in_bytes() const noexcept
2564{
2565 return p_->max_size_in_bytes();
2566}
2567
2568template <typename K>
2569int64_t PersistentCache<K, std::string, std::string>::disk_size_in_bytes() const
2570{
2571 return p_->disk_size_in_bytes();
2572}
2573
2574template <typename K>
2575CacheDiscardPolicy PersistentCache<K, std::string, std::string>::discard_policy() const noexcept
2576{
2577 return p_->discard_policy();
2578}
2579
2580template <typename K>
2581PersistentCacheStats PersistentCache<K, std::string, std::string>::stats() const
2582{
2583 return p_->stats();
2584}
2585
2586template <typename K>
2587bool PersistentCache<K, std::string, std::string>::put(K const& key,
2588 std::string const& value,
2589 std::chrono::time_point<std::chrono::system_clock> expiry_time)
2590{
2591 return p_->put(CacheCodec<K>::encode(key), value, expiry_time);
2592}
2593
2594template <typename K>
2595bool PersistentCache<K, std::string, std::string>::put(K const& key,
2596 char const* value,
2597 int64_t size,
2598 std::chrono::time_point<std::chrono::system_clock> expiry_time)
2599{
2600 return p_->put(CacheCodec<K>::encode(key), value, size, expiry_time);
2601}
2602
2603template <typename K>
2604bool PersistentCache<K, std::string, std::string>::put(K const& key,
2605 std::string const& value,
2606 std::string const& metadata,
2607 std::chrono::time_point<std::chrono::system_clock> expiry_time)
2608{
2609 return p_->put(CacheCodec<K>::encode(key), value, metadata, expiry_time);
2610}
2611
2612template <typename K>
2613bool PersistentCache<K, std::string, std::string>::put(K const& key,
2614 char const* value,
2615 int64_t value_size,
2616 char const* metadata,
2617 int64_t metadata_size,
2618 std::chrono::time_point<std::chrono::system_clock> expiry_time)
2619{
2620 return p_->put(CacheCodec<K>::encode(key), value, value_size, metadata, metadata_size, expiry_time);
2621}
2622
2623template <typename K>
2624typename PersistentCache<K, std::string, std::string>::OptionalValue
2625 PersistentCache<K, std::string, std::string>::get_or_put(
2626 K const& key, PersistentCache<K, std::string, std::string>::Loader const& load_func)
2627{
2628 auto skey = CacheCodec<K>::encode(key);
2629 auto sload_func = [&](std::string const&, PersistentStringCache const&)
2630 {
2631 load_func(key, *this);
2632 };
2633 auto svalue = p_->get_or_put(skey, sload_func);
2634 return svalue ? OptionalValue(*svalue) : OptionalValue();
2635}
2636
2637template <typename K>
2638typename PersistentCache<K, std::string, std::string>::OptionalData
2639 PersistentCache<K, std::string, std::string>::get_or_put_data(
2640 K const& key, PersistentCache<K, std::string, std::string>::Loader const& load_func)
2641{
2642 auto skey = CacheCodec<K>::encode(key);
2643 auto sload_func = [&](std::string const&, PersistentStringCache const&)
2644 {
2645 load_func(key, *this);
2646 };
2647 auto sdata = p_->get_or_put_data(skey, sload_func);
2648 if (!sdata)
2649 {
2650 return OptionalData();
2651 }
2652 return OptionalData({sdata->value, sdata->metadata});
2653}
2654
2655template <typename K>
2656bool PersistentCache<K, std::string, std::string>::put_metadata(K const& key, std::string const& metadata)
2657{
2658 return p_->put_metadata(CacheCodec<K>::encode(key), metadata);
2659}
2660
2661template <typename K>
2662bool PersistentCache<K, std::string, std::string>::put_metadata(K const& key, char const* metadata, int64_t size)
2663{
2664 return p_->put_metadata(CacheCodec<K>::encode(key), metadata, size);
2665}
2666
2667template <typename K>
2668typename PersistentCache<K, std::string, std::string>::OptionalValue PersistentCache<K, std::string, std::string>::take(
2669 K const& key)
2670{
2671 auto svalue = p_->take(CacheCodec<K>::encode(key));
2672 return svalue ? OptionalValue(*svalue) : OptionalValue();
2673}
2674
2675template <typename K>
2676typename PersistentCache<K, std::string, std::string>::OptionalData
2677 PersistentCache<K, std::string, std::string>::take_data(K const& key)
2678{
2679 auto sdata = p_->take_data(CacheCodec<K>::encode(key));
2680 if (!sdata)
2681 {
2682 return OptionalData();
2683 }
2684 return OptionalData({sdata->value, sdata->metadata});
2685}
2686
2687template <typename K>
2688bool PersistentCache<K, std::string, std::string>::invalidate(K const& key)
2689{
2690 return p_->invalidate(CacheCodec<K>::encode(key));
2691}
2692
2693template <typename K>
2694void PersistentCache<K, std::string, std::string>::invalidate(std::vector<K> const& keys)
2695{
2696 invalidate(keys.begin(), keys.end());
2697}
2698
2699template <typename K>
2700template <typename It>
2701void PersistentCache<K, std::string, std::string>::invalidate(It begin, It end)
2702{
2703 std::vector<std::string> skeys;
2704 for (auto&& it = begin; it < end; ++it)
2705 {
2706 skeys.push_back(CacheCodec<K>::encode(*it));
2707 }
2708 p_->invalidate(skeys.begin(), skeys.end());
2709}
2710
2711template <typename K>
2712void PersistentCache<K, std::string, std::string>::invalidate(std::initializer_list<K> const& keys)
2713{
2714 invalidate(keys.begin(), keys.end());
2715}
2716
2717template <typename K>
2718void PersistentCache<K, std::string, std::string>::invalidate()
2719{
2720 p_->invalidate();
2721}
2722
2723template <typename K>
2724bool PersistentCache<K, std::string, std::string>::touch(K const& key,
2725 std::chrono::time_point<std::chrono::system_clock> expiry_time)
2726{
2727 return p_->touch(CacheCodec<K>::encode(key), expiry_time);
2728}
2729
2730template <typename K>
2731void PersistentCache<K, std::string, std::string>::clear_stats()
2732{
2733 p_->clear_stats();
2734}
2735
2736template <typename K>
2737void PersistentCache<K, std::string, std::string>::resize(int64_t size_in_bytes)
2738{
2739 p_->resize(size_in_bytes);
2740}
2741
2742template <typename K>
2743void PersistentCache<K, std::string, std::string>::trim_to(int64_t used_size_in_bytes)
2744{
2745 p_->trim_to(used_size_in_bytes);
2746}
2747
2748template <typename K>
2749void PersistentCache<K, std::string, std::string>::compact()
2750{
2751 p_->compact();
2752}
2753
2754template <typename K>
2755void PersistentCache<K, std::string, std::string>::set_handler(CacheEvent events, EventCallback cb)
2756{
2757 auto scb = [cb](std::string const& key, CacheEvent ev, PersistentCacheStats const& c)
2758 {
2759 cb(CacheCodec<K>::decode(key), ev, c);
2760 };
2761 p_->set_handler(events, scb);
2762}
2763
2764// Specialization for K, V, and M = std::string.
2765
2766template <>
2767class PersistentCache<std::string, std::string, std::string>
2768{
2769public:
2770 typedef std::unique_ptr<PersistentCache<std::string, std::string, std::string>> UPtr;
2771
2772 typedef Optional<std::string> OptionalKey;
2773 typedef Optional<std::string> OptionalValue;
2774 typedef Optional<std::string> OptionalMetadata;
2775
2776 struct Data
2777 {
2778 std::string value;
2779 std::string metadata;
2780 };
2781 typedef Optional<Data> OptionalData;
2782
2783 PersistentCache(PersistentCache const&) = delete;
2784 PersistentCache& operator=(PersistentCache const&) = delete;
2785
2786 PersistentCache(PersistentCache&&) = default;
2787 PersistentCache& operator=(PersistentCache&&) = default;
2788
2789 ~PersistentCache() = default;
2790
2791 static UPtr open(std::string const& cache_path, int64_t max_size_in_bytes, CacheDiscardPolicy policy);
2792 static UPtr open(std::string const& cache_path);
2793
2794 OptionalValue get(std::string const& key) const;
2795 OptionalData get_data(std::string const& key) const;
2796 OptionalMetadata get_metadata(std::string const& key) const;
2797 bool contains_key(std::string const& key) const;
2798 int64_t size() const noexcept;
2799 int64_t size_in_bytes() const noexcept;
2800 int64_t max_size_in_bytes() const noexcept;
2801 int64_t disk_size_in_bytes() const;
2802 CacheDiscardPolicy discard_policy() const noexcept;
2803 PersistentCacheStats stats() const;
2804
2805 bool put(std::string const& key,
2806 std::string const& value,
2807 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
2808 bool put(std::string const& key,
2809 char const* value,
2810 int64_t size,
2811 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
2812 bool put(std::string const& key,
2813 std::string const& value,
2814 std::string const& metadata,
2815 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
2816 bool put(std::string const& key,
2817 char const* value,
2818 int64_t value_size,
2819 char const* metadata,
2820 int64_t metadata_size,
2821 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
2822
2823 typedef std::function<void(std::string const& key, PersistentCache<std::string, std::string, std::string>& cache)>
2824 Loader;
2825
2826 OptionalValue get_or_put(std::string const& key, Loader const& load_func);
2827 OptionalData get_or_put_data(std::string const& key, Loader const& load_func);
2828
2829 bool put_metadata(std::string const& key, std::string const& metadata);
2830 bool put_metadata(std::string const& key, char const* metadata, int64_t size);
2831 OptionalValue take(std::string const& key);
2832 OptionalData take_data(std::string const& key);
2833 bool invalidate(std::string const& key);
2834 void invalidate(std::vector<std::string> const& keys);
2835 template <typename It>
2836 void invalidate(It begin, It end);
2837 void invalidate(std::initializer_list<std::string> const& keys);
2838 void invalidate();
2839 bool touch(
2840 std::string const& key,
2841 std::chrono::time_point<std::chrono::system_clock> expiry_time = std::chrono::system_clock::time_point());
2842 void clear_stats();
2843 void resize(int64_t size_in_bytes);
2844 void trim_to(int64_t used_size_in_bytes);
2845 void compact();
2846
2847 typedef std::function<void(std::string const& key, CacheEvent ev, PersistentCacheStats const& stats)> EventCallback;
2848
2849 void set_handler(CacheEvent events, EventCallback cb);
2850
2851private:
2852 PersistentCache(std::string const& cache_path, int64_t max_size_in_bytes, CacheDiscardPolicy policy);
2853 PersistentCache(std::string const& cache_path);
2854
2855 std::unique_ptr<PersistentStringCache> p_;
2856};
2857
2858PersistentCache<std::string, std::string, std::string>::PersistentCache(std::string const& cache_path,
2859 int64_t max_size_in_bytes,
2860 CacheDiscardPolicy policy)
2861 : p_(PersistentStringCache::open(cache_path, max_size_in_bytes, policy))
2862{
2863}
2864
2865PersistentCache<std::string, std::string, std::string>::PersistentCache(std::string const& cache_path)
2866 : p_(PersistentStringCache::open(cache_path))
2867{
2868}
2869
2870typename PersistentCache<std::string, std::string, std::string>::UPtr
2871 PersistentCache<std::string, std::string, std::string>::open(std::string const& cache_path,
2872 int64_t max_size_in_bytes,
2873 CacheDiscardPolicy policy)
2874{
2875 return PersistentCache<std::string, std::string, std::string>::UPtr(
2876 new PersistentCache<std::string, std::string, std::string>(cache_path, max_size_in_bytes, policy));
2877}
2878
2879typename PersistentCache<std::string, std::string, std::string>::UPtr
2880 PersistentCache<std::string, std::string, std::string>::open(std::string const& cache_path)
2881{
2882 return PersistentCache<std::string, std::string, std::string>::UPtr(
2883 new PersistentCache<std::string, std::string, std::string>(cache_path));
2884}
2885
2886typename PersistentCache<std::string, std::string, std::string>::OptionalValue
2887 PersistentCache<std::string, std::string, std::string>::get(std::string const& key) const
2888{
2889 auto const& svalue = p_->get(key);
2890 return svalue ? OptionalValue(*svalue) : OptionalValue();
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: