7373cf518f
Do a few other changes to dircache and file code flags to accomodate its demands. Change-Id: I4742a54e8cfbe4d8b9cffb75faaf920dd907cf8a
218 lines
7.7 KiB
C
218 lines
7.7 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2005 by Miika Pekkarinen
|
|
* Copyright (C) 2014 by Michael Sevakis
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
****************************************************************************/
|
|
#ifndef _DIRCACHE_H
|
|
#define _DIRCACHE_H
|
|
|
|
#include "mv.h"
|
|
#include <string.h> /* size_t */
|
|
#include <sys/types.h> /* ssize_t */
|
|
|
|
#ifdef HAVE_DIRCACHE
|
|
|
|
/****************************************************************************
|
|
** Configurable values
|
|
**/
|
|
|
|
#if 0
|
|
/* enable dumping code */
|
|
#define DIRCACHE_DUMPSTER
|
|
#define DIRCACHE_DUMPSTER_BIN "/dircache_dump.bin"
|
|
#define DIRCACHE_DUMPSTER_CSV "/dircache_dump.csv"
|
|
#endif
|
|
|
|
/* dircache builds won't search below this but will work down to this point
|
|
while below it the cache will just pass requests through to the storage;
|
|
the limiting factor is the scanning thread stack size, not the
|
|
implementation -- tune the two together */
|
|
#define DIRCACHE_MAX_DEPTH 15
|
|
#define DIRCACHE_STACK_SIZE (DEFAULT_STACK_SIZE + 0x100)
|
|
|
|
/* memory buffer constants that control allocation */
|
|
#define DIRCACHE_RESERVE (1024*64) /* 64 KB - new entry slack */
|
|
#define DIRCACHE_MIN (1024*1024*1) /* 1 MB - provision min size */
|
|
#define DIRCACHE_LIMIT (1024*1024*6) /* 6 MB - provision max size */
|
|
|
|
/* make it easy to change serialnumber size without modifying anything else;
|
|
32 bits allows 21845 builds before wrapping in a 6MB cache that is filled
|
|
exclusively with entries and nothing else (32 byte entries), making that
|
|
figure pessimistic */
|
|
typedef uint32_t dc_serial_t;
|
|
|
|
/* these should agree with size of dc_serial_t */
|
|
#define DC_SERHASH_START 0xffffffff
|
|
|
|
/* I was originally using FNV hash but decided this is probably okay
|
|
(for now) */
|
|
#define dc_hash_serialnum(s, h) \
|
|
({ dc_serial_t __x = (s); crc_32(&(__x), sizeof(dc_serial_t), (h)); })
|
|
#define DC_SERIAL_FMT "0x%08lX"
|
|
|
|
/**
|
|
****************************************************************************/
|
|
|
|
#define IF_DIRCACHE(...) __VA_ARGS__
|
|
#define IFN_DIRCACHE(...)
|
|
|
|
#if CONFIG_PLATFORM & PLATFORM_NATIVE
|
|
/* native dircache is lower-level than on a hosted target */
|
|
#define DIRCACHE_NATIVE
|
|
#endif
|
|
|
|
struct dircache_file
|
|
{
|
|
int idx; /* this file's cache index */
|
|
dc_serial_t serialnum; /* this file's serial number */
|
|
};
|
|
|
|
enum dircache_status
|
|
{
|
|
DIRCACHE_IDLE = 0, /* no volume is initialized */
|
|
DIRCACHE_SCANNING = 1, /* dircache is scanning a volume */
|
|
DIRCACHE_READY = 2, /* dircache is ready to be used */
|
|
};
|
|
|
|
/** Dircache control **/
|
|
void dircache_wait(void);
|
|
void dircache_suspend(void);
|
|
int dircache_resume(void);
|
|
int dircache_enable(void);
|
|
void dircache_disable(void);
|
|
void dircache_free_buffer(void);
|
|
|
|
/** Volume mounting **/
|
|
void dircache_mount(void); /* always tries building everything it can */
|
|
void dircache_unmount(IF_MV_NONVOID(int volume));
|
|
|
|
|
|
/** File API service functions **/
|
|
|
|
/* avoid forcing #include of file_internal.h, fat.h and dir.h */
|
|
struct filestr_base;
|
|
struct file_base_info;
|
|
struct file_base_binding;
|
|
struct dirent;
|
|
struct dirscan_info;
|
|
struct dirinfo_native;
|
|
|
|
int dircache_readdir_dirent(struct filestr_base *stream,
|
|
struct dirscan_info *scanp,
|
|
struct dirent *entry);
|
|
void dircache_rewinddir_dirent(struct dirscan_info *scanp);
|
|
|
|
#ifdef DIRCACHE_NATIVE
|
|
struct fat_direntry;
|
|
int dircache_readdir_internal(struct filestr_base *stream,
|
|
struct file_base_info *infop,
|
|
struct fat_direntry *fatent);
|
|
void dircache_rewinddir_internal(struct file_base_info *info);
|
|
#endif /* DIRCACHE_NATIVE */
|
|
|
|
|
|
/** Dircache live updating **/
|
|
|
|
void dircache_get_rootinfo(struct file_base_info *infop);
|
|
void dircache_bind_file(struct file_base_binding *bindp);
|
|
void dircache_unbind_file(struct file_base_binding *bindp);
|
|
void dircache_fileop_create(struct file_base_info *dirinfop,
|
|
struct file_base_binding *bindp,
|
|
const char *basename,
|
|
const struct dirinfo_native *dinp);
|
|
void dircache_fileop_rename(struct file_base_info *dirinfop,
|
|
struct file_base_binding *bindp,
|
|
const char *basename);
|
|
void dircache_fileop_remove(struct file_base_binding *bindp);
|
|
void dircache_fileop_sync(struct file_base_binding *infop,
|
|
const struct dirinfo_native *dinp);
|
|
|
|
|
|
/** Dircache paths, files and shortcuts **/
|
|
struct dircache_fileref
|
|
{
|
|
struct dircache_file dcfile;
|
|
dc_serial_t serialhash; /* Hash of serialnumbers to root */
|
|
};
|
|
|
|
void dircache_fileref_init(struct dircache_fileref *dcfrefp);
|
|
ssize_t dircache_get_fileref_path(const struct dircache_fileref *dcfrefp,
|
|
char *buf, size_t size);
|
|
|
|
/* Bitflags for dircache_search() */
|
|
enum dircache_search_flags
|
|
{
|
|
DCS_FILEREF = 0x01, /* Check fileref existence and serial number */
|
|
_DCS_VERIFY_FLAG = 0x02, /* Internal: Only valid with DCS_FILEREF */
|
|
DCS_FILEREF_VERIFY = 0x03, /* Do DCS_FILEREF check + verify serial hash */
|
|
DCS_CACHED_PATH = 0x04, /* Check only cache for provided path */
|
|
_DCS_STORAGE_FLAG = 0x08, /* Internal: Only valid with DCS_CACHED_PATH */
|
|
DCS_STORAGE_PATH = 0x0c, /* Read-through if needed for provided path */
|
|
DCS_UPDATE_FILEREF = 0x10, /* If fileref is not valid but path is found or
|
|
searching a path, update the reference
|
|
information */
|
|
};
|
|
|
|
int dircache_search(unsigned int flags, struct dircache_fileref *dcfrefp,
|
|
const char *path);
|
|
|
|
int dircache_fileref_cmp(const struct dircache_fileref *dcfrefp1,
|
|
const struct dircache_fileref *dcfrefp2);
|
|
|
|
|
|
/** Debug screen/info stuff **/
|
|
|
|
struct dircache_info
|
|
{
|
|
enum dircache_status status; /* current composite status value */
|
|
const char *statusdesc; /* pointer to string describing 'status' */
|
|
size_t last_size; /* cache size after last build */
|
|
size_t size; /* total size of entries (with holes) */
|
|
size_t sizeused; /* bytes of 'size' actually utilized */
|
|
size_t size_limit; /* maximum possible size */
|
|
size_t reserve; /* size of reserve area */
|
|
size_t reserve_used; /* amount of reserve used */
|
|
unsigned int entry_count; /* number of cache entries */
|
|
long build_ticks; /* total time used to build cache */
|
|
};
|
|
|
|
void dircache_get_info(struct dircache_info *info);
|
|
#ifdef DIRCACHE_DUMPSTER
|
|
void dircache_dump(void);
|
|
#endif /* DIRCACHE_DUMPSTER */
|
|
|
|
|
|
/** Misc. stuff **/
|
|
void dircache_dcfile_init(struct dircache_file *dcfilep);
|
|
|
|
#ifdef HAVE_EEPROM_SETTINGS
|
|
int dircache_load(void);
|
|
int dircache_save(void);
|
|
#endif /* HAVE_EEPROM_SETTINGS */
|
|
|
|
void dircache_init(size_t last_size) INIT_ATTR;
|
|
|
|
#else /* !HAVE_DIRCACHE */
|
|
|
|
#define IF_DIRCACHE(...)
|
|
#define IFN_DIRCACHE(...) __VA_ARGS__
|
|
|
|
#endif /* HAVE_DIRCACHE */
|
|
|
|
#endif /* _DIRCACHE_H */
|