]> git.sur5r.net Git - openldap/blob - libraries/libmdb/midl.c
Use FNV-1A hash to generate unique mutex names
[openldap] / libraries / libmdb / midl.c
1 /**     @file midl.c
2  *      @brief ldap bdb back-end ID List functions */
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 2000-2011 The OpenLDAP Foundation.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in the file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17
18 #include <limits.h>
19 #include <string.h>
20 #include <sys/types.h>
21 #include <assert.h>
22 #include "midl.h"
23
24 /** @defgroup internal  MDB Internals
25  *      @{
26  */
27 /** @defgroup idls      ID List Management
28  *      @{
29  */
30 #define CMP(x,y)         ( (x) < (y) ? -1 : (x) > (y) )
31
32 #if 0   /* superseded by append/sort */
33 static unsigned mdb_midl_search( IDL ids, ID id )
34 {
35         /*
36          * binary search of id in ids
37          * if found, returns position of id
38          * if not found, returns first position greater than id
39          */
40         unsigned base = 0;
41         unsigned cursor = 0;
42         int val = 0;
43         unsigned n = ids[0];
44
45         while( 0 < n ) {
46                 int pivot = n >> 1;
47                 cursor = base + pivot;
48                 val = CMP( ids[cursor + 1], id );
49
50                 if( val < 0 ) {
51                         n = pivot;
52
53                 } else if ( val > 0 ) {
54                         base = cursor + 1;
55                         n -= pivot + 1;
56
57                 } else {
58                         return cursor + 1;
59                 }
60         }
61         
62         if( val > 0 ) {
63                 return cursor + 2;
64         } else {
65                 return cursor + 1;
66         }
67 }
68
69 int mdb_midl_insert( IDL ids, ID id )
70 {
71         unsigned x, i;
72
73         if (MDB_IDL_IS_RANGE( ids )) {
74                 /* if already in range, treat as a dup */
75                 if (id >= MDB_IDL_FIRST(ids) && id <= MDB_IDL_LAST(ids))
76                         return -1;
77                 if (id < MDB_IDL_FIRST(ids))
78                         ids[1] = id;
79                 else if (id > MDB_IDL_LAST(ids))
80                         ids[2] = id;
81                 return 0;
82         }
83
84         x = mdb_midl_search( ids, id );
85         assert( x > 0 );
86
87         if( x < 1 ) {
88                 /* internal error */
89                 return -2;
90         }
91
92         if ( x <= ids[0] && ids[x] == id ) {
93                 /* duplicate */
94                 assert(0);
95                 return -1;
96         }
97
98         if ( ++ids[0] >= MDB_IDL_DB_MAX ) {
99                 if( id < ids[1] ) {
100                         ids[1] = id;
101                         ids[2] = ids[ids[0]-1];
102                 } else if ( ids[ids[0]-1] < id ) {
103                         ids[2] = id;
104                 } else {
105                         ids[2] = ids[ids[0]-1];
106                 }
107                 ids[0] = NOID;
108         
109         } else {
110                 /* insert id */
111                 for (i=ids[0]; i>x; i--)
112                         ids[i] = ids[i-1];
113                 ids[x] = id;
114         }
115
116         return 0;
117 }
118 #endif
119
120 int mdb_midl_append( IDL ids, ID id )
121 {
122         /* Too big? */
123         if (ids[0] >= MDB_IDL_UM_MAX)
124                 return -1;
125         ids[0]++;
126         ids[ids[0]] = id;
127         return 0;
128 }
129
130 /* Quicksort + Insertion sort for small arrays */
131
132 #define SMALL   8
133 #define SWAP(a,b)       { itmp=(a); (a)=(b); (b)=itmp; }
134
135 void
136 mdb_midl_sort( ID *ids )
137 {
138         /* Max possible depth of int-indexed tree * 2 items/level */
139         int istack[sizeof(int)*CHAR_BIT * 2];
140         int i,j,k,l,ir,jstack;
141         ID a, itmp;
142
143         ir = ids[0];
144         l = 1;
145         jstack = 0;
146         for(;;) {
147                 if (ir - l < SMALL) {   /* Insertion sort */
148                         for (j=l+1;j<=ir;j++) {
149                                 a = ids[j];
150                                 for (i=j-1;i>=1;i--) {
151                                         if (ids[i] >= a) break;
152                                         ids[i+1] = ids[i];
153                                 }
154                                 ids[i+1] = a;
155                         }
156                         if (jstack == 0) break;
157                         ir = istack[jstack--];
158                         l = istack[jstack--];
159                 } else {
160                         k = (l + ir) >> 1;      /* Choose median of left, center, right */
161                         SWAP(ids[k], ids[l+1]);
162                         if (ids[l] < ids[ir]) {
163                                 SWAP(ids[l], ids[ir]);
164                         }
165                         if (ids[l+1] < ids[ir]) {
166                                 SWAP(ids[l+1], ids[ir]);
167                         }
168                         if (ids[l] < ids[l+1]) {
169                                 SWAP(ids[l], ids[l+1]);
170                         }
171                         i = l+1;
172                         j = ir;
173                         a = ids[l+1];
174                         for(;;) {
175                                 do i++; while(ids[i] > a);
176                                 do j--; while(ids[j] < a);
177                                 if (j < i) break;
178                                 SWAP(ids[i],ids[j]);
179                         }
180                         ids[l+1] = ids[j];
181                         ids[j] = a;
182                         jstack += 2;
183                         if (ir-i+1 >= j-1) {
184                                 istack[jstack] = ir;
185                                 istack[jstack-1] = i;
186                                 ir = j-1;
187                         } else {
188                                 istack[jstack] = j-1;
189                                 istack[jstack-1] = l;
190                                 l = i;
191                         }
192                 }
193         }
194 }
195
196 unsigned mdb_mid2l_search( ID2L ids, ID id )
197 {
198         /*
199          * binary search of id in ids
200          * if found, returns position of id
201          * if not found, returns first position greater than id
202          */
203         unsigned base = 0;
204         unsigned cursor = 0;
205         int val = 0;
206         unsigned n = ids[0].mid;
207
208         while( 0 < n ) {
209                 int pivot = n >> 1;
210                 cursor = base + pivot;
211                 val = CMP( id, ids[cursor + 1].mid );
212
213                 if( val < 0 ) {
214                         n = pivot;
215
216                 } else if ( val > 0 ) {
217                         base = cursor + 1;
218                         n -= pivot + 1;
219
220                 } else {
221                         return cursor + 1;
222                 }
223         }
224
225         if( val > 0 ) {
226                 return cursor + 2;
227         } else {
228                 return cursor + 1;
229         }
230 }
231
232 int mdb_mid2l_insert( ID2L ids, ID2 *id )
233 {
234         unsigned x, i;
235
236         x = mdb_mid2l_search( ids, id->mid );
237         assert( x > 0 );
238
239         if( x < 1 ) {
240                 /* internal error */
241                 return -2;
242         }
243
244         if ( x <= ids[0].mid && ids[x].mid == id->mid ) {
245                 /* duplicate */
246                 return -1;
247         }
248
249         if ( ids[0].mid >= MDB_IDL_UM_MAX ) {
250                 /* too big */
251                 return -2;
252
253         } else {
254                 /* insert id */
255                 ids[0].mid++;
256                 for (i=ids[0].mid; i>x; i--)
257                         ids[i] = ids[i-1];
258                 ids[x] = *id;
259         }
260
261         return 0;
262 }
263 /** @} */
264 /** @} */