Пример #1
0
/* ITS#7904 if we get blocked while writing results to client,
 * release the current reader txn and reacquire it after we
 * unblock.
 * Slight problem - if we're doing a scope-based walk (mdb_dn2id_walk)
 * to return results, we need to remember the state of the mcd cursor.
 * If the node that cursor was pointing to gets deleted while we're
 * blocked, we may be unable to restore the cursor position. In that
 * case return an LDAP_BUSY error - let the client know this search
 * couldn't succeed, but might succeed on a retry.
 */
static void
mdb_writewait( Operation *op, slap_callback *sc )
{
	ww_ctx *ww = sc->sc_private;
	if ( !ww->flag ) {
		MDB_val key, data;
		int rc;
		if ( ww->mcd ) {
			ww->data.iov_base = NULL;
			rc = mdb_cursor_get( ww->mcd, &key, &data, MDB_GET_CURRENT );
			if (likely( rc == MDB_SUCCESS )) {
				memcpy( &ww->key, key.mv_data, sizeof(ID) );
				ww->data.mv_size = data.mv_size;
				ww->data.mv_data = op->o_tmpalloc( data.mv_size, op->o_tmpmemctx );
				memcpy(ww->data.mv_data, data.mv_data, data.mv_size);
			}
		}
#if MDBX_MODE_ENABLED
		rc = mdb_txn_reset( ww->txn );
		assert(rc == MDB_SUCCESS);
		(void) rc;
#else
		mdb_txn_reset( ww->txn );
#endif /* MDBX_MODE_ENABLED */
		ww->flag = 1;
	}
}
Пример #2
0
bool B_ACCURATE_LMDB::send_base_file_list(JCR *jcr)
{
   int result;
   int32_t LinkFIc;
   FF_PKT *ff_pkt;
   MDB_cursor *cursor;
   MDB_val key, data;
   bool retval = false;
   accurate_payload *payload;
   int stream = STREAM_UNIX_ATTRIBUTES;

   if (!jcr->accurate || jcr->getJobLevel() != L_FULL) {
      return true;
   }

   /*
    * Commit any pending write transactions.
    */
   if (m_db_rw_txn) {
      result = mdb_txn_commit(m_db_rw_txn);
      if (result != 0) {
         Jmsg1(jcr, M_FATAL, 0, _("Unable close write transaction: %s\n"), mdb_strerror(result));
         goto bail_out;
      }
      m_db_rw_txn = NULL;
   }

   ff_pkt = init_find_files();
   ff_pkt->type = FT_BASE;

   result = mdb_cursor_open(m_db_ro_txn, m_db_dbi, &cursor);
   if (result == 0) {
      while ((result = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
         payload = (accurate_payload *)data.mv_data;
         if (bit_is_set(payload->filenr, m_seen_bitmap)) {
            Dmsg1(dbglvl, "base file fname=%s\n", key.mv_data);
            decode_stat(payload->lstat, &ff_pkt->statp, sizeof(struct stat), &LinkFIc); /* decode catalog stat */
            ff_pkt->fname = (char *)key.mv_data;
            encode_and_send_attributes(jcr, ff_pkt, stream);
         }
      }
      mdb_cursor_close(cursor);
   } else {
      Jmsg1(jcr, M_FATAL, 0, _("Unable create cursor: %s\n"), mdb_strerror(result));
   }

   mdb_txn_reset(m_db_ro_txn);
   result = mdb_txn_renew(m_db_ro_txn);
   if (result != 0) {
      Jmsg1(jcr, M_FATAL, 0, _("Unable to renew read transaction: %s\n"), mdb_strerror(result));
      goto bail_out;
   }

   retval = true;

bail_out:
   term_find_files(ff_pkt);
   return retval;
}
Пример #3
0
/*
 * sets *hasSubordinates to LDAP_COMPARE_TRUE/LDAP_COMPARE_FALSE
 * if the entry has children or not.
 */
int
mdb_hasSubordinates(
	Operation	*op,
	Entry		*e,
	int		*hasSubordinates )
{
	struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
	MDB_txn		*rtxn;
	mdb_op_info	opinfo = {{{0}}}, *moi = &opinfo;
	int		rc;
	
	assert( e != NULL );

	rc = mdb_opinfo_get(op, mdb, 1, &moi);
	switch(rc) {
	case 0:
		break;
	default:
		rc = LDAP_OTHER;
		goto done;
	}

	rtxn = moi->moi_txn;

	rc = mdb_dn2id_children( op, rtxn, e );

	switch( rc ) {
	case 0:
		*hasSubordinates = LDAP_COMPARE_TRUE;
		break;

	case MDB_NOTFOUND:
		*hasSubordinates = LDAP_COMPARE_FALSE;
		rc = LDAP_SUCCESS;
		break;

	default:
		Debug(LDAP_DEBUG_ARGS, 
			"<=- " LDAP_XSTRING(mdb_hasSubordinates)
			": has_children failed: %s (%d)\n", 
			mdb_strerror(rc), rc, 0 );
		rc = LDAP_OTHER;
	}

done:;
	if ( moi == &opinfo ) {
		mdb_txn_reset( moi->moi_txn );
		LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next );
	} else {
		moi->moi_ref--;
	}
	return rc;
}
Пример #4
0
accurate_payload *B_ACCURATE_LMDB::lookup_payload(JCR *jcr, char *fname)
{
   int result;
   int lstat_length;
   MDB_val key, data;
   accurate_payload *payload = NULL;

   key.mv_data = fname;
   key.mv_size = strlen(fname) + 1;

   result = mdb_get(m_db_ro_txn, m_db_dbi, &key, &data);
   switch (result) {
   case 0:
      /*
       * Success.
       *
       * We need to make a private copy of the LDMB data as we are not
       * allowed to change its content and we need to update the lstat
       * and chksum pointer to point to the actual lstat and chksum that
       * is stored behind the accurate_payload structure in the LMDB.
       */
      m_pay_load = check_pool_memory_size(m_pay_load, data.mv_size);

      payload = (accurate_payload *)m_pay_load;
      memcpy(payload, data.mv_data, data.mv_size);
      payload->lstat = (char *)payload + sizeof(accurate_payload);
      lstat_length = strlen(payload->lstat);
      payload->chksum = (char *)payload->lstat + lstat_length + 1;

      /*
       * We keep the transaction as short a possible so after a lookup
       * and copying the actual data out we reset the read transaction
       * and do a renew of the read transaction for a new run.
       */
      mdb_txn_reset(m_db_ro_txn);
      result = mdb_txn_renew(m_db_ro_txn);
      if (result != 0) {
         Jmsg1(jcr, M_FATAL, 0, _("Unable to renew read transaction: %s\n"), mdb_strerror(result));
         return NULL;
      }
      break;
   case MDB_NOTFOUND:
      /*
       * Failed to find the given key.
       */
      break;
   default:
      break;
   }

   return payload;
}
Пример #5
0
static void *perform(void *arg)
{
	db_thread *thr = (db_thread*)arg;
	int i,rc;
	mdbinf* mdb = &thr->mdb;

	srand((u32)pthread_self());
	open_txn(mdb, MDB_RDONLY);
	thr->resFrames = alloca((SQLITE_DEFAULT_PAGE_SIZE/thr->maxvalsize + 1)*sizeof(MDB_val));
	
	for (i = 0; i < 1000*100; i++)
	{
		int j = rand() % NCONS;

		if (i % 1000 == 0)
			printf("r %lld %d\n",(i64)pthread_self(),i);

		if (pthread_mutex_trylock(&g_cons[j].wal.mtx) != 0)
			continue;

		g_tsd_conn = &g_cons[j];

		rc = sqlite3_exec(g_cons[j].db,"SELECT max(id) FROM tab;",NULL,NULL,NULL);
		if (rc != SQLITE_OK)
		{
			printf("Error select");
			break;
		}

		pthread_mutex_unlock(&g_cons[j].wal.mtx);

		mdb_txn_reset(thr->mdb.txn);
		rc = mdb_txn_renew(thr->mdb.txn);
		if (rc != MDB_SUCCESS)
			break;
		rc = mdb_cursor_renew(mdb->txn, mdb->cursorLog);
		if (rc != MDB_SUCCESS)
			break;
		rc = mdb_cursor_renew(mdb->txn, mdb->cursorPages);
		if (rc != MDB_SUCCESS)
			break;
		rc = mdb_cursor_renew(mdb->txn, mdb->cursorInfo);
		if (rc != MDB_SUCCESS)
			break;
	}
	mdb_cursor_close(mdb->cursorLog);
	mdb_cursor_close(mdb->cursorPages);
	mdb_cursor_close(mdb->cursorInfo);
	mdb_txn_abort(mdb->txn);
	return NULL;
}
Пример #6
0
/* ITS#7904 if we get blocked while writing results to client,
 * release the current reader txn and reacquire it after we
 * unblock.
 * Slight problem - if we're doing a scope-based walk (mdb_dn2id_walk)
 * to return results, we need to remember the state of the mcd cursor.
 * If the node that cursor was pointing to gets deleted while we're
 * blocked, we may be unable to restore the cursor position. In that
 * case return an LDAP_BUSY error - let the client know this search
 * couldn't succeed, but might succeed on a retry.
 */
static void
mdb_rtxn_snap( Operation *op, ww_ctx *ww )
{
	/* save cursor position and release read txn */
	if ( ww->mcd ) {
		MDB_val key, data;
		mdb_cursor_get( ww->mcd, &key, &data, MDB_GET_CURRENT );
		memcpy( &ww->key, key.mv_data, sizeof(ID) );
		ww->data.mv_size = data.mv_size;
		ww->data.mv_data = op->o_tmpalloc( data.mv_size, op->o_tmpmemctx );
		memcpy(ww->data.mv_data, data.mv_data, data.mv_size);
	}
	mdb_txn_reset( ww->txn );
	ww->flag = 1;
}
Пример #7
0
/* ITS#7904 if we get blocked while writing results to client,
 * release the current reader txn and reacquire it after we
 * unblock.
 * Slight problem - if we're doing a scope-based walk (mdb_dn2id_walk)
 * to return results, we need to remember the state of the mcd cursor.
 * If the node that cursor was pointing to gets deleted while we're
 * blocked, we may be unable to restore the cursor position. In that
 * case return an LDAP_BUSY error - let the client know this search
 * couldn't succeed, but might succeed on a retry.
 */
static void
mdb_writewait( Operation *op, slap_callback *sc )
{
	ww_ctx *ww = sc->sc_private;
	if ( !ww->flag ) {
		if ( ww->mcd ) {
			MDB_val key, data;
			mdb_cursor_get( ww->mcd, &key, &data, MDB_GET_CURRENT );
			memcpy( &ww->key, key.mv_data, sizeof(ID) );
			ww->data.mv_size = data.mv_size;
			ww->data.mv_data = op->o_tmpalloc( data.mv_size, op->o_tmpmemctx );
			memcpy(ww->data.mv_data, data.mv_data, data.mv_size);
		}
		mdb_txn_reset( ww->txn );
		ww->flag = 1;
	}
}
Пример #8
0
int
mdb_search( Operation *op, SlapReply *rs )
{
	struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
	ID		id, cursor, nsubs, ncand, cscope;
	ID		lastid = NOID;
	ID		candidates[MDB_IDL_UM_SIZE];
	ID		iscopes[MDB_IDL_DB_SIZE];
	ID2		*scopes;
	void	*stack;
	Entry		*e = NULL, *base = NULL;
	Entry		*matched = NULL;
	AttributeName	*attrs;
	slap_mask_t	mask;
	time_t		stoptime;
	int		manageDSAit;
	int		tentries = 0;
	IdScopes	isc;
	MDB_cursor	*mci, *mcd;
	ww_ctx wwctx;
	slap_callback cb = { 0 };

	mdb_op_info	opinfo = {{{0}}}, *moi = &opinfo;
	MDB_txn			*ltid = NULL;

	Debug( LDAP_DEBUG_TRACE, "=> " LDAP_XSTRING(mdb_search) "\n", 0, 0, 0);
	attrs = op->oq_search.rs_attrs;

	manageDSAit = get_manageDSAit( op );

	rs->sr_err = mdb_opinfo_get( op, mdb, 1, &moi );
	switch(rs->sr_err) {
	case 0:
		break;
	default:
		send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
		return rs->sr_err;
	}

	ltid = moi->moi_txn;

	rs->sr_err = mdb_cursor_open( ltid, mdb->mi_id2entry, &mci );
	if ( rs->sr_err ) {
		send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
		return rs->sr_err;
	}

	rs->sr_err = mdb_cursor_open( ltid, mdb->mi_dn2id, &mcd );
	if ( rs->sr_err ) {
		mdb_cursor_close( mci );
		send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
		return rs->sr_err;
	}

	scopes = scope_chunk_get( op );
	stack = search_stack( op );
	isc.mt = ltid;
	isc.mc = mcd;
	isc.scopes = scopes;
	isc.oscope = op->ors_scope;
	isc.sctmp = stack;

	if ( op->ors_deref & LDAP_DEREF_FINDING ) {
		MDB_IDL_ZERO(candidates);
	}
dn2entry_retry:
	/* get entry with reader lock */
	rs->sr_err = mdb_dn2entry( op, ltid, mcd, &op->o_req_ndn, &e, &nsubs, 1 );

	switch(rs->sr_err) {
	case MDB_NOTFOUND:
		matched = e;
		e = NULL;
		break;
	case 0:
		break;
	case LDAP_BUSY:
		send_ldap_error( op, rs, LDAP_BUSY, "ldap server busy" );
		goto done;
	default:
		send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
		goto done;
	}

	if ( op->ors_deref & LDAP_DEREF_FINDING ) {
		if ( matched && is_entry_alias( matched )) {
			struct berval stub;

			stub.bv_val = op->o_req_ndn.bv_val;
			stub.bv_len = op->o_req_ndn.bv_len - matched->e_nname.bv_len - 1;
			e = deref_base( op, rs, matched, &matched, ltid,
				candidates, NULL );
			if ( e ) {
				build_new_dn( &op->o_req_ndn, &e->e_nname, &stub,
					op->o_tmpmemctx );
				mdb_entry_return(op, e);
				matched = NULL;
				goto dn2entry_retry;
			}
		} else if ( e && is_entry_alias( e )) {
			e = deref_base( op, rs, e, &matched, ltid,
				candidates, NULL );
		}
	}

	if ( e == NULL ) {
		struct berval matched_dn = BER_BVNULL;

		if ( matched != NULL ) {
			BerVarray erefs = NULL;

			/* return referral only if "disclose"
			 * is granted on the object */
			if ( ! access_allowed( op, matched,
						slap_schema.si_ad_entry,
						NULL, ACL_DISCLOSE, NULL ) )
			{
				rs->sr_err = LDAP_NO_SUCH_OBJECT;

			} else {
				ber_dupbv( &matched_dn, &matched->e_name );

				erefs = is_entry_referral( matched )
					? get_entry_referrals( op, matched )
					: NULL;
				if ( rs->sr_err == MDB_NOTFOUND )
					rs->sr_err = LDAP_REFERRAL;
				rs->sr_matched = matched_dn.bv_val;
			}

			mdb_entry_return(op, matched);
			matched = NULL;

			if ( erefs ) {
				rs->sr_ref = referral_rewrite( erefs, &matched_dn,
					&op->o_req_dn, op->oq_search.rs_scope );
				ber_bvarray_free( erefs );
			}

		} else {
			rs->sr_ref = referral_rewrite( default_referral,
				NULL, &op->o_req_dn, op->oq_search.rs_scope );
			rs->sr_err = rs->sr_ref != NULL ? LDAP_REFERRAL : LDAP_NO_SUCH_OBJECT;
		}

		send_ldap_result( op, rs );

		if ( rs->sr_ref ) {
			ber_bvarray_free( rs->sr_ref );
			rs->sr_ref = NULL;
		}
		if ( !BER_BVISNULL( &matched_dn ) ) {
			ber_memfree( matched_dn.bv_val );
			rs->sr_matched = NULL;
		}
		goto done;
	}

	/* NOTE: __NEW__ "search" access is required
	 * on searchBase object */
	if ( ! access_allowed_mask( op, e, slap_schema.si_ad_entry,
				NULL, ACL_SEARCH, NULL, &mask ) )
	{
		if ( !ACL_GRANT( mask, ACL_DISCLOSE ) ) {
			rs->sr_err = LDAP_NO_SUCH_OBJECT;
		} else {
			rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
		}

		mdb_entry_return( op,e);
		send_ldap_result( op, rs );
		goto done;
	}

	if ( !manageDSAit && is_entry_referral( e ) ) {
		/* entry is a referral */
		struct berval matched_dn = BER_BVNULL;
		BerVarray erefs = NULL;
		
		ber_dupbv( &matched_dn, &e->e_name );
		erefs = get_entry_referrals( op, e );

		rs->sr_err = LDAP_REFERRAL;

		mdb_entry_return( op, e );
		e = NULL;

		if ( erefs ) {
			rs->sr_ref = referral_rewrite( erefs, &matched_dn,
				&op->o_req_dn, op->oq_search.rs_scope );
			ber_bvarray_free( erefs );

			if ( !rs->sr_ref ) {
				rs->sr_text = "bad_referral object";
			}
		}

		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(mdb_search) ": entry is referral\n",
			0, 0, 0 );

		rs->sr_matched = matched_dn.bv_val;
		send_ldap_result( op, rs );

		ber_bvarray_free( rs->sr_ref );
		rs->sr_ref = NULL;
		ber_memfree( matched_dn.bv_val );
		rs->sr_matched = NULL;
		goto done;
	}

	if ( get_assert( op ) &&
		( test_filter( op, e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
	{
		rs->sr_err = LDAP_ASSERTION_FAILED;
		mdb_entry_return( op,e);
		send_ldap_result( op, rs );
		goto done;
	}

	/* compute it anyway; root does not use it */
	stoptime = op->o_time + op->ors_tlimit;

	base = e;

	e = NULL;

	/* select candidates */
	if ( op->oq_search.rs_scope == LDAP_SCOPE_BASE ) {
		rs->sr_err = base_candidate( op->o_bd, base, candidates );
		scopes[0].mid = 0;
		ncand = 1;
	} else {
		if ( op->ors_scope == LDAP_SCOPE_ONELEVEL ) {
			size_t nkids;
			MDB_val key, data;
			key.mv_data = &base->e_id;
			key.mv_size = sizeof( ID );
			mdb_cursor_get( mcd, &key, &data, MDB_SET );
			mdb_cursor_count( mcd, &nkids );
			nsubs = nkids - 1;
		} else if ( !base->e_id ) {
			/* we don't maintain nsubs for entryID 0.
			 * just grab entry count from id2entry stat
			 */
			MDB_stat ms;
			mdb_stat( ltid, mdb->mi_id2entry, &ms );
			nsubs = ms.ms_entries;
		}
		MDB_IDL_ZERO( candidates );
		scopes[0].mid = 1;
		scopes[1].mid = base->e_id;
		scopes[1].mval.mv_data = NULL;
		rs->sr_err = search_candidates( op, rs, base,
			&isc, mci, candidates, stack );
		ncand = MDB_IDL_N( candidates );
		if ( !base->e_id || ncand == NOID ) {
			/* grab entry count from id2entry stat
			 */
			MDB_stat ms;
			mdb_stat( ltid, mdb->mi_id2entry, &ms );
			if ( !base->e_id )
				nsubs = ms.ms_entries;
			if ( ncand == NOID )
				ncand = ms.ms_entries;
		}
	}

	/* start cursor at beginning of candidates.
	 */
	cursor = 0;

	if ( candidates[0] == 0 ) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(mdb_search) ": no candidates\n",
			0, 0, 0 );

		goto nochange;
	}

	/* if not root and candidates exceed to-be-checked entries, abort */
	if ( op->ors_limit	/* isroot == FALSE */ &&
		op->ors_limit->lms_s_unchecked != -1 &&
		ncand > (unsigned) op->ors_limit->lms_s_unchecked )
	{
		rs->sr_err = LDAP_ADMINLIMIT_EXCEEDED;
		send_ldap_result( op, rs );
		rs->sr_err = LDAP_SUCCESS;
		goto done;
	}

	if ( op->ors_limit == NULL	/* isroot == TRUE */ ||
		!op->ors_limit->lms_s_pr_hide )
	{
		tentries = ncand;
	}

	wwctx.flag = 0;
	/* If we're running in our own read txn */
	if (  moi == &opinfo ) {
		cb.sc_writewait = mdb_writewait;
		cb.sc_private = &wwctx;
		wwctx.txn = ltid;
		wwctx.mcd = NULL;
		cb.sc_next = op->o_callback;
		op->o_callback = &cb;
	}

	if ( get_pagedresults( op ) > SLAP_CONTROL_IGNORED ) {
		PagedResultsState *ps = op->o_pagedresults_state;
		/* deferred cookie parsing */
		rs->sr_err = parse_paged_cookie( op, rs );
		if ( rs->sr_err != LDAP_SUCCESS ) {
			send_ldap_result( op, rs );
			goto done;
		}

		cursor = (ID) ps->ps_cookie;
		if ( cursor && ps->ps_size == 0 ) {
			rs->sr_err = LDAP_SUCCESS;
			rs->sr_text = "search abandoned by pagedResult size=0";
			send_ldap_result( op, rs );
			goto done;
		}
		id = mdb_idl_first( candidates, &cursor );
		if ( id == NOID ) {
			Debug( LDAP_DEBUG_TRACE, 
				LDAP_XSTRING(mdb_search)
				": no paged results candidates\n",
				0, 0, 0 );
			send_paged_response( op, rs, &lastid, 0 );

			rs->sr_err = LDAP_OTHER;
			goto done;
		}
		if ( id == (ID)ps->ps_cookie )
			id = mdb_idl_next( candidates, &cursor );
		nsubs = ncand;	/* always bypass scope'd search */
		goto loop_begin;
	}
	if ( nsubs < ncand ) {
		int rc;
		/* Do scope-based search */

		/* if any alias scopes were set, save them */
		if (scopes[0].mid > 1) {
			cursor = 1;
			for (cscope = 1; cscope <= scopes[0].mid; cscope++) {
				/* Ignore the original base */
				if (scopes[cscope].mid == base->e_id)
					continue;
				iscopes[cursor++] = scopes[cscope].mid;
			}
			iscopes[0] = scopes[0].mid - 1;
		} else {
			iscopes[0] = 0;
		}

		wwctx.mcd = mcd;
		isc.id = base->e_id;
		isc.numrdns = 0;
		rc = mdb_dn2id_walk( op, &isc );
		if ( rc )
			id = NOID;
		else
			id = isc.id;
		cscope = 0;
	} else {
		id = mdb_idl_first( candidates, &cursor );
	}

	while (id != NOID)
	{
		int scopeok;
		MDB_val edata;

loop_begin:

		/* check for abandon */
		if ( op->o_abandon ) {
			rs->sr_err = SLAPD_ABANDON;
			send_ldap_result( op, rs );
			goto done;
		}

		/* mostly needed by internal searches,
		 * e.g. related to syncrepl, for whom
		 * abandon does not get set... */
		if ( slapd_shutdown ) {
			rs->sr_err = LDAP_UNAVAILABLE;
			send_ldap_disconnect( op, rs );
			goto done;
		}

		/* check time limit */
		if ( op->ors_tlimit != SLAP_NO_LIMIT
				&& slap_get_time() > stoptime )
		{
			rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;
			rs->sr_ref = rs->sr_v2ref;
			send_ldap_result( op, rs );
			rs->sr_err = LDAP_SUCCESS;
			goto done;
		}


		if ( nsubs < ncand ) {
			unsigned i;
			/* Is this entry in the candidate list? */
			scopeok = 0;
			if (MDB_IDL_IS_RANGE( candidates )) {
				if ( id >= MDB_IDL_RANGE_FIRST( candidates ) &&
					id <= MDB_IDL_RANGE_LAST( candidates ))
					scopeok = 1;
			} else {
				i = mdb_idl_search( candidates, id );
				if ( candidates[i] == id )
					scopeok = 1;
			}
			if ( scopeok )
				goto scopeok;
			goto loop_continue;
		}

		/* Does this candidate actually satisfy the search scope?
		 */
		scopeok = 0;
		isc.numrdns = 0;
		switch( op->ors_scope ) {
		case LDAP_SCOPE_BASE:
			/* This is always true, yes? */
			if ( id == base->e_id ) scopeok = 1;
			break;

#ifdef LDAP_SCOPE_CHILDREN
		case LDAP_SCOPE_CHILDREN:
			if ( id == base->e_id ) break;
			/* Fall-thru */
#endif
		case LDAP_SCOPE_SUBTREE:
			if ( id == base->e_id ) {
				scopeok = 1;
				break;
			}
			/* Fall-thru */
		case LDAP_SCOPE_ONELEVEL:
			isc.id = id;
			isc.nscope = 0;
			rs->sr_err = mdb_idscopes( op, &isc );
			if ( rs->sr_err == MDB_SUCCESS ) {
				if ( isc.nscope )
					scopeok = 1;
			} else {
				if ( rs->sr_err == MDB_NOTFOUND )
					goto notfound;
			}
			break;
		}

		/* Not in scope, ignore it */
		if ( !scopeok )
		{
			Debug( LDAP_DEBUG_TRACE,
				LDAP_XSTRING(mdb_search)
				": %ld scope not okay\n",
				(long) id, 0, 0 );
			goto loop_continue;
		}

scopeok:
		if ( id == base->e_id ) {
			e = base;
		} else {

			/* get the entry */
			rs->sr_err = mdb_id2edata( op, mci, id, &edata );
			if ( rs->sr_err == MDB_NOTFOUND ) {
notfound:
				if( nsubs < ncand )
					goto loop_continue;

				if( !MDB_IDL_IS_RANGE(candidates) ) {
					/* only complain for non-range IDLs */
					Debug( LDAP_DEBUG_TRACE,
						LDAP_XSTRING(mdb_search)
						": candidate %ld not found\n",
						(long) id, 0, 0 );
				} else {
					/* get the next ID from the DB */
					rs->sr_err = mdb_get_nextid( mci, &cursor );
					if ( rs->sr_err == MDB_NOTFOUND ) {
						break;
					}
					if ( rs->sr_err ) {
						rs->sr_err = LDAP_OTHER;
						rs->sr_text = "internal error in get_nextid";
						send_ldap_result( op, rs );
						goto done;
					}
					cursor--;
				}

				goto loop_continue;
			} else if ( rs->sr_err ) {
				rs->sr_err = LDAP_OTHER;
				rs->sr_text = "internal error in mdb_id2edata";
				send_ldap_result( op, rs );
				goto done;
			}

			rs->sr_err = mdb_entry_decode( op, ltid, &edata, &e );
			if ( rs->sr_err ) {
				rs->sr_err = LDAP_OTHER;
				rs->sr_text = "internal error in mdb_entry_decode";
				send_ldap_result( op, rs );
				goto done;
			}
			e->e_id = id;
			e->e_name.bv_val = NULL;
			e->e_nname.bv_val = NULL;
		}

		if ( is_entry_subentry( e ) ) {
			if( op->oq_search.rs_scope != LDAP_SCOPE_BASE ) {
				if(!get_subentries_visibility( op )) {
					/* only subentries are visible */
					goto loop_continue;
				}

			} else if ( get_subentries( op ) &&
				!get_subentries_visibility( op ))
			{
				/* only subentries are visible */
				goto loop_continue;
			}

		} else if ( get_subentries_visibility( op )) {
			/* only subentries are visible */
			goto loop_continue;
		}

		/* aliases were already dereferenced in candidate list */
		if ( op->ors_deref & LDAP_DEREF_SEARCHING ) {
			/* but if the search base is an alias, and we didn't
			 * deref it when finding, return it.
			 */
			if ( is_entry_alias(e) &&
				((op->ors_deref & LDAP_DEREF_FINDING) || e != base ))
			{
				goto loop_continue;
			}
		}

		if ( !manageDSAit && is_entry_glue( e )) {
			goto loop_continue;
		}

		if (e != base) {
			struct berval pdn, pndn;
			char *d, *n;
			int i;

			/* child of base, just append RDNs to base->e_name */
			if ( nsubs < ncand || isc.scopes[isc.nscope].mid == base->e_id ) {
				pdn = base->e_name;
				pndn = base->e_nname;
			} else {
				mdb_id2name( op, ltid, &isc.mc, scopes[isc.nscope].mid, &pdn, &pndn );
			}
			e->e_name.bv_len = pdn.bv_len;
			e->e_nname.bv_len = pndn.bv_len;
			for (i=0; i<isc.numrdns; i++) {
				e->e_name.bv_len += isc.rdns[i].bv_len + 1;
				e->e_nname.bv_len += isc.nrdns[i].bv_len + 1;
			}
			e->e_name.bv_val = op->o_tmpalloc(e->e_name.bv_len + 1, op->o_tmpmemctx);
			e->e_nname.bv_val = op->o_tmpalloc(e->e_nname.bv_len + 1, op->o_tmpmemctx);
			d = e->e_name.bv_val;
			n = e->e_nname.bv_val;
			if (nsubs < ncand) {
				/* RDNs are in top-down order */
				for (i=isc.numrdns-1; i>=0; i--) {
					memcpy(d, isc.rdns[i].bv_val, isc.rdns[i].bv_len);
					d += isc.rdns[i].bv_len;
					*d++ = ',';
					memcpy(n, isc.nrdns[i].bv_val, isc.nrdns[i].bv_len);
					n += isc.nrdns[i].bv_len;
					*n++ = ',';
				}
			} else {
				/* RDNs are in bottom-up order */
				for (i=0; i<isc.numrdns; i++) {
					memcpy(d, isc.rdns[i].bv_val, isc.rdns[i].bv_len);
					d += isc.rdns[i].bv_len;
					*d++ = ',';
					memcpy(n, isc.nrdns[i].bv_val, isc.nrdns[i].bv_len);
					n += isc.nrdns[i].bv_len;
					*n++ = ',';
				}
			}

			if (pdn.bv_len) {
				memcpy(d, pdn.bv_val, pdn.bv_len+1);
				memcpy(n, pndn.bv_val, pndn.bv_len+1);
			} else {
				*--d = '\0';
				*--n = '\0';
				e->e_name.bv_len--;
				e->e_nname.bv_len--;
			}
			if (pndn.bv_val != base->e_nname.bv_val) {
				op->o_tmpfree(pndn.bv_val, op->o_tmpmemctx);
				op->o_tmpfree(pdn.bv_val, op->o_tmpmemctx);
			}
		}

		/*
		 * if it's a referral, add it to the list of referrals. only do
		 * this for non-base searches, and don't check the filter
		 * explicitly here since it's only a candidate anyway.
		 */
		if ( !manageDSAit && op->oq_search.rs_scope != LDAP_SCOPE_BASE
			&& is_entry_referral( e ) )
		{
			BerVarray erefs = get_entry_referrals( op, e );
			rs->sr_ref = referral_rewrite( erefs, &e->e_name, NULL,
				op->oq_search.rs_scope == LDAP_SCOPE_ONELEVEL
					? LDAP_SCOPE_BASE : LDAP_SCOPE_SUBTREE );

			rs->sr_entry = e;
			rs->sr_flags = 0;

			send_search_reference( op, rs );

			if (e != base)
				mdb_entry_return( op, e );
			rs->sr_entry = NULL;
			e = NULL;

			ber_bvarray_free( rs->sr_ref );
			ber_bvarray_free( erefs );
			rs->sr_ref = NULL;

			if ( wwctx.flag ) {
				rs->sr_err = mdb_waitfixup( op, &wwctx, mci, mcd );
				if ( rs->sr_err ) {
					send_ldap_result( op, rs );
					goto done;
				}
			}

			goto loop_continue;
		}

		/* if it matches the filter and scope, send it */
		rs->sr_err = test_filter( op, e, op->oq_search.rs_filter );

		if ( rs->sr_err == LDAP_COMPARE_TRUE ) {
			/* check size limit */
			if ( get_pagedresults(op) > SLAP_CONTROL_IGNORED ) {
				if ( rs->sr_nentries >= ((PagedResultsState *)op->o_pagedresults_state)->ps_size ) {
					mdb_entry_return( op, e );
					e = NULL;
					send_paged_response( op, rs, &lastid, tentries );
					goto done;
				}
				lastid = id;
			}

			if (e) {
				/* safe default */
				rs->sr_attrs = op->oq_search.rs_attrs;
				rs->sr_operational_attrs = NULL;
				rs->sr_ctrls = NULL;
				rs->sr_entry = e;
				RS_ASSERT( e->e_private != NULL );
				rs->sr_flags = 0;
				rs->sr_err = LDAP_SUCCESS;
				rs->sr_err = send_search_entry( op, rs );
				rs->sr_attrs = NULL;
				rs->sr_entry = NULL;
				if (e != base)
					mdb_entry_return( op, e );
				e = NULL;

				switch ( rs->sr_err ) {
				case LDAP_SUCCESS:	/* entry sent ok */
					break;
				default:		/* entry not sent */
					break;
				case LDAP_BUSY:
					send_ldap_result( op, rs );
					goto done;
				case LDAP_UNAVAILABLE:
				case LDAP_SIZELIMIT_EXCEEDED:
					if ( rs->sr_err == LDAP_SIZELIMIT_EXCEEDED ) {
						rs->sr_ref = rs->sr_v2ref;
						send_ldap_result( op, rs );
						rs->sr_err = LDAP_SUCCESS;

					} else {
						rs->sr_err = LDAP_OTHER;
					}
					goto done;
				}
				if ( wwctx.flag ) {
					rs->sr_err = mdb_waitfixup( op, &wwctx, mci, mcd );
					if ( rs->sr_err ) {
						send_ldap_result( op, rs );
						goto done;
					}
				}
			}

		} else {
			Debug( LDAP_DEBUG_TRACE,
				LDAP_XSTRING(mdb_search)
				": %ld does not match filter\n",
				(long) id, 0, 0 );
		}

loop_continue:
		if( e != NULL ) {
			if ( e != base )
				mdb_entry_return( op, e );
			RS_ASSERT( rs->sr_entry == NULL );
			e = NULL;
			rs->sr_entry = NULL;
		}

		if ( nsubs < ncand ) {
			int rc = mdb_dn2id_walk( op, &isc );
			if (rc) {
				id = NOID;
				/* We got to the end of a subtree. If there are any
				 * alias scopes left, search them too.
				 */
				while (iscopes[0] && cscope < iscopes[0]) {
					cscope++;
					isc.id = iscopes[cscope];
					if ( base )
						mdb_entry_return( op, base );
					rs->sr_err = mdb_id2entry(op, mci, isc.id, &base);
					if ( !rs->sr_err ) {
						mdb_id2name( op, ltid, &isc.mc, isc.id, &base->e_name, &base->e_nname );
						isc.numrdns = 0;
						if (isc.oscope == LDAP_SCOPE_ONELEVEL)
							isc.oscope = LDAP_SCOPE_BASE;
						rc = mdb_dn2id_walk( op, &isc );
						if ( !rc ) {
							id = isc.id;
							break;
						}
					}
				}
			} else
				id = isc.id;
		} else {
			id = mdb_idl_next( candidates, &cursor );
		}
	}

nochange:
	rs->sr_ctrls = NULL;
	rs->sr_ref = rs->sr_v2ref;
	rs->sr_err = (rs->sr_v2ref == NULL) ? LDAP_SUCCESS : LDAP_REFERRAL;
	rs->sr_rspoid = NULL;
	if ( get_pagedresults(op) > SLAP_CONTROL_IGNORED ) {
		send_paged_response( op, rs, NULL, 0 );
	} else {
		send_ldap_result( op, rs );
	}

	rs->sr_err = LDAP_SUCCESS;

done:
	if ( cb.sc_private ) {
		/* remove our writewait callback */
		slap_callback **scp = &op->o_callback;
		while ( *scp ) {
			if ( *scp == &cb ) {
				*scp = cb.sc_next;
				cb.sc_private = NULL;
				break;
			}
		}
	}
	mdb_cursor_close( mcd );
	mdb_cursor_close( mci );
	if ( moi == &opinfo ) {
		mdb_txn_reset( moi->moi_txn );
		LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next );
	} else {
		moi->moi_ref--;
	}
	if( rs->sr_v2ref ) {
		ber_bvarray_free( rs->sr_v2ref );
		rs->sr_v2ref = NULL;
	}
	if (base)
		mdb_entry_return( op, base );
	scope_chunk_ret( op, scopes );

	return rs->sr_err;
}
Пример #9
0
/*
 * Class:     jmdb_DatabaseWrapper
 * Method:    txnReset
 * Signature: (J)V
 */
JNIEXPORT void JNICALL Java_jmdb_DatabaseWrapper_txnReset(JNIEnv *vm,
		jclass clazz, jlong txnL) {
	mdb_txn_reset((MDB_txn*) txnL);
}
Пример #10
0
int
mdb_referrals( Operation *op, SlapReply *rs )
{
	struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
	Entry *e = NULL;
	int rc = LDAP_SUCCESS;

	MDB_txn		*rtxn;
	mdb_op_info	opinfo = {0}, *moi = &opinfo;

	if( op->o_tag == LDAP_REQ_SEARCH ) {
		/* let search take care of itself */
		return rc;
	}

	if( get_manageDSAit( op ) ) {
		/* let op take care of DSA management */
		return rc;
	} 

	rc = mdb_opinfo_get(op, mdb, 1, &moi);
	switch(rc) {
	case 0:
		break;
	default:
		return LDAP_OTHER;
	}

	rtxn = moi->moi_txn;

	/* get entry */
	rc = mdb_dn2entry( op, rtxn, &op->o_req_ndn, &e, 1 );

	switch(rc) {
	case MDB_NOTFOUND:
	case 0:
		break;
	case LDAP_BUSY:
		rs->sr_text = "ldap server busy";
		goto done;
	default:
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(mdb_referrals)
			": dn2entry failed: %s (%d)\n",
			mdb_strerror(rc), rc, 0 );
		rs->sr_text = "internal error";
		rc = LDAP_OTHER;
		goto done;
	}

	if ( rc == MDB_NOTFOUND ) {
		rc = LDAP_SUCCESS;
		rs->sr_matched = NULL;
		if ( e != NULL ) {
			Debug( LDAP_DEBUG_TRACE,
				LDAP_XSTRING(mdb_referrals)
				": tag=%lu target=\"%s\" matched=\"%s\"\n",
				(unsigned long)op->o_tag, op->o_req_dn.bv_val, e->e_name.bv_val );

			if( is_entry_referral( e ) ) {
				BerVarray ref = get_entry_referrals( op, e );
				rc = LDAP_OTHER;
				rs->sr_ref = referral_rewrite( ref, &e->e_name,
					&op->o_req_dn, LDAP_SCOPE_DEFAULT );
				ber_bvarray_free( ref );
				if ( rs->sr_ref ) {
					rs->sr_matched = ber_strdup_x(
					e->e_name.bv_val, op->o_tmpmemctx );
				}
			}

			mdb_entry_return( op, e );
			e = NULL;
		}

		if( rs->sr_ref != NULL ) {
			/* send referrals */
			rc = rs->sr_err = LDAP_REFERRAL;
			send_ldap_result( op, rs );
			ber_bvarray_free( rs->sr_ref );
			rs->sr_ref = NULL;
		} else if ( rc != LDAP_SUCCESS ) {
			rs->sr_text = rs->sr_matched ? "bad referral object" : NULL;
		}

		if (rs->sr_matched) {
			op->o_tmpfree( (char *)rs->sr_matched, op->o_tmpmemctx );
			rs->sr_matched = NULL;
		}
		goto done;
	}

	if ( is_entry_referral( e ) ) {
		/* entry is a referral */
		BerVarray refs = get_entry_referrals( op, e );
		rs->sr_ref = referral_rewrite(
			refs, &e->e_name, &op->o_req_dn, LDAP_SCOPE_DEFAULT );

		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(mdb_referrals)
			": tag=%lu target=\"%s\" matched=\"%s\"\n",
			(unsigned long)op->o_tag, op->o_req_dn.bv_val, e->e_name.bv_val );

		rs->sr_matched = e->e_name.bv_val;
		if( rs->sr_ref != NULL ) {
			rc = rs->sr_err = LDAP_REFERRAL;
			send_ldap_result( op, rs );
			ber_bvarray_free( rs->sr_ref );
			rs->sr_ref = NULL;
		} else {
			rc = LDAP_OTHER;
			rs->sr_text = "bad referral object";
		}

		rs->sr_matched = NULL;
		ber_bvarray_free( refs );
	}

done:
	if ( moi == &opinfo ) {
		mdb_txn_reset( moi->moi_txn );
		LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next );
	}
	if ( e )
		mdb_entry_return( op, e );
	return rc;
}
Пример #11
0
int
mdb_bind( Operation *op, SlapReply *rs )
{
	struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
	Entry		*e;
	Attribute	*a;

	AttributeDescription *password = slap_schema.si_ad_userPassword;

	MDB_txn		*rtxn;
	mdb_op_info	opinfo = {{{0}}}, *moi = &opinfo;

	Debug( LDAP_DEBUG_ARGS,
		"==> " LDAP_XSTRING(mdb_bind) ": dn: %s\n",
		op->o_req_dn.bv_val, 0, 0);

	/* allow noauth binds */
	switch ( be_rootdn_bind( op, NULL ) ) {
	case LDAP_SUCCESS:
		/* frontend will send result */
		return rs->sr_err = LDAP_SUCCESS;

	default:
		/* give the database a chance */
		/* NOTE: this behavior departs from that of other backends,
		 * since the others, in case of password checking failure
		 * do not give the database a chance.  If an entry with
		 * rootdn's name does not exist in the database the result
		 * will be the same.  See ITS#4962 for discussion. */
		break;
	}

	rs->sr_err = mdb_opinfo_get(op, mdb, 1, &moi);
	switch(rs->sr_err) {
	case 0:
		break;
	default:
		rs->sr_text = "internal error";
		send_ldap_result( op, rs );
		return rs->sr_err;
	}

	rtxn = moi->moi_txn;

	/* get entry with reader lock */
	rs->sr_err = mdb_dn2entry( op, rtxn, NULL, &op->o_req_ndn, &e, NULL, 0 );

	switch(rs->sr_err) {
	case MDB_NOTFOUND:
		rs->sr_err = LDAP_INVALID_CREDENTIALS;
		goto done;
	case 0:
		break;
	case LDAP_BUSY:
		rs->sr_text = "ldap_server_busy";
		goto done;
	default:
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "internal error";
		goto done;
	}

	ber_dupbv( &op->oq_bind.rb_edn, &e->e_name );

	/* check for deleted */
	if ( is_entry_subentry( e ) ) {
		/* entry is an subentry, don't allow bind */
		Debug( LDAP_DEBUG_TRACE, "entry is subentry\n", 0,
			0, 0 );
		rs->sr_err = LDAP_INVALID_CREDENTIALS;
		goto done;
	}

	if ( is_entry_alias( e ) ) {
		/* entry is an alias, don't allow bind */
		Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0, 0, 0 );
		rs->sr_err = LDAP_INVALID_CREDENTIALS;
		goto done;
	}

	if ( is_entry_referral( e ) ) {
		Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
			0, 0 );
		rs->sr_err = LDAP_INVALID_CREDENTIALS;
		goto done;
	}

	switch ( op->oq_bind.rb_method ) {
	case LDAP_AUTH_SIMPLE:
		a = attr_find( e->e_attrs, password );
		if ( a == NULL ) {
			rs->sr_err = LDAP_INVALID_CREDENTIALS;
			goto done;
		}

		if ( slap_passwd_check( op, e, a, &op->oq_bind.rb_cred,
					&rs->sr_text ) != 0 )
		{
			/* failure; stop front end from sending result */
			rs->sr_err = LDAP_INVALID_CREDENTIALS;
			goto done;
		}
			
		rs->sr_err = 0;
		break;

	default:
		assert( 0 ); /* should not be reachable */
		rs->sr_err = LDAP_STRONG_AUTH_NOT_SUPPORTED;
		rs->sr_text = "authentication method not supported";
	}

done:
	if ( moi == &opinfo ) {
		mdb_txn_reset( moi->moi_txn );
		LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next );
	} else {
		moi->moi_ref--;
	}
	/* free entry and reader lock */
	if( e != NULL ) {
		mdb_entry_return( op, e );
	}

	if ( rs->sr_err ) {
		send_ldap_result( op, rs );
		if ( rs->sr_ref ) {
			ber_bvarray_free( rs->sr_ref );
			rs->sr_ref = NULL;
		}
	}
	/* front end will send result on success (rs->sr_err==0) */
	return rs->sr_err;
}
Пример #12
0
int main(int argc, const char* argv[])
{
	g_log = stdout;
	db_thread thr;
	db_thread threads[RTHREADS];
	pthread_t tids[RTHREADS];
	priv_data pd;
	mdbinf* mdb = &thr.mdb;
	int i, rc;
	db_connection *cons;
	g_pd = &pd;
	char commit = 1;
	MDB_env *menv = NULL;
	char *lmpath = "lmdb";
	MDB_txn *txn;
	MDB_val key = {1,(void*)"?"}, data = {0,NULL};
	MDB_envinfo stat;

	sqlite3_initialize();
	sqlite3_vfs_register(sqlite3_nullvfs(), 1);

	unlink(lmpath);

	memset(threads, 0, sizeof(threads));
	memset(&thr, 0, sizeof(db_thread));
	memset(&pd, 0, sizeof(priv_data));

	pd.wmdb = calloc(1,sizeof(mdbinf));
	pd.nEnvs = 1;
	pd.nReadThreads = RTHREADS;
	pd.nWriteThreads = 1;
	pd.syncNumbers = calloc(1,sizeof(u64));
	pd.actorIndexes = calloc(1,sizeof(atomic_llong));
	atomic_init(pd.actorIndexes,0);
	g_cons = cons = calloc(NCONS, sizeof(db_connection));
	g_tsd_cursync = 0;
	g_tsd_conn    = NULL;
	g_tsd_wmdb    = NULL;
	g_tsd_thread  = &thr;

	if (mdb_env_create(&menv) != MDB_SUCCESS)
		return -1;
	if (mdb_env_set_maxdbs(menv,5) != MDB_SUCCESS)
		return -1;
	if (mdb_env_set_mapsize(menv,1024*1024*1024) != MDB_SUCCESS)
		return -1;
	// Syncs are handled from erlang.
	if (mdb_env_open(menv, lmpath, MDB_NOSUBDIR|MDB_NOTLS|MDB_NOSYNC, 0664) != MDB_SUCCESS) //MDB_NOSYNC
		return -1;
	if (mdb_txn_begin(menv, NULL, 0, &txn) != MDB_SUCCESS)
		return -1;
	if (mdb_dbi_open(txn, "info", MDB_INTEGERKEY | MDB_CREATE, &pd.wmdb[0].infodb) != MDB_SUCCESS)
		return -1;
	if (mdb_dbi_open(txn, "actors", MDB_CREATE, &pd.wmdb[0].actorsdb) != MDB_SUCCESS)
		return -1;
	if (mdb_dbi_open(txn, "log", MDB_CREATE | MDB_DUPSORT | MDB_DUPFIXED | MDB_INTEGERDUP, 
			&pd.wmdb[0].logdb) != MDB_SUCCESS)
		return -1;
	if (mdb_dbi_open(txn, "pages", MDB_CREATE | MDB_DUPSORT, &pd.wmdb[0].pagesdb) != MDB_SUCCESS)
		return -1;
	if (mdb_txn_commit(txn) != MDB_SUCCESS)
		return -1;

	pd.wmdb[0].env = menv;
	thr.nEnv = 0;
	thr.isreadonly = 0;
	thr.mdb.env = menv;
	thr.mdb.infodb = pd.wmdb[0].infodb;
	thr.mdb.actorsdb = pd.wmdb[0].actorsdb;
	thr.mdb.logdb = pd.wmdb[0].logdb;
	thr.mdb.pagesdb = pd.wmdb[0].pagesdb;
	thr.maxvalsize = mdb_env_get_maxkeysize(mdb->env);
	thr.resFrames = alloca((SQLITE_DEFAULT_PAGE_SIZE/thr.maxvalsize + 1)*sizeof(MDB_val));
	open_txn(&thr.mdb, MDB_RDONLY);

	for (i = 0; i < NCONS; i++)
	{
		char filename[256];
		char commit = 1;
		g_tsd_conn = &cons[i];
		sprintf(filename, "ac%d.db", i);

		pthread_mutex_init(&cons[i].wal.mtx, NULL);

		thr.pagesChanged = 0;

		rc = sqlite3_open(filename,&(cons[i].db));
		if(rc != SQLITE_OK)
		{
			DBG("Unable to open db");
			break;
		}
		rc = sqlite3_exec(cons[i].db,"PRAGMA synchronous=0;PRAGMA journal_mode=wal;",NULL,NULL,NULL);
		if (rc != SQLITE_OK)
		{
			DBG("unable to open wal");
			break;
		}
		cons[i].wal.inProgressTerm = 1;
		cons[i].wal.inProgressEvnum = 1;
		rc = sqlite3_exec(cons[i].db,"CREATE TABLE tab (id INTEGER PRIMARY KEY, txt TEXT);"
			"insert into tab values (1,'aaaa');",NULL,NULL,NULL);
		if (rc != SQLITE_OK)
		{
			DBG("Cant create table");
			break;
		}
		unlock_write_txn(thr.nEnv, 0, &commit);

		mdb_txn_reset(thr.mdb.txn);

		rc = mdb_txn_renew(thr.mdb.txn);
		if (rc != MDB_SUCCESS)
			break;
		rc = mdb_cursor_renew(thr.mdb.txn, mdb->cursorLog);
		if (rc != MDB_SUCCESS)
			break;
		rc = mdb_cursor_renew(thr.mdb.txn, mdb->cursorPages);
		if (rc != MDB_SUCCESS)
			break;
		rc = mdb_cursor_renew(thr.mdb.txn, mdb->cursorInfo);
		if (rc != MDB_SUCCESS)
			break;
	}
	// mdb_cursor_close(thr.mdb.cursorLog);
	// mdb_cursor_close(thr.mdb.cursorPages);
	// mdb_cursor_close(thr.mdb.cursorInfo);
	// mdb_txn_abort(thr.mdb.txn);


	for (i = 0; i < RTHREADS; i++)
	{
		threads[i].nEnv = 0;
		threads[i].isreadonly = 0;
		threads[i].mdb.env = menv;
		threads[i].mdb.infodb = pd.wmdb[0].infodb;
		threads[i].mdb.actorsdb = pd.wmdb[0].actorsdb;
		threads[i].mdb.logdb = pd.wmdb[0].logdb;
		threads[i].mdb.pagesdb = pd.wmdb[0].pagesdb;
		threads[i].maxvalsize = mdb_env_get_maxkeysize(mdb->env);
		pthread_create(&tids[i], NULL, perform, (void *)&threads[i]);
	}

	srand((u32)pthread_self() + time(NULL));
	for (i = 0; i < 1000*200; i++)
	{
		char commit = 1;
		int j = rand() % NCONS;
		db_connection *con = &g_cons[j];
		char str[100];
		if (pthread_mutex_trylock(&con->wal.mtx) != 0)
		{
			i--;
			continue;
		}

		if (i % 1000 == 0)
			printf("w %d\n",i);
		g_tsd_conn = con;
		lock_wtxn(thr.nEnv);

		thr.pagesChanged = 0;

		if (con->wal.firstCompleteEvnum+10 < con->wal.lastCompleteEvnum)
		{
			// printf("CHECKPOINT? %llu %llu\n",con->wal.firstCompleteEvnum,con->wal.lastCompleteEvnum);
			if (checkpoint(&con->wal, con->wal.lastCompleteEvnum-10) != SQLITE_OK)
			{
				printf("Checkpoint failed\n");
				break;
			}
		}
		con->wal.inProgressTerm = 1;
		con->wal.inProgressEvnum = con->wal.lastCompleteEvnum+1;

		sprintf(str,"INSERT INTO tab VALUES (%d,'VALUE VALUE13456');", i);
		sqlite3_exec(con->db,str,NULL,NULL,NULL);

		pthread_mutex_unlock(&con->wal.mtx);

		unlock_write_txn(thr.nEnv, 0, &commit);

		mdb_txn_reset(thr.mdb.txn);
		rc = mdb_txn_renew(thr.mdb.txn);
		if (rc != MDB_SUCCESS)
			break;
		rc = mdb_cursor_renew(thr.mdb.txn, mdb->cursorLog);
		if (rc != MDB_SUCCESS)
			break;
		rc = mdb_cursor_renew(thr.mdb.txn, mdb->cursorPages);
		if (rc != MDB_SUCCESS)
			break;
		rc = mdb_cursor_renew(thr.mdb.txn, mdb->cursorInfo);
		if (rc != MDB_SUCCESS)
			break;
	}

	unlock_write_txn(thr.nEnv, 1, &commit);


	for (i = 0; i < RTHREADS; i++)
		pthread_join(tids[i],NULL);

	return 1;
}
Пример #13
0
int
mdb_compare( Operation *op, SlapReply *rs )
{
	struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
	Entry		*e = NULL;
	int		manageDSAit = get_manageDSAit( op );

	MDB_txn		*rtxn;
	mdb_op_info	opinfo = {{{0}}}, *moi = &opinfo;

	rs->sr_err = mdb_opinfo_get(op, mdb, 1, &moi);
	switch(rs->sr_err) {
	case 0:
		break;
	default:
		send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
		return rs->sr_err;
	}

	rtxn = moi->moi_txn;

	/* get entry */
	rs->sr_err = mdb_dn2entry( op, rtxn, NULL, &op->o_req_ndn, &e, NULL, 1 );
	switch( rs->sr_err ) {
	case MDB_NOTFOUND:
	case 0:
		break;
	case LDAP_BUSY:
		rs->sr_text = "ldap server busy";
		goto return_results;
	default:
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "internal error";
		goto return_results;
	}

	if ( rs->sr_err == MDB_NOTFOUND ) {
		if ( e != NULL ) {
			/* return referral only if "disclose" is granted on the object */
			if ( ! access_allowed( op, e, slap_schema.si_ad_entry,
				NULL, ACL_DISCLOSE, NULL ) )
			{
				rs->sr_err = LDAP_NO_SUCH_OBJECT;

			} else {
				rs->sr_matched = ch_strdup( e->e_dn );
				if ( is_entry_referral( e )) {
					BerVarray ref = get_entry_referrals( op, e );
					rs->sr_ref = referral_rewrite( ref, &e->e_name,
						&op->o_req_dn, LDAP_SCOPE_DEFAULT );
					ber_bvarray_free( ref );
				} else {
					rs->sr_ref = NULL;
				}
				rs->sr_err = LDAP_REFERRAL;
			}
			mdb_entry_return( op, e );
			e = NULL;

		} else {
			rs->sr_ref = referral_rewrite( default_referral,
				NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
			rs->sr_err = rs->sr_ref ? LDAP_REFERRAL : LDAP_NO_SUCH_OBJECT;
		}

		rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
		send_ldap_result( op, rs );
		goto done;
	}

	if (!manageDSAit && is_entry_referral( e ) ) {
		/* return referral only if "disclose" is granted on the object */
		if ( !access_allowed( op, e, slap_schema.si_ad_entry,
			NULL, ACL_DISCLOSE, NULL ) )
		{
			rs->sr_err = LDAP_NO_SUCH_OBJECT;
		} else {
			/* entry is a referral, don't allow compare */
			rs->sr_ref = get_entry_referrals( op, e );
			rs->sr_err = LDAP_REFERRAL;
			rs->sr_matched = e->e_name.bv_val;
		}

		Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 );

		send_ldap_result( op, rs );

		ber_bvarray_free( rs->sr_ref );
		rs->sr_ref = NULL;
		rs->sr_matched = NULL;
		goto done;
	}

	rs->sr_err = slap_compare_entry( op, e, op->orc_ava );

return_results:
	send_ldap_result( op, rs );

	switch ( rs->sr_err ) {
	case LDAP_COMPARE_FALSE:
	case LDAP_COMPARE_TRUE:
		rs->sr_err = LDAP_SUCCESS;
		break;
	}

done:
	if ( moi == &opinfo ) {
		mdb_txn_reset( moi->moi_txn );
		LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next );
	} else {
		moi->moi_ref--;
	}
	/* free entry */
	if ( e != NULL ) {
		mdb_entry_return( op, e );
	}

	return rs->sr_err;
}