1*549b59edSchristos /* $NetBSD: ctxcsn.c,v 1.3 2021/08/14 16:14:58 christos Exp $ */
24e6df137Slukem
32de962bdSlukem /* ctxcsn.c -- Context CSN Management Routines */
4d11b170bStron /* $OpenLDAP$ */
52de962bdSlukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
62de962bdSlukem *
7*549b59edSchristos * Copyright 2003-2021 The OpenLDAP Foundation.
82de962bdSlukem * Portions Copyright 2003 IBM Corporation.
92de962bdSlukem * All rights reserved.
102de962bdSlukem *
112de962bdSlukem * Redistribution and use in source and binary forms, with or without
122de962bdSlukem * modification, are permitted only as authorized by the OpenLDAP
132de962bdSlukem * Public License.
142de962bdSlukem *
152de962bdSlukem * A copy of this license is available in the file LICENSE in the
162de962bdSlukem * top-level directory of the distribution or, alternatively, at
172de962bdSlukem * <http://www.OpenLDAP.org/license.html>.
182de962bdSlukem */
192de962bdSlukem
20376af7d7Schristos #include <sys/cdefs.h>
21*549b59edSchristos __RCSID("$NetBSD: ctxcsn.c,v 1.3 2021/08/14 16:14:58 christos Exp $");
22376af7d7Schristos
232de962bdSlukem #include "portable.h"
242de962bdSlukem
252de962bdSlukem #include <stdio.h>
262de962bdSlukem
272de962bdSlukem #include <ac/string.h>
282de962bdSlukem #include <ac/socket.h>
292de962bdSlukem
302de962bdSlukem #include "lutil.h"
312de962bdSlukem #include "slap.h"
322de962bdSlukem #include "lutil_ldap.h"
332de962bdSlukem
342de962bdSlukem const struct berval slap_ldapsync_bv = BER_BVC("ldapsync");
352de962bdSlukem const struct berval slap_ldapsync_cn_bv = BER_BVC("cn=ldapsync");
362de962bdSlukem int slap_serverID;
372de962bdSlukem
38ef2f90d3Sadam /* maxcsn->bv_val must point to a char buf[LDAP_PVT_CSNSTR_BUFSIZE] */
392de962bdSlukem void
slap_get_commit_csn(Operation * op,struct berval * maxcsn,int * foundit)402de962bdSlukem slap_get_commit_csn(
412de962bdSlukem Operation *op,
424e6df137Slukem struct berval *maxcsn,
434e6df137Slukem int *foundit
442de962bdSlukem )
452de962bdSlukem {
462de962bdSlukem struct slap_csn_entry *csne, *committed_csne = NULL;
474e6df137Slukem BackendDB *be = op->o_bd->bd_self;
484e6df137Slukem int sid = -1;
492de962bdSlukem
502de962bdSlukem if ( maxcsn ) {
514e6df137Slukem assert( maxcsn->bv_val != NULL );
52ef2f90d3Sadam assert( maxcsn->bv_len >= LDAP_PVT_CSNSTR_BUFSIZE );
534e6df137Slukem }
544e6df137Slukem if ( foundit ) {
554e6df137Slukem *foundit = 0;
562de962bdSlukem }
572de962bdSlukem
584e6df137Slukem if ( !BER_BVISEMPTY( &op->o_csn )) {
594e6df137Slukem sid = slap_parse_csn_sid( &op->o_csn );
604e6df137Slukem }
614e6df137Slukem
62*549b59edSchristos ldap_pvt_thread_mutex_lock( &be->be_pcl_mutex );
63*549b59edSchristos
644e6df137Slukem LDAP_TAILQ_FOREACH( csne, be->be_pending_csn_list, ce_csn_link ) {
654e27b3e8Schristos if ( csne->ce_op == op ) {
662de962bdSlukem csne->ce_state = SLAP_CSN_COMMIT;
674e6df137Slukem if ( foundit ) *foundit = 1;
682de962bdSlukem break;
692de962bdSlukem }
702de962bdSlukem }
712de962bdSlukem
724e6df137Slukem LDAP_TAILQ_FOREACH( csne, be->be_pending_csn_list, ce_csn_link ) {
734e6df137Slukem if ( sid != -1 && sid == csne->ce_sid ) {
742de962bdSlukem if ( csne->ce_state == SLAP_CSN_COMMIT ) committed_csne = csne;
752de962bdSlukem if ( csne->ce_state == SLAP_CSN_PENDING ) break;
762de962bdSlukem }
774e6df137Slukem }
782de962bdSlukem
794e6df137Slukem if ( maxcsn ) {
804e6df137Slukem if ( committed_csne ) {
814e6df137Slukem if ( committed_csne->ce_csn.bv_len < maxcsn->bv_len )
824e6df137Slukem maxcsn->bv_len = committed_csne->ce_csn.bv_len;
834e6df137Slukem AC_MEMCPY( maxcsn->bv_val, committed_csne->ce_csn.bv_val,
844e6df137Slukem maxcsn->bv_len+1 );
854e6df137Slukem } else {
864e6df137Slukem maxcsn->bv_len = 0;
874e6df137Slukem maxcsn->bv_val[0] = 0;
884e6df137Slukem }
894e6df137Slukem }
904e6df137Slukem ldap_pvt_thread_mutex_unlock( &be->be_pcl_mutex );
912de962bdSlukem }
922de962bdSlukem
932de962bdSlukem void
slap_rewind_commit_csn(Operation * op)942de962bdSlukem slap_rewind_commit_csn( Operation *op )
952de962bdSlukem {
962de962bdSlukem struct slap_csn_entry *csne;
974e6df137Slukem BackendDB *be = op->o_bd->bd_self;
982de962bdSlukem
994e6df137Slukem ldap_pvt_thread_mutex_lock( &be->be_pcl_mutex );
1002de962bdSlukem
1014e6df137Slukem LDAP_TAILQ_FOREACH( csne, be->be_pending_csn_list, ce_csn_link ) {
1024e27b3e8Schristos if ( csne->ce_op == op ) {
1032de962bdSlukem csne->ce_state = SLAP_CSN_PENDING;
1042de962bdSlukem break;
1052de962bdSlukem }
1062de962bdSlukem }
1072de962bdSlukem
1084e6df137Slukem ldap_pvt_thread_mutex_unlock( &be->be_pcl_mutex );
1092de962bdSlukem }
1102de962bdSlukem
1112de962bdSlukem void
slap_graduate_commit_csn(Operation * op)1122de962bdSlukem slap_graduate_commit_csn( Operation *op )
1132de962bdSlukem {
1142de962bdSlukem struct slap_csn_entry *csne;
1154e6df137Slukem BackendDB *be;
1162de962bdSlukem
1172de962bdSlukem if ( op == NULL ) return;
1182de962bdSlukem if ( op->o_bd == NULL ) return;
1194e6df137Slukem be = op->o_bd->bd_self;
1202de962bdSlukem
1214e6df137Slukem ldap_pvt_thread_mutex_lock( &be->be_pcl_mutex );
1222de962bdSlukem
1234e6df137Slukem LDAP_TAILQ_FOREACH( csne, be->be_pending_csn_list, ce_csn_link ) {
1244e27b3e8Schristos if ( csne->ce_op == op ) {
1254e6df137Slukem LDAP_TAILQ_REMOVE( be->be_pending_csn_list,
1262de962bdSlukem csne, ce_csn_link );
1272de962bdSlukem Debug( LDAP_DEBUG_SYNC, "slap_graduate_commit_csn: removing %p %s\n",
128*549b59edSchristos csne, csne->ce_csn.bv_val );
1292de962bdSlukem if ( op->o_csn.bv_val == csne->ce_csn.bv_val ) {
1302de962bdSlukem BER_BVZERO( &op->o_csn );
1312de962bdSlukem }
1322de962bdSlukem ch_free( csne->ce_csn.bv_val );
1332de962bdSlukem ch_free( csne );
1342de962bdSlukem break;
1352de962bdSlukem }
1362de962bdSlukem }
1372de962bdSlukem
1384e6df137Slukem ldap_pvt_thread_mutex_unlock( &be->be_pcl_mutex );
1392de962bdSlukem
1402de962bdSlukem return;
1412de962bdSlukem }
1422de962bdSlukem
1432de962bdSlukem static struct berval ocbva[] = {
1442de962bdSlukem BER_BVC("top"),
1452de962bdSlukem BER_BVC("subentry"),
1462de962bdSlukem BER_BVC("syncProviderSubentry"),
1472de962bdSlukem BER_BVNULL
1482de962bdSlukem };
1492de962bdSlukem
1502de962bdSlukem Entry *
slap_create_context_csn_entry(Backend * be,struct berval * context_csn)1512de962bdSlukem slap_create_context_csn_entry(
1522de962bdSlukem Backend *be,
1532de962bdSlukem struct berval *context_csn )
1542de962bdSlukem {
1552de962bdSlukem Entry* e;
1562de962bdSlukem
1572de962bdSlukem struct berval bv;
1582de962bdSlukem
1592de962bdSlukem e = entry_alloc();
1602de962bdSlukem
1612de962bdSlukem attr_merge( e, slap_schema.si_ad_objectClass,
1622de962bdSlukem ocbva, NULL );
1632de962bdSlukem attr_merge_one( e, slap_schema.si_ad_structuralObjectClass,
1642de962bdSlukem &ocbva[1], NULL );
1652de962bdSlukem attr_merge_one( e, slap_schema.si_ad_cn,
1662de962bdSlukem (struct berval *)&slap_ldapsync_bv, NULL );
1672de962bdSlukem
1682de962bdSlukem if ( context_csn ) {
1692de962bdSlukem attr_merge_one( e, slap_schema.si_ad_contextCSN,
1702de962bdSlukem context_csn, NULL );
1712de962bdSlukem }
1722de962bdSlukem
1732de962bdSlukem BER_BVSTR( &bv, "{}" );
1742de962bdSlukem attr_merge_one( e, slap_schema.si_ad_subtreeSpecification, &bv, NULL );
1752de962bdSlukem
1762de962bdSlukem build_new_dn( &e->e_name, &be->be_nsuffix[0],
1772de962bdSlukem (struct berval *)&slap_ldapsync_cn_bv, NULL );
1782de962bdSlukem ber_dupbv( &e->e_nname, &e->e_name );
1792de962bdSlukem
1802de962bdSlukem return e;
1812de962bdSlukem }
1822de962bdSlukem
1832de962bdSlukem void
slap_queue_csn(Operation * op,struct berval * csn)1842de962bdSlukem slap_queue_csn(
1852de962bdSlukem Operation *op,
1862de962bdSlukem struct berval *csn )
1872de962bdSlukem {
1882de962bdSlukem struct slap_csn_entry *pending;
1894e6df137Slukem BackendDB *be = op->o_bd->bd_self;
1902de962bdSlukem
1912de962bdSlukem pending = (struct slap_csn_entry *) ch_calloc( 1,
1922de962bdSlukem sizeof( struct slap_csn_entry ));
1932de962bdSlukem
194*549b59edSchristos Debug( LDAP_DEBUG_SYNC, "slap_queue_csn: queueing %p %s\n", pending, csn->bv_val );
1952de962bdSlukem
1962de962bdSlukem ber_dupbv( &pending->ce_csn, csn );
1972de962bdSlukem ber_bvreplace_x( &op->o_csn, &pending->ce_csn, op->o_tmpmemctx );
1984e6df137Slukem pending->ce_sid = slap_parse_csn_sid( csn );
1994e27b3e8Schristos pending->ce_op = op;
2002de962bdSlukem pending->ce_state = SLAP_CSN_PENDING;
201*549b59edSchristos
202*549b59edSchristos ldap_pvt_thread_mutex_lock( &be->be_pcl_mutex );
2034e6df137Slukem LDAP_TAILQ_INSERT_TAIL( be->be_pending_csn_list,
2042de962bdSlukem pending, ce_csn_link );
2054e6df137Slukem ldap_pvt_thread_mutex_unlock( &be->be_pcl_mutex );
2062de962bdSlukem }
2072de962bdSlukem
2082de962bdSlukem int
slap_get_csn(Operation * op,struct berval * csn,int manage_ctxcsn)2092de962bdSlukem slap_get_csn(
2102de962bdSlukem Operation *op,
2112de962bdSlukem struct berval *csn,
2122de962bdSlukem int manage_ctxcsn )
2132de962bdSlukem {
2142de962bdSlukem if ( csn == NULL ) return LDAP_OTHER;
2152de962bdSlukem
216ef2f90d3Sadam csn->bv_len = ldap_pvt_csnstr( csn->bv_val, csn->bv_len, slap_serverID, 0 );
217*549b59edSchristos Debug( LDAP_DEBUG_SYNC, "slap_get_csn: %s generated new csn=%s manage=%d\n",
218*549b59edSchristos op->o_log_prefix, csn->bv_val, manage_ctxcsn );
2192de962bdSlukem if ( manage_ctxcsn )
2202de962bdSlukem slap_queue_csn( op, csn );
2212de962bdSlukem
2222de962bdSlukem return LDAP_SUCCESS;
2232de962bdSlukem }
224