This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
#include "librpc/gen_ndr/messaging.h"
#include "librpc/gen_ndr/ndr_messaging.h"
-/* the locking database handle */
-static int received_signal;
+struct messaging_tdb_context {
+ struct messaging_context *msg_ctx;
+ struct tdb_wrap *tdb;
+ struct tevent_signal *se;
+ int received_messages;
+};
static NTSTATUS messaging_tdb_send(struct messaging_context *msg_ctx,
struct server_id pid, int msg_type,
const DATA_BLOB *data,
struct messaging_backend *backend);
+static void message_dispatch(struct messaging_context *msg_ctx);
-/****************************************************************************
- Notifications come in as signals.
-****************************************************************************/
-
-static void sig_usr1(void)
+static void messaging_tdb_signal_handler(struct tevent_context *ev_ctx,
+ struct tevent_signal *se,
+ int signum, int count,
+ void *_info, void *private_data)
{
- received_signal = 1;
- sys_select_signal(SIGUSR1);
-}
+ struct messaging_tdb_context *ctx = talloc_get_type(private_data,
+ struct messaging_tdb_context);
-static int messaging_tdb_destructor(struct messaging_backend *tdb_ctx)
-{
- TDB_CONTEXT *tdb = (TDB_CONTEXT *)tdb_ctx->private_data;
- tdb_close(tdb);
- return 0;
+ ctx->received_messages++;
+
+ DEBUG(10, ("messaging_tdb_signal_handler: sig[%d] count[%d] msgs[%d]\n",
+ signum, count, ctx->received_messages));
+
+ message_dispatch(ctx->msg_ctx);
}
/****************************************************************************
struct messaging_backend **presult)
{
struct messaging_backend *result;
- TDB_CONTEXT *tdb;
+ struct messaging_tdb_context *ctx;
if (!(result = TALLOC_P(mem_ctx, struct messaging_backend))) {
DEBUG(0, ("talloc failed\n"));
return NT_STATUS_NO_MEMORY;
}
- tdb = tdb_open_log(lock_path("messages.tdb"),
- 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT,
- O_RDWR|O_CREAT,0600);
+ ctx = TALLOC_ZERO_P(result, struct messaging_tdb_context);
+ if (!ctx) {
+ DEBUG(0, ("talloc failed\n"));
+ TALLOC_FREE(result);
+ return NT_STATUS_NO_MEMORY;
+ }
+ result->private_data = ctx;
+ result->send_fn = messaging_tdb_send;
+
+ ctx->msg_ctx = msg_ctx;
+
+ ctx->tdb = tdb_wrap_open(ctx, lock_path("messages.tdb"), 0,
+ TDB_CLEAR_IF_FIRST|TDB_DEFAULT|TDB_VOLATILE,
+ O_RDWR|O_CREAT,0600);
- if (!tdb) {
+ if (!ctx->tdb) {
NTSTATUS status = map_nt_error_from_unix(errno);
DEBUG(0, ("ERROR: Failed to initialise messages database: "
"%s\n", strerror(errno)));
return status;
}
- sec_init();
-
- /* Activate the per-hashchain freelist */
- tdb_set_max_dead(tdb, 5);
-
- CatchSignal(SIGUSR1, SIGNAL_CAST sig_usr1);
-
- result->private_data = (void *)tdb;
- result->send_fn = messaging_tdb_send;
+ ctx->se = tevent_add_signal(msg_ctx->event_ctx,
+ ctx,
+ SIGUSR1, 0,
+ messaging_tdb_signal_handler,
+ ctx);
+ if (!ctx->se) {
+ NTSTATUS status = map_nt_error_from_unix(errno);
+ DEBUG(0, ("ERROR: Failed to initialise messages signal handler: "
+ "%s\n", strerror(errno)));
+ TALLOC_FREE(result);
+ return status;
+ }
- talloc_set_destructor(result, messaging_tdb_destructor);
+ sec_init();
*presult = result;
return NT_STATUS_OK;
Form a static tdb key from a pid.
******************************************************************/
-static TDB_DATA message_key_pid(struct server_id pid)
+static TDB_DATA message_key_pid(TALLOC_CTX *mem_ctx, struct server_id pid)
{
- static char key[20];
+ char *key;
TDB_DATA kbuf;
- slprintf(key, sizeof(key)-1, "PID/%s", procid_str_static(&pid));
+ key = talloc_asprintf(talloc_tos(), "PID/%s", procid_str_static(&pid));
+
+ SMB_ASSERT(key != NULL);
kbuf.dptr = (uint8 *)key;
kbuf.dsize = strlen(key)+1;
struct messaging_array *result;
TDB_DATA data;
DATA_BLOB blob;
- NTSTATUS status;
+ enum ndr_err_code ndr_err;
if (!(result = TALLOC_ZERO_P(mem_ctx, struct messaging_array))) {
return NT_STATUS_NO_MEMORY;
blob = data_blob_const(data.dptr, data.dsize);
- status = ndr_pull_struct_blob(
- &blob, result, result,
+ ndr_err = ndr_pull_struct_blob(
+ &blob, result, NULL, result,
(ndr_pull_flags_fn_t)ndr_pull_messaging_array);
SAFE_FREE(data.dptr);
- if (!NT_STATUS_IS_OK(status)) {
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
TALLOC_FREE(result);
- return status;
+ return ndr_map_error2ntstatus(ndr_err);
}
if (DEBUGLEVEL >= 10) {
{
TDB_DATA data;
DATA_BLOB blob;
- NTSTATUS status;
+ enum ndr_err_code ndr_err;
TALLOC_CTX *mem_ctx;
int ret;
return NT_STATUS_NO_MEMORY;
}
- status = ndr_push_struct_blob(
- &blob, mem_ctx, array,
+ ndr_err = ndr_push_struct_blob(
+ &blob, mem_ctx, NULL, array,
(ndr_push_flags_fn_t)ndr_push_messaging_array);
- if (!NT_STATUS_IS_OK(status)) {
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
talloc_free(mem_ctx);
- return status;
+ return ndr_map_error2ntstatus(ndr_err);
}
if (DEBUGLEVEL >= 10) {
const DATA_BLOB *data,
struct messaging_backend *backend)
{
+ struct messaging_tdb_context *ctx = talloc_get_type(backend->private_data,
+ struct messaging_tdb_context);
struct messaging_array *msg_array;
struct messaging_rec *rec;
- TALLOC_CTX *mem_ctx;
NTSTATUS status;
- TDB_DATA key = message_key_pid(pid);
- TDB_CONTEXT *tdb = (TDB_CONTEXT *)backend->private_data;
+ TDB_DATA key;
+ struct tdb_wrap *tdb = ctx->tdb;
+ TALLOC_CTX *frame = talloc_stackframe();
/* NULL pointer means implicit length zero. */
if (!data->data) {
SMB_ASSERT(procid_to_pid(&pid) > 0);
- if (!(mem_ctx = talloc_init("message_send_pid"))) {
- return NT_STATUS_NO_MEMORY;
- }
+ key = message_key_pid(frame, pid);
- if (tdb_chainlock(tdb, key) == -1) {
- TALLOC_FREE(mem_ctx);
+ if (tdb_chainlock(tdb->tdb, key) == -1) {
+ TALLOC_FREE(frame);
return NT_STATUS_LOCK_NOT_GRANTED;
}
- status = messaging_tdb_fetch(tdb, key, mem_ctx, &msg_array);
+ status = messaging_tdb_fetch(tdb->tdb, key, talloc_tos(), &msg_array);
if (!NT_STATUS_IS_OK(status)) {
goto done;
goto done;
}
- if (!(rec = TALLOC_REALLOC_ARRAY(mem_ctx, msg_array->messages,
+ if (!(rec = TALLOC_REALLOC_ARRAY(talloc_tos(), msg_array->messages,
struct messaging_rec,
msg_array->num_messages+1))) {
status = NT_STATUS_NO_MEMORY;
msg_array->messages = rec;
msg_array->num_messages += 1;
- status = messaging_tdb_store(tdb, key, msg_array);
+ status = messaging_tdb_store(tdb->tdb, key, msg_array);
if (!NT_STATUS_IS_OK(status)) {
goto done;
if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
DEBUG(2, ("pid %s doesn't exist - deleting messages record\n",
procid_str_static(&pid)));
- tdb_delete(tdb, message_key_pid(pid));
+ tdb_delete(tdb->tdb, message_key_pid(talloc_tos(), pid));
}
done:
- tdb_chainunlock(tdb, key);
- TALLOC_FREE(mem_ctx);
+ tdb_chainunlock(tdb->tdb, key);
+ TALLOC_FREE(frame);
return status;
}
struct messaging_array **presult)
{
struct messaging_array *result;
- TDB_DATA key = message_key_pid(procid_self());
+ TDB_DATA key = message_key_pid(mem_ctx, procid_self());
NTSTATUS status;
if (tdb_chainlock(msg_tdb, key) == -1) {
+ TALLOC_FREE(key.dptr);
return NT_STATUS_LOCK_NOT_GRANTED;
}
*presult = result;
}
+ TALLOC_FREE(key.dptr);
+
return status;
}
messages on an *odd* byte boundary.
****************************************************************************/
-void message_dispatch(struct messaging_context *msg_ctx)
+static void message_dispatch(struct messaging_context *msg_ctx)
{
+ struct messaging_tdb_context *ctx = talloc_get_type(msg_ctx->local->private_data,
+ struct messaging_tdb_context);
struct messaging_array *msg_array = NULL;
- TDB_CONTEXT *tdb = (TDB_CONTEXT *)(msg_ctx->local->private_data);
+ struct tdb_wrap *tdb = ctx->tdb;
+ NTSTATUS status;
uint32 i;
- if (!received_signal)
+ if (ctx->received_messages == 0) {
return;
+ }
- DEBUG(10, ("message_dispatch: received_signal = %d\n",
- received_signal));
-
- received_signal = 0;
+ DEBUG(10, ("message_dispatch: received_messages = %d\n",
+ ctx->received_messages));
- if (!NT_STATUS_IS_OK(retrieve_all_messages(tdb, NULL, &msg_array))) {
+ status = retrieve_all_messages(tdb->tdb, NULL, &msg_array);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("message_dispatch: failed to retrieve messages: %s\n",
+ nt_errstr(status)));
return;
}
+ ctx->received_messages = 0;
+
for (i=0; i<msg_array->num_messages; i++) {
messaging_dispatch_rec(msg_ctx, &msg_array->messages[i]);
}