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