CUBRID Engine  latest
api_handle.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
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  */
18 
19 /*
20  * api_handle.h
21  */
22 
23 #include "config.h"
24 #include <stdlib.h>
25 #include <assert.h>
26 #include <errno.h>
27 #include "api_handle.h"
28 #include "api_util.h"
29 #include "error_code.h"
30 
31 /* ------------------------------------------------------------------------- */
32 /* BIND HANDLE ROOT IMPLEMENTATION
33  */
34 typedef struct bh_root_s BH_ROOT;
35 typedef struct bhifs_node_s BHIFS_NODE;
39 
40 struct bh_root_s
41 {
45  int rrid; /* const after initialization */
48 };
49 
51 {
52  dlisth head; /* must be the first member */
53  BIND_HANDLE handle; /* key */
55  BHIFS_NODE *parent; /* parent node */
56  dlisth children; /* head for children node */
57 };
58 
59 #define bhifs_node_init(n,h,b) \
60  do { \
61  dlisth_init(&(n)->head); \
62  (n)->handle = (h); \
63  (n)->bind = (b); \
64  (b)->bptr = (n); \
65  (n)->parent = NULL; \
66  dlisth_init(&(n)->children); \
67  } while (0)
68 
69 #define bhifs_node_prune(n) \
70  do { \
71  dlisth_delete((dlisth *)(n)); \
72  (n)->parent = NULL; \
73  } while (0)
74 
75 #define bhifs_node_prune_and_register_root(fe,n) \
76  do { \
77  bhifs_node_prune(n); \
78  dlisth_insert_after((dlisth *)(n),&(fe)->root_handles); \
79  } while(0)
80 
81 /* BH_INTERFACE implementation */
83 {
84  BH_INTERFACE bhifs; /* should be the first member */
88 };
89 
90 /* BIND_HANDLE to BHIFS_NODE mapping abstract structure */
92 {
93  void (*destroy) (bh_context_be * be);
94  int (*lookup) (bh_context_be * be, BIND_HANDLE handle, BHIFS_NODE ** node);
95  int (*insert) (bh_context_be * be, BHIFS_NODE * const node);
96  int (*delete) (bh_context_be * be, BIND_HANDLE handle, BHIFS_NODE ** node);
97 };
98 
99 /* hash table based bh_context_be implementation */
101 {
105 };
106 
107 #define RR_LOCK() API_LOCK(&rr_mutex)
108 #define RR_UNLOCK() API_UNLOCK(&rr_mutex)
109 #define MAX_NUM_ROOTS 1024
110 /*
111  * bind handle structure (64 bits)
112  * - rid (16 bits) : used to identify resource root
113  * - id (48 bits) : used to identify handle within a resource root
114  */
115 #define BH_RID_BITS 16
116 #define BH_RID_OFFSET 48
117 #define BH_RID_MASK 0xffff000000000000ULL
118 #define BH_RID_FILTER(h) (0xffffULL & (h))
119 
120 #define BH_ID_BITS 48
121 #define BH_ID_OFFSET 0
122 #define BH_ID_MASK 0x0000ffffffffffffULL
123 #define BH_ID_FILTER(h) (0xffffffffffffULL & (h))
124 
125 #define BH_MAKE(rr_,id_) \
126  (((BH_RID_FILTER(rr_)<< BH_RID_OFFSET) & BH_RID_MASK) | \
127  ((BH_ID_FILTER(id_)<<BH_ID_OFFSET) & BH_ID_MASK))
128 
129 #define BH_GET_RID(h) \
130  BH_RID_FILTER(((h)&BH_RID_MASK)>>BH_RID_OFFSET)
131 
132 #define BH_SET_RID(h,r) \
133  h = (((r)<<BH_RID_OFFSET)&BH_RID_MASK) | ((h) & ~BH_RID_MASK)
134 
135 #define BH_GET_ID(h) \
136  BH_ID_FILTER(((h)&BH_ID_MASK)>>BH_ID_OFFSET)
137 
138 #define BH_SET_ID(h,r) \
139  h = (((r)<<BH_ID_OFFSET)&BH_ID_MASK) | ((h) & ~BH_ID_MASK)
140 
141 /* BH_ROOT related functions */
142 static int rr_next_handle (bh_provider * bh, BIND_HANDLE * rv);
143 static int rr_lazy_init (void);
144 static int bri_init_root (void);
145 static int bri_alloc_root (int *rrid, BH_ROOT ** root);
146 static int bri_access_root (int rrid, BH_ROOT ** root);
147 
148 /* BH_INTERFACE implementation */
149 static int fe_alloc_handle (BH_INTERFACE * bhifs, BH_BIND * bind, BIND_HANDLE * bh);
150 static int fe_destroy_handle_worker (bh_context_fe * fe, BHIFS_NODE * node);
152 static int fe_lookup (BH_INTERFACE * bhifs, BIND_HANDLE bh, BH_BIND ** bind);
153 static int fe_bind_to_handle (BH_INTERFACE * bhifs, BH_BIND * bind, BIND_HANDLE * bh);
154 static int fe_bind_get_parent (BH_INTERFACE * bhifs, BH_BIND * bind, BH_BIND ** pbind);
155 static int fe_bind_prune (BH_INTERFACE * bhifs, BH_BIND * bind);
156 static int fe_bind_graft (BH_INTERFACE * bhifs, BH_BIND * bind, BH_BIND * pbind);
157 static int fe_bind_get_first_child (BH_INTERFACE * bhifs, BH_BIND * bind, BH_BIND ** pchild);
158 static int fe_bind_get_next_sibling (BH_INTERFACE * bhifs, BH_BIND * bind, BH_BIND ** psibling);
159 static int fe_bind_map_worker (bh_context_fe * fe, BHIFS_NODE * node, bh_mapf mf, void *arg);
160 static int fe_bind_map (BH_INTERFACE * bhifs, BH_BIND * bind, bh_mapf mf, void *arg);
161 static void fe_destroy (BH_INTERFACE * bhifs);
162 /* static hash based bh_context_be implementaiton */
163 static int sh_comparef (void *key1, void *key2, int *rc);
164 static int sh_hashf (void *key, unsigned int *rv);
165 static int sh_keyf (void *elem, void **rk);
166 static void sh_destroy (bh_context_be * be);
167 static int sh_lookup (bh_context_be * be, BIND_HANDLE handle, BHIFS_NODE ** node);
168 static int sh_insert (bh_context_be * be, BHIFS_NODE * const node);
169 static int sh_delete (bh_context_be * be, BIND_HANDLE handle, BHIFS_NODE ** node);
170 static int be_create_static_hash (bh_context_be ** be, int bucket_sz);
171 
172 /* static variables */
174 static int rr_initialized = 0;
177 static int rr_alloc_count = 0;
178 
179 /*
180  * rr_next_handle - get next handle value
181  * return: NO_ERROR
182  * bh(in): BH_ROOT pointer
183  * rv(out): next handle value
184  */
185 static int
187 {
188  BH_ROOT *root;
189  assert (bh != NULL);
190  assert (rv != NULL);
191  root = (BH_ROOT *) bh;
192  root->rrv++;
193  *rv = BH_MAKE (root->rrid, root->rrv);
194  return NO_ERROR;
195 }
196 
197 /*
198  * rr_lazy_init - lazy initialize resource root module
199  * return: NO_ERROR if successful, error_code otherwise
200  */
201 static int
203 {
204  int res;
205 
206  if (rr_initialized)
207  return NO_ERROR;
208 
209  RR_LOCK ();
210  if (rr_initialized)
211  {
212  RR_UNLOCK ();
213  return NO_ERROR;
214  }
215  if ((res = bri_init_root ()) != NO_ERROR)
216  {
217  RR_UNLOCK ();
218  return res;
219  }
220  rr_free_list = NULL;
221  rr_initialized = 1;
222  RR_UNLOCK ();
223 
224  return NO_ERROR;
225 }
226 
227 /*
228  * rr_init_root - init resource root structure
229  * return: void
230  * root(in): BH_ROOT structure to be initialized
231  */
232 static void
233 rr_init_root (BH_ROOT * root, int i)
234 {
236  root->rrv = 0LL;
237  API_MUTEX_INIT (&root->mutex);
238  root->rrid = i;
239  root->free_link = NULL;
240  root->bhifs = NULL;
241 }
242 
243 /*
244  * bri_init_root - init array based root allcation
245  * return: NO_ERROR
246  */
247 static int
249 {
250  return NO_ERROR;
251 }
252 
253 /*
254  * bri_alloc_root - allocate new resource root id and BH_ROOT structure
255  * return: NO_ERROR if successful, error code otherwise
256  * rrid(out): resource root id
257  * root(out): BH_ROOT structure allcated
258  */
259 static int
260 bri_alloc_root (int *rrid, BH_ROOT ** root)
261 {
263  {
264  rr_init_root (&Roots[rr_alloc_count], rr_alloc_count);
265  *rrid = rr_alloc_count++;
266  *root = &Roots[*rrid];
267  return NO_ERROR;
268  }
270 }
271 
272 /*
273  * bri_access_root - get pointer to BH_ROOT indexed by rrid
274  * return: NO_ERROR
275  * rrid(in): resource root id
276  * root(out): pointer to BH_ROOT structure
277  */
278 static int
280 {
281  if (rrid < 0 || rrid >= rr_alloc_count)
283  *root = &Roots[rrid];
284  return NO_ERROR;
285 }
286 
287 
288 /*
289  * fe_alloc_handle - allocate a new handle for the given bind
290  * return: NO_ERROR if successful, error code otherwise
291  * bhifs(in): BH_INTERFACE
292  * bind(in): BH_BIND structure
293  * bh(out): handle allcated
294  */
295 static int
297 {
298  bh_context_fe *fe;
299  BHIFS_NODE *node;
301  int res;
302 
303  assert (bhifs != NULL);
304  assert (bh != NULL);
305 
306  fe = (bh_context_fe *) bhifs;
307  if ((res = fe->handle_provider->next_handle (fe->handle_provider, &handle)) != NO_ERROR)
308  return res;
309 
310  if ((node = API_MALLOC (sizeof (*node))) == NULL)
312  bhifs_node_init (node, handle, bind);
313 
314  if ((res = fe->be->insert (fe->be, node)) != NO_ERROR)
315  {
316  API_FREE (node);
317  return res;
318  }
319 
320  dlisth_insert_after ((dlisth *) node, &fe->root_handles);
321  *bh = handle;
322  return NO_ERROR;
323 }
324 
325 /*
326  * fe_destroy_handle_worker - destroy BHIFS_NODE recursively
327  * return: NO_ERROR if successful, error code otherwise
328  * fe(in): bh_context_fe structure
329  * node(in): node to destroy
330  */
331 static int
333 {
334  BHIFS_NODE *tmp;
335  int res;
336 
337  while (!dlisth_is_empty (&node->children))
338  {
339  BHIFS_NODE *n = (BHIFS_NODE *) node->children.next;
340  res = fe_destroy_handle_worker (fe, n);
341  if (res != NO_ERROR)
342  return res;
343  }
344 
345  if ((res = fe->be->delete (fe->be, node->handle, &tmp)) != NO_ERROR)
346  return res;
347  assert (tmp == node);
348 
349  if (node->bind != NULL && node->bind->dtor != NULL)
350  node->bind->dtor (node->bind);
351 
352  bhifs_node_prune (node);
353  API_FREE (node);
354 
355  return NO_ERROR;
356 }
357 
358 /*
359  * fe_destroy_handle - destroy given handle
360  * return: NO_ERROR if successful, error code otherwise
361  * bhifs(in): BH_INTERFACE
362  * bh(in): handle
363  */
364 static int
366 {
367  bh_context_fe *fe;
368  BHIFS_NODE *node;
369  int res;
370 
371  assert (bhifs != NULL);
372  fe = (bh_context_fe *) bhifs;
373 
374  if ((res = fe->be->lookup (fe->be, bh, &node)) != NO_ERROR)
375  return res;
376 
377  return fe_destroy_handle_worker (fe, node);
378 }
379 
380 /*
381  * fe_lookup - lookup BH_BIND * corresponding to BH_HANDLE
382  * return: NO_ERROR if successful, error code otherwise
383  * bhifs(in): BH_INTERFACE pointer
384  * bh(in): BIND_HANDLE
385  * bind(out): BH_BIND pointer
386  */
387 static int
389 {
390  bh_context_fe *fe;
391  BHIFS_NODE *node;
392  int res;
393 
394  assert (bhifs != NULL);
395  assert (bind != NULL);
396 
397  fe = (bh_context_fe *) bhifs;
398  if ((res = fe->be->lookup (fe->be, bh, &node)) != NO_ERROR)
399  return res;
400 
401  *bind = node->bind;
402  return NO_ERROR;
403 }
404 
405 /*
406  * fe_bind_to_handle - get BIND_HANDLE from BH_BIND
407  * return: NO_ERROR if successful, error code otherwise
408  * bhifs(in): BH_INTERFACE
409  * bind(in): BH_BIND
410  * bh(out): BIND_HANDLE
411  */
412 static int
414 {
415  BHIFS_NODE *node;
416 
417  assert (bhifs != NULL);
418  assert (bind != NULL);
419  assert (bh != NULL);
420  assert (bind->bptr != NULL);
421 
422  node = (BHIFS_NODE *) bind->bptr;
423  *bh = node->handle;
424  return NO_ERROR;
425 }
426 
427 /*
428  * fe_bind_get_parent - get parent BH_BIND of the given BH_BIND
429  * return: NO_ERROR if successful, error code otherwise
430  * bhifs(in): BH_INTERFACE
431  * bind(in): BH_BIND
432  * pbind(out): parent BH_BIND
433  */
434 static int
436 {
437  BHIFS_NODE *node, *parent_node;
438 
439  assert (bhifs != NULL);
440  assert (bind != NULL);
441  assert (pbind != NULL);
442 
443  node = (BHIFS_NODE *) bind->bptr;
444  assert (node != NULL);
445  parent_node = node->parent;
446  if (parent_node)
447  *pbind = parent_node->bind;
448  else
449  *pbind = NULL;
450  return NO_ERROR;
451 }
452 
453 /*
454  * fe_bind_prune - detach BH_BIND from the parent
455  * return: NO_ERROR if successful, error code otherwise
456  * bhifs(in): BH_INTERFACE
457  * bind(in): BH_BIND to prune
458  */
459 static int
461 {
462  BHIFS_NODE *node;
463  bh_context_fe *fe;
464 
465  assert (bhifs != NULL);
466  assert (bind != NULL);
467  assert (bind->bptr != NULL);
468 
469  node = (BHIFS_NODE *) bind->bptr;
470  fe = (bh_context_fe *) bhifs;
471 
473  return NO_ERROR;
474 }
475 
476 /*
477  * fe_bind_graft - graft BH_BIND to another BH_BIND
478  * return: NO_ERROR if successful, error code otherwise
479  * bhifs(in): BH_INTERFACE
480  * bind(in): child BH_BIND
481  * pbind(in): parent BH_BIND
482  */
483 static int
485 {
486  BHIFS_NODE *node, *parent_node;
487  bh_context_fe *fe;
488 
489  assert (bhifs != NULL);
490  assert (bind != NULL);
491  assert (bind->bptr != NULL);
492  assert (pbind != NULL);
493  assert (pbind->bptr != NULL);
494  assert (bind != pbind);
495 
496  fe = (bh_context_fe *) bhifs;
497  node = (BHIFS_NODE *) bind->bptr;
498  parent_node = (BHIFS_NODE *) pbind->bptr;
499  bhifs_node_prune (node);
500  dlisth_insert_before ((dlisth *) node, &parent_node->children);
501  node->parent = parent_node;
502  return NO_ERROR;
503 }
504 
505 /*
506  * fe_bind_get_first_child - get first child of given bind
507  * return: NO_ERROR if successful, error_code otherwise
508  * bhifs(in): BH_INTERFACE
509  * bind(in): BH_BIND
510  * pchild(out): child BH_BIND
511  */
512 static int
514 {
515  BHIFS_NODE *node, *child;
516 
517  assert (bhifs != NULL);
518  assert (bind != NULL);
519  assert (pchild != NULL);
520 
521  node = (BHIFS_NODE *) bind->bptr;
522  assert (node != NULL);
523  if (dlisth_is_empty (&node->children))
524  {
525  *pchild = NULL;
526  return NO_ERROR;
527  }
528  child = (BHIFS_NODE *) node->children.next;
529  assert (child->bind != NULL);
530  *pchild = child->bind;
531  return NO_ERROR;
532 }
533 
534 /*
535  * fe_bind_get_next_sibling - get next sibling of the given BH_BIND
536  * return: NO_ERROR if successful, error code otherwise
537  * bhifs(in): BH_INTERFACE
538  * bind(in): BH_BIND
539  * psibling(out): next sibling
540  */
541 static int
543 {
544  BHIFS_NODE *node, *sibling;
545 
546  assert (bhifs != NULL);
547  assert (bind != NULL);
548  assert (psibling != NULL);
549 
550  node = (BHIFS_NODE *) bind->bptr;
551  assert (node != NULL);
552  if (node->parent == NULL || node->head.next == &node->parent->children)
553  {
554  *psibling = NULL;
555  return NO_ERROR;
556  }
557  sibling = (BHIFS_NODE *) node->head.next;
558  assert (sibling->bind != NULL);
559  *psibling = sibling->bind;
560  return NO_ERROR;
561 }
562 
563 /*
564  * fe_bind_map_worker - worker function for the fe_bind_map()
565  * return: NO_ERROR if successful, error code otherwise
566  * fe(in): BH_INTERFACE
567  * node(in): BH_BIND
568  * mf(in): map function
569  * arg(in): argument of the map function
570  */
571 static int
572 fe_bind_map_worker (bh_context_fe * fe, BHIFS_NODE * node, bh_mapf mf, void *arg)
573 {
574  dlisth *h;
575 
576  for (h = node->children.next; h != &node->children; h = h->next)
577  {
578  BHIFS_NODE *n = (BHIFS_NODE *) h;
579  int res = fe_bind_map_worker (fe, n, mf, arg);
580  if (res != NO_ERROR)
581  return res;
582  }
583  return mf ((BH_INTERFACE *) fe, node->bind, arg);
584 }
585 
586 /*
587  * fe_bind_map - call map function for each decendenat BH_BIND node.
588  * in post order.
589  * return: NO_ERROR if successful, error code otherwise
590  * bhifs(in): BH_INTERFACE
591  * bind(in): BH_BIND to map
592  * mf(in): map function
593  * arg(in): map function argument
594  */
595 static int
596 fe_bind_map (BH_INTERFACE * bhifs, BH_BIND * bind, bh_mapf mf, void *arg)
597 {
598  assert (bhifs != NULL);
599  assert (bind != NULL);
600  assert (mf != NULL);
601  assert (bind->bptr != NULL);
602 
603  return fe_bind_map_worker ((bh_context_fe *) bhifs, (BHIFS_NODE *) bind->bptr, mf, arg);
604 }
605 
606 /*
607  * fe_destroy - destroy BH_INTERFACE
608  * return: void
609  * bhifs(in): BH_INTERFACE
610  */
611 static void
613 {
614  bh_context_fe *fe;
615  dlisth *h;
616  int res;
617 
618  assert (bhifs != NULL);
619  fe = (bh_context_fe *) bhifs;
620 
621  while ((h = fe->root_handles.next) != &fe->root_handles)
622  {
623  BHIFS_NODE *n = (BHIFS_NODE *) h;
624  bhifs_node_prune (n);
625  res = fe_destroy_handle_worker (fe, n);
626 
627  if (res != NO_ERROR)
628  continue;
629  }
630 
631  fe->be->destroy (fe->be);
632  API_FREE (fe);
633  return;
634 }
635 
636 
637 /*
638  * sh_comparef - hash compare function
639  * return: NO_ERROR
640  * key1(in): pointer to the key (BIND_HANDLE)
641  * key2(in): pointer to another key (BIND_HANDLE)
642  * rc(out): compare result (1, 0, -1)
643  */
644 static int
645 sh_comparef (void *key1, void *key2, int *rc)
646 {
647  BIND_HANDLE p1, p2;
648 
649  assert (key1 != NULL);
650  assert (key2 != NULL);
651 
652  p1 = *(BIND_HANDLE *) key1;
653  p2 = *(BIND_HANDLE *) key2;
654 
655  *rc = (p1 == p2) ? 0 : p1 < p2 ? -1 : 1;
656  return NO_ERROR;
657 }
658 
659 /*
660  * sh_hashf - hash hash function
661  * return: NO_ERROR
662  * key(in): pointer to the key (BIND_HANDLE)
663  * rv(out): hash value
664  */
665 static int
666 sh_hashf (void *key, unsigned int *rv)
667 {
668  BIND_HANDLE *p;
669 
670  assert (key != NULL);
671  assert (rv != NULL);
672 
673  p = (BIND_HANDLE *) key;
674  *rv = (unsigned int) (*p % UINT_MAX);
675  return NO_ERROR;
676 }
677 
678 /*
679  * sh_keyf - hash key function. get handle fields from BHIFS_NODE
680  * return: NO_ERROR
681  * elem(in): pointer to the element (BHIFS_NODE)
682  * rk(in): pointer to the key
683  */
684 static int
685 sh_keyf (void *elem, void **rk)
686 {
687  BHIFS_NODE *node;
688 
689  assert (elem != NULL);
690  assert (rk != NULL);
691 
692  node = (BHIFS_NODE *) elem;
693  *rk = &node->handle;
694  return NO_ERROR;
695 }
696 
697 /*
698  * sh_destroy - destroy hash based bh_context_be
699  * return: void
700  * be(in): bh_context_be
701  */
702 static void
704 {
705  sh_context_be *sbe;
706  assert (be != NULL);
707  sbe = (sh_context_be *) be;
708  hash_destroy (sbe->ht, NULL);
709  API_FREE (sbe);
710  return;
711 }
712 
713 
714 /*
715  * sh_lookup - lookup BHIFS_NODE for the BIND_HANDLE
716  * return: NO_ERROR if successful, error code otherwise
717  * be(in): bh_context_be pointer
718  * handle(in): BIND_HANDLE
719  * node(out): BHIFS_NODE found
720  */
721 static int
723 {
724  sh_context_be *sbe;
725  assert (be != NULL);
726  sbe = (sh_context_be *) be;
727  return hash_lookup (sbe->ht, &handle, (void **) node);
728 }
729 
730 /*
731  * sh_insert - insert BHIFS_NODE to the bh_context_be
732  * return: NO_ERROR if successful, error code otherwise
733  * be(in): bh_context_be pointer
734  * node(in): BHIFS_NODE to insert
735  */
736 static int
737 sh_insert (bh_context_be * be, BHIFS_NODE * const node)
738 {
739  sh_context_be *sbe;
740  assert (be != NULL);
741  sbe = (sh_context_be *) be;
742  return hash_insert (sbe->ht, (void *) node);
743 }
744 
745 /*
746  * sh_delete - delete hash entry for BIND_HANDLE and return BHIFS_NODE
747  * if exists
748  * return: NO_ERROR if successful, error code otherwise
749  * be(in): bh_context_be pointer
750  * handle(in): BIND_HANDLE
751  * node(out): BHIFS_NODE found
752  */
753 static int
755 {
756  sh_context_be *sbe;
757  assert (be != NULL);
758  sbe = (sh_context_be *) be;
759  return hash_delete (sbe->ht, &handle, (void **) node);
760 }
761 
762 /*
763  * be_create_static_hash - create static hash based bh_context_be interface
764  * return: NO_ERROR if successful, error code otherwise
765  * be(out): bh_context_be
766  * bucket_sz(in): bucket size
767  */
768 static int
769 be_create_static_hash (bh_context_be ** be, int bucket_sz)
770 {
771  hash_table *ht;
772  sh_context_be *sbe;
773  int res;
774 
775  ht = NULL;
776  res = hash_new (bucket_sz, sh_hashf, sh_keyf, sh_comparef, &ht);
777  if (res != NO_ERROR)
778  return res;
779 
780  if ((sbe = API_MALLOC (sizeof (*sbe))) == NULL)
781  {
782  hash_destroy (ht, NULL);
784  }
785  sbe->be.destroy = sh_destroy;
786  sbe->be.lookup = sh_lookup;
787  sbe->be.insert = sh_insert;
788  sbe->be.delete = sh_delete;
789  sbe->bucket_sz = bucket_sz;
790  sbe->ht = ht;
791  *be = (bh_context_be *) sbe;
792  return NO_ERROR;
793 }
794 
795 /*
796  * bh_get_rid - get root id from BIND_HANDLE
797  * return: NO_ERROR
798  * bh(in): BIND_HANDL
799  * rid(out): root id
800  */
801 int
802 bh_get_rid (BIND_HANDLE bh, int *rid)
803 {
804  if (rid == NULL)
806  *rid = BH_GET_RID (bh);
807  return NO_ERROR;
808 }
809 
810 /*
811  * bh_root_acquire - create a new root id
812  * return: NO_ERROR if successful, error code otherwise
813  * rrid(out): root id
814  * rt(rt): BH_ROOT_TYPE
815  */
816 int
818 {
819  int res;
820  BH_ROOT *rr;
822 
823  if (rrid == NULL)
825 
826  if ((res = rr_lazy_init ()) != NO_ERROR)
827  return res;
828 
829  rr = NULL;
830  res = NO_ERROR;
831 
832  RR_LOCK ();
833  if (rr_free_list)
834  {
835  rr = rr_free_list;
836  rr_free_list = rr_free_list->free_link;
837  rr->free_link = NULL;
838  }
839  else
840  res = bri_alloc_root (rrid, &rr);
841  RR_UNLOCK ();
842 
843  if (res != NO_ERROR)
844  return res;
845 
846  assert (rr != NULL);
847  bhifs = NULL;
848 
849  res = create_handle_context ((bh_provider *) rr, rt, &bhifs);
850  if (res != NO_ERROR)
851  {
852  RR_LOCK ();
853  rr->free_link = rr_free_list;
854  rr_free_list = rr;
855  RR_UNLOCK ();
856  return res;
857  }
858  API_LOCK (&rr->mutex);
859  rr->bhifs = bhifs;
860  *rrid = rr->rrid;
861  API_UNLOCK (&rr->mutex);
862  return res;
863 }
864 
865 /*
866  * bh_root_release - release root for the root id
867  * return: NO_ERROR if successful, error code otherwise
868  * rrid(in): root id
869  */
870 int
872 {
873  BH_ROOT *root;
875  int res;
876 
877  if ((res = bri_access_root (rrid, &root)) != NO_ERROR)
878  return res;
879 
880  RR_LOCK ();
881  API_LOCK (&root->mutex);
882  if (root->bhifs == NULL)
883  {
884  API_UNLOCK (&root->mutex);
885  RR_UNLOCK ();
887  }
888  root->free_link = rr_free_list;
889  rr_free_list = root;
890  bhifs = root->bhifs;
891  root->bhifs = NULL;
892  API_UNLOCK (&root->mutex);
893  RR_UNLOCK ();
894 
895  assert (bhifs != NULL);
896  bhifs->destroy (bhifs);
897  return NO_ERROR;
898 }
899 
900 /*
901  * bh_root_lock - try to lock the root identified by root id. if successful
902  * return BH_INTERFACE also via out parameter.
903  * return: NO_ERROR if successful, error code otherwise
904  * rrid(in): root id
905  * bhifs(out): BH_INTERFACE
906  */
907 int
909 {
910  BH_ROOT *root;
911  int res;
912 
913  if (rr_initialized == 0)
914  return ER_INTERFACE_GENERIC;
915 
916  if ((res = bri_access_root (rrid, &root)) != NO_ERROR)
917  return res;
918 
919  res = API_TRYLOCK (&root->mutex);
920  if (res != 0)
921  {
922  if (res == EBUSY)
924  else
925  return ER_INTERFACE_GENERIC;
926  }
927  if (root->bhifs == NULL)
928  {
929  API_UNLOCK (&root->mutex);
931  }
932  if (bhifs)
933  *bhifs = root->bhifs;
934 
935  return NO_ERROR;
936 }
937 
938 /*
939  * bh_root_unlock - unlock root
940  * return: NO_ERROR if successful, error code otherwise
941  * rrid(in): root id
942  */
943 int
945 {
946  BH_ROOT *root;
947  int res;
948 
949  if (rr_initialized == 0)
950  return ER_INTERFACE_GENERIC;
951  if ((res = bri_access_root (rrid, &root)) != NO_ERROR)
952  return res;
953 
954  API_UNLOCK (&root->mutex);
955 
956  return NO_ERROR;
957 }
958 
959 /*
960  * create_handle_context - create a BH_INTERFACE
961  * return: NO_ERROR if successful, error code otherwise
962  * prov(in): bh_provider
963  * rt(in): BH_ROOT_TYPE
964  * bhifs(out): BH_INTERFACE created
965  */
966 int
968 {
969  bh_context_fe *fe;
970  bh_context_be *be;
971  int res;
972 
973  assert (prov != NULL);
974  assert (bhifs != NULL);
975 
976  be = NULL;
977  switch (rt)
978  {
980  res = be_create_static_hash (&be, 64);
981  break;
983  res = be_create_static_hash (&be, 128);
984  break;
986  res = be_create_static_hash (&be, 1024);
987  break;
990  default:
992  }
993  if (res != NO_ERROR)
994  return res;
995  assert (be != NULL);
996 
997  if ((fe = API_MALLOC (sizeof (*fe))) == NULL)
1001  fe->bhifs.lookup = fe_lookup;
1008  fe->bhifs.bind_map = fe_bind_map;
1009  fe->bhifs.destroy = fe_destroy;
1010  fe->handle_provider = prov;
1011  dlisth_init (&fe->root_handles);
1012  fe->be = be;
1013  *bhifs = (BH_INTERFACE *) fe;
1014  return NO_ERROR;
1015 }
int bh_root_unlock(int rrid)
Definition: api_handle.c:944
#define dlisth_insert_before(ih, bh)
Definition: api_util.h:58
#define RR_UNLOCK()
Definition: api_handle.c:108
#define dlisth_insert_after(ih, bh)
Definition: api_util.h:68
dlisth * next
Definition: api_util.h:33
void * handle
#define ER_INTERFACE_HANDLE_TIMEOUT
Definition: error_code.h:1178
int(* bind_get_first_child)(BH_INTERFACE *ifs, BH_BIND *bind, BH_BIND **pchild)
Definition: api_handle.h:67
#define NO_ERROR
Definition: error_code.h:46
void(* destroy)(BH_INTERFACE *ifs)
Definition: api_handle.h:70
int hash_insert(hash_table *ht, void *elem)
Definition: api_util.c:275
dlisth children
Definition: api_handle.c:56
static int sh_keyf(void *elem, void **rk)
Definition: api_handle.c:685
static int rr_alloc_count
Definition: api_handle.c:177
int bh_root_release(int rrid)
Definition: api_handle.c:871
static int rr_next_handle(bh_provider *bh, BIND_HANDLE *rv)
Definition: api_handle.c:186
dlisth root_handles
Definition: api_handle.c:86
#define BH_MAKE(rr_, id_)
Definition: api_handle.c:125
int(* bind_graft)(BH_INTERFACE *ifs, BH_BIND *bind, BH_BIND *on_bind)
Definition: api_handle.h:66
void hash_destroy(hash_table *ht, ht_destroyf dtor)
Definition: api_util.c:198
static int fe_bind_map_worker(bh_context_fe *fe, BHIFS_NODE *node, bh_mapf mf, void *arg)
Definition: api_handle.c:572
static int rr_initialized
Definition: api_handle.c:174
int hash_lookup(hash_table *ht, void *key, void **relem)
Definition: api_util.c:233
int(* lookup)(BH_INTERFACE *ifs, BIND_HANDLE bh, BH_BIND **bind)
Definition: api_handle.h:62
int bh_root_lock(int rrid, BH_INTERFACE **bhifs)
Definition: api_handle.c:908
bh_context_be * be
Definition: api_handle.c:87
#define ER_INTERFACE_NOT_SUPPORTED_OPERATION
Definition: error_code.h:1177
int hash_delete(hash_table *ht, void *key, void **relem)
Definition: api_util.c:318
BH_ROOT * free_link
Definition: api_handle.c:46
bh_context_be be
Definition: api_handle.c:102
static API_MUTEX rr_mutex
Definition: api_handle.c:173
dlisth head
Definition: api_handle.c:52
#define API_MUTEX
Definition: api_util.h:97
static int fe_alloc_handle(BH_INTERFACE *bhifs, BH_BIND *bind, BIND_HANDLE *bh)
Definition: api_handle.c:296
int(* bh_mapf)(BH_INTERFACE *ifs, BH_BIND *bind, void *arg)
Definition: api_handle.h:32
int bh_root_acquire(int *rrid, BH_ROOT_TYPE rt)
Definition: api_handle.c:817
static int fe_destroy_handle_worker(bh_context_fe *fe, BHIFS_NODE *node)
Definition: api_handle.c:332
BH_BIND * bind
Definition: api_handle.c:54
#define ER_INTERFACE_TOO_MANY_CONNECTION
Definition: error_code.h:1175
int(* bind_get_next_sibling)(BH_INTERFACE *ifs, BH_BIND *bind, BH_BIND **psibling)
Definition: api_handle.h:68
#define RR_LOCK()
Definition: api_handle.c:107
static int bri_init_root(void)
Definition: api_handle.c:248
bh_provider * handle_provider
Definition: api_handle.c:85
static int be_create_static_hash(bh_context_be **be, int bucket_sz)
Definition: api_handle.c:769
static int fe_destroy_handle(BH_INTERFACE *bhifs, BIND_HANDLE bh)
Definition: api_handle.c:365
#define API_UNLOCK(m)
Definition: api_util.h:101
BH_ROOT_TYPE
Definition: api_handle.h:35
#define bhifs_node_prune_and_register_root(fe, n)
Definition: api_handle.c:75
#define assert(x)
#define bhifs_node_prune(n)
Definition: api_handle.c:69
#define ER_INTERFACE_GENERIC
Definition: error_code.h:1179
BH_INTERFACE * bhifs
Definition: api_handle.c:47
static int rr_lazy_init(void)
Definition: api_handle.c:202
bh_destroyf dtor
Definition: api_handle.h:50
static int sh_delete(bh_context_be *be, BIND_HANDLE handle, BHIFS_NODE **node)
Definition: api_handle.c:754
#define bhifs_node_init(n, h, b)
Definition: api_handle.c:59
void(* destroy)(bh_context_be *be)
Definition: api_handle.c:93
int(* bind_to_handle)(BH_INTERFACE *ifs, BH_BIND *bind, BIND_HANDLE *bh)
Definition: api_handle.h:63
API_MUTEX mutex
Definition: api_handle.c:44
static int rv
Definition: area_alloc.c:52
static BH_ROOT Roots[MAX_NUM_ROOTS]
Definition: api_handle.c:176
#define NULL
Definition: freelistheap.h:34
static int fe_lookup(BH_INTERFACE *bhifs, BIND_HANDLE bh, BH_BIND **bind)
Definition: api_handle.c:388
static int fe_bind_get_parent(BH_INTERFACE *bhifs, BH_BIND *bind, BH_BIND **pbind)
Definition: api_handle.c:435
#define MAX_NUM_ROOTS
Definition: api_handle.c:109
int rrid
Definition: api_handle.c:45
#define API_LOCK(m)
Definition: api_util.h:100
int create_handle_context(bh_provider *prov, BH_ROOT_TYPE rt, BH_INTERFACE **bhifs)
Definition: api_handle.c:967
static int fe_bind_get_next_sibling(BH_INTERFACE *bhifs, BH_BIND *bind, BH_BIND **psibling)
Definition: api_handle.c:542
bh_provider provider
Definition: api_handle.c:42
BHIFS_NODE * parent
Definition: api_handle.c:55
#define API_FREE(p)
Definition: api_util.h:112
int(* bind_get_parent)(BH_INTERFACE *ifs, BH_BIND *bind, BH_BIND **pbind)
Definition: api_handle.h:64
static int sh_comparef(void *key1, void *key2, int *rc)
Definition: api_handle.c:645
int(* insert)(bh_context_be *be, BHIFS_NODE *const node)
Definition: api_handle.c:95
#define BH_GET_RID(h)
Definition: api_handle.c:129
static int rc
Definition: serial.c:50
static int sh_insert(bh_context_be *be, BHIFS_NODE *const node)
Definition: api_handle.c:737
static int bri_alloc_root(int *rrid, BH_ROOT **root)
Definition: api_handle.c:260
static int fe_bind_get_first_child(BH_INTERFACE *bhifs, BH_BIND *bind, BH_BIND **pchild)
Definition: api_handle.c:513
BIND_HANDLE handle
Definition: api_handle.c:53
static int sh_hashf(void *key, unsigned int *rv)
Definition: api_handle.c:666
int(* bind_prune)(BH_INTERFACE *ifs, BH_BIND *bind)
Definition: api_handle.h:65
static int fe_bind_to_handle(BH_INTERFACE *bhifs, BH_BIND *bind, BIND_HANDLE *bh)
Definition: api_handle.c:413
static void sh_destroy(bh_context_be *be)
Definition: api_handle.c:703
int(* delete)(bh_context_be *be, BIND_HANDLE handle, BHIFS_NODE **node)
Definition: api_handle.c:96
static int sh_lookup(bh_context_be *be, BIND_HANDLE handle, BHIFS_NODE **node)
Definition: api_handle.c:722
int(* next_handle)(bh_provider *p, BIND_HANDLE *rv)
Definition: api_handle.h:79
int bh_get_rid(BIND_HANDLE bh, int *rid)
Definition: api_handle.c:802
static int fe_bind_prune(BH_INTERFACE *bhifs, BH_BIND *bind)
Definition: api_handle.c:460
int i
Definition: dynamic_load.c:954
#define API_MALLOC(s)
Definition: api_util.h:111
static BH_ROOT * rr_free_list
Definition: api_handle.c:175
static int fe_bind_map(BH_INTERFACE *bhifs, BH_BIND *bind, bh_mapf mf, void *arg)
Definition: api_handle.c:596
#define dlisth_is_empty(h)
Definition: api_util.h:48
int(* destroy_handle)(BH_INTERFACE *ifs, BIND_HANDLE bh)
Definition: api_handle.h:61
int(* alloc_handle)(BH_INTERFACE *ifs, BH_BIND *bind, BIND_HANDLE *bh)
Definition: api_handle.h:60
#define API_MUTEX_INIT(m)
Definition: api_util.h:98
#define dlisth_init(h)
Definition: api_util.h:42
void * bptr
Definition: api_handle.h:51
UINT64 BIND_HANDLE
Definition: api_handle.h:28
#define API_MUTEX_INITIALIZER
Definition: api_util.h:99
BH_INTERFACE bhifs
Definition: api_handle.c:84
static int fe_bind_graft(BH_INTERFACE *bhifs, BH_BIND *bind, BH_BIND *pbind)
Definition: api_handle.c:484
static void rr_init_root(BH_ROOT *root, int i)
Definition: api_handle.c:233
#define ER_INTERFACE_INVALID_ARGUMENT
Definition: error_code.h:1174
#define ER_INTERFACE_INVALID_HANDLE
Definition: error_code.h:1176
int(* bind_map)(BH_INTERFACE *ifs, BH_BIND *bind, bh_mapf mf, void *arg)
Definition: api_handle.h:69
BIND_HANDLE rrv
Definition: api_handle.c:43
hash_table * ht
Definition: api_handle.c:104
const char ** p
Definition: dynamic_load.c:945
int(* lookup)(bh_context_be *be, BIND_HANDLE handle, BHIFS_NODE **node)
Definition: api_handle.c:94
static int bri_access_root(int rrid, BH_ROOT **root)
Definition: api_handle.c:279
int hash_new(int bucket_sz, ht_hashf hashf, ht_keyf keyf, ht_comparef comparef, hash_table **rht)
Definition: api_util.c:166
#define API_TRYLOCK(m)
Definition: api_util.h:102
#define ER_INTERFACE_NO_MORE_MEMORY
Definition: error_code.h:1198
static void fe_destroy(BH_INTERFACE *bhifs)
Definition: api_handle.c:612