forked from len0rd/rockbox
FS#7598 - Dircache support for multivolume targets (by Phil Light).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16632 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
afde7f74d4
commit
52d827a26d
6 changed files with 102 additions and 49 deletions
|
@ -380,7 +380,7 @@ Keith Perri
|
||||||
Mark Fawcus
|
Mark Fawcus
|
||||||
Ivan Pesic
|
Ivan Pesic
|
||||||
Marcel Barbulescu
|
Marcel Barbulescu
|
||||||
|
Phil Light
|
||||||
|
|
||||||
The libmad team
|
The libmad team
|
||||||
The wavpack team
|
The wavpack team
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
#include "dir.h"
|
#include "dir.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "atoi.h"
|
#include "atoi.h"
|
||||||
//#include "dircache.h"
|
|
||||||
|
|
||||||
#define MAX_OPEN_DIRS 8
|
#define MAX_OPEN_DIRS 8
|
||||||
|
|
||||||
|
@ -32,22 +31,9 @@ static DIR_UNCACHED opendirs[MAX_OPEN_DIRS];
|
||||||
|
|
||||||
#ifdef HAVE_MULTIVOLUME
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
|
||||||
/* how to name volumes, first char must be outside of legal file names,
|
|
||||||
a number gets appended to enumerate, if applicable */
|
|
||||||
#ifdef HAVE_MMC
|
|
||||||
static const char* vol_names = "<MMC%d>";
|
|
||||||
#define VOL_ENUM_POS 4 /* position of %d, to avoid runtime calculation */
|
|
||||||
#elif defined(HAVE_HOTSWAP)
|
|
||||||
static const char* vol_names = "<microSD%d>";
|
|
||||||
#define VOL_ENUM_POS 8 /* position of %d, to avoid runtime calculation */
|
|
||||||
#else
|
|
||||||
static const char* vol_names = "<HD%d>";
|
|
||||||
#define VOL_ENUM_POS 3
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* returns on which volume this is, and copies the reduced name
|
/* returns on which volume this is, and copies the reduced name
|
||||||
(sortof a preprocessor for volume-decorated pathnames) */
|
(sortof a preprocessor for volume-decorated pathnames) */
|
||||||
static int strip_volume(const char* name, char* namecopy)
|
int strip_volume(const char* name, char* namecopy)
|
||||||
{
|
{
|
||||||
int volume = 0;
|
int volume = 0;
|
||||||
const char *temp = name;
|
const char *temp = name;
|
||||||
|
@ -55,7 +41,7 @@ static int strip_volume(const char* name, char* namecopy)
|
||||||
while (*temp == '/') /* skip all leading slashes */
|
while (*temp == '/') /* skip all leading slashes */
|
||||||
++temp;
|
++temp;
|
||||||
|
|
||||||
if (*temp && !strncmp(temp, vol_names, VOL_ENUM_POS))
|
if (*temp && !strncmp(temp, VOL_NAMES, VOL_ENUM_POS))
|
||||||
{
|
{
|
||||||
temp += VOL_ENUM_POS; /* behind special name */
|
temp += VOL_ENUM_POS; /* behind special name */
|
||||||
volume = atoi(temp); /* number is following */
|
volume = atoi(temp); /* number is following */
|
||||||
|
@ -199,7 +185,7 @@ struct dirent_uncached* readdir_uncached(DIR_UNCACHED* dir)
|
||||||
memset(theent, 0, sizeof(*theent));
|
memset(theent, 0, sizeof(*theent));
|
||||||
theent->attribute = FAT_ATTR_DIRECTORY | FAT_ATTR_VOLUME;
|
theent->attribute = FAT_ATTR_DIRECTORY | FAT_ATTR_VOLUME;
|
||||||
snprintf(theent->d_name, sizeof(theent->d_name),
|
snprintf(theent->d_name, sizeof(theent->d_name),
|
||||||
vol_names, dir->volumecounter);
|
VOL_NAMES, dir->volumecounter);
|
||||||
return theent;
|
return theent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "dir.h"
|
||||||
#if CONFIG_RTC
|
#if CONFIG_RTC
|
||||||
#include "time.h"
|
#include "time.h"
|
||||||
#include "timefuncs.h"
|
#include "timefuncs.h"
|
||||||
|
@ -51,6 +52,9 @@ DIR_CACHED opendirs[MAX_OPEN_DIRS];
|
||||||
|
|
||||||
static struct dircache_entry *fd_bindings[MAX_OPEN_FILES];
|
static struct dircache_entry *fd_bindings[MAX_OPEN_FILES];
|
||||||
static struct dircache_entry *dircache_root;
|
static struct dircache_entry *dircache_root;
|
||||||
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
static struct dircache_entry *append_position;
|
||||||
|
#endif
|
||||||
|
|
||||||
static bool dircache_initialized = false;
|
static bool dircache_initialized = false;
|
||||||
static bool dircache_initializing = false;
|
static bool dircache_initializing = false;
|
||||||
|
@ -155,6 +159,9 @@ static bool check_event_queue(void)
|
||||||
{
|
{
|
||||||
case DIRCACHE_STOP:
|
case DIRCACHE_STOP:
|
||||||
case SYS_USB_CONNECTED:
|
case SYS_USB_CONNECTED:
|
||||||
|
#ifdef HAVE_HOTSWAP
|
||||||
|
case SYS_FS_CHANGED:
|
||||||
|
#endif
|
||||||
/* Put the event back into the queue. */
|
/* Put the event back into the queue. */
|
||||||
queue_post(&dircache_queue, ev.id, ev.data);
|
queue_post(&dircache_queue, ev.id, ev.data);
|
||||||
return true;
|
return true;
|
||||||
|
@ -166,7 +173,7 @@ static bool check_event_queue(void)
|
||||||
/**
|
/**
|
||||||
* Internal function to iterate a path.
|
* Internal function to iterate a path.
|
||||||
*/
|
*/
|
||||||
static int dircache_scan(struct travel_data *td)
|
static int dircache_scan(IF_MV2(int volume,) struct travel_data *td)
|
||||||
{
|
{
|
||||||
#ifdef SIMULATOR
|
#ifdef SIMULATOR
|
||||||
while ( ( td->entry = readdir_uncached(td->dir) ) )
|
while ( ( td->entry = readdir_uncached(td->dir) ) )
|
||||||
|
@ -273,22 +280,37 @@ static int dircache_scan(struct travel_data *td)
|
||||||
* Recursively scan the hard disk and build the cache.
|
* Recursively scan the hard disk and build the cache.
|
||||||
*/
|
*/
|
||||||
#ifdef SIMULATOR
|
#ifdef SIMULATOR
|
||||||
static int dircache_travel(DIR_UNCACHED *dir, struct dircache_entry *ce)
|
static int dircache_travel(IF_MV2(int volume,) DIR_UNCACHED *dir, struct dircache_entry *ce)
|
||||||
#else
|
#else
|
||||||
static int dircache_travel(struct fat_dir *dir, struct dircache_entry *ce)
|
static int dircache_travel(IF_MV2(int volume,) struct fat_dir *dir, struct dircache_entry *ce)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
int depth = 0;
|
int depth = 0;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
memset(ce, 0, sizeof(struct dircache_entry));
|
memset(ce, 0, sizeof(struct dircache_entry));
|
||||||
|
|
||||||
|
#if defined(HAVE_MULTIVOLUME) && !defined(SIMULATOR)
|
||||||
|
if (volume > 0)
|
||||||
|
{
|
||||||
|
ce->d_name = ((char *)dircache_root+dircache_size);
|
||||||
|
snprintf(ce->d_name, VOL_ENUM_POS + 3, VOL_NAMES, volume);
|
||||||
|
ce->name_len = VOL_ENUM_POS + 3;
|
||||||
|
dircache_size += ce->name_len;
|
||||||
|
ce->attribute = FAT_ATTR_DIRECTORY | FAT_ATTR_VOLUME;
|
||||||
|
ce->size = 0;
|
||||||
|
append_position = dircache_gen_next(ce);
|
||||||
|
ce = dircache_gen_down(ce);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
dir_recursion[0].dir = dir;
|
dir_recursion[0].dir = dir;
|
||||||
dir_recursion[0].ce = ce;
|
dir_recursion[0].ce = ce;
|
||||||
dir_recursion[0].first = ce;
|
dir_recursion[0].first = ce;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
//logf("=> %s", dircache_cur_path);
|
//logf("=> %s", dircache_cur_path);
|
||||||
result = dircache_scan(&dir_recursion[depth]);
|
result = dircache_scan(IF_MV2(volume,) &dir_recursion[depth]);
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case 0: /* Leaving the current directory. */
|
case 0: /* Leaving the current directory. */
|
||||||
/* Add the standard . and .. entries. */
|
/* Add the standard . and .. entries. */
|
||||||
|
@ -536,37 +558,57 @@ static int dircache_do_rebuild(void)
|
||||||
start_tick = current_tick;
|
start_tick = current_tick;
|
||||||
dircache_initializing = true;
|
dircache_initializing = true;
|
||||||
appflags = 0;
|
appflags = 0;
|
||||||
|
entry_count = 0;
|
||||||
#ifdef SIMULATOR
|
|
||||||
pdir = opendir_uncached("/");
|
|
||||||
if (pdir == NULL)
|
|
||||||
{
|
|
||||||
logf("Failed to open rootdir");
|
|
||||||
dircache_initializing = false;
|
|
||||||
return -3;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if ( fat_opendir(IF_MV2(volume,) &dir, 0, NULL) < 0 ) {
|
|
||||||
logf("Failed opening root dir");
|
|
||||||
dircache_initializing = false;
|
|
||||||
return -3;
|
|
||||||
}
|
|
||||||
pdir = &dir;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
memset(dircache_cur_path, 0, sizeof(dircache_cur_path));
|
memset(dircache_cur_path, 0, sizeof(dircache_cur_path));
|
||||||
dircache_size = sizeof(struct dircache_entry);
|
dircache_size = sizeof(struct dircache_entry);
|
||||||
|
|
||||||
cpu_boost(true);
|
#ifdef HAVE_MULTIVOLUME
|
||||||
if (dircache_travel(pdir, dircache_root) < 0)
|
append_position = dircache_root;
|
||||||
|
|
||||||
|
for (i = NUM_VOLUMES; i >= 0; i--)
|
||||||
{
|
{
|
||||||
logf("dircache_travel failed");
|
if (fat_ismounted(i))
|
||||||
cpu_boost(false);
|
{
|
||||||
dircache_size = 0;
|
#endif
|
||||||
dircache_initializing = false;
|
#ifdef SIMULATOR
|
||||||
return -2;
|
pdir = opendir_uncached("/");
|
||||||
|
if (pdir == NULL)
|
||||||
|
{
|
||||||
|
logf("Failed to open rootdir");
|
||||||
|
dircache_initializing = false;
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
if ( fat_opendir(IF_MV2(i,) &dir, 0, NULL) < 0 ) {
|
||||||
|
#else
|
||||||
|
if ( fat_opendir(IF_MV2(0,) &dir, 0, NULL) < 0 ) {
|
||||||
|
#endif /* HAVE_MULTIVOLUME */
|
||||||
|
logf("Failed opening root dir");
|
||||||
|
dircache_initializing = false;
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
pdir = &dir;
|
||||||
|
#endif
|
||||||
|
cpu_boost(true);
|
||||||
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
if (dircache_travel(IF_MV2(i,) pdir, append_position) < 0)
|
||||||
|
#else
|
||||||
|
if (dircache_travel(IF_MV2(0,) pdir, dircache_root) < 0)
|
||||||
|
#endif /* HAVE_MULTIVOLUME */
|
||||||
|
{
|
||||||
|
logf("dircache_travel failed");
|
||||||
|
cpu_boost(false);
|
||||||
|
dircache_size = 0;
|
||||||
|
dircache_initializing = false;
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
cpu_boost(false);
|
||||||
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cpu_boost(false);
|
#endif
|
||||||
|
|
||||||
logf("Done, %ld KiB used", dircache_size / 1024);
|
logf("Done, %ld KiB used", dircache_size / 1024);
|
||||||
|
|
||||||
|
@ -610,6 +652,12 @@ static void dircache_thread(void)
|
||||||
|
|
||||||
switch (ev.id)
|
switch (ev.id)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_HOTSWAP
|
||||||
|
case SYS_FS_CHANGED:
|
||||||
|
if (!dircache_initialized)
|
||||||
|
break;
|
||||||
|
dircache_initialized = false;
|
||||||
|
#endif
|
||||||
case DIRCACHE_BUILD:
|
case DIRCACHE_BUILD:
|
||||||
thread_enabled = true;
|
thread_enabled = true;
|
||||||
dircache_do_rebuild();
|
dircache_do_rebuild();
|
||||||
|
|
|
@ -313,9 +313,7 @@
|
||||||
* plenty of RAM. Both features can be enabled independently. */
|
* plenty of RAM. Both features can be enabled independently. */
|
||||||
#if ((defined(MEMORYSIZE) && (MEMORYSIZE > 8)) || MEM > 8) && \
|
#if ((defined(MEMORYSIZE) && (MEMORYSIZE > 8)) || MEM > 8) && \
|
||||||
!defined(BOOTLOADER)
|
!defined(BOOTLOADER)
|
||||||
#if !defined(SANSA_E200) && !defined(SANSA_C200)
|
|
||||||
#define HAVE_DIRCACHE
|
#define HAVE_DIRCACHE
|
||||||
#endif
|
|
||||||
#ifdef HAVE_TAGCACHE
|
#ifdef HAVE_TAGCACHE
|
||||||
#define HAVE_TC_RAMCACHE
|
#define HAVE_TC_RAMCACHE
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -22,6 +22,23 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
|
||||||
|
/* how to name volumes, first char must be outside of legal file names,
|
||||||
|
a number gets appended to enumerate, if applicable */
|
||||||
|
#ifdef HAVE_MMC
|
||||||
|
#define VOL_NAMES "<MMC%d>"
|
||||||
|
#define VOL_ENUM_POS 4 /* position of %d, to avoid runtime calculation */
|
||||||
|
#elif defined(HAVE_HOTSWAP)
|
||||||
|
#define VOL_NAMES "<microSD%d>"
|
||||||
|
#define VOL_ENUM_POS 8 /* position of %d, to avoid runtime calculation */
|
||||||
|
#else
|
||||||
|
#define VOL_NAMES "<HD%d>"
|
||||||
|
#define VOL_ENUM_POS 3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_DIRCACHE
|
#ifdef HAVE_DIRCACHE
|
||||||
# include "dircache.h"
|
# include "dircache.h"
|
||||||
# define DIR DIR_CACHED
|
# define DIR DIR_CACHED
|
||||||
|
|
|
@ -75,6 +75,10 @@ typedef struct {
|
||||||
char *get_volume_name(int volume);
|
char *get_volume_name(int volume);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
int strip_volume(const char*, char*);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef DIRFUNCTIONS_DEFINED
|
#ifndef DIRFUNCTIONS_DEFINED
|
||||||
|
|
||||||
extern DIR_UNCACHED* opendir_uncached(const char* name);
|
extern DIR_UNCACHED* opendir_uncached(const char* name);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue