X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Ferasure-code%2Fisa%2FErasureCodeIsaTableCache.cc;fp=src%2Fceph%2Fsrc%2Ferasure-code%2Fisa%2FErasureCodeIsaTableCache.cc;h=a4d20a6fb17a571e84b9c549a0e9ab25b35c4977;hb=812ff6ca9fcd3e629e49d4328905f33eee8ca3f5;hp=0000000000000000000000000000000000000000;hpb=15280273faafb77777eab341909a3f495cf248d9;p=stor4nfv.git diff --git a/src/ceph/src/erasure-code/isa/ErasureCodeIsaTableCache.cc b/src/ceph/src/erasure-code/isa/ErasureCodeIsaTableCache.cc new file mode 100644 index 0000000..a4d20a6 --- /dev/null +++ b/src/ceph/src/erasure-code/isa/ErasureCodeIsaTableCache.cc @@ -0,0 +1,327 @@ +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2014 CERN (Switzerland) + * + * Author: Andreas-Joachim Peters + * + * 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. + * + */ + + +/** + * @file ErasureCodeIsaTableCache.cc + * + * @brief Erasure Code Isa CODEC Table Cache + * + * The INTEL ISA-L library supports two pre-defined encoding matrices (cauchy = default, reed_sol_van = default) + * The default CODEC implementation using these two matrices is implemented in class ErasureCodeIsaDefault. + * ISA-L allows to use custom matrices which might be added later as implementations deriving from the base class ErasoreCodeIsa. + */ + +// ----------------------------------------------------------------------------- +#include "ErasureCodeIsaTableCache.h" +#include "common/debug.h" +// ----------------------------------------------------------------------------- + +// ----------------------------------------------------------------------------- +#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 << "ErasureCodeIsaTableCache: "; +} + +// ----------------------------------------------------------------------------- + +ErasureCodeIsaTableCache::~ErasureCodeIsaTableCache() +{ + Mutex::Locker lock(codec_tables_guard); + + codec_technique_tables_t::const_iterator ttables_it; + codec_tables_t::const_iterator tables_it; + codec_table_t::const_iterator table_it; + + std::map::const_iterator lru_map_it; + std::map::const_iterator lru_list_it; + + // clean-up all allocated tables + for (ttables_it = encoding_coefficient.begin(); ttables_it != encoding_coefficient.end(); ++ttables_it) { + for (tables_it = ttables_it->second.begin(); tables_it != ttables_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 (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 (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; + } + } +} + +// ----------------------------------------------------------------------------- + +int +ErasureCodeIsaTableCache::getDecodingTableCacheSize(int matrixtype) +{ + Mutex::Locker lock(codec_tables_guard); + if (decoding_tables[matrixtype]) + return decoding_tables[matrixtype]->size(); + else + return -1; +} + +// ----------------------------------------------------------------------------- + +ErasureCodeIsaTableCache::lru_map_t* +ErasureCodeIsaTableCache::getDecodingTables(int matrix_type) +{ + // the caller must hold the guard mutex: + // => Mutex::Locker lock(codec_tables_guard); + + // create an lru_map if not yet allocated + if (!decoding_tables[matrix_type]) { + decoding_tables[matrix_type] = new lru_map_t; + } + return decoding_tables[matrix_type]; +} + +// ----------------------------------------------------------------------------- + +ErasureCodeIsaTableCache::lru_list_t* +ErasureCodeIsaTableCache::getDecodingTablesLru(int matrix_type) +{ + // 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[matrix_type]) { + decoding_tables_lru[matrix_type] = new lru_list_t; + } + return decoding_tables_lru[matrix_type]; +} + +// ----------------------------------------------------------------------------- + +unsigned char** +ErasureCodeIsaTableCache::getEncodingTable(int matrix, int k, int m) +{ + Mutex::Locker lock(codec_tables_guard); + return getEncodingTableNoLock(matrix,k,m); +} + +// ----------------------------------------------------------------------------- + +unsigned char** +ErasureCodeIsaTableCache::getEncodingTableNoLock(int matrix, int k, int m) +{ + // create a pointer to store an encoding table address + if (!encoding_table[matrix][k][m]) { + encoding_table[matrix][k][m] = new (unsigned char*); + *encoding_table[matrix][k][m] = 0; + } + return encoding_table[matrix][k][m]; +} + +// ----------------------------------------------------------------------------- + +unsigned char** +ErasureCodeIsaTableCache::getEncodingCoefficient(int matrix, int k, int m) +{ + Mutex::Locker lock(codec_tables_guard); + return getEncodingCoefficientNoLock(matrix,k,m); +} + +// ----------------------------------------------------------------------------- + +unsigned char** +ErasureCodeIsaTableCache::getEncodingCoefficientNoLock(int matrix, int k, int m) +{ + // create a pointer to store an encoding coefficients adddress + if (!encoding_coefficient[matrix][k][m]) { + encoding_coefficient[matrix][k][m] = new (unsigned char*); + *encoding_coefficient[matrix][k][m] = 0; + } + return encoding_coefficient[matrix][k][m]; +} + +// ----------------------------------------------------------------------------- + +unsigned char* +ErasureCodeIsaTableCache::setEncodingTable(int matrix, int k, int m, unsigned char* ec_in_table) +{ + Mutex::Locker lock(codec_tables_guard); + unsigned char** ec_out_table = getEncodingTableNoLock(matrix, k, m); + 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[matrix][k][m] = ec_in_table; + return ec_in_table; + } +} + +// ----------------------------------------------------------------------------- + +unsigned char* +ErasureCodeIsaTableCache::setEncodingCoefficient(int matrix, int k, int m, unsigned char* ec_in_coeff) +{ + Mutex::Locker lock(codec_tables_guard); + unsigned char** ec_out_coeff = getEncodingCoefficientNoLock(matrix, k, m); + if (*ec_out_coeff) { + // somebody might have deposited these coefficients in the meanwhile, so clean + // the input coefficients and return the stored ones + free (ec_in_coeff); + return *ec_out_coeff; + } else { + // we store the provided input coefficients and return these + *encoding_coefficient[matrix][k][m] = ec_in_coeff; + return ec_in_coeff; + } +} + +// ----------------------------------------------------------------------------- + +Mutex* +ErasureCodeIsaTableCache::getLock() +{ + return &codec_tables_guard; +} + +// ----------------------------------------------------------------------------- + +bool +ErasureCodeIsaTableCache::getDecodingTableFromCache(std::string &signature, + unsigned char* &table, + int matrixtype, + int k, + int m) +{ + // -------------------------------------------------------------------------- + // LRU decoding matrix cache + // -------------------------------------------------------------------------- + + dout(12) << "[ get table ] = " << signature << dendl; + + // we try to fetch a decoding table from an LRU cache + bool found = false; + + Mutex::Locker lock(codec_tables_guard); + + lru_map_t* decode_tbls_map = + getDecodingTables(matrixtype); + + lru_list_t* decode_tbls_lru = + getDecodingTablesLru(matrixtype); + + if (decode_tbls_map->count(signature)) { + dout(12) << "[ cached table ] = " << signature << dendl; + // copy the table out of the cache + memcpy(table, (*decode_tbls_map)[signature].second.c_str(), k * (m + k)*32); + // find item in LRU queue and push back + dout(12) << "[ cache size ] = " << decode_tbls_lru->size() << dendl; + decode_tbls_lru->splice( (decode_tbls_lru->begin()), *decode_tbls_lru, (*decode_tbls_map)[signature].first); + found = true; + } + + return found; +} + +// ----------------------------------------------------------------------------- + +void +ErasureCodeIsaTableCache::putDecodingTableToCache(std::string &signature, + unsigned char* &table, + int matrixtype, + int k, + int m) +{ + // -------------------------------------------------------------------------- + // LRU decoding matrix cache + // -------------------------------------------------------------------------- + + dout(12) << "[ put table ] = " << signature << dendl; + + // we store a new table to the cache + + bufferptr cachetable; + + Mutex::Locker lock(codec_tables_guard); + + lru_map_t* decode_tbls_map = + getDecodingTables(matrixtype); + + lru_list_t* decode_tbls_lru = + getDecodingTablesLru(matrixtype); + + // evt. shrink the LRU queue/map + if ((int) decode_tbls_lru->size() >= ErasureCodeIsaTableCache::decoding_tables_lru_length) { + dout(12) << "[ shrink lru ] = " << signature << dendl; + // reuse old buffer + cachetable = (*decode_tbls_map)[decode_tbls_lru->back()].second; + + if ((int) cachetable.length() != (k * (m + k)*32)) { + // we need to replace this with a different size buffer + cachetable = buffer::create(k * (m + k)*32); + } + + // remove from map + decode_tbls_map->erase(decode_tbls_lru->back()); + // remove from lru + decode_tbls_lru->pop_back(); + // add to the head of lru + decode_tbls_lru->push_front(signature); + // add the new to the map + (*decode_tbls_map)[signature] = std::make_pair(decode_tbls_lru->begin(), cachetable); + } else { + dout(12) << "[ store table ] = " << signature << dendl; + // allocate a new buffer + cachetable = buffer::create(k * (m + k)*32); + decode_tbls_lru->push_front(signature); + (*decode_tbls_map)[signature] = std::make_pair(decode_tbls_lru->begin(), cachetable); + dout(12) << "[ cache size ] = " << decode_tbls_lru->size() << dendl; + } + + // copy-in the new table + memcpy(cachetable.c_str(), table, k * (m + k)*32); +}