Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
libdaos_mock.cxx
Go to the documentation of this file.
1/// \file libdaos_mock.cxx
2/// \ingroup NTuple ROOT7
3/// \author Javier Lopez-Gomez <j.lopez@cern.ch>
4/// \date 2021-01-20
5/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
6/// is welcome!
7
8/*************************************************************************
9 * Copyright (C) 1995-2021, Rene Brun and Fons Rademakers. *
10 * All rights reserved. *
11 * *
12 * For the licensing terms see $ROOTSYS/LICENSE. *
13 * For the list of contributors see $ROOTSYS/README/CREDITS. *
14 *************************************************************************/
15
16#include <ROOT/RLogger.hxx>
17#include <ROOT/RNTupleUtil.hxx>
18#include <ROOT/RStringView.hxx>
19
20#include <daos.h>
21
22#include <array>
23#include <algorithm>
24#include <cstring>
25#include <memory>
26#include <mutex>
27#include <string>
28#include <type_traits>
29#include <unordered_map>
30
31using Uuid_t = std::array<unsigned char, 16>;
32namespace std {
33 // Required by `std::unordered_map<daos_obj_id, ...>`. Based on boost::hash_combine().
34 template <> struct hash<daos_obj_id_t> {
35 std::size_t operator()(const daos_obj_id_t& oid) const {
36 auto seed = std::hash<uint64_t>{}(oid.lo);
37 seed ^= std::hash<uint64_t>{}(oid.hi) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
38 return seed;
39 }
40 };
41
42 // Required by `std::unordered_map<Uuid_t, ...>`; forward to std::hash<std::string_view>{}()
43 template <> struct hash<Uuid_t> {
44 std::size_t operator()(const Uuid_t& u) const {
45 return std::hash<std::string_view>{}
46 (std::string_view(reinterpret_cast<std::string_view::const_pointer>(u.data()), u.size()));
47 }
48 };
49}
50
51inline bool operator==(const daos_obj_id_t& lhs, const daos_obj_id_t& rhs)
52{ return (lhs.lo == rhs.lo) && (lhs.hi == rhs.hi); }
53
54namespace {
55// clang-format off
56/**
57\class RDaosFakeObject
58\brief Manages in-memory storage for a fake DAOS object.
59
60Currently, only 1 I/O descriptor/scather-gather list is supported.
61*/
62// clang-format on
63class RDaosFakeObject {
64private:
65 std::mutex fMutexStorage;
66 std::unordered_map<std::string, std::string> fStorage;
67
68 /// \brief Return the internal storage key by concatenating both dkey and akey.
69 static std::string GetKey(daos_key_t *dkey, daos_key_t *akey) {
70 return std::string{reinterpret_cast<char *>(dkey->iov_buf), dkey->iov_buf_len}
71 .append(reinterpret_cast<char *>(akey->iov_buf), akey->iov_buf_len);
72 }
73
74public:
75 RDaosFakeObject() = default;
76 ~RDaosFakeObject() = default;
77
78 int Fetch(daos_key_t *dkey, unsigned int nr, daos_iod_t *iods, d_sg_list_t *sgls);
79 int Update(daos_key_t *dkey, unsigned int nr, daos_iod_t *iods, d_sg_list_t *sgls);
80};
81
82int RDaosFakeObject::Fetch(daos_key_t *dkey, unsigned int nr, daos_iod_t *iods, d_sg_list_t *sgls)
83{
84 if (nr != 1 || iods[0].iod_nr !=1 || iods[0].iod_type != DAOS_IOD_SINGLE
85 || sgls[0].sg_nr != 1)
86 return -DER_INVAL;
87
88 std::lock_guard<std::mutex> lock(fMutexStorage);
89 auto it = fStorage.find(GetKey(dkey, &iods[0].iod_name));
90 if (it == fStorage.end())
91 return -DER_INVAL;
92 d_iov_t &iov = sgls[0].sg_iovs[0];
93 std::copy_n(std::begin(it->second), std::min(iov.iov_buf_len, it->second.size()),
94 reinterpret_cast<char *>(iov.iov_buf));
95 return 0;
96}
97
98int RDaosFakeObject::Update(daos_key_t *dkey, unsigned int nr, daos_iod_t *iods, d_sg_list_t *sgls)
99{
100 if (nr != 1 || iods[0].iod_nr !=1 || iods[0].iod_type != DAOS_IOD_SINGLE
101 || sgls[0].sg_nr != 1)
102 return -DER_INVAL;
103
104 std::lock_guard<std::mutex> lock(fMutexStorage);
105 auto &data = fStorage[GetKey(dkey, &iods[0].iod_name)];
106 d_iov_t &iov = sgls[0].sg_iovs[0];
107 data.assign(reinterpret_cast<char *>(iov.iov_buf), iov.iov_buf_len);
108 return 0;
109}
110
111// clang-format off
112/**
113\class RDaosFakeContainer
114\brief Manages objects in a fake DAOS container.
115*/
116// clang-format on
117class RDaosFakeContainer {
118private:
119 std::mutex fMutexObjects;
120 std::unordered_map<daos_obj_id_t, std::unique_ptr<RDaosFakeObject>> fObjects;
121
122public:
123 RDaosFakeContainer() = default;
124 ~RDaosFakeContainer() = default;
125
126 RDaosFakeObject *GetObject(daos_obj_id_t oid, unsigned int mode) {
127 (void)mode;
128 std::lock_guard<std::mutex> lock(fMutexObjects);
129 auto &obj = fObjects[oid];
130 if (!obj)
131 obj = std::make_unique<RDaosFakeObject>();
132 return obj.get();
133 }
134};
135
136// clang-format off
137/**
138\class RDaosFakePool
139\brief Manages user-defined containers in a fake DAOS pool.
140*/
141// clang-format on
142class RDaosFakePool {
143private:
144 static std::mutex fMutexPools;
145 static std::unordered_map<Uuid_t, std::unique_ptr<RDaosFakePool>> fPools;
146
147 std::mutex fMutexContainers;
148 std::unordered_map<Uuid_t, std::unique_ptr<RDaosFakeContainer>> fContainers;
149
150public:
151 /// \brief Get a pointer to a RDaosFakePool object associated to the given UUID.
152 /// Non-existent pools shall be created on-demand.
153 static RDaosFakePool *GetPool(const Uuid_t uuid) {
154 std::lock_guard<std::mutex> lock(fMutexPools);
155 auto &pool = fPools[uuid];
156 if (!pool)
157 pool = std::make_unique<RDaosFakePool>();
158 return pool.get();
159 }
160
161 RDaosFakePool() = default;
162 ~RDaosFakePool() = default;
163
164 void CreateContainer(const Uuid_t uuid) {
165 std::lock_guard<std::mutex> lock(fMutexContainers);
166 fContainers.emplace(uuid, std::make_unique<RDaosFakeContainer>());
167 }
168
169 RDaosFakeContainer *GetContainer(const Uuid_t uuid) {
170 std::lock_guard<std::mutex> lock(fMutexContainers);
171 auto it = fContainers.find(uuid);
172 return (it != fContainers.end()) ? it->second.get() : nullptr;
173 }
174};
175
176std::mutex RDaosFakePool::fMutexPools;
177std::unordered_map<Uuid_t, std::unique_ptr<RDaosFakePool>> RDaosFakePool::fPools;
178
179// clang-format off
180/**
181\class RDaosHandle
182\brief Translates a `daos_handle_t` to a pointer to object and viceversa.
183
184A `daos_handle_t` is used by some API functions (in particular, those that work
185with pools, containers, or objects) to reference an entity. This type (aka
186`uint64_t`) is large enough for a pointer in all architectures. However, an
187indirection layer is added in order to detect the use of invalidated handles.
188*/
189// clang-format on
190class RDaosHandle {
191private:
192 /// \brief Wrapper over a `void *` that may help to detect the use of invalid handles.
193 struct Cookie {
194 Cookie(void *p) : fPointer(p) {}
195 ~Cookie() { fPointer = nullptr; }
196 void *GetPointer() { return fPointer; }
197
198 void *fPointer;
199 };
200
201public:
202 template <typename T>
203 static inline daos_handle_t ToHandle(const T& p)
204 { return { reinterpret_cast<decltype(daos_handle_t::cookie)>(new Cookie(p)) }; }
205
206 template <typename T>
207 static inline typename std::add_pointer<T>::type ToPointer(const daos_handle_t h)
208 { return reinterpret_cast<typename std::add_pointer<T>::type>(
209 reinterpret_cast<Cookie *>(h.cookie)->GetPointer()); }
210
211 static inline void Invalidate(daos_handle_t h)
212 { delete reinterpret_cast<Cookie *>(h.cookie); }
213};
214
215} // anonymous namespace
216
217extern "C" {
218int daos_init(void)
219{
220 R__LOG_WARNING(ROOT::Experimental::NTupleLog()) << "This RNTuple build uses libdaos_mock. Use only for testing!";
221 return 0;
222}
223
224int daos_fini(void)
225{
226 return 0;
227}
228
229d_rank_list_t *daos_rank_list_parse(const char *str, const char *sep)
230{
231 (void)str;
232 (void)sep;
233 return nullptr;
234}
235
237{
238 (void)rank_list;
239}
240
241const char *d_errstr(int rc)
242{
243 return rc ? "DER_INVAL" : "Success";
244}
245
246int daos_oclass_name2id(const char *name)
247{
248 if (strcmp(name, "SX") == 0) return OC_SX;
249 if (strcmp(name, "RP_XSF") == 0) return OC_RP_XSF;
250 return OC_UNKNOWN;
251}
252
254{
255 switch (oc_id) {
256 case OC_SX:
257 strcpy(name, "SX"); // NOLINT
258 return 0;
259 case OC_RP_XSF:
260 strcpy(name, "RP_XSF"); // NOLINT
261 return 0;
262 }
263 return -1;
264}
265
266
267////////////////////////////////////////////////////////////////////////////////
268
269
270int daos_cont_create(daos_handle_t poh, const uuid_t uuid, daos_prop_t *cont_prop,
271 daos_event_t *ev)
272{
273 (void)cont_prop;
274 (void)ev;
275
276 auto pool = RDaosHandle::ToPointer<RDaosFakePool>(poh);
277 if (!pool)
278 return -DER_INVAL;
279 Uuid_t u;
280 std::copy_n(uuid, std::tuple_size<Uuid_t>::value, std::begin(u));
281 pool->CreateContainer(u);
282 return 0;
283}
284
285int daos_cont_open(daos_handle_t poh, const uuid_t uuid, unsigned int flags,
287{
288 (void)flags;
289 (void)info;
290 (void)ev;
291
292 auto pool = RDaosHandle::ToPointer<RDaosFakePool>(poh);
293 if (!pool)
294 return -DER_INVAL;
295
296 Uuid_t u;
297 std::copy_n(uuid, std::tuple_size<Uuid_t>::value, std::begin(u));
298 auto cont = pool->GetContainer(u);
299 if (!cont)
300 return -DER_INVAL;
301 *coh = RDaosHandle::ToHandle(cont);
302 return 0;
303}
304
306{
307 (void)ev;
308 RDaosHandle::Invalidate(coh);
309 return 0;
310}
311
312
313////////////////////////////////////////////////////////////////////////////////
314
315
317{
318 (void)eqh;
319 return 0;
320}
321
323{
324 (void)eqh;
325 (void)flags;
326 return 0;
327}
328
329int daos_eq_poll(daos_handle_t eqh, int wait_running,
330 int64_t timeout, unsigned int nevents, daos_event_t **events)
331{
332 (void)eqh;
333 (void)wait_running;
334 (void)timeout;
335 (void)events;
336 return nevents;
337}
338
340{
341 (void)ev;
342 (void)eqh;
343 (void)parent;
344 return 0;
345}
346
348{
349 (void)ev;
350 return 0;
351}
352
353
354////////////////////////////////////////////////////////////////////////////////
355
356
357int daos_obj_open(daos_handle_t coh, daos_obj_id_t oid, unsigned int mode,
359{
360 (void)ev;
361
362 auto cont = RDaosHandle::ToPointer<RDaosFakeContainer>(coh);
363 if (!cont)
364 return -DER_INVAL;
365 auto obj = cont->GetObject(oid, mode);
366 *oh = RDaosHandle::ToHandle(obj);
367 return 0;
368}
369
371{
372 (void)ev;
373 RDaosHandle::Invalidate(oh);
374 return 0;
375}
376
377int daos_obj_fetch(daos_handle_t oh, daos_handle_t th, uint64_t flags,
378 daos_key_t *dkey, unsigned int nr, daos_iod_t *iods,
379 d_sg_list_t *sgls, daos_iom_t *ioms, daos_event_t *ev)
380{
381 (void)th;
382 (void)flags;
383 (void)ioms;
384 (void)ev;
385
386 auto obj = RDaosHandle::ToPointer<RDaosFakeObject>(oh);
387 if (!obj)
388 return -DER_INVAL;
389 return obj->Fetch(dkey, nr, iods, sgls);
390}
391
392int daos_obj_update(daos_handle_t oh, daos_handle_t th, uint64_t flags,
393 daos_key_t *dkey, unsigned int nr, daos_iod_t *iods,
394 d_sg_list_t *sgls, daos_event_t *ev)
395{
396 (void)th;
397 (void)flags;
398 (void)ev;
399
400 auto obj = RDaosHandle::ToPointer<RDaosFakeObject>(oh);
401 if (!obj)
402 return -DER_INVAL;
403 return obj->Update(dkey, nr, iods, sgls);
404}
405
406
407////////////////////////////////////////////////////////////////////////////////
408
409
410int daos_pool_connect(const uuid_t uuid, const char *grp,
411 const d_rank_list_t *svc, unsigned int flags,
413{
414 (void)grp;
415 (void)svc;
416 (void)flags;
417 (void)info;
418 (void)ev;
419
420 Uuid_t u;
421 std::copy_n(uuid, std::tuple_size<Uuid_t>::value, std::begin(u));
422 *poh = RDaosHandle::ToHandle(RDaosFakePool::GetPool(u));
423 return 0;
424}
425
427{
428 (void)ev;
429 RDaosHandle::Invalidate(poh);
430 return 0;
431}
432
433} // extern "C"
typedef void(GLAPIENTRYP _GLUfuncptr)(void)
#define R__LOG_WARNING(...)
Definition RLogger.hxx:363
#define h(i)
Definition RSha256.hxx:106
char name[80]
Definition TGX11.cxx:110
TRObject operator()(const T1 &t1) const
This file is a reduced version of daos_xxx.h headers that provides (simplified) declarations for use ...
uint16_t daos_oclass_id_t
Definition daos.h:133
@ DAOS_IOD_SINGLE
Definition daos.h:184
#define DER_INVAL
Definition daos.h:287
@ OC_SX
Definition daos.h:127
@ OC_UNKNOWN
Definition daos.h:107
@ OC_RP_XSF
Replicated object class which is extremely scalable for fetch.
Definition daos.h:110
int daos_oclass_id2name(daos_oclass_id_t oc_id, char *name)
const char * d_errstr(int rc)
int daos_pool_disconnect(daos_handle_t poh, daos_event_t *ev)
void d_rank_list_free(d_rank_list_t *rank_list)
int daos_oclass_name2id(const char *name)
int daos_obj_fetch(daos_handle_t oh, daos_handle_t th, uint64_t flags, daos_key_t *dkey, unsigned int nr, daos_iod_t *iods, d_sg_list_t *sgls, daos_iom_t *ioms, daos_event_t *ev)
int daos_obj_open(daos_handle_t coh, daos_obj_id_t oid, unsigned int mode, daos_handle_t *oh, daos_event_t *ev)
int daos_cont_create(daos_handle_t poh, const uuid_t uuid, daos_prop_t *cont_prop, daos_event_t *ev)
int daos_event_fini(daos_event_t *ev)
int daos_init(void)
int daos_obj_update(daos_handle_t oh, daos_handle_t th, uint64_t flags, daos_key_t *dkey, unsigned int nr, daos_iod_t *iods, d_sg_list_t *sgls, daos_event_t *ev)
int daos_cont_close(daos_handle_t coh, daos_event_t *ev)
int daos_event_init(daos_event_t *ev, daos_handle_t eqh, daos_event_t *parent)
int daos_eq_create(daos_handle_t *eqh)
int daos_cont_open(daos_handle_t poh, const uuid_t uuid, unsigned int flags, daos_handle_t *coh, daos_cont_info_t *info, daos_event_t *ev)
int daos_pool_connect(const uuid_t uuid, const char *grp, const d_rank_list_t *svc, unsigned int flags, daos_handle_t *poh, daos_pool_info_t *info, daos_event_t *ev)
d_rank_list_t * daos_rank_list_parse(const char *str, const char *sep)
int daos_obj_close(daos_handle_t oh, daos_event_t *ev)
std::array< unsigned char, 16 > Uuid_t
int daos_eq_destroy(daos_handle_t eqh, int flags)
int daos_eq_poll(daos_handle_t eqh, int wait_running, int64_t timeout, unsigned int nevents, daos_event_t **events)
int daos_fini(void)
bool operator==(const daos_obj_id_t &lhs, const daos_obj_id_t &rhs)
RLogChannel & NTupleLog()
Log channel for RNTuple diagnostics.
iovec for memory buffer
Definition daos.h:37
size_t iov_buf_len
Definition daos.h:39
void * iov_buf
Definition daos.h:38
Scatter/gather list for memory buffers.
Definition daos.h:48
d_iov_t * sg_iovs
Definition daos.h:51
Container information.
Definition daos.h:256
Event and event queue.
Definition daos.h:77
Generic handle for various DAOS components like container, object, etc.
Definition daos.h:63
uint64_t cookie
Definition daos.h:64
uint64_t hi
Definition daos.h:145
uint64_t lo
Definition daos.h:144
Storage pool.
Definition daos.h:273
daos properties, for pool or container
Definition daos.h:244