persistent-cache-cpp: /build/persistent-cache-cpp-git/src/persistent-cache-cpp/include/core/persistent_cache.h Source File

persistent-cache-cpp

persistent_cache.h
Go to the documentation of this file.
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
24 namespace core
25 {
26
117 template <typename K, typename V, typename M = std::string>
118 class PersistentCache
119 {
120 public:
124 typedef std::unique_ptr<PersistentCache<K, V, M>> UPtr;
125
129 struct Data
130 {
134 V value;
135
140 M metadata;
141 };
142
146 //{@
147
155 typedef Optional<K> OptionalKey;
156 typedef Optional<V> OptionalValue;
157 typedef Optional<M> OptionalMetadata;
158 typedef Optional<Data> OptionalData;
159
161
165 //{@
166 PersistentCache(PersistentCache const&) = delete;
167 PersistentCache& operator=(PersistentCache const&) = delete;
168
169 PersistentCache(PersistentCache&&) = default;
170 PersistentCache& operator=(PersistentCache&&) = default;
172
179 ~PersistentCache() = default;
180
184 //{@
185
189 static UPtr open(std::string const& cache_path, int64_t max_size_in_bytes, CacheDiscardPolicy policy);
190
194 static UPtr open(std::string const& cache_path);
195
197
201 //{@
202
206 OptionalValue get(K const& key) const;
207
211 OptionalData get_data(K const& key) const;
212
216 OptionalMetadata get_metadata(K const& key) const;
217
221 bool contains_key(K const& key) const;
222
226 int64_t size() const noexcept;
227
231 int64_t size_in_bytes() const noexcept;
232
236 int64_t max_size_in_bytes() const noexcept;
237
241 int64_t disk_size_in_bytes() const;
242
246 CacheDiscardPolicy discard_policy() const noexcept;
247
251 PersistentCacheStats stats() const;
252
254
258 //{@
259
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
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
280 typedef std::function<void(K const& key, PersistentCache<K, V, M>& cache)> Loader;
281
285 OptionalValue get_or_put(K const& key, Loader const& load_func);
286
290 OptionalData get_or_put_data(K const& key, Loader const& load_func);
291
296 bool put_metadata(K const& key, M const& metadata);
297
301 OptionalValue take(K const& key);
302
306 OptionalData take_data(K const& key);
307
311 bool invalidate(K const& key);
312
316 void invalidate(std::vector<K> const& keys);
317
321 template <typename It>
322 void invalidate(It begin, It end);
323
327 void invalidate(std::initializer_list<K> const& keys);
328
332 void invalidate();
333
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
344 void clear_stats();
345
349 void resize(int64_t size_in_bytes);
350
354 void trim_to(int64_t used_size_in_bytes);
355
359 void compact();
360
362
366 //{@
367
371 typedef std::function<void(K const& key, CacheEvent ev, PersistentCacheStats const& stats)> EventCallback;
372
376 void set_handler(CacheEvent events, EventCallback cb);
377
379
380 private:
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
393 template <typename K, typename V, typename M>
394 PersistentCache<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
401 template <typename K, typename V, typename M>
402 PersistentCache<K, V, M>::PersistentCache(std::string const& cache_path)
403 : p_(PersistentStringCache::open(cache_path))
404 {
405 }
406
407 template <typename K, typename V, typename M>
408 typename 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
415 template <typename K, typename V, typename M>
416 typename 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
421 template <typename K, typename V, typename M>
422 typename 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
428 template <typename K, typename V, typename M>
429 typename 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
439 template <typename K, typename V, typename M>
440 typename 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
446 template <typename K, typename V, typename M>
447 bool PersistentCache<K, V, M>::contains_key(K const& key) const
448 {
449 return p_->contains_key(CacheCodec<K>::encode(key));
450 }
451
452 template <typename K, typename V, typename M>
453 int64_t PersistentCache<K, V, M>::size() const noexcept
454 {
455 return p_->size();
456 }
457
458 template <typename K, typename V, typename M>
459 int64_t PersistentCache<K, V, M>::size_in_bytes() const noexcept
460 {
461 return p_->size_in_bytes();
462 }
463
464 template <typename K, typename V, typename M>
465 int64_t PersistentCache<K, V, M>::max_size_in_bytes() const noexcept
466 {
467 return p_->max_size_in_bytes();
468 }
469
470 template <typename K, typename V, typename M>
471 int64_t PersistentCache<K, V, M>::disk_size_in_bytes() const
472 {
473 return p_->disk_size_in_bytes();
474 }
475
476 template <typename K, typename V, typename M>
477 CacheDiscardPolicy PersistentCache<K, V, M>::discard_policy() const noexcept
478 {
479 return p_->discard_policy();
480 }
481
482 template <typename K, typename V, typename M>
483 PersistentCacheStats PersistentCache<K, V, M>::stats() const
484 {
485 return p_->stats();
486 }
487
488 template <typename K, typename V, typename M>
489 bool 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
496 template <typename K, typename V, typename M>
497 bool 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
506 template <typename K, typename V, typename M>
507 typename 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
519 template <typename K, typename V, typename M>
520 typename 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
536 template <typename K, typename V, typename M>
537 bool 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
542 template <typename K, typename V, typename M>
543 typename 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
549 template <typename K, typename V, typename M>
550 typename 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
560 template <typename K, typename V, typename M>
561 bool PersistentCache<K, V, M>::invalidate(K const& key)
562 {
563 return p_->invalidate(CacheCodec<K>::encode(key));
564 }
565
566 template <typename K, typename V, typename M>
567 void PersistentCache<K, V, M>::invalidate(std::vector<K> const& keys)
568 {
569 invalidate(keys.begin(), keys.end());
570 }
571
572 template <typename K, typename V, typename M>
573 template <typename It>
574 void 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
584 template <typename K, typename V, typename M>
585 void PersistentCache<K, V, M>::invalidate(std::initializer_list<K> const& keys)
586 {
587 invalidate(keys.begin(), keys.end());
588 }
589
590 template <typename K, typename V, typename M>
591 void PersistentCache<K, V, M>::invalidate()
592 {
593 p_->invalidate();
594 }
595
596 template <typename K, typename V, typename M>
597 bool 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
602 template <typename K, typename V, typename M>
603 void PersistentCache<K, V, M>::clear_stats()
604 {
605 p_->clear_stats();
606 }
607
608 template <typename K, typename V, typename M>
609 void PersistentCache<K, V, M>::resize(int64_t size_in_bytes)
610 {
611 p_->resize(size_in_bytes);
612 }
613
614 template <typename K, typename V, typename M>
615 void PersistentCache<K, V, M>::trim_to(int64_t used_size_in_bytes)
616 {
617 p_->trim_to(used_size_in_bytes);
618 }
619
620 template <typename K, typename V, typename M>
621 void PersistentCache<K, V, M>::compact()
622 {
623 p_->compact();
624 }
625
626 template <typename K, typename V, typename M>
627 void 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
648 template <typename V, typename M>
649 class PersistentCache<std::string, V, M>
650 {
651 public:
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
721 private:
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
728 template <typename V, typename M>
729 PersistentCache<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
736 template <typename V, typename M>
737 PersistentCache<std::string, V, M>::PersistentCache(std::string const& cache_path)
738 : p_(PersistentStringCache::open(cache_path))
739 {
740 }
741
742 template <typename V, typename M>
743 typename 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
750 template <typename V, typename M>
751 typename 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
757 template <typename V, typename M>
758 typename 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
765 template <typename V, typename M>
766 typename 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
777 template <typename V, typename M>
778 typename 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
785 template <typename V, typename M>
786 bool PersistentCache<std::string, V, M>::contains_key(std::string const& key) const
787 {
788 return p_->contains_key(key);
789 }
790
791 template <typename V, typename M>
792 int64_t PersistentCache<std::string, V, M>::size() const noexcept
793 {
794 return p_->size();
795 }
796
797 template <typename V, typename M>
798 int64_t PersistentCache<std::string, V, M>::size_in_bytes() const noexcept
799 {
800 return p_->size_in_bytes();
801 }
802
803 template <typename V, typename M>
804 int64_t PersistentCache<std::string, V, M>::max_size_in_bytes() const noexcept
805 {
806 return p_->max_size_in_bytes();
807 }
808
809 template <typename V, typename M>
810 int64_t PersistentCache<std::string, V, M>::disk_size_in_bytes() const
811 {
812 return p_->disk_size_in_bytes();
813 }
814
815 template <typename V, typename M>
816 CacheDiscardPolicy PersistentCache<std::string, V, M>::discard_policy() const noexcept
817 {
818 return p_->discard_policy();
819 }
820
821 template <typename V, typename M>
822 PersistentCacheStats PersistentCache<std::string, V, M>::stats() const
823 {
824 return p_->stats();
825 }
826
827 template <typename V, typename M>
828 bool 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
835 template <typename V, typename M>
836 bool 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
844 template <typename V, typename M>
845 typename 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
856 template <typename V, typename M>
857 typename 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
872 template <typename V, typename M>
873 bool 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
878 template <typename V, typename M>
879 typename 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
886 template <typename V, typename M>
887 typename 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
898 template <typename V, typename M>
899 bool PersistentCache<std::string, V, M>::invalidate(std::string const& key)
900 {
901 return p_->invalidate(key);
902 }
903
904 template <typename V, typename M>
905 void PersistentCache<std::string, V, M>::invalidate(std::vector<std::string> const& keys)
906 {
907 invalidate(keys.begin(), keys.end());
908 }
909
910 template <typename V, typename M>
911 template <typename It>
912 void 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
922 template <typename V, typename M>
923 void PersistentCache<std::string, V, M>::invalidate(std::initializer_list<std::string> const& keys)
924 {
925 invalidate(keys.begin(), keys.end());
926 }
927
928 template <typename V, typename M>
929 void PersistentCache<std::string, V, M>::invalidate()
930 {
931 p_->invalidate();
932 }
933
934 template <typename V, typename M>
935 bool 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
941 template <typename V, typename M>
942 void PersistentCache<std::string, V, M>::clear_stats()
943 {
944 p_->clear_stats();
945 }
946
947 template <typename V, typename M>
948 void PersistentCache<std::string, V, M>::resize(int64_t size_in_bytes)
949 {
950 p_->resize(size_in_bytes);
951 }
952
953 template <typename V, typename M>
954 void PersistentCache<std::string, V, M>::trim_to(int64_t used_size_in_bytes)
955 {
956 p_->trim_to(used_size_in_bytes);
957 }
958
959 template <typename V, typename M>
960 void PersistentCache<std::string, V, M>::compact()
961 {
962 p_->compact();
963 }
964
965 template <typename V, typename M>
966 void 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
973 template <typename K, typename M>
974 class PersistentCache<K, std::string, M>
975 {
976 public:
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
1055 private:
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
1062 template <typename K, typename M>
1063 PersistentCache<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
1070 template <typename K, typename M>
1071 PersistentCache<K, std::string, M>::PersistentCache(std::string const& cache_path)
1072 : p_(PersistentStringCache::open(cache_path))
1073 {
1074 }
1075
1076 template <typename K, typename M>
1077 typename 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
1084 template <typename K, typename M>
1085 typename 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
1091 template <typename K, typename M>
1092 typename 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
1098 template <typename K, typename M>
1099 typename 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
1110 template <typename K, typename M>
1111 typename 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
1118 template <typename K, typename M>
1119 bool PersistentCache<K, std::string, M>::contains_key(K const& key) const
1120 {
1121 return p_->contains_key(CacheCodec<K>::encode(key));
1122 }
1123
1124 template <typename K, typename M>
1125 int64_t PersistentCache<K, std::string, M>::size() const noexcept
1126 {
1127 return p_->size();
1128 }
1129
1130 template <typename K, typename M>
1131 int64_t PersistentCache<K, std::string, M>::size_in_bytes() const noexcept
1132 {
1133 return p_->size_in_bytes();
1134 }
1135
1136 template <typename K, typename M>
1137 int64_t PersistentCache<K, std::string, M>::max_size_in_bytes() const noexcept
1138 {
1139 return p_->max_size_in_bytes();
1140 }
1141
1142 template <typename K, typename M>
1143 int64_t PersistentCache<K, std::string, M>::disk_size_in_bytes() const
1144 {
1145 return p_->disk_size_in_bytes();
1146 }
1147
1148 template <typename K, typename M>
1149 CacheDiscardPolicy PersistentCache<K, std::string, M>::discard_policy() const noexcept
1150 {
1151 return p_->discard_policy();
1152 }
1153
1154 template <typename K, typename M>
1155 PersistentCacheStats PersistentCache<K, std::string, M>::stats() const
1156 {
1157 return p_->stats();
1158 }
1159
1160 template <typename K, typename M>
1161 bool 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
1168 template <typename K, typename M>
1169 bool 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
1177 template <typename K, typename M>
1178 bool 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
1186 template <typename K, typename M>
1187 bool 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
1197 template <typename K, typename M>
1198 typename 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
1210 template <typename K, typename M>
1211 typename 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
1227 template <typename K, typename M>
1228 bool 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
1233 template <typename K, typename M>
1234 typename 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
1240 template <typename K, typename M>
1241 typename 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
1252 template <typename K, typename M>
1253 bool PersistentCache<K, std::string, M>::invalidate(K const& key)
1254 {
1255 return p_->invalidate(CacheCodec<K>::encode(key));
1256 }
1257
1258 template <typename K, typename M>
1259 void PersistentCache<K, std::string, M>::invalidate(std::vector<K> const& keys)
1260 {
1261 invalidate(keys.begin(), keys.end());
1262 }
1263
1264 template <typename K, typename M>
1265 template <typename It>
1266 void 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
1276 template <typename K, typename M>
1277 void PersistentCache<K, std::string, M>::invalidate(std::initializer_list<K> const& keys)
1278 {
1279 invalidate(keys.begin(), keys.end());
1280 }
1281
1282 template <typename K, typename M>
1283 void PersistentCache<K, std::string, M>::invalidate()
1284 {
1285 p_->invalidate();
1286 }
1287
1288 template <typename K, typename M>
1289 bool 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
1295 template <typename K, typename M>
1296 void PersistentCache<K, std::string, M>::clear_stats()
1297 {
1298 p_->clear_stats();
1299 }
1300
1301 template <typename K, typename M>
1302 void PersistentCache<K, std::string, M>::resize(int64_t size_in_bytes)
1303 {
1304 p_->resize(size_in_bytes);
1305 }
1306
1307 template <typename K, typename M>
1308 void PersistentCache<K, std::string, M>::trim_to(int64_t used_size_in_bytes)
1309 {
1310 p_->trim_to(used_size_in_bytes);
1311 }
1312
1313 template <typename K, typename M>
1314 void PersistentCache<K, std::string, M>::compact()
1315 {
1316 p_->compact();
1317 }
1318
1319 template <typename K, typename M>
1320 void 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
1331 template <typename K, typename V>
1332 class PersistentCache<K, V, std::string>
1333 {
1334 public:
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
1410 private:
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
1417 template <typename K, typename V>
1418 PersistentCache<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
1425 template <typename K, typename V>
1426 PersistentCache<K, V, std::string>::PersistentCache(std::string const& cache_path)
1427 : p_(PersistentStringCache::open(cache_path))
1428 {
1429 }
1430
1431 template <typename K, typename V>
1432 typename 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
1439 template <typename K, typename V>
1440 typename 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
1446 template <typename K, typename V>
1447 typename 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
1453 template <typename K, typename V>
1454 typename 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
1465 template <typename K, typename V>
1466 typename 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
1473 template <typename K, typename V>
1474 bool PersistentCache<K, V, std::string>::contains_key(K const& key) const
1475 {
1476 return p_->contains_key(CacheCodec<K>::encode(key));
1477 }
1478
1479 template <typename K, typename V>
1480 int64_t PersistentCache<K, V, std::string>::size() const noexcept
1481 {
1482 return p_->size();
1483 }
1484
1485 template <typename K, typename V>
1486 int64_t PersistentCache<K, V, std::string>::size_in_bytes() const noexcept
1487 {
1488 return p_->size_in_bytes();
1489 }
1490
1491 template <typename K, typename V>
1492 int64_t PersistentCache<K, V, std::string>::max_size_in_bytes() const noexcept
1493 {
1494 return p_->max_size_in_bytes();
1495 }
1496
1497 template <typename K, typename V>
1498 int64_t PersistentCache<K, V, std::string>::disk_size_in_bytes() const
1499 {
1500 return p_->disk_size_in_bytes();
1501 }
1502
1503 template <typename K, typename V>
1504 CacheDiscardPolicy PersistentCache<K, V, std::string>::discard_policy() const noexcept
1505 {
1506 return p_->discard_policy();
1507 }
1508
1509 template <typename K, typename V>
1510 PersistentCacheStats PersistentCache<K, V, std::string>::stats() const
1511 {
1512 return p_->stats();
1513 }
1514
1515 template <typename K, typename V>
1516 bool 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
1523 template <typename K, typename V>
1524 bool 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
1533 template <typename K, typename V>
1534 bool 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
1544 template <typename K, typename V>
1545 typename 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
1557 template <typename K, typename V>
1558 typename 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
1574 template <typename K, typename V>
1575 bool 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
1580 template <typename K, typename V>
1581 bool 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
1586 template <typename K, typename V>
1587 typename 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
1593 template <typename K, typename V>
1594 typename 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
1605 template <typename K, typename V>
1606 bool PersistentCache<K, V, std::string>::invalidate(K const& key)
1607 {
1608 return p_->invalidate(CacheCodec<K>::encode(key));
1609 }
1610
1611 template <typename K, typename V>
1612 void PersistentCache<K, V, std::string>::invalidate(std::vector<K> const& keys)
1613 {
1614 invalidate(keys.begin(), keys.end());
1615 }
1616
1617 template <typename K, typename V>
1618 template <typename It>
1619 void 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
1629 template <typename K, typename V>
1630 void PersistentCache<K, V, std::string>::invalidate(std::initializer_list<K> const& keys)
1631 {
1632 invalidate(keys.begin(), keys.end());
1633 }
1634
1635 template <typename K, typename V>
1636 void PersistentCache<K, V, std::string>::invalidate()
1637 {
1638 p_->invalidate();
1639 }
1640
1641 template <typename K, typename V>
1642 bool 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
1648 template <typename K, typename V>
1649 void PersistentCache<K, V, std::string>::clear_stats()
1650 {
1651 p_->clear_stats();
1652 }
1653
1654 template <typename K, typename V>
1655 void PersistentCache<K, V, std::string>::resize(int64_t size_in_bytes)
1656 {
1657 p_->resize(size_in_bytes);
1658 }
1659
1660 template <typename K, typename V>
1661 void PersistentCache<K, V, std::string>::trim_to(int64_t used_size_in_bytes)
1662 {
1663 p_->trim_to(used_size_in_bytes);
1664 }
1665
1666 template <typename K, typename V>
1667 void PersistentCache<K, V, std::string>::compact()
1668 {
1669 p_->compact();
1670 }
1671
1672 template <typename K, typename V>
1673 void 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
1684 template <typename M>
1685 class PersistentCache<std::string, std::string, M>
1686 {
1687 public:
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
1766 private:
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
1773 template <typename M>
1774 PersistentCache<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
1781 template <typename M>
1782 PersistentCache<std::string, std::string, M>::PersistentCache(std::string const& cache_path)
1783 : p_(PersistentStringCache::open(cache_path))
1784 {
1785 }
1786
1787 template <typename M>
1788 typename 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
1795 template <typename M>
1796 typename 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
1803 template <typename M>
1804 typename 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
1811 template <typename M>
1812 typename 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
1823 template <typename M>
1824 typename 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
1831 template <typename M>
1832 bool PersistentCache<std::string, std::string, M>::contains_key(std::string const& key) const
1833 {
1834 return p_->contains_key(key);
1835 }
1836
1837 template <typename M>
1838 int64_t PersistentCache<std::string, std::string, M>::size() const noexcept
1839 {
1840 return p_->size();
1841 }
1842
1843 template <typename M>
1844 int64_t PersistentCache<std::string, std::string, M>::size_in_bytes() const noexcept
1845 {
1846 return p_->size_in_bytes();
1847 }
1848
1849 template <typename M>
1850 int64_t PersistentCache<std::string, std::string, M>::max_size_in_bytes() const noexcept
1851 {
1852 return p_->max_size_in_bytes();
1853 }
1854
1855 template <typename M>
1856 int64_t PersistentCache<std::string, std::string, M>::disk_size_in_bytes() const
1857 {
1858 return p_->disk_size_in_bytes();
1859 }
1860
1861 template <typename M>
1862 CacheDiscardPolicy PersistentCache<std::string, std::string, M>::discard_policy() const noexcept
1863 {
1864 return p_->discard_policy();
1865 }
1866
1867 template <typename M>
1868 PersistentCacheStats PersistentCache<std::string, std::string, M>::stats() const
1869 {
1870 return p_->stats();
1871 }
1872
1873 template <typename M>
1874 bool 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
1881 template <typename M>
1882 bool 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
1890 template <typename M>
1891 bool 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
1899 template <typename M>
1900 bool 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
1910 template <typename M>
1911 typename 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
1923 template <typename M>
1924 typename 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
1940 template <typename M>
1941 bool 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
1946 template <typename M>
1947 typename 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
1954 template <typename M>
1955 typename 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
1966 template <typename M>
1967 bool PersistentCache<std::string, std::string, M>::invalidate(std::string const& key)
1968 {
1969 return p_->invalidate(key);
1970 }
1971
1972 template <typename M>
1973 void PersistentCache<std::string, std::string, M>::invalidate(std::vector<std::string> const& keys)
1974 {
1975 invalidate(keys.begin(), keys.end());
1976 }
1977
1978 template <typename M>
1979 template <typename It>
1980 void 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
1990 template <typename M>
1991 void PersistentCache<std::string, std::string, M>::invalidate(std::initializer_list<std::string> const& keys)
1992 {
1993 invalidate(keys.begin(), keys.end());
1994 }
1995
1996 template <typename M>
1997 void PersistentCache<std::string, std::string, M>::invalidate()
1998 {
1999 p_->invalidate();
2000 }
2001
2002 template <typename M>
2003 bool 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
2009 template <typename M>
2010 void PersistentCache<std::string, std::string, M>::clear_stats()
2011 {
2012 p_->clear_stats();
2013 }
2014
2015 template <typename M>
2016 void PersistentCache<std::string, std::string, M>::resize(int64_t size_in_bytes)
2017 {
2018 p_->resize(size_in_bytes);
2019 }
2020
2021 template <typename M>
2022 void 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
2027 template <typename M>
2028 void PersistentCache<std::string, std::string, M>::compact()
2029 {
2030 p_->compact();
2031 }
2032
2033 template <typename M>
2034 void 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
2041 template <typename V>
2042 class PersistentCache<std::string, V, std::string>
2043 {
2044 public:
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
2120 private:
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
2127 template <typename V>
2128 PersistentCache<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
2135 template <typename V>
2136 PersistentCache<std::string, V, std::string>::PersistentCache(std::string const& cache_path)
2137 : p_(PersistentStringCache::open(cache_path))
2138 {
2139 }
2140
2141 template <typename V>
2142 typename 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
2149 template <typename V>
2150 typename 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
2157 template <typename V>
2158 typename 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
2165 template <typename V>
2166 typename 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
2177 template <typename V>
2178 typename 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
2185 template <typename V>
2186 bool PersistentCache<std::string, V, std::string>::contains_key(std::string const& key) const
2187 {
2188 return p_->contains_key(key);
2189 }
2190
2191 template <typename V>
2192 int64_t PersistentCache<std::string, V, std::string>::size() const noexcept
2193 {
2194 return p_->size();
2195 }
2196
2197 template <typename V>
2198 int64_t PersistentCache<std::string, V, std::string>::size_in_bytes() const noexcept
2199 {
2200 return p_->size_in_bytes();
2201 }
2202
2203 template <typename V>
2204 int64_t PersistentCache<std::string, V, std::string>::max_size_in_bytes() const noexcept
2205 {
2206 return p_->max_size_in_bytes();
2207 }
2208
2209 template <typename V>
2210 int64_t PersistentCache<std::string, V, std::string>::disk_size_in_bytes() const
2211 {
2212 return p_->disk_size_in_bytes();
2213 }
2214
2215 template <typename V>
2216 CacheDiscardPolicy PersistentCache<std::string, V, std::string>::discard_policy() const noexcept
2217 {
2218 return p_->discard_policy();
2219 }
2220
2221 template <typename V>
2222 PersistentCacheStats PersistentCache<std::string, V, std::string>::stats() const
2223 {
2224 return p_->stats();
2225 }
2226
2227 template <typename V>
2228 bool 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
2235 template <typename V>
2236 bool 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
2245 template <typename V>
2246 bool 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
2256 template <typename V>
2257 typename 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
2269 template <typename V>
2270 typename 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
2286 template <typename V>
2287 bool 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
2292 template <typename V>
2293 bool 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
2300 template <typename V>
2301 typename 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
2308 template <typename V>
2309 typename 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
2320 template <typename V>
2321 bool PersistentCache<std::string, V, std::string>::invalidate(std::string const& key)
2322 {
2323 return p_->invalidate(key);
2324 }
2325
2326 template <typename V>
2327 void PersistentCache<std::string, V, std::string>::invalidate(std::vector<std::string> const& keys)
2328 {
2329 invalidate(keys.begin(), keys.end());
2330 }
2331
2332 template <typename V>
2333 template <typename It>
2334 void 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
2344 template <typename V>
2345 void PersistentCache<std::string, V, std::string>::invalidate(std::initializer_list<std::string> const& keys)
2346 {
2347 invalidate(keys.begin(), keys.end());
2348 }
2349
2350 template <typename V>
2351 void PersistentCache<std::string, V, std::string>::invalidate()
2352 {
2353 p_->invalidate();
2354 }
2355
2356 template <typename V>
2357 bool 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
2363 template <typename V>
2364 void PersistentCache<std::string, V, std::string>::clear_stats()
2365 {
2366 p_->clear_stats();
2367 }
2368
2369 template <typename V>
2370 void PersistentCache<std::string, V, std::string>::resize(int64_t size_in_bytes)
2371 {
2372 p_->resize(size_in_bytes);
2373 }
2374
2375 template <typename V>
2376 void 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
2381 template <typename V>
2382 void PersistentCache<std::string, V, std::string>::compact()
2383 {
2384 p_->compact();
2385 }
2386
2387 template <typename V>
2388 void 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
2395 template <typename K>
2396 class PersistentCache<K, std::string, std::string>
2397 {
2398 public:
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
2479 private:
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
2486 template <typename K>
2487 PersistentCache<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
2494 template <typename K>
2495 PersistentCache<K, std::string, std::string>::PersistentCache(std::string const& cache_path)
2496 : p_(PersistentStringCache::open(cache_path))
2497 {
2498 }
2499
2500 template <typename K>
2501 typename 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
2508 template <typename K>
2509 typename 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
2516 template <typename K>
2517 typename 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
2524 template <typename K>
2525 typename 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
2536 template <typename K>
2537 typename 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
2544 template <typename K>
2545 bool PersistentCache<K, std::string, std::string>::contains_key(K const& key) const
2546 {
2547 return p_->contains_key(CacheCodec<K>::encode(key));
2548 }
2549
2550 template <typename K>
2551 int64_t PersistentCache<K, std::string, std::string>::size() const noexcept
2552 {
2553 return p_->size();
2554 }
2555
2556 template <typename K>
2557 int64_t PersistentCache<K, std::string, std::string>::size_in_bytes() const noexcept
2558 {
2559 return p_->size_in_bytes();
2560 }
2561
2562 template <typename K>
2563 int64_t PersistentCache<K, std::string, std::string>::max_size_in_bytes() const noexcept
2564 {
2565 return p_->max_size_in_bytes();
2566 }
2567
2568 template <typename K>
2569 int64_t PersistentCache<K, std::string, std::string>::disk_size_in_bytes() const
2570 {
2571 return p_->disk_size_in_bytes();
2572 }
2573
2574 template <typename K>
2575 CacheDiscardPolicy PersistentCache<K, std::string, std::string>::discard_policy() const noexcept
2576 {
2577 return p_->discard_policy();
2578 }
2579
2580 template <typename K>
2581 PersistentCacheStats PersistentCache<K, std::string, std::string>::stats() const
2582 {
2583 return p_->stats();
2584 }
2585
2586 template <typename K>
2587 bool 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
2594 template <typename K>
2595 bool 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
2603 template <typename K>
2604 bool 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
2612 template <typename K>
2613 bool 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
2623 template <typename K>
2624 typename 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
2637 template <typename K>
2638 typename 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
2655 template <typename K>
2656 bool 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
2661 template <typename K>
2662 bool 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
2667 template <typename K>
2668 typename 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
2675 template <typename K>
2676 typename 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
2687 template <typename K>
2688 bool PersistentCache<K, std::string, std::string>::invalidate(K const& key)
2689 {
2690 return p_->invalidate(CacheCodec<K>::encode(key));
2691 }
2692
2693 template <typename K>
2694 void PersistentCache<K, std::string, std::string>::invalidate(std::vector<K> const& keys)
2695 {
2696 invalidate(keys.begin(), keys.end());
2697 }
2698
2699 template <typename K>
2700 template <typename It>
2701 void 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
2711 template <typename K>
2712 void PersistentCache<K, std::string, std::string>::invalidate(std::initializer_list<K> const& keys)
2713 {
2714 invalidate(keys.begin(), keys.end());
2715 }
2716
2717 template <typename K>
2718 void PersistentCache<K, std::string, std::string>::invalidate()
2719 {
2720 p_->invalidate();
2721 }
2722
2723 template <typename K>
2724 bool 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
2730 template <typename K>
2731 void PersistentCache<K, std::string, std::string>::clear_stats()
2732 {
2733 p_->clear_stats();
2734 }
2735
2736 template <typename K>
2737 void PersistentCache<K, std::string, std::string>::resize(int64_t size_in_bytes)
2738 {
2739 p_->resize(size_in_bytes);
2740 }
2741
2742 template <typename K>
2743 void 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
2748 template <typename K>
2749 void PersistentCache<K, std::string, std::string>::compact()
2750 {
2751 p_->compact();
2752 }
2753
2754 template <typename K>
2755 void 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
2766 template <>
2767 class PersistentCache<std::string, std::string, std::string>
2768 {
2769 public:
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
2851 private:
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
2858 PersistentCache<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
2865 PersistentCache<std::string, std::string, std::string>::PersistentCache(std::string const& cache_path)
2866 : p_(PersistentStringCache::open(cache_path))
2867 {
2868 }
2869
2870 typename 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
2879 typename 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
2886 typename 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();
2891 }
2892
2893 typename PersistentCache<std::string, std::string, std::string>::OptionalData
2894 PersistentCache<std::string, std::string, std::string>::get_data(std::string const& key) const
2895 {
2896 auto sdata = p_->get_data(key);
2897 if (!sdata)
2898 {
2899 return OptionalData();
2900 }
2901 return OptionalData({sdata->value, sdata->metadata});
2902 }
2903
2904 typename PersistentCache<std::string, std::string, std::string>::OptionalMetadata
2905 PersistentCache<std::string, std::string, std::string>::get_metadata(std::string const& key) const
2906 {
2907 auto smeta = p_->get_metadata(key);
2908 return smeta ? OptionalMetadata(*smeta) : OptionalMetadata();
2909 }
2910
2911 bool PersistentCache<std::string, std::string, std::string>::contains_key(std::string const& key) const
2912 {
2913 return p_->contains_key(key);
2914 }
2915
2916 int64_t PersistentCache<std::string, std::string, std::string>::size() const noexcept
2917 {
2918 return p_->size();
2919 }
2920
2921 int64_t PersistentCache<std::string, std::string, std::string>::size_in_bytes() const noexcept
2922 {
2923 return p_->size_in_bytes();
2924 }
2925
2926 int64_t PersistentCache<std::string, std::string, std::string>::max_size_in_bytes() const noexcept
2927 {
2928 return p_->max_size_in_bytes();
2929 }
2930
2931 int64_t PersistentCache<std::string, std::string, std::string>::disk_size_in_bytes() const
2932 {
2933 return p_->disk_size_in_bytes();
2934 }
2935
2936 CacheDiscardPolicy PersistentCache<std::string, std::string, std::string>::discard_policy() const noexcept
2937 {
2938 return p_->discard_policy();
2939 }
2940
2941 PersistentCacheStats PersistentCache<std::string, std::string, std::string>::stats() const
2942 {
2943 return p_->stats();
2944 }
2945
2946 bool PersistentCache<std::string, std::string, std::string>::put(
2947 std::string const& key, std::string const& value, std::chrono::time_point<std::chrono::system_clock> expiry_time)
2948 {
2949 return p_->put(key, value, expiry_time);
2950 }
2951
2952 bool PersistentCache<std::string, std::string, std::string>::put(
2953 std::string const& key,
2954 char const* value,
2955 int64_t size,
2956 std::chrono::time_point<std::chrono::system_clock> expiry_time)
2957 {
2958 return p_->put(key, value, size, expiry_time);
2959 }
2960
2961 bool PersistentCache<std::string, std::string, std::string>::put(
2962 std::string const& key,
2963 std::string const& value,
2964 std::string const& metadata,
2965 std::chrono::time_point<std::chrono::system_clock> expiry_time)
2966 {
2967 return p_->put(key, value, metadata, expiry_time);
2968 }
2969
2970 bool PersistentCache<std::string, std::string, std::string>::put(
2971 std::string const& key,
2972 char const* value,
2973 int64_t value_size,
2974 char const* metadata,
2975 int64_t metadata_size,
2976 std::chrono::time_point<std::chrono::system_clock> expiry_time)
2977 {
2978 return p_->put(key, value, value_size, metadata, metadata_size, expiry_time);
2979 }
2980
2981 typename PersistentCache<std::string, std::string, std::string>::OptionalValue
2982 PersistentCache<std::string, std::string, std::string>::get_or_put(
2983 std::string const& key, PersistentCache<std::string, std::string, std::string>::Loader const& load_func)
2984 {
2985 auto sload_func = [&](std::string const&, PersistentStringCache const&)
2986 {
2987 load_func(key, *this);
2988 };
2989 auto svalue = p_->get_or_put(key, sload_func);
2990 return svalue ? OptionalValue(*svalue) : OptionalValue();
2991 }
2992
2993 typename PersistentCache<std::string, std::string, std::string>::OptionalData
2994 PersistentCache<std::string, std::string, std::string>::get_or_put_data(
2995 std::string const& key, PersistentCache<std::string, std::string, std::string>::Loader const& load_func)
2996 {
2997 auto sload_func = [&](std::string const&, PersistentStringCache const&)
2998 {
2999 load_func(key, *this);
3000 };
3001 auto sdata = p_->get_or_put_data(key, sload_func);
3002 if (!sdata)
3003 {
3004 return OptionalData();
3005 }
3006 return OptionalData({sdata->value, sdata->metadata});
3007 }
3008
3009 bool PersistentCache<std::string, std::string, std::string>::put_metadata(std::string const& key,
3010 std::string const& metadata)
3011 {
3012 return p_->put_metadata(key, metadata);
3013 }
3014
3015 bool PersistentCache<std::string, std::string, std::string>::put_metadata(std::string const& key,
3016 char const* metadata,
3017 int64_t size)
3018 {
3019 return p_->put_metadata(key, metadata, size);
3020 }
3021
3022 typename PersistentCache<std::string, std::string, std::string>::OptionalValue
3023 PersistentCache<std::string, std::string, std::string>::take(std::string const& key)
3024 {
3025 auto svalue = p_->take(key);
3026 return svalue ? OptionalValue(*svalue) : OptionalValue();
3027 }
3028
3029 typename PersistentCache<std::string, std::string, std::string>::OptionalData
3030 PersistentCache<std::string, std::string, std::string>::take_data(std::string const& key)
3031 {
3032 auto sdata = p_->take_data(key);
3033 if (!sdata)
3034 {
3035 return OptionalData();
3036 }
3037 return OptionalData({sdata->value, sdata->metadata});
3038 }
3039
3040 bool PersistentCache<std::string, std::string, std::string>::invalidate(std::string const& key)
3041 {
3042 return p_->invalidate(key);
3043 }
3044
3045 void PersistentCache<std::string, std::string, std::string>::invalidate(std::vector<std::string> const& keys)
3046 {
3047 invalidate(keys.begin(), keys.end());
3048 }
3049
3050 template <typename It>
3051 void PersistentCache<std::string, std::string, std::string>::invalidate(It begin, It end)
3052 {
3053 std::vector<std::string> skeys;
3054 for (auto&& it = begin; it < end; ++it)
3055 {
3056 skeys.push_back(*it);
3057 }
3058 p_->invalidate(skeys.begin(), skeys.end());
3059 }
3060
3061 void PersistentCache<std::string, std::string, std::string>::invalidate(std::initializer_list<std::string> const& keys)
3062 {
3063 invalidate(keys.begin(), keys.end());
3064 }
3065
3066 void PersistentCache<std::string, std::string, std::string>::invalidate()
3067 {
3068 p_->invalidate();
3069 }
3070
3071 bool PersistentCache<std::string, std::string, std::string>::touch(
3072 std::string const& key, std::chrono::time_point<std::chrono::system_clock> expiry_time)
3073 {
3074 return p_->touch(key, expiry_time);
3075 }
3076
3077 void PersistentCache<std::string, std::string, std::string>::clear_stats()
3078 {
3079 p_->clear_stats();
3080 }
3081
3082 void PersistentCache<std::string, std::string, std::string>::resize(int64_t size_in_bytes)
3083 {
3084 p_->resize(size_in_bytes);
3085 }
3086
3087 void PersistentCache<std::string, std::string, std::string>::trim_to(int64_t used_size_in_bytes)
3088 {
3089 p_->trim_to(used_size_in_bytes);
3090 }
3091
3092 void PersistentCache<std::string, std::string, std::string>::compact()
3093 {
3094 p_->compact();
3095 }
3096
3097 void PersistentCache<std::string, std::string, std::string>::set_handler(CacheEvent events, EventCallback cb)
3098 {
3099 p_->set_handler(events, cb);
3100 }
3101
3102 // @endcond
3103
3104 } // namespace core
core::PersistentCache::get_metadata
OptionalMetadata get_metadata(K const &key) const
Returns the metadata for an entry in the cache, provided the entry has not expired.
core::PersistentCache::trim_to
void trim_to(int64_t used_size_in_bytes)
Expires entries.
core::PersistentCache::touch
bool touch(K const &key, std::chrono::time_point< std::chrono::system_clock > expiry_time=std::chrono::system_clock::time_point())
Updates the access time of an entry.
core::CacheDiscardPolicy
CacheDiscardPolicy
Indicates the discard policy to make room for entries when the cache is full.
Definition: cache_discard_policy.h:36
core::PersistentCache::get_data
OptionalData get_data(K const &key) const
Returns the data for an entry in the cache, provided the entry has not expired.
core::PersistentCache::OptionalValue
Optional< V > OptionalValue
Definition: persistent_cache.h:156
core::PersistentCache::contains_key
bool contains_key(K const &key) const
Tests if an (unexpired) entry is in the cache.
core::PersistentCacheStats
Class that provides (read-only) access to cache statistics and settings.
Definition: persistent_cache_stats.h:43
core::Optional
boost::optional< T > Optional
Convenience typedef for nullable values.
Definition: optional.h:33
core::PersistentCache::OptionalMetadata
Optional< M > OptionalMetadata
Definition: persistent_cache.h:157
core::PersistentCache::open
static UPtr open(std::string const &cache_path, int64_t max_size_in_bytes, CacheDiscardPolicy policy)
Creates or opens a PersistentCache.
core::PersistentCache::resize
void resize(int64_t size_in_bytes)
Changes the maximum size of the cache.
core::PersistentCache::put_metadata
bool put_metadata(K const &key, M const &metadata)
Adds or replaces the metadata for an entry. If M = std::string, an overload that accepts const char* ...
core::PersistentCache::size
int64_t size() const noexcept
Returns the number of entries in the cache.
core::PersistentCache::get_or_put_data
OptionalData get_or_put_data(K const &key, Loader const &load_func)
Atomically retrieves or stores a cache entry.
core::CacheCodec::encode
static std::string encode(T const &value)
Converts a value of custom type T into a string.
core::PersistentCache::discard_policy
CacheDiscardPolicy discard_policy() const noexcept
Returns the discard policy of the cache.
core::CacheCodec::decode
static T decode(std::string const &s)
Converts a string into a value of custom type T.
core::PersistentCache::operator=
PersistentCache & operator=(PersistentCache &&)=default
core::PersistentCache::EventCallback
std::function< void(K const &key, CacheEvent ev, PersistentCacheStats const &stats)> EventCallback
The type of a handler function.
Definition: persistent_cache.h:371
core::PersistentCache::operator=
PersistentCache & operator=(PersistentCache const &)=delete
core::PersistentCache::Loader
std::function< void(K const &key, PersistentCache< K, V, M > &cache)> Loader
Function called by the cache to load an entry after a cache miss.
Definition: persistent_cache.h:280
core::PersistentCache::OptionalKey
Optional< K > OptionalKey
Convenience typedefs for returning nullable values.
Definition: persistent_cache.h:155
core::PersistentCache::Data::metadata
M metadata
Stores the metadata of an entry. If no metadata exists for an entry, metadata is returned as the empt...
Definition: persistent_cache.h:140
persistent_string_cache.h
core::PersistentCache::PersistentCache
PersistentCache(PersistentCache &&)=default
core::PersistentCache::take
OptionalValue take(K const &key)
Removes an entry and returns its value.
core::PersistentCache::invalidate
void invalidate()
Deletes all entries from the cache.
core::PersistentCache::max_size_in_bytes
int64_t max_size_in_bytes() const noexcept
Returns the maximum size of the cache in bytes.
core
Top-level namespace for core functionality.
Definition: cache_codec.h:24
core::PersistentCache::OptionalData
Optional< Data > OptionalData
Definition: persistent_cache.h:158
core::PersistentCache::get_or_put
OptionalValue get_or_put(K const &key, Loader const &load_func)
Atomically retrieves or stores a cache entry.
core::PersistentCache::size_in_bytes
int64_t size_in_bytes() const noexcept
Returns the number of bytes consumed by entries in the cache.
cache_codec.h
core::PersistentStringCache
A cache of key-value pairs with persistent storage.
Definition: persistent_string_cache.h:69
core::PersistentCache
A persistent cache of key-value pairs and metadata of user-defined type.
Definition: persistent_cache.h:119
core::PersistentCache::put
bool put(K const &key, V const &value, std::chrono::time_point< std::chrono::system_clock > expiry_time=std::chrono::system_clock::time_point())
Adds or updates an entry. If V = std::string, the method is also overloaded to to accept char const* ...
core::PersistentCache::get
OptionalValue get(K const &key) const
Returns the value of an entry in the cache, provided the entry has not expired.
core::PersistentCache::UPtr
std::unique_ptr< PersistentCache< K, V, M > > UPtr
Definition: persistent_cache.h:124
core::PersistentCache::disk_size_in_bytes
int64_t disk_size_in_bytes() const
Returns an estimate of the disk space consumed by the cache.
core::PersistentCache::set_handler
void set_handler(CacheEvent events, EventCallback cb)
Installs a handler for one or more events.
core::PersistentCache::stats
PersistentCacheStats stats() const
Returns statistics for the cache.
core::PersistentCache::take_data
OptionalData take_data(K const &key)
Removes an entry and returns its value and metadata.
core::PersistentCache::~PersistentCache
~PersistentCache()=default
core::PersistentCache::PersistentCache
PersistentCache(PersistentCache const &)=delete
core::PersistentCache::Data
Simple pair of value and metadata.
Definition: persistent_cache.h:130
core::PersistentCache::Data::value
V value
Stores the value of an entry.
Definition: persistent_cache.h:134
core::PersistentCache::clear_stats
void clear_stats()
Resets all statistics counters.
core::PersistentCache::open
static UPtr open(std::string const &cache_path)
Opens an existing PersistentCache.
core::PersistentCache::compact
void compact()
Compacts the database.
core::CacheEvent
CacheEvent
Event types that can be monitored.
Definition: cache_events.h:39