2 * Ceph - scalable distributed file system
4 * Copyright (C) 2014 CERN (Switzerland)
6 * Author: Andreas-Joachim Peters <Andreas.Joachim.Peters@cern.ch>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
17 * @file ErasureCodeIsaTableCache.cc
19 * @brief Erasure Code Isa CODEC Table Cache
21 * The INTEL ISA-L library supports two pre-defined encoding matrices (cauchy = default, reed_sol_van = default)
22 * The default CODEC implementation using these two matrices is implemented in class ErasureCodeIsaDefault.
23 * ISA-L allows to use custom matrices which might be added later as implementations deriving from the base class ErasoreCodeIsa.
26 // -----------------------------------------------------------------------------
27 #include "ErasureCodeIsaTableCache.h"
28 #include "common/debug.h"
29 // -----------------------------------------------------------------------------
31 // -----------------------------------------------------------------------------
32 #define dout_context g_ceph_context
33 #define dout_subsys ceph_subsys_osd
35 #define dout_prefix _tc_prefix(_dout)
36 // -----------------------------------------------------------------------------
38 // -----------------------------------------------------------------------------
41 _tc_prefix(std::ostream* _dout)
43 return *_dout << "ErasureCodeIsaTableCache: ";
46 // -----------------------------------------------------------------------------
48 ErasureCodeIsaTableCache::~ErasureCodeIsaTableCache()
50 Mutex::Locker lock(codec_tables_guard);
52 codec_technique_tables_t::const_iterator ttables_it;
53 codec_tables_t::const_iterator tables_it;
54 codec_table_t::const_iterator table_it;
56 std::map<int, lru_map_t*>::const_iterator lru_map_it;
57 std::map<int, lru_list_t*>::const_iterator lru_list_it;
59 // clean-up all allocated tables
60 for (ttables_it = encoding_coefficient.begin(); ttables_it != encoding_coefficient.end(); ++ttables_it) {
61 for (tables_it = ttables_it->second.begin(); tables_it != ttables_it->second.end(); ++tables_it) {
62 for (table_it = tables_it->second.begin(); table_it != tables_it->second.end(); ++table_it) {
63 if (table_it->second) {
64 if (*(table_it->second)) {
65 delete *(table_it->second);
67 delete table_it->second;
73 for (ttables_it = encoding_table.begin(); ttables_it != encoding_table.end(); ++ttables_it) {
74 for (tables_it = ttables_it->second.begin(); tables_it != ttables_it->second.end(); ++tables_it) {
75 for (table_it = tables_it->second.begin(); table_it != tables_it->second.end(); ++table_it) {
76 if (table_it->second) {
77 if (*(table_it->second)) {
78 delete *(table_it->second);
80 delete table_it->second;
86 for (lru_map_it = decoding_tables.begin(); lru_map_it != decoding_tables.end(); ++lru_map_it) {
87 if (lru_map_it->second) {
88 delete lru_map_it->second;
92 for (lru_list_it = decoding_tables_lru.begin(); lru_list_it != decoding_tables_lru.end(); ++lru_list_it) {
93 if (lru_list_it->second) {
94 delete lru_list_it->second;
99 // -----------------------------------------------------------------------------
102 ErasureCodeIsaTableCache::getDecodingTableCacheSize(int matrixtype)
104 Mutex::Locker lock(codec_tables_guard);
105 if (decoding_tables[matrixtype])
106 return decoding_tables[matrixtype]->size();
111 // -----------------------------------------------------------------------------
113 ErasureCodeIsaTableCache::lru_map_t*
114 ErasureCodeIsaTableCache::getDecodingTables(int matrix_type)
116 // the caller must hold the guard mutex:
117 // => Mutex::Locker lock(codec_tables_guard);
119 // create an lru_map if not yet allocated
120 if (!decoding_tables[matrix_type]) {
121 decoding_tables[matrix_type] = new lru_map_t;
123 return decoding_tables[matrix_type];
126 // -----------------------------------------------------------------------------
128 ErasureCodeIsaTableCache::lru_list_t*
129 ErasureCodeIsaTableCache::getDecodingTablesLru(int matrix_type)
131 // the caller must hold the guard mutex:
132 // => Mutex::Locker lock(codec_tables_guard);
134 // create an lru_list if not yet allocated
135 if (!decoding_tables_lru[matrix_type]) {
136 decoding_tables_lru[matrix_type] = new lru_list_t;
138 return decoding_tables_lru[matrix_type];
141 // -----------------------------------------------------------------------------
144 ErasureCodeIsaTableCache::getEncodingTable(int matrix, int k, int m)
146 Mutex::Locker lock(codec_tables_guard);
147 return getEncodingTableNoLock(matrix,k,m);
150 // -----------------------------------------------------------------------------
153 ErasureCodeIsaTableCache::getEncodingTableNoLock(int matrix, int k, int m)
155 // create a pointer to store an encoding table address
156 if (!encoding_table[matrix][k][m]) {
157 encoding_table[matrix][k][m] = new (unsigned char*);
158 *encoding_table[matrix][k][m] = 0;
160 return encoding_table[matrix][k][m];
163 // -----------------------------------------------------------------------------
166 ErasureCodeIsaTableCache::getEncodingCoefficient(int matrix, int k, int m)
168 Mutex::Locker lock(codec_tables_guard);
169 return getEncodingCoefficientNoLock(matrix,k,m);
172 // -----------------------------------------------------------------------------
175 ErasureCodeIsaTableCache::getEncodingCoefficientNoLock(int matrix, int k, int m)
177 // create a pointer to store an encoding coefficients adddress
178 if (!encoding_coefficient[matrix][k][m]) {
179 encoding_coefficient[matrix][k][m] = new (unsigned char*);
180 *encoding_coefficient[matrix][k][m] = 0;
182 return encoding_coefficient[matrix][k][m];
185 // -----------------------------------------------------------------------------
188 ErasureCodeIsaTableCache::setEncodingTable(int matrix, int k, int m, unsigned char* ec_in_table)
190 Mutex::Locker lock(codec_tables_guard);
191 unsigned char** ec_out_table = getEncodingTableNoLock(matrix, k, m);
193 // somebody might have deposited this table in the meanwhile, so clean
194 // the input table and return the stored one
196 return *ec_out_table;
198 // we store the provided input table and return this one
199 *encoding_table[matrix][k][m] = ec_in_table;
204 // -----------------------------------------------------------------------------
207 ErasureCodeIsaTableCache::setEncodingCoefficient(int matrix, int k, int m, unsigned char* ec_in_coeff)
209 Mutex::Locker lock(codec_tables_guard);
210 unsigned char** ec_out_coeff = getEncodingCoefficientNoLock(matrix, k, m);
212 // somebody might have deposited these coefficients in the meanwhile, so clean
213 // the input coefficients and return the stored ones
215 return *ec_out_coeff;
217 // we store the provided input coefficients and return these
218 *encoding_coefficient[matrix][k][m] = ec_in_coeff;
223 // -----------------------------------------------------------------------------
226 ErasureCodeIsaTableCache::getLock()
228 return &codec_tables_guard;
231 // -----------------------------------------------------------------------------
234 ErasureCodeIsaTableCache::getDecodingTableFromCache(std::string &signature,
235 unsigned char* &table,
240 // --------------------------------------------------------------------------
241 // LRU decoding matrix cache
242 // --------------------------------------------------------------------------
244 dout(12) << "[ get table ] = " << signature << dendl;
246 // we try to fetch a decoding table from an LRU cache
249 Mutex::Locker lock(codec_tables_guard);
251 lru_map_t* decode_tbls_map =
252 getDecodingTables(matrixtype);
254 lru_list_t* decode_tbls_lru =
255 getDecodingTablesLru(matrixtype);
257 if (decode_tbls_map->count(signature)) {
258 dout(12) << "[ cached table ] = " << signature << dendl;
259 // copy the table out of the cache
260 memcpy(table, (*decode_tbls_map)[signature].second.c_str(), k * (m + k)*32);
261 // find item in LRU queue and push back
262 dout(12) << "[ cache size ] = " << decode_tbls_lru->size() << dendl;
263 decode_tbls_lru->splice( (decode_tbls_lru->begin()), *decode_tbls_lru, (*decode_tbls_map)[signature].first);
270 // -----------------------------------------------------------------------------
273 ErasureCodeIsaTableCache::putDecodingTableToCache(std::string &signature,
274 unsigned char* &table,
279 // --------------------------------------------------------------------------
280 // LRU decoding matrix cache
281 // --------------------------------------------------------------------------
283 dout(12) << "[ put table ] = " << signature << dendl;
285 // we store a new table to the cache
287 bufferptr cachetable;
289 Mutex::Locker lock(codec_tables_guard);
291 lru_map_t* decode_tbls_map =
292 getDecodingTables(matrixtype);
294 lru_list_t* decode_tbls_lru =
295 getDecodingTablesLru(matrixtype);
297 // evt. shrink the LRU queue/map
298 if ((int) decode_tbls_lru->size() >= ErasureCodeIsaTableCache::decoding_tables_lru_length) {
299 dout(12) << "[ shrink lru ] = " << signature << dendl;
301 cachetable = (*decode_tbls_map)[decode_tbls_lru->back()].second;
303 if ((int) cachetable.length() != (k * (m + k)*32)) {
304 // we need to replace this with a different size buffer
305 cachetable = buffer::create(k * (m + k)*32);
309 decode_tbls_map->erase(decode_tbls_lru->back());
311 decode_tbls_lru->pop_back();
312 // add to the head of lru
313 decode_tbls_lru->push_front(signature);
314 // add the new to the map
315 (*decode_tbls_map)[signature] = std::make_pair(decode_tbls_lru->begin(), cachetable);
317 dout(12) << "[ store table ] = " << signature << dendl;
318 // allocate a new buffer
319 cachetable = buffer::create(k * (m + k)*32);
320 decode_tbls_lru->push_front(signature);
321 (*decode_tbls_map)[signature] = std::make_pair(decode_tbls_lru->begin(), cachetable);
322 dout(12) << "[ cache size ] = " << decode_tbls_lru->size() << dendl;
325 // copy-in the new table
326 memcpy(cachetable.c_str(), table, k * (m + k)*32);