After years of saying "I really wish AOLserver had [ns_info filters] and
[ns_info procs]" I finally went ahead and implemented them.

You can see the change here:

https://github.com/dossy/aolserver/commit/5ea2ab5a5e6cfef32eb55a64d91666838d820b88

It's only in my personal fork of aolserver on github.  If people test it
and think it's suitable for general consumption, I can pull it up into
the aolserver main github repo.

-- 
Dossy Shiobara              | do...@panoptic.com | http://dossy.org/
Panoptic Computer Network   | http://panoptic.com/
  "He realized the fastest way to change is to laugh at your own
    folly -- then you can let go and quickly move on." (p. 70) 



--
AOLserver - http://www.aolserver.com/

To Remove yourself from this list, simply send an email to 
<lists...@listserv.aol.com> with the
body of "SIGNOFF AOLSERVER" in the email message. You can leave the Subject: 
field of your email blank.
diff --git a/doc/ns_info.n b/doc/ns_info.n
index 4d407c9..916c6ae 100644
--- a/doc/ns_info.n
+++ b/doc/ns_info.n
@@ -88,6 +88,10 @@ Returns the server boot time in seconds.
 .RS
 Returns the configuration file name.
 .RE
+\fBns_info filters\fR
+.RS
+Returns a list of registered filters added through ns_register_filter or 
Ns_RegisterFilter().
+.RE
 \fBns_info home\fR 
 .RS
 Returns the directory where the AOLserver was installed.
@@ -120,6 +124,10 @@ Returns the name of the AOLserver. It's usually 
"AOLserver."
 .RS
 Returns the name of the platform that the server is running on (e.g., Solaris).
 .RE
+\fBns_info procs\fR
+.RS
+Returns a list of registered procs from maps defined at startup, or added 
through ns_register_proc or Ns_RegisterRequest().
+.RE
 \fBns_info\fR server 
 .RS
 returns the name of this virtual server.
diff --git a/include/ns.h b/include/ns.h
index f9a92c3..e3e3566 100644
--- a/include/ns.h
+++ b/include/ns.h
@@ -750,6 +750,7 @@ NS_EXTERN void *Ns_RegisterFilter(char *server, char 
*method, char *URL,
 NS_EXTERN void *Ns_RegisterServerTrace(char *server, Ns_TraceProc *proc, void 
*arg);
 NS_EXTERN void *Ns_RegisterConnCleanup(char *server, Ns_TraceProc *proc, void 
*arg);
 NS_EXTERN void *Ns_RegisterCleanup(Ns_TraceProc *proc, void *arg);
+NS_EXTERN void Ns_FilterList(Tcl_DString *dsPtr, char *server);
 
 /*
  * htuu.c
@@ -964,6 +965,7 @@ NS_EXTERN void Ns_GetRequest(char *server, char *method, 
char *url,
                          int *flagsPtr);
 NS_EXTERN void Ns_UnRegisterRequest(char *server, char *method, char *url,
                                 int inherit);
+NS_EXTERN int Ns_WalkRequests(char *server, Tcl_DString *dsPtr);
 NS_EXTERN int Ns_ConnRunRequest(Ns_Conn *conn);
 NS_EXTERN int Ns_ConnRedirect(Ns_Conn *conn, char *url);
 
@@ -1294,6 +1296,7 @@ NS_EXTERN void Ns_ServerSpecificSet(char *handle, int id, 
void *data, int flags,
                                 void (*deletefunc) (void *));
 NS_EXTERN void *Ns_ServerSpecificGet(char *handle, int id);
 NS_EXTERN void *Ns_ServerSpecificDestroy(char *handle, int id, int flags);
+NS_EXTERN int Ns_TrieWalk(int id, int (*callback) (const void *, void *), void 
*userdata);
 
 /*
  * fd.c:
diff --git a/nsd/filter.c b/nsd/filter.c
index 4c9f10f..81ee545 100644
--- a/nsd/filter.c
+++ b/nsd/filter.c
@@ -107,6 +107,47 @@ Ns_RegisterFilter(char *server, char *method, char *url,
 
 /*
  *----------------------------------------------------------------------
+ * Ns_RegisterFilter --
+ *
+ *      Register a filter function to handle a method/URL combination.
+ *
+ * Results:
+ *      Returns a pointer to an opaque object that contains the filter
+ *     information.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Ns_FilterList(Tcl_DString *dsPtr, char *server)
+{
+    NsServer *servPtr = NsGetServer(server);
+    Filter *fPtr;
+
+    if (servPtr == NULL) {
+       return;
+    }
+    fPtr = servPtr->filter.firstFilterPtr;
+    while (fPtr != NULL) {
+       char when[8];
+       
+       Tcl_DStringStartSublist(dsPtr);
+       sprintf(when, "%d", fPtr->when);
+       Tcl_DStringAppendElement(dsPtr, when);
+       Tcl_DStringAppendElement(dsPtr, fPtr->method);
+       Tcl_DStringAppendElement(dsPtr, fPtr->url);
+       Ns_GetProcInfo(dsPtr, fPtr->proc, fPtr->arg);
+       Tcl_DStringEndSublist(dsPtr);
+       fPtr = fPtr->nextPtr;
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
  * NsRunFilters --
  *
  *      Execute each registered filter function in the Filter list.
diff --git a/nsd/info.c b/nsd/info.c
index 669fb2d..efa230d 100644
--- a/nsd/info.c
+++ b/nsd/info.c
@@ -499,19 +499,19 @@ NsTclInfoObjCmd(ClientData arg, Tcl_Interp *interp, int 
objc, Tcl_Obj **objv)
     Tcl_DString ds;
     static CONST char *opts[] = {
        "address", "argv0", "boottime", "builddate", "callbacks",
-       "config", "home", "hostname", "label", "locks", "log",
-       "major", "minor", "name", "nsd", "pageroot", "patchlevel",
-       "pid", "platform", "pools", "scheduled", "server", "servers",
-       "sockcallbacks", "tag", "tcllib", "threads", "uptime",
-       "version", "winnt", NULL
+       "config", "filters", "home", "hostname", "label", "locks",
+       "log", "major", "minor", "name", "nsd", "pageroot",
+       "patchlevel", "pid", "platform", "pools", "procs",
+       "scheduled", "server", "servers", "sockcallbacks", "tag",
+       "tcllib", "threads", "uptime", "version", "winnt", NULL
     };
     enum {
        IAddressIdx, IArgv0Idx, IBoottimeIdx, IBuilddateIdx, ICallbacksIdx,
-       IConfigIdx, IHomeIdx, hostINameIdx, ILabelIdx, ILocksIdx, ILogIdx,
-       IMajorIdx, IMinorIdx, INameIdx, INsdIdx, IPageRootIdx, IPatchLevelIdx,
-       IPidIdx, IPlatformIdx, IPoolsIdx, IScheduledIdx, IServerIdx, 
IServersIdx,
-       sockICallbacksIdx, ITagIdx, ITclLibIdx, IThreadsIdx, IUptimeIdx,
-       IVersionIdx, IWinntIdx,
+       IConfigIdx, IFiltersIdx, IHomeIdx, hostINameIdx, ILabelIdx, ILocksIdx,
+       ILogIdx, IMajorIdx, IMinorIdx, INameIdx, INsdIdx, IPageRootIdx,
+               IPatchLevelIdx, IPidIdx, IPlatformIdx, IPoolsIdx, IProcsIdx,
+               IScheduledIdx, IServerIdx, IServersIdx, sockICallbacksIdx, 
ITagIdx,
+               ITclLibIdx, IThreadsIdx, IUptimeIdx, IVersionIdx, IWinntIdx,
     } _nsmayalias opt;
 
     if (objc != 2) {
@@ -573,6 +573,19 @@ NsTclInfoObjCmd(ClientData arg, Tcl_Interp *interp, int 
objc, Tcl_Obj **objv)
 #endif
        break;
 
+    case IFiltersIdx:
+       if (NsTclGetServer(itPtr, &server) != TCL_OK) {
+            return TCL_ERROR;
+        }
+       Ns_FilterList(&ds, itPtr->servPtr->server);
+       Tcl_DStringResult(interp, &ds);
+       break;
+
+    case IProcsIdx:
+       (void) Ns_WalkRequests(NULL, &ds);
+       Tcl_DStringResult(interp, &ds);
+       break;
+
     case ILogIdx:
     elog = Ns_InfoErrorLog();
        Tcl_SetResult(interp, elog == NULL ? "STDOUT" : elog, TCL_STATIC);
diff --git a/nsd/init.c b/nsd/init.c
index c09b9c5..35a7e80 100644
--- a/nsd/init.c
+++ b/nsd/init.c
@@ -106,5 +106,6 @@ Ns_LibInit(void)
        NsInitSched();
        NsInitServers();
        NsInitTcl();
+       NsInitTclRequests();
     }
 }
diff --git a/nsd/nsd.h b/nsd/nsd.h
index fc5b3c6..ca9097f 100644
--- a/nsd/nsd.h
+++ b/nsd/nsd.h
@@ -904,6 +904,7 @@ extern void NsInitSched(void);
 extern void NsInitServers(void);
 extern void NsInitTcl(void);
 extern void NsInitTclCache(void);
+extern void NsInitTclRequests(void);
 extern void NsInitUrlSpace(void);
 extern void NsInitRequests(void);
 extern char *NsFindVersion(char *request, unsigned int *majorPtr,
@@ -946,6 +947,8 @@ extern Ns_SockProc NsTclSockProc;
 extern Ns_ArgProc NsTclSockArgProc;
 extern Ns_ThreadProc NsConnThread;
 extern Ns_ArgProc NsConnArgProc;
+extern Ns_ArgProc NsProcArgProc;
+extern Ns_ArgProc NsFilterArgProc;
 
 extern void NsGetCallbacks(Tcl_DString *dsPtr);
 extern void NsGetSockCallbacks(Tcl_DString *dsPtr);
diff --git a/nsd/op.c b/nsd/op.c
index f933922..b6c2729 100644
--- a/nsd/op.c
+++ b/nsd/op.c
@@ -50,6 +50,8 @@ typedef struct {
     int                    refcnt;
     Ns_OpProc      *proc;
     Ns_Callback    *delete;
+    char           *method;
+    char           *url;
     void           *arg;
     unsigned int    flags;
 } Req;
@@ -59,6 +61,7 @@ typedef struct {
  */
 
 static void FreeReq(void *arg);
+static int  RequestWalkCallback(const void *data, void *userdata);
 
 /*
  * Static variables defined in this file.
@@ -120,6 +123,8 @@ Ns_RegisterRequest(char *server, char *method, char *url, 
Ns_OpProc *proc,
     reqPtr = ns_malloc(sizeof(Req));
     reqPtr->proc = proc;
     reqPtr->delete = delete;
+    reqPtr->method = ns_strdup(method);
+    reqPtr->url = ns_strdup(url);
     reqPtr->arg = arg;
     reqPtr->flags = flags;
     reqPtr->refcnt = 1;
@@ -199,6 +204,52 @@ Ns_UnRegisterRequest(char *server, char *method, char 
*url, int inherit)
 /*
  *----------------------------------------------------------------------
  *
+ * Ns_WalkRequests --
+ *
+ *     Walk the url space of registered procs.
+ *
+ * Results:
+ *     NS_OK, or callback return value if not NS_OK.
+ *
+ * Side effects:
+ *     Depends on callback implementation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Ns_WalkRequests(char *server, Tcl_DString *dsPtr)
+{
+    int result;
+
+    Ns_MutexLock(&ulock);
+    result = Ns_TrieWalk(uid, RequestWalkCallback, dsPtr);
+    Ns_MutexUnlock(&ulock);
+
+    return result;
+}
+
+static int
+RequestWalkCallback(const void *data, void *userdata)
+{
+    Req *reqPtr = data;
+    Tcl_DString *dsPtr = userdata;
+
+    if (reqPtr != NULL) {
+       Tcl_DStringStartSublist(dsPtr);
+       Tcl_DStringAppendElement(dsPtr, reqPtr->method);
+       Tcl_DStringAppendElement(dsPtr, reqPtr->url);
+       Ns_GetProcInfo(dsPtr, reqPtr->proc, reqPtr->arg);
+       Tcl_DStringEndSublist(dsPtr);
+    }
+
+    return NS_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
  * Ns_ConnRunRequest --
  *
  *     Locate and execute the procedure for the given method and
@@ -481,6 +532,8 @@ FreeReq(void *arg)
     Req *reqPtr = (Req *) arg;
 
     if (--reqPtr->refcnt == 0) {
+       ns_free(reqPtr->method);
+       ns_free(reqPtr->url);
        if (reqPtr->delete != NULL) {
            (*reqPtr->delete) (reqPtr->arg);
         }
diff --git a/nsd/proc.c b/nsd/proc.c
index 48e0542..038ceef 100644
--- a/nsd/proc.c
+++ b/nsd/proc.c
@@ -64,6 +64,8 @@ struct proc {
        {(void *) NsTclSockProc, "ns:tclsockcallback", NsTclSockArgProc},
        {(void *) NsCachePurge, "ns:cachepurge", NsCacheArgProc},
        {(void *) NsConnThread, "ns:connthread", NsConnArgProc},
+       {(void *) NsAdpProc, "ns:adp", NULL},
+       {(void *) Ns_FastPathOp, "ns:fastpath", NULL},
        {NULL, NULL, NULL}
 };
 
diff --git a/nsd/tclrequest.c b/nsd/tclrequest.c
index 82bb98b..8dec683 100644
--- a/nsd/tclrequest.c
+++ b/nsd/tclrequest.c
@@ -68,6 +68,32 @@ static int GetNumArgs(Tcl_Interp *interp, Proc *procPtr);
 /*
  *----------------------------------------------------------------------
  *
+ * NsInitTclRequests --
+ *
+ *     Register Ns_OpProcs at startup.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     ProcInfo entries registered.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+NsInitTclRequests(void)
+{
+    Ns_RegisterProcInfo(ProcRequest, "ns:proc", NsProcArgProc);
+    Ns_RegisterProcInfo(AdpRequest, "ns:adp", NULL);
+    Ns_RegisterProcInfo(ProcFilter, "ns:filter", NsProcArgProc);
+    Ns_RegisterProcInfo(Ns_FastPathOp, "ns:fastpath", NULL);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
  * Ns_TclRequest --
  *
  *     Dummy up a direct call to TclProcRequest for a connection.
@@ -708,3 +734,29 @@ FreeProc(void *arg)
     }
     ns_free(procPtr);
 }
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NsProcArgProc --
+ *
+ *     Proc info routine to copy registered proc args.
+ *
+ * Results:
+ *     None. 
+ *
+ * Side effects:
+ *     Will copy script to given dstring.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+NsProcArgProc(Tcl_DString *dsPtr, void *arg)
+{
+     Proc *procPtr = arg;
+
+     Tcl_DStringAppendElement(dsPtr, procPtr->name);
+     Tcl_DStringAppendElement(dsPtr, procPtr->args);
+}
diff --git a/nsd/urlspace.c b/nsd/urlspace.c
index c8b4aee..7298982 100644
--- a/nsd/urlspace.c
+++ b/nsd/urlspace.c
@@ -161,6 +161,8 @@ static void  TrieDestroy(Trie *triePtr);
 static int   TrieBranchTrunc(Trie *triePtr, char *seq, int id);
 static void *TrieFind(Trie *triePtr, char *seq, int id, int *depthPtr);
 static void *TrieFindExact(Trie *triePtr, char *seq, int id, int flags);
+static int   TrieWalk(Trie *triePtr, int id,
+                             int (*callback) (const void *, void *), void 
*userdata);
 static void *TrieDelete(Trie *triePtr, char *seq, int id, int flags);
 
 /*
@@ -186,6 +188,8 @@ static void JunctionBranchTrunc(Junction *juncPtr, char 
*seq, int id);
 static void *JunctionFind(Junction *juncPtr, char *seq, int id, int fast);
 static void *JunctionFindExact(Junction *juncPtr, char *seq, int id, int flags,
                               int fast);
+static int   JunctionWalk(Junction *juncPtr, int id,
+                                 int (*callback) (const void *, void *), void 
*userdata);
 static void *JunctionDelete(Junction *juncPtr, char *seq, int id, int flags);
 
 /*
@@ -496,7 +500,6 @@ Ns_ServerSpecificGet(char *handle, int id)
     return Ns_UrlSpecificGet(handle, NULL, NULL, id);
 }
 
-
 
 /*
  *----------------------------------------------------------------------
@@ -524,6 +527,35 @@ Ns_ServerSpecificDestroy(char *handle, int id, int flags)
 /*
  *----------------------------------------------------------------------
  *
+ * Ns_TrieWalk --
+ *
+ *     Walk a url space trie.
+ *
+ * Results:
+ *     NS_OK, or callback return value if not NS_OK.
+ *
+ * Side effects:
+ *     Depends on callback implementation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Ns_TrieWalk(int id, int (*callback) (const void *, void *), void *userdata)
+{
+    int         result;
+
+    Ns_MutexLock(&lock);
+    result = JunctionWalk(&urlspace, id, callback, userdata);
+    Ns_MutexUnlock(&lock);
+
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
  * NodeDestroy --
  *
  *     Free a node and its data 
@@ -1169,6 +1201,80 @@ TrieFindExact(Trie *triePtr, char *seq, int id, int 
flags)
 /*
  *----------------------------------------------------------------------
  *
+ * TrieWalk --
+ *
+ *     Walk a trie, invoking a callback on each node.
+ *
+ * Results:
+ *     NS_OK, or callback return value if not NS_OK.
+ *
+ * Side effects:
+ *     Depends on callback implementation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TrieWalk(Trie *triePtr, int id, int (*callback) (const void *, void *), void 
*userdata)
+{
+    int   i, l;
+    int   result = 0;
+
+    if (triePtr->indexnode != NULL) {
+       Node *nodePtr;
+
+       /*
+        * We've reached a trie with an indexnode, which means that our
+        * data may be here. (If node is null that means that there
+        * is data at this branch, but not with this particular ID).
+        */
+
+       nodePtr = Ns_IndexFind(triePtr->indexnode, (void *) id);
+
+        if (nodePtr != NULL) {
+            if (nodePtr->dataNoInherit != NULL) {
+               result = callback((const void *) nodePtr->dataNoInherit,
+                       userdata);
+            } else {
+               result = callback((const void *) nodePtr->dataInherit,
+                       userdata);
+            }
+        }
+
+
+       /*
+        * Callback didn't return NS_OK, so we short circuit and stop.
+        */
+
+       if (result != NS_OK) {
+           return result;
+       }
+    }
+
+    l = Ns_IndexCount(&triePtr->branches);
+
+    for (i = 0; i < l; i++) {
+       Branch *branchPtr = Ns_IndexEl(&triePtr->branches, i);
+
+       if (branchPtr != NULL) {
+           result = TrieWalk(&branchPtr->node, id, callback, userdata);
+
+           /*
+            * Callback didn't return NS_OK, so we short circuit and stop.
+            */
+
+           if (result != NS_OK) {
+               return result;
+           }
+       }
+    }
+    
+    return NS_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
  * TrieDelete --
  *
  *     Delete a url, defined by a sequence, from a trie.
@@ -1791,6 +1897,70 @@ JunctionFindExact(Junction *juncPtr, char *seq, int id, 
int flags, int fast)
 /*
  *----------------------------------------------------------------------
  *
+ * JunctionWalk --
+ *
+ *     Walk an entire junction, invoking a callback on each node.
+ *
+ * Results:
+ *     NS_OK, or callback return value if not NS_OK.
+ *
+ * Side effects:
+ *     Depends on callback implementation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+JunctionWalk(Junction *juncPtr, int id, int (*callback) (const void *, void 
*), void *userdata)
+{
+    int   i, l;
+    int   result;
+
+    /*
+     * Check filters from most restrictive to least restrictive
+     */
+    
+#ifndef __URLSPACE_OPTIMIZE__
+    l = Ns_IndexCount(&juncPtr->byuse);
+#else
+    l = Ns_IndexCount(&juncPtr->byname);
+#endif
+
+    /* 
+     * For __URLSPACE_OPTIMIZE__
+     * Basically if we use the optimize, let's reverse the order
+     * by which we search because the byname is in "almost" exact
+     * reverse lexicographical order.
+     *
+     * Loop over all the channels in the index.
+     */
+    
+#ifndef __URLSPACE_OPTIMIZE__
+    for (i = 0; i < l; i++) {
+        Channel *channelPtr = Ns_IndexEl(&juncPtr->byuse, i);
+#else
+    for (i = (l - 1); i >= 0; i--) {
+        Channel *channelPtr = Ns_IndexEl(&juncPtr->byname, i);
+#endif
+
+       result = TrieWalk(&channelPtr->trie, id, callback, userdata);
+
+       if (result != NS_OK) {
+           /*
+            * Callback didn't return NS_OK, so we short circuit and stop.
+            */
+
+           return result;
+       }
+    }
+
+    return NS_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
  * JunctionDelete --
  *
  *     Delete a node from a junction matching a sequence 


--
AOLserver - http://www.aolserver.com/

To Remove yourself from this list, simply send an email to 
<lists...@listserv.aol.com> with the
body of "SIGNOFF AOLSERVER" in the email message. You can leave the Subject: 
field of your email blank.

Reply via email to