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** Thanks. -- [johnnyjacob.org] "May you share freely, never taking more than you give "
commit 5b6769a67afbc768d96c04897d5ce5520721c3c7 Author: Johnny Jacob <[email protected]> Date: Fri Nov 27 12:37:09 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 02e00a7..b87365a 100644 --- a/libmapi/IMAPISupport.c +++ b/libmapi/IMAPISupport.c @@ -361,14 +361,14 @@ _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 to check if it should continue to + process notifications. \return MAPI_E_SUCCESS on success, otherwise MAPI error. @@ -384,8 +384,8 @@ _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, + mapi_notify_continue_callback_t check_continue) { struct mapi_response *mapi_response; struct mapi_notify_ctx *notify_ctx; @@ -394,27 +394,41 @@ _PUBLIC_ enum MAPISTATUS MonitorNotification(struct mapi_session *session, int is_done; int err; char buf[512]; - + fd_set read_fds; + struct timeval tv; + int nread; + /* 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; + tv.tv_sec = 2; /* FIXME: Let the caller set this value? */ + tv.tv_usec = 0; + 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); + } + } while (nread > 0 && err != -1); } - if (err <= 0) is_done = 1; + if ((check_continue != NULL && check_continue ()) || err < 0) + is_done = 1; } return MAPI_E_SUCCESS; Modified libmapi/emsmdb.c diff --git a/libmapi/emsmdb.c b/libmapi/emsmdb.c index fb14391..59355ec 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> @@ -408,6 +410,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..a8d4ba3 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 */ 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 4fff042..91419d8 100644 --- a/utils/openchangeclient.c +++ b/utils/openchangeclient.c @@ -2321,7 +2321,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
