CAP/applications/aufs/afpspd.c

411 lines
7.4 KiB
C

/*
Speedup routines
Author: Dan Oscarsson (Dan@dna.lth.se)
*/
#include <sys/param.h>
#ifndef _TYPES
/* assume included by param.h */
# include <sys/types.h>
#endif
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <netat/appletalk.h>
#include <netat/compat.h>
#include "afps.h"
#ifdef STAT_CACHE
struct statobj {
char * NAME;
struct stat STAT;
int FN,RS;
time_t VAL_TIME;
};
#define VAL_OK 1
#define VAL_NO 0
#define VAL_INVALID 2
#define MAX_LEVEL 20
private struct statobj STATS[MAX_LEVEL+1];
private time_t CUR_TIME;
private struct timeval *Sched_Now = NULL; /* pointer to scheduler clock */
#define EXP_TIME 120;
private char CUR_DIR_STR[1024];
private char * CUR_DIR = NULL;
private int CUR_DIR_LEN;
private char CUR_STAT_STR[1024];
private int CUR_STAT_LEVEL = 0;
/*
* The following is used as a sentinel in a statobj to mark invalid
* entries. It is stored in the st_nlink field in the STAT substructure.
*
*/
#define BAD_LINK 0x7fff
OSStatInit()
{
register int P;
for (P = 0; P <= MAX_LEVEL; P++) {
STATS[P].NAME = NULL;
STATS[P].STAT.st_nlink = BAD_LINK;
STATS[P].FN = VAL_INVALID;
STATS[P].RS = VAL_INVALID;
}
getschedulerclock(&Sched_Now);
time(&CUR_TIME); /* since scheduler has not run yet */
}
OScd(path)
char * path;
{
if (CUR_DIR != NULL && strlen(path) == CUR_DIR_LEN-1 && strncmp(path,CUR_DIR,CUR_DIR_LEN-1) == 0)
return;
if (chdir(path) < 0)
return;
CUR_DIR = CUR_DIR_STR;
strcpy(CUR_DIR,path);
strcat(CUR_DIR,"/");
CUR_DIR_LEN = strlen(CUR_DIR);
if (DBOSI)
printf("OScd=%s\n",CUR_DIR);
}
cwd_stat(path,buf)
char * path;
struct stat *buf;
{
if (CUR_DIR != NULL && strncmp(path,CUR_DIR,CUR_DIR_LEN) == 0) {
if (DBOSI)
printf("OScwd_stat=%s\n",path+CUR_DIR_LEN);
return(stat(path+CUR_DIR_LEN,buf));
}
if (DBOSI)
printf("OScwd_stat=%s\n",path);
return(stat(path,buf));
}
cwd_open(path,flags,mode)
char * path;
int flags,mode;
{
if (CUR_DIR != NULL && strncmp(path,CUR_DIR,CUR_DIR_LEN) == 0) {
if (DBOSI)
printf("OScwd_open=%s\n",path+CUR_DIR_LEN);
return(open(path+CUR_DIR_LEN,flags,mode));
}
if (DBOSI)
printf("OScwd_open=%s\n",path);
return(open(path,flags,mode));
}
char * cwd_path(path)
char * path;
{
if (CUR_DIR != NULL && strncmp(path,CUR_DIR,CUR_DIR_LEN) == 0) {
if (DBOSI)
printf("OScwd_path=%s\n",path+CUR_DIR_LEN);
return path+CUR_DIR_LEN;
}
if (DBOSI)
printf("OScwd_path=%s\n",path);
return path;
}
private release_stats(K)
int K;
{
register int P;
if (DBOSI)
printf("release_stats=%d of %d\n",K,CUR_STAT_LEVEL);
for (P = K; P <= CUR_STAT_LEVEL; P++) {
STATS[P].STAT.st_nlink = BAD_LINK;
STATS[P].FN = VAL_INVALID;
STATS[P].RS = VAL_INVALID;
STATS[P].NAME = NULL;
}
if (K < CUR_STAT_LEVEL)
CUR_STAT_LEVEL = K;
}
private int EXPIRE_REQ;
private expire_stats()
{
register int K;
if (!EXPIRE_REQ)
return;
EXPIRE_REQ = 0;
for (K = 0; K <= CUR_STAT_LEVEL; K++) {
if (STATS[K].STAT.st_nlink == BAD_LINK)
continue;
if (STATS[K].VAL_TIME <= CUR_TIME) {
if (DBOSI)
printf("expired=%d(%s) t=%d\n",
K, STATS[K].NAME,
STATS[K].VAL_TIME - CUR_TIME);
STATS[K].STAT.st_nlink = BAD_LINK;
STATS[K].FN = VAL_INVALID;
STATS[K].RS = VAL_INVALID;
STATS[K].NAME = NULL;
}
}
}
private struct statobj * locate_statobj(path)
char * path;
{
register char *NEW, *OLD;
register char *TMP;
register int K;
char *REPLACE;
if (DBOSI)
printf("locate_statobj: path '%s'\n", path);
/* get the path and make sure it is an absolute one */
NEW = path;
if (*NEW++ != '/')
return(NULL);
/* get rid of old information */
expire_stats();
/* record what we are replacing */
REPLACE = CUR_STAT_STR;
/* loop thru each path component and check against current */
for(K=0;;) {
/* strip leading slashes */
while (*NEW == '/')
NEW++;
/* handle root */
if (K == 0) {
if (*NEW == '\0') {
if (DBOSI)
printf("locate_statobj: root\n");
STATS[0].NAME = "<root>";
return(&STATS[0]);
}
/* something more */
K++;
}
/* do we have info for this level? */
if (K > CUR_STAT_LEVEL)
break; /* nope */
/* do we have a name for this level */
if ((OLD = STATS[K].NAME) == NULL)
break; /* nope */
/* record buffer name */
REPLACE = OLD;
/* compare name */
TMP = NEW;
while (*OLD && *OLD == *TMP) {
OLD++;
TMP++;
}
/* did we end cleanly? */
if (*OLD != '\0')
break; /* nope */
/* did NEW path end? */
if (*TMP == '\0') {
/* yes */
if (DBOSI)
printf("locate_statobj: found %d: '%s'\n",
K,STATS[K].NAME);
return(&STATS[K]);
}
/* did NEW path end on slash? */
if (*TMP != '/')
break; /* nope */
/* about to loop, see if too many levels */
if (++K >= MAX_LEVEL) {
if (DBOSI)
printf("locate_statobj: too many '%s'\n",
path);
return(NULL);
}
/* loop again */
REPLACE = ++OLD;
NEW = TMP;
}
/* add components */
release_stats(K);
OLD = REPLACE;
for (;;) {
/* strip leading slashes */
while (*NEW == '/')
NEW++;
/* make sure we have something */
if (*NEW == '\0') {
/* must be trailing slash */
if (DBOSI)
printf("locate_statobj: trailing / in '%s'\n",
path);
return(NULL);
}
/* record and copy component */
STATS[K].NAME = OLD;
while (*NEW && *NEW != '/')
*OLD++ = *NEW++;
*OLD++ = '\0';
/* record new stat level */
CUR_STAT_LEVEL = K;
/* are we done? */
if (*NEW == '\0') {
/* yep */
if (DBOSI)
printf("locate_statobj: return %d: '%s'\n",
K,STATS[K].NAME);
return(&STATS[K]);
}
/* about to loop, see if too many levels */
if (++K >= MAX_LEVEL) {
if (DBOSI)
printf("locate_statobj: too many (add) '%s'\n",
path);
return(NULL);
}
/* loop again */
}
/* NEVER REACHED */
}
OSstat(path,buf)
char * path;
struct stat *buf;
{
struct statobj * CE;
if (DBOSI)
printf("OSstat=%s\n",path);
CE = locate_statobj(path);
if (CE != NULL) {
if (CE->STAT.st_nlink != BAD_LINK) {
if (DBOSI)
printf("OSstat=cache path\n");
bcopy(&CE->STAT,buf,sizeof(struct stat));
return 0;
}
if (cwd_stat(path,buf) == 0) {
if (DBOSI)
printf("OSstat=caching path\n");
bcopy(buf,&CE->STAT,sizeof(struct stat));
CE->VAL_TIME = CUR_TIME+EXP_TIME;
return 0;
}
if (DBOSI)
printf("OSstat=no cache\n");
return -1;
}
if (DBOSI)
printf("OSstat=not cached\n");
return cwd_stat(path,buf);
}
OSfinderinfo(path)
char * path;
{
char pp[MAXPATHLEN];
struct stat S;
struct statobj * CE;
CE = locate_statobj(path);
if (CE != NULL) {
if (CE->FN != VAL_INVALID)
return CE->FN;
strcpy(pp,path);
toFinderInfo(pp,"");
if (cwd_stat(pp,&S) < 0 || !S_ISDIR(S.st_mode))
CE->FN = VAL_NO;
else
CE->FN = VAL_OK;
return CE->FN;
}
strcpy(pp,path);
toFinderInfo(pp,"");
if (cwd_stat(pp,&S) < 0 || !S_ISDIR(S.st_mode))
return 0;
else
return 1;
}
OSresourcedir(path)
char * path;
{
char pp[MAXPATHLEN];
struct stat S;
struct statobj * CE;
CE = locate_statobj(path);
if (CE != NULL) {
if (CE->RS != VAL_INVALID)
return CE->RS;
strcpy(pp,path);
toResFork(pp,"");
if (cwd_stat(pp,&S) < 0 || !S_ISDIR(S.st_mode))
CE->RS = VAL_NO;
else
CE->RS = VAL_OK;
return CE->RS;
}
strcpy(pp,path);
toResFork(pp,"");
if (cwd_stat(pp,&S) < 0 || !S_ISDIR(S.st_mode))
return 0;
else
return 1;
}
OSflush_stat()
{
CUR_TIME = Sched_Now->tv_sec;
if (DBOSI)
printf("OSflush_stat\n");
release_stats(0);
}
OSstat_cache_update()
{
CUR_TIME = Sched_Now->tv_sec;
EXPIRE_REQ = 1;
}
#endif STAT_CACHE