diff options
Diffstat (limited to 'src/erasure-code/shec/ErasureCodeShecTableCache.cc')
-rw-r--r-- | src/erasure-code/shec/ErasureCodeShecTableCache.cc | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/src/erasure-code/shec/ErasureCodeShecTableCache.cc b/src/erasure-code/shec/ErasureCodeShecTableCache.cc new file mode 100644 index 000000000..2f9a60b62 --- /dev/null +++ b/src/erasure-code/shec/ErasureCodeShecTableCache.cc @@ -0,0 +1,318 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2014 FUJITSU LIMITED + * Copyright (C) 2014 CERN (Switzerland) + * + * Author: Takanori Nakao <nakao.takanori@jp.fujitsu.com> + * Author: Takeshi Miyamae <miyamae.takeshi@jp.fujitsu.com> + * Author: Andreas-Joachim Peters <Andreas.Joachim.Peters@cern.ch> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + */ + +// ----------------------------------------------------------------------------- +#include "ErasureCodeShecTableCache.h" +#include "common/debug.h" +// ----------------------------------------------------------------------------- +using namespace std; + +// ----------------------------------------------------------------------------- +#define dout_context g_ceph_context +#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() +{ + std::lock_guard lock{codec_tables_guard}; + + // 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; + } + } + } + } + } + } + } + + { + 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: + // => std::lock_guard 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: + // => std::lock_guard 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** +ErasureCodeShecTableCache::getEncodingTable(int technique, int k, int m, int c, int w) +{ + std::lock_guard lock{codec_tables_guard}; + return getEncodingTableNoLock(technique,k,m,c,w); +} + +// ----------------------------------------------------------------------------- + +int** +ErasureCodeShecTableCache::getEncodingTableNoLock(int technique, int k, int m, int c, int w) +{ + // create a pointer to store an encoding table address + if (!encoding_table[technique][k][m][c][w]) { + encoding_table[technique][k][m][c][w] = new (int*); + *encoding_table[technique][k][m][c][w] = 0; + } + return encoding_table[technique][k][m][c][w]; +} + +int* +ErasureCodeShecTableCache::setEncodingTable(int technique, int k, int m, int c, int w, int* ec_in_table) +{ + std::lock_guard lock{codec_tables_guard}; + int** ec_out_table = getEncodingTableNoLock(technique, k, m, c, w); + if (*ec_out_table) { + // somebody might have deposited this table in the meanwhile, so clean + // the input table and return the stored one + free (ec_in_table); + return *ec_out_table; + } else { + // we store the provided input table and return this one + *encoding_table[technique][k][m][c][w] = ec_in_table; + return ec_in_table; + } +} + +ceph::mutex* +ErasureCodeShecTableCache::getLock() +{ + 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); + std::lock_guard 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 + // -------------------------------------------------------------------------- + + std::lock_guard 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; + } +} |