version 1.29, 2000/11/24 14:36:33 |
version 1.30, 2001/03/02 16:57:26 |
|
|
|
|
LIST dirSearchPath; /* main search path */ |
LIST dirSearchPath; /* main search path */ |
|
|
static struct hash openDirectories; /* cache all open directories */ |
static struct ohash openDirectories; /* cache all open directories */ |
|
|
/* |
/* |
* Variables for gathering statistics on the efficiency of the hashing |
* Variables for gathering statistics on the efficiency of the hashing |
|
|
char name[1]; /* ...for that file. */ |
char name[1]; /* ...for that file. */ |
}; |
}; |
|
|
static struct hash mtimes; /* Results of doing a last-resort stat in |
static struct ohash mtimes; /* Results of doing a last-resort stat in |
* Dir_FindFile -- if we have to go to the |
* Dir_FindFile -- if we have to go to the |
* system to find the file, we might as well |
* system to find the file, we might as well |
* have its mtime on record. XXX: If this is done |
* have its mtime on record. XXX: If this is done |
|
|
* - to collate files's last modification times (global mtimes) |
* - to collate files's last modification times (global mtimes) |
* - to collate file names (in each Path structure) |
* - to collate file names (in each Path structure) |
* - to collate known directories (global openDirectories). */ |
* - to collate known directories (global openDirectories). */ |
static struct hash_info stamp_info = { offsetof(struct file_stamp, name), |
static struct ohash_info stamp_info = { offsetof(struct file_stamp, name), |
NULL, hash_alloc, hash_free, element_alloc }; |
NULL, hash_alloc, hash_free, element_alloc }; |
|
|
static struct hash_info file_info = { 0, |
static struct ohash_info file_info = { 0, |
NULL, hash_alloc, hash_free, element_alloc }; |
NULL, hash_alloc, hash_free, element_alloc }; |
|
|
static struct hash_info dir_info = { offsetof(Path, name), |
static struct ohash_info dir_info = { offsetof(Path, name), |
NULL, hash_alloc, hash_free, element_alloc }; |
NULL, hash_alloc, hash_free, element_alloc }; |
|
|
static void record_stamp __P((const char *, TIMESTAMP)); |
static void record_stamp __P((const char *, TIMESTAMP)); |
static void add_file __P((Path *, const char *)); |
static void add_file __P((Path *, const char *)); |
static char *find_file_hash __P((Path *, const char *, const char *, u_int32_t)); |
static char *find_file_hash __P((Path *, const char *, const char *, u_int32_t)); |
static struct file_stamp *find_stamp __P((const char *)); |
static struct file_stamp *find_stamp __P((const char *)); |
static void free_hash __P((struct hash *)); |
static void free_hash __P((struct ohash *)); |
|
|
static Path *DirReaddir __P((const char *, const char *)); |
static Path *DirReaddir __P((const char *, const char *)); |
static void DirMatchFiles __P((char *, Path *, Lst)); |
static void DirMatchFiles __P((char *, Path *, Lst)); |
|
|
const char *end = NULL; |
const char *end = NULL; |
struct file_stamp *n; |
struct file_stamp *n; |
|
|
slot = hash_qlookupi(&mtimes, file, &end); |
slot = ohash_qlookupi(&mtimes, file, &end); |
n = hash_find(&mtimes, slot); |
n = ohash_find(&mtimes, slot); |
if (n) |
if (n) |
n->mtime = t; |
n->mtime = t; |
else { |
else { |
n = hash_create_entry(&stamp_info, file, &end); |
n = ohash_create_entry(&stamp_info, file, &end); |
n->mtime = t; |
n->mtime = t; |
hash_insert(&mtimes, slot, n); |
ohash_insert(&mtimes, slot, n); |
} |
} |
} |
} |
|
|
|
|
find_stamp(file) |
find_stamp(file) |
const char *file; |
const char *file; |
{ |
{ |
return hash_find(&mtimes, hash_qlookup(&mtimes, file)); |
return ohash_find(&mtimes, ohash_qlookup(&mtimes, file)); |
} |
} |
|
|
static void |
static void |
|
|
unsigned slot; |
unsigned slot; |
const char *end = NULL; |
const char *end = NULL; |
char *n; |
char *n; |
struct hash *h = &p->files; |
struct ohash *h = &p->files; |
|
|
slot = hash_qlookupi(h, file, &end); |
slot = ohash_qlookupi(h, file, &end); |
n = hash_find(h, slot); |
n = ohash_find(h, slot); |
if (n == NULL) { |
if (n == NULL) { |
n = hash_create_entry(&file_info, file, &end); |
n = ohash_create_entry(&file_info, file, &end); |
hash_insert(h, slot, n); |
ohash_insert(h, slot, n); |
} |
} |
} |
} |
|
|
|
|
const char *e; |
const char *e; |
u_int32_t hv; |
u_int32_t hv; |
{ |
{ |
struct hash *h = &p->files; |
struct ohash *h = &p->files; |
|
|
return hash_find(h, hash_lookup_interval(h, file, e, hv)); |
return ohash_find(h, ohash_lookup_interval(h, file, e, hv)); |
} |
} |
|
|
static void |
static void |
free_hash(h) |
free_hash(h) |
struct hash *h; |
struct ohash *h; |
{ |
{ |
void *e; |
void *e; |
unsigned i; |
unsigned i; |
|
|
for (e = hash_first(h, &i); e != NULL; e = hash_next(h, &i)) |
for (e = ohash_first(h, &i); e != NULL; e = ohash_next(h, &i)) |
free(e); |
free(e); |
hash_delete(h); |
ohash_delete(h); |
} |
} |
|
|
/*- |
/*- |
|
|
Dir_Init() |
Dir_Init() |
{ |
{ |
Lst_Init(&dirSearchPath); |
Lst_Init(&dirSearchPath); |
hash_init(&openDirectories, 4, &dir_info); |
ohash_init(&openDirectories, 4, &dir_info); |
hash_init(&mtimes, 4, &stamp_info); |
ohash_init(&mtimes, 4, &stamp_info); |
|
|
dot = DirReaddir(".", NULL); |
dot = DirReaddir(".", NULL); |
|
|
|
|
dot->refCount--; |
dot->refCount--; |
Dir_Destroy(dot); |
Dir_Destroy(dot); |
Lst_Destroy(&dirSearchPath, Dir_Destroy); |
Lst_Destroy(&dirSearchPath, Dir_Destroy); |
for (p = hash_first(&openDirectories, &i); p != NULL; |
for (p = ohash_first(&openDirectories, &i); p != NULL; |
p = hash_next(&openDirectories, &i)) |
p = ohash_next(&openDirectories, &i)) |
Dir_Destroy(p); |
Dir_Destroy(p); |
hash_delete(&openDirectories); |
ohash_delete(&openDirectories); |
free_hash(&mtimes); |
free_hash(&mtimes); |
#endif |
#endif |
} |
} |
|
|
|
|
isDot = (*p->name == '.' && p->name[1] == '\0'); |
isDot = (*p->name == '.' && p->name[1] == '\0'); |
|
|
for (entry = hash_first(&p->files, &search); entry != NULL; |
for (entry = ohash_first(&p->files, &search); entry != NULL; |
entry = hash_next(&p->files, &search)) { |
entry = ohash_next(&p->files, &search)) { |
/* See if the file matches the given pattern. Note we follow the UNIX |
/* See if the file matches the given pattern. Note we follow the UNIX |
* convention that dot files will only be found if the pattern |
* convention that dot files will only be found if the pattern |
* begins with a dot (note also that as a side effect of the hashing |
* begins with a dot (note also that as a side effect of the hashing |
|
|
} |
} |
|
|
e = NULL; |
e = NULL; |
hv = hash_interval(cp, &e); |
hv = ohash_interval(cp, &e); |
|
|
if (DEBUG(DIR)) { |
if (DEBUG(DIR)) { |
printf("Searching for %s...", name); |
printf("Searching for %s...", name); |
|
|
} else |
} else |
fullName = gn->path; |
fullName = gn->path; |
|
|
slot = hash_qlookup(&mtimes, fullName); |
slot = ohash_qlookup(&mtimes, fullName); |
entry = hash_find(&mtimes, slot); |
entry = ohash_find(&mtimes, slot); |
if (entry != NULL) { |
if (entry != NULL) { |
/* Only do this once -- the second time folks are checking to |
/* Only do this once -- the second time folks are checking to |
* see if the file was actually updated, so we need to actually go |
* see if the file was actually updated, so we need to actually go |
|
|
Targ_FmtTime(entry->mtime), fullName); |
Targ_FmtTime(entry->mtime), fullName); |
mtime = entry->mtime; |
mtime = entry->mtime; |
free(entry); |
free(entry); |
hash_remove(&mtimes, slot); |
ohash_remove(&mtimes, slot); |
} else if (stat(fullName, &stb) == 0) |
} else if (stat(fullName, &stb) == 0) |
grab_stat(stb, mtime); |
grab_stat(stb, mtime); |
else { |
else { |
|
|
struct dirent *dp; /* entry in directory */ |
struct dirent *dp; /* entry in directory */ |
unsigned int slot; |
unsigned int slot; |
|
|
slot = hash_qlookupi(&openDirectories, name, &end); |
slot = ohash_qlookupi(&openDirectories, name, &end); |
p = hash_find(&openDirectories, slot); |
p = ohash_find(&openDirectories, slot); |
|
|
if (p != NULL) |
if (p != NULL) |
return p; |
return p; |
|
|
p = hash_create_entry(&dir_info, name, &end); |
p = ohash_create_entry(&dir_info, name, &end); |
p->hits = 0; |
p->hits = 0; |
p->refCount = 0; |
p->refCount = 0; |
hash_init(&p->files, 4, &file_info); |
ohash_init(&p->files, 4, &file_info); |
|
|
if (DEBUG(DIR)) { |
if (DEBUG(DIR)) { |
printf("Caching %s...", p->name); |
printf("Caching %s...", p->name); |
|
|
if (DEBUG(DIR)) |
if (DEBUG(DIR)) |
printf("done\n"); |
printf("done\n"); |
|
|
hash_insert(&openDirectories, slot, p); |
ohash_insert(&openDirectories, slot, p); |
return p; |
return p; |
} |
} |
|
|
|
|
Path *p = (Path *) pp; |
Path *p = (Path *) pp; |
|
|
if (--p->refCount == 0) { |
if (--p->refCount == 0) { |
hash_remove(&openDirectories, hash_qlookup(&openDirectories, p->name)); |
ohash_remove(&openDirectories, ohash_qlookup(&openDirectories, p->name)); |
free_hash(&p->files); |
free_hash(&p->files); |
free(p); |
free(p); |
} |
} |
|
|
(hits+bigmisses+nearmisses ? |
(hits+bigmisses+nearmisses ? |
hits * 100 / (hits + bigmisses + nearmisses) : 0)); |
hits * 100 / (hits + bigmisses + nearmisses) : 0)); |
printf ("# %-20s referenced\thits\n", "directory"); |
printf ("# %-20s referenced\thits\n", "directory"); |
for (p = hash_first(&openDirectories, &i); p != NULL; |
for (p = ohash_first(&openDirectories, &i); p != NULL; |
p = hash_next(&openDirectories, &i)) |
p = ohash_next(&openDirectories, &i)) |
printf("# %-20s %10d\t%4d\n", p->name, p->refCount, p->hits); |
printf("# %-20s %10d\t%4d\n", p->name, p->refCount, p->hits); |
} |
} |
|
|