]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/nextid.c
f7a3e6dfbae49587abe6d10f4458f6f140c4addc
[openldap] / servers / slapd / back-bdb / nextid.c
1 /* init.c - initialize bdb backend */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11 #include <ac/string.h>
12
13 #include "back-bdb.h"
14
15 int bdb_next_id( BackendDB *be, DB_TXN *tid, ID *out )
16 {
17         struct bdb_info *bdb = (struct bdb_info *) be->be_private;
18         int rc;
19         ID kid = NOID;
20         ID id;
21         DBT key, data;
22         DB_TXN  *ltid = NULL;
23
24         DBTzero( &key );
25         key.data = (char *) &kid;
26         key.size = sizeof( kid );
27
28         DBTzero( &data );
29         data.data = (char *) &id;
30         data.ulen = sizeof( id );
31         data.flags = DB_DBT_USERMEM;
32
33         if( 0 ) {
34 retry:  if( tid != NULL ) {
35                         /* nested transaction, abort and return */
36                         (void) txn_abort( ltid );
37                         Debug( LDAP_DEBUG_ANY,
38                                 "=> bdb_next_id: aborted!\n",
39                                 0, 0, 0 );
40                         return rc;
41                 }
42                 rc = txn_abort( ltid );
43                 if( rc != 0 ) {
44                         Debug( LDAP_DEBUG_ANY,
45                                 "=> bdb_next_id: txn_abort failed: %s (%d)\n",
46                                 db_strerror(rc), rc, 0 );
47                         return rc;
48                 }
49         }
50
51         if( bdb->bi_txn ) {
52                 rc = txn_begin( bdb->bi_dbenv, tid, &ltid, 0 );
53                 if( rc != 0 ) {
54                         Debug( LDAP_DEBUG_ANY,
55                                 "=> bdb_next_id: txn_begin failed: %s (%d)\n",
56                                 db_strerror(rc), rc, 0 );
57                         return rc;
58                 }
59         }
60
61         /* get existing value for read/modify/write */
62         rc = bdb->bi_nextid->bdi_db->get( bdb->bi_nextid->bdi_db,
63                 ltid, &key, &data, DB_RMW );
64
65         switch(rc) {
66         case DB_LOCK_DEADLOCK:
67         case DB_LOCK_NOTGRANTED:
68                 goto retry;
69
70         case DB_NOTFOUND:
71                 id = 0;
72                 break;
73
74         case 0:
75                 if ( data.size != sizeof( id ) ) {
76                         Debug( LDAP_DEBUG_ANY,
77                                 "=> bdb_next_id: get size mismatch: expected %ld, got %ld\n",
78                                 (long) sizeof( id ), (long) data.size, 0 );
79                         rc = -1;
80                         goto done;
81                 }
82                 break;
83
84         default:
85                 Debug( LDAP_DEBUG_ANY,
86                         "=> bdb_next_id: get failed: %s (%d)\n",
87                         db_strerror(rc), rc, 0 );
88                 goto done;
89         }
90
91         if( bdb->bi_lastid > id ) id = bdb->bi_lastid;
92
93         id++;
94         data.size = sizeof( id );
95
96         /* put new value */
97         rc = bdb->bi_nextid->bdi_db->put( bdb->bi_nextid->bdi_db,
98                 ltid, &key, &data, 0 );
99
100         switch(rc) {
101         case DB_LOCK_DEADLOCK:
102         case DB_LOCK_NOTGRANTED:
103                 goto retry;
104
105         case 0:
106                 *out = id;
107
108                 bdb->bi_lastid = id;
109
110                 if (bdb->bi_txn) {
111                         rc = txn_commit( ltid, 0 );
112                         ltid = NULL;
113                 }
114
115                 if( rc != 0 ) {
116                         Debug( LDAP_DEBUG_ANY,
117                                 "=> bdb_next_id: commit failed: %s (%d)\n",
118                                 db_strerror(rc), rc, 0 );
119                 }
120                 break;
121
122         default:
123                 Debug( LDAP_DEBUG_ANY,
124                         "=> bdb_next_id: put failed: %s (%d)\n",
125                         db_strerror(rc), rc, 0 );
126 done:   (void) txn_abort( ltid );
127         }
128
129         return rc;
130 }
131
132 int bdb_last_id( BackendDB *be, DB_TXN *tid )
133 {
134         struct bdb_info *bdb = (struct bdb_info *) be->be_private;
135         int rc;
136         ID kid = NOID;
137         ID id;
138         DBT key, data;
139
140         DBTzero( &key );
141         key.data = (char *) &kid;
142         key.size = sizeof( kid );
143
144         DBTzero( &data );
145         data.data = (char *) &id;
146         data.ulen = sizeof( id );
147         data.flags = DB_DBT_USERMEM;
148
149         /* get existing value for read/modify/write */
150         rc = bdb->bi_nextid->bdi_db->get( bdb->bi_nextid->bdi_db,
151                 tid, &key, &data, 0 );
152
153         switch(rc) {
154         case DB_NOTFOUND:
155                 id = 0;
156                 rc = 0;
157                 break;
158
159         case 0:
160                 if ( data.size != sizeof( id ) ) {
161                         Debug( LDAP_DEBUG_ANY,
162                                 "=> bdb_last_id: get size mismatch: expected %ld, got %ld\n",
163                                 (long) sizeof( id ), (long) data.size, 0 );
164                         rc = -1;
165                         goto done;
166                 }
167                 break;
168
169         default:
170                 Debug( LDAP_DEBUG_ANY,
171                         "=> bdb_next_id: get failed: %s (%d)\n",
172                         db_strerror(rc), rc, 0 );
173                 goto done;
174         }
175
176         bdb->bi_lastid = id;
177
178 done:
179         return rc;
180 }