On Fri, 2009-12-18 at 12:23 +0100, Julien Kerihuel wrote: > On Fri, 2009-12-18 at 16:53 +0530, Johnny Jacob wrote: > > Hello, > > > > Attached a patch for MonitorNotification (IMAPISupport) to make it > > non-blocking. The API takes a callback to check if it should > continue > > processing notifications or return. > > > > **Patch causes a API change** > > Hi Johnny, > > The new version of this patch sounds good for integration. > Maybe one last remark (since you also mentioned it within your patch). > > It may be useful to refactor the 3rd argument within a data structure > which would take a pointer on a timeval structure and a pointer on the > notification callback. > > The main idea being to make the 2sec notification timeout customizable > and the whole idea a bit more generic. >
Attached a updated patch. Also added a 'void *data' for the callback to use. Thanks. -- [johnnyjacob.org] "May you share freely, never taking more than you give "
commit 4120c22f6908398de4e9a27e827f4c11e9281a20 Author: Johnny Jacob <[email protected]> Date: Mon Dec 21 16:03:40 2009 +0530 Changed MonitorNotification to be non-blocking. Also checks whether to process notifications using a callback. Modified libmapi/IMAPISupport.c diff --git a/libmapi/IMAPISupport.c b/libmapi/IMAPISupport.c index 32d97fc..f6a9784 100644 --- a/libmapi/IMAPISupport.c +++ b/libmapi/IMAPISupport.c @@ -365,14 +365,15 @@ _PUBLIC_ enum MAPISTATUS DispatchNotifications(struct mapi_session *session) /** \details Wait for notifications and process them - This function indefinively waits for notifications on the UDP port + This function waits for notifications on the UDP port and generates the traffic needed to receive MAPI notifications. These MAPI notifications are next compared to the registered ones and the callback specified in Subscribe() called if it matches. - Note that the function will loop indefinitively until an error - occurs. + The function takes a callback in cb_data to check if it should + continue to process notifications. Timeval in cb_data can be + used to control the behavior of select. \return MAPI_E_SUCCESS on success, otherwise MAPI error. @@ -388,37 +389,56 @@ _PUBLIC_ enum MAPISTATUS DispatchNotifications(struct mapi_session *session) non-threaded, only supports fnevNewmail and fnevCreatedObject notifications and will block your process until you send a signal. */ -_PUBLIC_ enum MAPISTATUS MonitorNotification(struct mapi_session *session, - void *private_data) +_PUBLIC_ enum MAPISTATUS MonitorNotification(struct mapi_session *session, void *private_data, + struct mapi_notify_continue_callback_data *cb_data) { struct mapi_response *mapi_response; struct mapi_notify_ctx *notify_ctx; - enum MAPISTATUS retval; NTSTATUS status; int is_done; int err; char buf[512]; - + fd_set read_fds; + int nread; + mapi_notify_continue_callback_t callback; + void *data; + struct timeval *tv; + enum MAPISTATUS retval; + /* sanity checks */ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL); OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL); OPENCHANGE_RETVAL_IF(!session->notify_ctx, MAPI_E_INVALID_PARAMETER, NULL); notify_ctx = session->notify_ctx; + callback = cb_data ? cb_data->callback : NULL; + data = cb_data ? cb_data->data : NULL; + tv = cb_data ? &cb_data->tv : NULL; + nread = 0; is_done = 0; while (!is_done) { - err = read(notify_ctx->fd, buf, sizeof(buf)); - if (err > 0) { - status = emsmdb_transaction_null((struct emsmdb_context *)session->emsmdb->ctx, &mapi_response); - if (!NT_STATUS_IS_OK(status)) { - err = -1; - } else { - retval = ProcessNotification(notify_ctx, mapi_response); - OPENCHANGE_RETVAL_IF(retval, retval, NULL); - } + FD_ZERO(&read_fds); + FD_SET(notify_ctx->fd, &read_fds); + + err = select(notify_ctx->fd + 1, &read_fds, NULL, NULL, tv); + if (FD_ISSET(notify_ctx->fd, &read_fds)) { + do { + nread = read(notify_ctx->fd, buf, sizeof(buf)); + if (nread > 0) { + status = emsmdb_transaction_null((struct emsmdb_context *)session->emsmdb->ctx, + &mapi_response); + if (!NT_STATUS_IS_OK(status)) + err = -1; + else { + retval = ProcessNotification(notify_ctx, mapi_response); + OPENCHANGE_RETVAL_IF(retval, retval, NULL); + } + } + } while (nread > 0 && err != -1); } - if (err <= 0) is_done = 1; + if ((callback != NULL && callback (data)) || err < 0) + is_done = 1; } return MAPI_E_SUCCESS; Modified libmapi/emsmdb.c diff --git a/libmapi/emsmdb.c b/libmapi/emsmdb.c index 52f6ae4..a2cbcb2 100644 --- a/libmapi/emsmdb.c +++ b/libmapi/emsmdb.c @@ -18,6 +18,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <unistd.h> +#include <fcntl.h> #include <libmapi/libmapi.h> #include <libmapi/proto_private.h> #include <gen_ndr/ndr_exchange.h> @@ -412,6 +414,8 @@ retry: return NULL; } + fcntl(notify_ctx->fd, F_SETFL, O_NONBLOCK); + if (bind(notify_ctx->fd, notify_ctx->addr, sizeof(struct sockaddr)) == -1) { shutdown(notify_ctx->fd, SHUT_RDWR); close(notify_ctx->fd); Modified libmapi/mapi_notification.h diff --git a/libmapi/mapi_notification.h b/libmapi/mapi_notification.h index 4ffa63f..8dda76c 100644 --- a/libmapi/mapi_notification.h +++ b/libmapi/mapi_notification.h @@ -27,6 +27,8 @@ */ typedef int (*mapi_notify_callback_t)(uint16_t, void *, void *); +typedef int (*mapi_notify_continue_callback_t)(void *); + struct notifications { uint32_t ulConnection; /* connection number */ uint32_t NotificationFlags; /* events mask associated */ @@ -45,6 +47,12 @@ struct mapi_notify_ctx { struct notifications *notifications; }; +struct mapi_notify_continue_callback_data { + mapi_notify_continue_callback_t callback; /* Consulted for continuing processing events*/ + void *data; /* Data for callback */ + struct timeval tv; /* Timeout for Select call */ +}; + #define DFLT_NOTIF_PORT 2500 #endif /*!__MAPI_NOTIFICATION_H__ */ Modified torture/mapi_newmail.c diff --git a/torture/mapi_newmail.c b/torture/mapi_newmail.c index b2f892a..0310c40 100644 --- a/torture/mapi_newmail.c +++ b/torture/mapi_newmail.c @@ -109,7 +109,7 @@ bool torture_rpc_mapi_newmail(struct torture_context *torture) if (retval != MAPI_E_SUCCESS) return false; /* wait for notifications */ - MonitorNotification(mapi_object_get_session(&obj_inbox),(void *)&obj_store); + MonitorNotification(mapi_object_get_session(&obj_inbox),(void *)&obj_store, NULL); mapi_object_release(&obj_inbox); mapi_object_release(&obj_store); Modified utils/openchangeclient.c diff --git a/utils/openchangeclient.c b/utils/openchangeclient.c index e6bb2fd..e47f4bb 100644 --- a/utils/openchangeclient.c +++ b/utils/openchangeclient.c @@ -2318,7 +2318,7 @@ static bool openchangeclient_notifications(TALLOC_CTX *mem_ctx, mapi_object_t *o if (retval != MAPI_E_SUCCESS) return false; /* wait for notifications: infinite loop */ - retval = MonitorNotification(mapi_object_get_session(obj_store), (void *)obj_store); + retval = MonitorNotification(mapi_object_get_session(obj_store), (void *)obj_store, NULL); if (retval != MAPI_E_SUCCESS) return false; retval = Unsubscribe(mapi_object_get_session(obj_store), ulConnection);
signature.asc
Description: This is a digitally signed message part
_______________________________________________ devel mailing list [email protected] http://mailman.openchange.org/listinfo/devel
