Logo ROOT  
Reference Guide
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 label_t = std::string;
32namespace std {
33// Required by `std::unordered_map<daos_obj_id, ...>`. Based on boost::hash_combine().
34template <>
35struct hash<daos_obj_id_t> {
36 std::size_t operator()(const daos_obj_id_t &oid) const
37 {
38 auto seed = std::hash<uint64_t>{}(oid.lo);
39 seed ^= std::hash<uint64_t>{}(oid.hi) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
40 return seed;
41 }
42};
43} // namespace std
44
45inline bool operator==(const daos_obj_id_t &lhs, const daos_obj_id_t &rhs)
46{
47 return (lhs.lo == rhs.lo) && (lhs.hi == rhs.hi);
48}
49
50namespace {
51// clang-format off
52/**
53\class RDaosFakeObject
54\brief Manages in-memory storage for a fake DAOS object.
55
56Currently, only 1 I/O descriptor/scather-gather list is supported.
57*/
58// clang-format on
59class RDaosFakeObject {
60private:
61 std::mutex fMutexStorage;
62 std::unordered_map<std::string, std::string> fStorage;
63
64 /// \brief Return the internal storage key by concatenating both dkey and akey.
65 static std::string GetKey(daos_key_t *dkey, daos_key_t *akey)
66 {
67 return std::string{reinterpret_cast<char *>(dkey->iov_buf), dkey->iov_buf_len}.append(
68 reinterpret_cast<char *>(akey->iov_buf), akey->iov_buf_len);
69 }
70
71public:
72 RDaosFakeObject() = default;
73 ~RDaosFakeObject() = default;
74
75 int Fetch(daos_key_t *dkey, unsigned int nr, daos_iod_t *iods, d_sg_list_t *sgls);
76 int Update(daos_key_t *dkey, unsigned int nr, daos_iod_t *iods, d_sg_list_t *sgls);
77};
78
79int RDaosFakeObject::Fetch(daos_key_t *dkey, unsigned int nr, daos_iod_t *iods, d_sg_list_t *sgls)
80{
81 /* For documentation see DAOS' daos_obj_fetch */
82
83 std::lock_guard<std::mutex> lock(fMutexStorage);
84 /* Iterate over pairs of (I/O descriptor, scatter-gather list) */
85 for (unsigned i = 0; i < nr; i++) {
86 /* Retrieve entry data for (dkey, akey). Fails if not found */
87 auto data = fStorage.find(GetKey(dkey, /*akey=*/&iods[i].iod_name));
88 if (data == fStorage.end())
89 return -DER_INVAL;
90
91 /* In principle, we can safely assume that each attribute key is associated to a single value,
92 * i.e. one extent per I/O descriptor; and that the corresponding data is copied to exactly one
93 * I/O vector. */
94 if (iods[i].iod_nr != 1 || iods[i].iod_type != DAOS_IOD_SINGLE)
95 return -DER_INVAL;
96 if (sgls[i].sg_nr != 1)
97 return -DER_INVAL;
98
99 d_iov_t &iov = sgls[i].sg_iovs[0];
100 std::copy_n(std::begin(data->second), std::min(iov.iov_buf_len, data->second.size()),
101 reinterpret_cast<char *>(iov.iov_buf));
102 }
103 return 0;
104}
105
106int RDaosFakeObject::Update(daos_key_t *dkey, unsigned int nr, daos_iod_t *iods, d_sg_list_t *sgls)
107{
108 /* For documentation see DAOS' daos_obj_update */
109
110 std::lock_guard<std::mutex> lock(fMutexStorage);
111 /* Process each I/O descriptor and associated SG list */
112 for (unsigned i = 0; i < nr; i++) {
113 auto &data = fStorage[GetKey(dkey, /*akey=*/&iods[i].iod_name)];
114 /* We assume each attribute key is associated to a single value whose corresponding data is
115 * updated from exactly one I/O vector. */
116 if (iods[i].iod_nr != 1 || iods[i].iod_type != DAOS_IOD_SINGLE)
117 return -DER_INVAL;
118 if (sgls[i].sg_nr != 1)
119 return -DER_INVAL;
120
121 d_iov_t &iov = sgls[i].sg_iovs[0];
122 data.assign(reinterpret_cast<char *>(iov.iov_buf), iov.iov_buf_len); // Write to buffer
123 }
124 return 0;
125}
126
127// clang-format off
128/**
129\class RDaosFakeContainer
130\brief Manages objects in a fake DAOS container.
131*/
132// clang-format on
133class RDaosFakeContainer {
134private:
135 std::mutex fMutexObjects;
136 std::unordered_map<daos_obj_id_t, std::unique_ptr<RDaosFakeObject>> fObjects;
137
138public:
139 RDaosFakeContainer() = default;
140 ~RDaosFakeContainer() = default;
141
142 RDaosFakeObject *GetObject(daos_obj_id_t oid, unsigned int /*mode*/)
143 {
144 std::lock_guard<std::mutex> lock(fMutexObjects);
145 auto &obj = fObjects[oid];
146 if (!obj)
147 obj = std::make_unique<RDaosFakeObject>();
148 return obj.get();
149 }
150};
151
152// clang-format off
153/**
154\class RDaosFakePool
155\brief Manages user-defined containers in a fake DAOS pool.
156*/
157// clang-format on
158class RDaosFakePool {
159private:
160 static std::mutex fMutexPools;
161 static std::unordered_map<label_t, std::unique_ptr<RDaosFakePool>> fPools;
162
163 std::mutex fMutexContainers;
164 std::unordered_map<label_t, std::unique_ptr<RDaosFakeContainer>> fContainers;
165
166public:
167 /// \brief Get a pointer to a RDaosFakePool object associated to the given UUID.
168 /// Non-existent pools shall be created on-demand.
169 static RDaosFakePool *GetPool(const label_t &label)
170 {
171 std::lock_guard<std::mutex> lock(fMutexPools);
172 auto &pool = fPools[label];
173 if (!pool)
174 pool = std::make_unique<RDaosFakePool>();
175 return pool.get();
176 }
177
178 RDaosFakePool() = default;
179 ~RDaosFakePool() = default;
180
181 void CreateContainer(const label_t &label)
182 {
183 std::lock_guard<std::mutex> lock(fMutexContainers);
184 fContainers.emplace(label, std::make_unique<RDaosFakeContainer>());
185 }
186
187 RDaosFakeContainer *GetContainer(const label_t &label)
188 {
189 std::lock_guard<std::mutex> lock(fMutexContainers);
190 auto it = fContainers.find(label);
191 return (it != fContainers.end()) ? it->second.get() : nullptr;
192 }
193};
194
195std::mutex RDaosFakePool::fMutexPools;
196std::unordered_map<label_t, std::unique_ptr<RDaosFakePool>> RDaosFakePool::fPools;
197
198// clang-format off
199/**
200\class RDaosHandle
201\brief Translates a `daos_handle_t` to a pointer to object and viceversa.
202
203A `daos_handle_t` is used by some API functions (in particular, those that work
204with pools, containers, or objects) to reference an entity. This type (aka
205`uint64_t`) is large enough for a pointer in all architectures. However, an
206indirection layer is added in order to detect the use of invalidated handles.
207*/
208// clang-format on
209class RDaosHandle {
210private:
211 /// \brief Wrapper over a `void *` that may help to detect the use of invalid handles.
212 struct Cookie {
213 Cookie(void *p) : fPointer(p) {}
214 ~Cookie() { fPointer = nullptr; }
215 void *GetPointer() { return fPointer; }
216
217 void *fPointer;
218 };
219
220public:
221 template <typename T>
222 static inline daos_handle_t ToHandle(const T &p)
223 {
224 return {reinterpret_cast<decltype(daos_handle_t::cookie)>(new Cookie(p))};
225 }
226
227 template <typename T>
228 static inline typename std::add_pointer<T>::type ToPointer(const daos_handle_t h)
229 {
230 return reinterpret_cast<typename std::add_pointer<T>::type>(reinterpret_cast<Cookie *>(h.cookie)->GetPointer());
231 }
232
233 static inline void Invalidate(daos_handle_t h) { delete reinterpret_cast<Cookie *>(h.cookie); }
234};
235
236} // anonymous namespace
237
238extern "C" {
239int daos_init(void)
240{
241 R__LOG_WARNING(ROOT::Experimental::NTupleLog()) << "This RNTuple build uses libdaos_mock. Use only for testing!";
242 return 0;
243}
244
245int daos_fini(void)
246{
247 return 0;
248}
249
250const char *d_errstr(int rc)
251{
252 return rc ? "DER_INVAL" : "Success";
253}
254
255int daos_oclass_name2id(const char *name)
256{
257 if (strcmp(name, "SX") == 0)
258 return OC_SX;
259 if (strcmp(name, "RP_XSF") == 0)
260 return OC_RP_XSF;
261 return OC_UNKNOWN;
262}
263
265{
266 switch (oc_id) {
267 case OC_SX:
268 strcpy(name, "SX"); // NOLINT
269 return 0;
270 case OC_RP_XSF:
271 strcpy(name, "RP_XSF"); // NOLINT
272 return 0;
273 }
274 return -1;
275}
276
277////////////////////////////////////////////////////////////////////////////////
278
279int daos_cont_create_with_label(daos_handle_t poh, const char *label, daos_prop_t * /*cont_prop*/, uuid_t * /*uuid*/,
280 daos_event_t * /*ev*/)
281{
282 auto pool = RDaosHandle::ToPointer<RDaosFakePool>(poh);
283 if (!pool)
284 return -DER_INVAL;
285
286 if (!daos_label_is_valid(label))
287 return -DER_INVAL;
288
289 pool->CreateContainer(label_t(label));
290 return 0;
291}
292
293int daos_cont_open(daos_handle_t poh, const char *label, unsigned int /*flags*/, daos_handle_t *coh,
294 daos_cont_info_t * /*info*/, daos_event_t * /*ev*/)
295{
296 auto pool = RDaosHandle::ToPointer<RDaosFakePool>(poh);
297 if (!pool)
298 return -DER_INVAL;
299
300 if (!daos_label_is_valid(label))
301 return -DER_INVAL;
302
303 auto cont = pool->GetContainer(label_t(label));
304 if (!cont)
305 return -DER_INVAL;
306 *coh = RDaosHandle::ToHandle(cont);
307 return 0;
308}
309
311{
312 RDaosHandle::Invalidate(coh);
313 return 0;
314}
315
316////////////////////////////////////////////////////////////////////////////////
317
319{
320 return 0;
321}
322
323int daos_eq_destroy(daos_handle_t /*eqh*/, int /*flags*/)
324{
325 return 0;
326}
327
328int daos_eq_poll(daos_handle_t /*eqh*/, int /*wait_running*/, int64_t /*timeout*/, unsigned int nevents,
329 daos_event_t ** /*events*/)
330{
331 return nevents;
332}
333
334int daos_event_test(daos_event * /*ev*/, int64_t /*timeout*/, bool *flag)
335{
336 if (flag != nullptr)
337 *flag = true;
338 return 0;
339}
340
342{
343 return 0;
344}
345
346int daos_event_init(daos_event_t * /*ev*/, daos_handle_t /*eqh*/, daos_event_t * /*parent*/)
347{
348 return 0;
349}
350
352{
353 return 0;
354}
355
356////////////////////////////////////////////////////////////////////////////////
357
358int daos_obj_open(daos_handle_t coh, daos_obj_id_t oid, unsigned int mode, daos_handle_t *oh, daos_event_t * /*ev*/)
359{
360 auto cont = RDaosHandle::ToPointer<RDaosFakeContainer>(coh);
361 if (!cont)
362 return -DER_INVAL;
363 auto obj = cont->GetObject(oid, mode);
364 *oh = RDaosHandle::ToHandle(obj);
365 return 0;
366}
367
369{
370 RDaosHandle::Invalidate(oh);
371 return 0;
372}
373
375 daos_oclass_hints_t /*hints*/, uint32_t /*args*/)
376{
377 uint64_t hdr;
378
379 /* Validate user-specified bits are not reserved by DAOS */
381 return -DER_INVAL;
382
383 oid->hi &= (1ULL << OID_FMT_INTR_BITS) - 1;
384 // | Upper bits contain
385 // | OID_FMT_TYPE_BITS (object type)
386 // | OID_FMT_META_BITS (object class metadata)
387 // | OID_FMT_CLASS_BITS (object class)
388 // | 96-bit for upper layer
389 hdr = ((uint64_t)type << OID_FMT_TYPE_SHIFT);
390 hdr |= ((uint64_t)0 << OID_FMT_META_SHIFT);
391 hdr |= ((uint64_t)cid << OID_FMT_CLASS_SHIFT);
392 oid->hi |= hdr;
393
394 return 0;
395}
396
397int daos_obj_fetch(daos_handle_t oh, daos_handle_t /*th*/, uint64_t /*flags*/, daos_key_t *dkey, unsigned int nr,
398 daos_iod_t *iods, d_sg_list_t *sgls, daos_iom_t * /*ioms*/, daos_event_t * /*ev*/)
399{
400 auto obj = RDaosHandle::ToPointer<RDaosFakeObject>(oh);
401 if (!obj)
402 return -DER_INVAL;
403 return obj->Fetch(dkey, nr, iods, sgls);
404}
405
406int daos_obj_update(daos_handle_t oh, daos_handle_t /*th*/, uint64_t /*flags*/, daos_key_t *dkey, unsigned int nr,
407 daos_iod_t *iods, d_sg_list_t *sgls, daos_event_t * /*ev*/)
408{
409 auto obj = RDaosHandle::ToPointer<RDaosFakeObject>(oh);
410 if (!obj)
411 return -DER_INVAL;
412 return obj->Update(dkey, nr, iods, sgls);
413}
414
415////////////////////////////////////////////////////////////////////////////////
416
417int daos_pool_connect(const char *label, const char * /*grp*/, unsigned int /*flags*/, daos_handle_t *poh,
418 daos_pool_info_t * /*info*/, daos_event_t * /*ev*/)
419{
420
421 *poh = RDaosHandle::ToHandle(RDaosFakePool::GetPool(label_t(label)));
422 return 0;
423}
424
426{
427 RDaosHandle::Invalidate(poh);
428 return 0;
429}
430
431} // extern "C"
#define R__LOG_WARNING(...)
Definition: RLogger.hxx:363
#define h(i)
Definition: RSha256.hxx:106
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
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 ...
daos_otype_t
DAOS object type.
Definition: daos.h:162
uint16_t daos_oclass_hints_t
Definition: daos.h:136
#define OID_FMT_META_SHIFT
Definition: daos.h:159
static bool daos_label_is_valid(const char *)
Definition: daos.h:246
uint16_t daos_oclass_id_t
Definition: daos.h:135
#define OID_FMT_INTR_BITS
Definition: daos.h:152
static bool daos_otype_t_is_valid(enum daos_otype_t type)
Definition: daos.h:172
@ DAOS_IOD_SINGLE
Definition: daos.h:195
#define DER_INVAL
Definition: daos.h:283
#define OID_FMT_CLASS_SHIFT
Definition: daos.h:158
#define OID_FMT_TYPE_SHIFT
Definition: daos.h:157
@ OC_SX
Definition: daos.h:129
@ OC_UNKNOWN
Definition: daos.h:109
@ OC_RP_XSF
Replicated object class which is extremely scalable for fetch.
Definition: daos.h:112
int daos_oclass_id2name(daos_oclass_id_t oc_id, char *name)
const char * d_errstr(int rc)
int daos_cont_create_with_label(daos_handle_t poh, const char *label, daos_prop_t *, uuid_t *, daos_event_t *)
int daos_eq_poll(daos_handle_t, int, int64_t, unsigned int nevents, daos_event_t **)
int daos_event_init(daos_event_t *, daos_handle_t, daos_event_t *)
int daos_oclass_name2id(const char *name)
int daos_obj_open(daos_handle_t coh, daos_obj_id_t oid, unsigned int mode, daos_handle_t *oh, daos_event_t *)
int daos_pool_connect(const char *label, const char *, unsigned int, daos_handle_t *poh, daos_pool_info_t *, daos_event_t *)
int daos_init(void)
int daos_obj_fetch(daos_handle_t oh, daos_handle_t, uint64_t, daos_key_t *dkey, unsigned int nr, daos_iod_t *iods, d_sg_list_t *sgls, daos_iom_t *, daos_event_t *)
int daos_event_test(daos_event *, int64_t, bool *flag)
int daos_event_fini(daos_event_t *)
int daos_eq_create(daos_handle_t *)
int daos_obj_generate_oid(daos_handle_t, daos_obj_id_t *oid, enum daos_otype_t type, daos_oclass_id_t cid, daos_oclass_hints_t, uint32_t)
int daos_event_parent_barrier(daos_event_t *)
int daos_cont_open(daos_handle_t poh, const char *label, unsigned int, daos_handle_t *coh, daos_cont_info_t *, daos_event_t *)
int daos_obj_close(daos_handle_t oh, daos_event_t *)
int daos_fini(void)
bool operator==(const daos_obj_id_t &lhs, const daos_obj_id_t &rhs)
int daos_eq_destroy(daos_handle_t, int)
int daos_cont_close(daos_handle_t coh, daos_event_t *)
int daos_pool_disconnect(daos_handle_t poh, daos_event_t *)
int daos_obj_update(daos_handle_t oh, daos_handle_t, uint64_t, daos_key_t *dkey, unsigned int nr, daos_iod_t *iods, d_sg_list_t *sgls, daos_event_t *)
std::string label_t
RLogChannel & NTupleLog()
Log channel for RNTuple diagnostics.
Definition: RNTupleUtil.cxx:24
double T(double x)
Definition: ChebyshevPol.h:34
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:44
d_iov_t * sg_iovs
Definition: daos.h:47
Container information.
Definition: daos.h:258
Event and event queue.
Definition: daos.h:79
Generic handle for various DAOS components like container, object, etc.
Definition: daos.h:59
uint64_t cookie
Definition: daos.h:60
uint64_t hi
Definition: daos.h:147
uint64_t lo
Definition: daos.h:146
Storage pool.
Definition: daos.h:272
daos properties, for pool or container
Definition: daos.h:238