-
Notifications
You must be signed in to change notification settings - Fork 48
Expand file tree
/
Copy pathstatcache.c
More file actions
102 lines (88 loc) · 2.49 KB
/
statcache.c
File metadata and controls
102 lines (88 loc) · 2.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include <string.h> /* memset */
#include <stdlib.h> /* malloc */
#include <stdio.h> /* printf */
#include <errno.h>
#include "statcache.h"
#include "support.h"
#include "mem.h"
#include "path.h"
#define STATCACHE_HASH_SIZE (16*1024)
struct STATCACHE_ENTRY
{
hash_t hashid;
time_t timestamp;
unsigned int isregular:1;
unsigned int isdir:1;
struct STATCACHE_ENTRY* next;
};
struct STATCACHE
{
struct HEAP* heap;
struct STATCACHE_ENTRY* entries[STATCACHE_HASH_SIZE];
};
struct STATCACHE* statcache_create()
{
struct STATCACHE* statcache = malloc(sizeof(struct STATCACHE));
memset(statcache, 0, sizeof(struct STATCACHE));
statcache->heap = mem_create();
return statcache;
}
void statcache_free(struct STATCACHE* statcache)
{
if(!statcache)
return;
mem_destroy(statcache->heap);
free( statcache );
}
struct STATCACHE_ENTRY* statcache_getstat_int(struct STATCACHE* statcache, const char* filename)
{
hash_t namehash = string_hash_path( filename );
int hashindex = namehash & ( STATCACHE_HASH_SIZE - 1 );
struct STATCACHE_ENTRY* entry = NULL;
for ( entry = statcache->entries[ hashindex ]; entry; entry = entry->next ) {
if ( entry->hashid == namehash ) {
break;
}
}
if ( !entry ) {
entry = ( struct STATCACHE_ENTRY* )mem_allocate( statcache->heap, sizeof( struct STATCACHE_ENTRY ) );
entry->hashid = namehash;
unsigned int isregular = 0;
unsigned int isdir = 0;
uint64 size = 0;
if(file_stat(filename, &entry->timestamp, &isregular, &isdir, &size) == 0)
{
entry->isregular = isregular;
entry->isdir = isdir;
}
entry->next = statcache->entries[ hashindex ];
statcache->entries[ hashindex ] = entry;
}
return entry;
}
int statcache_getstat(struct STATCACHE* statcache, const char* filename, time_t* timestamp, int* isregularfile)
{
if(!statcache)
return 1;
// check if the folder exists first. Many files share the same folder path,
// so this check is likely to hit the cache even if the full path is unique
// total number stats is 38% of what it was without in my (large, actual project) test
char dirname[MAX_PATH_LENGTH];
if(path_directory(filename, dirname, MAX_PATH_LENGTH) == 0 && dirname[0] != '\0')
{
struct STATCACHE_ENTRY* direntry = statcache_getstat_int(statcache, dirname);
if(direntry)
{
if(direntry->timestamp == 0)
{
*timestamp = 0;
*isregularfile = 0;
return 0;
}
}
}
struct STATCACHE_ENTRY* entry = statcache_getstat_int(statcache, filename);
*timestamp=entry->timestamp;
*isregularfile = entry->isregular;
return 0;
}