#include "ErasureCodePlugin.h"
#include "common/errno.h"
#include "include/str_list.h"
+#include "include/ceph_assert.h"
using namespace std;
#define PLUGIN_INIT_FUNCTION "__erasure_code_init"
#define PLUGIN_VERSION_FUNCTION "__erasure_code_version"
+namespace ceph {
+
ErasureCodePluginRegistry ErasureCodePluginRegistry::singleton;
-ErasureCodePluginRegistry::ErasureCodePluginRegistry() :
- lock("ErasureCodePluginRegistry::lock"),
- loading(false),
- disable_dlclose(false)
-{
-}
+ErasureCodePluginRegistry::ErasureCodePluginRegistry() = default;
ErasureCodePluginRegistry::~ErasureCodePluginRegistry()
{
int ErasureCodePluginRegistry::remove(const std::string &name)
{
- ceph_assert(lock.is_locked());
+ ceph_assert(ceph_mutex_is_locked(lock));
if (plugins.find(name) == plugins.end())
return -ENOENT;
std::map<std::string,ErasureCodePlugin*>::iterator plugin = plugins.find(name);
int ErasureCodePluginRegistry::add(const std::string &name,
ErasureCodePlugin* plugin)
{
- ceph_assert(lock.is_locked());
+ ceph_assert(ceph_mutex_is_locked(lock));
if (plugins.find(name) != plugins.end())
return -EEXIST;
plugins[name] = plugin;
ErasureCodePlugin *ErasureCodePluginRegistry::get(const std::string &name)
{
- ceph_assert(lock.is_locked());
+ ceph_assert(ceph_mutex_is_locked(lock));
if (plugins.find(name) != plugins.end())
return plugins[name];
else
{
ErasureCodePlugin *plugin;
{
- Mutex::Locker l(lock);
+ std::lock_guard l{lock};
plugin = get(plugin_name);
if (plugin == 0) {
loading = true;
ErasureCodePlugin **plugin,
ostream *ss)
{
- ceph_assert(lock.is_locked());
+ ceph_assert(ceph_mutex_is_locked(lock));
std::string fname = directory + "/" PLUGIN_PREFIX
+ plugin_name + PLUGIN_SUFFIX;
void *library = dlopen(fname.c_str(), RTLD_NOW);
const std::string &directory,
ostream *ss)
{
- Mutex::Locker l(lock);
+ std::lock_guard l{lock};
list<string> plugins_list;
get_str_list(plugins, plugins_list);
for (list<string>::iterator i = plugins_list.begin();
}
return 0;
}
+}
#ifndef CEPH_ERASURE_CODE_PLUGIN_H
#define CEPH_ERASURE_CODE_PLUGIN_H
-#include "common/Mutex.h"
+#include "common/ceph_mutex.h"
#include "ErasureCodeInterface.h"
extern "C" {
class ErasureCodePluginRegistry {
public:
- Mutex lock;
- bool loading;
- bool disable_dlclose;
+ ceph::mutex lock = ceph::make_mutex("ErasureCodePluginRegistry::lock");
+ bool loading = false;
+ bool disable_dlclose = false;
std::map<std::string,ErasureCodePlugin*> plugins;
static ErasureCodePluginRegistry singleton;
ErasureCodeIsaTableCache::~ErasureCodeIsaTableCache()
{
- Mutex::Locker lock(codec_tables_guard);
+ std::lock_guard lock{codec_tables_guard};
codec_technique_tables_t::const_iterator ttables_it;
codec_tables_t::const_iterator tables_it;
int
ErasureCodeIsaTableCache::getDecodingTableCacheSize(int matrixtype)
{
- Mutex::Locker lock(codec_tables_guard);
+ std::lock_guard lock{codec_tables_guard};
if (decoding_tables[matrixtype])
return decoding_tables[matrixtype]->size();
else
ErasureCodeIsaTableCache::getDecodingTables(int matrix_type)
{
// the caller must hold the guard mutex:
- // => Mutex::Locker lock(codec_tables_guard);
+ // => std::lock_guard lock{codec_tables_guard};
// create an lru_map if not yet allocated
if (!decoding_tables[matrix_type]) {
ErasureCodeIsaTableCache::getDecodingTablesLru(int matrix_type)
{
// the caller must hold the guard mutex:
- // => Mutex::Locker lock(codec_tables_guard);
+ // => std::lock_guard lock{codec_tables_guard};
// create an lru_list if not yet allocated
if (!decoding_tables_lru[matrix_type]) {
unsigned char**
ErasureCodeIsaTableCache::getEncodingTable(int matrix, int k, int m)
{
- Mutex::Locker lock(codec_tables_guard);
+ std::lock_guard lock{codec_tables_guard};
return getEncodingTableNoLock(matrix,k,m);
}
unsigned char**
ErasureCodeIsaTableCache::getEncodingCoefficient(int matrix, int k, int m)
{
- Mutex::Locker lock(codec_tables_guard);
+ std::lock_guard lock{codec_tables_guard};
return getEncodingCoefficientNoLock(matrix,k,m);
}
unsigned char*
ErasureCodeIsaTableCache::setEncodingTable(int matrix, int k, int m, unsigned char* ec_in_table)
{
- Mutex::Locker lock(codec_tables_guard);
+ 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
unsigned char*
ErasureCodeIsaTableCache::setEncodingCoefficient(int matrix, int k, int m, unsigned char* ec_in_coeff)
{
- Mutex::Locker lock(codec_tables_guard);
+ 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
// -----------------------------------------------------------------------------
-Mutex*
+ceph::mutex*
ErasureCodeIsaTableCache::getLock()
{
return &codec_tables_guard;
// we try to fetch a decoding table from an LRU cache
bool found = false;
- Mutex::Locker lock(codec_tables_guard);
+ std::lock_guard lock{codec_tables_guard};
lru_map_t* decode_tbls_map =
getDecodingTables(matrixtype);
ceph::buffer::ptr cachetable;
- Mutex::Locker lock(codec_tables_guard);
+ std::lock_guard lock{codec_tables_guard};
lru_map_t* decode_tbls_map =
getDecodingTables(matrixtype);
#define CEPH_ERASURE_CODE_ISA_TABLE_CACHE_H
// -----------------------------------------------------------------------------
-#include "common/Mutex.h"
+#include "common/ceph_mutex.h"
#include "erasure-code/ErasureCodeInterface.h"
// -----------------------------------------------------------------------------
#include <list>
typedef std::map< std::string, lru_entry_t > lru_map_t;
typedef std::list< std::string > lru_list_t;
- ErasureCodeIsaTableCache() :
- codec_tables_guard("isa-lru-cache")
- {
- }
+ ErasureCodeIsaTableCache() = default;
virtual ~ErasureCodeIsaTableCache();
- Mutex codec_tables_guard; // mutex used to protect modifications in encoding/decoding table maps
+ // mutex used to protect modifications in encoding/decoding table maps
+ ceph::mutex codec_tables_guard = ceph::make_mutex("isa-lru-cache");
bool getDecodingTableFromCache(std::string &signature,
unsigned char* &table,
lru_list_t* getDecodingTablesLru(int matrix_type);
- Mutex* getLock();
+ ceph::mutex* getLock();
};
ErasureCodeShecTableCache::~ErasureCodeShecTableCache()
{
- Mutex::Locker lock(codec_tables_guard);
+ std::lock_guard lock{codec_tables_guard};
// clean-up all allocated tables
{
ErasureCodeShecTableCache::lru_map_t*
ErasureCodeShecTableCache::getDecodingTables(int technique) {
// the caller must hold the guard mutex:
- // => Mutex::Locker lock(codec_tables_guard);
+ // => std::lock_guard lock{codec_tables_guard};
// create an lru_map if not yet allocated
if (!decoding_tables[technique]) {
ErasureCodeShecTableCache::lru_list_t*
ErasureCodeShecTableCache::getDecodingTablesLru(int technique) {
// the caller must hold the guard mutex:
- // => Mutex::Locker lock(codec_tables_guard);
+ // => std::lock_guard lock{codec_tables_guard};
// create an lru_list if not yet allocated
if (!decoding_tables_lru[technique]) {
int**
ErasureCodeShecTableCache::getEncodingTable(int technique, int k, int m, int c, int w)
{
- Mutex::Locker lock(codec_tables_guard);
+ std::lock_guard lock{codec_tables_guard};
return getEncodingTableNoLock(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);
+ 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
}
}
-Mutex*
+ceph::mutex*
ErasureCodeShecTableCache::getLock()
{
return &codec_tables_guard;
// --------------------------------------------------------------------------
uint64_t signature = getDecodingCacheSignature(k, m, c, w, erased, avails);
- Mutex::Locker lock(codec_tables_guard);
+ std::lock_guard lock{codec_tables_guard};
dout(20) << "[ get table ] = " << signature << dendl;
// LRU decoding matrix cache
// --------------------------------------------------------------------------
- Mutex::Locker lock(codec_tables_guard);
+ std::lock_guard lock{codec_tables_guard};
uint64_t signature = getDecodingCacheSignature(k, m, c, w, erased, avails);
dout(20) << "[ put table ] = " << signature << dendl;
#define CEPH_ERASURE_CODE_SHEC_TABLE_CACHE_H
// -----------------------------------------------------------------------------
-#include "common/Mutex.h"
+#include "common/ceph_mutex.h"
#include "erasure-code/ErasureCodeInterface.h"
// -----------------------------------------------------------------------------
#include <list>
typedef std::map< uint64_t, lru_entry_t > lru_map_t;
typedef std::list< uint64_t > lru_list_t;
- ErasureCodeShecTableCache() :
- codec_tables_guard("shec-lru-cache")
- {
- }
-
+ ErasureCodeShecTableCache() = default;
virtual ~ErasureCodeShecTableCache();
-
- Mutex codec_tables_guard; // mutex used to protect modifications in encoding/decoding table maps
+ // mutex used to protect modifications in encoding/decoding table maps
+ ceph::mutex codec_tables_guard = ceph::make_mutex("shec-lru-cache");
bool getDecodingTableFromCache(int* matrix,
int* dm_row, int* dm_column,
uint64_t getDecodingCacheSignature(int k, int m, int c, int w,
int *want, int *avails);
- Mutex* getLock();
+ ceph::mutex* getLock();
};
#endif
extern "C" int __erasure_code_init(char *plugin_name, char *directory)
{
- sleep(1000);
+ sleep(10);
return 0;
}
#include "gtest/gtest.h"
-class ErasureCodePluginRegistryTest : public ::testing::Test {
-protected:
-
- class Thread_factory : public Thread {
- public:
- static void cleanup(void *arg) {
- ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance();
- if (instance.lock.is_locked())
- instance.lock.Unlock();
- }
-
- void *entry() override {
- ErasureCodeProfile profile;
- ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance();
- ErasureCodeInterfaceRef erasure_code;
- pthread_cleanup_push(cleanup, NULL);
- instance.factory("hangs",
- g_conf().get_val<std::string>("erasure_code_dir"),
- profile, &erasure_code, &cerr);
- pthread_cleanup_pop(0);
- return NULL;
- }
- };
-
-};
+class ErasureCodePluginRegistryTest : public ::testing::Test {};
TEST_F(ErasureCodePluginRegistryTest, factory_mutex) {
ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance();
- EXPECT_TRUE(instance.lock.TryLock());
- instance.lock.Unlock();
-
+ {
+ unique_lock l{instance.lock, std::try_to_lock};
+ EXPECT_TRUE(l.owns_lock());
+ }
//
// Test that the loading of a plugin is protected by a mutex.
- //
- useconds_t delay = 0;
- const useconds_t DELAY_MAX = 20 * 1000 * 1000;
- Thread_factory sleep_forever;
- sleep_forever.create("sleep_forever");
- do {
- cout << "Trying (1) with delay " << delay << "us\n";
- if (delay > 0)
- usleep(delay);
- if (!instance.loading)
- delay = ( delay + 1 ) * 2;
- } while(!instance.loading && delay < DELAY_MAX);
- ASSERT_TRUE(delay < DELAY_MAX);
-
- EXPECT_FALSE(instance.lock.TryLock());
- EXPECT_EQ(0, pthread_cancel(sleep_forever.get_thread_id()));
- EXPECT_EQ(0, sleep_forever.join());
+ std::thread sleep_for_10_secs([] {
+ ErasureCodeProfile profile;
+ ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance();
+ ErasureCodeInterfaceRef erasure_code;
+ instance.factory("hangs",
+ g_conf().get_val<std::string>("erasure_code_dir"),
+ profile, &erasure_code, &cerr);
+ });
+ auto wait_until = [&instance](bool loading, unsigned max_secs) {
+ auto delay = 0ms;
+ const auto DELAY_MAX = std::chrono::seconds(max_secs);
+ for (; delay < DELAY_MAX; delay = (delay + 1ms) * 2) {
+ cout << "Trying (1) with delay " << delay << "us\n";
+ if (delay.count() > 0) {
+ std::this_thread::sleep_for(delay);
+ }
+ if (instance.loading == loading) {
+ return true;
+ }
+ }
+ return false;
+ };
+ // should be loading in 5 seconds
+ ASSERT_TRUE(wait_until(true, 5));
+ {
+ unique_lock l{instance.lock, std::try_to_lock};
+ EXPECT_TRUE(!l.owns_lock());
+ }
+ // should finish loading in 15 seconds
+ ASSERT_TRUE(wait_until(false, 15));
+ {
+ unique_lock l{instance.lock, std::try_to_lock};
+ EXPECT_TRUE(l.owns_lock());
+ }
+ sleep_for_10_secs.join();
}
TEST_F(ErasureCodePluginRegistryTest, all)
EXPECT_TRUE(erasure_code.get());
ErasureCodePlugin *plugin = 0;
{
- Mutex::Locker l(instance.lock);
+ std::lock_guard l{instance.lock};
EXPECT_EQ(-EEXIST, instance.load("example", directory, &plugin, &cerr));
EXPECT_EQ(-ENOENT, instance.remove("does not exist"));
EXPECT_EQ(0, instance.remove("example"));
instance.disable_dlclose = true;
{
- Mutex::Locker l(instance.lock);
+ std::lock_guard l{instance.lock};
__erasure_code_init((char*) "shec", (char*) "");
}
std::cout << "__erasure_code_init finish " << std::endl;
int ErasureCodeCommand::plugin_exists() {
ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance();
ErasureCodePlugin *plugin = 0;
- Mutex::Locker l(instance.lock);
+ std::lock_guard l{instance.lock};
stringstream ss;
int code = instance.load(vm["plugin_exists"].as<string>(),
g_conf().get_val<std::string>("erasure_code_dir"), &plugin, &ss);