#include "common/debug.h"
// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+#define dout_subsys ceph_subsys_osd
+#undef dout_prefix
+#define dout_prefix _tc_prefix(_dout)
+// -----------------------------------------------------------------------------
+
+// -----------------------------------------------------------------------------
+
+static ostream&
+_tc_prefix(std::ostream* _dout) {
+ return *_dout << "ErasureCodeShecTableCache: ";
+}
+
+// -----------------------------------------------------------------------------
+
ErasureCodeShecTableCache::~ErasureCodeShecTableCache()
{
Mutex::Locker lock(codec_tables_guard);
- codec_technique_tables_t::const_iterator ttables_it;
- codec_tables_t::const_iterator tables_it;
- codec_tables_t_::const_iterator tables_it_;
- codec_tables_t__::const_iterator tables_it__;
- codec_table_t::const_iterator table_it;
-
// clean-up all allocated tables
+ {
+ codec_technique_tables_t::const_iterator ttables_it;
+ codec_tables_t::const_iterator tables_it;
+ codec_tables_t_::const_iterator tables_it_;
+ codec_tables_t__::const_iterator tables_it__;
+ codec_table_t::const_iterator table_it;
- for (ttables_it = encoding_table.begin(); ttables_it != encoding_table.end(); ++ttables_it) {
- for (tables_it = ttables_it->second.begin(); tables_it != ttables_it->second.end(); ++tables_it) {
- for (tables_it_ = tables_it->second.begin(); tables_it_ != tables_it->second.end(); ++tables_it_) {
- for (tables_it__ = tables_it_->second.begin(); tables_it__ != tables_it_->second.end(); ++tables_it__) {
- for (table_it = tables_it__->second.begin(); table_it != tables_it__->second.end(); ++table_it) {
- if (table_it->second) {
- if (*(table_it->second)) {
- delete *(table_it->second);
- }
- delete table_it->second;
- }
- }
+ for (ttables_it = encoding_table.begin(); ttables_it != encoding_table.end(); ++ttables_it) {
+ for (tables_it = ttables_it->second.begin(); tables_it != ttables_it->second.end(); ++tables_it) {
+ for (tables_it_ = tables_it->second.begin(); tables_it_ != tables_it->second.end(); ++tables_it_) {
+ for (tables_it__ = tables_it_->second.begin(); tables_it__ != tables_it_->second.end(); ++tables_it__) {
+ for (table_it = tables_it__->second.begin(); table_it != tables_it__->second.end(); ++table_it) {
+ if (table_it->second) {
+ if (*(table_it->second)) {
+ delete *(table_it->second);
+ }
+ delete table_it->second;
+ }
+ }
+ }
}
}
}
}
+
+ {
+ std::map<int, lru_map_t*>::const_iterator lru_map_it;
+ std::map<int, lru_list_t*>::const_iterator lru_list_it;
+
+ for (lru_map_it = decoding_tables.begin();
+ lru_map_it != decoding_tables.end();
+ ++lru_map_it) {
+ if (lru_map_it->second) {
+ delete lru_map_it->second;
+ }
+ }
+
+ for (lru_list_it = decoding_tables_lru.begin();
+ lru_list_it != decoding_tables_lru.end();
+ ++lru_list_it) {
+ if (lru_list_it->second) {
+ delete lru_list_it->second;
+ }
+ }
+ }
+}
+
+ErasureCodeShecTableCache::lru_map_t*
+ErasureCodeShecTableCache::getDecodingTables(int technique) {
+ // the caller must hold the guard mutex:
+ // => Mutex::Locker lock(codec_tables_guard);
+
+ // create an lru_map if not yet allocated
+ if (!decoding_tables[technique]) {
+ decoding_tables[technique] = new lru_map_t;
+ }
+ return decoding_tables[technique];
+}
+
+ErasureCodeShecTableCache::lru_list_t*
+ErasureCodeShecTableCache::getDecodingTablesLru(int technique) {
+ // the caller must hold the guard mutex:
+ // => Mutex::Locker lock(codec_tables_guard);
+
+ // create an lru_list if not yet allocated
+ if (!decoding_tables_lru[technique]) {
+ decoding_tables_lru[technique] = new lru_list_t;
+ }
+ return decoding_tables_lru[technique];
}
int**
{
return &codec_tables_guard;
}
+
+uint64_t
+ErasureCodeShecTableCache::getDecodingCacheSignature(int k, int m, int c, int w,
+ int *erased, int *avails) {
+ uint64_t signature = 0;
+ signature = (uint64_t)k;
+ signature |= ((uint64_t)m << 6);
+ signature |= ((uint64_t)c << 12);
+ signature |= ((uint64_t)w << 18);
+
+ for (int i=0; i < k+m; i++) {
+ signature |= ((uint64_t)(avails[i] ? 1 : 0) << (24+i));
+ }
+ for (int i=0; i < k+m; i++) {
+ signature |= ((uint64_t)(erased[i] ? 1 : 0) << (44+i));
+ }
+ return signature;
+}
+
+bool
+ErasureCodeShecTableCache::getDecodingTableFromCache(int* decoding_matrix,
+ int* dm_row,
+ int* dm_column,
+ int* minimum,
+ int technique,
+ int k,
+ int m,
+ int c,
+ int w,
+ int* erased,
+ int* avails) {
+ // --------------------------------------------------------------------------
+ // LRU decoding matrix cache
+ // --------------------------------------------------------------------------
+
+ uint64_t signature = getDecodingCacheSignature(k, m, c, w, erased, avails);
+ Mutex::Locker lock(codec_tables_guard);
+
+ dout(20) << "[ get table ] = " << signature << dendl;
+
+ // we try to fetch a decoding table from an LRU cache
+ lru_map_t* decode_tbls_map =
+ getDecodingTables(technique);
+
+ lru_list_t* decode_tbls_lru =
+ getDecodingTablesLru(technique);
+
+ lru_map_t::iterator decode_tbls_map_it = decode_tbls_map->find(signature);
+ if (decode_tbls_map_it == decode_tbls_map->end()) {
+ return false;
+ }
+
+ dout(20) << "[ cached table ] = " << signature << dendl;
+ // copy parameters out of the cache
+
+ memcpy(decoding_matrix,
+ decode_tbls_map_it->second.second.decoding_matrix,
+ k * k * sizeof(int));
+ memcpy(dm_row,
+ decode_tbls_map_it->second.second.dm_row,
+ k * sizeof(int));
+ memcpy(dm_column,
+ decode_tbls_map_it->second.second.dm_column,
+ k * sizeof(int));
+ memcpy(minimum,
+ decode_tbls_map_it->second.second.minimum,
+ (k+m) * sizeof(int));
+
+ // find item in LRU queue and push back
+ decode_tbls_lru->splice(decode_tbls_lru->end(),
+ *decode_tbls_lru,
+ decode_tbls_map_it->second.first);
+ return true;
+}
+
+void
+ErasureCodeShecTableCache::putDecodingTableToCache(int* decoding_matrix,
+ int* dm_row,
+ int* dm_column,
+ int* minimum,
+ int technique,
+ int k,
+ int m,
+ int c,
+ int w,
+ int* erased,
+ int* avails) {
+ // --------------------------------------------------------------------------
+ // LRU decoding matrix cache
+ // --------------------------------------------------------------------------
+
+ Mutex::Locker lock(codec_tables_guard);
+
+ uint64_t signature = getDecodingCacheSignature(k, m, c, w, erased, avails);
+ dout(20) << "[ put table ] = " << signature << dendl;
+
+ // we store a new table to the cache
+
+ // bufferptr cachetable;
+
+ lru_map_t* decode_tbls_map =
+ getDecodingTables(technique);
+
+ lru_list_t* decode_tbls_lru =
+ getDecodingTablesLru(technique);
+
+ if (decode_tbls_map->count(signature)) {
+ dout(20) << "[ already on table ] = " << signature << dendl;
+
+ // find item in LRU queue and push back
+ decode_tbls_lru->splice(decode_tbls_lru->end(),
+ *decode_tbls_lru,
+ (*decode_tbls_map)[signature].first);
+ return;
+ }
+
+ // evt. shrink the LRU queue/map
+ if ((int)decode_tbls_lru->size() >=
+ ErasureCodeShecTableCache::decoding_tables_lru_length) {
+ dout(20) << "[ shrink lru ] = " << signature << dendl;
+ // remove from map
+ decode_tbls_map->erase(decode_tbls_lru->front());
+ // remove from lru
+ decode_tbls_lru->pop_front();
+ }
+
+ {
+ dout(20) << "[ store table ] = " << signature << dendl;
+
+ decode_tbls_lru->push_back(signature);
+
+ // allocate a new buffer
+ lru_list_t::iterator it_end = decode_tbls_lru->end();
+ it_end--;
+
+ lru_entry_t &map_value =
+ (*decode_tbls_map)[signature] =
+ std::make_pair(it_end, DecodingCacheParameter());
+ map_value.second.decoding_matrix = new int[k*k];
+ map_value.second.dm_row = new int[k];
+ map_value.second.dm_column = new int[k];
+ map_value.second.minimum = new int[k+m];
+
+ memcpy(map_value.second.decoding_matrix,
+ decoding_matrix,
+ k * k * sizeof(int));
+ memcpy(map_value.second.dm_row,
+ dm_row,
+ k * sizeof(int));
+ memcpy(map_value.second.dm_column,
+ dm_column,
+ k * sizeof(int));
+ memcpy(map_value.second.minimum,
+ minimum,
+ (k+m) * sizeof(int));
+
+ dout(20) << "[ cache size ] = " << decode_tbls_lru->size() << dendl;
+ }
+}
// ---------------------------------------------------------------------------
// This class implements a table cache for encoding and decoding matrices.
// Encoding matrices are shared for the same (k,m,c,w) combination.
+ // It supplies a decoding matrix lru cache which is shared for identical
+ // matrix types e.g. there is one cache (lru-list + lru-map)
// ---------------------------------------------------------------------------
+ class DecodingCacheParameter {
+ public:
+ int* decoding_matrix; // size: k*k
+ int* dm_row; // size: k
+ int* dm_column; // size: k
+ int* minimum; // size: k+m
+ DecodingCacheParameter() {
+ decoding_matrix = 0;
+ dm_row = 0;
+ dm_column = 0;
+ minimum = 0;
+ }
+ ~DecodingCacheParameter() {
+ if (decoding_matrix) {
+ delete[] decoding_matrix;
+ }
+ if (dm_row) {
+ delete[] dm_row;
+ }
+ if (dm_column) {
+ delete[] dm_column;
+ }
+ if (minimum) {
+ delete[] minimum;
+ }
+ }
+ };
+
public:
- typedef std::pair<std::list<std::string>::iterator, bufferptr> lru_entry_t;
+ static const int decoding_tables_lru_length = 10000;
+ typedef std::pair<std::list<uint64_t>::iterator,
+ DecodingCacheParameter> lru_entry_t;
typedef std::map< int, int** > codec_table_t;
typedef std::map< int, codec_table_t > codec_tables_t__;
typedef std::map< int, codec_tables_t__ > codec_tables_t_;
typedef std::map< int, codec_tables_t > codec_technique_tables_t;
// int** matrix = codec_technique_tables_t[technique][k][m][c][w]
+ typedef std::map< uint64_t, lru_entry_t > lru_map_t;
+ typedef std::list< uint64_t > lru_list_t;
+
ErasureCodeShecTableCache() :
codec_tables_guard("shec-lru-cache")
{
Mutex codec_tables_guard; // mutex used to protect modifications in encoding/decoding table maps
+ bool getDecodingTableFromCache(int* matrix,
+ int* dm_row, int* dm_column,
+ int* minimum,
+ int technique,
+ int k, int m, int c, int w,
+ int* want, int* avails);
+
+ void putDecodingTableToCache(int* matrix,
+ int* dm_row, int* dm_column,
+ int* minimum,
+ int technique,
+ int k, int m, int c, int w,
+ int* want, int* avails);
+
int** getEncodingTable(int technique, int k, int m, int c, int w);
int** getEncodingTableNoLock(int technique, int k, int m, int c, int w);
int* setEncodingTable(int technique, int k, int m, int c, int w, int*);
private:
- codec_technique_tables_t encoding_table; // encoding coefficients accessed via table[technique][k][m]
-
+ // encoding table accessed via table[matrix][k][m][c][w]
+ // decoding table cache accessed via map[matrixtype]
+ // decoding table lru list accessed via list[matrixtype]
+ codec_technique_tables_t encoding_table;
+ std::map<int, lru_map_t*> decoding_tables;
+ std::map<int, lru_list_t*> decoding_tables_lru;
+
+ lru_map_t* getDecodingTables(int technique);
+ lru_list_t* getDecodingTablesLru(int technique);
+ uint64_t getDecodingCacheSignature(int k, int m, int c, int w,
+ int *want, int *avails);
+
Mutex* getLock();
-
};
#endif