From bd69be7a587df5862cb59d681c1e6f082868569d Mon Sep 17 00:00:00 2001 From: Martin Hedenfal Date: Fri, 11 Jun 2010 12:02:04 +0000 Subject: Wrap searches in a read-only transaction so it is guaranteed to see a consistent snapshot of the database. Also fixes a couple of format string errors for long long ints. --- usr.sbin/ldapd/ldapd.h | 4 +++- usr.sbin/ldapd/search.c | 35 +++++++++++++++++++++++++---------- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/usr.sbin/ldapd/ldapd.h b/usr.sbin/ldapd/ldapd.h index d6e573abbf5..9aebad24db6 100644 --- a/usr.sbin/ldapd/ldapd.h +++ b/usr.sbin/ldapd/ldapd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ldapd.h,v 1.2 2010/06/03 17:29:54 martinh Exp $ */ +/* $OpenBSD: ldapd.h,v 1.3 2010/06/11 12:02:03 martinh Exp $ */ /* * Copyright (c) 2009, 2010 Martin Hedenfalk @@ -162,6 +162,8 @@ struct search { struct conn *conn; struct request *req; struct namespace *ns; + struct btree_txn *data_txn; + struct btree_txn *indx_txn; struct cursor *cursor; unsigned int nscanned, nmatched, ndups; time_t started_at; diff --git a/usr.sbin/ldapd/search.c b/usr.sbin/ldapd/search.c index 6d134811f89..4b2882a2701 100644 --- a/usr.sbin/ldapd/search.c +++ b/usr.sbin/ldapd/search.c @@ -1,4 +1,4 @@ -/* $OpenBSD: search.c,v 1.3 2010/06/03 17:32:25 martinh Exp $ */ +/* $OpenBSD: search.c,v 1.4 2010/06/11 12:02:03 martinh Exp $ */ /* * Copyright (c) 2009, 2010 Martin Hedenfalk @@ -166,8 +166,10 @@ search_close(struct search *search) } btree_cursor_close(search->cursor); + btree_txn_abort(search->data_txn); + btree_txn_abort(search->indx_txn); - log_debug("finished search on msgid %d", search->req->msgid); + log_debug("finished search on msgid %lld", search->req->msgid); TAILQ_REMOVE(&search->conn->searches, search, next); request_free(search->req); filter_free(search->plan); @@ -276,7 +278,7 @@ conn_search(struct search *search) unsigned int op = BT_NEXT; time_t now; struct conn *conn; - struct btree *db; + struct btree_txn *txn; struct btval key, ikey, val; conn = search->conn; @@ -285,12 +287,13 @@ conn_search(struct search *search) bzero(&val, sizeof(val)); if (search->plan->indexed) - db = search->ns->indx_db; + txn = search->indx_txn; else - db = search->ns->data_db; + txn = search->data_txn; if (!search->init) { - if ((search->cursor = btree_cursor_open(db)) == NULL) { + search->cursor = btree_txn_cursor_open(NULL, txn); + if (search->cursor == NULL) { log_warn("btree_cursor_open"); search_close(search); return; @@ -383,7 +386,7 @@ conn_search(struct search *search) btval_reset(&key); continue; } - rc = btree_get(search->ns->data_db, &key, &val); + rc = btree_txn_get(NULL, search->data_txn, &key, &val); if (rc == BT_FAIL) { log_warnx("btree failure"); reason = LDAP_OTHER; @@ -422,7 +425,7 @@ conn_search(struct search *search) /* Check if we have passed the size limit. */ if (rc == BT_SUCCESS && search->szlim > 0 && search->nmatched >= search->szlim) { - log_debug("search %i/%i has reached size limit (%u)", + log_debug("search %d/%lld has reached size limit (%u)", search->conn->fd, search->req->msgid, search->szlim); reason = LDAP_SIZELIMIT_EXCEEDED; @@ -434,7 +437,7 @@ conn_search(struct search *search) now = time(0); if (rc == 0 && search->tmlim > 0 && search->started_at + search->tmlim <= now) { - log_debug("search %i/%i has reached time limit (%u)", + log_debug("search %d/%lld has reached time limit (%u)", search->conn->fd, search->req->msgid, search->tmlim); reason = LDAP_TIMELIMIT_EXCEEDED; @@ -779,6 +782,16 @@ ldap_search(struct request *req) goto done; } + search->data_txn = btree_txn_begin(search->ns->data_db, 1); + if (search->data_txn != NULL) + search->indx_txn = btree_txn_begin(search->ns->indx_db, 1); + if (search->indx_txn == NULL) { + btree_txn_abort(search->data_txn); + search->data_txn = NULL; + reason = LDAP_OPERATIONS_ERROR; + goto done; + } + if (search->scope == LDAP_SCOPE_BASE) { struct btval key, val; @@ -786,7 +799,7 @@ ldap_search(struct request *req) bzero(&val, sizeof(val)); key.data = search->basedn; key.size = strlen(key.data); - switch (btree_get(search->ns->data_db, &key, &val)) { + switch (btree_txn_get(NULL, search->data_txn, &key, &val)) { case BT_SUCCESS: check_search_entry(&key, &val, search); btval_reset(&val); @@ -794,7 +807,9 @@ ldap_search(struct request *req) case BT_NOTFOUND: reason = LDAP_SUCCESS; goto done; + case BT_DEAD: case BT_FAIL: + default: reason = LDAP_OTHER; goto done; } -- cgit v1.2.3