r14755: the change notify code now passes most of the RAW-NOTIFY test. Still
authorAndrew Tridgell <tridge@samba.org>
Wed, 29 Mar 2006 13:31:30 +0000 (13:31 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:59:18 +0000 (13:59 -0500)
more work to do though
(This used to be commit 4d234b37e528137b5c00f6bbb84c2d6939fea324)

source4/ntvfs/common/notify.c
source4/ntvfs/posix/pvfs_mkdir.c
source4/ntvfs/posix/pvfs_notify.c
source4/ntvfs/posix/pvfs_wait.c

index 604b6a1a2d903463e6de38595da67e2b5418c2e4..bc04c830f162096bb36a4a5b11fb48ce4a1cb6c4 100644 (file)
@@ -332,9 +332,6 @@ static BOOL notify_match(struct notify_context *notify, struct notify_entry *e,
                return False;
        }
 
-       if (path[len] == 0) {
-               return True;
-       }
        if (path[len] != '/') {
                return False;
        }
@@ -395,7 +392,9 @@ void notify_trigger(struct notify_context *notify,
        /* this needs to be changed to a log(n) search */
        for (i=0;i<notify->array->num_entries;i++) {
                if (notify_match(notify, &notify->array->entries[i], path, action)) {
-                       notify_send(notify, &notify->array->entries[i], path, action);
+                       notify_send(notify, &notify->array->entries[i], 
+                                   path + strlen(notify->array->entries[i].path) + 1, 
+                                   action);
                }
        }
 }
index 047b6f45a7a60061e3b10b7be2b544dda7151462..5ec7df3b9d3cebb7d21cbb5f5571ad9efd3b5bdf 100644 (file)
@@ -83,6 +83,8 @@ static NTSTATUS pvfs_t2mkdir(struct pvfs_state *pvfs,
                return status;
        }
 
+       notify_trigger(pvfs->notify_context, NOTIFY_ACTION_ADDED, name->full_name);
+
        return NT_STATUS_OK;
 }
 
@@ -135,6 +137,8 @@ NTSTATUS pvfs_mkdir(struct ntvfs_module_context *ntvfs,
                return status;
        }
 
+       notify_trigger(pvfs->notify_context, NOTIFY_ACTION_ADDED, name->full_name);
+
        return NT_STATUS_OK;
 }
 
@@ -172,5 +176,7 @@ NTSTATUS pvfs_rmdir(struct ntvfs_module_context *ntvfs,
                return pvfs_map_errno(pvfs, errno);
        }
 
+       notify_trigger(pvfs->notify_context, NOTIFY_ACTION_REMOVED, name->full_name);
+
        return NT_STATUS_OK;
 }
index 566b6bc0e29b2c276c542f71d6128f4e8bdd9d1d..55a9767863e6354ca9615904c377beb25187d70f 100644 (file)
@@ -33,10 +33,13 @@ struct pvfs_notify_buffer {
        struct notify_changes *changes;
        uint32_t max_buffer_size;
        uint32_t current_buffer_size;
-       void *wait_handle;
+       
+       /* these last two are only present when a notify request is
+          pending */
+       struct ntvfs_request *req;
+       struct smb_notify *info;
 };
 
-
 /*
   destroy a notify buffer. Called when the handle is closed
  */
@@ -48,6 +51,34 @@ static int pvfs_notify_destructor(void *ptr)
        return 0;
 }
 
+/*
+  send a reply to a pending notify request
+*/
+static void pvfs_notify_send(struct pvfs_notify_buffer *notify_buffer)
+{
+       struct ntvfs_request *req = notify_buffer->req;
+       struct smb_notify *info = notify_buffer->info;
+
+       info->out.num_changes = notify_buffer->num_changes;
+       info->out.changes = talloc_steal(req, notify_buffer->changes);
+       notify_buffer->num_changes = 0;
+       notify_buffer->changes = NULL;
+       notify_buffer->current_buffer_size = 0;
+       
+       notify_buffer->req = NULL;
+       notify_buffer->info = NULL;
+
+       DEBUG(0,("sending %d changes\n", info->out.num_changes));
+
+       if (info->out.num_changes == 0) {
+               req->async_states->status = NT_STATUS_CANCELLED;
+       } else {
+               req->async_states->status = NT_STATUS_OK;
+       }
+       req->async_states->send_fn(req);
+}
+
+
 
 /*
   called when a async notify event comes in
@@ -55,7 +86,17 @@ static int pvfs_notify_destructor(void *ptr)
 static void pvfs_notify_callback(void *private, const struct notify_event *ev)
 {
        struct pvfs_notify_buffer *n = talloc_get_type(private, struct pvfs_notify_buffer);
-       DEBUG(0,("got notify for '%s'\n", ev->path));
+
+       n->changes = talloc_realloc(n, n->changes, struct notify_changes, n->num_changes+1);
+       n->changes[n->num_changes].action = ev->action;
+       n->changes[n->num_changes].name.s = talloc_strdup(n->changes, ev->path);
+       n->num_changes++;
+
+       DEBUG(0,("got notify for '%s' action=%d\n", ev->path, ev->action));
+
+       if (n->req != NULL) {
+               pvfs_notify_send(n);
+       }
 }
 
 /*
@@ -86,6 +127,22 @@ static NTSTATUS pvfs_notify_setup(struct pvfs_state *pvfs, struct pvfs_file *f,
        return NT_STATUS_OK;
 }
 
+/*
+  called from the pvfs_wait code when either an event has come in, or
+  the notify request has been cancelled
+*/
+static void pvfs_notify_end(void *private, enum pvfs_wait_notice reason)
+{
+       struct pvfs_notify_buffer *notify_buffer = talloc_get_type(private, struct pvfs_notify_buffer);
+       struct ntvfs_request *req = notify_buffer->req;
+
+       if (req == NULL) {
+               /* nothing to do, nobody is waiting */
+               return;
+       }
+
+       pvfs_notify_send(notify_buffer);
+}
 
 /* change notify request - always async. This request blocks until the
    event buffer is non-empty */
@@ -110,7 +167,7 @@ NTSTATUS pvfs_notify(struct ntvfs_module_context *ntvfs,
 
        /* its only valid for directories */
        if (f->handle->fd != -1) {
-               return NT_STATUS_NOT_A_DIRECTORY;
+               return NT_STATUS_INVALID_PARAMETER;
        }
 
        /* if the handle doesn't currently have a notify buffer then
@@ -123,19 +180,27 @@ NTSTATUS pvfs_notify(struct ntvfs_module_context *ntvfs,
                NT_STATUS_NOT_OK_RETURN(status);
        }
 
+       req->async_states->status = NT_STATUS_OK;
+       
+       if (f->notify_buffer->req != NULL) {
+               DEBUG(0,("Notify already setup\n"));
+               pvfs_notify_send(f->notify_buffer);
+       }
+
+       f->notify_buffer->req = talloc_reference(f->notify_buffer, req);
+       f->notify_buffer->info = info;
+
        /* if the buffer is empty then start waiting */
        if (f->notify_buffer->num_changes == 0) {
-               req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC;
+               void *wait_handle =
+                       pvfs_wait_message(pvfs, req, -1, timeval_zero(), 
+                                         pvfs_notify_end, f->notify_buffer);
+               NT_STATUS_HAVE_NO_MEMORY(wait_handle);
+               talloc_steal(req, wait_handle);
                return NT_STATUS_OK;
        }
 
-       /* otherwise if the buffer is not empty then return its
-          contents immediately */
-       info->out.num_changes = f->notify_buffer->num_changes;
-       info->out.changes = talloc_steal(req, f->notify_buffer->changes);
-       f->notify_buffer->num_changes = 0;
-       f->notify_buffer->changes = NULL;
-       f->notify_buffer->current_buffer_size = 0;
+       pvfs_notify_send(f->notify_buffer);
 
        return NT_STATUS_OK;
 }
index 2d7e41c247481a1e6efa786698f385212212ffe3..5750c0fe087a6baf49d142a946dacad0cdf4b3ae 100644 (file)
@@ -105,7 +105,9 @@ static void pvfs_wait_timeout(struct event_context *ev,
 static int pvfs_wait_destructor(void *ptr)
 {
        struct pvfs_wait *pwait = ptr;
-       messaging_deregister(pwait->msg_ctx, pwait->msg_type, pwait);
+       if (pwait->msg_type != -1) {
+               messaging_deregister(pwait->msg_ctx, pwait->msg_type, pwait);
+       }
        DLIST_REMOVE(pwait->pvfs->wait_list, pwait);
        return 0;
 }
@@ -116,6 +118,9 @@ static int pvfs_wait_destructor(void *ptr)
 
   the return value is a handle. To stop waiting talloc_free this
   handle.
+
+  if msg_type == -1 then no message is registered, and it is assumed
+  that the caller handles any messaging setup needed
 */
 void *pvfs_wait_message(struct pvfs_state *pvfs, 
                        struct ntvfs_request *req, 
@@ -146,10 +151,12 @@ void *pvfs_wait_message(struct pvfs_state *pvfs,
 
        /* register with the messaging subsystem for this message
           type */
-       messaging_register(pwait->msg_ctx,
-                          pwait,
-                          msg_type,
-                          pvfs_wait_dispatch);
+       if (msg_type != -1) {
+               messaging_register(pwait->msg_ctx,
+                                  pwait,
+                                  msg_type,
+                                  pvfs_wait_dispatch);
+       }
 
        /* tell the main smb server layer that we will be replying 
           asynchronously */