Motr  M0
seg_dict.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2013-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_BE
24 #include "lib/trace.h"
25 
26 #include "be/seg_dict.h"
27 
28 #include "lib/errno.h" /* ENOMEM */
29 #include "lib/finject.h" /* M0_FI_ENABLED */
30 #include "lib/string.h" /* m0_streq */
31 #include "motr/magic.h"
32 
33 #include "be/alloc.h"
34 #include "be/op.h" /* M0_BE_OP_SYNC */
35 #include "be/seg.h"
36 #include "be/seg_internal.h" /* m0_be_seg_hdr */
37 #include "be/tx.h" /* M0_BE_TX_CAPTURE_PTR */
38 
45 /* -------------------------------------------------------------------
46  * Helpers
47  */
48 
50  char *dkv_key;
55  size_t dkv_key_len;
56  void *dkv_val;
58  uint64_t dkv_magic;
59 };
60 
61 M0_BE_LIST_DESCR_DEFINE(be_seg_dict, "be_seg_dict", static,
62  struct be_seg_dict_keyval, dkv_link, dkv_magic,
64 M0_BE_LIST_DEFINE(be_seg_dict, static, struct be_seg_dict_keyval);
65 
66 static struct m0_be_list *be_seg_dict_get(const struct m0_be_seg *seg)
67 {
68  return &((struct m0_be_seg_hdr *) seg->bs_addr)->bh_dict;
69 }
70 
71 static void be_seg_dict_kv_get(const struct be_seg_dict_keyval *kv)
72 {
73  /* GET kv */
74  /* GET kv->dkv_key */
75 }
76 
77 static void be_seg_dict_kv_put(const struct be_seg_dict_keyval *kv)
78 {
79  /* PUT kv->dkv_key */
80  /* PUT kv */
81 }
82 
83 static struct be_seg_dict_keyval *
85  const char *user_key,
86  bool (*compare)(const char *dict_key,
87  const char *user_key))
88 {
89  struct m0_be_list *dict = be_seg_dict_get(seg);
90  struct be_seg_dict_keyval *kv;
91  struct be_seg_dict_keyval *result = NULL;
92 
93  m0_be_list_for(be_seg_dict, dict, kv) {
95  if (compare(kv->dkv_key, user_key))
96  result = kv;
98  if (result != NULL)
99  break;
101 
102  return result;
103 }
104 
105 static bool be_seg_dict_kv_eq(const char *dict_key, const char *user_key)
106 {
107  return m0_streq(dict_key, user_key);
108 }
109 
110 /* -------------------------------------------------------------------
111  * Credits
112  */
113 
114 M0_INTERNAL void m0_be_seg_dict_insert_credit(struct m0_be_seg *seg,
115  const char *name,
116  struct m0_be_tx_credit *accum)
117 {
118  struct be_seg_dict_keyval *kv;
119  size_t buf_len = strlen(name) + 1;
120 
121  M0_BE_ALLOC_CREDIT_PTR(kv, seg, accum);
122  M0_BE_ALLOC_CREDIT_ARR(name, buf_len, seg, accum);
123  m0_be_tx_credit_add(accum, &M0_BE_TX_CREDIT(1, buf_len));
125  be_seg_dict_be_list_credit(M0_BLO_TLINK_CREATE, 1, accum);
126  be_seg_dict_be_list_credit(M0_BLO_ADD, 1, accum);
127  /* Failure path. */
128  M0_BE_FREE_CREDIT_PTR(kv, seg, accum);
129 }
130 
131 M0_INTERNAL void m0_be_seg_dict_delete_credit(struct m0_be_seg *seg,
132  const char *name,
133  struct m0_be_tx_credit *accum)
134 {
135  struct be_seg_dict_keyval *kv;
136  size_t buf_len = strlen(name) + 1;
137 
138  be_seg_dict_be_list_credit(M0_BLO_DEL, 1, accum);
139  be_seg_dict_be_list_credit(M0_BLO_TLINK_DESTROY, 1, accum);
140  M0_BE_FREE_CREDIT_ARR(name, buf_len, seg, accum);
141  M0_BE_FREE_CREDIT_PTR(kv, seg, accum);
142 }
143 
144 M0_INTERNAL void m0_be_seg_dict_create_credit(struct m0_be_seg *seg,
145  struct m0_be_tx_credit *accum)
146 {
147  be_seg_dict_be_list_credit(M0_BLO_CREATE, 1, accum);
148 }
149 
150 M0_INTERNAL void m0_be_seg_dict_destroy_credit(struct m0_be_seg *seg,
151  struct m0_be_tx_credit *accum)
152 {
153  be_seg_dict_be_list_credit(M0_BLO_DESTROY, 1, accum);
154 }
155 
156 /* -------------------------------------------------------------------
157  * Operations
158  */
159 
160 M0_INTERNAL void m0_be_seg_dict_init(struct m0_be_seg *seg)
161 {
162  M0_ENTRY("seg=%p", seg);
164 
165  /* NOOP, be/list doesn't have init */
166 
167  M0_LEAVE();
168 }
169 
170 M0_INTERNAL void m0_be_seg_dict_fini(struct m0_be_seg *seg)
171 {
172  M0_ENTRY("seg=%p", seg);
174 
175  /* NOOP, be/list doesn't have fini */
176 
177  M0_LEAVE();
178 }
179 
180 M0_INTERNAL int m0_be_seg_dict_lookup(struct m0_be_seg *seg,
181  const char *name,
182  void **out)
183 {
184  struct be_seg_dict_keyval *kv;
185 
186  M0_ENTRY("seg=%p name='%s'", seg, name);
188  if (kv != NULL) {
189  be_seg_dict_kv_get(kv);
190  *out = kv->dkv_val;
191  be_seg_dict_kv_put(kv);
192  }
193  return kv == NULL ? M0_RC(-ENOENT) : M0_RC(0);
194 }
195 
196 static bool be_seg_dict_kv_begin(const char *dict_key,
197  const char *user_key)
198 {
199  return strcmp(dict_key, user_key) >= 0;
200 }
201 
202 static bool be_seg_dict_kv_next(const char *dict_key,
203  const char *user_key)
204 {
205  return strcmp(dict_key, user_key) > 0;
206 }
207 
208 static int be_seg_dict_iterate(struct m0_be_seg *seg,
209  const char *prefix,
210  const char *start_key,
211  const char **this_key,
212  void **this_rec,
213  bool (*compare)(const char *dict_key,
214  const char *user_key))
215 {
216  struct be_seg_dict_keyval *kv;
217  int rc = -ENOENT;
218 
219  kv = be_seg_dict_find(seg, start_key, compare);
220  if (kv) {
221  be_seg_dict_kv_get(kv);
222  if (strstr(kv->dkv_key, "M0_BE:") != NULL &&
223  strstr(kv->dkv_key, prefix) != NULL) {
224  rc = 0;
225  *this_key = kv->dkv_key;
226  *this_rec = kv->dkv_val;
227  }
228  M0_LOG(M0_DEBUG, "rc=%d, dict_key='%s', prefix='%s'",
229  rc, kv->dkv_key, prefix);
230  be_seg_dict_kv_put(kv);
231  }
232  return M0_RC(rc);
233 }
234 
235 
236 M0_INTERNAL int m0_be_seg_dict_begin(struct m0_be_seg *seg,
237  const char *start_key,
238  const char **this_key,
239  void **this_rec)
240 {
241  return be_seg_dict_iterate(seg, start_key, start_key,
242  this_key, this_rec, be_seg_dict_kv_begin);
243 }
244 
245 M0_INTERNAL int m0_be_seg_dict_next(struct m0_be_seg *seg,
246  const char *prefix,
247  const char *start_key,
248  const char **this_key,
249  void **this_rec)
250 {
251  return be_seg_dict_iterate(seg, prefix, start_key,
252  this_key, this_rec, be_seg_dict_kv_next);
253 }
254 
255 M0_INTERNAL int m0_be_seg_dict_insert(struct m0_be_seg *seg,
256  struct m0_be_tx *tx,
257  const char *name,
258  void *value)
259 {
260  struct m0_be_list *dict = be_seg_dict_get(seg);
261  struct be_seg_dict_keyval *kv;
262  struct be_seg_dict_keyval *next;
263  size_t buf_len = strlen(name) + 1;
264  int rc = 0;
265 
266  M0_ENTRY("seg=%p name='%s'", seg, name);
268 
269  if (M0_FI_ENABLED("dict_insert_fail"))
270  return M0_RC(-ENOENT);
271 
272  /* Check for collision */
274  if (next != NULL) {
276  if (m0_streq(next->dkv_key, name))
277  rc = M0_RC(-EEXIST);
279  if (rc != 0)
280  return rc;
281  }
282 
283  /* Create new entry */
284 
285  M0_BE_ALLOC_PTR_SYNC(kv, seg, tx);
286  if (kv == NULL)
287  return M0_ERR(-ENOMEM);
288  /* GET kv */
289  M0_BE_ALLOC_ARR_SYNC(kv->dkv_key, buf_len, seg, tx);
290  if (kv->dkv_key == NULL) {
292  tx, &op, kv));
293  rc = M0_ERR(-ENOMEM);
294  }
295  if (rc == 0) {
296  /* GET kv->dkv_key */
297  strncpy(kv->dkv_key, name, buf_len);
298  M0_ASSERT(kv->dkv_key[buf_len - 1] == '\0');
299  kv->dkv_key_len = buf_len;
300  kv->dkv_val = value;
301  M0_BE_TX_CAPTURE_ARR(seg, tx, kv->dkv_key, buf_len);
302  M0_BE_TX_CAPTURE_PTR(seg, tx, kv);
303  be_seg_dict_be_tlink_create(kv, tx);
304  if (next == NULL)
305  be_seg_dict_be_list_add_tail(dict, tx, kv);
306  else
307  be_seg_dict_be_list_add_before(dict, tx, next, kv);
308  /* PUT kv->dkv_key */
309  }
310  /* PUT kv */
311 
313  return M0_RC(rc);
314 }
315 
316 M0_INTERNAL int m0_be_seg_dict_delete(struct m0_be_seg *seg,
317  struct m0_be_tx *tx,
318  const char *name)
319 {
320  struct m0_be_list *dict = be_seg_dict_get(seg);
321  struct be_seg_dict_keyval *kv;
322 
323  M0_ENTRY("seg=%p name='%s'", seg, name);
325 
327  if (kv == NULL)
328  return M0_ERR(-ENOENT);
329 
330  be_seg_dict_be_list_del(dict, tx, kv);
331  be_seg_dict_be_tlink_destroy(kv, tx);
332  be_seg_dict_kv_get(kv);
334  kv->dkv_key));
336  be_seg_dict_kv_put(kv);
337 
339  return M0_RC(0);
340 }
341 
342 M0_INTERNAL void m0_be_seg_dict_create(struct m0_be_seg *seg,
343  struct m0_be_tx *tx)
344 {
345  struct m0_be_list *dict = be_seg_dict_get(seg);
346 
347  M0_ENTRY("seg=%p", seg);
349 
350  be_seg_dict_be_list_create(dict, tx);
351  M0_LEAVE();
352 }
353 
354 M0_INTERNAL void m0_be_seg_dict_destroy(struct m0_be_seg *seg,
355  struct m0_be_tx *tx)
356 {
357  struct m0_be_list *dict = be_seg_dict_get(seg);
358 
359  M0_ENTRY("seg=%p", seg);
361 
362  be_seg_dict_be_list_destroy(dict, tx);
363  M0_LEAVE();
364 }
365 
367 #undef M0_TRACE_SUBSYSTEM
368 
369 /*
370  * Local variables:
371  * c-indentation-style: "K&R"
372  * c-basic-offset: 8
373  * tab-width: 8
374  * fill-column: 80
375  * scroll-step: 1
376  * End:
377  */
378 /*
379  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
380  */
void * bs_addr
Definition: seg.h:71
#define M0_BE_TX_CREDIT_PTR(ptr)
Definition: tx_credit.h:98
#define M0_BE_ALLOC_CREDIT_PTR(ptr, seg, accum)
Definition: alloc.h:355
M0_INTERNAL int m0_be_seg_dict_begin(struct m0_be_seg *seg, const char *start_key, const char **this_key, void **this_rec)
Definition: seg_dict.c:236
#define M0_PRE(cond)
#define M0_BE_ALLOC_PTR_SYNC(ptr, seg, tx)
Definition: alloc.h:339
static struct be_seg_dict_keyval * be_seg_dict_find(struct m0_be_seg *seg, const char *user_key, bool(*compare)(const char *dict_key, const char *user_key))
Definition: seg_dict.c:84
uint64_t dkv_magic
Definition: seg_dict.c:58
M0_INTERNAL int m0_be_seg_dict_insert(struct m0_be_seg *seg, struct m0_be_tx *tx, const char *name, void *value)
Definition: seg_dict.c:255
#define NULL
Definition: misc.h:38
M0_INTERNAL void m0_be_seg_dict_init(struct m0_be_seg *seg)
Definition: seg_dict.c:160
#define M0_LOG(level,...)
Definition: trace.h:167
M0_LEAVE()
#define M0_BE_ALLOC_CREDIT_ARR(arr, nr, seg, accum)
Definition: alloc.h:363
M0_INTERNAL int m0_be_seg_dict_next(struct m0_be_seg *seg, const char *prefix, const char *start_key, const char **this_key, void **this_rec)
Definition: seg_dict.c:245
static struct m0_uint128 prefix
Definition: extmap.c:45
#define M0_BE_OP_SYNC(op_obj, action)
Definition: op.h:190
int const char const void * value
Definition: dir.c:325
#define M0_BE_TX_CAPTURE_PTR(seg, tx, ptr)
Definition: tx.h:505
size_t dkv_key_len
Definition: seg_dict.c:55
static bool be_seg_dict_kv_eq(const char *dict_key, const char *user_key)
Definition: seg_dict.c:105
M0_INTERNAL bool m0_be_seg__invariant(const struct m0_be_seg *seg)
Definition: stubs.c:221
static void be_seg_dict_kv_get(const struct be_seg_dict_keyval *kv)
Definition: seg_dict.c:71
#define M0_BE_TX_CAPTURE_ARR(seg, tx, arr, nr)
Definition: tx.h:507
static struct m0_be_list * be_seg_dict_get(const struct m0_be_seg *seg)
Definition: seg_dict.c:66
return M0_RC(rc)
op
Definition: libdemo.c:64
#define M0_BE_TX_CREDIT(nr, size)
Definition: tx_credit.h:94
#define M0_ENTRY(...)
Definition: trace.h:170
return M0_ERR(-EOPNOTSUPP)
const char * name
Definition: trace.c:110
M0_INTERNAL int m0_be_seg_dict_delete(struct m0_be_seg *seg, struct m0_be_tx *tx, const char *name)
Definition: seg_dict.c:316
#define M0_ASSERT(cond)
M0_INTERNAL struct m0_be_allocator * m0_be_seg_allocator(struct m0_be_seg *seg)
Definition: stubs.c:113
static int be_seg_dict_iterate(struct m0_be_seg *seg, const char *prefix, const char *start_key, const char **this_key, void **this_rec, bool(*compare)(const char *dict_key, const char *user_key))
Definition: seg_dict.c:208
M0_INTERNAL void m0_be_tx_credit_add(struct m0_be_tx_credit *c0, const struct m0_be_tx_credit *c1)
Definition: tx_credit.c:44
#define m0_streq(a, b)
Definition: string.h:34
M0_INTERNAL void m0_be_seg_dict_fini(struct m0_be_seg *seg)
Definition: seg_dict.c:170
static int next[]
Definition: cp.c:248
M0_BE_LIST_DESCR_DEFINE(be_seg_dict, "be_seg_dict", static, struct be_seg_dict_keyval, dkv_link, dkv_magic, M0_BE_SEG_DICT_MAGIC, M0_BE_SEG_DICT_HEAD_MAGIC)
static bool be_seg_dict_kv_next(const char *dict_key, const char *user_key)
Definition: seg_dict.c:202
#define M0_POST(cond)
M0_INTERNAL void m0_be_seg_dict_destroy_credit(struct m0_be_seg *seg, struct m0_be_tx_credit *accum)
Definition: seg_dict.c:150
Definition: seg.h:66
static bool compare(const struct m0_sns_ir *ir, const uint32_t *failed_arr, const struct m0_bufvec *x, const struct m0_matvec *r)
M0_INTERNAL void m0_be_seg_dict_delete_credit(struct m0_be_seg *seg, const char *name, struct m0_be_tx_credit *accum)
Definition: seg_dict.c:131
M0_INTERNAL void m0_be_free(struct m0_be_allocator *a, struct m0_be_tx *tx, struct m0_be_op *op, void *ptr)
Definition: alloc.c:1151
#define M0_FI_ENABLED(tag)
Definition: finject.h:231
M0_INTERNAL void m0_be_seg_dict_create_credit(struct m0_be_seg *seg, struct m0_be_tx_credit *accum)
Definition: seg_dict.c:144
static bool be_seg_dict_kv_begin(const char *dict_key, const char *user_key)
Definition: seg_dict.c:196
M0_INTERNAL void m0_be_seg_dict_destroy(struct m0_be_seg *seg, struct m0_be_tx *tx)
Definition: seg_dict.c:354
#define M0_BE_ALLOC_ARR_SYNC(arr, nr, seg, tx)
Definition: alloc.h:335
#define m0_be_list_endfor
Definition: list.h:369
static struct m0_be_seg * seg
Definition: btree.c:40
M0_BE_LIST_DEFINE(be_seg_dict, static, struct be_seg_dict_keyval)
M0_INTERNAL void m0_be_seg_dict_create(struct m0_be_seg *seg, struct m0_be_tx *tx)
Definition: seg_dict.c:342
#define out(...)
Definition: gen.c:41
M0_INTERNAL void m0_be_seg_dict_insert_credit(struct m0_be_seg *seg, const char *name, struct m0_be_tx_credit *accum)
Definition: seg_dict.c:114
M0_INTERNAL int m0_be_seg_dict_lookup(struct m0_be_seg *seg, const char *name, void **out)
Definition: seg_dict.c:180
int32_t rc
Definition: trigger_fop.h:47
#define M0_BE_FREE_CREDIT_ARR(arr, nr, seg, accum)
Definition: alloc.h:367
#define m0_be_list_for(name, head, obj)
Definition: list.h:358
#define M0_BE_FREE_CREDIT_PTR(ptr, seg, accum)
Definition: alloc.h:359
struct m0_be_list_link dkv_link
Definition: seg_dict.c:57
Definition: tx.h:280
static void be_seg_dict_kv_put(const struct be_seg_dict_keyval *kv)
Definition: seg_dict.c:77