]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/librados_test_stub/TestClassHandler.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / test / librados_test_stub / TestClassHandler.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
4#include "test/librados_test_stub/TestClassHandler.h"
5#include "test/librados_test_stub/TestIoCtxImpl.h"
6#include <boost/algorithm/string/predicate.hpp>
7#include <dlfcn.h>
8#include <errno.h>
9#include <stdlib.h>
10#include <string.h>
11#include "common/debug.h"
11fdf7f2 12#include "include/ceph_assert.h"
7c673cae
FG
13
14#define dout_context g_ceph_context
15#define dout_subsys ceph_subsys_rados
16
17namespace librados {
18
19TestClassHandler::TestClassHandler() {
20}
21
22TestClassHandler::~TestClassHandler() {
23 for (ClassHandles::iterator it = m_class_handles.begin();
24 it != m_class_handles.end(); ++it) {
25 dlclose(*it);
26 }
27}
28
29void TestClassHandler::open_class(const std::string& name,
30 const std::string& path) {
31 void *handle = dlopen(path.c_str(), RTLD_NOW);
32 if (handle == NULL) {
11fdf7f2
TL
33 std::cerr << "Failed to load class: " << name << " (" << path << "): "
34 << dlerror() << std::endl;
7c673cae
FG
35 return;
36 }
11fdf7f2
TL
37
38 // clear any existing error
39 dlerror();
7c673cae
FG
40
41 // initialize
42 void (*cls_init)() = reinterpret_cast<void (*)()>(
11fdf7f2
TL
43 dlsym(handle, "__cls_init"));
44
45 char* error = nullptr;
46 if ((error = dlerror()) != nullptr) {
47 std::cerr << "Error locating initializer: " << error << std::endl;
48 } else if (cls_init) {
49 m_class_handles.push_back(handle);
7c673cae 50 cls_init();
11fdf7f2 51 return;
7c673cae 52 }
11fdf7f2
TL
53
54 std::cerr << "Class: " << name << " (" << path << ") missing initializer"
55 << std::endl;
56 dlclose(handle);
7c673cae
FG
57}
58
59void TestClassHandler::open_all_classes() {
11fdf7f2 60 ceph_assert(m_class_handles.empty());
7c673cae
FG
61
62 const char* env = getenv("CEPH_LIB");
11fdf7f2 63 std::string CEPH_LIB(env ? env : "lib");
7c673cae
FG
64 DIR *dir = ::opendir(CEPH_LIB.c_str());
65 if (dir == NULL) {
11fdf7f2 66 ceph_abort();;
7c673cae
FG
67 }
68
11fdf7f2 69 std::set<std::string> names;
7c673cae
FG
70 struct dirent *pde = nullptr;
71 while ((pde = ::readdir(dir))) {
72 std::string name(pde->d_name);
73 if (!boost::algorithm::starts_with(name, "libcls_") ||
74 !boost::algorithm::ends_with(name, ".so")) {
75 continue;
76 }
11fdf7f2
TL
77 names.insert(name);
78 }
79
80 for (auto& name : names) {
7c673cae
FG
81 std::string class_name = name.substr(7, name.size() - 10);
82 open_class(class_name, CEPH_LIB + "/" + name);
83 }
84 closedir(dir);
85}
86
87int TestClassHandler::create(const std::string &name, cls_handle_t *handle) {
88 if (m_classes.find(name) != m_classes.end()) {
11fdf7f2 89 std::cerr << "Class " << name << " already exists" << std::endl;
7c673cae
FG
90 return -EEXIST;
91 }
92
93 SharedClass cls(new Class());
94 m_classes[name] = cls;
95 *handle = reinterpret_cast<cls_handle_t>(cls.get());
96 return 0;
97}
98
99int TestClassHandler::create_method(cls_handle_t hclass,
100 const char *name,
101 cls_method_cxx_call_t class_call,
102 cls_method_handle_t *handle) {
103 Class *cls = reinterpret_cast<Class*>(hclass);
104 if (cls->methods.find(name) != cls->methods.end()) {
11fdf7f2
TL
105 std::cerr << "Class method " << hclass << ":" << name << " already exists"
106 << std::endl;
7c673cae
FG
107 return -EEXIST;
108 }
109
110 SharedMethod method(new Method());
111 method->class_call = class_call;
112 cls->methods[name] = method;
113 return 0;
114}
115
116cls_method_cxx_call_t TestClassHandler::get_method(const std::string &cls,
117 const std::string &method) {
118 Classes::iterator c_it = m_classes.find(cls);
119 if (c_it == m_classes.end()) {
11fdf7f2 120 std::cerr << "Failed to located class " << cls << std::endl;
7c673cae
FG
121 return NULL;
122 }
123
124 SharedClass scls = c_it->second;
125 Methods::iterator m_it = scls->methods.find(method);
126 if (m_it == scls->methods.end()) {
11fdf7f2
TL
127 std::cerr << "Failed to located class method" << cls << "." << method
128 << std::endl;
7c673cae
FG
129 return NULL;
130 }
131 return m_it->second->class_call;
132}
133
134TestClassHandler::SharedMethodContext TestClassHandler::get_method_context(
135 TestIoCtxImpl *io_ctx_impl, const std::string &oid,
136 const SnapContext &snapc) {
137 SharedMethodContext ctx(new MethodContext());
138
139 // clone to ioctx to provide a firewall for gmock expectations
140 ctx->io_ctx_impl = io_ctx_impl->clone();
141 ctx->oid = oid;
142 ctx->snapc = snapc;
143 return ctx;
144}
145
146int TestClassHandler::create_filter(cls_handle_t hclass,
147 const std::string& name,
148 cls_cxx_filter_factory_t fn)
149{
150 Class *cls = reinterpret_cast<Class*>(hclass);
151 if (cls->filters.find(name) != cls->filters.end()) {
152 return -EEXIST;
153 }
154 cls->filters[name] = fn;
155 return 0;
156}
157
158TestClassHandler::MethodContext::~MethodContext() {
159 io_ctx_impl->put();
160}
161
162} // namespace librados