Author: jmcd Date: 2006-09-08 13:00:48 +0000 (Fri, 08 Sep 2006) New Revision: 18263
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=18263 Log: >From Aleksey Fedoseev: Add database traverse for lockd-based locking, allowing locks to be seen in smbstatus. Modified: branches/tmp/vl-messaging/source/include/messages.h branches/tmp/vl-messaging/source/lib/dbwrap_msg.c branches/tmp/vl-messaging/source/lib/messages.c Changeset: Modified: branches/tmp/vl-messaging/source/include/messages.h =================================================================== --- branches/tmp/vl-messaging/source/include/messages.h 2006-09-08 12:48:51 UTC (rev 18262) +++ branches/tmp/vl-messaging/source/include/messages.h 2006-09-08 13:00:48 UTC (rev 18263) @@ -88,6 +88,7 @@ #define MSG_DB_STORE 5005 #define MSG_DB_DELETE 5006 #define MSG_DB_REINIT 5007 +#define MSG_DB_TRAVERSE 5008 /* Flags to classify messages - used in message_send_all() */ /* Sender will filter by flag. */ Modified: branches/tmp/vl-messaging/source/lib/dbwrap_msg.c =================================================================== --- branches/tmp/vl-messaging/source/lib/dbwrap_msg.c 2006-09-08 12:48:51 UTC (rev 18262) +++ branches/tmp/vl-messaging/source/lib/dbwrap_msg.c 2006-09-08 13:00:48 UTC (rev 18263) @@ -445,13 +445,59 @@ return 0; } +static void handle_traverse_return(int msg_type, struct process_id pid, + void *buf, size_t len); + static int db_msg_traverse(struct db_context *db, int (*fn)(TDB_DATA key, TDB_DATA value, void *private_data), void *private_data) { - /* TODO... but traverse will be VERY expensive */ - return -1; + struct db_msg_ctx *ctx = talloc_get_type_abort(db->private_data, + struct db_msg_ctx); + TDB_DATA null_data; + TDB_DATA buf; + static BOOL traverse_msg_reg = False; + int count = 0; + + null_data.dsize = 0; + null_data.dptr = NULL; + buf = msg_pack_data(ctx, ctx->db_index, null_data); + + if(buf.dptr == NULL) { + return -1; + } + + if(!traverse_msg_reg) { + message_register(MSG_DB_TRAVERSE, handle_traverse_return); + traverse_msg_reg = True; + } + + message_send_pid(ctx->lockd, MSG_DB_TRAVERSE, + buf.dptr, buf.dsize, False); + + TALLOC_FREE(buf.dptr); + + SMB_ASSERT(ctx->record == NULL); + + wait_for_return(ctx); + + while(ctx->record != NULL) { + count++; + + if(fn && fn(ctx->record->key, ctx->record->value, private_data)) { + /* break the traversal */ + TALLOC_FREE(ctx->record); + message_deregister(MSG_DB_TRAVERSE); + traverse_msg_reg = False; + break; + } + + TALLOC_FREE(ctx->record); + wait_for_return(ctx); + } + + return count; } static BOOL db_msg_reinit(struct db_context *db) @@ -584,6 +630,70 @@ ctx->record = result; } +static void handle_traverse_return(int msg_type, struct process_id pid, + void *buf, size_t len) +{ + struct db_record *result; + struct db_msg_ctx *ctx = ctx_list; + uint8_t idx; + TDB_DATA key, value; + + DEBUG(10, ("msg_traverse received with len %d\n", len)); + + if(!msg_unpack_double_data((const char *)buf, len, NULL, &idx, &key, &value)) { + DEBUG(2, ("Unpacking error\n")); + return ; + } + + while(ctx) { + if(ctx->db_index == idx) break; + ctx = ctx->next; + } + + if(ctx == NULL) { + DEBUG(2, ("Bad database index %d\n", idx)); + return ; + } + + ctx->received = True; + ctx->record = NULL; + + if(key.dsize > 0) { + result = TALLOC_ZERO_P(ctx, struct db_record); + if (result == NULL) { + DEBUG(0, ("talloc failed\n")); + return ; + } + + result->key.dsize = key.dsize; + result->key.dptr = (char *)talloc_memdup( + result, key.dptr, key.dsize); + + TALLOC_FREE(key.dptr); + + if (result->key.dptr == NULL) { + DEBUG(0, ("talloc failed\n")); + TALLOC_FREE(result); + TALLOC_FREE(value.dptr); + return ; + } + + if(value.dsize > 0) { + result->value.dsize = value.dsize; + result->value.dptr = (char *)talloc_memdup( + result, value.dptr, value.dsize); + TALLOC_FREE(value.dptr); + if (result->value.dptr == NULL) { + DEBUG(0, ("talloc failed\n")); + TALLOC_FREE(result); + return ; + } + } + + ctx->record = result; + } +} + struct db_context *db_open_msg(TALLOC_CTX *mem_ctx, const char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode) @@ -839,8 +949,6 @@ { struct db_records_list *record; - DEBUG(10, ("%p, %d\n", key.dptr, key.dsize)); - if(key.dptr == NULL) { DEBUG(0, ("Fetching null key!\n")); return ; @@ -897,8 +1005,8 @@ data = msg_pack_data(NULL, database->idx, record->value); if(data.dptr != NULL) { - DEBUG(10, ("Sending fetchlock response (len %d)\n", - data.dsize)); + DEBUG(10, ("Sending fetchlock response (len %d) to %s\n", + data.dsize, procid_str_static(src_pid))); message_send_pid_stream(*lockd_pid, *src_pid, MSG_DB_FETCHLOCK, @@ -924,6 +1032,75 @@ } /**************************************************************************** + process database request - traverse +****************************************************************************/ + +struct msg_traverse_ctx { + struct process_id *lockd_pid, *src_pid; + uint8_t db_index; +}; + +static int msg_traverse_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, + void *private_data) +{ + struct msg_traverse_ctx *ctx = (struct msg_traverse_ctx *)private_data; + TDB_DATA data; + + data = msg_pack_double_data(NULL, ctx->db_index, + kbuf, dbuf); + if(data.dptr == NULL) { + DEBUG(0, ("talloc failed\n")); + return 1; + } + + message_send_pid_stream(*ctx->lockd_pid, *ctx->src_pid, + MSG_DB_TRAVERSE, + data.dptr, data.dsize, + False, 0); + + TALLOC_FREE(data.dptr); + + return 0; +} + +static void process_db_traverse(struct process_id *lockd_pid, + struct process_id *src_pid, + struct db_entry *database) +{ + struct msg_traverse_ctx ctx; + TDB_DATA data; + TDB_DATA null_data; + + ctx.lockd_pid = lockd_pid; + ctx.src_pid = src_pid; + ctx.db_index = database->idx; + + if(tdb_traverse(database->db, msg_traverse_func, &ctx) == -1) { + DEBUG(0, ("tdb_traverse error\n")); + return ; + } + + /* final (empty) traverse message */ + + null_data.dsize = 0; + null_data.dptr = NULL; + + data = msg_pack_double_data(NULL, database->idx, + null_data, null_data); + if(data.dptr == NULL) { + DEBUG(0, ("talloc failed\n")); + return ; + } + + message_send_pid_stream(*lockd_pid, *src_pid, + MSG_DB_TRAVERSE, + data.dptr, data.dsize, + False, 0); + + TALLOC_FREE(data.dptr); +} + +/**************************************************************************** process database request - unlock record ****************************************************************************/ @@ -951,8 +1128,8 @@ data = msg_pack_data(NULL, database->idx, record->value); - DEBUG(10, ("Sending fetchlock response (len %d)\n", - data.dsize)); + DEBUG(10, ("Sending fetchlock response (len %d) to %s\n", + data.dsize, procid_str_static(&source))); message_send_pid_stream(*lockd_pid, source, MSG_DB_FETCHLOCK, data.dptr, data.dsize, False, 0); @@ -1075,6 +1252,10 @@ process_db_fetch(lockd_pid, src_pid, dbl, data1); + } else if(msg_type == MSG_DB_TRAVERSE) { + + process_db_traverse(lockd_pid, src_pid, dbl); + } else { /* find the record */ Modified: branches/tmp/vl-messaging/source/lib/messages.c =================================================================== --- branches/tmp/vl-messaging/source/lib/messages.c 2006-09-08 12:48:51 UTC (rev 18262) +++ branches/tmp/vl-messaging/source/lib/messages.c 2006-09-08 13:00:48 UTC (rev 18263) @@ -251,7 +251,7 @@ ****************************************************************************/ static BOOL retrieve_mask_messages(unsigned int mask, - struct message_list **list) + struct message_list **list) { SMB_ASSERT(retrieve_mask_messages_func != NULL); return retrieve_mask_messages_func(mask, list);