blob: 8d7702290e36a8ceba88cae2cb1fa3253fbb1498 [file] [log] [blame]
Shad Ansari2f7f9be2017-06-07 13:34:53 -07001/******************************************************************************
2 *
3 * <:copyright-BRCM:2016:DUAL/GPL:standard
4 *
5 * Copyright (c) 2016 Broadcom
6 * All Rights Reserved
7 *
8 * Unless you and Broadcom execute a separate written software license
9 * agreement governing use of this software, this software is licensed
10 * to you under the terms of the GNU General Public License version 2
11 * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
12 * with the following added to such license:
13 *
14 * As a special exception, the copyright holders of this software give
15 * you permission to link this software with independent modules, and
16 * to copy and distribute the resulting executable under terms of your
17 * choice, provided that you also meet, for each linked independent
18 * module, the terms and conditions of the license of that module.
19 * An independent module is a module which is not derived from this
20 * software. The special exception does not apply to any modifications
21 * of the software.
22 *
23 * Not withstanding the above, under no circumstances may you combine
24 * this software in any way with any other Broadcom software provided
25 * under a license other than the GPL, without Broadcom's express prior
26 * written consent.
27 *
28 * :>
29 *
30 *****************************************************************************/
31
32/*
33 * bcm_db_engine.c
34 *
35 * Data base engine
36 */
37#ifndef BCMDB_ENGINE_H
38
39#define BCMDB_ENGINE_H
40
41/** \defgroup bcmdb_e Data Base Engine Module
42Hierarchical data base is built from 3 types of objects:
43- set: consists of control info and dynamic array of other sets OR of records of the same kind.
44 - Mixing subsets and records in the same set is not supported.
45 - Sets are objects that perform operations like access, locking, adding or removing elements,
46 etc., via methods that can differ for every set.
47 - Set elements are addressed using a single key.
48 - Most sets are internally organized as arrays. However, other organizations (e.g., lists, hash tables)
49 are also possible because each set can have different set of methods for element access.
50- record: is a container for storing information.
51 - Record consists of control info and a structure containing fields.
52 - Record is the smallest DB element that has a handle and can be individually locked.
53 - Record size is fixed at time when the set containing records is created.
54- field: is a convenience element.
55 - DB API includes field access macros for convenience and traceability.
56 Apart from that, record layout is transparent to the DB engine.
57 - DB user has an option of accessing record fields directly (as C structure fields), without using DB API
58 @{
59*/
60
61#define bcmdb_error_print(rc,format,args...) BCMOS_TRACE_ERR("status:%s :" format, bcmos_strerror(rc), ##args)
62
63/** Data base backend type
64 */
65typedef enum
66{
67 BCMDB_BACKEND_ARRAY, /**< Array-based backend */
68 BCMDB_BACKEND_HASH, /**< Hash-based backend */
69 BCMDB_BACKEND_OTHER /**< User-defined backend */
70} bcmdb_backend_type;
71
72
73/** Data locking policy
74 */
75typedef enum
76{
77 BCMDB_LOCK_NONE, /**< No record-level locking. Can be used for records containing independent fields */
78 BCMDB_LOCK_NB_READ_SHADOW_WRITE,/**< Non-blocking read, write using shadow area (default) */
79 BCMDB_LOCK_SEM_READ_SEM_WRITE, /**< Strong locking. Both read and write locks use semaphores */
80 BCMDB_LOCK_OTHER /**< User-defined locking policy */
81} bcmdb_lock_policy;
82
83
84/** Data base key
85 * Valid values >= 0
86 */
87typedef int bcmdb_key;
88
89
90/** Any key
91 */
92#define BCMDB_KEY_ANY (-1)
93
94/** Invalid key
95 */
96#define BCMDB_KEY_INVAL (-2)
97
98/** No more records
99 */
100#define BCMDB_KEY_NO_MORE (-3)
101
102
103 /** Data Base Set control block */
104typedef struct bcmdb_set bcmdb_set;
105
106/** Data Base Record control block */
107typedef struct bcmdb_record bcmdb_record;
108
109/** Data Base Set or Record */
110typedef struct bcmdb_entry bcmdb_entry;
111
112
113/** Data base operations for notifications.
114 */
115typedef enum
116{
117 BCMDB_OPER_ADD, /**< Entry has been added */
118 BCMDB_OPER_DELETE, /**< Entry has been deleted */
119 BCMDB_OPER_UPDATE /**< Entry has been modified */
120} bcmdb_oper_t;
121
122
123/** Data base update notification callback.
124 */
125typedef void (*bcmdb_notify_cb)(bcmdb_set *set, bcmdb_key key, bcmdb_oper_t oper, void *new_data);
126
127
128/** Format callback. Used by bcmdb_record_read_formatted to convert record data to human-readible format */
129typedef int (*bcmdb_format_cb)(const void *data, char *buffer, int buffer_size);
130
131
132/** Set-of-Sets init structure.
133 */
134typedef struct bcmdb_sos_init
135{
136 const char *name; /**< Set name */
137 bcmdb_backend_type backend_type; /**< Backend type */
138 uint32_t max_entries; /**< Max number of entries. 0=unlimited (not supported for array backend) */
139 uint32_t os_flags; /**< OS flags. Control whether set can be accessed by multiple cores. See bcmos_mutex_create() */
140} bcmdb_sos_init;
141
142
143/** Set-of-Records init structure.
144 */
145typedef struct bcmdb_sor_init
146{
147 const char *name; /**< Set name */
148 bcmdb_backend_type backend_type; /**< Backend type */
149 bcmdb_lock_policy lock_policy; /**< Set locking policy */
150 uint32_t max_entries; /**< Max number of entries. 0=unlimited (not supported for array backend) */
151 uint32_t record_size; /**< Record size > 0 */
152 bcmdb_format_cb format; /**< callback that converts record data to human-readable form */
153 uint32_t os_flags; /**< OS flags. Control whether set can be accessed by multiple cores. See bcmos_mutex_create() */
154} bcmdb_sor_init;
155
156
157/** Initialize data base engine
158 *
159 * \return
160 * 0 - OK\n
161 * <0 - error code
162 */
163int bcmdb_module_init(void);
164
165
166/** Make set-of-sets control block.
167 *
168 * Helper function that creates a set of sets with reasonable defaults for all callbacks and fields.
169 * Once created, the set control block can be tuned before adding the new set to its parent set.
170 * \param[in] init set parameters
171 * \param[out] new_set set control block
172 * \return
173 * 0 - OK\n
174 * <0 - error code
175 */
176int bcmdb_make_set_of_sets(const bcmdb_sos_init *init, bcmdb_set **new_set);
177
178
179/** Make set-of-sets control block macro.
180 *
181 * Calls \ref bcmdb_make_set_of_sets.
182 * Prints error message and jumps to error_label in case of failure.
183 * For parameter description see \ref bcmdb_make_set_of_sets
184 */
185#define BCMDB_MAKE_SOS(_name,_backend,_max_entries,_p_handle,_rc,_error_label) \
186({\
187 bcmdb_sos_init _init = { .name=_name, .max_entries=_max_entries, .backend_type=_backend};\
188 _rc = bcmdb_make_set_of_sets(&_init, _p_handle);\
189 if (_rc)\
190 {\
191 bcmdb_error_print(_rc, "failed to create set %s.\n", _name);\
192 goto _error_label;\
193 }\
194})
195
196
197/** Make set-of-records control block.
198 *
199 * Helper function that creates a set of records with reasonable defaults for all callbacks and fields.
200 * Once created, the set control block can be tuned before adding the new set to its parent set.
201 * \param[in] init set parameters
202 * \param[in] alloc_records true (1) - allocate memory for all records.
203 * \param[out] new_set set control block
204 * \return
205 * 0 - OK\n
206 * <0 - error code
207 */
208int bcmdb_make_set_of_records(const bcmdb_sor_init *init, int alloc_records, bcmdb_set **new_set);
209
210
211/** Make set-of-records control block macro.
212 *
213 * Calls \ref bcmdb_make_set_of_records.
214 * Prints error message and jumps to error_label in case of failure.
215 * For parameter description see \ref bcmdb_make_set_of_records
216 */
217#define BCMDB_MAKE_SOR(_name,_backend,_lock,_max_entries,_rec_size,_is_alloc,_format,_p_handle,_rc,_error_label) \
218({\
219 bcmdb_sor_init _init = { .name=_name, .max_entries=_max_entries, .backend_type=_backend,\
220 .lock_policy=_lock, .record_size=_rec_size,.format=_format};\
221 _rc = bcmdb_make_set_of_records(&_init,_is_alloc,_p_handle);\
222 if (_rc)\
223 {\
224 bcmdb_error_print(_rc, "failed to create record set %s.\n", _name);\
225 goto _error_label;\
226 }\
227})
228
229
230/** Lock data set. When set is locked - it can't be modified.
231 *
232 * \param[in] set data base set to be locked
233 *
234 */
235void bcmdb_set_lock_read(bcmdb_set *set);
236
237
238/** Release data set lock
239 *
240 * Unlock set locked by \ref bcmdb_set_lock_read
241 *
242 * \param[in] set data base set to be unlocked
243 */
244void bcmdb_set_unlock_read(bcmdb_set *set);
245
246
247/** Lock data set for modify. If the set is SoS, the locking
248 * will be recursive.
249 *
250 * \param[in] set data base set to be locked
251 *
252 * \ingroup bcmdb
253 */
254void bcmdb_set_lock_modify(bcmdb_set *set);
255
256
257/** Release data set lock
258 *
259 * Unlock set locked by \ref bcmdb_set_lock_modify
260 *
261 * \param[in] set data base set to be unlocked
262 *
263 * \ingroup bcmdb
264 */
265void bcmdb_set_unlock_modify(bcmdb_set *set);
266
267
268/** Add set to the parent set.
269 *
270 * The function adds set to the parent set creating data base hierarchy.
271 * The function automatically acquires modify lock and releases it
272 * in the end of operation.
273 * \param[in] sos parent set of sets
274 * \param[in] key key to add new set at
275 * \param[in] new_set set control block
276 * \return
277 * =0 - OK\n
278 * <0 - error code
279 */
280int bcmdb_set_add(bcmdb_set *sos, bcmdb_key key, bcmdb_set *new_set);
281
282
283/** Add set to the parent set with specific key macro.
284 *
285 * Calls \ref bcmdb_set_add.
286 * Prints error message and jumps to error_label in case of failure.
287 * For parameter description see \ref bcmdb_set_add
288 */
289#define BCMDB_SET_ADD(_parent,_key,_set,_rc,_error_label) \
290({\
291 _rc = bcmdb_set_add(_parent,_key,_set);\
292 if (_rc)\
293 {\
294 bcmdb_error_print(_rc, "failed to add set %s to %s.\n", bcmdb_set_name(_set), bcmdb_set_name(_parent));\
295 goto _error_label;\
296 }\
297})
298
299
300/** Get set handle given its key.
301 *
302 * \param[in] sos parent set of sets
303 * \param[in] key set key.
304 * \return
305 * !=0 - set handle
306 * NULL- doesn't exist
307 */
308bcmdb_set *bcmdb_set_handle(const bcmdb_set *sos, bcmdb_key key);
309
310
311/** Get set key given its handle.
312 *
313 * \param[in] set set handle
314 * \return
315 * !=BCMDB_KEY_INVAL - set key\n
316 * BCMDB_KEY_INVAL - error
317 */
318bcmdb_key bcmdb_set_key(const bcmdb_set *set);
319
320
321/** Get set name
322 *
323 * \param[in] set set handle
324 * \return set name
325 */
326const char *bcmdb_set_name(const bcmdb_set *set);
327
328
329/** Get number of records in the set.
330 *
331 * \param[in] set set handle
332 * \return number of active records in the set
333 */
334int bcmdb_set_num_records(const bcmdb_set *set);
335
336
337/** Get entry size
338 *
339 * \param[in] set set handle
340 * \return set entry size
341 */
342int bcmdb_set_entry_size(const bcmdb_set *set);
343
344
345/** Add record to the parent set.
346 *
347 * The function creates a new record and adds it to the parent set with specific key.
348 * The function automatically acquires modify lock and releases it
349 * in the end of operation.
350 * \param[in] sor parent set of records
351 * \param[in] key record key
352 * \param[in] data record data. Data size is defined at parent SOR registration time.
353 * \return
354 * =0 - OK\n
355 * <0 - error code
356 */
357int bcmdb_record_add(bcmdb_set *sor, bcmdb_key key, const void *data);
358
359
360/** Delete record from the parent SoR given the record key.
361 *
362 * The function automatically acquires modify lock and releases it
363 * in the end of operation.
364 *
365 * \param[in] sor parent set of records
366 * \param[in] key record key.
367 */
368void bcmdb_record_delete(bcmdb_set *sor, bcmdb_key key);
369
370
371/** Get record data pointer without locking.
372 *
373 * The function returns pointer to data structure stored in data base record.\n
374 * Attention! The caller is required to aquire read or write lock - as appropriate
375 * before calling this function and release the lock when processing is finished.
376 * The function is low-level. It is recommended to use \ref bcmdb_record_get_nolock instead.
377 *
378 * \param[in] sor parent set of records
379 * \param[in] key record key
380 * \return
381 * data pointer. NULL if there is no record matching the key.
382 */
383void *bcmdb_record_getraw_nolock(bcmdb_set *sor, bcmdb_key key);
384
385
386/** Get record data pointer without locking.
387 *
388 * The function returns pointer to data structure stored in data base record.\n
389 * Attention! The caller is required to aquire read or write lock - as appropriate
390 * before calling this function and release the lock when processing is finished.
391 *
392 * \param[in] _sor parent set of records
393 * \param[in] _key record key
394 * \param[in] _record_type underlying data type.
395 * \return
396 * data pointer casted to the underlying data type\n
397 * NULL if there is no record matching the key.
398 */
399#define bcmdb_record_get_nolock(_sor, _key, _record_type) \
400 ({ \
401 assert(sizeof(_record_type)==bcmdb_set_entry_size(_sor)); \
402 (_record_type *)bcmdb_record_getraw_nolock(_sor, _key); \
403 })
404
405
406/** Lock record for reading and return record data pointer.
407 *
408 * The function aquires read-lock and returns pointer to data structure stored in data base record.\n
409 * read-lock must be released separately when the pointer is no longer in use.
410 * Note that the default record-read lock is non-blocking and counting.
411 * That means that multiple processes can read-lock the same record without blocking.
412 * The function is low-level. It is recommended to use macro \ref bcmdb_record_get_read instead.
413 *
414 * \param[in] sor parent set of records
415 * \param[in] key record key
416 * \return
417 * data pointer. NULL if there is no record matching the key.
418 */
419const void *bcmdb_record_getraw_read(bcmdb_set *sor, bcmdb_key key);
420
421
422/** Lock record for reading and return record data pointer.
423 *
424 * The macro returns pointer to data structure stored in data base record.\n
425 * The read-lock must be released separately when the pointer is no longer in use.
426 * Note that the default record-read lock is non-blocking and counting.
427 * That means that multiple processes can read-lock the same record without blocking.
428 *
429 * \param[in] _sor parent set of records
430 * \param[in] _key record key
431 * \param[in] _record_type underlying data type.
432 * \return
433 * data pointer casted to the underlying data type
434 */
435#define bcmdb_record_get_read(_sor, _key, _record_type) \
436 ({ \
437 assert(sizeof(_record_type)==bcmdb_set_entry_size(_sor)); \
438 (const _record_type *)bcmdb_record_getraw_read(_sor, _key);\
439 })
440
441
442/** Unlock record locked for reading.
443 *
444 * This function must be called after \ref bcmdb_record_get_read or
445 * \ref bcmdb_record_getraw_read. Following bcmdb_record_read_unlock
446 * call pointer returned by \ref bcmdb_record_get_read becomes invalid.
447 *
448 * \param[in] sor parent set of records
449 * \param[in] key record key
450 *
451 */
452void bcmdb_record_unlock_read(bcmdb_set *sor, bcmdb_key key);
453
454
455/** Read record data into user area.
456 *
457 * The function aquires read-lock, reads data into user area and releases read-lock.
458 *
459 * \param[in] sor parent set of records
460 * \param[in] key record key
461 * \param[in] offset offset in data record
462 * \param[in] size data size. Note that offset+size must be <= record_size
463 * \param[in] data data pointer.
464 * \return
465 * =0-OK\n
466 * <0-error code
467 */
468int bcmdb_record_read(bcmdb_set *sor, bcmdb_key key, int offset, int size, void *data);
469
470
471/** Get record field.
472 *
473 * The macro returns record field value.
474 *
475 * \param[in] _sor parent set of records
476 * \param[in] _key record key
477 * \param[in] _record_type type of the underlying data structure.
478 * \param[in] _field_name data structure field name
479 * \param[out] _p_field_value pointer of variable where data structure field value should be returned
480 * \return
481 * =0-OK\n
482 * <0-error code
483 */
484#define bcmdb_record_read_field(_sor, _key, _record_type, _field_name, _p_field_value) \
485 bcmdb_record_read(_sor, _key, offsetof(_record_type, _field_name), \
486 sizeof(*(_p_field_value)), _p_field_value);
487
488
489/** Lock record for writing and return record data pointer.
490 *
491 * The function aquires write-lock and returns pointer to data structure stored in data base record.\n
492 * write-lock must be released separately when the pointer is no longer in use.
493 * The function is low-level. It is recommended to use macro \ref bcmdb_record_get_write instead.
494 *
495 * \param[in] sor parent set of records
496 * \param[in] key record key
497 * \return
498 * data pointer. NULL if there is no record matching the key.
499 */
500void *bcmdb_record_getraw_write(bcmdb_set *sor, bcmdb_key key);
501
502
503/** Lock record for writing and return record data pointer.
504 *
505 * The function aquires write-lock and returns pointer to data structure stored in data base record.\n
506 * write-lock must be released separately when the pointer is no longer in use.
507 *
508 * \param[in] _sor parent set of records
509 * \param[in] _key record key
510 * \param[in] _record_type underlying data type.
511 * \return
512 * data pointer casted to the underlying data type
513 */
514#define bcmdb_record_get_write(_sor, _key, _record_type) \
515 ({ \
516 assert(sizeof(_record_type)==bcmdb_set_entry_size(_sor)); \
517 (_record_type *)bcmdb_record_getraw_write(_sor, _key);\
518 })
519
520
521/** Unlock record locked for writing.
522 *
523 * This function must be called after \ref bcmdb_record_get_write or
524 * \ref bcmdb_record_getraw_write. Following bcmdb_record_unlock_write
525 * call pointer returned by \ref bcmdb_record_get_write becomes invalid.
526 *
527 * \param[in] sor parent set of records
528 * \param[in] is_cancellation TRUE=cancel transaction
529 *
530 */
531void bcmdb_record_unlock_write(bcmdb_set *sor, int is_cancellation);
532
533
534
535/** Write record data.
536 *
537 * The function aquires modify-lock, replaces data stored in data base record
538 * and releses the lock.
539 *
540 * \param[in] sor parent set of records
541 * \param[in] key record key
542 * \param[in] offset offset in data record
543 * \param[in] size data size. Note that offset+size must be <= record_size
544 * \param[in] data data pointer.
545 * \return
546 * =0-OK\n
547 * <0-error code
548 */
549int bcmdb_record_write(bcmdb_set *sor, bcmdb_key key, int offset, int size, const void *data);
550
551
552/** Write record field.
553 *
554 * The macro updates record field value.\n
555 * The macro aquires and releases record-modify lock.
556 *
557 * \param[in] _sor parent set of records
558 * \param[in] _key record key
559 * \param[in] _record_type type of the underlying data structure.
560 * \param[in] _field_name data structure field name
561 * \param[in] _field_value field value
562 * \return
563 * =0-OK\n
564 * <0-error code
565 */
566#define bcmdb_record_write_field(_sor, _key, _record_type, _field_name, _field_value) \
567 ({ \
568 typeof(((_record_type *)0)->_field_name) _f = _field_value;\
569 bcmdb_record_write(_sor, _key, offsetof(_record_type, _field_name), sizeof(_f), &_f);\
570 });
571
572
573/** Register notification function to get informed
574 * when data base set is modified.
575 *
576 * \param[in] sor parent set of records
577 * \param[in] cb callback function pointer
578 * \param[in] cb_priv private data that should be passed to the callback
579 * \return
580 * =0 - OK\n
581 * <0 - error code
582 */
583int bcmdb_set_notify_register(bcmdb_set *sor, bcmdb_notify_cb cb, long cb_priv);
584
585
586/** Data base iterator
587 *
588 * \param[in] set data base set
589 * \param[in] prev last entry. BCMDB_KEY_ANY=start from the beginning
590 * \return data base entry key following prev or BCMDB_KEY_NO_MORE if end is reached.\n
591 * BCMDB_KEY_INVAL is reqturned if prev key is invalid
592 */
593bcmdb_key bcmdb_set_iterate(const bcmdb_set *set, bcmdb_key prev);
594
595
596/** Print database structure.
597 *
598 * \param[in] set root set
599 */
600void bcmdb_set_print_structure(const bcmdb_set *set);
601
602
603/** Format record for printing.
604 *
605 * The function converts record data to human-readable format.
606 *
607 * \param[in] sor parent set of records
608 * \param[in] key record key
609 * \param[out] buffer output buffer
610 * \param[in] size buffer size
611 * \return
612 * >=0-amount of data placed in the buffer\n
613 * <0-error code
614 */
615int bcmdb_record_read_formatted(bcmdb_set *sor, bcmdb_key key, char *buffer, int size);
616
617
618/** @} end of bcmdb_e group */
619
620
621#endif /* #ifndef BCMDB_ENGINE_H */
622