1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2013 Inktank Storage, Inc.
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
18 #include "include/Context.h"
19 #include "common/sharedptr_registry.hpp"
23 * Abstraction for ordering key updates
25 template<typename K, typename V>
28 /// Set keys according to map
29 virtual void set_keys(
30 const std::map<K, V> &keys ///< [in] keys/values to set
34 virtual void remove_keys(
35 const std::set<K> &to_remove ///< [in] keys to remove
38 /// Add context to fire when data is readable
39 virtual void add_callback(
40 Context *c ///< [in] Context to fire on readable
42 virtual ~Transaction() {}
46 * Abstraction for fetching keys
48 template<typename K, typename V>
51 /// Returns requested key values
53 const std::set<K> &keys, ///< [in] keys requested
54 std::map<K, V> *got ///< [out] values for keys obtained
55 ) = 0; ///< @return error value
59 const K &key, ///< [in] key after which to get next
60 pair<K, V> *next ///< [out] first key after key
61 ) = 0; ///< @return 0 on success, -ENOENT if there is no next
63 virtual ~StoreDriver() {}
67 * Uses SharedPtrRegistry to cache objects of in progress writes
68 * allowing the user to read/write a consistent view of the map
69 * without flushing writes.
71 template<typename K, typename V>
74 StoreDriver<K, V> *driver;
76 SharedPtrRegistry<K, boost::optional<V> > in_progress;
77 typedef typename SharedPtrRegistry<K, boost::optional<V> >::VPtr VPtr;
78 typedef ContainerContext<set<VPtr> > TransHolder;
81 MapCacher(StoreDriver<K, V> *driver) : driver(driver) {}
83 /// Fetch first key/value pair after specified key
85 K key, ///< [in] key after which to get next
86 pair<K, V> *next ///< [out] next key
89 pair<K, boost::optional<V> > cached;
91 bool got_cached = in_progress.get_next(key, &cached);
93 bool got_store = false;
94 int r = driver->get_next(key, &store);
95 if (r < 0 && r != -ENOENT) {
101 if (!got_cached && !got_store) {
105 (!got_store || store.first >= cached.first)) {
108 *next = make_pair(cached.first, cached.second.get());
112 continue; // value was cached as removed, recurse
120 ceph_abort(); // not reachable
122 } ///< @return error value, 0 on success, -ENOENT if no more entries
124 /// Adds operation setting keys to Transaction
126 const map<K, V> &keys, ///< [in] keys/values to set
127 Transaction<K, V> *t ///< [out] transaction to use
129 std::set<VPtr> vptrs;
130 for (typename map<K, V>::const_iterator i = keys.begin();
133 VPtr ip = in_progress.lookup_or_create(i->first, i->second);
138 t->add_callback(new TransHolder(vptrs));
141 /// Adds operation removing keys to Transaction
143 const set<K> &keys, ///< [in]
144 Transaction<K, V> *t ///< [out] transaction to use
146 std::set<VPtr> vptrs;
147 for (typename set<K>::const_iterator i = keys.begin();
150 boost::optional<V> empty;
151 VPtr ip = in_progress.lookup_or_create(*i, empty);
155 t->remove_keys(keys);
156 t->add_callback(new TransHolder(vptrs));
159 /// Gets keys, uses cached values for unstable keys
161 const set<K> &keys_to_get, ///< [in] set of keys to fetch
162 map<K, V> *got ///< [out] keys gotten
166 for (typename set<K>::const_iterator i = keys_to_get.begin();
167 i != keys_to_get.end();
169 VPtr val = in_progress.lookup(*i);
172 got->insert(make_pair(*i, val->get()));
173 //else: value cached is empty, key doesn't exist
178 int r = driver->get_keys(to_get, &_got);
181 for (typename map<K, V>::iterator i = _got.begin();
187 } ///< @return error value, 0 on success