summaryrefslogtreecommitdiffstats
path: root/src/erasure-code/isa/ErasureCodeIsaTableCache.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/erasure-code/isa/ErasureCodeIsaTableCache.cc')
-rw-r--r--src/erasure-code/isa/ErasureCodeIsaTableCache.cc327
1 files changed, 327 insertions, 0 deletions
diff --git a/src/erasure-code/isa/ErasureCodeIsaTableCache.cc b/src/erasure-code/isa/ErasureCodeIsaTableCache.cc
new file mode 100644
index 000000000..8a3318aa1
--- /dev/null
+++ b/src/erasure-code/isa/ErasureCodeIsaTableCache.cc
@@ -0,0 +1,327 @@
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2014 CERN (Switzerland)
+ *
+ * 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.
+ *
+ */
+
+
+/**
+ * @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 std::ostream&
+_tc_prefix(std::ostream* _dout)
+{
+ return *_dout << "ErasureCodeIsaTableCache: ";
+}
+
+// -----------------------------------------------------------------------------
+
+ErasureCodeIsaTableCache::~ErasureCodeIsaTableCache()
+{
+ std::lock_guard 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<int, lru_map_t*>::const_iterator lru_map_it;
+ std::map<int, lru_list_t*>::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)
+{
+ std::lock_guard 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:
+ // => std::lock_guard 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:
+ // => std::lock_guard 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)
+{
+ std::lock_guard 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)
+{
+ std::lock_guard 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 address
+ 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)
+{
+ std::lock_guard 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)
+{
+ std::lock_guard 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;
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+ceph::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;
+
+ std::lock_guard 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
+
+ ceph::buffer::ptr cachetable;
+
+ std::lock_guard 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 = ceph::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 = ceph::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);
+}