2020-10-25 03:09:07 +03:00
|
|
|
module pref
|
|
|
|
|
|
|
|
import os
|
2020-10-25 10:22:31 +03:00
|
|
|
import hash
|
2020-10-25 03:09:07 +03:00
|
|
|
|
|
|
|
// Using a 2 level cache, ensures a more even distribution of cache entries,
|
|
|
|
// so there will not be cramped folders that contain many thousands of them.
|
|
|
|
// Most filesystems can not handle performantly such folders, and slow down.
|
|
|
|
// The first level will contain a max of 256 folders, named from 00/ to ff/.
|
|
|
|
// Each of them will contain many entries, but hopefully < 1000.
|
|
|
|
// NB: using a hash here, makes the cache storage immune to special
|
|
|
|
// characters in the keys, like quotes, spaces and so on.
|
|
|
|
// Cleanup of the cache is simple: just delete the $VCACHE folder.
|
|
|
|
// The cache tree will look like this:
|
|
|
|
// │ $VCACHE
|
|
|
|
// │ ├── 0f
|
|
|
|
// │ │ ├── 0f004f983ab9c487b0d7c1a0a73840a5.txt
|
|
|
|
// │ │ ├── 0f599edf5e16c2756fbcdd4c865087ac.description.txt <-- build details
|
|
|
|
// │ │ └── 0f599edf5e16c2756fbcdd4c865087ac.vh
|
|
|
|
// │ ├── 29
|
|
|
|
// │ │ ├── 294717dd02a1cca5f2a0393fca2c5c22.o
|
|
|
|
// │ │ └── 294717dd02a1cca5f2a0393fca2c5c22.description.txt <-- build details
|
|
|
|
// │ ├── 62
|
|
|
|
// │ │ └── 620d60d6b81fdcb3cab030a37fd86996.h
|
|
|
|
// │ └── 76
|
|
|
|
// │ └── 7674f983ab9c487b0d7c1a0ad73840a5.c
|
|
|
|
pub struct CacheManager {
|
|
|
|
pub:
|
|
|
|
basepath string
|
|
|
|
pub mut:
|
|
|
|
vopts string
|
|
|
|
k2cpath map[string]string // key -> filesystem cache path for the object
|
|
|
|
}
|
|
|
|
|
|
|
|
fn new_cache_manager(opts []string) CacheManager {
|
|
|
|
mut vcache_basepath := os.getenv('VCACHE')
|
|
|
|
if vcache_basepath == '' {
|
|
|
|
vcache_basepath = os.join_path(os.home_dir(), '.vmodules', 'cache')
|
|
|
|
}
|
|
|
|
return CacheManager{
|
|
|
|
basepath: vcache_basepath
|
|
|
|
vopts: opts.join('|')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn (mut cm CacheManager) key2cpath(key string) string {
|
|
|
|
mut cpath := cm.k2cpath[key]
|
|
|
|
if cpath == '' {
|
|
|
|
hk := cm.vopts + key
|
2020-10-25 10:22:31 +03:00
|
|
|
a := hash.sum64_string(hk, 5).hex_full()
|
|
|
|
b := hash.sum64_string(hk, 7).hex_full()
|
|
|
|
khash := a + b
|
|
|
|
prefix := khash[0..2]
|
2020-10-25 03:09:07 +03:00
|
|
|
cprefix_folder := os.join_path(cm.basepath, prefix)
|
2020-10-25 10:22:31 +03:00
|
|
|
cpath = os.join_path(cprefix_folder, khash)
|
2020-10-25 03:09:07 +03:00
|
|
|
if !os.is_dir(cprefix_folder) {
|
|
|
|
os.mkdir_all(cprefix_folder)
|
|
|
|
os.chmod(cprefix_folder, 0o777)
|
|
|
|
}
|
|
|
|
cm.k2cpath[key] = cpath
|
|
|
|
}
|
|
|
|
return cpath
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn (mut cm CacheManager) postfix_with_key2cpath(postfix string, key string) string {
|
|
|
|
return cm.key2cpath(key) + postfix
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn (mut cm CacheManager) exists(postfix string, key string) ?string {
|
|
|
|
fpath := cm.postfix_with_key2cpath(postfix, key)
|
|
|
|
if !os.exists(fpath) {
|
|
|
|
return error('does not exist yet')
|
|
|
|
}
|
|
|
|
return fpath
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn (mut cm CacheManager) save(postfix string, key string, content string) ?string {
|
|
|
|
fpath := cm.postfix_with_key2cpath(postfix, key)
|
|
|
|
os.write_file(fpath, content) ?
|
|
|
|
return fpath
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn (mut cm CacheManager) load(postfix string, key string) ?string {
|
|
|
|
fpath := cm.exists(postfix, key) ?
|
|
|
|
content := os.read_file(fpath) ?
|
|
|
|
return content
|
|
|
|
}
|