-/*
- * Copyright (C) 1998, 1989 Transarc Corporation - All rights reserved
- *
- * (C) COPYRIGHT IBM CORPORATION 1987, 1988
- * LICENSED MATERIALS - PROPERTY OF IBM
- *
- *
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License. For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
*/
/* Copyright (C) 1994 Cazamar Systems, Inc. */
#include <afs/param.h>
#include <afs/stds.h>
+#ifndef DJGPP
#include <windows.h>
+#endif
#include <osi.h>
#include <malloc.h>
#include <stdio.h>
#include "afsd.h"
-void afsi_log();
+extern void afsi_log(char *pattern, ...);
/* This module implements the buffer package used by the local transaction
* system (cm). It is initialized by calling cm_Init, which calls buf_Init;
long buf_bufferSize = CM_BUF_SIZE;
long buf_hashSize = CM_BUF_HASHSIZE;
+#ifndef DJGPP
static
HANDLE CacheHandle;
static
SYSTEM_INFO sysInfo;
+#endif /* !DJGPP */
/* buffer reservation variables */
long buf_reservedBufs;
/* another hash table */
cm_buf_t **buf_fileHashTablepp;
+#ifdef DISKCACHE95
+/* for experimental disk caching support in Win95 client */
+cm_buf_t *buf_diskFreeListp;
+cm_buf_t *buf_diskFreeListEndp;
+cm_buf_t *buf_diskAllp;
+extern int cm_diskCacheEnabled;
+#endif /* DISKCACHE95 */
+
/* hold a reference to an already held buffer */
void buf_Hold(cm_buf_t *bp)
{
lock_ReleaseWrite(&buf_globalLock);
nAtOnce = buf_nbuffers / 10;
while (1) {
- i = SleepEx(5000, 1);
+#ifndef DJGPP
+ i = SleepEx(5000, 1);
if (i != 0) continue;
+#else
+ thrd_Sleep(5000);
+#endif /* DJGPP */
/* now go through our percentage of the buffers */
for(i=0; i<nAtOnce; i++) {
} /* whole daemon's while loop */
}
+#ifndef DJGPP
/* Create a security attribute structure suitable for use when the cache file
* is created. What we mainly want is that only the administrator should be
* able to do anything with the file. We create an ACL with only one entry,
return psa;
}
+#endif /* !DJGPP */
+#ifndef DJGPP
/* Free a security attribute structure created by CreateCacheFileSA() */
VOID FreeCacheFileSA(PSECURITY_ATTRIBUTES psa)
{
GlobalFree(psa->lpSecurityDescriptor);
GlobalFree(psa);
}
+#endif /* !DJGPP */
/* initialize the buffer package; called with no locks
* held during the initialization phase.
static osi_once_t once;
cm_buf_t *bp;
long sectorSize;
- HANDLE phandle;
+ thread_t phandle;
+#ifndef DJGPP
+ HANDLE hf, hm;
+ PSECURITY_ATTRIBUTES psa;
+#endif /* !DJGPP */
long i;
unsigned long pid;
- HANDLE hf, hm;
char *data;
- PSECURITY_ATTRIBUTES psa;
long cs;
+#ifndef DJGPP
/* Get system info; all we really want is the allocation granularity */
GetSystemInfo(&sysInfo);
+#endif /* !DJGPP */
/* Have to be able to reserve a whole chunk */
if (((buf_nbuffers - 3) * buf_bufferSize) < cm_chunkSize)
/* initialize global locks */
lock_InitializeRWLock(&buf_globalLock, "Global buffer lock");
+#ifndef DJGPP
/*
* Cache file mapping constrained by
* system allocation granularity;
afsi_log("Cache size rounded up to %d buffers",
buf_nbuffers);
}
+#endif /* !DJGPP */
/* remember this for those who want to reset it */
buf_nOrigBuffers = buf_nbuffers;
/* min value for which this works */
sectorSize = 1;
+#ifndef DJGPP
/* Reserve buffer space by mapping cache file */
psa = CreateCacheFileSA();
hf = CreateFile(cm_CachePath,
return CM_ERROR_INVAL;
}
CloseHandle(hm);
+#else
+ /* djgpp doesn't support memory mapped files */
+ data = malloc(buf_nbuffers * buf_bufferSize);
+#endif /* !DJGPP */
/* create buffer headers and put in free list */
bp = malloc(buf_nbuffers * sizeof(cm_buf_t));
osi_EndOnce(&once);
/* and create the incr-syncer */
- phandle = CreateThread((SECURITY_ATTRIBUTES *) 0, 0,
- (LPTHREAD_START_ROUTINE) buf_IncrSyncer, 0, 0, &pid);
+ phandle = thrd_Create(0, 0,
+ (ThreadFunc) buf_IncrSyncer, 0, 0, &pid,
+ "buf_IncrSyncer");
+
osi_assertx(phandle != NULL, "buf: can't create incremental sync proc");
+#ifndef DJGPP
CloseHandle(phandle);
+#endif /* !DJGPP */
}
return 0;
cm_buf_t *bp;
int i;
char *data;
+#ifndef DJGPP
HANDLE hm;
long cs;
+ afsi_log("%d buffers being added to the existing cache of size %d",
+ nbuffers, buf_nbuffers);
+
/*
* Cache file mapping constrained by
* system allocation granularity;
return CM_ERROR_INVAL;
}
CloseHandle(hm);
+#else
+ data = malloc(buf_nbuffers * buf_bufferSize);
+#endif /* DJGPP */
/* Create buffer headers and put in free list */
bp = malloc(nbuffers * sizeof(*bp));
if (!(bp->flags & (CM_BUF_READING | CM_BUF_WRITING)))
break;
- /* otherwise I/O is happening, but some other thread is waiting for
- * the I/O already. Wait for that guy to figure out what happened,
- * and then check again.
- */
- bp->flags |= CM_BUF_WAITING;
- osi_SleepM((long) bp, &bp->mx);
- lock_ObtainMutex(&bp->mx);
+ /* otherwise I/O is happening, but some other thread is waiting for
+ * the I/O already. Wait for that guy to figure out what happened,
+ * and then check again.
+ */
+ if ( bp->flags & CM_BUF_WAITING )
+ osi_Log1(buf_logp, "buf_WaitIO CM_BUF_WAITING already set for 0x%x", bp);
+
+ bp->flags |= CM_BUF_WAITING;
+ osi_SleepM((long) bp, &bp->mx);
+ lock_ObtainMutex(&bp->mx);
osi_Log1(buf_logp, "buf_WaitIO conflict wait done for 0x%x", bp);
- }
+ }
- /* if we get here, the IO is done, but we may have to wakeup people waiting for
- * the I/O to complete. Do so.
- */
- if (bp->flags & CM_BUF_WAITING) {
+ /* if we get here, the IO is done, but we may have to wakeup people waiting for
+ * the I/O to complete. Do so.
+ */
+ if (bp->flags & CM_BUF_WAITING) {
bp->flags &= ~CM_BUF_WAITING;
- osi_Wakeup((long) bp);
- }
- osi_Log1(buf_logp, "WaitIO finished wait for bp 0x%x", (long) bp);
+ osi_Wakeup((long) bp);
+ }
+ osi_Log1(buf_logp, "WaitIO finished wait for bp 0x%x", (long) bp);
}
/* code to drop reference count while holding buf_globalLock */
lock_ObtainMutex(&bp->mx);
if (code) break;
+
+#ifdef DISKCACHE95
+ /* Disk cache support */
+ /* write buffer to disk cache (synchronous for now) */
+ diskcache_Update(bp->dcp, bp->datap, buf_bufferSize, bp->dataVersion);
+#endif /* DISKCACHE95 */
};
/* do logging after call to GetLastError, or else */
osi_hyper_t pageOffset;
unsigned long tcount;
int created;
+#ifdef DISKCACHE95
+ cm_diskcache_t *dcp;
+#endif /* DISKCACHE95 */
created = 0;
pageOffset.HighPart = offsetp->HighPart;
/* lock it and break out */
lock_ObtainMutex(&bp->mx);
break;
+
+#ifdef DISKCACHE95
+ /* touch disk chunk to update LRU info */
+ diskcache_Touch(bp->dcp);
+#endif /* DISKCACHE95 */
}
/* otherwise, we have to create a page */
osi_assert(!(bp->flags & (CM_BUF_READING | CM_BUF_WRITING)));
/* setup offset, event */
+#ifndef DJGPP /* doesn't seem to be used */
bp->over.Offset = bp->offset.LowPart;
bp->over.OffsetHigh = bp->offset.HighPart;
+#endif /* !DJGPP */
/* start the I/O; may drop lock */
bp->flags |= CM_BUF_READING;
code = (*cm_buf_opsp->Readp)(bp, buf_bufferSize, &tcount, NULL);
+
+#ifdef DISKCACHE95
+ code = diskcache_Get(&bp->fid, &bp->offset, bp->datap, buf_bufferSize, &bp->dataVersion, &tcount, &dcp);
+ bp->dcp = dcp; /* pointer to disk cache struct. */
+#endif /* DISKCACHE95 */
+
if (code != 0) {
/* failure or queued */
+#ifndef DJGPP /* cm_bufRead always returns 0 */
if (code != ERROR_IO_PENDING) {
+#endif
bp->error = code;
bp->flags |= CM_BUF_ERROR;
bp->flags &= ~CM_BUF_READING;
lock_ReleaseMutex(&bp->mx);
buf_Release(bp);
return code;
+#ifndef DJGPP
}
+#endif
} else {
/* otherwise, I/O completed instantly and we're done, except
* for padding the xfr out with 0s and checking for EOF
{
long code;
cm_buf_t *bp; /* buffer we're hacking on */
- cm_buf_t *nbp; /* next one */
+ cm_buf_t *nbp; /* next one */
long i;
i = BUF_FILEHASH(&scp->fid);
code = 0;
lock_ObtainWrite(&buf_globalLock);
- bp = buf_fileHashTablepp[i];
- if (bp) bp->refCount++;
- lock_ReleaseWrite(&buf_globalLock);
+ bp = buf_fileHashTablepp[i];
+ if (bp) bp->refCount++;
+ lock_ReleaseWrite(&buf_globalLock);
for(; bp; bp = nbp) {
/* clean buffer synchronously */
if (cm_FidCmp(&bp->fid, &scp->fid) == 0) {
if (userp) {
+ cm_HoldUser(userp);
lock_ObtainMutex(&bp->mx);
- if (bp->userp) cm_ReleaseUser(bp->userp);
- bp->userp = userp;
+ if (bp->userp)
+ cm_ReleaseUser(bp->userp);
+ bp->userp = userp;
lock_ReleaseMutex(&bp->mx);
- cm_HoldUser(userp);
- }
+ }
buf_CleanAsync(bp, reqp);
- buf_CleanWait(bp);
- lock_ObtainMutex(&bp->mx);
+ buf_CleanWait(bp);
+ lock_ObtainMutex(&bp->mx);
if (bp->flags & CM_BUF_ERROR) {
if (code == 0 || code == -1) code = bp->error;
- if (code == 0) code = -1;
- }
- lock_ReleaseMutex(&bp->mx);
+ if (code == 0) code = -1;
+ }
+ lock_ReleaseMutex(&bp->mx);
}
lock_ObtainWrite(&buf_globalLock);
buf_LockedRelease(bp);
- nbp = bp->fileHashp;
- if (nbp) nbp->refCount++;
+ nbp = bp->fileHashp;
+ if (nbp) nbp->refCount++;
lock_ReleaseWrite(&buf_globalLock);
} /* for loop over a bunch of buffers */
- /* done */
+ /* done */
return code;
}
+
+/* dump the contents of the buf_hashTablepp. */
+int cm_DumpBufHashTable(FILE *outputFile, char *cookie)
+{
+ int zilch;
+ cm_buf_t *bp;
+ char output[1024];
+ int i;
+
+ if (buf_hashTablepp == NULL)
+ return -1;
+
+ lock_ObtainRead(&buf_globalLock);
+
+ sprintf(output, "%s - dumping buf_HashTable - buf_hashSize=%d\n", cookie, buf_hashSize);
+ WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+
+ for (i = 0; i < buf_hashSize; i++)
+ {
+ for(bp = buf_hashTablepp[i]; bp; bp=bp->hashp)
+ {
+ if (bp->refCount)
+ {
+ sprintf(output, "%s bp=0x%08X, hash=%d, fid (cell=%d, volume=%d,"
+ "vnode=%d, unique=%d), size=%d refCount=%d\n",
+ cookie, (void *)bp, i, bp->fid.cell, bp->fid.volume,
+ bp->fid.vnode, bp->fid.unique, bp->size, bp->refCount);
+ WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+ }
+ }
+ }
+
+ sprintf(output, "%s - Done dumping buf_HashTable.\n", cookie);
+ WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+
+ lock_ReleaseRead(&buf_globalLock);
+ return 0;
+}
+