bpt.h

Go to the documentation of this file.
00001 /*
00002 ** bpt.h for lseos in lseos-lib/libc/conven
00003 **
00004 ** Copyright (c)2004 Julien Quintard
00005 ** Login   <quinta_j@epita.fr>
00006 **
00007 ** Started on  Fri Jul  9 17:38:49 2004 Julien Quintard
00008 ** Last update Mon Nov 29 18:47:41 2004 Julien Quintard
00009 */
00010 
00011 #ifndef BPT_H
00012 #define BPT_H
00013 
00014 /*
00015  * includes
00016  */
00017 
00018 #ifndef __LSEOS_COMPLIANT__
00019 # include <sys/types.h>
00020 # include <string.h>
00021 # include <stdio.h>
00022 #endif
00023 
00024 /*
00025  * general defines
00026  */
00027 
00028 #define BPT_VERSION             "1.9"
00029 
00030 /*
00031  * init values and limitations
00032  */
00033 
00034 #define BPT_INIT_HEIGHT         0x1
00035 #define BPT_INIT_NIKEYS         0x2
00036 #define BPT_INIT_NLKEYS         0x2
00037 
00038 /*
00039  * default types
00040  */
00041 
00042 #define BPT_NDI_T               signed int
00043 #define BPT_UNI_T               signed int
00044 #define BPT_OPTS_T              unsigned char
00045 #define BPT_CB_T                unsigned char
00046 #define BPT_TYPE_T              unsigned char
00047 #define BPT_FLAGS_T             unsigned char
00048 #define BPT_BLKSZ_T             unsigned int
00049 #define BPT_NODES_T             unsigned int
00050 #define BPT_HEIGHT_T            unsigned short
00051 
00052 /*
00053  * general types
00054  */
00055 
00056 typedef BPT_CB_T                t_bpt_cb;
00057 typedef BPT_OPTS_T              t_bpt_opts;
00058 typedef BPT_TYPE_T              t_bpt_type;
00059 typedef BPT_FLAGS_T             t_bpt_flags;
00060 
00061 /*
00062  * options
00063  */
00064 
00065 #define BPT_OPT_ZERO            0x0
00066 
00067 #define BPT_OPT_TREE            0x1
00068 #define BPT_OPT_NODE            0x2
00069 
00070 #define BPT_OPT_HEAD            0x1
00071 #define BPT_OPT_TAIL            0x2
00072 
00073 #define BPT_OPT_KEY             0x1
00074 #define BPT_OPT_PARENT          0x2
00075 
00076 #define BPT_OPT_PERFECT         0x1
00077 #define BPT_OPT_PARTIAL         0x2
00078 #define BPT_OPT_COLLIDE         0x4
00079 
00080 #define BPT_OPT_NONDI(T)        (t_bpt_ndi_##T)0x0
00081 #define BPT_OPT_NOKEY(T)        (t_bpt_key_##T)0x0
00082 #define BPT_OPT_NOVALUE(T)      (t_bpt_addr_##T)0x0
00083 
00084 #define BPT_OPT_INIT            0x1
00085 #define BPT_OPT_ADD             0x2
00086 #define BPT_OPT_MODIFY          0x3
00087 #define BPT_OPT_REMOVE          0x4
00088 #define BPT_OPT_CLEAN           0x5
00089 
00090 /*
00091  * callbacks
00092  */
00093 
00094 #define BPT_CB_UNKNOWN          0x0
00095 #define BPT_CB_INSERT           0x1
00096 #define BPT_CB_SPLIT            0x2
00097 #define BPT_CB_MODIFY           0x3
00098 #define BPT_CB_DELETE           0x4
00099 #define BPT_CB_MIGRATE          0x5
00100 #define BPT_CB_BALANCE          0x6
00101 
00102 /*
00103  * flags
00104  */
00105 
00106 #define BPT_FLAG_ZERO           0x0
00107 #define BPT_FLAG_CALLBACK       0x1
00108 #define BPT_FLAG_COLLIDE        0x2
00109 
00110 /*
00111  * types
00112  */
00113 
00114 #define BPT_TYPE_INTERNAL       0x1
00115 #define BPT_TYPE_LEAF           0x2
00116 
00117 /*
00118  * debug macro
00119  */
00120 
00121 #ifdef BPT_DEBUG
00122 #define         bpt_debug(fmt...)                                             \
00123   {                                                                           \
00124     fprintf(stderr, "[%s:%u] ", __FILE__, __LINE__);                          \
00125     fprintf(stderr, fmt);                                                     \
00126   }
00127 
00128 #else
00129 #define         bpt_debug(fmt...)
00130 #endif
00131 
00132 /*
00133  * macros that indicate the number of array's entries the programmer has to
00134  * fill with blocks addresses before performing common tree's operations
00135  * such as: init, add, modify ...
00136  *
00137  * for the remove operations, no blocks addresses are needed but an array
00138  * has to be passed, because the bpt library will fill the entries with
00139  * the addresses of the blocks that are now unused.
00140  *
00141  * for the init operation, a block is needed for creating the root node.
00142  *
00143  * the clean operation doest no use any allocation but need an array
00144  */
00145 
00146 #define         BPT_INIT_ALLOC()                                              \
00147   (1)
00148 
00149 #define         BPT_ADD_ALLOC(_bpt_)                                          \
00150   ((_bpt_)->height + 1)
00151 
00152 #define         BPT_REMOVE_ALLOC(_bpt_)                                       \
00153   (0)
00154 
00155 #define         BPT_MODIFY_ALLOC(_bpt_)                                       \
00156   (BPT_ADD_ALLOC(_bpt_) + BPT_REMOVE_ALLOC(_bpt_))
00157 
00158 #define         BPT_CLEAN_ALLOC(_bpt_)                                        \
00159   (0)
00160 
00161 /*
00162  * macros that specify the size of the array the bpt library need as
00163  * parameter
00164  */
00165 
00166 #define         BPT_INIT_SIZE()                                               \
00167   (1)
00168 
00169 #define         BPT_ADD_SIZE(_bpt_)                                           \
00170   ((_bpt_)->height + 1)
00171 
00172 #define         BPT_REMOVE_SIZE(_bpt_)                                        \
00173   ((_bpt_)->height * ((_bpt_)->height - 1) + 1)
00174 
00175 #define         BPT_MODIFY_SIZE(_bpt_)                                        \
00176   (BPT_ADD_SIZE(_bpt_) + BPT_REMOVE_SIZE(_bpt_))
00177 
00178 #define         BPT_CLEAN_SIZE(_bpt_)                                         \
00179   ((_bpt_)->nodes)
00180 
00181 /*
00182  * user friendly macros
00183  */
00184 
00185 #define         t_bpt_key(T)                                                  \
00186   t_bpt_key_##T
00187 
00188 #define         t_bpt_addr(T)                                                 \
00189   t_bpt_addr_##T
00190 
00191 #define         t_bpt_ndi(T)                                                  \
00192   t_bpt_ndi_##T
00193 
00194 #define         t_bpt_uni(T)                                                  \
00195   t_bpt_uni_##T
00196 
00197 #define         t_bpt_blksz(T)                                                \
00198   t_bpt_blksz_##T
00199 
00200 #define         t_bpt_nodes(T)                                                \
00201   t_bpt_nodes_##T
00202 
00203 #define         t_bpt_height(T)                                               \
00204   t_bpt_height_##T
00205 
00206 #define         t_bpt_node(T)                                                 \
00207   t_bpt_node_##T
00208 
00209 #define         t_bpt_imm(T)                                                  \
00210   t_bpt_imm_##T
00211 
00212 #define         t_bpt(T)                                                      \
00213   t_bpt_##T
00214 
00215 #define         t_bpt_cbctx(T)                                                \
00216   t_bpt_cbctx_##T
00217 
00218 #define         t_bpt_unused(T)                                               \
00219   t_bpt_unused_##T
00220 
00221 #define         t_bpt_head(T)                                                 \
00222   t_bpt_head_##T
00223 
00224 #define         t_bpt_inentry(T)                                              \
00225   t_bpt_inentry_##T
00226 
00227 #define         t_bpt_lfentry(T)                                              \
00228   t_bpt_lfentry_##T
00229 
00230 #define         t_bpt_entry(T)                                                \
00231   t_bpt_entry_##T
00232 
00233 #define         t_bpt_load_fn(T)                                              \
00234   t_bpt_load_fn_##T
00235 
00236 #define         t_bpt_unload_fn(T)                                            \
00237   t_bpt_unload_fn_##T
00238 
00239 #define         t_bpt_callback_fn(T)                                          \
00240   t_bpt_callback_fn_##T
00241 
00242 /*
00243  * bpt traps
00244  */
00245 
00246 #define         bpt_list(T, _bpt_, _node_, _entry_, _opts_)                   \
00247   bpt_list_##T(_bpt_, _node_, _entry_, _opts_)
00248 
00249 #define         bpt_check_unused(T, _bpt_, _unused_, _opts_)                  \
00250   bpt_check_unused_##T(_bpt_, _unused_, _opts_)
00251 
00252 #define         bpt_first_entry(T, _bpt_, _node_, _first_)                    \
00253   bpt_first_entry_##T(_bpt_, _node_, _first_)
00254 
00255 #define         bpt_prev_entry(T, _bpt_, _current_, _previous_, _opts_)       \
00256   bpt_prev_entry_##T(_bpt_, _current_, _previous_, _opts_)
00257 
00258 #define         bpt_next_entry(T, _bpt_, _current_, _next_, _opts_)           \
00259   bpt_next_entry_##T(_bpt_, _current_, _next_, _opts_)
00260 
00261 #define         bpt_last_entry(T, _bpt_, _node_, _last_)                      \
00262   bpt_last_entry_##T(_bpt_, _node_, _last_)
00263 
00264 #define         bpt_reinit_entries(T, _bpt_, _node_)                          \
00265   bpt_reinit_entries_##T(_bpt_, _node_)
00266 
00267 #define         bpt_make_node(T, _bpt_, _node_, _type_, _parent_)             \
00268   bpt_make_node_##T(_bpt_, _node_, _type_, _parent_)
00269 
00270 #define         bpt_key(T, _bpt_, _node_, _key_)                              \
00271   bpt_key_##T(_bpt_, _node_, _key_)
00272 
00273 #define         bpt_ndi(T, _bpt_, _node_, _value_, _ndi_)                     \
00274   bpt_ndi_##T(_bpt_, _node_, _value_, _ndi_)
00275 
00276 #define         bpt_update_node(T, _bpt_, _node_, _addr_, _key_,_opts_)       \
00277   bpt_update_node_##T(_bpt_, _node_, _addr_, _key_, _opts_)
00278 
00279 #define         bpt_update_parent(T, _bpt_, _node_)                           \
00280   bpt_update_parent_##T(_bpt_, _node_)
00281 
00282 #define         bpt_update(T, _bpt_, _node_, _opts_)                          \
00283   bpt_update_##T(_bpt_, _node_, _opts_)
00284 
00285 #define         bpt_linear_search(T, _bpt_, _node_, _key_, _ndi_, _opts_)     \
00286   bpt_linear_search_##T(_bpt_, _node_, _key_, _ndi_, _opts_)
00287 
00288 #define         bpt_dichotomic_search(T, _bpt_, _node_, _key_, _ndi_, _opts_) \
00289   bpt_dichotomic_search_##T(_bpt_, _node_, _key_, _ndi_, _opts_)
00290 
00291 #define         bpt_search_entry(T, _bpt_, _node_, _key_, _ndi_, _opts_)      \
00292   bpt_search_entry_##T(_bpt_, _node_, _key_, _ndi_, _opts_)
00293 
00294 #define         bpt_search_leaf(T, _bpt_, _node_, _leaf_, _key_)              \
00295   bpt_search_leaf_##T(_bpt_, _node_, _leaf_, _key_)
00296 
00297 #define         bpt_search(T, _bpt_, _key_, _entry_)                          \
00298   bpt_search_##T(_bpt_, _key_, _entry_)
00299 
00300 #define         bpt_collide_next(T, _bpt_, _key_, _entry_)                    \
00301   bpt_collide_next_##T(_bpt_, _key_, _entry_)
00302 
00303 #define         bpt_collide_search(T, _bpt_, _key_, _value_, _entry_)         \
00304   bpt_collide_search_##T(_bpt_, _key_, _value_, _entry_)
00305 
00306 #define         bpt_check_collide(T, _bpt_, _node1_, _key_, _value_)          \
00307   bpt_check_collide_##T(_bpt_, _node1_, _key_, _value_)
00308 
00309 #define         bpt_node_size(T, _bpt_, _node_)                               \
00310   bpt_node_size_##T(_bpt_, _node_)
00311 
00312 #define         bpt_simplify(T, _bpt_, _node_, _unused_)                      \
00313   bpt_simplify_##T(_bpt_, _node_, _unused_)
00314 
00315 #define         bpt_balancein_1(T, _bpt_, _node1_, _node2_,                   \
00316                                 _cbctx_, _prev_, _unused_)                    \
00317   bpt_balancein_1_##T(_bpt_, _node1_, _node2_, _cbctx_, _prev_, _unused_)
00318 
00319 #define         bpt_balancein_2(T, _bpt_, _node1_, _node2_,                   \
00320                                 _cbctx_, _prev_, _unused_)                    \
00321   bpt_balancein_2_##T(_bpt_, _node1_, _node2_, _cbctx_, _prev_, _unused_)
00322 
00323 #define         bpt_balancein_3(T, _bpt_, _node1_, _node2_,                   \
00324                                 _cbctx_, _prev_, _unused_)                    \
00325   bpt_balancein_3_##T(_bpt_, _node1_, _node2_, _cbctx_, _prev_, _unused_)
00326 
00327 #define         bpt_balancein_4(T, _bpt_, _node1_, _node2_,                   \
00328                                 _cbctx_, _prev_, _unused_)                    \
00329   bpt_balancein_4_##T(_bpt_, _node1_, _node2_, _cbctx_, _prev_, _unused_)
00330 
00331 #define         bpt_delete(T, _bpt_, _entry_, _cbctx_, _unused_)              \
00332   bpt_delete_##T(_bpt_, _entry_, _cbctx_, _unused_)
00333 
00334 #define         bpt_remove(T, _bpt_, _key_, _unused_)                         \
00335   bpt_remove_##T(_bpt_, _key_, _unused_)
00336 
00337 #define         bpt_collide_remove(T, _bpt_, _entry_, _unused_)               \
00338   bpt_collide_remove_##T(_bpt_, _entry_, _unused_)
00339 
00340 #define         bpt_modify(T, _bpt_, _key_, _lfentry_, _unused_)              \
00341   bpt_modify_##T(_bpt_, _key_, _lfentry_, _unused_)
00342 
00343 #define         bpt_collide_modify(T, _bpt_, _entry_, _lfentry_, _unused_)    \
00344   bpt_collide_modify_##T(_bpt_, _entry_, _lfentry_, _unused_)
00345 
00346 #define         bpt_insert_head(T, _bpt_, _node1_, _node2_)                   \
00347   bpt_insert_head_##T(_bpt_, _node1_, _node2_)
00348 
00349 #define         bpt_insert_tail(T, _bpt_, _node1_, _node2_)                   \
00350   bpt_insert_tail_##T(_bpt_, _node1_, _node2_)
00351 
00352 #define         bpt_shift_sort(T, _bpt_, _node_)                              \
00353   bpt_shift_sort_##T(_bpt_, _node_)
00354 
00355 #define         bpt_insert_sort(T, _bpt_, _node_, _key_, _value_,             \
00356                                 _ndi_, _opts_)                                \
00357   bpt_insert_sort_##T(_bpt_, _node_, _key_, _value_, _ndi_, _opts_)
00358 
00359 #define         bpt_new_root(T, _bpt_, _node1_, _node2_, _unused_)            \
00360   bpt_new_root_##T(_bpt_, _node1_, _node2_, _unused_)
00361 
00362 #define         bpt_balanceout(T, _bpt_, _node1_, _node2_, _entry_, _cbctx_)  \
00363   bpt_balanceout_##T(_bpt_, _node1_, _node2_, _entry_, _cbctx_)
00364 
00365 #define         bpt_split_node(T, _bpt_, _node1_, _entry_,                    \
00366                                _current_, _unused_)                           \
00367   bpt_split_node_##T(_bpt_, _node1_, _entry_, _current_, _unused_)
00368 
00369 #define         bpt_insert(T, _bpt_, _node_, _entry_, _cbctx_, _unused_)      \
00370   bpt_insert_##T(_bpt_, _node_, _entry_, _cbctx_, _unused_)
00371 
00372 #define         bpt_add(T, _bpt_, _lfentry_, _unused_)                        \
00373   bpt_add_##T(_bpt_, _lfentry_, _unused_)
00374 
00375 #define         bpt_init(T, _bpt_, _blksz_, _unusedval_, _flags_,             \
00376                          _load_, _unload_, _callback_, _unused_)              \
00377   bpt_init_##T(_bpt_, _blksz_, _unusedval_, _flags_, _load_,                  \
00378                _unload_, _callback_, _unused_)
00379 
00380 #define         bpt_clean_node(T, _bpt_, _node_, _unused_)                    \
00381   bpt_clean_node_##T(_bpt_, _node_, _unused_)
00382 
00383 #define         bpt_clean(T, _bpt_, _unused_)                                 \
00384   bpt_clean_##T(_bpt_, _unused_)
00385 
00386 /*
00387  * macros used to manipule nodes and entries
00388  */
00389 
00390 #define         BPT_HEAD(T, _node_)                                           \
00391   (t_bpt_head(T) *)((_node_)->buf)
00392 
00393 #define         BPT_INENTRY(T, _node_, _ndi_)                                 \
00394   (t_bpt_inentry(T) *)((_node_)->buf + sizeof(t_bpt_head(T)) +                \
00395                        (_ndi_) * sizeof(t_bpt_inentry(T)))
00396 
00397 #define         BPT_LFENTRY(T, _node_, _ndi_)                                 \
00398   (t_bpt_lfentry(T) *)((_node_)->buf + sizeof(t_bpt_head(T)) +                \
00399                        (_ndi_) * sizeof(t_bpt_lfentry(T)))
00400 
00401 #define         BPT_INIT_ENTRY(T, _node_, _ndi_)                              \
00402   memset((BPT_HEAD(T, (_node_)))->type == BPT_TYPE_INTERNAL ?                 \
00403          (_node_)->buf + sizeof(t_bpt_head(T)) +                              \
00404          (_ndi_) * sizeof(t_bpt_inentry(T)) :                                 \
00405          (_node_)->buf + sizeof(t_bpt_head(T)) +                              \
00406          (_ndi_) * sizeof(t_bpt_lfentry(T)), 0x0,                             \
00407          (BPT_HEAD(T, (_node_)))->type == BPT_TYPE_INTERNAL ?                 \
00408          sizeof(t_bpt_inentry(T)) : sizeof(t_bpt_lfentry(T)))
00409 
00410 #define         BPT_IMPORT_ENTRY(T, _node_, _ndi_, _entry_)                   \
00411   memcpy((BPT_HEAD(T, (_node_)))->type == BPT_TYPE_INTERNAL ?                 \
00412          (_node_)->buf + sizeof(t_bpt_head(T)) +                              \
00413          (_ndi_) * sizeof(t_bpt_inentry(T)) :                                 \
00414          (_node_)->buf + sizeof(t_bpt_head(T)) +                              \
00415          (_ndi_) * sizeof(t_bpt_lfentry(T)),                                  \
00416          (_entry_),                                                           \
00417          (BPT_HEAD(T, (_node_)))->type == BPT_TYPE_INTERNAL ?                 \
00418          sizeof(t_bpt_inentry(T)) : sizeof(t_bpt_lfentry(T)));
00419 
00420 #define         BPT_EXPORT_ENTRY(T, _node_, _ndi_, _entry_)                   \
00421   memcpy((_entry_),                                                           \
00422          (BPT_HEAD(T, (_node_)))->type == BPT_TYPE_INTERNAL ?                 \
00423          (_node_)->buf + sizeof(t_bpt_head(T)) +                              \
00424          (_ndi_) * sizeof(t_bpt_inentry(T)) :                                 \
00425          (_node_)->buf + sizeof(t_bpt_head(T)) +                              \
00426          (_ndi_) * sizeof(t_bpt_lfentry(T)),                                  \
00427          (_BPT_HEAD(T, (_node_))->type == BPT_TYPE_INTERNAL ?                 \
00428          sizeof(t_bpt_inentry(T)) : sizeof(t_bpt_lfentry(T)));
00429 
00430 #define         BPT_COPY_ENTRY(T, _node1_, _node2_, _ndi1_, _ndi2_)           \
00431   memcpy((BPT_HEAD(T, (_node1_)))->type == BPT_TYPE_INTERNAL ?                \
00432          (_node2_)->buf + sizeof(t_bpt_head(T)) +                             \
00433          (_ndi2_) * sizeof(t_bpt_inentry(T)) :                                \
00434          (_node2_)->buf + sizeof(t_bpt_head(T)) +                             \
00435          (_ndi2_) * sizeof(t_bpt_lfentry(T)),                                 \
00436          (BPT_HEAD(T, (_node1_)))->type == BPT_TYPE_INTERNAL ?                \
00437          (_node1_)->buf + sizeof(t_bpt_head(T)) +                             \
00438          (_ndi1_) * sizeof(t_bpt_inentry(T)) :                                \
00439          (_node1_)->buf + sizeof(t_bpt_head(T)) +                             \
00440          (_ndi1_) * sizeof(t_bpt_lfentry(T)),                                 \
00441          (BPT_HEAD(T, (_node1_)))->type == BPT_TYPE_INTERNAL ?                \
00442          sizeof(t_bpt_inentry(T)) : sizeof(t_bpt_lfentry(T)));
00443 
00444 #define         BPT_SWAP_ENTRIES(T, _node_, _ndi1_, _ndi2_)                   \
00445   {                                                                           \
00446     if ((BPT_HEAD(T, (_node_)))->type == BPT_TYPE_INTERNAL)                   \
00447       {                                                                       \
00448         t_bpt_inentry(T)        _swap_;                                       \
00449                                                                               \
00450         memcpy(&_swap_, (_node_)->buf + sizeof(t_bpt_head(T)) + (_ndi1_) *    \
00451                sizeof(t_bpt_inentry(T)), sizeof(t_bpt_inentry(T)));           \
00452         memcpy((_node_)->buf + sizeof(t_bpt_head(T)) + (_ndi1_) *             \
00453                sizeof(t_bpt_inentry(T)), (_node_)->buf +                      \
00454                sizeof(t_bpt_head(T)) + (_ndi2_) *                             \
00455                sizeof(t_bpt_inentry(T)), sizeof(t_bpt_inentry(T)));           \
00456         memcpy((_node_)->buf + sizeof(t_bpt_head(T)) + (_ndi2_) *             \
00457                sizeof(t_bpt_inentry(T)), &_swap_,                             \
00458                sizeof(t_bpt_inentry(T)));                                     \
00459       }                                                                       \
00460     else                                                                      \
00461       {                                                                       \
00462         t_bpt_lfentry(T)        _swap_;                                       \
00463                                                                               \
00464         memcpy(&_swap_, (_node_)->buf + sizeof(t_bpt_head(T)) + (_ndi1_) *    \
00465                sizeof(t_bpt_lfentry(T)), sizeof(t_bpt_lfentry(T)));           \
00466         memcpy((_node_)->buf + sizeof(t_bpt_head(T)) + (_ndi1_) *             \
00467                sizeof(t_bpt_lfentry(T)), (_node_)->buf +                      \
00468                sizeof(t_bpt_head(T)) + (_ndi2_) *                             \
00469                sizeof(t_bpt_lfentry(T)), sizeof(t_bpt_lfentry(T)));           \
00470         memcpy((_node_)->buf + sizeof(t_bpt_head(T)) + (_ndi2_) *             \
00471                sizeof(t_bpt_lfentry(T)), &_swap_,                             \
00472                sizeof(t_bpt_lfentry(T)));                                     \
00473       }                                                                       \
00474   }
00475 
00476 #define         BPT_SET_ENTRY(T, _node_, _ndi_, _elem_, _value_)              \
00477   {                                                                           \
00478     if ((BPT_HEAD(T, (_node_)))->type == BPT_TYPE_INTERNAL)                   \
00479       {                                                                       \
00480         t_bpt_inentry(T)        *_entry_ = BPT_INENTRY(T, _node_, _ndi_);     \
00481                                                                               \
00482         _entry_->_elem_ = (_value_);                                          \
00483       }                                                                       \
00484     else                                                                      \
00485       {                                                                       \
00486         t_bpt_lfentry(T)        *_entry_ = BPT_LFENTRY(T, _node_, _ndi_);     \
00487                                                                               \
00488         _entry_->_elem_ = (_value_);                                          \
00489       }                                                                       \
00490   }
00491 
00492 #define         BPT_GET_ENTRY(T, _node_, _ndi_, _elem_)                       \
00493   ((BPT_HEAD(T, (_node_)))->type == BPT_TYPE_INTERNAL ?                       \
00494    ((t_bpt_inentry(T) *)((_node_)->buf + sizeof(t_bpt_head(T)) + (_ndi_) *    \
00495     sizeof(t_bpt_inentry(T))))->_elem_ :                                      \
00496    ((t_bpt_lfentry(T) *)((_node_)->buf + sizeof(t_bpt_head(T)) + (_ndi_) *    \
00497     sizeof(t_bpt_lfentry(T))))->_elem_)
00498 
00499 #define         BPT_GET_THIS_ENTRY(T, _head_, _ptr_, _elem_)                  \
00500   ((_head_)->type == BPT_TYPE_INTERNAL ?                                      \
00501    ((t_bpt_inentry(T) *)(_ptr_))->_elem_ :                                    \
00502    ((t_bpt_lfentry(T) *)(_ptr_))->_elem_)
00503 
00504 #define         BPT_QUOTA(T, _bpt_, _node_)                                   \
00505   (t_bpt_ndi(T)) ((BPT_HEAD(T, (_node_)))->type == BPT_TYPE_INTERNAL ?        \
00506    ((_bpt_)->nikeys * 50 / 100) :                                             \
00507    ((_bpt_)->nlkeys * 50 / 100))
00508 
00509 /*
00510  * type non-dependent macros
00511  */
00512 
00513 #define         BPT_NODES(_bpt_)                                              \
00514   (_bpt_)->nodes
00515 
00516 #define         BPT_NIKEYS(_bpt_)                                             \
00517   (_bpt_)->nikeys
00518 
00519 #define         BPT_NLKEYS(_bpt_)                                             \
00520   (_bpt_)->nlkeys
00521 
00522 #define         BPT_HEIGHT(_bpt_)                                             \
00523   (_bpt_)->height
00524 
00525 #define         BPT_NKEYS(T, _bpt_, _node_)                                   \
00526   ((BPT_HEAD(T, (_node_)))->type == BPT_TYPE_INTERNAL ?                       \
00527    (_bpt_)->nikeys : (_bpt_)->nlkeys)
00528 
00529 #define         BPT_COPY_NODE(_bpt_, _node1_, _node2_)                        \
00530   memcpy((_node2_), (_node1_), (_bpt_)->blksz)
00531 
00532 #define         BPT_LOAD(_bpt_, _node_, _addr_)                               \
00533   (_bpt_)->load((_bpt_), (_node_), (_addr_))
00534 
00535 #define         BPT_UNLOAD(_bpt_, _node_)                                     \
00536   (_bpt_)->unload((_bpt_), (_node_));
00537 
00538 #define         BPT_CALLBACK(_bpt_, _cbctx_)                                  \
00539   {                                                                           \
00540     if ((_bpt_)->flags & BPT_FLAG_CALLBACK)                                   \
00541       (_bpt_)->callback((_bpt_), (_cbctx_));                                  \
00542   }
00543 
00544 #define         BPT_GET_ROOT(_bpt_)                                           \
00545   (_bpt_)->root
00546 
00547 #define         BPT_SET_ROOT(_bpt_, _root_)                                   \
00548   (_bpt_)->root = (_root_)
00549 
00550 #define         BPT_INIT_CBCTX(_bpt_, _cbctx_)                                \
00551   {                                                                           \
00552     if ((_bpt_)->flags & BPT_FLAG_CALLBACK)                                   \
00553       {                                                                       \
00554         (_cbctx_)->cb = BPT_CB_UNKNOWN;                                       \
00555                                                                               \
00556         (_cbctx_)->previous.node = (_bpt_)->unused;                           \
00557         (_cbctx_)->previous.ndi = 0;                                          \
00558         (_cbctx_)->current.node = (_bpt_)->unused;                            \
00559         (_cbctx_)->current.ndi = 0;                                           \
00560                                                                               \
00561         (_cbctx_)->node = (_bpt_)->unused;                                    \
00562                                                                               \
00563         (_cbctx_)->node1 = (_bpt_)->unused;                                   \
00564         (_cbctx_)->node2 = (_bpt_)->unused;                                   \
00565       }                                                                       \
00566   }
00567 
00568 #define         BPT_SET_CBCTX(_bpt_, _head_, _cbctx_, _elem_, _value_)        \
00569   {                                                                           \
00570     if (((_bpt_)->flags & BPT_FLAG_CALLBACK) &&                               \
00571         ((_head_)->type == BPT_TYPE_LEAF))                                    \
00572       (_cbctx_)->_elem_ = (_value_);                                          \
00573   }
00574 
00575 #define         BPT_RESERVE(_bpt_, _unused_, _var_)                           \
00576   {                                                                           \
00577     (_var_) = (_unused_)->array[(_unused_)->index];                           \
00578     (_unused_)->array[(_unused_)->index] = (_bpt_)->unused;                   \
00579     (_unused_)->index--;                                                      \
00580     (_bpt_)->nodes++;                                                         \
00581   }
00582 
00583 #define         BPT_RELEASE(_bpt_, _unused_, _val_)                           \
00584   {                                                                           \
00585     (_unused_)->index++;                                                      \
00586     (_unused_)->array[(_unused_)->index] = (_val_);                           \
00587     (_bpt_)->nodes--;                                                         \
00588   }
00589 
00590 /*
00591  * the core macros that build types, prototypes and functions
00592  */
00593 
00594 #define         bpt_make_types(T, _t_bpt_blksz_, _t_bpt_ndi_, _t_bpt_uni_,    \
00595                                _t_bpt_nodes_, _t_bpt_height_, _t_bpt_key_,    \
00596                                _t_bpt_addr_, _t_bpt_inentry_,                 \
00597                                _t_bpt_lfentry_)                               \
00598                                                                               \
00599 typedef struct s_bpt_##T        t_bpt_##T;                                    \
00600                                                                               \
00601 typedef _t_bpt_blksz_           t_bpt_blksz_##T;                              \
00602 typedef _t_bpt_ndi_             t_bpt_ndi_##T;                                \
00603 typedef _t_bpt_uni_             t_bpt_uni_##T;                                \
00604 typedef _t_bpt_nodes_           t_bpt_nodes_##T;                              \
00605 typedef _t_bpt_height_          t_bpt_height_##T;                             \
00606 typedef _t_bpt_key_             t_bpt_key_##T;                                \
00607 typedef _t_bpt_addr_            t_bpt_addr_##T;                               \
00608 typedef _t_bpt_inentry_         t_bpt_inentry_##T;                            \
00609 typedef _t_bpt_lfentry_         t_bpt_lfentry_##T;                            \
00610                                                                               \
00611 typedef _t_bpt_addr_            t_bpt_node_##T;                               \
00612                                                                               \
00613 typedef struct                  s_bpt_imm_##T                                 \
00614 {                                                                             \
00615   t_bpt_node(T)                 addr;                                         \
00616   void                          *buf;                                         \
00617 }                               t_bpt_imm_##T;                                \
00618                                                                               \
00619 typedef struct                  s_bpt_entry_##T                               \
00620 {                                                                             \
00621   t_bpt_node(T)                 node;                                         \
00622   t_bpt_ndi(T)                  ndi;                                          \
00623 }                               t_bpt_entry_##T;                              \
00624                                                                               \
00625 typedef struct                  s_bpt_cbctx_##T                               \
00626 {                                                                             \
00627   t_bpt_cb                      cb;                                           \
00628                                                                               \
00629   t_bpt_entry(T)                previous;                                     \
00630   t_bpt_entry(T)                current;                                      \
00631                                                                               \
00632   t_bpt_node(T)                 node;                                         \
00633                                                                               \
00634   t_bpt_node(T)                 node1;                                        \
00635   t_bpt_node(T)                 node2;                                        \
00636 }                               t_bpt_cbctx_##T;                              \
00637                                                                               \
00638 typedef void    (*t_bpt_load_fn_##T)(t_bpt(T)                   *bpt,         \
00639                                      t_bpt_imm(T)               *node,        \
00640                                      t_bpt_node(T)              addr);        \
00641                                                                               \
00642 typedef void    (*t_bpt_unload_fn_##T)(t_bpt(T)                 *bpt,         \
00643                                        t_bpt_imm(T)             *node);       \
00644                                                                               \
00645 typedef void    (*t_bpt_callback_fn_##T)(t_bpt(T)               *bpt,         \
00646                                          t_bpt_cbctx(T)         *cbctx);      \
00647                                                                               \
00648 struct                          s_bpt_##T                                     \
00649 {                                                                             \
00650   t_bpt_blksz(T)                blksz;                                        \
00651   t_bpt_addr(T)                 unused;                                       \
00652   t_bpt_nodes(T)                nodes;                                        \
00653                                                                               \
00654   t_bpt_flags                   flags;                                        \
00655   t_bpt_ndi(T)                  nikeys;                                       \
00656   t_bpt_ndi(T)                  nlkeys;                                       \
00657   t_bpt_height(T)               height;                                       \
00658   t_bpt_node(T)                 root;                                         \
00659                                                                               \
00660   t_bpt_load_fn(T)              load;                                         \
00661   t_bpt_unload_fn(T)            unload;                                       \
00662   t_bpt_callback_fn(T)          callback;                                     \
00663 };                                                                            \
00664                                                                               \
00665 typedef struct                  s_bpt_unused_##T                              \
00666 {                                                                             \
00667   t_bpt_addr(T)                 *array;                                       \
00668   t_bpt_uni(T)                  index;                                        \
00669 }                               t_bpt_unused_##T;                             \
00670                                                                               \
00671 typedef struct                  s_bpt_head_##T                                \
00672 {                                                                             \
00673   t_bpt_type                    type;                                         \
00674   t_bpt_node(T)                 parent;                                       \
00675   t_bpt_node(T)                 prv;                                          \
00676   t_bpt_node(T)                 nxt;                                          \
00677 }                               __attribute__((packed)) t_bpt_head_##T;       
00678 
00679 #define         bpt_make_protos(T)                                            \
00680                                                                               \
00681 int                     bpt_list_##T(t_bpt(T)                   *bpt,         \
00682                                      t_bpt_imm(T)               *node,        \
00683                                      t_bpt_entry(T)             *entry,       \
00684                                      t_bpt_opts                 opts);        \
00685                                                                               \
00686 int                     bpt_check_unused_##T(t_bpt(T)           *bpt,         \
00687                                              t_bpt_unused(T)    *unused,      \
00688                                              t_bpt_opts         opts);        \
00689                                                                               \
00690 int                     bpt_first_entry_##T(t_bpt(T)            *bpt,         \
00691                                             t_bpt_imm(T)        *node,        \
00692                                             t_bpt_ndi(T)        *first);      \
00693                                                                               \
00694 int                     bpt_prev_entry_##T(t_bpt(T)             *bpt,         \
00695                                            t_bpt_entry(T)       current,      \
00696                                            t_bpt_entry(T)       *previous,    \
00697                                            t_bpt_opts           opts);        \
00698                                                                               \
00699 int                     bpt_next_entry_##T(t_bpt(T)             *bpt,         \
00700                                            t_bpt_entry(T)       current,      \
00701                                            t_bpt_entry(T)       *next,        \
00702                                            t_bpt_opts           opts);        \
00703                                                                               \
00704 int                     bpt_last_entry_##T(t_bpt(T)             *bpt,         \
00705                                            t_bpt_imm(T)         *node,        \
00706                                            t_bpt_ndi(T)         *last);       \
00707                                                                               \
00708 void                    bpt_reinit_entries_##T(t_bpt(T)         *bpt,         \
00709                                                t_bpt_imm(T)     *node);       \
00710                                                                               \
00711 void                    bpt_make_node_##T(t_bpt(T)              *bpt,         \
00712                                           t_bpt_imm(T)          *node,        \
00713                                           t_bpt_type            type,         \
00714                                           t_bpt_node(T)         parent);      \
00715                                                                               \
00716 void                    bpt_key_##T(t_bpt(T)                    *bpt,         \
00717                                     t_bpt_imm(T)                *node,        \
00718                                     t_bpt_key(T)                *key);        \
00719                                                                               \
00720                                                                               \
00721 int                     bpt_ndi_##T(t_bpt(T)                    *bpt,         \
00722                                     t_bpt_imm(T)                *node,        \
00723                                     t_bpt_addr(T)               value,        \
00724                                     t_bpt_ndi(T)                *ndi);        \
00725                                                                               \
00726 int                     bpt_update_node_##T(t_bpt(T)            *bpt,         \
00727                                             t_bpt_imm(T)        *node,        \
00728                                             t_bpt_node(T)       addr,         \
00729                                             t_bpt_key(T)        key,          \
00730                                             t_bpt_opts          opts);        \
00731                                                                               \
00732 void                    bpt_update_parent_##T(t_bpt(T)          *bpt,         \
00733                                               t_bpt_imm(T)      *node);       \
00734                                                                               \
00735 int                     bpt_update_##T(t_bpt(T)                 *bpt,         \
00736                                        t_bpt_imm(T)             *node,        \
00737                                        t_bpt_opts               opts);        \
00738                                                                               \
00739 int                     bpt_linear_search_##T(t_bpt(T)          *bpt,         \
00740                                               t_bpt_imm(T)      *node,        \
00741                                               t_bpt_key(T)      key,          \
00742                                               t_bpt_ndi(T)      *ndi,         \
00743                                               t_bpt_opts        opts);        \
00744                                                                               \
00745 int                     bpt_dichotomic_search_##T(t_bpt(T)      *bpt,         \
00746                                                   t_bpt_imm(T)  *node,        \
00747                                                   t_bpt_key(T)  key,          \
00748                                                   t_bpt_ndi(T)  *ndi,         \
00749                                                   t_bpt_opts    opts);        \
00750                                                                               \
00751 int                     bpt_search_entry_##T(t_bpt(T)           *bpt,         \
00752                                              t_bpt_imm(T)       *node,        \
00753                                              t_bpt_key(T)       key,          \
00754                                              t_bpt_ndi(T)       *ndi,         \
00755                                              t_bpt_opts         opts);        \
00756                                                                               \
00757 int                     bpt_search_leaf_##T(t_bpt(T)            *bpt,         \
00758                                             t_bpt_imm(T)        *node,        \
00759                                             t_bpt_node(T)       *leaf,        \
00760                                             t_bpt_key(T)        key);         \
00761                                                                               \
00762 int                     bpt_search_##T(t_bpt(T)                 *bpt,         \
00763                                        t_bpt_key(T)             key,          \
00764                                        t_bpt_entry(T)           *entry);      \
00765                                                                               \
00766 int                     bpt_collide_next_##T(t_bpt(T)           *bpt,         \
00767                                              t_bpt_key(T)       key,          \
00768                                              t_bpt_entry(T)     *entry);      \
00769                                                                               \
00770 int                     bpt_collide_search_##T(t_bpt(T)         *bpt,         \
00771                                                t_bpt_key(T)     key,          \
00772                                                t_bpt_addr(T)    value,        \
00773                                                t_bpt_entry(T)   *entry);      \
00774                                                                               \
00775 int                     bpt_check_collide_##T(t_bpt(T)          *bpt,         \
00776                                               t_bpt_imm(T)      *node1,       \
00777                                               t_bpt_key(T)      key,          \
00778                                               t_bpt_addr(T)     value);       \
00779                                                                               \
00780 t_bpt_ndi(T)            bpt_node_size_##T(t_bpt(T)              *bpt,         \
00781                                           t_bpt_imm(T)          *node);       \
00782                                                                               \
00783 void                    bpt_simplify_##T(t_bpt(T)               *bpt,         \
00784                                          t_bpt_imm(T)           *node,        \
00785                                          t_bpt_unused(T)        *unused);     \
00786                                                                               \
00787 int                     bpt_balancein_1_##T(t_bpt(T)            *bpt,         \
00788                                             t_bpt_imm(T)        *node1,       \
00789                                             t_bpt_imm(T)        *node2,       \
00790                                             t_bpt_cbctx(T)      *cbctx,       \
00791                                             t_bpt_entry(T)      prev,         \
00792                                             t_bpt_unused(T)     *unused);     \
00793                                                                               \
00794 int                     bpt_balancein_2_##T(t_bpt(T)            *bpt,         \
00795                                             t_bpt_imm(T)        *node1,       \
00796                                             t_bpt_imm(T)        *node2,       \
00797                                             t_bpt_cbctx(T)      *cbctx,       \
00798                                             t_bpt_entry(T)      prev,         \
00799                                             t_bpt_unused(T)     *unused);     \
00800                                                                               \
00801 int                     bpt_balancein_3_##T(t_bpt(T)            *bpt,         \
00802                                             t_bpt_imm(T)        *node2,       \
00803                                             t_bpt_imm(T)        *node1,       \
00804                                             t_bpt_cbctx(T)      *cbctx,       \
00805                                             t_bpt_entry(T)      prev,         \
00806                                             t_bpt_unused(T)     *unused);     \
00807                                                                               \
00808 int                     bpt_balancein_4_##T(t_bpt(T)            *bpt,         \
00809                                             t_bpt_imm(T)        *node2,       \
00810                                             t_bpt_imm(T)        *node1,       \
00811                                             t_bpt_cbctx(T)      *cbctx,       \
00812                                             t_bpt_entry(T)      prev,         \
00813                                             t_bpt_unused(T)     *unused);     \
00814                                                                               \
00815 int                     bpt_delete_##T(t_bpt(T)                 *bpt,         \
00816                                        t_bpt_entry(T)           entry,        \
00817                                        t_bpt_cbctx(T)           *cbctx,       \
00818                                        t_bpt_unused(T)          *unused);     \
00819                                                                               \
00820 int                     bpt_remove_##T(t_bpt(T)                 *bpt,         \
00821                                        t_bpt_key(T)             key,          \
00822                                        t_bpt_unused(T)          *unused);     \
00823                                                                               \
00824 int                     bpt_collide_remove_##T(t_bpt(T)         *bpt,         \
00825                                                t_bpt_entry(T)   entry,        \
00826                                                t_bpt_unused(T)  *unused);     \
00827                                                                               \
00828 int                     bpt_modify_##T(t_bpt(T)                 *bpt,         \
00829                                        t_bpt_key(T)             key,          \
00830                                        t_bpt_lfentry(T)         *lfentry,     \
00831                                        t_bpt_unused(T)          *unused);     \
00832                                                                               \
00833 int                     bpt_collide_modify_##T(t_bpt(T)         *bpt,         \
00834                                                t_bpt_entry(T)   entry,        \
00835                                                t_bpt_lfentry(T) *lfentry,     \
00836                                                t_bpt_unused(T)  *unused);     \
00837                                                                               \
00838 void                    bpt_insert_head_##T(t_bpt(T)            *bpt,         \
00839                                             t_bpt_imm(T)        *node1,       \
00840                                             t_bpt_imm(T)        *node2);      \
00841                                                                               \
00842 void                    bpt_insert_tail_##T(t_bpt(T)            *bpt,         \
00843                                             t_bpt_imm(T)        *node1,       \
00844                                             t_bpt_imm(T)        *node2);      \
00845                                                                               \
00846 void                    bpt_shift_sort_##T(t_bpt(T)             *bpt,         \
00847                                            t_bpt_imm(T)         *node);       \
00848                                                                               \
00849 void                    bpt_insert_sort_##T(t_bpt(T)            *bpt,         \
00850                                             t_bpt_imm(T)        *node,        \
00851                                             t_bpt_key(T)        key,          \
00852                                             t_bpt_addr(T)       value,        \
00853                                             t_bpt_ndi(T)        *ndi,         \
00854                                             t_bpt_opts          opts);        \
00855                                                                               \
00856 void                    bpt_new_root_##T(t_bpt(T)               *bpt,         \
00857                                          t_bpt_imm(T)           *node1,       \
00858                                          t_bpt_imm(T)           *node2,       \
00859                                          t_bpt_unused(T)        *unused);     \
00860                                                                               \
00861 int                     bpt_balanceout_##T(t_bpt(T)             *bpt,         \
00862                                            t_bpt_imm(T)         *node1,       \
00863                                            t_bpt_imm(T)         *node2,       \
00864                                            void                 *entry,       \
00865                                            t_bpt_cbctx(T)       *cbctx);      \
00866                                                                               \
00867 int                     bpt_split_node_##T(t_bpt(T)             *bpt,         \
00868                                            t_bpt_imm(T)         *node1,       \
00869                                            void                 *entry,       \
00870                                            t_bpt_cbctx(T)       *cbctx,       \
00871                                            t_bpt_unused(T)      *unused);     \
00872                                                                               \
00873 int                     bpt_insert_##T(t_bpt(T)                 *bpt,         \
00874                                        t_bpt_imm(T)             *node,        \
00875                                        void                     *entry,       \
00876                                        t_bpt_cbctx(T)           *cbctx,       \
00877                                        t_bpt_unused(T)          *unused);     \
00878                                                                               \
00879 int                     bpt_add_##T(t_bpt(T)                    *bpt,         \
00880                                     t_bpt_lfentry(T)            *lfentry,     \
00881                                     t_bpt_unused(T)             *unused);     \
00882                                                                               \
00883 int                     bpt_init_##T(t_bpt(T)                   *bpt,         \
00884                                      t_bpt_blksz(T)             blksz,        \
00885                                      t_bpt_addr(T)              unusedvalue,  \
00886                                      t_bpt_flags                flags,        \
00887                                      t_bpt_load_fn(T)           load,         \
00888                                      t_bpt_unload_fn(T)         unload,       \
00889                                      t_bpt_callback_fn(T)       callback,     \
00890                                      t_bpt_unused(T)            *unused);     \
00891                                                                               \
00892 int                     bpt_clean_node_##T(t_bpt(T)             *bpt,         \
00893                                            t_bpt_imm(T)         *node,        \
00894                                            t_bpt_unused(T)      *unused);     \
00895                                                                               \
00896 int                     bpt_clean_##T(t_bpt(T)                  *bpt,         \
00897                                       t_bpt_unused(T)           *unused);     
00898 
00899 #define         bpt_make_functions(T, _key_, _value_)                         \
00900                                                                               \
00901 /*                                                                            \
00902  * this function finds the head/tail entry in the leaf linked list            \
00903  */                                                                           \
00904                                                                               \
00905 int                     bpt_list_##T(t_bpt(T)                   *bpt,         \
00906                                      t_bpt_imm(T)               *node,        \
00907                                      t_bpt_entry(T)             *entry,       \
00908                                      t_bpt_opts                 opts)         \
00909 {                                                                             \
00910   t_bpt_head(T)         *head = BPT_HEAD(T, node);                            \
00911   t_bpt_imm(T)          child;                                                \
00912   t_bpt_ndi(T)          i;                                                    \
00913                                                                               \
00914   if (head->type == BPT_TYPE_LEAF)                                            \
00915     {                                                                         \
00916       entry->node = node->addr;                                               \
00917       if (opts & BPT_OPT_HEAD)                                                \
00918         {                                                                     \
00919           if (bpt_first_entry(T, bpt, node, &entry->ndi) != 0)                \
00920             return (-1);                                                      \
00921         }                                                                     \
00922       else if (opts & BPT_OPT_TAIL)                                           \
00923         {                                                                     \
00924           if (bpt_last_entry(T, bpt, node, &entry->ndi) != 0)                 \
00925             return (-1);                                                      \
00926         }                                                                     \
00927       else                                                                    \
00928         return (-1);                                                          \
00929                                                                               \
00930       return (0);                                                             \
00931     }                                                                         \
00932                                                                               \
00933   if (opts & BPT_OPT_HEAD)                                                    \
00934     {                                                                         \
00935       if (bpt_first_entry(T, bpt, node, &i) != 0)                             \
00936         return (-1);                                                          \
00937     }                                                                         \
00938   else if (opts & BPT_OPT_TAIL)                                               \
00939     {                                                                         \
00940       if (bpt_last_entry(T, bpt, node, &i) != 0)                              \
00941         return (-1);                                                          \
00942     }                                                                         \
00943   else                                                                        \
00944     return (-1);                                                              \
00945                                                                               \
00946   BPT_LOAD(bpt, &child, BPT_GET_ENTRY(T, node, i, _value_));                  \
00947                                                                               \
00948   if (bpt_list(T, bpt, &child, entry, opts) != 0)                             \
00949     {                                                                         \
00950       BPT_UNLOAD(bpt, &child);                                                \
00951       return (-1);                                                            \
00952     }                                                                         \
00953                                                                               \
00954   BPT_UNLOAD(bpt, &child);                                                    \
00955                                                                               \
00956   return (0);                                                                 \
00957 }                                                                             \
00958                                                                               \
00959 /*                                                                            \
00960  * this function checks whether the unused array was correctly built          \
00961  */                                                                           \
00962                                                                               \
00963 int                     bpt_check_unused_##T(t_bpt(T)           *bpt,         \
00964                                              t_bpt_unused(T)    *unused,      \
00965                                              t_bpt_opts         opts)         \
00966 {                                                                             \
00967   if (opts == BPT_OPT_INIT)                                                   \
00968     {                                                                         \
00969       if (unused->index >= (BPT_INIT_ALLOC() - 1))                            \
00970         return (0);                                                           \
00971     }                                                                         \
00972   else if (opts == BPT_OPT_ADD)                                               \
00973     {                                                                         \
00974       if (unused->index >= (BPT_ADD_ALLOC(bpt) - 1))                          \
00975         return (0);                                                           \
00976     }                                                                         \
00977   else if (opts == BPT_OPT_MODIFY)                                            \
00978     {                                                                         \
00979       if (unused->index >= (BPT_MODIFY_ALLOC(bpt) - 1))                       \
00980         return (0);                                                           \
00981     }                                                                         \
00982   else if (opts == BPT_OPT_REMOVE)                                            \
00983     {                                                                         \
00984       if (unused->index >= (BPT_REMOVE_ALLOC(bpt) - 1))                       \
00985         return (0);                                                           \
00986     }                                                                         \
00987   else if (opts == BPT_OPT_CLEAN)                                             \
00988     {                                                                         \
00989       if (unused->index >= (BPT_CLEAN_ALLOC(bpt) - 1))                        \
00990         return (0);                                                           \
00991     }                                                                         \
00992                                                                               \
00993   return (-1);                                                                \
00994 }                                                                             \
00995                                                                               \
00996 /*                                                                            \
00997  * this functions returns the first entry of the node                         \
00998  */                                                                           \
00999                                                                               \
01000 int                     bpt_first_entry_##T(t_bpt(T)            *bpt,         \
01001                                             t_bpt_imm(T)        *node,        \
01002                                             t_bpt_ndi(T)        *first)       \
01003 {                                                                             \
01004   t_bpt_ndi(T)          nkeys = BPT_NKEYS(T, bpt, node);                      \
01005   t_bpt_ndi(T)          i;                                                    \
01006                                                                               \
01007   for (i = 0; i < nkeys; i++)                                                 \
01008     if (BPT_GET_ENTRY(T, node, i, _value_) != bpt->unused)                    \
01009       {                                                                       \
01010         *first = i;                                                           \
01011         return (0);                                                           \
01012       }                                                                       \
01013                                                                               \
01014   return (-1);                                                                \
01015 }                                                                             \
01016                                                                               \
01017 /*                                                                            \
01018  * this function returns the previous entry                                   \
01019  */                                                                           \
01020                                                                               \
01021 int                     bpt_prev_entry_##T(t_bpt(T)             *bpt,         \
01022                                            t_bpt_entry(T)       current,      \
01023                                            t_bpt_entry(T)       *previous,    \
01024                                            t_bpt_opts           opts)         \
01025 {                                                                             \
01026   if (opts & BPT_OPT_NODE)                                                    \
01027     {                                                                         \
01028       t_bpt_head(T)     *head;                                                \
01029       t_bpt_ndi(T)      nkeys;                                                \
01030       t_bpt_imm(T)      node;                                                 \
01031       t_bpt_ndi(T)      i;                                                    \
01032                                                                               \
01033       if ((current.ndi - 1) < 0)                                              \
01034         return (-1);                                                          \
01035                                                                               \
01036       BPT_LOAD(bpt, &node, current.node);                                     \
01037       head = BPT_HEAD(T, &node);                                              \
01038       nkeys = BPT_NKEYS(T, bpt, &node);                                       \
01039                                                                               \
01040       if (current.ndi >= nkeys)                                               \
01041         {                                                                     \
01042           BPT_UNLOAD(bpt, &node);                                             \
01043           return (-1);                                                        \
01044         }                                                                     \
01045                                                                               \
01046       for (i = current.ndi - 1; i >= 0; i--)                                  \
01047         if (BPT_GET_ENTRY(T, &node, i, _value_) != bpt->unused)               \
01048           {                                                                   \
01049             previous->node = node.addr;                                       \
01050             previous->ndi = i;                                                \
01051                                                                               \
01052             BPT_UNLOAD(bpt, &node);                                           \
01053                                                                               \
01054             return (0);                                                       \
01055           }                                                                   \
01056                                                                               \
01057       BPT_UNLOAD(bpt, &node);                                                 \
01058     }                                                                         \
01059                                                                               \
01060   if (opts & BPT_OPT_TREE)                                                    \
01061     {                                                                         \
01062       t_bpt_head(T)     *head;                                                \
01063       t_bpt_imm(T)      node;                                                 \
01064       t_bpt_imm(T)      prev;                                                 \
01065                                                                               \
01066       if (bpt_prev_entry(T, bpt, current, previous, BPT_OPT_NODE) == 0)       \
01067         return (0);                                                           \
01068                                                                               \
01069       do                                                                      \
01070         {                                                                     \
01071           BPT_LOAD(bpt, &node, current.node);                                 \
01072           head = BPT_HEAD(T, &node);                                          \
01073                                                                               \
01074           if (head->prv == bpt->unused)                                       \
01075             {                                                                 \
01076               BPT_UNLOAD(bpt, &node);                                         \
01077               return (-1);                                                    \
01078             }                                                                 \
01079                                                                               \
01080           BPT_LOAD(bpt, &prev, head->prv);                                    \
01081           BPT_UNLOAD(bpt, &node);                                             \
01082                                                                               \
01083           previous->node = prev.addr;                                         \
01084           if (bpt_last_entry(T, bpt, &prev, &previous->ndi) == 0)             \
01085             {                                                                 \
01086               BPT_UNLOAD(bpt, &prev);                                         \
01087               return (0);                                                     \
01088             }                                                                 \
01089                                                                               \
01090           current.node = prev.addr;                                           \
01091                                                                               \
01092           BPT_UNLOAD(bpt, &prev);                                             \
01093         } while (1);                                                          \
01094                                                                               \
01095       return (0);                                                             \
01096     }                                                                         \
01097                                                                               \
01098   return (-1);                                                                \
01099 }                                                                             \
01100                                                                               \
01101 /*                                                                            \
01102  * this function returns the next entry                                       \
01103  */                                                                           \
01104                                                                               \
01105 int                     bpt_next_entry_##T(t_bpt(T)             *bpt,         \
01106                                            t_bpt_entry(T)       current,      \
01107                                            t_bpt_entry(T)       *next,        \
01108                                            t_bpt_opts           opts)         \
01109 {                                                                             \
01110   if (opts & BPT_OPT_NODE)                                                    \
01111     {                                                                         \
01112       t_bpt_head(T)     *head;                                                \
01113       t_bpt_ndi(T)      nkeys;                                                \
01114       t_bpt_imm(T)      node;                                                 \
01115       t_bpt_ndi(T)      i;                                                    \
01116                                                                               \
01117       BPT_LOAD(bpt, &node, current.node);                                     \
01118       head = BPT_HEAD(T, &node);                                              \
01119       nkeys = BPT_NKEYS(T, bpt, &node);                                       \
01120                                                                               \
01121       if ((current.ndi >= nkeys) ||                                           \
01122           ((current.ndi + 1) >= nkeys))                                       \
01123         {                                                                     \
01124           BPT_UNLOAD(bpt, &node);                                             \
01125           return (-1);                                                        \
01126         }                                                                     \
01127                                                                               \
01128       for (i = current.ndi + 1; i < nkeys; i++)                               \
01129         if (BPT_GET_ENTRY(T, &node, i, _value_) != bpt->unused)               \
01130           {                                                                   \
01131             next->node = node.addr;                                           \
01132             next->ndi = i;                                                    \
01133                                                                               \
01134             BPT_UNLOAD(bpt, &node);                                           \
01135                                                                               \
01136             return (0);                                                       \
01137           }                                                                   \
01138                                                                               \
01139       BPT_UNLOAD(bpt, &node);                                                 \
01140     }                                                                         \
01141                                                                               \
01142   if (opts & BPT_OPT_TREE)                                                    \
01143     {                                                                         \
01144       t_bpt_head(T)     *head;                                                \
01145       t_bpt_imm(T)      node;                                                 \
01146       t_bpt_imm(T)      nxt;                                                  \
01147                                                                               \
01148       if (bpt_next_entry(T, bpt, current, next, BPT_OPT_NODE) == 0)           \
01149         return (0);                                                           \
01150                                                                               \
01151       do                                                                      \
01152         {                                                                     \
01153           BPT_LOAD(bpt, &node, current.node);                                 \
01154           head = BPT_HEAD(T, &node);                                          \
01155                                                                               \
01156           if (head->nxt == bpt->unused)                                       \
01157             {                                                                 \
01158               BPT_UNLOAD(bpt, &node);                                         \
01159               return (-1);                                                    \
01160             }                                                                 \
01161                                                                               \
01162           BPT_LOAD(bpt, &nxt, head->nxt);                                     \
01163           BPT_UNLOAD(bpt, &node);                                             \
01164                                                                               \
01165           next->node = nxt.addr;                                              \
01166           if (bpt_first_entry(T, bpt, &nxt, &next->ndi) == 0)                 \
01167             {                                                                 \
01168               BPT_UNLOAD(bpt, &nxt);                                          \
01169               return (0);                                                     \
01170             }                                                                 \
01171                                                                               \
01172           current.node = nxt.addr;                                            \
01173                                                                               \
01174           BPT_UNLOAD(bpt, &nxt);                                              \
01175         } while (1);                                                          \
01176                                                                               \
01177       return (0);                                                             \
01178     }                                                                         \
01179                                                                               \
01180   return (-1);                                                                \
01181 }                                                                             \
01182                                                                               \
01183 /*                                                                            \
01184  * this function returns the last entry of the node                           \
01185  */                                                                           \
01186                                                                               \
01187 int                     bpt_last_entry_##T(t_bpt(T)             *bpt,         \
01188                                            t_bpt_imm(T)         *node,        \
01189                                            t_bpt_ndi(T)         *last)        \
01190 {                                                                             \
01191   if ((*last = bpt_node_size(T, bpt, node) - 1) < 0)                          \
01192     return (-1);                                                              \
01193                                                                               \
01194   return (0);                                                                 \
01195 }                                                                             \
01196                                                                               \
01197 /*                                                                            \
01198  * this function simply reinitializes entries                                 \
01199  */                                                                           \
01200                                                                               \
01201 void                    bpt_reinit_entries_##T(t_bpt(T)         *bpt,         \
01202                                                t_bpt_imm(T)     *node)        \
01203 {                                                                             \
01204   t_bpt_ndi(T)          nkeys = BPT_NKEYS(T, bpt, node);                      \
01205   t_bpt_ndi(T)          i;                                                    \
01206                                                                               \
01207   for (i = 0; i < nkeys; i++)                                                 \
01208     {                                                                         \
01209       BPT_INIT_ENTRY(T, node, i);                                             \
01210       BPT_SET_ENTRY(T, node, i, _value_, bpt->unused);                        \
01211     }                                                                         \
01212 }                                                                             \
01213                                                                               \
01214 /*                                                                            \
01215  * this function creates and initializes a node                               \
01216  */                                                                           \
01217                                                                               \
01218 void                    bpt_make_node_##T(t_bpt(T)              *bpt,         \
01219                                           t_bpt_imm(T)          *node,        \
01220                                           t_bpt_type            type,         \
01221                                           t_bpt_node(T)         parent)       \
01222 {                                                                             \
01223   t_bpt_head(T)         *head = BPT_HEAD(T, node);                            \
01224   t_bpt_ndi(T)          nkeys;                                                \
01225   t_bpt_ndi(T)          i;                                                    \
01226                                                                               \
01227   nkeys = type == BPT_TYPE_INTERNAL ? bpt->nikeys : bpt->nlkeys;              \
01228                                                                               \
01229   head->type = type;                                                          \
01230   head->parent = parent;                                                      \
01231   head->prv = bpt->unused;                                                    \
01232   head->nxt = bpt->unused;                                                    \
01233                                                                               \
01234   for (i = 0; i < nkeys; i++)                                                 \
01235     {                                                                         \
01236       BPT_INIT_ENTRY(T, node, i);                                             \
01237       BPT_SET_ENTRY(T, node, i, _value_, bpt->unused);                        \
01238     }                                                                         \
01239 }                                                                             \
01240                                                                               \
01241 /*                                                                            \
01242  * this function looks for the highest key present in a node                  \
01243  */                                                                           \
01244                                                                               \
01245 void                    bpt_key_##T(t_bpt(T)                    *bpt,         \
01246                                     t_bpt_imm(T)                *node,        \
01247                                     t_bpt_key(T)                *key)         \
01248 {                                                                             \
01249   t_bpt_ndi(T)          ndi;                                                  \
01250                                                                               \
01251   bpt_last_entry(T, bpt, node, &ndi);                                         \
01252                                                                               \
01253   *key = BPT_GET_ENTRY(T, node, ndi, _key_);                                  \
01254 }                                                                             \
01255                                                                               \
01256 /*                                                                            \
01257  * this function tries to find the more appropriate entry that matchs         \
01258  * with the parameter value. finally the function returns the                 \
01259  * node index.                                                                \
01260  *                                                                            \
01261  * the value field is used because two entries cannot have the same           \
01262  * value field but can have the same key: collision.                          \
01263  *                                                                            \
01264  * so the value field is used to retrieve an entry among collisions.          \
01265  */                                                                           \
01266                                                                               \
01267 int                     bpt_ndi_##T(t_bpt(T)                    *bpt,         \
01268                                     t_bpt_imm(T)                *node,        \
01269                                     t_bpt_addr(T)               value,        \
01270                                     t_bpt_ndi(T)                *ndi)         \
01271 {                                                                             \
01272   t_bpt_ndi(T)          nkeys = BPT_NKEYS(T, bpt, node);                      \
01273   t_bpt_ndi(T)          i;                                                    \
01274                                                                               \
01275   for (i = 0; (i < nkeys) &&                                                  \
01276          (BPT_GET_ENTRY(T, node, i, _value_) != bpt->unused);                 \
01277        i++)                                                                   \
01278     if (BPT_GET_ENTRY(T, node, i, _value_) == value)                          \
01279       {                                                                       \
01280         *ndi = i;                                                             \
01281         return (0);                                                           \
01282       }                                                                       \
01283                                                                               \
01284   return (-1);                                                                \
01285 }                                                                             \
01286                                                                               \
01287 /*                                                                            \
01288  * this function updates the key field                                        \
01289  */                                                                           \
01290                                                                               \
01291 int                     bpt_update_node_##T(t_bpt(T)            *bpt,         \
01292                                             t_bpt_imm(T)        *node,        \
01293                                             t_bpt_node(T)       addr,         \
01294                                             t_bpt_key(T)        key,          \
01295                                             t_bpt_opts          opts)         \
01296 {                                                                             \
01297   t_bpt_head(T)         *head = BPT_HEAD(T, node);                            \
01298   t_bpt_key(T)          oldk = 0;                                             \
01299   t_bpt_key(T)          newk = 0;                                             \
01300   t_bpt_imm(T)          parent;                                               \
01301   t_bpt_ndi(T)          ndi;                                                  \
01302                                                                               \
01303   if (bpt_ndi(T, bpt, node, addr, &ndi) != 0)                                 \
01304     {                                                                         \
01305       bpt_debug("[bptd] panic: this case should never happen\n");             \
01306       return (-1);                                                            \
01307     }                                                                         \
01308                                                                               \
01309   if (opts & BPT_OPT_KEY)                                                     \
01310     {                                                                         \
01311       bpt_key(T, bpt, node, &oldk);                                           \
01312       BPT_SET_ENTRY(T, node, ndi, _key_, key);                                \
01313     }                                                                         \
01314                                                                               \
01315   if (head->parent == bpt->unused)                                            \
01316     return (0);                                                               \
01317                                                                               \
01318   bpt_key(T, bpt, node, &newk);                                               \
01319                                                                               \
01320   if (!(opts & BPT_OPT_KEY))                                                  \
01321     oldk = newk;                                                              \
01322                                                                               \
01323   if (newk == oldk)                                                           \
01324     return (0);                                                               \
01325                                                                               \
01326   BPT_LOAD(bpt, &parent, head->parent);                                       \
01327                                                                               \
01328   if (bpt_update_node(T, bpt, &parent, node->addr, newk, opts) != 0)          \
01329     {                                                                         \
01330       BPT_UNLOAD(bpt, &parent);                                               \
01331       return (-1);                                                            \
01332     }                                                                         \
01333                                                                               \
01334   BPT_UNLOAD(bpt, &parent);                                                   \
01335                                                                               \
01336   return (0);                                                                 \
01337 }                                                                             \
01338                                                                               \
01339 /*                                                                            \
01340  * this function updates the parent field of each children                    \
01341  */                                                                           \
01342                                                                               \
01343 void                    bpt_update_parent_##T(t_bpt(T)          *bpt,         \
01344                                               t_bpt_imm(T)      *node)        \
01345 {                                                                             \
01346   t_bpt_ndi(T)          nkeys = BPT_NKEYS(T, bpt, node);                      \
01347   t_bpt_ndi(T)          i;                                                    \
01348                                                                               \
01349   for (i = 0; (i < nkeys) &&                                                  \
01350          (BPT_GET_ENTRY(T, node, i, _value_) != bpt->unused);                 \
01351        i++)                                                                   \
01352     {                                                                         \
01353       t_bpt_head(T)     *chead;                                               \
01354       t_bpt_imm(T)      child;                                                \
01355                                                                               \
01356       BPT_LOAD(bpt, &child, BPT_GET_ENTRY(T, node, i, _value_));              \
01357       chead = BPT_HEAD(T, &child);                                            \
01358       chead->parent = node->addr;                                             \
01359       BPT_UNLOAD(bpt, &child);                                                \
01360     }                                                                         \
01361 }                                                                             \
01362                                                                               \
01363 /*                                                                            \
01364  * this function recursively updates the parent node                          \
01365  */                                                                           \
01366                                                                               \
01367 int                     bpt_update_##T(t_bpt(T)                 *bpt,         \
01368                                        t_bpt_imm(T)             *node,        \
01369                                        t_bpt_opts               opts)         \
01370 {                                                                             \
01371   t_bpt_head(T)         *head = BPT_HEAD(T, node);                            \
01372   t_bpt_imm(T)          parent;                                               \
01373   t_bpt_key(T)          key;                                                  \
01374                                                                               \
01375   if (opts & BPT_OPT_PARENT)                                                  \
01376     {                                                                         \
01377       bpt_update_parent(T, bpt, node);                                        \
01378       opts &= ~BPT_OPT_PARENT;                                                \
01379     }                                                                         \
01380                                                                               \
01381   if (head->parent == bpt->unused)                                            \
01382     return (0);                                                               \
01383                                                                               \
01384   if (opts == BPT_OPT_ZERO)                                                   \
01385     return (0);                                                               \
01386                                                                               \
01387   bpt_key(T, bpt, node, &key);                                                \
01388                                                                               \
01389   BPT_LOAD(bpt, &parent, head->parent);                                       \
01390                                                                               \
01391   if (bpt_update_node(T, bpt, &parent, node->addr, key, opts) != 0)           \
01392     {                                                                         \
01393       BPT_UNLOAD(bpt, &parent);                                               \
01394       return (-1);                                                            \
01395     }                                                                         \
01396                                                                               \
01397   BPT_UNLOAD(bpt, &parent);                                                   \
01398                                                                               \
01399   return (0);                                                                 \
01400 }                                                                             \
01401                                                                               \
01402 /*                                                                            \
01403  * this function linearly searchs a key                                       \
01404  */                                                                           \
01405                                                                               \
01406 int                     bpt_linear_search_##T(t_bpt(T)          *bpt,         \
01407                                               t_bpt_imm(T)      *node,        \
01408                                               t_bpt_key(T)      key,          \
01409                                               t_bpt_ndi(T)      *ndi,         \
01410                                               t_bpt_opts        opts)         \
01411 {                                                                             \
01412   t_bpt_ndi(T)          nkeys = BPT_NKEYS(T, bpt, node);                      \
01413   t_bpt_ndi(T)          i;                                                    \
01414                                                                               \
01415   for (i = 0; (i < nkeys) &&                                                  \
01416          (BPT_GET_ENTRY(T, node, i, _value_) != bpt->unused);                 \
01417        i++)                                                                   \
01418     {                                                                         \
01419       if (opts & BPT_OPT_PARTIAL)                                             \
01420         if ((key <= BPT_GET_ENTRY(T, node, i, _key_)) ||                      \
01421             ((i + 1) >= nkeys) ||                                             \
01422             (BPT_GET_ENTRY(T, node, i + 1, _value_) == bpt->unused))          \
01423           {                                                                   \
01424             *ndi = i;                                                         \
01425             return (0);                                                       \
01426           }                                                                   \
01427                                                                               \
01428       if (opts & BPT_OPT_PERFECT)                                             \
01429         if (key == BPT_GET_ENTRY(T, node, i, _key_))                          \
01430           {                                                                   \
01431             *ndi = i;                                                         \
01432             return (0);                                                       \
01433           }                                                                   \
01434     }                                                                         \
01435                                                                               \
01436   return (-1);                                                                \
01437 }                                                                             \
01438                                                                               \
01439 /*                                                                            \
01440  * this function looks for a key using a dichotomic search                    \
01441  */                                                                           \
01442                                                                               \
01443 int                     bpt_dichotomic_search_##T(t_bpt(T)      *bpt,         \
01444                                                   t_bpt_imm(T)  *node,        \
01445                                                   t_bpt_key(T)  key,          \
01446                                                   t_bpt_ndi(T)  *ndi,         \
01447                                                   t_bpt_opts    opts)         \
01448 {                                                                             \
01449   t_bpt_ndi(T)          j = BPT_NKEYS(T, bpt, node) - 1;                      \
01450   t_bpt_ndi(T)          i = 0;                                                \
01451                                                                               \
01452   if (BPT_GET_ENTRY(T, node, 0, _value_) == bpt->unused)                      \
01453     {                                                                         \
01454       *ndi = 0;                                                               \
01455       return (opts & BPT_OPT_PARTIAL ? 0 : -1);                               \
01456     }                                                                         \
01457                                                                               \
01458   while (i <= j)                                                              \
01459     {                                                                         \
01460       t_bpt_ndi(T)      k = (i + j) / 2;                                      \
01461                                                                               \
01462       if (BPT_GET_ENTRY(T, node, k, _value_) == bpt->unused)                  \
01463         {                                                                     \
01464           j = k - 1;                                                          \
01465           continue;                                                           \
01466         }                                                                     \
01467                                                                               \
01468       if (opts & BPT_OPT_PERFECT)                                             \
01469         if (BPT_GET_ENTRY(T, node, k, _key_) == key)                          \
01470           {                                                                   \
01471             *ndi = k;                                                         \
01472             return (0);                                                       \
01473           }                                                                   \
01474                                                                               \
01475       if (opts & BPT_OPT_PARTIAL)                                             \
01476         if ((key <= BPT_GET_ENTRY(T, node, k, _key_)) &&                      \
01477             ((k == 0) ||                                                      \
01478              (key > BPT_GET_ENTRY(T, node, k - 1, _key_))))                   \
01479           {                                                                   \
01480             *ndi = k;                                                         \
01481             return (0);                                                       \
01482           }                                                                   \
01483                                                                               \
01484       if (key < BPT_GET_ENTRY(T, node, k, _key_))                             \
01485         j = k - 1;                                                            \
01486       else                                                                    \
01487         i = k + 1;                                                            \
01488     }                                                                         \
01489                                                                               \
01490   if (opts & BPT_OPT_PARTIAL)                                                 \
01491     {                                                                         \
01492       if (bpt_last_entry(T, bpt, node, ndi) != 0)                             \
01493         return (-1);                                                          \
01494                                                                               \
01495       return (0);                                                             \
01496     }                                                                         \
01497                                                                               \
01498   return (-1);                                                                \
01499 }                                                                             \
01500                                                                               \
01501 /*                                                                            \
01502  * this function is used to find an entry in a node.                          \
01503  * this function takes the choice of using either a linear or dichotomic      \
01504  * search depending of the flags.                                             \
01505  */                                                                           \
01506                                                                               \
01507 int                     bpt_search_entry_##T(t_bpt(T)           *bpt,         \
01508                                              t_bpt_imm(T)       *node,        \
01509                                              t_bpt_key(T)       key,          \
01510                                              t_bpt_ndi(T)       *ndi,         \
01511                                              t_bpt_opts         opts)         \
01512 {                                                                             \
01513   if (bpt->flags & BPT_FLAG_COLLIDE)                                          \
01514     return (bpt_linear_search(T, bpt, node, key, ndi, opts));                 \
01515   else                                                                        \
01516     return (bpt_dichotomic_search(T, bpt, node, key, ndi, opts));             \
01517 }                                                                             \
01518                                                                               \
01519 /*                                                                            \
01520  * this function looks for the leaf entry that theorically contains           \
01521  * the key                                                                    \
01522  */                                                                           \
01523                                                                               \
01524 int                     bpt_search_leaf_##T(t_bpt(T)            *bpt,         \
01525                                             t_bpt_imm(T)        *node,        \
01526                                             t_bpt_node(T)       *leaf,        \
01527                                             t_bpt_key(T)        key)          \
01528 {                                                                             \
01529   t_bpt_head(T)         *head = BPT_HEAD(T, node);                            \
01530   t_bpt_imm(T)          child;                                                \
01531   t_bpt_ndi(T)          ndi;                                                  \
01532                                                                               \
01533   if (head->type == BPT_TYPE_LEAF)                                            \
01534     {                                                                         \
01535       *leaf = node->addr;                                                     \
01536       return (0);                                                             \
01537     }                                                                         \
01538                                                                               \
01539   if (bpt_search_entry(T, bpt, node, key, &ndi, BPT_OPT_PARTIAL) != 0)        \
01540     return (-1);                                                              \
01541                                                                               \
01542   BPT_LOAD(bpt, &child, BPT_GET_ENTRY(T, node, ndi, _value_));                \
01543                                                                               \
01544   if (bpt_search_leaf(T, bpt, &child, leaf, key) != 0)                        \
01545     {                                                                         \
01546       BPT_UNLOAD(bpt, &child);                                                \
01547       return (-1);                                                            \
01548     }                                                                         \
01549                                                                               \
01550   BPT_UNLOAD(bpt, &child);                                                    \
01551                                                                               \
01552   return (0);                                                                 \
01553 }                                                                             \
01554                                                                               \
01555 /*                                                                            \
01556  * this function looks for a key and returns the address of the node and      \
01557  * the index of the entry containing this key.                                \
01558  *                                                                            \
01559  * be careful of not using this function with collisions because              \
01560  * the bpt_collide_search() function exists.                                  \
01561  */                                                                           \
01562                                                                               \
01563 int                     bpt_search_##T(t_bpt(T)                 *bpt,         \
01564                                        t_bpt_key(T)             key,          \
01565                                        t_bpt_entry(T)           *entry)       \
01566 {                                                                             \
01567   t_bpt_head(T)         *head;                                                \
01568   t_bpt_imm(T)          leaf;                                                 \
01569   t_bpt_imm(T)          root;                                                 \
01570                                                                               \
01571   BPT_LOAD(bpt, &root, BPT_GET_ROOT(bpt));                                    \
01572   head = BPT_HEAD(T, &root);                                                  \
01573                                                                               \
01574   if (bpt_search_leaf(T, bpt, &root, &entry->node, key) != 0)                 \
01575     {                                                                         \
01576       bpt_debug("[bptd] no leaf present in the tree\n");                      \
01577       BPT_UNLOAD(bpt, &root);                                                 \
01578       return (-1);                                                            \
01579     }                                                                         \
01580                                                                               \
01581   BPT_UNLOAD(bpt, &root);                                                     \
01582   BPT_LOAD(bpt, &leaf, entry->node);                                          \
01583   head = BPT_HEAD(T, &leaf);                                                  \
01584                                                                               \
01585   if (bpt_search_entry(T, bpt, &leaf, key, &entry->ndi,                       \
01586                        BPT_OPT_PERFECT) != 0)                                 \
01587     {                                                                         \
01588       bpt_debug("[bptd] cannot find the entry\n");                            \
01589       BPT_UNLOAD(bpt, &leaf);                                                 \
01590       return (-1);                                                            \
01591     }                                                                         \
01592                                                                               \
01593   BPT_UNLOAD(bpt, &leaf);                                                     \
01594                                                                               \
01595   return (0);                                                                 \
01596 }                                                                             \
01597                                                                               \
01598 /*                                                                            \
01599  * this function tries to find the next entry that collide with               \
01600  * the current one specified by the entry variable.                           \
01601  *                                                                            \
01602  * first try to find an entry with the same key in the current node. if no    \
01603  * one exists, look for in the next node because leaves are doubly linked.    \
01604  *                                                                            \
01605  * the function returns -1 if there is no other entry in collision            \
01606  */                                                                           \
01607                                                                               \
01608 int                     bpt_collide_next_##T(t_bpt(T)           *bpt,         \
01609                                              t_bpt_key(T)       key,          \
01610                                              t_bpt_entry(T)     *entry)       \
01611 {                                                                             \
01612   t_bpt_head(T)         *head;                                                \
01613   t_bpt_imm(T)          node;                                                 \
01614                                                                               \
01615   if (bpt_next_entry(T, bpt, *entry, entry, BPT_OPT_TREE) != 0)               \
01616     return (-1);                                                              \
01617                                                                               \
01618   BPT_LOAD(bpt, &node, entry->node);                                          \
01619   head = BPT_HEAD(T, &node);                                                  \
01620                                                                               \
01621   if (BPT_GET_ENTRY(T, &node, entry->ndi, _key_) != key)                      \
01622     {                                                                         \
01623       BPT_UNLOAD(bpt, &node);                                                 \
01624       return (-1);                                                            \
01625     }                                                                         \
01626                                                                               \
01627   BPT_UNLOAD(bpt, &node);                                                     \
01628                                                                               \
01629   return (0);                                                                 \
01630 }                                                                             \
01631                                                                               \
01632 /*                                                                            \
01633  * this function looks for an entry in collision                              \
01634  */                                                                           \
01635                                                                               \
01636 int                     bpt_collide_search_##T(t_bpt(T)         *bpt,         \
01637                                                t_bpt_key(T)     key,          \
01638                                                t_bpt_addr(T)    value,        \
01639                                                t_bpt_entry(T)   *entry)       \
01640 {                                                                             \
01641   t_bpt_head(T)         *head;                                                \
01642   t_bpt_imm(T)          node;                                                 \
01643                                                                               \
01644   if (bpt_search(T, bpt, key, entry) != 0)                                    \
01645     {                                                                         \
01646       bpt_debug("[bptd] cannot find the entry in collision\n");               \
01647       return (-1);                                                            \
01648     }                                                                         \
01649                                                                               \
01650   do                                                                          \
01651     {                                                                         \
01652       BPT_LOAD(bpt, &node, entry->node);                                      \
01653       head = BPT_HEAD(T, &node);                                              \
01654                                                                               \
01655       if ((BPT_GET_ENTRY(T, &node, entry->ndi, _key_) == key) &&              \
01656           (BPT_GET_ENTRY(T, &node, entry->ndi, _value_) == value))            \
01657         {                                                                     \
01658           BPT_UNLOAD(bpt, &node);                                             \
01659           return (0);                                                         \
01660         }                                                                     \
01661                                                                               \
01662       BPT_UNLOAD(bpt, &node);                                                 \
01663     } while (bpt_collide_next(T, bpt, key, entry) == 0);                      \
01664                                                                               \
01665   return (-1);                                                                \
01666 }                                                                             \
01667                                                                               \
01668 /*                                                                            \
01669  * this function checks wheter a full collision (key:value) exists            \
01670  */                                                                           \
01671                                                                               \
01672 int                     bpt_check_collide_##T(t_bpt(T)          *bpt,         \
01673                                               t_bpt_imm(T)      *node1,       \
01674                                               t_bpt_key(T)      key,          \
01675                                               t_bpt_addr(T)     value)        \
01676 {                                                                             \
01677   t_bpt_head(T)         *head2;                                               \
01678   t_bpt_imm(T)          node2;                                                \
01679   t_bpt_entry(T)        entry;                                                \
01680                                                                               \
01681   entry.node = node1->addr;                                                   \
01682   if (bpt_search_entry(T, bpt, node1, key, &entry.ndi,                        \
01683                        BPT_OPT_PERFECT) != 0)                                 \
01684     return (0);                                                               \
01685                                                                               \
01686   do                                                                          \
01687     {                                                                         \
01688       BPT_LOAD(bpt, &node2, entry.node);                                      \
01689       head2 = BPT_HEAD(T, &node2);                                            \
01690                                                                               \
01691       if ((BPT_GET_ENTRY(T, &node2, entry.ndi, _key_) == key) &&              \
01692           (BPT_GET_ENTRY(T, &node2, entry.ndi, _value_) == value))            \
01693         {                                                                     \
01694           BPT_UNLOAD(bpt, &node2);                                            \
01695           return (-1);                                                        \
01696         }                                                                     \
01697                                                                               \
01698       BPT_UNLOAD(bpt, &node2);                                                \
01699     } while (bpt_collide_next(T, bpt, key, &entry) == 0);                     \
01700                                                                               \
01701   return (0);                                                                 \
01702 }                                                                             \
01703                                                                               \
01704 /*                                                                            \
01705  * this function returns the number of used entries in the node               \
01706  *                                                                            \
01707  * this function can only be used if the node is sorted and correctly         \
01708  * built                                                                      \
01709  */                                                                           \
01710                                                                               \
01711 t_bpt_ndi(T)            bpt_node_size_##T(t_bpt(T)              *bpt,         \
01712                                           t_bpt_imm(T)          *node)        \
01713 {                                                                             \
01714   t_bpt_ndi(T)          nkeys = BPT_NKEYS(T, bpt, node);                      \
01715   t_bpt_ndi(T)          j = nkeys - 1;                                        \
01716   t_bpt_ndi(T)          i = 0;                                                \
01717                                                                               \
01718   if (BPT_GET_ENTRY(T, node, 0, _value_) == bpt->unused)                      \
01719     return (0);                                                               \
01720                                                                               \
01721   while (i <= j)                                                              \
01722     {                                                                         \
01723       t_bpt_ndi(T)      k = (i + j) / 2;                                      \
01724                                                                               \
01725       if ((BPT_GET_ENTRY(T, node, k, _value_) != bpt->unused)                 \
01726           && (((k + 1) > j) ||                                                \
01727               (BPT_GET_ENTRY(T, node, k + 1, _value_) == bpt->unused)))       \
01728         return (k + 1);                                                       \
01729                                                                               \
01730       if (BPT_GET_ENTRY(T, node, k, _value_) == bpt->unused)                  \
01731         j = k - 1;                                                            \
01732       else                                                                    \
01733         i = k + 1;                                                            \
01734     }                                                                         \
01735                                                                               \
01736   return (0);                                                                 \
01737 }                                                                             \
01738                                                                               \
01739 /*                                                                            \
01740  * this function tries to simplify the tree. indeed if the current node       \
01741  * has no neighbour, the tree can be curtail and the node becomes the         \
01742  * root one.                                                                  \
01743  */                                                                           \
01744                                                                               \
01745 void                    bpt_simplify_##T(t_bpt(T)               *bpt,         \
01746                                          t_bpt_imm(T)           *node1,       \
01747                                          t_bpt_unused(T)        *unused)      \
01748 {                                                                             \
01749   t_bpt_head(T)         *head1 = BPT_HEAD(T, node1);                          \
01750   t_bpt_head(T)         *head2;                                               \
01751   t_bpt_node(T)         parent;                                               \
01752   t_bpt_imm(T)          node2;                                                \
01753                                                                               \
01754   if (head1->parent == bpt->unused)                                           \
01755     return ;                                                                  \
01756                                                                               \
01757   if ((head1->prv != bpt->unused) || (head1->nxt != bpt->unused))             \
01758     return ;                                                                  \
01759                                                                               \
01760   BPT_LOAD(bpt, &node2, node1->addr);                                         \
01761   head2 = BPT_HEAD(T, &node2);                                                \
01762                                                                               \
01763   while (head2->parent != bpt->unused)                                        \
01764     {                                                                         \
01765       parent = head2->parent;                                                 \
01766                                                                               \
01767       BPT_UNLOAD(bpt, &node2);                                                \
01768                                                                               \
01769       BPT_LOAD(bpt, &node2, parent);                                          \
01770       head2 = BPT_HEAD(T, &node2);                                            \
01771                                                                               \
01772       BPT_RELEASE(bpt, unused, node2.addr);                                   \
01773     }                                                                         \
01774                                                                               \
01775   BPT_UNLOAD(bpt, &node2);                                                    \
01776                                                                               \
01777   head1->parent = bpt->unused;                                                \
01778   BPT_SET_ROOT(bpt, node1->addr);                                             \
01779 }                                                                             \
01780                                                                               \
01781 /*                                                                            \
01782  * this function just moves node1's entries in node2 and then                 \
01783  * eliminate the node1 'cause it's now unused.                                \
01784  */                                                                           \
01785                                                                               \
01786 int                     bpt_balancein_1_##T(t_bpt(T)            *bpt,         \
01787                                             t_bpt_imm(T)        *node1,       \
01788                                             t_bpt_imm(T)        *node2,       \
01789                                             t_bpt_cbctx(T)      *cbctx,       \
01790                                             t_bpt_entry(T)      prev,         \
01791                                             t_bpt_unused(T)     *unused)      \
01792 {                                                                             \
01793   t_bpt_head(T)         *head1 = BPT_HEAD(T, node1);                          \
01794   t_bpt_head(T)         *head2 = BPT_HEAD(T, node2);                          \
01795   t_bpt_imm(T)          parent;                                               \
01796   t_bpt_entry(T)        entry;                                                \
01797                                                                               \
01798   bpt_insert_head(T, bpt, node1, node2);                                      \
01799                                                                               \
01800   head2->prv = head1->prv;                                                    \
01801   if (head2->prv != bpt->unused)                                              \
01802     {                                                                         \
01803       t_bpt_head(T)     *head3;                                               \
01804       t_bpt_imm(T)      node3;                                                \
01805                                                                               \
01806       BPT_LOAD(bpt, &node3, head2->prv);                                      \
01807       head3 = BPT_HEAD(T, &node3);                                            \
01808       head3->nxt = node2->addr;                                               \
01809       BPT_UNLOAD(bpt, &node3);                                                \
01810     }                                                                         \
01811                                                                               \
01812   if (head2->type == BPT_TYPE_INTERNAL)                                       \
01813     if (bpt_update(T, bpt, node2, BPT_OPT_PARENT) != 0)                       \
01814       return (-1);                                                            \
01815                                                                               \
01816   BPT_LOAD(bpt, &parent, head1->parent);                                      \
01817                                                                               \
01818   entry.node = parent.addr;                                                   \
01819   if (bpt_ndi(T, bpt, &parent, node1->addr, &entry.ndi) != 0)                 \
01820     {                                                                         \
01821       BPT_UNLOAD(bpt, &parent);                                               \
01822       return (-1);                                                            \
01823     }                                                                         \
01824                                                                               \
01825   BPT_UNLOAD(bpt, &parent);                                                   \
01826                                                                               \
01827   if (bpt_delete(T, bpt, entry, cbctx, unused) != 0)                          \
01828     return (-1);                                                              \
01829                                                                               \
01830   BPT_SET_CBCTX(bpt, head2, cbctx, cb, BPT_CB_MIGRATE);                       \
01831   if (prev.node == node1->addr)                                               \
01832     {                                                                         \
01833        BPT_SET_CBCTX(bpt, head2, cbctx, previous.node, node2->addr);          \
01834        BPT_SET_CBCTX(bpt, head2, cbctx, previous.ndi, prev.ndi);              \
01835     }                                                                         \
01836   else                                                                        \
01837     {                                                                         \
01838       BPT_SET_CBCTX(bpt, head2, cbctx, previous.node, prev.node);             \
01839       BPT_SET_CBCTX(bpt, head2, cbctx, previous.ndi, prev.ndi);               \
01840     }                                                                         \
01841   BPT_SET_CBCTX(bpt, head2, cbctx, node, node2->addr);                        \
01842                                                                               \
01843   BPT_RELEASE(bpt, unused, node1->addr);                                      \
01844                                                                               \
01845   return (0);                                                                 \
01846 }                                                                             \
01847                                                                               \
01848 /*                                                                            \
01849  * this function just takes an entry in the next node and inserts it          \
01850  * in the current node to not have to move the entries                        \
01851  */                                                                           \
01852                                                                               \
01853 int                     bpt_balancein_2_##T(t_bpt(T)            *bpt,         \
01854                                             t_bpt_imm(T)        *node1,       \
01855                                             t_bpt_imm(T)        *node2,       \
01856                                             t_bpt_cbctx(T)      *cbctx,       \
01857                                             t_bpt_entry(T)      prev,         \
01858                                             t_bpt_unused(T)     *unused)      \
01859 {                                                                             \
01860   t_bpt_head(T)         *head1 = BPT_HEAD(T, node1);                          \
01861   t_bpt_ndi(T)          ndi1;                                                 \
01862   t_bpt_ndi(T)          ndi2;                                                 \
01863                                                                               \
01864   bpt_insert_sort(T, bpt, node1, BPT_OPT_NOKEY(T), BPT_OPT_NOVALUE(T),        \
01865                   &ndi1, BPT_OPT_TAIL);                                       \
01866                                                                               \
01867   if (bpt_first_entry(T, bpt, node2, &ndi2) != 0)                             \
01868     return (-1);                                                              \
01869                                                                               \
01870   BPT_COPY_ENTRY(T, node2, node1, ndi2, ndi1);                                \
01871                                                                               \
01872   BPT_INIT_ENTRY(T, node2, ndi2);                                             \
01873   BPT_SET_ENTRY(T, node2, ndi2, _value_, bpt->unused);                        \
01874                                                                               \
01875   bpt_shift_sort(T, bpt, node2);                                              \
01876                                                                               \
01877   if (head1->type == BPT_TYPE_INTERNAL)                                       \
01878     if (bpt_update(T, bpt, node1, BPT_OPT_PARENT) != 0)                       \
01879       return (-1);                                                            \
01880                                                                               \
01881   if (bpt_update(T, bpt, node1, BPT_OPT_KEY) != 0)                            \
01882     return (-1);                                                              \
01883                                                                               \
01884   BPT_SET_CBCTX(bpt, head1, cbctx, cb, BPT_CB_BALANCE);                       \
01885   BPT_SET_CBCTX(bpt, head1, cbctx, previous.node, prev.node);                 \
01886   BPT_SET_CBCTX(bpt, head1, cbctx, previous.ndi, prev.ndi);                   \
01887   BPT_SET_CBCTX(bpt, head1, cbctx, node1, node1->addr);                       \
01888   BPT_SET_CBCTX(bpt, head1, cbctx, node2, node2->addr);                       \
01889                                                                               \
01890   return (0);                                                                 \
01891 }                                                                             \
01892                                                                               \
01893 /*                                                                            \
01894  * this function balances node1's entries in the node2 and marks              \
01895  * node1 as unused                                                            \
01896  */                                                                           \
01897                                                                               \
01898 int                     bpt_balancein_3_##T(t_bpt(T)            *bpt,         \
01899                                             t_bpt_imm(T)        *node2,       \
01900                                             t_bpt_imm(T)        *node1,       \
01901                                             t_bpt_cbctx(T)      *cbctx,       \
01902                                             t_bpt_entry(T)      prev,         \
01903                                             t_bpt_unused(T)     *unused)      \
01904 {                                                                             \
01905   t_bpt_head(T)         *head1 = BPT_HEAD(T, node1);                          \
01906   t_bpt_head(T)         *head2 = BPT_HEAD(T, node2);                          \
01907   t_bpt_ndi(T)          node1sz = bpt_node_size(T, bpt, node1);               \
01908   t_bpt_imm(T)          parent;                                               \
01909   t_bpt_entry(T)        entry;                                                \
01910                                                                               \
01911   bpt_insert_tail(T, bpt, node2, node1);                                      \
01912                                                                               \
01913   head1->nxt = head2->nxt;                                                    \
01914   if (head1->nxt != bpt->unused)                                              \
01915     {                                                                         \
01916       t_bpt_head(T)     *head3;                                               \
01917       t_bpt_imm(T)      node3;                                                \
01918                                                                               \
01919       BPT_LOAD(bpt, &node3, head2->nxt);                                      \
01920       head3 = BPT_HEAD(T, &node3);                                            \
01921       head3->prv = node1->addr;                                               \
01922       BPT_UNLOAD(bpt, &node3);                                                \
01923     }                                                                         \
01924                                                                               \
01925   if (head1->type == BPT_TYPE_INTERNAL)                                       \
01926     if (bpt_update(T, bpt, node1, BPT_OPT_PARENT) != 0)                       \
01927       return (-1);                                                            \
01928                                                                               \
01929   if (bpt_update(T, bpt, node1, BPT_OPT_KEY) != 0)                            \
01930     return (-1);                                                              \
01931                                                                               \
01932   BPT_LOAD(bpt, &parent, head2->parent);                                      \
01933                                                                               \
01934   entry.node = head2->parent;                                                 \
01935   if (bpt_ndi(T, bpt, &parent, node2->addr, &entry.ndi) != 0)                 \
01936     {                                                                         \
01937       BPT_UNLOAD(bpt, &parent);                                               \
01938       return (-1);                                                            \
01939     }                                                                         \
01940                                                                               \
01941   BPT_UNLOAD(bpt, &parent);                                                   \
01942                                                                               \
01943   if (bpt_delete(T, bpt, entry, cbctx, unused) != 0)                          \
01944     return (-1);                                                              \
01945                                                                               \
01946   BPT_SET_CBCTX(bpt, head1, cbctx, cb, BPT_CB_MIGRATE);                       \
01947   if (prev.node == node2->addr)                                               \
01948     {                                                                         \
01949       BPT_SET_CBCTX(bpt, head1, cbctx, previous.node, node1->addr);           \
01950       BPT_SET_CBCTX(bpt, head1, cbctx, previous.ndi,                          \
01951                     node1sz + prev.ndi);                                      \
01952     }                                                                         \
01953   else                                                                        \
01954     {                                                                         \
01955       BPT_SET_CBCTX(bpt, head1, cbctx, previous.node, prev.node);             \
01956       BPT_SET_CBCTX(bpt, head1, cbctx, previous.ndi, prev.ndi);               \
01957     }                                                                         \
01958   BPT_SET_CBCTX(bpt, head1, cbctx, node, node1->addr);                        \
01959                                                                               \
01960   BPT_RELEASE(bpt, unused, node2->addr);                                      \
01961                                                                               \
01962   return (0);                                                                 \
01963 }                                                                             \
01964                                                                               \
01965 /*                                                                            \
01966  * this function moves one entry of the node2 in the node1                    \
01967  */                                                                           \
01968                                                                               \
01969 int                     bpt_balancein_4_##T(t_bpt(T)            *bpt,         \
01970                                             t_bpt_imm(T)        *node2,       \
01971                                             t_bpt_imm(T)        *node1,       \
01972                                             t_bpt_cbctx(T)      *cbctx,       \
01973                                             t_bpt_entry(T)      prev,         \
01974                                             t_bpt_unused(T)     *unused)      \
01975 {                                                                             \
01976   t_bpt_head(T)         *head2 = BPT_HEAD(T, node2);                          \
01977   t_bpt_ndi(T)          ndi1;                                                 \
01978   t_bpt_ndi(T)          ndi2;                                                 \
01979                                                                               \
01980   bpt_insert_sort(T, bpt, node2, BPT_OPT_NOKEY(T), BPT_OPT_NOVALUE(T),        \
01981                   &ndi2, BPT_OPT_HEAD);                                       \
01982                                                                               \
01983   if (bpt_last_entry(T, bpt, node1, &ndi1) != 0)                              \
01984     return (-1);                                                              \
01985                                                                               \
01986   BPT_COPY_ENTRY(T, node1, node2, ndi1, ndi2);                                \
01987                                                                               \
01988   BPT_INIT_ENTRY(T, node1, ndi1);                                             \
01989   BPT_SET_ENTRY(T, node1, ndi1, _value_, bpt->unused);                        \
01990                                                                               \
01991   if (head2->type == BPT_TYPE_INTERNAL)                                       \
01992     if (bpt_update(T, bpt, node2, BPT_OPT_PARENT) != 0)                       \
01993       return (-1);                                                            \
01994                                                                               \
01995   if (bpt_update(T, bpt, node1, BPT_OPT_KEY) != 0)                            \
01996     return (-1);                                                              \
01997                                                                               \
01998   BPT_SET_CBCTX(bpt, head2, cbctx, cb, BPT_CB_BALANCE);                       \
01999   if ((prev.node == node1->addr) && (prev.ndi == ndi1))                       \
02000     {                                                                         \
02001       BPT_SET_CBCTX(bpt, head2, cbctx, previous.node, node2->addr);           \
02002       BPT_SET_CBCTX(bpt, head2, cbctx, previous.ndi, ndi2);                   \
02003     }                                                                         \
02004   else                                                                        \
02005     {                                                                         \
02006       BPT_SET_CBCTX(bpt, head2, cbctx, previous.node, prev.node);             \
02007       BPT_SET_CBCTX(bpt, head2, cbctx, previous.ndi, prev.ndi + 1);           \
02008     }                                                                         \
02009   BPT_SET_CBCTX(bpt, head2, cbctx, node1, node1->addr);                       \
02010   BPT_SET_CBCTX(bpt, head2, cbctx, node2, node2->addr);                       \
02011                                                                               \
02012   return (0);                                                                 \
02013 }                                                                             \
02014                                                                               \
02015 /*                                                                            \
02016  * this function deletes an entry in a giving node and rebalances             \
02017  * entries if necessary.                                                      \
02018  *                                                                            \
02019  * if a balancing has to be done, the function operates according             \
02020  * to four cases:                                                             \
02021  *                                                                            \
02022  * 1) the next node is large enough to receive the entries of the node1       \
02023  * 2) the next node is not large enough so we equilibrate the two nodes       \
02024  *    taking a node2's entry to move it in the node1                          \
02025  * 3) the previous node is large enough to receive the entries of the node1   \
02026  * 4) the previous node is not large enough so we equilibrate the two nodes   \
02027  *    taking a node2's entry to move it in the node1                          \
02028  */                                                                           \
02029                                                                               \
02030 int                     bpt_delete_##T(t_bpt(T)                 *bpt,         \
02031                                        t_bpt_entry(T)           entry,        \
02032                                        t_bpt_cbctx(T)           *cbctx,       \
02033                                        t_bpt_unused(T)          *unused)      \
02034 {                                                                             \
02035   t_bpt_head(T)         *head1;                                               \
02036   t_bpt_head(T)         *head2;                                               \
02037   t_bpt_imm(T)          node1;                                                \
02038   t_bpt_imm(T)          node2;                                                \
02039   t_bpt_ndi(T)          nkeys;                                                \
02040   t_bpt_entry(T)        prev;                                                 \
02041                                                                               \
02042   if (bpt_prev_entry(T, bpt, entry, &prev, BPT_OPT_TREE) != 0)                \
02043     {                                                                         \
02044       prev.node = bpt->unused;                                                \
02045       prev.ndi = 0;                                                           \
02046     }                                                                         \
02047                                                                               \
02048   BPT_LOAD(bpt, &node1, entry.node);                                          \
02049   head1 = BPT_HEAD(T, &node1);                                                \
02050   nkeys = BPT_NKEYS(T, bpt, &node1);                                          \
02051                                                                               \
02052   BPT_INIT_ENTRY(T, &node1, entry.ndi);                                       \
02053   BPT_SET_ENTRY(T, &node1, entry.ndi, _value_, bpt->unused);                  \
02054                                                                               \
02055   bpt_shift_sort(T, bpt, &node1);                                             \
02056                                                                               \
02057   if ((head1->parent == bpt->unused) ||                                       \
02058       (bpt_node_size(T, bpt, &node1) >= BPT_QUOTA(T, bpt, &node1)))           \
02059     {                                                                         \
02060       if (bpt_update(T, bpt, &node1, BPT_OPT_KEY) != 0)                       \
02061         {                                                                     \
02062           bpt_debug("[bptd] cannot update the node\n");                       \
02063           BPT_UNLOAD(bpt, &node1);                                            \
02064           return (-1);                                                        \
02065        }                                                                      \
02066                                                                               \
02067       BPT_SET_CBCTX(bpt, head1, cbctx, cb, BPT_CB_DELETE);                    \
02068       BPT_SET_CBCTX(bpt, head1, cbctx, previous.node, prev.node);             \
02069       BPT_SET_CBCTX(bpt, head1, cbctx, previous.ndi, prev.ndi);               \
02070       BPT_SET_CBCTX(bpt, head1, cbctx, node, node1.addr);                     \
02071                                                                               \
02072       BPT_UNLOAD(bpt, &node1);                                                \
02073                                                                               \
02074       return (0);                                                             \
02075     }                                                                         \
02076                                                                               \
02077   if (head1->nxt != bpt->unused)                                              \
02078     {                                                                         \
02079       BPT_LOAD(bpt, &node2, head1->nxt);                                      \
02080       head2 = BPT_HEAD(T, &node2);                                            \
02081                                                                               \
02082       if ((bpt_node_size(T, bpt, &node2) +                                    \
02083            bpt_node_size(T, bpt, &node1)) <= nkeys)                           \
02084         {                                                                     \
02085           if (bpt_balancein_1(T, bpt, &node1, &node2, cbctx,                  \
02086                               prev, unused) != 0)                             \
02087             {                                                                 \
02088               bpt_debug("[bptd] cannot balance entries in the "               \
02089                         "second node\n");                                     \
02090               BPT_UNLOAD(bpt, &node2);                                        \
02091               BPT_UNLOAD(bpt, &node1);                                        \
02092               return (-1);                                                    \
02093             }                                                                 \
02094                                                                               \
02095           bpt_simplify(T, bpt, &node2, unused);                               \
02096                                                                               \
02097           BPT_UNLOAD(bpt, &node2);                                            \
02098           BPT_UNLOAD(bpt, &node1);                                            \
02099           return (0);                                                         \
02100         }                                                                     \
02101       else                                                                    \
02102         {                                                                     \
02103           if (bpt_balancein_2(T, bpt, &node1, &node2, cbctx,                  \
02104                               prev, unused) != 0)                             \
02105             {                                                                 \
02106               bpt_debug("[bptd] cannot balance one entry in the node\n");     \
02107               BPT_UNLOAD(bpt, &node2);                                        \
02108               BPT_UNLOAD(bpt, &node1);                                        \
02109               return (-1);                                                    \
02110             }                                                                 \
02111                                                                               \
02112           BPT_UNLOAD(bpt, &node2);                                            \
02113           BPT_UNLOAD(bpt, &node1);                                            \
02114           return (0);                                                         \
02115         }                                                                     \
02116                                                                               \
02117       BPT_UNLOAD(bpt, &node2);                                                \
02118     }                                                                         \
02119                                                                               \
02120   if (head1->prv != bpt->unused)                                              \
02121     {                                                                         \
02122       BPT_LOAD(bpt, &node2, head1->prv);                                      \
02123       head2 = BPT_HEAD(T, &node2);                                            \
02124                                                                               \
02125       if ((bpt_node_size(T, bpt, &node2) +                                    \
02126            bpt_node_size(T, bpt, &node1)) <= nkeys)                           \
02127         {                                                                     \
02128           if (bpt_balancein_3(T, bpt, &node1, &node2, cbctx,                  \
02129                               prev, unused) != 0)                             \
02130             {                                                                 \
02131               bpt_debug("[bptd] cannot balance entries in the second "        \
02132                         "node\n");                                            \
02133               BPT_UNLOAD(bpt, &node2);                                        \
02134               BPT_UNLOAD(bpt, &node1);                                        \
02135               return (-1);                                                    \
02136             }                                                                 \
02137                                                                               \
02138           bpt_simplify(T, bpt, &node2, unused);                               \
02139                                                                               \
02140           BPT_UNLOAD(bpt, &node2);                                            \
02141           BPT_UNLOAD(bpt, &node1);                                            \
02142           return (0);                                                         \
02143         }                                                                     \
02144       else                                                                    \
02145         {                                                                     \
02146           if (bpt_balancein_4(T, bpt, &node1, &node2, cbctx,                  \
02147                               prev, unused) != 0)                             \
02148             {                                                                 \
02149               bpt_debug("[bptd] cannot balance one entry in the node\n");     \
02150               BPT_UNLOAD(bpt, &node2);                                        \
02151               BPT_UNLOAD(bpt, &node1);                                        \
02152               return (-1);                                                    \
02153             }                                                                 \
02154                                                                               \
02155           BPT_UNLOAD(bpt, &node2);                                            \
02156           BPT_UNLOAD(bpt, &node1);                                            \
02157           return (0);                                                         \
02158         }                                                                     \
02159                                                                               \
02160       BPT_UNLOAD(bpt, &node2);                                                \
02161     }                                                                         \
02162                                                                               \
02163   if (bpt_update(T, bpt, &node1, BPT_OPT_KEY) != 0)                           \
02164     {                                                                         \
02165       bpt_debug("[bptd] cannot update the node\n");                           \
02166       BPT_UNLOAD(bpt, &node1);                                                \
02167       return (-1);                                                            \
02168     }                                                                         \
02169                                                                               \
02170   bpt_simplify(T, bpt, &node1, unused);                                       \
02171                                                                               \
02172   BPT_SET_CBCTX(bpt, head1, cbctx, cb, BPT_CB_DELETE);                        \
02173   BPT_SET_CBCTX(bpt, head1, cbctx, previous.node, prev.node);                 \
02174   BPT_SET_CBCTX(bpt, head1, cbctx, previous.ndi, prev.ndi);                   \
02175   BPT_SET_CBCTX(bpt, head1, cbctx, node, node1.addr);                         \
02176                                                                               \
02177   BPT_UNLOAD(bpt, &node1);                                                    \
02178                                                                               \
02179   return (0);                                                                 \
02180 }                                                                             \
02181                                                                               \
02182 /*                                                                            \
02183  * this function removes a leaf entry                                         \
02184  *                                                                            \
02185  * this function does not take care about collisions assuming there is no     \
02186  * one. like bpt_modify(), if the programmer want to remove a specific        \
02187  * entry that collide with others, he has to use the collide_remove()         \
02188  * function.                                                                  \
02189  *                                                                            \
02190  * the function also fills the unused array with the addresses of the now     \
02191  * unused blocks.                                                             \
02192  */                                                                           \
02193                                                                               \
02194 int                     bpt_remove_##T(t_bpt(T)                 *bpt,         \
02195                                        t_bpt_key(T)             key,          \
02196                                        t_bpt_unused(T)          *unused)      \
02197 {                                                                             \
02198   t_bpt_cbctx(T)        cbctx;                                                \
02199   t_bpt_entry(T)        entry;                                                \
02200                                                                               \
02201   if (bpt_check_unused(T, bpt, unused, BPT_OPT_REMOVE) != 0)                  \
02202     {                                                                         \
02203       bpt_debug("[bptd] bad unused array\n");                                 \
02204       return (-1);                                                            \
02205     }                                                                         \
02206                                                                               \
02207   if (bpt_search(T, bpt, key, &entry) != 0)                                   \
02208     {                                                                         \
02209       bpt_debug("[bptd] cannot find the entry looked for\n");                 \
02210       return (-1);                                                            \
02211     }                                                                         \
02212                                                                               \
02213   BPT_INIT_CBCTX(bpt, &cbctx);                                                \
02214                                                                               \
02215   if (bpt_delete(T, bpt, entry, &cbctx, unused) != 0)                         \
02216     {                                                                         \
02217       bpt_debug("[bptd] cannot delete the leaf entry\n");                     \
02218       return (-1);                                                            \
02219     }                                                                         \
02220                                                                               \
02221   BPT_CALLBACK(bpt, &cbctx);                                                  \
02222                                                                               \
02223   return (0);                                                                 \
02224 }                                                                             \
02225                                                                               \
02226 /*                                                                            \
02227  * this function is similar to the bpt_remove() one.                          \
02228  * the singular difference is that the function takes an entry descriptor     \
02229  * as parameter. by this, this function is able to remove an entry that       \
02230  * collide with others.                                                       \
02231  */                                                                           \
02232                                                                               \
02233 int                     bpt_collide_remove_##T(t_bpt(T)         *bpt,         \
02234                                                t_bpt_entry(T)   entry,        \
02235                                                t_bpt_unused(T)  *unused)      \
02236 {                                                                             \
02237   t_bpt_cbctx(T)        cbctx;                                                \
02238                                                                               \
02239   if (bpt_check_unused(T, bpt, unused, BPT_OPT_REMOVE) != 0)                  \
02240     {                                                                         \
02241       bpt_debug("[bptd] bad unused array\n");                                 \
02242       return (-1);                                                            \
02243     }                                                                         \
02244                                                                               \
02245   BPT_INIT_CBCTX(bpt, &cbctx);                                                \
02246                                                                               \
02247   if (bpt_delete(T, bpt, entry, &cbctx, unused) != 0)                         \
02248     {                                                                         \
02249       bpt_debug("[bptd] cannot delete the leaf entry\n");                     \
02250       return (-1);                                                            \
02251     }                                                                         \
02252                                                                               \
02253   BPT_CALLBACK(bpt, &cbctx);                                                  \
02254                                                                               \
02255   return (0);                                                                 \
02256 }                                                                             \
02257                                                                               \
02258 /*                                                                            \
02259  * this function modifies an entry. this entry may be moved due to the        \
02260  * key modification.                                                          \
02261  *                                                                            \
02262  * this function supposes that there is no collision. if the tree accepts     \
02263  * collisions, we advice you to not use this function. instead you must       \
02264  * implement your own version or use collide_modify().                        \
02265  *                                                                            \
02266  * the unused variable must contain free blocks that the bpt library          \
02267  * can use for splitting.                                                     \
02268  * this restriction may seem abusive, so *ONLY* if the programmer knows       \
02269  * that the new leaf entry has the same key, this function can be called      \
02270  * with a NULL unused variable because it will never be used.                 \
02271  *                                                                            \
02272  * to know what the unused variable is supposed to contain, take a look       \
02273  * to the bpt_add() function.                                                 \
02274  */                                                                           \
02275                                                                               \
02276 int                     bpt_modify_##T(t_bpt(T)                 *bpt,         \
02277                                        t_bpt_key(T)             key,          \
02278                                        t_bpt_lfentry(T)         *lfentry,     \
02279                                        t_bpt_unused(T)          *unused)      \
02280 {                                                                             \
02281   t_bpt_cbctx(T)        cbctx;                                                \
02282   t_bpt_head(T)         *head;                                                \
02283   t_bpt_entry(T)        entry;                                                \
02284   t_bpt_imm(T)          node;                                                 \
02285                                                                               \
02286   if (bpt_check_unused(T, bpt, unused, BPT_OPT_MODIFY) != 0)                  \
02287     {                                                                         \
02288       bpt_debug("[bptd] bad unused array\n");                                 \
02289       return (-1);                                                            \
02290     }                                                                         \
02291                                                                               \
02292   if (lfentry->_value_ == bpt->unused)                                        \
02293     {                                                                         \
02294       bpt_debug("[bptd] the leaf entry to update has a non-valid key\n");     \
02295       return (-1);                                                            \
02296     }                                                                         \
02297                                                                               \
02298   if (bpt_search(T, bpt, key, &entry) != 0)                                   \
02299     {                                                                         \
02300       bpt_debug("[bptd] cannot find the entry\n");                            \
02301       return (-1);                                                            \
02302     }                                                                         \
02303                                                                               \
02304   BPT_LOAD(bpt, &node, entry.node);                                           \
02305   head = BPT_HEAD(T, &node);                                                  \
02306                                                                               \
02307   BPT_INIT_CBCTX(bpt, &cbctx);                                                \
02308                                                                               \
02309   if (lfentry->_key_ == BPT_GET_ENTRY(T, &node, entry.ndi, _key_))            \
02310     {                                                                         \
02311       BPT_IMPORT_ENTRY(T, &node, entry.ndi, lfentry);                         \
02312                                                                               \
02313       BPT_SET_CBCTX(bpt, head, &cbctx, cb, BPT_CB_MODIFY);                    \
02314       BPT_SET_CBCTX(bpt, head, &cbctx, current.node, node.addr);              \
02315       BPT_SET_CBCTX(bpt, head, &cbctx, current.ndi, entry.ndi);               \
02316       BPT_SET_CBCTX(bpt, head, &cbctx, node, node.addr);                      \
02317                                                                               \
02318       BPT_CALLBACK(bpt, &cbctx);                                              \
02319                                                                               \
02320       BPT_UNLOAD(bpt, &node);                                                 \
02321                                                                               \
02322       return (0);                                                             \
02323     }                                                                         \
02324                                                                               \
02325   BPT_UNLOAD(bpt, &node);                                                     \
02326                                                                               \
02327   if (bpt_remove(T, bpt, key, unused) != 0)                                   \
02328     {                                                                         \
02329       bpt_debug("[bptd] cannot remove the entry\n");                          \
02330       return (-1);                                                            \
02331     }                                                                         \
02332                                                                               \
02333   if (bpt_add(T, bpt, lfentry, unused) != 0)                                  \
02334     {                                                                         \
02335       bpt_debug("[bptd] cannot add the entry\n");                             \
02336       return (-1);                                                            \
02337     }                                                                         \
02338                                                                               \
02339   return (0);                                                                 \
02340 }                                                                             \
02341                                                                               \
02342 /*                                                                            \
02343  * this function is similar to the bpt_modify() function except the fact      \
02344  * that it takes a entry descriptor to specify a precise entry to modify.     \
02345  *                                                                            \
02346  * this function is adapted to the trees that manage collisions.              \
02347  */                                                                           \
02348                                                                               \
02349 int                     bpt_collide_modify_##T(t_bpt(T)         *bpt,         \
02350                                                t_bpt_entry(T)   entry,        \
02351                                                t_bpt_lfentry(T) *lfentry,     \
02352                                                t_bpt_unused(T)  *unused)      \
02353 {                                                                             \
02354   t_bpt_cbctx(T)        cbctx;                                                \
02355   t_bpt_head(T)         *head;                                                \
02356   t_bpt_imm(T)          node;                                                 \
02357                                                                               \
02358   if (bpt_check_unused(T, bpt, unused, BPT_OPT_MODIFY) != 0)                  \
02359     {                                                                         \
02360       bpt_debug("[bptd] bad unused array\n");                                 \
02361       return (-1);                                                            \
02362     }                                                                         \
02363                                                                               \
02364   if (lfentry->_value_ == bpt->unused)                                        \
02365     {                                                                         \
02366       bpt_debug("[bptd] the leaf entry to update has a non-valid key\n");     \
02367       return (-1);                                                            \
02368     }                                                                         \
02369                                                                               \
02370   BPT_LOAD(bpt, &node, entry.node);                                           \
02371   head = BPT_HEAD(T, &node);                                                  \
02372                                                                               \
02373   BPT_INIT_CBCTX(bpt, &cbctx);                                                \
02374                                                                               \
02375   if (lfentry->_key_ == BPT_GET_ENTRY(T, &node, entry.ndi, _key_))            \
02376     {                                                                         \
02377       BPT_IMPORT_ENTRY(T, &node, entry.ndi, lfentry);                         \
02378                                                                               \
02379       BPT_SET_CBCTX(bpt, head, &cbctx, cb, BPT_CB_MODIFY);                    \
02380       BPT_SET_CBCTX(bpt, head, &cbctx, current.node, node.addr);              \
02381       BPT_SET_CBCTX(bpt, head, &cbctx, current.ndi, entry.ndi);               \
02382       BPT_SET_CBCTX(bpt, head, &cbctx, node, node.addr);                      \
02383                                                                               \
02384       BPT_CALLBACK(bpt, &cbctx);                                              \
02385                                                                               \
02386       BPT_UNLOAD(bpt, &node);                                                 \
02387                                                                               \
02388       return (0);                                                             \
02389     }                                                                         \
02390                                                                               \
02391   BPT_UNLOAD(bpt, &node);                                                     \
02392                                                                               \
02393   if (bpt_collide_remove(T, bpt, entry, unused) != 0)                         \
02394     {                                                                         \
02395       bpt_debug("[bptd] cannot remove a collision\n");                        \
02396       return (-1);                                                            \
02397     }                                                                         \
02398                                                                               \
02399   if (bpt_add(T, bpt, lfentry, unused) != 0)                                  \
02400     {                                                                         \
02401       bpt_debug("[bptd] cannot add an entry\n");                              \
02402       return (-1);                                                            \
02403     }                                                                         \
02404                                                                               \
02405   return (0);                                                                 \
02406 }                                                                             \
02407                                                                               \
02408 /*                                                                            \
02409  * this function inserts node1's entries at the head of the node2             \
02410  */                                                                           \
02411                                                                               \
02412 void                    bpt_insert_head_##T(t_bpt(T)            *bpt,         \
02413                                             t_bpt_imm(T)        *node1,       \
02414                                             t_bpt_imm(T)        *node2)       \
02415 {                                                                             \
02416   t_bpt_ndi(T)          node1sz = bpt_node_size(T, bpt, node1);               \
02417   t_bpt_ndi(T)          node2sz = bpt_node_size(T, bpt, node2);               \
02418   t_bpt_ndi(T)          i;                                                    \
02419                                                                               \
02420   for (i = node2sz - 1; i >= 0; i--)                                          \
02421     BPT_COPY_ENTRY(T, node2, node2, i, node1sz + i);                          \
02422   for (i = 0; i < node1sz; i++)                                               \
02423     BPT_COPY_ENTRY(T, node1, node2, i, i);                                    \
02424 }                                                                             \
02425                                                                               \
02426 /*                                                                            \
02427  * this function inserts node1's entries at the tail of the node2             \
02428  */                                                                           \
02429                                                                               \
02430 void                    bpt_insert_tail_##T(t_bpt(T)            *bpt,         \
02431                                             t_bpt_imm(T)        *node1,       \
02432                                             t_bpt_imm(T)        *node2)       \
02433 {                                                                             \
02434   t_bpt_ndi(T)          node2sz = bpt_node_size(T, bpt, node2);               \
02435   t_bpt_ndi(T)          nkeys = BPT_NKEYS(T, bpt, node1);                     \
02436   t_bpt_ndi(T)          i;                                                    \
02437                                                                               \
02438   for (i = 0; (i < nkeys) &&                                                  \
02439          (BPT_GET_ENTRY(T, node1, i, _value_) != bpt->unused);                \
02440        i++)                                                                   \
02441     BPT_COPY_ENTRY(T, node1, node2, i, node2sz + i);                          \
02442 }                                                                             \
02443                                                                               \
02444 /*                                                                            \
02445  * this function shifts entries to place unused entries at the end of         \
02446  * the node                                                                   \
02447  */                                                                           \
02448                                                                               \
02449 void                    bpt_shift_sort_##T(t_bpt(T)             *bpt,         \
02450                                            t_bpt_imm(T)         *node)        \
02451 {                                                                             \
02452   t_bpt_ndi(T)          nkeys = BPT_NKEYS(T, bpt, node);                      \
02453   t_bpt_entry(T)        current;                                              \
02454                                                                               \
02455   for (current.node = node->addr, current.ndi = 0;                            \
02456        current.ndi < nkeys; current.ndi++)                                    \
02457     if (BPT_GET_ENTRY(T, node, current.ndi, _value_) == bpt->unused)          \
02458       {                                                                       \
02459         t_bpt_entry(T)  next;                                                 \
02460                                                                               \
02461         if (bpt_next_entry(T, bpt, current, &next, BPT_OPT_NODE) != 0)        \
02462           break;                                                              \
02463                                                                               \
02464         BPT_SWAP_ENTRIES(T, node, current.ndi, next.ndi);                     \
02465       }                                                                       \
02466 }                                                                             \
02467                                                                               \
02468 /*                                                                            \
02469  * this function inserts and sorts an entry                                   \
02470  */                                                                           \
02471                                                                               \
02472 void                    bpt_insert_sort_##T(t_bpt(T)            *bpt,         \
02473                                             t_bpt_imm(T)        *node,        \
02474                                             t_bpt_key(T)        key,          \
02475                                             t_bpt_addr(T)       value,        \
02476                                             t_bpt_ndi(T)        *ndi,         \
02477                                             t_bpt_opts          opts)         \
02478 {                                                                             \
02479   t_bpt_ndi(T)          nodesz = bpt_node_size(T, bpt, node);                 \
02480   t_bpt_ndi(T)          nkeys = BPT_NKEYS(T, bpt, node);                      \
02481   t_bpt_ndi(T)          i;                                                    \
02482                                                                               \
02483   if (opts & BPT_OPT_HEAD)                                                    \
02484     {                                                                         \
02485       for (*ndi = 0, i = nodesz - 1; i >= 0; i--)                             \
02486         BPT_COPY_ENTRY(T, node, node, i, i + 1);                              \
02487     }                                                                         \
02488   else if (opts & BPT_OPT_TAIL)                                               \
02489     {                                                                         \
02490       *ndi = nodesz;                                                          \
02491     }                                                                         \
02492   else                                                                        \
02493     {                                                                         \
02494       for (*ndi = 0; (*ndi < nkeys) &&                                        \
02495              (BPT_GET_ENTRY(T, node, *ndi, _value_) != bpt->unused);          \
02496            (*ndi)++)                                                          \
02497         if (BPT_GET_ENTRY(T, node, *ndi, _key_) >= key)                       \
02498           {                                                                   \
02499             if (bpt->flags & BPT_FLAG_COLLIDE)                                \
02500               while ((BPT_GET_ENTRY(T, node, *ndi, _value_) != bpt->unused) &&\
02501                      (BPT_GET_ENTRY(T, node, *ndi, _key_) == key) &&          \
02502                      (BPT_GET_ENTRY(T, node, *ndi, _value_) < value))         \
02503                 *ndi = *ndi + 1;                                              \
02504             break;                                                            \
02505           }                                                                   \
02506                                                                               \
02507       if (nodesz > *ndi)                                                      \
02508         for (i = nodesz - 1; i >= *ndi; i--)                                  \
02509           BPT_COPY_ENTRY(T, node, node, i, i + 1);                            \
02510     }                                                                         \
02511                                                                               \
02512   BPT_INIT_ENTRY(T, node, *ndi);                                              \
02513   BPT_SET_ENTRY(T, node, *ndi, _value_, bpt->unused);                         \
02514 }                                                                             \
02515                                                                               \
02516 /*                                                                            \
02517  * this function creates a new root node and then inserts two entries         \
02518  * in it for the two children node1 and node2                                 \
02519  */                                                                           \
02520                                                                               \
02521 void                    bpt_new_root_##T(t_bpt(T)               *bpt,         \
02522                                          t_bpt_imm(T)           *node1,       \
02523                                          t_bpt_imm(T)           *node2,       \
02524                                          t_bpt_unused(T)        *unused)      \
02525 {                                                                             \
02526   t_bpt_head(T)         *head1 = BPT_HEAD(T, node1);                          \
02527   t_bpt_head(T)         *head2 = BPT_HEAD(T, node2);                          \
02528   t_bpt_inentry(T)      inentry;                                              \
02529   t_bpt_head(T)         *head0;                                               \
02530   t_bpt_imm(T)          root;                                                 \
02531   t_bpt_addr(T)         blk;                                                  \
02532   t_bpt_ndi(T)          ndi;                                                  \
02533                                                                               \
02534   BPT_RESERVE(bpt, unused, blk);                                              \
02535   BPT_LOAD(bpt, &root, blk);                                                  \
02536                                                                               \
02537   bpt_make_node(T, bpt, &root, BPT_TYPE_INTERNAL, bpt->unused);               \
02538   head0 = BPT_HEAD(T, &root);                                                 \
02539                                                                               \
02540   memset(&inentry, 0x0, sizeof(t_bpt_inentry(T)));                            \
02541   bpt_key(T, bpt, node1, &inentry._key_);                                     \
02542   inentry._value_ = node1->addr;                                              \
02543                                                                               \
02544   bpt_insert_sort(T, bpt, &root, inentry._key_, inentry._value_,              \
02545                   &ndi, BPT_OPT_ZERO);                                        \
02546                                                                               \
02547   BPT_IMPORT_ENTRY(T, &root, ndi, &inentry);                                  \
02548                                                                               \
02549   memset(&inentry, 0x0, sizeof(t_bpt_inentry(T)));                            \
02550   bpt_key(T, bpt, node2, &inentry._key_);                                     \
02551   inentry._value_ = node2->addr;                                              \
02552                                                                               \
02553   bpt_insert_sort(T, bpt, &root, inentry._key_, inentry._value_,              \
02554                   &ndi, BPT_OPT_ZERO);                                        \
02555                                                                               \
02556   BPT_IMPORT_ENTRY(T, &root, ndi, &inentry);                                  \
02557                                                                               \
02558   BPT_SET_ROOT(bpt, root.addr);                                               \
02559   head1->parent = root.addr;                                                  \
02560   head2->parent = root.addr;                                                  \
02561                                                                               \
02562   bpt->height++;                                                              \
02563                                                                               \
02564   BPT_UNLOAD(bpt, &root);                                                     \
02565 }                                                                             \
02566                                                                               \
02567 /*                                                                            \
02568  * this function, used by bpt_split_node() rebalances the                     \
02569  * entries of node1 in the two nodes node1 and node2.                         \
02570  */                                                                           \
02571                                                                               \
02572 int                     bpt_balanceout_##T(t_bpt(T)             *bpt,         \
02573                                            t_bpt_imm(T)         *node1,       \
02574                                            t_bpt_imm(T)         *node2,       \
02575                                            void                 *entry,       \
02576                                            t_bpt_cbctx(T)       *cbctx)       \
02577 {                                                                             \
02578   t_bpt_head(T)         *head1 = BPT_HEAD(T, node1);                          \
02579   t_bpt_ndi(T)          nkeys = BPT_NKEYS(T, bpt, node1);                     \
02580   t_bpt_head(T)         *head2;                                               \
02581   t_bpt_ndi(T)          i;                                                    \
02582   t_bpt_ndi(T)          j;                                                    \
02583                                                                               \
02584   BPT_COPY_NODE(bpt, node1->buf, node2->buf);                                 \
02585   bpt_reinit_entries(T, bpt, node1);                                          \
02586   head2 = BPT_HEAD(T, node2);                                                 \
02587                                                                               \
02588   for (i = 0, j = 0; i < ((nkeys + 1) / 2); i++)                              \
02589     {                                                                         \
02590       if ((entry != NULL) &&                                                  \
02591           (BPT_GET_THIS_ENTRY(T, head1, entry, _key_) <                       \
02592            BPT_GET_ENTRY(T, node2, j, _key_)))                                \
02593         {                                                                     \
02594           BPT_IMPORT_ENTRY(T, node1, i, entry);                               \
02595                                                                               \
02596           BPT_SET_CBCTX(bpt, head1, cbctx, current.node, node1->addr);        \
02597           BPT_SET_CBCTX(bpt, head1, cbctx, current.ndi, i);                   \
02598                                                                               \
02599           entry = NULL;                                                       \
02600           continue;                                                           \
02601         }                                                                     \
02602                                                                               \
02603       BPT_COPY_ENTRY(T, node2, node1, j, i);                                  \
02604       BPT_INIT_ENTRY(T, node2, j);                                            \
02605       BPT_SET_ENTRY(T, node2, j, _value_, bpt->unused);                       \
02606       j++;                                                                    \
02607     }                                                                         \
02608                                                                               \
02609   bpt_shift_sort(T, bpt, node2);                                              \
02610                                                                               \
02611   if (entry != NULL)                                                          \
02612     {                                                                         \
02613       bpt_insert_sort(T, bpt, node2,                                          \
02614                       BPT_GET_THIS_ENTRY(T, head1, entry, _key_),             \
02615                       BPT_GET_THIS_ENTRY(T, head1, entry, _value_),           \
02616                       &i, BPT_OPT_ZERO);                                      \
02617       BPT_IMPORT_ENTRY(T, node2, i, entry);                                   \
02618                                                                               \
02619       BPT_SET_CBCTX(bpt, head2, cbctx, current.node, node2->addr);            \
02620       BPT_SET_CBCTX(bpt, head2, cbctx, current.ndi, i);                       \
02621     }                                                                         \
02622                                                                               \
02623   head2->prv = node1->addr;                                                   \
02624   head2->nxt = head1->nxt;                                                    \
02625   head1->nxt = node2->addr;                                                   \
02626                                                                               \
02627   if (head2->nxt != bpt->unused)                                              \
02628     {                                                                         \
02629       t_bpt_head(T)     *head3;                                               \
02630       t_bpt_imm(T)      node3;                                                \
02631                                                                               \
02632       BPT_LOAD(bpt, &node3, head2->nxt);                                      \
02633       head3 = BPT_HEAD(T, &node3);                                            \
02634       head3->prv = node2->addr;                                               \
02635       BPT_UNLOAD(bpt, &node3);                                                \
02636     }                                                                         \
02637                                                                               \
02638   if (head1->type == BPT_TYPE_INTERNAL)                                       \
02639     {                                                                         \
02640       if (bpt_update(T, bpt, node1, BPT_OPT_PARENT) != 0)                     \
02641         return (-1);                                                          \
02642                                                                               \
02643       if (bpt_update(T, bpt, node2, BPT_OPT_PARENT) != 0)                     \
02644         return (-1);                                                          \
02645     }                                                                         \
02646                                                                               \
02647   return (0);                                                                 \
02648 }                                                                             \
02649                                                                               \
02650 /*                                                                            \
02651  * this function splits a node so creates one new node (using an unused       \
02652  * address) and reorganizes the entries. if splitting the root node, a new    \
02653  * root node has to be created.                                               \
02654  * the function also inserts the specified entry.                             \
02655  *                                                                            \
02656  * finally the function fills the entry descriptor that indicates the         \
02657  * location of the inserted entry                                             \
02658  */                                                                           \
02659                                                                               \
02660 int                     bpt_split_node_##T(t_bpt(T)             *bpt,         \
02661                                            t_bpt_imm(T)         *node1,       \
02662                                            void                 *entry,       \
02663                                            t_bpt_cbctx(T)       *cbctx,       \
02664                                            t_bpt_unused(T)      *unused)      \
02665 {                                                                             \
02666   t_bpt_head(T)         *head1 = BPT_HEAD(T, node1);                          \
02667   t_bpt_head(T)         *head2;                                               \
02668   t_bpt_imm(T)          node2;                                                \
02669   t_bpt_addr(T)         blk;                                                  \
02670                                                                               \
02671   BPT_RESERVE(bpt, unused, blk);                                              \
02672   BPT_LOAD(bpt, &node2, blk);                                                 \
02673                                                                               \
02674   bpt_make_node(T, bpt, &node2, head1->type, head1->parent);                  \
02675   head2 = BPT_HEAD(T, &node2);                                                \
02676                                                                               \
02677   if (bpt_balanceout(T, bpt, node1, &node2, entry, cbctx) != 0)               \
02678     {                                                                         \
02679       bpt_debug("[bptd] cannot balance entries between two nodes\n");         \
02680       BPT_UNLOAD(bpt, &node2);                                                \
02681       BPT_RELEASE(bpt, unused, blk);                                          \
02682       return (-1);                                                            \
02683     }                                                                         \
02684                                                                               \
02685   if (head1->parent == bpt->unused)                                           \
02686     {                                                                         \
02687       bpt_new_root(T, bpt, node1, &node2, unused);                            \
02688     }                                                                         \
02689   else                                                                        \
02690     {                                                                         \
02691       t_bpt_inentry(T)  inentry;                                              \
02692       t_bpt_imm(T)      parent;                                               \
02693                                                                               \
02694       if (bpt_update(T, bpt, node1, BPT_OPT_KEY) != 0)                        \
02695         {                                                                     \
02696           BPT_UNLOAD(bpt, &node2);                                            \
02697           BPT_RELEASE(bpt, unused, blk);                                      \
02698           return (-1);                                                        \
02699         }                                                                     \
02700                                                                               \
02701       memset(&inentry, 0x0, sizeof(t_bpt_inentry(T)));                        \
02702       bpt_key(T, bpt, &node2, &inentry._key_);                                \
02703       inentry._value_ = node2.addr;                                           \
02704                                                                               \
02705       BPT_LOAD(bpt, &parent, head2->parent);                                  \
02706                                                                               \
02707       if (bpt_insert(T, bpt, &parent, &inentry, cbctx, unused) != 0)          \
02708         {                                                                     \
02709           bpt_debug("[bptd] cannot insert the entry in the parent node\n");   \
02710           BPT_UNLOAD(bpt, &parent);                                           \
02711           BPT_UNLOAD(bpt, &node2);                                            \
02712           BPT_RELEASE(bpt, unused, blk);                                      \
02713           return (-1);                                                        \
02714         }                                                                     \
02715                                                                               \
02716       BPT_UNLOAD(bpt, &parent);                                               \
02717     }                                                                         \
02718                                                                               \
02719   BPT_SET_CBCTX(bpt, head1, cbctx, cb, BPT_CB_SPLIT);                         \
02720   BPT_SET_CBCTX(bpt, head1, cbctx, node1, node1->addr);                       \
02721   BPT_SET_CBCTX(bpt, head1, cbctx, node2, node2.addr);                        \
02722                                                                               \
02723   BPT_UNLOAD(bpt, &node2);                                                    \
02724                                                                               \
02725   return (0);                                                                 \
02726 }                                                                             \
02727                                                                               \
02728 /*                                                                            \
02729  * this function inserts the entry in the specified node.                     \
02730  * the node may be splitted and the entries rebalanced between the two        \
02731  * nodes.                                                                     \
02732  *                                                                            \
02733  * the unused variable contains unused blocks, one for each level             \
02734  * of the tree because at each level a node can be splitted and one           \
02735  * for the possible creation of a new root node.                              \
02736  */                                                                           \
02737                                                                               \
02738 int                     bpt_insert_##T(t_bpt(T)                 *bpt,         \
02739                                        t_bpt_imm(T)             *node,        \
02740                                        void                     *entry,       \
02741                                        t_bpt_cbctx(T)           *cbctx,       \
02742                                        t_bpt_unused(T)          *unused)      \
02743 {                                                                             \
02744   t_bpt_head(T)         *head = BPT_HEAD(T, node);                            \
02745                                                                               \
02746   if (bpt_node_size(T, bpt, node) < BPT_NKEYS(T, bpt, node))                  \
02747     {                                                                         \
02748       t_bpt_ndi(T)      ndi;                                                  \
02749                                                                               \
02750       bpt_insert_sort(T, bpt, node,                                           \
02751                       BPT_GET_THIS_ENTRY(T, head, entry, _key_),              \
02752                       BPT_GET_THIS_ENTRY(T, head, entry, _value_),            \
02753                       &ndi, BPT_OPT_ZERO);                                    \
02754                                                                               \
02755       BPT_IMPORT_ENTRY(T, node, ndi, entry);                                  \
02756                                                                               \
02757       if (bpt_update(T, bpt, node, BPT_OPT_KEY) != 0)                         \
02758         {                                                                     \
02759           bpt_debug("[bptd] cannot update the tree\n");                       \
02760           return (-1);                                                        \
02761         }                                                                     \
02762                                                                               \
02763       BPT_SET_CBCTX(bpt, head, cbctx, cb, BPT_CB_INSERT);                     \
02764       BPT_SET_CBCTX(bpt, head, cbctx, current.node, node->addr);              \
02765       BPT_SET_CBCTX(bpt, head, cbctx, current.ndi, ndi);                      \
02766       BPT_SET_CBCTX(bpt, head, cbctx, node, node->addr);                      \
02767     }                                                                         \
02768   else                                                                        \
02769     {                                                                         \
02770       if (bpt_split_node(T, bpt, node, entry, cbctx, unused) != 0)            \
02771         {                                                                     \
02772           bpt_debug("[bptd] cannot split the node\n");                        \
02773           return (-1);                                                        \
02774         }                                                                     \
02775     }                                                                         \
02776                                                                               \
02777   return (0);                                                                 \
02778 }                                                                             \
02779                                                                               \
02780 /*                                                                            \
02781  * this function adds the lfentry in a leaf of the tree.                      \
02782  * the tree may grow and split some nodes to insert the new entry.            \
02783  *                                                                            \
02784  * the variable unused contains N+1 unused block addresses where N is         \
02785  * the tree's height. the '+1' designs the possible creation of a new         \
02786  * root node.                                                                 \
02787  *                                                                            \
02788  * if the programmer knows that the insertion of the new entry will           \
02789  * only split M node - where M is lower than N - the unused                   \
02790  * variable can be built in consequence.                                      \
02791  */                                                                           \
02792                                                                               \
02793 int                     bpt_add_##T(t_bpt(T)                    *bpt,         \
02794                                     t_bpt_lfentry(T)            *lfentry,     \
02795                                     t_bpt_unused(T)             *unused)      \
02796 {                                                                             \
02797   t_bpt_cbctx(T)        cbctx;                                                \
02798   t_bpt_addr(T)         addr;                                                 \
02799   t_bpt_imm(T)          leaf;                                                 \
02800   t_bpt_imm(T)          root;                                                 \
02801                                                                               \
02802   if (bpt_check_unused(T, bpt, unused, BPT_OPT_ADD) != 0)                     \
02803     {                                                                         \
02804       bpt_debug("[bptd] bad unused array\n");                                 \
02805       return (-1);                                                            \
02806     }                                                                         \
02807                                                                               \
02808   if (lfentry->_value_ == bpt->unused)                                        \
02809     {                                                                         \
02810       bpt_debug("[bptd] the leaf entry to insert has a non-valid key\n");     \
02811       return (-1);                                                            \
02812     }                                                                         \
02813                                                                               \
02814   BPT_LOAD(bpt, &root, BPT_GET_ROOT(bpt));                                    \
02815                                                                               \
02816   if (bpt_search_leaf(T, bpt, &root, &addr, lfentry->_key_) != 0)             \
02817     {                                                                         \
02818       bpt_debug("[bptd] no leaf present in the tree\n");                      \
02819       BPT_UNLOAD(bpt, &root);                                                 \
02820       return (-1);                                                            \
02821     }                                                                         \
02822                                                                               \
02823   BPT_UNLOAD(bpt, &root);                                                     \
02824   BPT_LOAD(bpt, &leaf, addr);                                                 \
02825                                                                               \
02826   if (bpt_check_collide(T, bpt, &leaf, lfentry->_key_, lfentry->_value_) != 0)\
02827     {                                                                         \
02828       bpt_debug("[bptd] this entry collide with an other\n");                 \
02829       BPT_UNLOAD(bpt, &leaf);                                                 \
02830       return (-1);                                                            \
02831     }                                                                         \
02832                                                                               \
02833   BPT_INIT_CBCTX(bpt, &cbctx);                                                \
02834                                                                               \
02835   if (bpt_insert(T, bpt, &leaf, lfentry, &cbctx, unused) != 0)                \
02836     {                                                                         \
02837       bpt_debug("[bptd] cannot insert the leaf entry\n");                     \
02838       BPT_UNLOAD(bpt, &leaf);                                                 \
02839       return (-1);                                                            \
02840     }                                                                         \
02841                                                                               \
02842   BPT_CALLBACK(bpt, &cbctx);                                                  \
02843                                                                               \
02844   BPT_UNLOAD(bpt, &leaf);                                                     \
02845                                                                               \
02846   return (0);                                                                 \
02847 }                                                                             \
02848                                                                               \
02849 /*                                                                            \
02850  * this function initializes the core structure and build the tree's          \
02851  * root node                                                                  \
02852  */                                                                           \
02853                                                                               \
02854 int                     bpt_init_##T(t_bpt(T)                   *bpt,         \
02855                                      t_bpt_blksz(T)             blksz,        \
02856                                      t_bpt_addr(T)              unusedvalue,  \
02857                                      t_bpt_flags                flags,        \
02858                                      t_bpt_load_fn(T)           load,         \
02859                                      t_bpt_unload_fn(T)         unload,       \
02860                                      t_bpt_callback_fn(T)       callback,     \
02861                                      t_bpt_unused(T)            *unused)      \
02862 {                                                                             \
02863   t_bpt_imm(T)          root;                                                 \
02864                                                                               \
02865   if (bpt_check_unused(T, bpt, unused, BPT_OPT_INIT) != 0)                    \
02866     {                                                                         \
02867       bpt_debug("[bptd] bad unused array\n");                                 \
02868       return (-1);                                                            \
02869     }                                                                         \
02870                                                                               \
02871   bpt->blksz = blksz;                                                         \
02872   bpt->unused = unusedvalue;                                                  \
02873   bpt->nodes = 0;                                                             \
02874   bpt->flags = flags;                                                         \
02875   bpt->nikeys = (bpt->blksz - sizeof(t_bpt_head(T))) /                        \
02876     sizeof(t_bpt_inentry(T));                                                 \
02877   bpt->nlkeys = (bpt->blksz - sizeof(t_bpt_head(T))) /                        \
02878     sizeof(t_bpt_lfentry(T));                                                 \
02879   bpt->height = BPT_INIT_HEIGHT;                                              \
02880                                                                               \
02881   if (bpt->nikeys < BPT_INIT_NIKEYS)                                          \
02882     {                                                                         \
02883       bpt_debug("[bptd] number of keys per internal node too low\n");         \
02884       return (-1);                                                            \
02885     }                                                                         \
02886                                                                               \
02887   if (bpt->nlkeys < BPT_INIT_NLKEYS)                                          \
02888     {                                                                         \
02889       bpt_debug("[bptd] number of keys per leaf node too low\n");             \
02890       return (-1);                                                            \
02891     }                                                                         \
02892                                                                               \
02893   BPT_RESERVE(bpt, unused, bpt->root);                                        \
02894                                                                               \
02895   bpt->load = load;                                                           \
02896   bpt->unload = unload;                                                       \
02897   bpt->callback = callback;                                                   \
02898                                                                               \
02899   BPT_LOAD(bpt, &root, BPT_GET_ROOT(bpt));                                    \
02900                                                                               \
02901   bpt_make_node(T, bpt, &root, BPT_TYPE_LEAF, bpt->unused);                   \
02902                                                                               \
02903   BPT_UNLOAD(bpt, &root);                                                     \
02904                                                                               \
02905   return (0);                                                                 \
02906 }                                                                             \
02907                                                                               \
02908 /*                                                                            \
02909  * this function cleans the node marking itself as unused                     \
02910  */                                                                           \
02911                                                                               \
02912 int                     bpt_clean_node_##T(t_bpt(T)             *bpt,         \
02913                                            t_bpt_imm(T)         *node,        \
02914                                            t_bpt_unused(T)      *unused)      \
02915 {                                                                             \
02916   t_bpt_head(T)         *head = BPT_HEAD(T, node);                            \
02917   t_bpt_ndi(T)          nkeys = BPT_NKEYS(T, bpt, node);                      \
02918   t_bpt_imm(T)          child;                                                \
02919   t_bpt_ndi(T)          i;                                                    \
02920                                                                               \
02921   BPT_RELEASE(bpt, unused, node->addr);                                       \
02922                                                                               \
02923   if (head->type == BPT_TYPE_LEAF)                                            \
02924     return (0);                                                               \
02925                                                                               \
02926   for (i = 0; (i < nkeys) &&                                                  \
02927          (BPT_GET_ENTRY(T, node, i, _value_) != bpt->unused);                 \
02928        i++)                                                                   \
02929     {                                                                         \
02930       BPT_LOAD(bpt, &child, BPT_GET_ENTRY(T, node, i, _value_));              \
02931                                                                               \
02932       if (bpt_clean_node(T, bpt, &child, unused) != 0)                        \
02933         {                                                                     \
02934           BPT_UNLOAD(bpt, &child);                                            \
02935           return (-1);                                                        \
02936         }                                                                     \
02937                                                                               \
02938       BPT_UNLOAD(bpt, &child);                                                \
02939     }                                                                         \
02940                                                                               \
02941   return (0);                                                                 \
02942 }                                                                             \
02943                                                                               \
02944 /*                                                                            \
02945  * this function cleans the tree, destroying each node.                       \
02946  *                                                                            \
02947  * the unused variable is finally filled with the addresses of the blocks     \
02948  * composing the tree.                                                        \
02949  */                                                                           \
02950                                                                               \
02951 int                     bpt_clean_##T(t_bpt(T)                  *bpt,         \
02952                                       t_bpt_unused(T)           *unused)      \
02953 {                                                                             \
02954   t_bpt_imm(T)          root;                                                 \
02955                                                                               \
02956   if (bpt_check_unused(T, bpt, unused, BPT_OPT_CLEAN) != 0)                   \
02957     {                                                                         \
02958       bpt_debug("[bptd] bad unused array\n");                                 \
02959       return (-1);                                                            \
02960     }                                                                         \
02961                                                                               \
02962   BPT_LOAD(bpt, &root, BPT_GET_ROOT(bpt));                                    \
02963                                                                               \
02964   if (bpt_clean_node(T, bpt, &root, unused) != 0)                             \
02965     {                                                                         \
02966       bpt_debug("[bptd] cannot clean the nodes\n");                           \
02967       BPT_UNLOAD(bpt, &root);                                                 \
02968       return (-1);                                                            \
02969     }                                                                         \
02970                                                                               \
02971   BPT_UNLOAD(bpt, &root);                                                     \
02972                                                                               \
02973   return (0);                                                                 \
02974 }
02975 
02976 #define         bpt_make(T, _t_bpt_blksz_, _t_bpt_ndi_, _t_bpt_uni_,          \
02977                          _t_bpt_nodes_, _t_bpt_height_, _t_bpt_key_,          \
02978                          _t_bpt_addr_, _t_bpt_inentry_, _t_bpt_lfentry_,      \
02979                          _key_, _value_)                                      \
02980   bpt_make_types(T, _t_bpt_blksz_, _t_bpt_ndi_, _t_bpt_uni_, _t_bpt_nodes_,   \
02981                  _t_bpt_height_, _t_bpt_key_, _t_bpt_addr_, _t_bpt_inentry_,  \
02982                  _t_bpt_lfentry_)                                             \
02983   bpt_make_protos(T)                                                          \
02984   bpt_make_functions(T, _key_, _value_)
02985 
02986 #endif

Generated on Wed May 24 23:04:16 2006 for LSE/OS by  doxygen 1.4.6