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) 2014 FUJITSU LIMITED
7 * Copyright (C) 2014 CERN (Switzerland)
9 * Author: Takanori Nakao <nakao.takanori@jp.fujitsu.com>
10 * Author: Takeshi Miyamae <miyamae.takeshi@jp.fujitsu.com>
11 * Author: Andreas-Joachim Peters <Andreas.Joachim.Peters@cern.ch>
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public
15 * License as published by the Free Software Foundation; either
16 * version 2.1 of the License, or (at your option) any later version.
20 // -----------------------------------------------------------------------------
21 #include "ErasureCodeShecTableCache.h"
22 #include "common/debug.h"
23 // -----------------------------------------------------------------------------
26 // -----------------------------------------------------------------------------
27 #define dout_context g_ceph_context
28 #define dout_subsys ceph_subsys_osd
30 #define dout_prefix _tc_prefix(_dout)
31 // -----------------------------------------------------------------------------
33 // -----------------------------------------------------------------------------
36 _tc_prefix(std::ostream* _dout) {
37 return *_dout << "ErasureCodeShecTableCache: ";
40 // -----------------------------------------------------------------------------
42 ErasureCodeShecTableCache::~ErasureCodeShecTableCache()
44 Mutex::Locker lock(codec_tables_guard);
46 // clean-up all allocated tables
48 codec_technique_tables_t::const_iterator ttables_it;
49 codec_tables_t::const_iterator tables_it;
50 codec_tables_t_::const_iterator tables_it_;
51 codec_tables_t__::const_iterator tables_it__;
52 codec_table_t::const_iterator table_it;
54 for (ttables_it = encoding_table.begin(); ttables_it != encoding_table.end(); ++ttables_it) {
55 for (tables_it = ttables_it->second.begin(); tables_it != ttables_it->second.end(); ++tables_it) {
56 for (tables_it_ = tables_it->second.begin(); tables_it_ != tables_it->second.end(); ++tables_it_) {
57 for (tables_it__ = tables_it_->second.begin(); tables_it__ != tables_it_->second.end(); ++tables_it__) {
58 for (table_it = tables_it__->second.begin(); table_it != tables_it__->second.end(); ++table_it) {
59 if (table_it->second) {
60 if (*(table_it->second)) {
61 delete *(table_it->second);
63 delete table_it->second;
73 std::map<int, lru_map_t*>::const_iterator lru_map_it;
74 std::map<int, lru_list_t*>::const_iterator lru_list_it;
76 for (lru_map_it = decoding_tables.begin();
77 lru_map_it != decoding_tables.end();
79 if (lru_map_it->second) {
80 delete lru_map_it->second;
84 for (lru_list_it = decoding_tables_lru.begin();
85 lru_list_it != decoding_tables_lru.end();
87 if (lru_list_it->second) {
88 delete lru_list_it->second;
94 ErasureCodeShecTableCache::lru_map_t*
95 ErasureCodeShecTableCache::getDecodingTables(int technique) {
96 // the caller must hold the guard mutex:
97 // => Mutex::Locker lock(codec_tables_guard);
99 // create an lru_map if not yet allocated
100 if (!decoding_tables[technique]) {
101 decoding_tables[technique] = new lru_map_t;
103 return decoding_tables[technique];
106 ErasureCodeShecTableCache::lru_list_t*
107 ErasureCodeShecTableCache::getDecodingTablesLru(int technique) {
108 // the caller must hold the guard mutex:
109 // => Mutex::Locker lock(codec_tables_guard);
111 // create an lru_list if not yet allocated
112 if (!decoding_tables_lru[technique]) {
113 decoding_tables_lru[technique] = new lru_list_t;
115 return decoding_tables_lru[technique];
119 ErasureCodeShecTableCache::getEncodingTable(int technique, int k, int m, int c, int w)
121 Mutex::Locker lock(codec_tables_guard);
122 return getEncodingTableNoLock(technique,k,m,c,w);
125 // -----------------------------------------------------------------------------
128 ErasureCodeShecTableCache::getEncodingTableNoLock(int technique, int k, int m, int c, int w)
130 // create a pointer to store an encoding table address
131 if (!encoding_table[technique][k][m][c][w]) {
132 encoding_table[technique][k][m][c][w] = new (int*);
133 *encoding_table[technique][k][m][c][w] = 0;
135 return encoding_table[technique][k][m][c][w];
139 ErasureCodeShecTableCache::setEncodingTable(int technique, int k, int m, int c, int w, int* ec_in_table)
141 Mutex::Locker lock(codec_tables_guard);
142 int** ec_out_table = getEncodingTableNoLock(technique, k, m, c, w);
144 // somebody might have deposited this table in the meanwhile, so clean
145 // the input table and return the stored one
147 return *ec_out_table;
149 // we store the provided input table and return this one
150 *encoding_table[technique][k][m][c][w] = ec_in_table;
156 ErasureCodeShecTableCache::getLock()
158 return &codec_tables_guard;
162 ErasureCodeShecTableCache::getDecodingCacheSignature(int k, int m, int c, int w,
163 int *erased, int *avails) {
164 uint64_t signature = 0;
165 signature = (uint64_t)k;
166 signature |= ((uint64_t)m << 6);
167 signature |= ((uint64_t)c << 12);
168 signature |= ((uint64_t)w << 18);
170 for (int i=0; i < k+m; i++) {
171 signature |= ((uint64_t)(avails[i] ? 1 : 0) << (24+i));
173 for (int i=0; i < k+m; i++) {
174 signature |= ((uint64_t)(erased[i] ? 1 : 0) << (44+i));
180 ErasureCodeShecTableCache::getDecodingTableFromCache(int* decoding_matrix,
191 // --------------------------------------------------------------------------
192 // LRU decoding matrix cache
193 // --------------------------------------------------------------------------
195 uint64_t signature = getDecodingCacheSignature(k, m, c, w, erased, avails);
196 Mutex::Locker lock(codec_tables_guard);
198 dout(20) << "[ get table ] = " << signature << dendl;
200 // we try to fetch a decoding table from an LRU cache
201 lru_map_t* decode_tbls_map =
202 getDecodingTables(technique);
204 lru_list_t* decode_tbls_lru =
205 getDecodingTablesLru(technique);
207 lru_map_t::iterator decode_tbls_map_it = decode_tbls_map->find(signature);
208 if (decode_tbls_map_it == decode_tbls_map->end()) {
212 dout(20) << "[ cached table ] = " << signature << dendl;
213 // copy parameters out of the cache
215 memcpy(decoding_matrix,
216 decode_tbls_map_it->second.second.decoding_matrix,
217 k * k * sizeof(int));
219 decode_tbls_map_it->second.second.dm_row,
222 decode_tbls_map_it->second.second.dm_column,
225 decode_tbls_map_it->second.second.minimum,
226 (k+m) * sizeof(int));
228 // find item in LRU queue and push back
229 decode_tbls_lru->splice(decode_tbls_lru->end(),
231 decode_tbls_map_it->second.first);
236 ErasureCodeShecTableCache::putDecodingTableToCache(int* decoding_matrix,
247 // --------------------------------------------------------------------------
248 // LRU decoding matrix cache
249 // --------------------------------------------------------------------------
251 Mutex::Locker lock(codec_tables_guard);
253 uint64_t signature = getDecodingCacheSignature(k, m, c, w, erased, avails);
254 dout(20) << "[ put table ] = " << signature << dendl;
256 // we store a new table to the cache
258 // bufferptr cachetable;
260 lru_map_t* decode_tbls_map =
261 getDecodingTables(technique);
263 lru_list_t* decode_tbls_lru =
264 getDecodingTablesLru(technique);
266 if (decode_tbls_map->count(signature)) {
267 dout(20) << "[ already on table ] = " << signature << dendl;
269 // find item in LRU queue and push back
270 decode_tbls_lru->splice(decode_tbls_lru->end(),
272 (*decode_tbls_map)[signature].first);
276 // evt. shrink the LRU queue/map
277 if ((int)decode_tbls_lru->size() >=
278 ErasureCodeShecTableCache::decoding_tables_lru_length) {
279 dout(20) << "[ shrink lru ] = " << signature << dendl;
281 decode_tbls_map->erase(decode_tbls_lru->front());
283 decode_tbls_lru->pop_front();
287 dout(20) << "[ store table ] = " << signature << dendl;
289 decode_tbls_lru->push_back(signature);
291 // allocate a new buffer
292 lru_list_t::iterator it_end = decode_tbls_lru->end();
295 lru_entry_t &map_value =
296 (*decode_tbls_map)[signature] =
297 std::make_pair(it_end, DecodingCacheParameter());
298 map_value.second.decoding_matrix = new int[k*k];
299 map_value.second.dm_row = new int[k];
300 map_value.second.dm_column = new int[k];
301 map_value.second.minimum = new int[k+m];
303 memcpy(map_value.second.decoding_matrix,
305 k * k * sizeof(int));
306 memcpy(map_value.second.dm_row,
309 memcpy(map_value.second.dm_column,
312 memcpy(map_value.second.minimum,
314 (k+m) * sizeof(int));
316 dout(20) << "[ cache size ] = " << decode_tbls_lru->size() << dendl;