]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/ctxcsn.c
Context CSN Patch (2)
[openldap] / servers / slapd / back-bdb / ctxcsn.c
1 /* $OpenLDAP$ */
2 /*
3  * back-bdb Context CSN Management Routines
4  */
5 /* Copyright (c) 2003 by International Business Machines, Inc.
6  *
7  * International Business Machines, Inc. (hereinafter called IBM) grants
8  * permission under its copyrights to use, copy, modify, and distribute this
9  * Software with or without fee, provided that the above copyright notice and
10  * all paragraphs of this notice appear in all copies, and that the name of IBM
11  * not be used in connection with the marketing of any product incorporating
12  * the Software or modifications thereof, without specific, written prior
13  * permission.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
16  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
17  * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
18  * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
19  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
20  * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
21  */
22
23 #include "portable.h"
24
25 #include <stdio.h>
26
27 #include <ac/string.h>
28 #include <ac/time.h>
29
30 #include "back-bdb.h"
31 #include "external.h"
32
33 #ifdef LDAP_SYNC
34 int
35 bdb_csn_commit(
36         Operation *op,
37         SlapReply *rs,
38         DB_TXN *tid,
39         EntryInfo *ei,
40         EntryInfo **suffix_ei,
41         Entry **ctxcsn_e,
42         int *ctxcsn_added,
43         u_int32_t locker
44 )
45 {
46         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
47         struct berval   ctxcsn_rdn = { 0, NULL };
48         struct berval   ctxcsn_ndn = { 0, NULL };
49         EntryInfo               *ctxcsn_ei = NULL;
50         DB_LOCK                 ctxcsn_lock;
51         struct berval   *max_committed_csn = NULL;
52         DB_LOCK                 suffix_lock;
53         int                             rc, ret;
54         ID                              ctxcsn_id;
55
56         ber_str2bv( "cn=ldapsync", strlen("cn=ldapsync"), 0, &ctxcsn_rdn );
57         build_new_dn( &ctxcsn_ndn, &op->o_bd->be_nsuffix[0], &ctxcsn_rdn );
58
59         rc = bdb_dn2entry( op, tid, &ctxcsn_ndn, &ctxcsn_ei,
60                                                            0, locker, &ctxcsn_lock );
61
62         if ( ctxcsn_ei ) {
63                 *ctxcsn_e = ctxcsn_ei->bei_e;
64                 bdb_cache_entry_db_relock( bdb->bi_dbenv, locker, ctxcsn_ei, 1, 0, &ctxcsn_lock );
65         }
66
67         max_committed_csn = slap_get_commit_csn( op );
68
69         if ( max_committed_csn == NULL )
70                 return BDB_CSN_COMMIT;
71
72         *ctxcsn_added = 0;
73
74         switch( rc ) {
75         case 0:
76                 if ( !*ctxcsn_e ) {
77                         rs->sr_err = LDAP_OTHER;
78                         rs->sr_text = "context csn not present";
79                         return BDB_CSN_ABORT;
80                 } else {
81                         attr_delete( &(*ctxcsn_e)->e_attrs, slap_schema.si_ad_contextCSN );
82                         attr_merge_normalize_one( *ctxcsn_e, slap_schema.si_ad_contextCSN,
83                                                         max_committed_csn, NULL );
84                         ret = bdb_id2entry_update( op->o_bd, tid, *ctxcsn_e );
85                         switch ( ret ) {
86                         case 0 :
87                                 break;
88                         case DB_LOCK_DEADLOCK :
89                         case DB_LOCK_NOTGRANTED :
90                                 goto rewind;
91                         default :
92                                 rs->sr_err = ret;
93                                 rs->sr_text = "context csn update failed";
94                                 return BDB_CSN_ABORT;
95                         }
96                         ret = bdb_index_entry_add( op, tid, *ctxcsn_e );
97                         switch ( ret ) {
98                         case 0 :
99                                 break;
100                         case DB_LOCK_DEADLOCK :
101                         case DB_LOCK_NOTGRANTED :
102                                 goto rewind;
103                         default :
104                                 rs->sr_err = LDAP_OTHER;
105                                 rs->sr_text = "context csn indexing failed";
106                                 return BDB_CSN_ABORT;
107                         }
108                 }
109                 break;
110         case DB_NOTFOUND:
111                 if ( !be_issuffix( op->o_bd, &op->ora_e->e_nname ) ) {
112                         rc = bdb_dn2entry( op, tid, &op->o_bd->be_nsuffix[0], suffix_ei,
113                                                                         0, locker, &suffix_lock );
114                 } else {
115                         *suffix_ei = ei;
116                 }
117
118                 /* This serializes add. But this case is very rare : only once. */
119                 rs->sr_err = bdb_next_id( op->o_bd, NULL, &ctxcsn_id );
120                 if ( rs->sr_err != 0 ) {
121 #ifdef NEW_LOGGING
122                         LDAP_LOG ( OPERATION, ERR,
123                                 "bdb_add: next_id failed (%d)\n", rs->sr_err, 0, 0 );
124 #else
125                         Debug( LDAP_DEBUG_TRACE,
126                                 "bdb_add: next_id failed (%d)\n", rs->sr_err, 0, 0 );
127 #endif
128                         rs->sr_err = LDAP_OTHER;
129                         rs->sr_text = "internal error";
130                         return BDB_CSN_ABORT;
131                 }
132
133                 *ctxcsn_e = slap_create_context_csn_entry( op->o_bd, max_committed_csn );
134                 (*ctxcsn_e)->e_id = ctxcsn_id;
135                 *ctxcsn_added = 1;
136                 ret = bdb_dn2id_add( op, tid, *suffix_ei, *ctxcsn_e );
137                 switch ( ret ) {
138                 case 0 :
139                         break;
140                 case DB_LOCK_DEADLOCK :
141                 case DB_LOCK_NOTGRANTED :
142                         goto rewind;
143                 case DB_KEYEXIST :
144                         rs->sr_err = LDAP_OTHER;
145                         rs->sr_text = "context csn exists before contex prefix does";
146                         return BDB_CSN_ABORT;
147                 default :
148                         rs->sr_err = LDAP_OTHER;
149                         rs->sr_text = "context csn store failed";
150                         return BDB_CSN_ABORT;
151                 }
152                 ret = bdb_id2entry_add( op->o_bd, tid, *ctxcsn_e );
153                 switch ( ret ) {
154                 case 0 :
155                         break;
156                 case DB_LOCK_DEADLOCK :
157                 case DB_LOCK_NOTGRANTED :
158                         goto rewind;
159                 default :
160                         rs->sr_err = LDAP_OTHER;
161                         rs->sr_text = "context csn store failed";
162                         return BDB_CSN_ABORT;
163                 }
164                 ret = bdb_index_entry_add( op, tid, *ctxcsn_e );
165                 switch ( ret ) {
166                 case 0 :
167                         break;
168                 case DB_LOCK_DEADLOCK :
169                 case DB_LOCK_NOTGRANTED :
170                         goto rewind;
171                 default :
172                         rs->sr_err = LDAP_OTHER;
173                         rs->sr_text = "context csn indexing failed";
174                         return BDB_CSN_ABORT;
175                 }
176                 break;
177         case DB_LOCK_DEADLOCK:
178         case DB_LOCK_NOTGRANTED:
179                 goto rewind;
180         case LDAP_BUSY:
181                 rs->sr_err = rc;
182                 rs->sr_text = "ldap server busy";
183                 return BDB_CSN_ABORT;
184         default:
185                 rs->sr_err = LDAP_OTHER;
186                 rs->sr_text = "internal error";
187                 return BDB_CSN_ABORT;
188         }
189
190         return BDB_CSN_COMMIT;
191
192 rewind :
193         slap_rewind_commit_csn( op );
194         return BDB_CSN_RETRY;
195 }
196 #endif