1//
2// UniqueAccessExpireStrategy.h
3//
4// Library: Foundation
5// Package: Cache
6// Module: UniqueAccessExpireStrategy
7//
8// Definition of the UniqueAccessExpireStrategy class.
9//
10// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
11// and Contributors.
12//
13// SPDX-License-Identifier: BSL-1.0
14//
15
16
17#ifndef Foundation_UniqueAccessExpireStrategy_INCLUDED
18#define Foundation_UniqueAccessExpireStrategy_INCLUDED
19
20
21#include "Poco/KeyValueArgs.h"
22#include "Poco/ValidArgs.h"
23#include "Poco/AbstractStrategy.h"
24#include "Poco/Bugcheck.h"
25#include "Poco/Timestamp.h"
26#include "Poco/Timespan.h"
27#include "Poco/EventArgs.h"
28#include "Poco/UniqueExpireStrategy.h"
29#include <set>
30#include <map>
31
32
33namespace Poco {
34
35
36template <
37 class TKey,
38 class TValue
39>
40class UniqueAccessExpireStrategy: public AbstractStrategy<TKey, TValue>
41 /// An UniqueExpireStrategy implements time based expiration of cache entries. In contrast
42 /// to ExpireStrategy which only allows to set a per cache expiration value, it allows to define
43 /// expiration per CacheEntry.
44 /// Each TValue object must thus offer the following method:
45 ///
46 /// const Poco::Timestamp& getTimeout() const;
47 ///
48 /// which returns the timespan for how long an object will be valid without being accessed.
49{
50public:
51 typedef std::pair<TKey, Timespan> KeyExpire;
52 typedef std::multimap<Timestamp, KeyExpire> TimeIndex;
53 typedef typename TimeIndex::iterator IndexIterator;
54 typedef typename TimeIndex::const_iterator ConstIndexIterator;
55 typedef std::map<TKey, IndexIterator> Keys;
56 typedef typename Keys::iterator Iterator;
57
58public:
59 UniqueAccessExpireStrategy()
60 /// Create an unique expire strategy.
61 {
62 }
63
64 ~UniqueAccessExpireStrategy()
65 {
66 }
67
68 void onAdd(const void*, const KeyValueArgs <TKey, TValue>& args)
69 {
70 // the expire value defines how many millisecs in the future the
71 // value will expire, even insert negative values!
72 Timestamp expire;
73 expire += args.value().getTimeout().totalMicroseconds();
74
75 IndexIterator it = _keyIndex.insert(std::make_pair(expire, std::make_pair(args.key(), args.value().getTimeout())));
76 std::pair<Iterator, bool> stat = _keys.insert(std::make_pair(args.key(), it));
77 if (!stat.second)
78 {
79 _keyIndex.erase(stat.first->second);
80 stat.first->second = it;
81 }
82 }
83
84 void onRemove(const void*, const TKey& key)
85 {
86 Iterator it = _keys.find(key);
87 if (it != _keys.end())
88 {
89 _keyIndex.erase(it->second);
90 _keys.erase(it);
91 }
92 }
93
94 void onGet(const void*, const TKey& key)
95 {
96 // get updates the expiration time stamp
97 Iterator it = _keys.find(key);
98 if (it != _keys.end())
99 {
100 KeyExpire ke = it->second->second;
101 // gen new absolute expire value
102 Timestamp expire;
103 expire += ke.second.totalMicroseconds();
104 // delete old index
105 _keyIndex.erase(it->second);
106 IndexIterator itt = _keyIndex.insert(std::make_pair(expire, ke));
107 // update iterator
108 it->second = itt;
109 }
110 }
111
112 void onClear(const void*, const EventArgs& args)
113 {
114 _keys.clear();
115 _keyIndex.clear();
116 }
117
118 void onIsValid(const void*, ValidArgs<TKey>& args)
119 {
120 Iterator it = _keys.find(args.key());
121 if (it != _keys.end())
122 {
123 Timestamp now;
124 if (it->second->first <= now)
125 {
126 args.invalidate();
127 }
128 }
129 else //not found: probably removed by onReplace
130 args.invalidate();
131 }
132
133 void onReplace(const void*, std::set<TKey>& elemsToRemove)
134 {
135 // Note: replace only informs the cache which elements
136 // it would like to remove!
137 // it does not remove them on its own!
138 IndexIterator it = _keyIndex.begin();
139 Timestamp now;
140 while (it != _keyIndex.end() && it->first < now)
141 {
142 elemsToRemove.insert(it->second.first);
143 ++it;
144 }
145 }
146
147protected:
148 Keys _keys; /// For faster replacement of keys, the iterator points to the _keyIndex map
149 TimeIndex _keyIndex; /// Maps time to key value
150};
151
152
153} // namespace Poco
154
155
156#endif // Foundation_UniqueAccessExpireStrategy_INCLUDED
157