windows-dnlc-20080229
[openafs.git] / src / WINNT / afsd / cm_dnlc.c
index 47bbd75..91a474c 100644 (file)
 #include <afs/param.h>
 #include <afs/stds.h>
 
-#ifndef DJGPP
 #include <windows.h>
 #include <winsock2.h>
-#endif /* !DJGPP */
 #include <string.h>
 #include <stdlib.h>
 #include <osi.h>
 #include "afsd.h"
+#include <WINNT/afsreg.h>
 
 osi_rwlock_t cm_dnlcLock;
 
@@ -38,21 +37,6 @@ static int cm_debugDnlc = 0; /* debug dnlc */
  *     1.  If nameHash[i] is NULL, list is empty
  *     2.  A single element in a hash bucket has itself as prev and next.
  */
-#ifndef DJGPP
-#define dnlcNotify(x,debug){                    \
-                        HANDLE  hh;             \
-                        char *ptbuf[1];         \
-                        ptbuf[0] = x;           \
-                       if ( debug ) {          \
-                            hh = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);   \
-                            ReportEvent(hh,EVENTLOG_ERROR_TYPE,0,__LINE__,  \
-                               NULL, 1, 0, ptbuf, NULL);                   \
-                            DeregisterEventSource(hh);                 \
-                       }                                               \
-                     }  
-#else
-#define dnlcNotify(x,debug)
-#endif /* !DJGPP */
 
 /* Must be called with cm_dnlcLock write locked */
 static cm_nc_t * 
@@ -80,7 +64,6 @@ GetMeAnEntry()
     tnc = cm_data.nameHash[nameptr];
     if (!tnc)   
     {
-       dnlcNotify("null tnc in GetMeAnEntry",1);
        osi_Log0(afsd_logp,"null tnc in GetMeAnEntry");
        return 0;
     }
@@ -99,8 +82,7 @@ GetMeAnEntry()
 }
 
 static void 
-InsertEntry(tnc)
-    cm_nc_t *tnc;
+InsertEntry(cm_nc_t *tnc)
 {
     unsigned int key; 
     key = tnc->key & (NHSIZE -1);
@@ -130,10 +112,14 @@ cm_dnlcEnter ( cm_scache_t *adp,
     unsigned int key, skey, new=0;
     char *ts = aname;
     int safety;
+    int writeLocked = 0;
 
     if (!cm_useDnlc)
        return ;
-  
+
+    if (!strcmp(aname,".") || !strcmp(aname,".."))
+       return ;
+
     if ( cm_debugDnlc ) 
        osi_Log3(afsd_logp,"cm_dnlcEnter dir %x name %s scache %x", 
            adp, osi_LogSaveString(afsd_logp,aname), avc);
@@ -143,9 +129,9 @@ cm_dnlcEnter ( cm_scache_t *adp,
        return ;
     skey = key & (NHSIZE -1);
 
-    lock_ObtainWrite(&cm_dnlcLock);
-    dnlcstats.enters++;
-  
+    InterlockedIncrement(&dnlcstats.enters);
+    lock_ObtainRead(&cm_dnlcLock);
+  retry:
     for (tnc = cm_data.nameHash[skey], safety=0; tnc; tnc = tnc->next, safety++ )
        if ((tnc->dirp == adp) && (!strcmp(tnc->name, aname)))
            break;                              /* preexisting entry */
@@ -156,10 +142,12 @@ cm_dnlcEnter ( cm_scache_t *adp,
        }
        else if (safety > NCSIZE) 
        {
-           dnlcstats.cycles++;
-           lock_ReleaseWrite(&cm_dnlcLock);
+           InterlockedIncrement(&dnlcstats.cycles);
+            if (writeLocked)
+                lock_ReleaseWrite(&cm_dnlcLock);
+            else
+                lock_ReleaseRead(&cm_dnlcLock);
 
-           dnlcNotify("DNLC cycle",1);
            if ( cm_debugDnlc )
                 osi_Log0(afsd_logp, "DNLC cycle");
            cm_dnlcPurge();
@@ -168,6 +156,11 @@ cm_dnlcEnter ( cm_scache_t *adp,
        
     if ( !tnc )
     {
+        if ( !writeLocked ) {
+            lock_ConvertRToW(&cm_dnlcLock);
+            writeLocked = 1;
+            goto retry;
+        }
        new = 1;        /* entry does not exist, we are creating a new entry*/
        tnc = GetMeAnEntry();
     }
@@ -182,7 +175,10 @@ cm_dnlcEnter ( cm_scache_t *adp,
                InsertEntry(tnc);
 
     }
-    lock_ReleaseWrite(&cm_dnlcLock);
+    if (writeLocked)
+        lock_ReleaseWrite(&cm_dnlcLock);
+    else
+        lock_ReleaseRead(&cm_dnlcLock);
 
     if ( !tnc)
        cm_dnlcPurge();
@@ -202,23 +198,28 @@ cm_dnlcLookup (cm_scache_t *adp, cm_lookupSearch_t* sp)
     int safety, match;
   
     if (!cm_useDnlc)
-       return 0;
+       return NULL;
+
     if ( cm_debugDnlc ) 
        osi_Log2(afsd_logp, "cm_dnlcLookup dir %x name %s", 
                adp, osi_LogSaveString(afsd_logp,aname));
 
     dnlcHash( ts, key );  /* leaves ts pointing at the NULL */
-    if (ts - aname >= CM_AFSNCNAMESIZE) 
-       return 0;
+
+    if (ts - aname >= CM_AFSNCNAMESIZE) {
+        InterlockedIncrement(&dnlcstats.lookups);
+        InterlockedIncrement(&dnlcstats.misses);
+       return NULL;
+    }
 
     skey = key & (NHSIZE -1);
 
     lock_ObtainRead(&cm_dnlcLock);
-    dnlcstats.lookups++;            /* Is a dnlcread lock sufficient? */
+    InterlockedIncrement(&dnlcstats.lookups);
 
     ts = 0;
     tnc_begin = cm_data.nameHash[skey];
-    for ( tvc = (cm_scache_t *) 0, tnc = tnc_begin, safety=0; 
+    for ( tvc = (cm_scache_t *) NULL, tnc = tnc_begin, safety=0; 
           tnc; tnc = tnc->next, safety++ ) 
     {
        if (tnc->dirp == adp) 
@@ -273,14 +274,13 @@ cm_dnlcLookup (cm_scache_t *adp, cm_lookupSearch_t* sp)
        }
        else if (tnc->next == tnc_begin || safety > NCSIZE) 
        {
-           dnlcstats.cycles++;
+           InterlockedIncrement(&dnlcstats.cycles);
            lock_ReleaseRead(&cm_dnlcLock);
 
-           dnlcNotify("DNLC cycle",1); 
            if ( cm_debugDnlc ) 
                osi_Log0(afsd_logp, "DNLC cycle"); 
            cm_dnlcPurge();
-           return(0);
+           return(NULL);
        }
     }
 
@@ -292,7 +292,7 @@ cm_dnlcLookup (cm_scache_t *adp, cm_lookupSearch_t* sp)
     }
 
     if (!tvc) 
-        dnlcstats.misses++;    /* Is a dnlcread lock sufficient? */
+        InterlockedIncrement(&dnlcstats.misses);
     else 
     {
         sp->found = 1;
@@ -312,13 +312,10 @@ cm_dnlcLookup (cm_scache_t *adp, cm_lookupSearch_t* sp)
 
 
 static int
-RemoveEntry (tnc, key)
-    cm_nc_t    *tnc;
-    unsigned int key;
+RemoveEntry (cm_nc_t *tnc, unsigned int key)
 {
     if (!tnc->prev) /* things on freelist always have null prev ptrs */
     {
-       dnlcNotify("Bogus dnlc freelist", 1);
        osi_Log0(afsd_logp,"Bogus dnlc freelist");
        return 1;   /* error */
     }
@@ -340,9 +337,7 @@ RemoveEntry (tnc, key)
 
 
 void 
-cm_dnlcRemove ( adp, aname)
-    cm_scache_t *adp;
-    char          *aname;
+cm_dnlcRemove (cm_scache_t *adp, char *aname)
 {
     unsigned int key, skey, error=0;
     int found= 0, safety;
@@ -362,7 +357,7 @@ cm_dnlcRemove ( adp, aname)
 
     skey = key & (NHSIZE -1);
     lock_ObtainWrite(&cm_dnlcLock);
-    dnlcstats.removes++;
+    InterlockedIncrement(&dnlcstats.removes);
 
     for (tnc = cm_data.nameHash[skey], safety=0; tnc; safety++) 
     {
@@ -386,10 +381,9 @@ cm_dnlcRemove ( adp, aname)
            tnc = tnc->next;
        if ( safety > NCSIZE )
        {
-           dnlcstats.cycles++;
+           InterlockedIncrement(&dnlcstats.cycles);
            lock_ReleaseWrite(&cm_dnlcLock);
 
-           dnlcNotify("DNLC cycle",1); 
            if ( cm_debugDnlc ) 
                osi_Log0(afsd_logp, "DNLC cycle"); 
            cm_dnlcPurge();
@@ -407,8 +401,7 @@ cm_dnlcRemove ( adp, aname)
 
 /* remove anything pertaining to this directory */
 void 
-cm_dnlcPurgedp (adp)
-  cm_scache_t *adp;
+cm_dnlcPurgedp (cm_scache_t *adp)
 {
     int i;
     int err=0;
@@ -420,7 +413,7 @@ cm_dnlcPurgedp (adp)
        osi_Log1(afsd_logp, "cm_dnlcPurgedp dir %x", adp);
 
     lock_ObtainWrite(&cm_dnlcLock);
-    dnlcstats.purgeds++;
+    InterlockedIncrement(&dnlcstats.purgeds);
 
     for (i=0; i<NCSIZE && !err; i++) 
     {
@@ -445,8 +438,7 @@ cm_dnlcPurgedp (adp)
 
 /* remove anything pertaining to this file */
 void 
-cm_dnlcPurgevp ( avc )
-  cm_scache_t *avc;
+cm_dnlcPurgevp (cm_scache_t *avc)
 {
     int i;
     int err=0;
@@ -458,7 +450,7 @@ cm_dnlcPurgevp ( avc )
        osi_Log1(afsd_logp, "cm_dnlcPurgevp scache %x", avc);
 
     lock_ObtainWrite(&cm_dnlcLock);
-    dnlcstats.purgevs++;
+    InterlockedIncrement(&dnlcstats.purgevs);
 
     for (i=0; i<NCSIZE && !err ; i++) 
     {
@@ -493,7 +485,7 @@ void cm_dnlcPurge(void)
        osi_Log0(afsd_logp, "cm_dnlcPurge");
 
     lock_ObtainWrite(&cm_dnlcLock);
-    dnlcstats.purges++;
+    InterlockedIncrement(&dnlcstats.purges);
     
     cm_data.ncfreelist = (cm_nc_t *) 0;
     memset (cm_data.nameCache, 0, sizeof(cm_nc_t) * NCSIZE);
@@ -509,15 +501,15 @@ void cm_dnlcPurge(void)
 }
 
 /* remove everything referencing a specific volume */
+/* is this function ever called? */
 void
-cm_dnlcPurgeVol( fidp )
-  AFSFid *fidp;
+cm_dnlcPurgeVol(AFSFid *fidp)
 {
 
     if (!cm_useDnlc)
         return ;
 
-    dnlcstats.purgevols++;
+    InterlockedIncrement(&dnlcstats.purgevols);
     cm_dnlcPurge();
 }
 
@@ -651,9 +643,29 @@ void
 cm_dnlcInit(int newFile)
 {
     int i;
-
-    if (!cm_useDnlc)
-        return ;
+    HKEY parmKey;
+    DWORD dummyLen;
+    DWORD dwValue;
+    DWORD code;
+
+    code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
+                         0, KEY_QUERY_VALUE, &parmKey);
+    if (code == ERROR_SUCCESS) {
+        dummyLen = sizeof(DWORD);
+        code = RegQueryValueEx(parmKey, "UseDNLC", NULL, NULL,
+                                (BYTE *) &dwValue, &dummyLen);
+        if (code == ERROR_SUCCESS)
+            cm_useDnlc = dwValue ? 1 : 0;
+        afsi_log("CM UseDNLC = %d", cm_useDnlc);
+
+        dummyLen = sizeof(DWORD);
+        code = RegQueryValueEx(parmKey, "DebugDNLC", NULL, NULL,
+                                (BYTE *) &dwValue, &dummyLen);
+        if (code == ERROR_SUCCESS)
+            cm_debugDnlc = dwValue ? 1 : 0;
+        afsi_log("CM DebugDNLC = %d", cm_debugDnlc);
+        RegCloseKey (parmKey);
+    }
 
     if ( cm_debugDnlc )
        osi_Log0(afsd_logp,"cm_dnlcInit");