mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-21 23:29:34 -05:00
ITS#8958 back-mdb: checkpoint online indexer
Save old/new indexmasks to allow processing to resume if slapd is stopped and restarted. Save last entryID indexed to allow resume after restart or pool pause.
This commit is contained in:
parent
5ad6ab3568
commit
f6a61ab7fe
4 changed files with 181 additions and 18 deletions
|
|
@ -33,7 +33,8 @@ LDAP_BEGIN_DECL
|
||||||
#define MDB_DN2ID 1
|
#define MDB_DN2ID 1
|
||||||
#define MDB_ID2ENTRY 2
|
#define MDB_ID2ENTRY 2
|
||||||
#define MDB_ID2VAL 3
|
#define MDB_ID2VAL 3
|
||||||
#define MDB_NDB 4
|
#define MDB_IDXCKP 4
|
||||||
|
#define MDB_NDB 5
|
||||||
|
|
||||||
/* The default search IDL stack cache depth */
|
/* The default search IDL stack cache depth */
|
||||||
#define DEFAULT_SEARCH_STACK_DEPTH 16
|
#define DEFAULT_SEARCH_STACK_DEPTH 16
|
||||||
|
|
@ -122,6 +123,7 @@ struct mdb_info {
|
||||||
#define mi_dn2id mi_dbis[MDB_DN2ID]
|
#define mi_dn2id mi_dbis[MDB_DN2ID]
|
||||||
#define mi_ad2id mi_dbis[MDB_AD2ID]
|
#define mi_ad2id mi_dbis[MDB_AD2ID]
|
||||||
#define mi_id2val mi_dbis[MDB_ID2VAL]
|
#define mi_id2val mi_dbis[MDB_ID2VAL]
|
||||||
|
#define mi_idxckp mi_dbis[MDB_IDXCKP]
|
||||||
|
|
||||||
typedef struct mdb_op_info {
|
typedef struct mdb_op_info {
|
||||||
OpExtra moi_oe;
|
OpExtra moi_oe;
|
||||||
|
|
|
||||||
|
|
@ -210,23 +210,52 @@ mdb_online_index( void *ctx, void *arg )
|
||||||
ID id;
|
ID id;
|
||||||
Entry *e;
|
Entry *e;
|
||||||
int rc, getnext = 1;
|
int rc, getnext = 1;
|
||||||
int i;
|
int i, first = 1;
|
||||||
|
int intr = 0;
|
||||||
|
|
||||||
connection_fake_init( &conn, &opbuf, ctx );
|
connection_fake_init( &conn, &opbuf, ctx );
|
||||||
op = &opbuf.ob_op;
|
op = &opbuf.ob_op;
|
||||||
|
|
||||||
op->o_bd = be;
|
op->o_bd = be;
|
||||||
|
|
||||||
id = 1;
|
|
||||||
key.mv_size = sizeof(ID);
|
key.mv_size = sizeof(ID);
|
||||||
|
|
||||||
while ( 1 ) {
|
while ( 1 ) {
|
||||||
if ( slapd_shutdown )
|
|
||||||
break;
|
|
||||||
|
|
||||||
rc = mdb_txn_begin( mdb->mi_dbenv, NULL, 0, &txn );
|
rc = mdb_txn_begin( mdb->mi_dbenv, NULL, 0, &txn );
|
||||||
if ( rc )
|
if ( rc )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* pick up where we left off */
|
||||||
|
if ( first ) {
|
||||||
|
MDB_val k0;
|
||||||
|
unsigned short s = 0;
|
||||||
|
|
||||||
|
first = 0;
|
||||||
|
k0.mv_size = sizeof(s);
|
||||||
|
k0.mv_data = &s;
|
||||||
|
rc = mdb_get( txn, mdb->mi_idxckp, &k0, &data );
|
||||||
|
if ( rc ) {
|
||||||
|
mdb_txn_abort( txn );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
memcpy( &id, data.mv_data, sizeof( id ));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save our stopping point */
|
||||||
|
if ( slapd_shutdown || ldap_pvt_thread_pool_pausequery( &connection_pool )) {
|
||||||
|
MDB_val k0;
|
||||||
|
unsigned short s = 0;
|
||||||
|
|
||||||
|
k0.mv_size = sizeof(s);
|
||||||
|
k0.mv_data = &s;
|
||||||
|
data.mv_data = &id;
|
||||||
|
data.mv_size = sizeof( id );
|
||||||
|
mdb_put( txn, mdb->mi_idxckp, &k0, &data, 0 );
|
||||||
|
mdb_txn_commit( txn );
|
||||||
|
intr = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
rc = mdb_cursor_open( txn, mdb->mi_id2entry, &curs );
|
rc = mdb_cursor_open( txn, mdb->mi_id2entry, &curs );
|
||||||
if ( rc ) {
|
if ( rc ) {
|
||||||
mdb_txn_abort( txn );
|
mdb_txn_abort( txn );
|
||||||
|
|
@ -276,25 +305,137 @@ mdb_online_index( void *ctx, void *arg )
|
||||||
getnext = 1;
|
getnext = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( i = 0; i < mdb->mi_nattrs; i++ ) {
|
/* all done */
|
||||||
if ( mdb->mi_attrs[ i ]->ai_indexmask & MDB_INDEX_DELETING
|
if ( !intr ) {
|
||||||
|| mdb->mi_attrs[ i ]->ai_newmask == 0 )
|
for ( i = 0; i < mdb->mi_nattrs; i++ ) {
|
||||||
{
|
if ( mdb->mi_attrs[ i ]->ai_indexmask & MDB_INDEX_DELETING
|
||||||
continue;
|
|| mdb->mi_attrs[ i ]->ai_newmask == 0 )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
mdb->mi_attrs[ i ]->ai_indexmask = mdb->mi_attrs[ i ]->ai_newmask;
|
||||||
|
mdb->mi_attrs[ i ]->ai_newmask = 0;
|
||||||
|
}
|
||||||
|
/* zero out checkpoint DB */
|
||||||
|
rc = mdb_txn_begin( mdb->mi_dbenv, NULL, 0, &txn );
|
||||||
|
if ( !rc ) {
|
||||||
|
mdb_drop( txn, mdb->mi_idxckp, 0 );
|
||||||
|
mdb_txn_commit( txn );
|
||||||
}
|
}
|
||||||
mdb->mi_attrs[ i ]->ai_indexmask = mdb->mi_attrs[ i ]->ai_newmask;
|
|
||||||
mdb->mi_attrs[ i ]->ai_newmask = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
|
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
|
||||||
ldap_pvt_runqueue_stoptask( &slapd_rq, rtask );
|
if ( ldap_pvt_runqueue_isrunning( &slapd_rq, rtask ))
|
||||||
mdb->mi_index_task = NULL;
|
ldap_pvt_runqueue_stoptask( &slapd_rq, rtask );
|
||||||
ldap_pvt_runqueue_remove( &slapd_rq, rtask );
|
if ( intr && !slapd_shutdown ) {
|
||||||
|
/* on pause, resched to run again immediately */
|
||||||
|
time_t t = rtask->interval.tv_sec;
|
||||||
|
rtask->interval.tv_sec = 0;
|
||||||
|
ldap_pvt_runqueue_resched( &slapd_rq, rtask, 0 );
|
||||||
|
rtask->interval.tv_sec = t;
|
||||||
|
} else if ( mdb->mi_index_task ) {
|
||||||
|
mdb->mi_index_task = NULL;
|
||||||
|
ldap_pvt_runqueue_remove( &slapd_rq, rtask );
|
||||||
|
}
|
||||||
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
|
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
mdb_setup_indexer( struct mdb_info *mdb )
|
||||||
|
{
|
||||||
|
MDB_txn *txn;
|
||||||
|
MDB_cursor *curs;
|
||||||
|
MDB_val key, data;
|
||||||
|
int i, rc;
|
||||||
|
unsigned short s;
|
||||||
|
|
||||||
|
rc = mdb_txn_begin( mdb->mi_dbenv, NULL, 0, &txn );
|
||||||
|
if ( rc )
|
||||||
|
return rc;
|
||||||
|
rc = mdb_cursor_open( txn, mdb->mi_idxckp, &curs );
|
||||||
|
if ( rc ) {
|
||||||
|
mdb_txn_abort( txn );
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
key.mv_size = sizeof( s );
|
||||||
|
key.mv_data = &s;
|
||||||
|
|
||||||
|
/* set indexer task to start at first entry */
|
||||||
|
{
|
||||||
|
ID id = 0;
|
||||||
|
s = 0; /* key 0 records next entryID to index */
|
||||||
|
data.mv_size = sizeof( ID );
|
||||||
|
data.mv_data = &id;
|
||||||
|
rc = mdb_cursor_put( curs, &key, &data, 0 );
|
||||||
|
if ( rc )
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* record current and new index masks for all new index definitions */
|
||||||
|
{
|
||||||
|
slap_mask_t mask[2];
|
||||||
|
data.mv_size = sizeof(mask);
|
||||||
|
data.mv_data = mask;
|
||||||
|
|
||||||
|
for ( i = 0; i < mdb->mi_nattrs; i++ ) {
|
||||||
|
if ( !mdb->mi_attrs[i]->ai_newmask ) continue;
|
||||||
|
s = mdb->mi_adxs[ mdb->mi_attrs[i]->ai_desc->ad_index ];
|
||||||
|
mask[0] = mdb->mi_attrs[i]->ai_indexmask;
|
||||||
|
mask[1] = mdb->mi_attrs[i]->ai_newmask;
|
||||||
|
rc = mdb_cursor_put( curs, &key, &data, 0 );
|
||||||
|
if ( rc )
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
mdb_cursor_close( curs );
|
||||||
|
if ( !rc )
|
||||||
|
mdb_txn_commit( txn );
|
||||||
|
else
|
||||||
|
mdb_txn_abort( txn );
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mdb_resume_index( BackendDB *be, MDB_txn *txn )
|
||||||
|
{
|
||||||
|
struct mdb_info *mdb = be->be_private;
|
||||||
|
MDB_cursor *curs;
|
||||||
|
MDB_val key, data;
|
||||||
|
int i, rc;
|
||||||
|
unsigned short *s;
|
||||||
|
slap_mask_t *mask;
|
||||||
|
AttributeDescription *ad;
|
||||||
|
|
||||||
|
rc = mdb_cursor_open( txn, mdb->mi_idxckp, &curs );
|
||||||
|
if ( rc )
|
||||||
|
return;
|
||||||
|
|
||||||
|
while(( rc = mdb_cursor_get( curs, &key, &data, MDB_NEXT )) == 0) {
|
||||||
|
s = key.mv_data;
|
||||||
|
if ( !*s )
|
||||||
|
continue;
|
||||||
|
ad = mdb->mi_ads[*s];
|
||||||
|
for ( i=0; i<mdb->mi_nattrs; i++) {
|
||||||
|
if (mdb->mi_attrs[i]->ai_desc == ad ) {
|
||||||
|
mask = data.mv_data;
|
||||||
|
mdb->mi_attrs[i]->ai_indexmask = mask[0];
|
||||||
|
mdb->mi_attrs[i]->ai_newmask = mask[1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mdb_cursor_close( curs );
|
||||||
|
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
|
||||||
|
mdb->mi_index_task = ldap_pvt_runqueue_insert( &slapd_rq, 36000,
|
||||||
|
mdb_online_index, be,
|
||||||
|
LDAP_XSTRING(mdb_online_index), be->be_suffix[0].bv_val );
|
||||||
|
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
|
||||||
|
}
|
||||||
|
|
||||||
/* Cleanup loose ends after Modify completes */
|
/* Cleanup loose ends after Modify completes */
|
||||||
static int
|
static int
|
||||||
mdb_cf_cleanup( ConfigArgs *c )
|
mdb_cf_cleanup( ConfigArgs *c )
|
||||||
|
|
@ -328,6 +469,7 @@ mdb_cf_cleanup( ConfigArgs *c )
|
||||||
rc = mdb_attr_dbs_open( c->be, NULL, &c->reply );
|
rc = mdb_attr_dbs_open( c->be, NULL, &c->reply );
|
||||||
if ( rc )
|
if ( rc )
|
||||||
rc = LDAP_OTHER;
|
rc = LDAP_OTHER;
|
||||||
|
mdb_setup_indexer( mdb );
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ static const struct berval mdmi_databases[] = {
|
||||||
BER_BVC("dn2i"),
|
BER_BVC("dn2i"),
|
||||||
BER_BVC("id2e"),
|
BER_BVC("id2e"),
|
||||||
BER_BVC("id2v"),
|
BER_BVC("id2v"),
|
||||||
|
BER_BVC("ixck"),
|
||||||
BER_BVNULL
|
BER_BVNULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -286,6 +287,13 @@ mdb_db_open( BackendDB *be, ConfigReply *cr )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( slapMode & SLAP_SERVER_MODE ) {
|
||||||
|
MDB_stat st;
|
||||||
|
rc = mdb_stat( txn, mdb->mi_idxckp, &st );
|
||||||
|
if ( st.ms_entries )
|
||||||
|
mdb_resume_index( be, txn );
|
||||||
|
}
|
||||||
|
|
||||||
rc = mdb_txn_commit(txn);
|
rc = mdb_txn_commit(txn);
|
||||||
if ( rc != 0 ) {
|
if ( rc != 0 ) {
|
||||||
Debug( LDAP_DEBUG_ANY,
|
Debug( LDAP_DEBUG_ANY,
|
||||||
|
|
@ -321,11 +329,21 @@ mdb_db_close( BackendDB *be, ConfigReply *cr )
|
||||||
|
|
||||||
mdb->mi_flags &= ~MDB_IS_OPEN;
|
mdb->mi_flags &= ~MDB_IS_OPEN;
|
||||||
|
|
||||||
if( mdb->mi_dbenv ) {
|
/* remove indexer task */
|
||||||
mdb_reader_flush( mdb->mi_dbenv );
|
if ( mdb->mi_index_task ) {
|
||||||
|
struct re_s *re = mdb->mi_index_task;
|
||||||
|
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
|
||||||
|
mdb->mi_index_task = NULL;
|
||||||
|
/* can never actually be running at this point, but paranoia */
|
||||||
|
if ( ldap_pvt_runqueue_isrunning( &slapd_rq, re ) )
|
||||||
|
ldap_pvt_runqueue_stoptask( &slapd_rq, re );
|
||||||
|
ldap_pvt_runqueue_remove( &slapd_rq, re );
|
||||||
|
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( mdb->mi_dbenv ) {
|
if ( mdb->mi_dbenv ) {
|
||||||
|
mdb_reader_flush( mdb->mi_dbenv );
|
||||||
|
|
||||||
if ( mdb->mi_dbis[0] ) {
|
if ( mdb->mi_dbis[0] ) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ void mdb_ad_unwind( struct mdb_info *mdb, int prev_ads );
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int mdb_back_init_cf( BackendInfo *bi );
|
int mdb_back_init_cf( BackendInfo *bi );
|
||||||
|
void mdb_resume_index( BackendDB *be, MDB_txn *txn );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* dn2entry.c
|
* dn2entry.c
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue