From 127967334fbf3851debacbc0f2574461b542cbad Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 7 Apr 2006 10:36:54 +0000 Subject: r14956: change the notify search to be much more efficient by using a per-depth bisection search. This makes the notify_trigger() call log(N) which makes us scale well for large numbers of outstanding notifies (This used to be commit 16fd00925fdbf77e7a403ad501bf6ea429404c76) --- source4/torture/raw/notify.c | 115 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) (limited to 'source4/torture/raw/notify.c') diff --git a/source4/torture/raw/notify.c b/source4/torture/raw/notify.c index 0e79a7ce07..8d024f983c 100644 --- a/source4/torture/raw/notify.c +++ b/source4/torture/raw/notify.c @@ -895,6 +895,120 @@ done: return ret; } + +/* + test multiple change notifies at different depths and with/without recursion +*/ +static BOOL test_notify_tree(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) +{ + BOOL ret = True; + struct smb_notify notify; + union smb_open io; + struct smbcli_request *req; + struct { + const char *path; + BOOL recursive; + uint32_t filter; + int expected; + int fnum; + } dirs[] = { + {BASEDIR "\\abc", True, FILE_NOTIFY_CHANGE_NAME, 30 }, + {BASEDIR "\\zqy", True, FILE_NOTIFY_CHANGE_NAME, 8 }, + {BASEDIR "\\atsy", True, FILE_NOTIFY_CHANGE_NAME, 4 }, + {BASEDIR "\\abc\\foo", True, FILE_NOTIFY_CHANGE_NAME, 2 }, + {BASEDIR "\\abc\\blah", True, FILE_NOTIFY_CHANGE_NAME, 13 }, + {BASEDIR "\\abc\\blah", False, FILE_NOTIFY_CHANGE_NAME, 7 }, + {BASEDIR "\\abc\\blah\\a", True, FILE_NOTIFY_CHANGE_NAME, 2 }, + {BASEDIR "\\abc\\blah\\b", True, FILE_NOTIFY_CHANGE_NAME, 2 }, + {BASEDIR "\\abc\\blah\\c", True, FILE_NOTIFY_CHANGE_NAME, 2 }, + {BASEDIR "\\abc\\fooblah", True, FILE_NOTIFY_CHANGE_NAME, 2 }, + {BASEDIR "\\zqy\\xx", True, FILE_NOTIFY_CHANGE_NAME, 2 }, + {BASEDIR "\\zqy\\yyy", True, FILE_NOTIFY_CHANGE_NAME, 2 }, + {BASEDIR "\\zqy\\..", True, FILE_NOTIFY_CHANGE_NAME, 40 }, + {BASEDIR, True, FILE_NOTIFY_CHANGE_NAME, 40 }, + {BASEDIR, False,FILE_NOTIFY_CHANGE_NAME, 6 }, + {BASEDIR "\\atsy", False,FILE_NOTIFY_CHANGE_NAME, 4 }, + {BASEDIR "\\abc", True, FILE_NOTIFY_CHANGE_NAME, 24 }, + {BASEDIR "\\abc", False,FILE_NOTIFY_CHANGE_FILE_NAME, 0 }, + {BASEDIR "\\abc", True, FILE_NOTIFY_CHANGE_FILE_NAME, 0 }, + {BASEDIR "\\abc", True, FILE_NOTIFY_CHANGE_NAME, 24 }, + }; + int i; + NTSTATUS status; + + printf("TESTING CHANGE NOTIFY FOR DIFFERENT DEPTHS\n"); + + io.generic.level = RAW_OPEN_NTCREATEX; + io.ntcreatex.in.root_fid = 0; + io.ntcreatex.in.flags = 0; + io.ntcreatex.in.access_mask = SEC_FILE_ALL; + io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; + io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; + io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE; + io.ntcreatex.in.alloc_size = 0; + io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF; + io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; + io.ntcreatex.in.security_flags = 0; + + notify.in.buffer_size = 20000; + + /* + setup the directory tree, and the notify buffer on each directory + */ + for (i=0;itree, mem_ctx, &io); + CHECK_STATUS(status, NT_STATUS_OK); + dirs[i].fnum = io.ntcreatex.out.file.fnum; + + notify.in.completion_filter = dirs[i].filter; + notify.in.file.fnum = dirs[i].fnum; + notify.in.recursive = dirs[i].recursive; + req = smb_raw_changenotify_send(cli->tree, ¬ify); + smb_raw_ntcancel(req); + status = smb_raw_changenotify_recv(req, mem_ctx, ¬ify); + CHECK_STATUS(status, NT_STATUS_CANCELLED); + } + + /* trigger 2 events in each dir */ + for (i=0;itree, path); + smbcli_rmdir(cli->tree, path); + talloc_free(path); + } + + /* give a bit of time for all the events to propogate */ + sleep(2); + + /* count events that have happened in each dir */ + for (i=0;itree, ¬ify); + smb_raw_ntcancel(req); + notify.out.num_changes = 0; + status = smb_raw_changenotify_recv(req, mem_ctx, ¬ify); + if (notify.out.num_changes != dirs[i].expected) { + printf("ERROR: i=%d expected %d got %d for '%s'\n", + i, dirs[i].expected, notify.out.num_changes, + dirs[i].path); + ret = False; + } + } + + /* + run from the back, closing and deleting + */ + for (i=ARRAY_SIZE(dirs)-1;i>=0;i--) { + smbcli_close(cli->tree, dirs[i].fnum); + smbcli_rmdir(cli->tree, dirs[i].path); + } + +done: + smb_raw_exit(cli->session); + return ret; +} + /* basic testing of change notify */ @@ -922,6 +1036,7 @@ BOOL torture_raw_notify(struct torture_context *torture) ret &= test_notify_exit(mem_ctx); ret &= test_notify_ulogoff(mem_ctx); ret &= test_notify_double(cli, mem_ctx); + ret &= test_notify_tree(cli, mem_ctx); smb_raw_exit(cli->session); smbcli_deltree(cli->tree, BASEDIR); -- cgit