Back to index

openldap  2.4.31
ctxcsn.c
Go to the documentation of this file.
00001 /* ctxcsn.c -- Context CSN Management Routines */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 2003-2012 The OpenLDAP Foundation.
00006  * Portions Copyright 2003 IBM Corporation.
00007  * All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted only as authorized by the OpenLDAP
00011  * Public License.
00012  *
00013  * A copy of this license is available in the file LICENSE in the
00014  * top-level directory of the distribution or, alternatively, at
00015  * <http://www.OpenLDAP.org/license.html>.
00016  */
00017 
00018 #include "portable.h"
00019 
00020 #include <stdio.h>
00021 
00022 #include <ac/string.h>
00023 #include <ac/socket.h>
00024 
00025 #include "lutil.h"
00026 #include "slap.h"
00027 #include "lutil_ldap.h"
00028 
00029 const struct berval slap_ldapsync_bv = BER_BVC("ldapsync");
00030 const struct berval slap_ldapsync_cn_bv = BER_BVC("cn=ldapsync");
00031 int slap_serverID;
00032 
00033 /* maxcsn->bv_val must point to a char buf[LDAP_PVT_CSNSTR_BUFSIZE] */
00034 void
00035 slap_get_commit_csn(
00036        Operation *op,
00037        struct berval *maxcsn,
00038        int *foundit
00039 )
00040 {
00041        struct slap_csn_entry *csne, *committed_csne = NULL;
00042        BackendDB *be = op->o_bd->bd_self;
00043        int sid = -1;
00044 
00045        if ( maxcsn ) {
00046               assert( maxcsn->bv_val != NULL );
00047               assert( maxcsn->bv_len >= LDAP_PVT_CSNSTR_BUFSIZE );
00048        }
00049        if ( foundit ) {
00050               *foundit = 0;
00051        }
00052 
00053        ldap_pvt_thread_mutex_lock( &be->be_pcl_mutex );
00054 
00055        if ( !BER_BVISEMPTY( &op->o_csn )) {
00056               sid = slap_parse_csn_sid( &op->o_csn );
00057        }
00058 
00059        LDAP_TAILQ_FOREACH( csne, be->be_pending_csn_list, ce_csn_link ) {
00060               if ( csne->ce_opid == op->o_opid && csne->ce_connid == op->o_connid ) {
00061                      csne->ce_state = SLAP_CSN_COMMIT;
00062                      if ( foundit ) *foundit = 1;
00063                      break;
00064               }
00065        }
00066 
00067        LDAP_TAILQ_FOREACH( csne, be->be_pending_csn_list, ce_csn_link ) {
00068               if ( sid != -1 && sid == csne->ce_sid ) {
00069                      if ( csne->ce_state == SLAP_CSN_COMMIT ) committed_csne = csne;
00070                      if ( csne->ce_state == SLAP_CSN_PENDING ) break;
00071               }
00072        }
00073 
00074        if ( maxcsn ) {
00075               if ( committed_csne ) {
00076                      if ( committed_csne->ce_csn.bv_len < maxcsn->bv_len )
00077                             maxcsn->bv_len = committed_csne->ce_csn.bv_len;
00078                      AC_MEMCPY( maxcsn->bv_val, committed_csne->ce_csn.bv_val,
00079                             maxcsn->bv_len+1 );
00080               } else {
00081                      maxcsn->bv_len = 0;
00082                      maxcsn->bv_val[0] = 0;
00083               }
00084        }
00085        ldap_pvt_thread_mutex_unlock( &be->be_pcl_mutex );
00086 }
00087 
00088 void
00089 slap_rewind_commit_csn( Operation *op )
00090 {
00091        struct slap_csn_entry *csne;
00092        BackendDB *be = op->o_bd->bd_self;
00093 
00094        ldap_pvt_thread_mutex_lock( &be->be_pcl_mutex );
00095 
00096        LDAP_TAILQ_FOREACH( csne, be->be_pending_csn_list, ce_csn_link ) {
00097               if ( csne->ce_opid == op->o_opid && csne->ce_connid == op->o_connid ) {
00098                      csne->ce_state = SLAP_CSN_PENDING;
00099                      break;
00100               }
00101        }
00102 
00103        ldap_pvt_thread_mutex_unlock( &be->be_pcl_mutex );
00104 }
00105 
00106 void
00107 slap_graduate_commit_csn( Operation *op )
00108 {
00109        struct slap_csn_entry *csne;
00110        BackendDB *be;
00111 
00112        if ( op == NULL ) return;
00113        if ( op->o_bd == NULL ) return;
00114        be = op->o_bd->bd_self;
00115 
00116        ldap_pvt_thread_mutex_lock( &be->be_pcl_mutex );
00117 
00118        LDAP_TAILQ_FOREACH( csne, be->be_pending_csn_list, ce_csn_link ) {
00119               if ( csne->ce_opid == op->o_opid && csne->ce_connid == op->o_connid ) {
00120                      LDAP_TAILQ_REMOVE( be->be_pending_csn_list,
00121                             csne, ce_csn_link );
00122                      Debug( LDAP_DEBUG_SYNC, "slap_graduate_commit_csn: removing %p %s\n",
00123                             csne->ce_csn.bv_val, csne->ce_csn.bv_val, 0 );
00124                      if ( op->o_csn.bv_val == csne->ce_csn.bv_val ) {
00125                             BER_BVZERO( &op->o_csn );
00126                      }
00127                      ch_free( csne->ce_csn.bv_val );
00128                      ch_free( csne );
00129                      break;
00130               }
00131        }
00132 
00133        ldap_pvt_thread_mutex_unlock( &be->be_pcl_mutex );
00134 
00135        return;
00136 }
00137 
00138 static struct berval ocbva[] = {
00139        BER_BVC("top"),
00140        BER_BVC("subentry"),
00141        BER_BVC("syncProviderSubentry"),
00142        BER_BVNULL
00143 };
00144 
00145 Entry *
00146 slap_create_context_csn_entry(
00147        Backend *be,
00148        struct berval *context_csn )
00149 {
00150        Entry* e;
00151 
00152        struct berval bv;
00153 
00154        e = entry_alloc();
00155 
00156        attr_merge( e, slap_schema.si_ad_objectClass,
00157               ocbva, NULL );
00158        attr_merge_one( e, slap_schema.si_ad_structuralObjectClass,
00159               &ocbva[1], NULL );
00160        attr_merge_one( e, slap_schema.si_ad_cn,
00161               (struct berval *)&slap_ldapsync_bv, NULL );
00162 
00163        if ( context_csn ) {
00164               attr_merge_one( e, slap_schema.si_ad_contextCSN,
00165                      context_csn, NULL );
00166        }
00167 
00168        BER_BVSTR( &bv, "{}" );
00169        attr_merge_one( e, slap_schema.si_ad_subtreeSpecification, &bv, NULL );
00170 
00171        build_new_dn( &e->e_name, &be->be_nsuffix[0],
00172               (struct berval *)&slap_ldapsync_cn_bv, NULL );
00173        ber_dupbv( &e->e_nname, &e->e_name );
00174 
00175        return e;
00176 }
00177 
00178 void
00179 slap_queue_csn(
00180        Operation *op,
00181        struct berval *csn )
00182 {
00183        struct slap_csn_entry *pending;
00184        BackendDB *be = op->o_bd->bd_self;
00185 
00186        pending = (struct slap_csn_entry *) ch_calloc( 1,
00187                      sizeof( struct slap_csn_entry ));
00188 
00189        Debug( LDAP_DEBUG_SYNC, "slap_queue_csn: queing %p %s\n", csn->bv_val, csn->bv_val, 0 );
00190 
00191        ldap_pvt_thread_mutex_lock( &be->be_pcl_mutex );
00192 
00193        ber_dupbv( &pending->ce_csn, csn );
00194        ber_bvreplace_x( &op->o_csn, &pending->ce_csn, op->o_tmpmemctx );
00195        pending->ce_sid = slap_parse_csn_sid( csn );
00196        pending->ce_connid = op->o_connid;
00197        pending->ce_opid = op->o_opid;
00198        pending->ce_state = SLAP_CSN_PENDING;
00199        LDAP_TAILQ_INSERT_TAIL( be->be_pending_csn_list,
00200               pending, ce_csn_link );
00201        ldap_pvt_thread_mutex_unlock( &be->be_pcl_mutex );
00202 }
00203 
00204 int
00205 slap_get_csn(
00206        Operation *op,
00207        struct berval *csn,
00208        int manage_ctxcsn )
00209 {
00210        if ( csn == NULL ) return LDAP_OTHER;
00211 
00212        csn->bv_len = ldap_pvt_csnstr( csn->bv_val, csn->bv_len, slap_serverID, 0 );
00213        if ( manage_ctxcsn )
00214               slap_queue_csn( op, csn );
00215 
00216        return LDAP_SUCCESS;
00217 }