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 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 * sequentially updated from one or more I/O vectors. */
116 if (iods[i].iod_nr != 1 || iods[i].iod_type != DAOS_IOD_SINGLE)
117 return -DER_INVAL;
118
119 data.clear();
120 for (unsigned j = 0; j < sgls[i].sg_nr; j++) {
121 const d_iov_t &iov = sgls[i].sg_iovs[j];
122 data.append(reinterpret_cast<const char *>(iov.iov_buf), iov.iov_buf_len);
123 }
124 }
125 return 0;
126}
127
128// clang-format off
129/**
130\class RDaosFakeContainer
131\brief Manages objects in a fake DAOS container.
132*/
133// clang-format on
134class RDaosFakeContainer {
135private:
136 std::mutex fMutexObjects;
137 std::unordered_map<daos_obj_id_t, std::unique_ptr<RDaosFakeObject>> fObjects;
138
139public:
140 RDaosFakeContainer() = default;
141 ~RDaosFakeContainer() = default;
142
143 RDaosFakeObject *GetObject(daos_obj_id_t oid, unsigned int /*mode*/)
144 {
145 std::lock_guard<std::mutex> lock(fMutexObjects);
146 auto &obj = fObjects[oid];
147 if (!obj)
148 obj = std::make_unique<RDaosFakeObject>();
149 return obj.get();
150 }
151};
152
153// clang-format off
154/**
155\class RDaosFakePool
156\brief Manages user-defined containers in a fake DAOS pool.
157*/
158// clang-format on
159class RDaosFakePool {
160private:
161 static std::mutex fMutexPools;
162 static std::unordered_map<label_t, std::unique_ptr<RDaosFakePool>> fPools;
163
164 std::mutex fMutexContainers;
165 std::unordered_map<label_t, std::unique_ptr<RDaosFakeContainer>> fContainers;
166
167public:
168 /// \brief Get a pointer to a RDaosFakePool object associated to the given UUID.
169 /// Non-existent pools shall be created on-demand.
170 static RDaosFakePool *GetPool(const label_t &label)
171 {
172 std::lock_guard<std::mutex> lock(fMutexPools);
173 auto &pool = fPools[label];
174 if (!pool)
175 pool = std::make_unique<RDaosFakePool>();
176 return pool.get();
177 }
178
179 RDaosFakePool() = default;
180 ~RDaosFakePool() = default;
181
182 void CreateContainer(const label_t &label)
183 {
184 std::lock_guard<std::mutex> lock(fMutexContainers);
185 fContainers.emplace(label, std::make_unique<RDaosFakeContainer>());
186 }
187
188 RDaosFakeContainer *GetContainer(const label_t &label)
189 {
190 std::lock_guard<std::mutex> lock(fMutexContainers);
191 auto it = fContainers.find(label);
192 return (it != fContainers.end()) ? it->second.get() : nullptr;
193 }
194};
195
196std::mutex RDaosFakePool::fMutexPools;
197std::unordered_map<label_t, std::unique_ptr<RDaosFakePool>> RDaosFakePool::fPools;
198
199// clang-format off
200/**
201\class RDaosHandle
202\brief Translates a `daos_handle_t` to a pointer to object and viceversa.
203
204A `daos_handle_t` is used by some API functions (in particular, those that work
205with pools, containers, or objects) to reference an entity. This type (aka
206`uint64_t`) is large enough for a pointer in all architectures. However, an
207indirection layer is added in order to detect the use of invalidated handles.
208*/
209// clang-format on
210class RDaosHandle {
211private:
212 /// \brief Wrapper over a `void *` that may help to detect the use of invalid handles.
213 struct Cookie {
214 Cookie(void *p) : fPointer(p) {}
215 ~Cookie() { fPointer = nullptr; }
216 void *GetPointer() { return fPointer; }
217
218 void *fPointer;
219 };
220
221public:
222 template <typename T>
223 static inline daos_handle_t ToHandle(const T &p)
224 {
225 return {reinterpret_cast<decltype(daos_handle_t::cookie)>(new Cookie(p))};
226 }
227
228 template <typename T>
229 static inline typename std::add_pointer<T>::type ToPointer(const daos_handle_t h)
230 {
231 return reinterpret_cast<typename std::add_pointer<T>::type>(reinterpret_cast<Cookie *>(h.cookie)->GetPointer());
232 }
233
234 static inline void Invalidate(daos_handle_t h) { delete reinterpret_cast<Cookie *>(h.cookie); }
235};
236
237} // anonymous namespace
238
239extern "C" {
240int daos_init(void)
241{
242 R__LOG_WARNING(ROOT::Experimental::NTupleLog()) << "This RNTuple build uses libdaos_mock. Use only for testing!";
243 return 0;
244}
245
246int daos_fini(void)
247{
248 return 0;
249}
250
251const char *d_errstr(int rc)
252{
253 return rc ? "DER_INVAL" : "Success";
254}
255
256int daos_oclass_name2id(const char *name)
257{
258 if (strcmp(name, "SX") == 0)
259 return OC_SX;
260 if (strcmp(name, "RP_XSF") == 0)
261 return OC_RP_XSF;
262 return OC_UNKNOWN;
263}
264
266{
267 switch (oc_id) {
268 case OC_SX:
269 strcpy(name, "SX"); // NOLINT
270 return 0;
271 case OC_RP_XSF:
272 strcpy(name, "RP_XSF"); // NOLINT
273 return 0;
274 }
275 return -1;
276}
277
278////////////////////////////////////////////////////////////////////////////////
279
280int daos_cont_create_with_label(daos_handle_t poh, const char *label, daos_prop_t * /*cont_prop*/, uuid_t * /*uuid*/,
281 daos_event_t * /*ev*/)
282{
283 auto pool = RDaosHandle::ToPointer<RDaosFakePool>(poh);
284 if (!pool)
285 return -DER_INVAL;
286
287 if (!daos_label_is_valid(label))
288 return -DER_INVAL;
289
290 pool->CreateContainer(label_t(label));
291 return 0;
292}
293
294int daos_cont_open(daos_handle_t poh, const char *label, unsigned int /*flags*/, daos_handle_t *coh,
295 daos_cont_info_t * /*info*/, daos_event_t * /*ev*/)
296{
297 auto pool = RDaosHandle::ToPointer<RDaosFakePool>(poh);
298 if (!pool)
299 return -DER_INVAL;
300
301 if (!daos_label_is_valid(label))
302 return -DER_INVAL;
303
304 auto cont = pool->GetContainer(label_t(label));
305 if (!cont)
306 return -DER_INVAL;
307 *coh = RDaosHandle::ToHandle(cont);
308 return 0;
309}
310
312{
313 RDaosHandle::Invalidate(coh);
314 return 0;
315}
316
317////////////////////////////////////////////////////////////////////////////////
318
320{
321 return 0;
322}
323
324int daos_eq_destroy(daos_handle_t /*eqh*/, int /*flags*/)
325{
326 return 0;
327}
328
329int daos_eq_poll(daos_handle_t /*eqh*/, int /*wait_running*/, int64_t /*timeout*/, unsigned int nevents,
330 daos_event_t ** /*events*/)
331{
332 return nevents;
333}
334
335int daos_event_test(daos_event * /*ev*/, int64_t /*timeout*/, bool *flag)
336{
337 if (flag != nullptr)
338 *flag = true;
339 return 0;
340}
341
343{
344 return 0;
345}
346
347int daos_event_init(daos_event_t * /*ev*/, daos_handle_t /*eqh*/, daos_event_t * /*parent*/)
348{
349 return 0;
350}
351
353{
354 return 0;
355}
356
357////////////////////////////////////////////////////////////////////////////////
358
359int daos_obj_open(daos_handle_t coh, daos_obj_id_t oid, unsigned int mode, daos_handle_t *oh, daos_event_t * /*ev*/)
360{
361 auto cont = RDaosHandle::ToPointer<RDaosFakeContainer>(coh);
362 if (!cont)
363 return -DER_INVAL;
364 auto obj = cont->GetObject(oid, mode);
365 *oh = RDaosHandle::ToHandle(obj);
366 return 0;
367}
368
370{
371 RDaosHandle::Invalidate(oh);
372 return 0;
373}
374
376 daos_oclass_hints_t /*hints*/, uint32_t /*args*/)
377{
378 uint64_t hdr;
379
380 /* Validate user-specified bits are not reserved by DAOS */
382 return -DER_INVAL;
383
384 oid->hi &= (1ULL << OID_FMT_INTR_BITS) - 1;
385 // | Upper bits contain
386 // | OID_FMT_TYPE_BITS (object type)
387 // | OID_FMT_META_BITS (object class metadata)
388 // | OID_FMT_CLASS_BITS (object class)
389 // | 96-bit for upper layer
390 hdr = ((uint64_t)type << OID_FMT_TYPE_SHIFT);
391 hdr |= ((uint64_t)0 << OID_FMT_META_SHIFT);
392 hdr |= ((uint64_t)cid << OID_FMT_CLASS_SHIFT);
393 oid->hi |= hdr;
394
395 return 0;
396}
397
398int daos_obj_fetch(daos_handle_t oh, daos_handle_t /*th*/, uint64_t /*flags*/, daos_key_t *dkey, unsigned int nr,
399 daos_iod_t *iods, d_sg_list_t *sgls, daos_iom_t * /*ioms*/, daos_event_t * /*ev*/)
400{
401 auto obj = RDaosHandle::ToPointer<RDaosFakeObject>(oh);
402 if (!obj)
403 return -DER_INVAL;
404 return obj->Fetch(dkey, nr, iods, sgls);
405}
406
407int daos_obj_update(daos_handle_t oh, daos_handle_t /*th*/, uint64_t /*flags*/, daos_key_t *dkey, unsigned int nr,
408 daos_iod_t *iods, d_sg_list_t *sgls, daos_event_t * /*ev*/)
409{
410 auto obj = RDaosHandle::ToPointer<RDaosFakeObject>(oh);
411 if (!obj)
412 return -DER_INVAL;
413 return obj->Update(dkey, nr, iods, sgls);
414}
415
416////////////////////////////////////////////////////////////////////////////////
417
418int daos_pool_connect(const char *label, const char * /*grp*/, unsigned int /*flags*/, daos_handle_t *poh,
419 daos_pool_info_t * /*info*/, daos_event_t * /*ev*/)
420{
421
422 *poh = RDaosHandle::ToHandle(RDaosFakePool::GetPool(label_t(label)));
423 return 0;
424}
425
427{
428 RDaosHandle::Invalidate(poh);
429 return 0;
430}
431
432} // 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 ...
@ 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
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:247
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:284
#define OID_FMT_CLASS_SHIFT
Definition daos.h:158
#define OID_FMT_TYPE_SHIFT
Definition daos.h:157
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.
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
uint32_t sg_nr
Definition daos.h:45
Container information.
Definition daos.h:259
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:273
daos properties, for pool or container
Definition daos.h:239