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