1 /* $NetBSD: ctxcsn.c,v 1.1.1.6 2018/02/06 01:53:15 christos Exp $ */ 2 3 /* ctxcsn.c -- Context CSN Management Routines */ 4 /* $OpenLDAP$ */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 2003-2017 The OpenLDAP Foundation. 8 * Portions Copyright 2003 IBM Corporation. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted only as authorized by the OpenLDAP 13 * Public License. 14 * 15 * A copy of this license is available in the file LICENSE in the 16 * top-level directory of the distribution or, alternatively, at 17 * <http://www.OpenLDAP.org/license.html>. 18 */ 19 20 #include <sys/cdefs.h> 21 __RCSID("$NetBSD: ctxcsn.c,v 1.1.1.6 2018/02/06 01:53:15 christos Exp $"); 22 23 #include "portable.h" 24 25 #include <stdio.h> 26 27 #include <ac/string.h> 28 #include <ac/socket.h> 29 30 #include "lutil.h" 31 #include "slap.h" 32 #include "lutil_ldap.h" 33 34 const struct berval slap_ldapsync_bv = BER_BVC("ldapsync"); 35 const struct berval slap_ldapsync_cn_bv = BER_BVC("cn=ldapsync"); 36 int slap_serverID; 37 38 /* maxcsn->bv_val must point to a char buf[LDAP_PVT_CSNSTR_BUFSIZE] */ 39 void 40 slap_get_commit_csn( 41 Operation *op, 42 struct berval *maxcsn, 43 int *foundit 44 ) 45 { 46 struct slap_csn_entry *csne, *committed_csne = NULL; 47 BackendDB *be = op->o_bd->bd_self; 48 int sid = -1; 49 50 if ( maxcsn ) { 51 assert( maxcsn->bv_val != NULL ); 52 assert( maxcsn->bv_len >= LDAP_PVT_CSNSTR_BUFSIZE ); 53 } 54 if ( foundit ) { 55 *foundit = 0; 56 } 57 58 ldap_pvt_thread_mutex_lock( &be->be_pcl_mutex ); 59 60 if ( !BER_BVISEMPTY( &op->o_csn )) { 61 sid = slap_parse_csn_sid( &op->o_csn ); 62 } 63 64 LDAP_TAILQ_FOREACH( csne, be->be_pending_csn_list, ce_csn_link ) { 65 if ( csne->ce_opid == op->o_opid && csne->ce_connid == op->o_connid ) { 66 csne->ce_state = SLAP_CSN_COMMIT; 67 if ( foundit ) *foundit = 1; 68 break; 69 } 70 } 71 72 LDAP_TAILQ_FOREACH( csne, be->be_pending_csn_list, ce_csn_link ) { 73 if ( sid != -1 && sid == csne->ce_sid ) { 74 if ( csne->ce_state == SLAP_CSN_COMMIT ) committed_csne = csne; 75 if ( csne->ce_state == SLAP_CSN_PENDING ) break; 76 } 77 } 78 79 if ( maxcsn ) { 80 if ( committed_csne ) { 81 if ( committed_csne->ce_csn.bv_len < maxcsn->bv_len ) 82 maxcsn->bv_len = committed_csne->ce_csn.bv_len; 83 AC_MEMCPY( maxcsn->bv_val, committed_csne->ce_csn.bv_val, 84 maxcsn->bv_len+1 ); 85 } else { 86 maxcsn->bv_len = 0; 87 maxcsn->bv_val[0] = 0; 88 } 89 } 90 ldap_pvt_thread_mutex_unlock( &be->be_pcl_mutex ); 91 } 92 93 void 94 slap_rewind_commit_csn( Operation *op ) 95 { 96 struct slap_csn_entry *csne; 97 BackendDB *be = op->o_bd->bd_self; 98 99 ldap_pvt_thread_mutex_lock( &be->be_pcl_mutex ); 100 101 LDAP_TAILQ_FOREACH( csne, be->be_pending_csn_list, ce_csn_link ) { 102 if ( csne->ce_opid == op->o_opid && csne->ce_connid == op->o_connid ) { 103 csne->ce_state = SLAP_CSN_PENDING; 104 break; 105 } 106 } 107 108 ldap_pvt_thread_mutex_unlock( &be->be_pcl_mutex ); 109 } 110 111 void 112 slap_graduate_commit_csn( Operation *op ) 113 { 114 struct slap_csn_entry *csne; 115 BackendDB *be; 116 117 if ( op == NULL ) return; 118 if ( op->o_bd == NULL ) return; 119 be = op->o_bd->bd_self; 120 121 ldap_pvt_thread_mutex_lock( &be->be_pcl_mutex ); 122 123 LDAP_TAILQ_FOREACH( csne, be->be_pending_csn_list, ce_csn_link ) { 124 if ( csne->ce_opid == op->o_opid && csne->ce_connid == op->o_connid ) { 125 LDAP_TAILQ_REMOVE( be->be_pending_csn_list, 126 csne, ce_csn_link ); 127 Debug( LDAP_DEBUG_SYNC, "slap_graduate_commit_csn: removing %p %s\n", 128 csne, csne->ce_csn.bv_val, 0 ); 129 if ( op->o_csn.bv_val == csne->ce_csn.bv_val ) { 130 BER_BVZERO( &op->o_csn ); 131 } 132 ch_free( csne->ce_csn.bv_val ); 133 ch_free( csne ); 134 break; 135 } 136 } 137 138 ldap_pvt_thread_mutex_unlock( &be->be_pcl_mutex ); 139 140 return; 141 } 142 143 static struct berval ocbva[] = { 144 BER_BVC("top"), 145 BER_BVC("subentry"), 146 BER_BVC("syncProviderSubentry"), 147 BER_BVNULL 148 }; 149 150 Entry * 151 slap_create_context_csn_entry( 152 Backend *be, 153 struct berval *context_csn ) 154 { 155 Entry* e; 156 157 struct berval bv; 158 159 e = entry_alloc(); 160 161 attr_merge( e, slap_schema.si_ad_objectClass, 162 ocbva, NULL ); 163 attr_merge_one( e, slap_schema.si_ad_structuralObjectClass, 164 &ocbva[1], NULL ); 165 attr_merge_one( e, slap_schema.si_ad_cn, 166 (struct berval *)&slap_ldapsync_bv, NULL ); 167 168 if ( context_csn ) { 169 attr_merge_one( e, slap_schema.si_ad_contextCSN, 170 context_csn, NULL ); 171 } 172 173 BER_BVSTR( &bv, "{}" ); 174 attr_merge_one( e, slap_schema.si_ad_subtreeSpecification, &bv, NULL ); 175 176 build_new_dn( &e->e_name, &be->be_nsuffix[0], 177 (struct berval *)&slap_ldapsync_cn_bv, NULL ); 178 ber_dupbv( &e->e_nname, &e->e_name ); 179 180 return e; 181 } 182 183 void 184 slap_queue_csn( 185 Operation *op, 186 struct berval *csn ) 187 { 188 struct slap_csn_entry *pending; 189 BackendDB *be = op->o_bd->bd_self; 190 191 pending = (struct slap_csn_entry *) ch_calloc( 1, 192 sizeof( struct slap_csn_entry )); 193 194 Debug( LDAP_DEBUG_SYNC, "slap_queue_csn: queueing %p %s\n", pending, csn->bv_val, 0 ); 195 196 ldap_pvt_thread_mutex_lock( &be->be_pcl_mutex ); 197 198 ber_dupbv( &pending->ce_csn, csn ); 199 ber_bvreplace_x( &op->o_csn, &pending->ce_csn, op->o_tmpmemctx ); 200 pending->ce_sid = slap_parse_csn_sid( csn ); 201 pending->ce_connid = op->o_connid; 202 pending->ce_opid = op->o_opid; 203 pending->ce_state = SLAP_CSN_PENDING; 204 LDAP_TAILQ_INSERT_TAIL( be->be_pending_csn_list, 205 pending, ce_csn_link ); 206 ldap_pvt_thread_mutex_unlock( &be->be_pcl_mutex ); 207 } 208 209 int 210 slap_get_csn( 211 Operation *op, 212 struct berval *csn, 213 int manage_ctxcsn ) 214 { 215 if ( csn == NULL ) return LDAP_OTHER; 216 217 csn->bv_len = ldap_pvt_csnstr( csn->bv_val, csn->bv_len, slap_serverID, 0 ); 218 if ( manage_ctxcsn ) 219 slap_queue_csn( op, csn ); 220 221 return LDAP_SUCCESS; 222 } 223