OpenLDAP synchronization based replication engine

This commit is contained in:
Jong Hyuk Choi 2003-04-21 14:08:13 +00:00
parent 3efe7398c9
commit 86a46c267a
7 changed files with 538 additions and 4 deletions

View File

@ -120,10 +120,19 @@ BackendInfo *backendInfo = NULL;
int nBackendDB = 0;
BackendDB *backendDB = NULL;
#ifdef LDAP_SYNCREPL
ldap_pvt_thread_pool_t syncrepl_pool;
int syncrepl_pool_max = SLAP_MAX_SYNCREPL_THREADS;
#endif
int backend_init(void)
{
int rc = -1;
#ifdef LDAP_SYNCREPL
ldap_pvt_thread_pool_init( &syncrepl_pool, syncrepl_pool_max, 0 );
#endif
if((nBackendInfo != 0) || (backendInfo != NULL)) {
/* already initialized */
#ifdef NEW_LOGGING
@ -231,6 +240,10 @@ int backend_startup(Backend *be)
int i;
int rc = 0;
#ifdef LDAP_SYNCREPL
init_syncrepl();
#endif
if( ! ( nBackendDB > 0 ) ) {
/* no databases */
#ifdef NEW_LOGGING
@ -332,6 +345,25 @@ int backend_startup(Backend *be)
return rc;
}
}
#ifdef LDAP_SYNCREPL
if ( backendDB[i].syncinfo != NULL ) {
int ret;
ret = ldap_pvt_thread_pool_submit( &syncrepl_pool,
do_syncrepl, (void *) &backendDB[i] );
if ( ret != 0 ) {
#ifdef NEW_LOGGING
LDAP_LOG( BACKEND, CRIT,
"syncrepl thread pool submit failed (%d)\n",
ret, 0, 0 );
#else
Debug( LDAP_DEBUG_ANY,
"ldap_pvt_thread_pool_submit failed (%d) \n",
ret, 0, 0 );
#endif
}
}
#endif
}
return rc;
@ -414,6 +446,10 @@ int backend_destroy(void)
int i;
BackendDB *bd;
#ifdef LDAP_SYNCREPL
ldap_pvt_thread_pool_destroy( &syncrepl_pool, 1 );
#endif
/* destroy each backend database */
for( i = 0, bd = backendDB; i < nBackendDB; i++, bd++ ) {
if ( bd->bd_info->bi_db_destroy ) {
@ -493,6 +529,10 @@ backend_db_init(
be->be_requires = global_requires;
be->be_ssf_set = global_ssf_set;
#ifdef LDAP_SYNCREPL
be->syncinfo = NULL;
#endif
/* assign a default depth limit for alias deref */
be->be_max_deref_depth = SLAPD_DEFAULT_MAXDEREFDEPTH;

View File

@ -80,6 +80,11 @@ static int fp_parse_line(int lineno, char *line);
static char *strtok_quote(char *line, char *sep);
static int load_ucdata(char *path);
#ifdef LDAP_SYNCREPL
static void add_syncrepl LDAP_P(( Backend *, char **, int ));
static int parse_syncrepl_line LDAP_P(( char **, int, syncinfo_t *));
#endif
int
read_config( const char *fname, int depth )
{
@ -1723,6 +1728,14 @@ read_config( const char *fname, int depth )
ldap_syslog += atoi( cargv[1] );
}
#ifdef LDAP_SYNCREPL
/* list of sync replication information in this backend (slave o
nly) */
} else if ( strcasecmp( cargv[0], "syncrepl" ) == 0 ) {
add_syncrepl( be, cargv, cargc );
#endif
/* list of replicas of the data in this backend (master only) */
} else if ( strcasecmp( cargv[0], "replica" ) == 0 ) {
if ( cargc < 2 ) {
@ -2655,3 +2668,319 @@ config_destroy( )
free( default_passwd_hash );
acl_destroy( global_acl, NULL );
}
#ifdef LDAP_SYNCREPL
static void
add_syncrepl(
Backend *be,
char **cargv,
int cargc
)
{
syncinfo_t *si;
si = be->syncinfo = (syncinfo_t *) ch_calloc( 1, sizeof( syncinfo_t ) );
if ( si == NULL ) {
#ifdef NEW_LOGGING
LDAP_LOG( CONFIG, ERR, "out of memory in add_syncrepl\n", 0, 0,0 );
#else
Debug( LDAP_DEBUG_ANY, "out of memory in add_syncrepl\n", 0, 0, 0 );
#endif
exit( EXIT_FAILURE );
}
if ( parse_syncrepl_line( cargv, cargc, si ) < 0 ) {
/* Something bad happened - back out */
#ifdef NEW_LOGGING
LDAP_LOG( CONFIG, ERR, "failed to add syncinfo\n", 0, 0,0 );
#else
Debug( LDAP_DEBUG_ANY, "failed to add syncinfo\n", 0, 0, 0 );
#endif
free( si );
be->syncinfo = NULL;
} else {
#ifdef NEW_LOGGING
LDAP_LOG ( CONFIG, RESULTS,
"add_syncrepl: Config: ** successfully added syncrepl \"%s%d\"\n",
si->mastername == NULL ? "(null)" : si->mastername,
si->masterport, 0 );
#else
Debug( LDAP_DEBUG_CONFIG,
"Config: ** successfully added syncrepl \"%s:%d\"\n",
si->mastername == NULL ? "(null)" : si->mastername,
si->masterport, 0 );
#endif
}
si->be = be;
}
#define GOT_ID 0x0001
#define GOT_HOST 0x0002
#define GOT_DN 0x0004
#define GOT_METHOD 0x0008
#define GOT_MECH 0x0010
#define GOT_FILTER 0x0020
#define GOT_SEARCHBASE 0x0040
#define GOT_SCOPE 0x0080
#define GOT_ATTRS 0x0100
#define GOT_TYPE 0x0200
#define GOT_INTERVAL 0x0400
#define GOT_LASTMOD 0x0800
#define GOT_ALL 0x0FFF
static int
parse_syncrepl_line(
char **cargv,
int cargc,
syncinfo_t *si
)
{
int gots = 0;
int i, j;
char *hp, *val;
int nr_attr = 0;
for ( i = 1; i < cargc; i++ ) {
if ( !strncasecmp( cargv[ i ], IDSTR, sizeof( IDSTR ) - 1 )) {
/* '\0' string terminator accounts for '=' */
val = cargv[ i ] + sizeof( IDSTR );
si->id = atoi( val );
gots |= GOT_ID;
} else if ( !strncasecmp( cargv[ i ], MASTERSTR,
sizeof( MASTERSTR ) - 1 )) {
val = cargv[ i ] + sizeof( MASTERSTR );
si->masteruri = strdup( val );
if (( hp = strchr( val, ':' )) != NULL ) {
if ( *( hp + 1 ) == '/' ) {
if ( *( hp + 2 ) == '/' ) {
val = hp + 3;
}
if (( hp = strchr( hp+1, ':' )) != NULL ) {
*hp = '\0';
hp++;
si->masterport = atoi( hp );
}
} else {
*hp = '\0';
hp++;
si->masterport = atoi( hp );
}
}
if ( si->masterport <= 0 ) {
si->masterport = 0;
}
si->mastername = strdup( val );
gots |= GOT_HOST;
} else if ( !strncasecmp( cargv[ i ], TLSSTR, sizeof( TLSSTR ) - 1 ) ) {
val = cargv[ i ] + sizeof( TLSSTR );
if( !strcasecmp( val, TLSCRITICALSTR ) ) {
si->tls = TLS_CRITICAL;
} else {
si->tls = TLS_ON;
}
} else if ( !strncasecmp( cargv[ i ],
"binddn", sizeof( BINDDNSTR ) - 1 ) ) {
val = cargv[ i ] + sizeof( BINDDNSTR );
si->binddn = strdup( val );
gots |= GOT_DN;
} else if ( !strncasecmp( cargv[ i ], BINDMETHSTR,
sizeof( BINDMETHSTR ) - 1 ) ) {
val = cargv[ i ] + sizeof( BINDMETHSTR );
if ( !strcasecmp( val, SIMPLESTR )) {
si->bindmethod = LDAP_AUTH_SIMPLE;
gots |= GOT_METHOD;
} else if ( !strcasecmp( val, SASLSTR )) {
si->bindmethod = LDAP_AUTH_SASL;
gots |= GOT_METHOD;
} else {
si->bindmethod = -1;
}
} else if ( !strncasecmp( cargv[ i ], LASTMODSTR,
sizeof( LASTMODSTR ) - 1 ) ) {
val = cargv[ i ] + sizeof( LASTMODSTR );
if ( !strcasecmp( val, LMREQSTR )) {
si->lastmod = LASTMOD_REQ;
gots |= GOT_LASTMOD;
} else if ( !strcasecmp( val, LMGENSTR )) {
si->lastmod = LASTMOD_GEN;
gots |= GOT_LASTMOD;
} else if ( !strcasecmp( val, LMNOSTR )) {
si->lastmod = LASTMOD_NO;
gots |= GOT_LASTMOD;
} else {
si->lastmod = -1;
}
} else if ( !strncasecmp( cargv[ i ],
SASLMECHSTR, sizeof( SASLMECHSTR ) - 1 ) ) {
val = cargv[ i ] + sizeof( SASLMECHSTR );
gots |= GOT_MECH;
si->saslmech = strdup( val );
} else if ( !strncasecmp( cargv[ i ],
CREDSTR, sizeof( CREDSTR ) - 1 ) ) {
val = cargv[ i ] + sizeof( CREDSTR );
si->passwd = strdup( val );
} else if ( !strncasecmp( cargv[ i ],
SECPROPSSTR, sizeof( SECPROPSSTR ) - 1 ) ) {
val = cargv[ i ] + sizeof( SECPROPSSTR );
si->secprops = strdup( val );
} else if ( !strncasecmp( cargv[ i ],
REALMSTR, sizeof( REALMSTR ) - 1 ) ) {
val = cargv[ i ] + sizeof( REALMSTR );
si->realm = strdup( val );
} else if ( !strncasecmp( cargv[ i ],
AUTHCSTR, sizeof( AUTHCSTR ) - 1 ) ) {
val = cargv[ i ] + sizeof( AUTHCSTR );
si->authcId = strdup( val );
} else if ( !strncasecmp( cargv[ i ],
OLDAUTHCSTR, sizeof( OLDAUTHCSTR ) - 1 ) ) {
/* Old authcID is provided for some backwards compatibility */
val = cargv[ i ] + sizeof( OLDAUTHCSTR );
si->authcId = strdup( val );
} else if ( !strncasecmp( cargv[ i ],
AUTHZSTR, sizeof( AUTHZSTR ) - 1 ) ) {
val = cargv[ i ] + sizeof( AUTHZSTR );
si->authzId = strdup( val );
} else if ( !strncasecmp( cargv[ i ],
SRVTABSTR, sizeof( SRVTABSTR ) - 1 ) ) {
val = cargv[ i ] + sizeof( SRVTABSTR );
if ( si->srvtab != NULL ) {
free( si->srvtab );
}
si->srvtab = strdup( val );
} else if ( !strncasecmp( cargv[ i ],
FILTERSTR, sizeof( FILTERSTR ) - 1 ) ) {
val = cargv[ i ] + sizeof( FILTERSTR );
gots |= GOT_FILTER;
si->filterstr = strdup( val );
} else if ( !strncasecmp( cargv[ i ],
SEARCHBASESTR, sizeof( SEARCHBASESTR ) - 1 ) ) {
val = cargv[ i ] + sizeof( SEARCHBASESTR );
gots |= GOT_SEARCHBASE;
si->base = strdup( val );
} else if ( !strncasecmp( cargv[ i ],
SCOPESTR, sizeof( SCOPESTR ) - 1 ) ) {
val = cargv[ i ] + sizeof( SCOPESTR );
gots |= GOT_SCOPE;
if ( !strncasecmp( val, "base", sizeof( "base" ) - 1 )) {
si->scope = LDAP_SCOPE_BASE;
} else if ( !strncasecmp( val, "one", sizeof( "one" ) - 1 )) {
si->scope = LDAP_SCOPE_ONELEVEL;
} else if ( !strncasecmp( val, "sub", sizeof( "sub" ) - 1 )) {
si->scope = LDAP_SCOPE_SUBTREE;
} else {
fprintf( stderr,
"Error: parse_syncrepl_line: unknown scope \"%s\"\n",
val);
return 1;
}
} else if ( !strncasecmp( cargv[ i ],
ATTRSONLYSTR, sizeof( ATTRSONLYSTR ) - 1 ) ) {
si->attrsonly = 1;
} else if ( !strncasecmp( cargv[ i ],
ATTRSSTR, sizeof( ATTRSSTR ) - 1 ) ) {
char **tmp;
val = cargv[ i ] + sizeof( ATTRSSTR );
for ( ; hp = strchr( val, ' ' ); val = ++hp ) {
*hp = '\0';
if ( *val != '\0' ) {
nr_attr++;
tmp = (char **) ch_realloc( si->attrs, nr_attr * sizeof( char * ));
if ( tmp == NULL ) {
#ifdef NEW_LOGGING
LDAP_LOG( CONFIG, ERR, "out of memory\n", 0,0,0 );
#else
Debug( LDAP_DEBUG_ANY,
"out of memory\n", 0,0,0 );
#endif
return -1;
}
si->attrs = tmp;
si->attrs[ nr_attr - 1 ] = strdup( val );
}
}
if ( *val != '\0' ) {
nr_attr++;
tmp = (char **) ch_realloc( si->attrs, nr_attr * sizeof( char * ));
if ( tmp == NULL ) {
#ifdef NEW_LOGGING
LDAP_LOG( CONFIG, ERR, "out of memory\n", 0,0,0 );
#else
Debug( LDAP_DEBUG_ANY,
"out of memory\n", 0,0,0 );
#endif
return -1;
}
si->attrs = tmp;
si->attrs[ nr_attr - 1 ] = strdup( val );
}
nr_attr++;
tmp = (char **) ch_realloc( si->attrs, nr_attr * sizeof( char * ));
if ( tmp == NULL ) {
#ifdef NEW_LOGGING
LDAP_LOG( CONFIG, ERR, "out of memory\n", 0,0,0 );
#else
Debug( LDAP_DEBUG_ANY, "out of memory\n", 0,0,0 );
#endif
return -1;
}
si->attrs = tmp;
si->attrs[ nr_attr - 1 ] = NULL;
gots |= GOT_ATTRS;
} else if ( !strncasecmp( cargv[ i ],
TYPESTR, sizeof( TYPESTR ) - 1 ) ) {
val = cargv[ i ] + sizeof( TYPESTR );
gots |= GOT_TYPE;
if ( !strncasecmp( val, "refreshOnly", sizeof( "refreshOnly" ) - 1 )) {
si->type = LDAP_SYNC_REFRESH_ONLY;
} else if ( !strncasecmp( val, "refreshAndPersist", sizeof( "refreshAndPersist" ) - 1 )) {
gots |= GOT_INTERVAL;
si->type = LDAP_SYNC_REFRESH_AND_PERSIST;
} else {
fprintf( stderr,
"Error: parse_syncrepl_line: unknown sync type \"%s\"\n",
val);
return 1;
}
} else if ( !strncasecmp( cargv[ i ],
INTERVALSTR, sizeof( INTERVALSTR ) - 1 ) ) {
val = cargv[ i ] + sizeof( INTERVALSTR );
gots |= GOT_INTERVAL;
si->interval = atoi( val );
if ( si->interval <= 0 ) {
fprintf( stderr,
"Error: parse_syncrepl_line: invalid interval \"%d
\"\n",
si->interval);
return 1;
}
} else if ( !strncasecmp( cargv[ i ],
COOKIESTR, sizeof( COOKIESTR ) - 1 ) ) {
val = cargv[ i ] + sizeof( COOKIESTR );
si->syncCookie = ber_str2bv( val, strlen( val ), 1, NULL );
} else {
fprintf( stderr,
"Error: parse_syncrepl_line: unknown keyword \"%s\"\n",
cargv[ i ] );
}
}
if ( si->bindmethod == LDAP_AUTH_SASL) {
if ((gots & GOT_MECH) == 0) {
fprintf( stderr, "Error: \"syncrepl\" line needs SASLmech flag in
" );
fprintf( stderr, "slapd config file\n" );
return -1;
}
}
gots |= GOT_MECH;
if ( gots != GOT_ALL ) {
fprintf( stderr, "Error: Malformed \"syncrepl\" line in slapd config file"
);
return -1;
}
return 0;
}
#endif /* LDAP_SYNCREPL */

View File

@ -1118,6 +1118,15 @@ LDAP_SLAPD_F (int) do_search LDAP_P((Operation *op, SlapReply *rs));
LDAP_SLAPD_F (int) do_unbind LDAP_P((Operation *op, SlapReply *rs));
LDAP_SLAPD_F (int) do_extended LDAP_P((Operation *op, SlapReply *rs));
/*
* syncrepl
*/
#ifdef LDAP_SYNCREPL
LDAP_SLAPD_F (void) init_syncrepl LDAP_P(());
LDAP_SLAPD_F (void*) do_syncrepl LDAP_P((void *, void *));
#endif
LDAP_END_DECL
#endif /* PROTO_SLAP_H */

View File

@ -223,10 +223,21 @@ entry_schema_check(
}
/* naming check */
rc = entry_naming_check( e, text, textbuf, textlen );
if( rc != LDAP_SUCCESS ) {
return rc;
}
#ifdef LDAP_SYNCREPL
if ( !is_entry_objectclass ( e, slap_schema.si_oc_glue, 0 ) ) {
rc = entry_naming_check( e, text, textbuf, textlen );
if( rc != LDAP_SUCCESS ) {
return rc;
}
} else {
printf("glue !!!\n");
}
#else
rc = entry_naming_check( e, text, textbuf, textlen );
if( rc != LDAP_SUCCESS ) {
return rc;
}
#endif
#ifdef SLAP_EXTENDED_SCHEMA
/* find the content rule for the structural class */

View File

@ -331,6 +331,29 @@ static struct slap_schema_oc_map {
"SUP top AUXILIARY )",
dynamicObjectClass, SLAP_OC_DYNAMICOBJECT,
offsetof(struct slap_internal_schema, si_oc_dynamicObject) },
#endif
#ifdef LDAP_SYNCREPL
{ "glue", "( 1.3.6.1.4.1.4203.666.3.4 "
"NAME 'glue' "
"DESC 'Glue Entry' "
"SUP top STRUCTURAL )",
0, SLAP_OC_OPERATIONAL,
offsetof(struct slap_internal_schema, si_oc_glue) },
{ "syncConsumerSubentry", "( 1.3.6.1.4.1.4203.666.3.5 "
"NAME 'syncConsumerSubentry' "
"DESC 'Persistent Info for SyncRepl Consumer' "
"AUXILIARY "
"MAY syncreplCookie )",
0, SLAP_OC_OPERATIONAL,
offsetof(struct slap_internal_schema, si_oc_syncConsumerSubentry) },
{ "syncProviderSubentry", "( 1.3.6.1.4.1.4203.666.3.6 "
"NAME 'syncProviderSubentry' "
"DESC 'Persistent Info for SyncRepl Producer' "
"AUXILIARY "
"MAY syncreplCookie )",
0, SLAP_OC_OPERATIONAL,
offsetof(struct slap_internal_schema, si_oc_syncProviderSubentry) },
#endif
{ NULL, NULL, NULL, 0, 0 }
};
@ -489,6 +512,18 @@ static struct slap_schema_ad_map {
offsetof(struct slap_internal_schema, si_ad_queryid) },
#endif /* LDAP_CACHING */
#ifdef LDAP_SYNCREPL
{ "syncreplCookie", "( 1.3.6.1.4.1.4203.666.1.13 NAME 'syncreplCookie' "
"DESC 'syncrepl Cookie for shadow copy' "
"EQUALITY octetStringMatch "
"ORDERING octetStringOrderingMatch "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{64} "
"SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
NULL, SLAP_AT_HIDE,
NULL, NULL, NULL, NULL, NULL,
offsetof(struct slap_internal_schema, si_ad_syncreplCookie) },
#endif
/* root DSE attributes */
{ "altServer", "( 1.3.6.1.4.1.1466.101.120.6 NAME 'altServer' "
"DESC 'RFC2252: alternative servers' "

View File

@ -77,6 +77,10 @@ LDAP_BEGIN_DECL
#define SLAP_MAX_WORKER_THREADS (16)
#ifdef LDAP_SYNCREPL
#define SLAP_MAX_SYNCREPL_THREADS (8)
#endif
#define SLAP_SB_MAX_INCOMING_DEFAULT ((1<<18) - 1)
#define SLAP_SB_MAX_INCOMING_AUTH ((1<<24) - 1)
@ -698,6 +702,12 @@ struct slap_internal_schema {
ObjectClass *si_oc_collectiveAttributeSubentry;
ObjectClass *si_oc_dynamicObject;
#ifdef LDAP_SYNCREPL
ObjectClass *si_oc_glue;
ObjectClass *si_oc_syncConsumerSubentry;
ObjectClass *si_oc_syncProviderSubentry;
#endif
/* objectClass attribute descriptions */
AttributeDescription *si_ad_objectClass;
@ -721,6 +731,11 @@ struct slap_internal_schema {
AttributeDescription *si_ad_queryid;
#endif /* LDAP_CACHING */
#ifdef LDAP_SYNCREPL
AttributeDescription *si_ad_dseType;
AttributeDescription *si_ad_syncreplCookie;
#endif
/* root DSE attribute descriptions */
AttributeDescription *si_ad_altServer;
AttributeDescription *si_ad_namingContexts;
@ -1252,6 +1267,87 @@ typedef BackendDB Backend;
#define nbackends nBackendDB
#define backends backendDB
#ifdef LDAP_SYNCREPL
/*
* syncinfo structure for syncrepl
*/
typedef struct syncinfo_s {
struct slap_conn *conn;
struct slap_backend_db *be;
struct slap_entry *e;
void *ctx;
int id;
char *masteruri;
char *mastername;
int masterport;
int type;
char *binddn;
int bindmethod;
char *passwd;
char *secprops;
char *realm;
char *authcId;
char *authzId;
char *srvtab;
char *saslmech;
int interval;
char *base;
int scope;
int deref;
int slimit;
int tlimit;
Filter *filter;
char *filterstr;
char **attrs;
int attrsonly;
#define LASTMOD_REQ 0
#define LASTMOD_GEN 1
#define LASTMOD_NO 2
int lastmod;
/* TLS flags */
#define TLS_OFF 0
#define TLS_ON 1
#define TLS_CRITICAL 2
int tls;
int found;
struct berval *syncUUID;
struct berval *syncCookie;
Avlnode *presentlist;
} syncinfo_t;
#define IDSTR "id"
#define MASTERSTR "master"
#define SUFFIXSTR "suffix"
#define BINDDNSTR "binddn"
#define BINDMETHSTR "bindmethod"
#define SIMPLESTR "simple"
#define SASLSTR "sasl"
#define CREDSTR "credentials"
#define OLDAUTHCSTR "bindprincipal"
#define AUTHCSTR "authcID"
#define AUTHZSTR "authzID"
#define SRVTABSTR "srvtab"
#define SASLMECHSTR "saslmech"
#define REALMSTR "realm"
#define SECPROPSSTR "secprops"
#define TLSSTR "tls"
#define TLSCRITICALSTR "critical"
#define FILTERSTR "filter"
#define SEARCHBASESTR "searchbase"
#define SCOPESTR "scope"
#define ATTRSSTR "attrs"
#define ATTRSONLYSTR "attrsonly"
#define TYPESTR "type"
#define INTERVALSTR "interval"
#define COOKIESTR "cookie"
#define LASTMODSTR "lastmod"
#define LMREQSTR "req"
#define LMGENSTR "gen"
#define LMNOSTR "no"
#endif /* LDAP_SYNCREPL */
struct slap_backend_db {
BackendInfo *bd_info; /* pointer to shared backend info */
@ -1392,6 +1488,9 @@ struct slap_backend_db {
void *be_private; /* anything the backend database needs */
void *be_pb; /* Netscape plugin */
#ifdef LDAP_SYNCREPL
syncinfo_t *syncinfo; /* For syncrepl */
#endif
};
struct slap_conn;

View File

@ -247,3 +247,14 @@ int root_dse_info( Connection *conn, Entry **entry, const char **text )
return -1;
}
#ifdef LDAP_SYNCREPL
void init_syncrepl( )
{
return -1;
}
void* do_syncrepl( void *ctx, void *arg )
{
return -1;
}
#endif