xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/ctxcsn.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
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