X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=ndmp-src%2Fndmpconnobj.c;fp=ndmp-src%2Fndmpconnobj.c;h=ef4de85ffeec14272c307217d8fd517999b13ab7;hb=d28952249e392eb31bc8eecc53f6c477f30c617b;hp=41d14ed0e884515ab6c850dfb96c82c65e0a49c9;hpb=949b8910a5e23c4285d0b1aedacfc82a14dc97a5;p=debian%2Famanda diff --git a/ndmp-src/ndmpconnobj.c b/ndmp-src/ndmpconnobj.c index 41d14ed..ef4de85 100644 --- a/ndmp-src/ndmpconnobj.c +++ b/ndmp-src/ndmpconnobj.c @@ -1,9 +1,10 @@ /* * Copyright (c) 2009-2012 Zmanda, Inc. All Rights Reserved. * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. + * 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 (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY @@ -737,7 +738,7 @@ ndmp_connection_wait_for_notify( } } -typedef struct notify_data { +typedef struct notify_data_s { NDMPConnection *self; ndmp9_data_halt_reason *data_halt_reason; ndmp9_mover_halt_reason *mover_halt_reason; @@ -746,11 +747,15 @@ typedef struct notify_data { GMutex *abort_mutex; GCond *abort_cond; int status; + int in_use; event_handle_t *read_event; -} notify_data; +} notify_data_t; static void handle_notify(void *cookie); +static GStaticMutex notify_mutex = G_STATIC_MUTEX_INIT; +static notify_data_t **notify_data = NULL; +static int nb_notify_data = 0; int ndmp_connection_wait_for_notify_with_cond( NDMPConnection *self, @@ -758,21 +763,53 @@ ndmp_connection_wait_for_notify_with_cond( ndmp9_mover_halt_reason *mover_halt_reason, ndmp9_mover_pause_reason *mover_pause_reason, guint64 *mover_pause_seek_position, + int *cancelled, GMutex *abort_mutex, GCond *abort_cond) { struct ndmp_msg_buf nmb; - notify_data ndata; + notify_data_t *ndata; gboolean found = FALSE; - - ndata.self = self; - ndata.data_halt_reason= data_halt_reason; - ndata.mover_halt_reason= mover_halt_reason; - ndata.mover_pause_reason= mover_pause_reason; - ndata.mover_pause_seek_position = mover_pause_seek_position; - ndata.abort_mutex = abort_mutex; - ndata.abort_cond = abort_cond; - ndata.status = 2; + int status; + int i; + + g_static_mutex_lock(¬ify_mutex); + if (notify_data == NULL) { + glib_init(); + nb_notify_data = 10; + notify_data = g_new0(notify_data_t *, nb_notify_data); + for (i=0;iin_use > 0) { + i++; + } + if (i == nb_notify_data) { + int new_nb_notify_data = nb_notify_data * 2; + int j; + notify_data = g_realloc(notify_data, + sizeof(notify_data_t *) * new_nb_notify_data); + for (j=nb_notify_data; jself = self; + ndata->data_halt_reason= data_halt_reason; + ndata->mover_halt_reason= mover_halt_reason; + ndata->mover_pause_reason= mover_pause_reason; + ndata->mover_pause_seek_position = mover_pause_seek_position; + ndata->abort_mutex = abort_mutex; + ndata->abort_cond = abort_cond; + ndata->status = 2; + ndata->in_use = 1; + g_static_mutex_unlock(¬ify_mutex); g_assert(!self->startup_err); @@ -818,33 +855,43 @@ ndmp_connection_wait_for_notify_with_cond( * outside of the ndmlib_mutex critical section. This will also be * useful to allow the wait to be aborted. */ - ndata.read_event = event_register(self->conn->chan.fd, - EV_READFD, handle_notify, &ndata); + /* handle_notify can be executed before the register exit */ + ndata->read_event = event_create(self->conn->chan.fd, + EV_READFD, handle_notify, ndata); + event_activate(ndata->read_event); - g_cond_wait(abort_cond, abort_mutex); + while (!*cancelled && ndata->status == 2) { + g_cond_wait(abort_cond, abort_mutex); + } + g_static_mutex_lock(¬ify_mutex); - if (ndata.read_event) { - event_release(ndata.read_event); + if (ndata->read_event) { + event_release(ndata->read_event); + ndata->read_event = NULL; } - if (ndata.status == 2) { + if (ndata->status == 2) { ndmp_connection_mover_abort(self); ndmp_connection_mover_stop(self); } - return ndata.status; + status = ndata->status; + ndata->in_use++; + if (ndata->in_use == 3) + ndata->in_use = 0; + g_static_mutex_unlock(¬ify_mutex); + return status; } static void handle_notify(void *cookie) { - notify_data *ndata = cookie; + notify_data_t *ndata = cookie; struct ndmp_msg_buf nmb; gboolean found = FALSE; + GCond *abort_cond = ndata->abort_cond; + GMutex *abort_mutex = ndata->abort_mutex; - g_mutex_lock(ndata->abort_mutex); - - event_release(ndata->read_event); - ndata->read_event = NULL; + g_mutex_lock(abort_mutex); g_static_mutex_lock(&ndmlib_mutex); NDMOS_MACRO_ZEROFILL(&nmb); @@ -885,16 +932,31 @@ handle_notify(void *cookie) } if (!found) { - ndata->read_event = event_register(ndata->self->conn->chan.fd, - EV_READFD, handle_notify, ndata); - g_mutex_unlock(ndata->abort_mutex); + g_static_mutex_lock(¬ify_mutex); + if (ndata->in_use == 2) { + goto notify_done_locked; + } + g_static_mutex_unlock(¬ify_mutex); + + g_mutex_unlock(abort_mutex); return; } ndata->status = 0; notify_done: - g_cond_broadcast(ndata->abort_cond); - g_mutex_unlock(ndata->abort_mutex); + g_static_mutex_lock(¬ify_mutex); +notify_done_locked: + if (ndata->read_event) { + event_release(ndata->read_event); + ndata->read_event = NULL; + } + ndata->in_use++; + if (ndata->in_use == 3) + ndata->in_use = 0; + g_static_mutex_unlock(¬ify_mutex); + + g_cond_broadcast(abort_cond); + g_mutex_unlock(abort_mutex); } /* * Class Mechanics