initial code repo
[stor4nfv.git] / src / ceph / src / erasure-code / shec / ErasureCodeShecTableCache.cc
diff --git a/src/ceph/src/erasure-code/shec/ErasureCodeShecTableCache.cc b/src/ceph/src/erasure-code/shec/ErasureCodeShecTableCache.cc
new file mode 100644 (file)
index 0000000..891cada
--- /dev/null
@@ -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()
+{
+  Mutex::Locker 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:
+  // => 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**
+ErasureCodeShecTableCache::getEncodingTable(int technique, int k, int m, int c, int w)
+{
+  Mutex::Locker 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)
+{
+  Mutex::Locker 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;
+  }
+}
+
+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);
+  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;
+  }
+}