summaryrefslogtreecommitdiffstats
path: root/src/erasure-code/shec/ErasureCodeShecTableCache.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/erasure-code/shec/ErasureCodeShecTableCache.cc')
-rw-r--r--src/erasure-code/shec/ErasureCodeShecTableCache.cc318
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;
+ }
+}