faster smb browsing - added thread to parse entries

This commit is contained in:
dborth 2009-07-07 06:37:22 +00:00
parent 014505c37c
commit d941c4a02c
3 changed files with 120 additions and 72 deletions

View File

@ -33,6 +33,8 @@
#include "filebrowser.h" #include "filebrowser.h"
#include "preferences.h" #include "preferences.h"
#define THREAD_SLEEP 100
unsigned char savebuffer[SAVEBUFFERSIZE] ATTRIBUTE_ALIGN(32); unsigned char savebuffer[SAVEBUFFERSIZE] ATTRIBUTE_ALIGN(32);
static mutex_t bufferLock = LWP_MUTEX_NULL; static mutex_t bufferLock = LWP_MUTEX_NULL;
FILE * file; // file pointer - the only one we should ever use! FILE * file; // file pointer - the only one we should ever use!
@ -47,9 +49,13 @@ bool isMounted[9] = { false, false, false, false, false, false, false, false, fa
const DISC_INTERFACE* cardb = &__io_gcsdb; const DISC_INTERFACE* cardb = &__io_gcsdb;
#endif #endif
/**************************************************************************** // folder parsing thread
* deviceThreading static lwp_t parsethread = LWP_THREAD_NULL;
***************************************************************************/ static DIR_ITER * dirIter = NULL;
static bool parseHalt = true;
bool ParseDirEntries();
// device thread
static lwp_t devicethread = LWP_THREAD_NULL; static lwp_t devicethread = LWP_THREAD_NULL;
static bool deviceHalt = true; static bool deviceHalt = true;
@ -82,7 +88,7 @@ HaltDeviceThread()
// wait for thread to finish // wait for thread to finish
while(!LWP_ThreadIsSuspended(devicethread)) while(!LWP_ThreadIsSuspended(devicethread))
usleep(100); usleep(THREAD_SLEEP);
} }
/**************************************************************************** /****************************************************************************
@ -100,8 +106,8 @@ devicecallback (void *arg)
{ {
if(deviceHalt) if(deviceHalt)
LWP_SuspendThread(devicethread); LWP_SuspendThread(devicethread);
usleep(100); usleep(THREAD_SLEEP);
devsleep -= 100; devsleep -= THREAD_SLEEP;
} }
while (1) while (1)
@ -151,13 +157,25 @@ devicecallback (void *arg)
{ {
if(deviceHalt) if(deviceHalt)
LWP_SuspendThread(devicethread); LWP_SuspendThread(devicethread);
usleep(100); usleep(THREAD_SLEEP);
devsleep -= 100; devsleep -= THREAD_SLEEP;
} }
} }
return NULL; return NULL;
} }
static void *
parsecallback (void *arg)
{
while(1)
{
while(ParseDirEntries())
usleep(THREAD_SLEEP);
LWP_SuspendThread(parsethread);
}
return NULL;
}
/**************************************************************************** /****************************************************************************
* InitDeviceThread * InitDeviceThread
* *
@ -168,6 +186,7 @@ void
InitDeviceThread() InitDeviceThread()
{ {
LWP_CreateThread (&devicethread, devicecallback, NULL, NULL, 0, 40); LWP_CreateThread (&devicethread, devicecallback, NULL, NULL, 0, 40);
LWP_CreateThread (&parsethread, parsecallback, NULL, NULL, 0, 80);
} }
/**************************************************************************** /****************************************************************************
@ -314,32 +333,107 @@ bool ChangeInterface(int method, bool silent)
return mounted; return mounted;
} }
bool ParseDirEntries()
{
if(!dirIter)
return false;
char filename[MAXPATHLEN];
struct stat filestat;
int i, res;
for(i=0; i < 20; i++)
{
res = dirnext(dirIter,filename,&filestat);
if(res != 0)
break;
if(strcmp(filename,".") == 0)
{
i--;
continue;
}
BROWSERENTRY * newBrowserList = (BROWSERENTRY *)realloc(browserList, (browser.numEntries+i+1) * sizeof(BROWSERENTRY));
if(!newBrowserList) // failed to allocate required memory
{
ResetBrowser();
ErrorPrompt("Out of memory: too many files!");
break;
}
else
{
browserList = newBrowserList;
}
memset(&(browserList[browser.numEntries+i]), 0, sizeof(BROWSERENTRY)); // clear the new entry
strncpy(browserList[browser.numEntries+i].filename, filename, MAXJOLIET);
browserList[browser.numEntries+i].length = filestat.st_size;
browserList[browser.numEntries+i].mtime = filestat.st_mtime;
browserList[browser.numEntries+i].isdir = (filestat.st_mode & _IFDIR) == 0 ? 0 : 1; // flag this as a dir
if(browserList[browser.numEntries+i].isdir)
{
if(strcmp(filename, "..") == 0)
sprintf(browserList[browser.numEntries+i].displayname, "Up One Level");
else
strncpy(browserList[browser.numEntries+i].displayname, browserList[browser.numEntries+i].filename, MAXJOLIET);
}
else
{
StripExt(browserList[browser.numEntries+i].displayname, browserList[browser.numEntries+i].filename); // hide file extension
}
}
// Sort the file list
if(i >= 0)
{
browser.numEntries += i;
qsort(browserList, browser.numEntries, sizeof(BROWSERENTRY), FileSortCallback);
}
if(res != 0 || parseHalt)
{
dirclose(dirIter); // close directory
dirIter = NULL;
return false; // no more entries
}
return true; // more entries
}
/*************************************************************************** /***************************************************************************
* Browse subdirectories * Browse subdirectories
**************************************************************************/ **************************************************************************/
int int
ParseDirectory(int method) ParseDirectory(int method)
{ {
DIR_ITER *dir = NULL;
char fulldir[MAXPATHLEN]; char fulldir[MAXPATHLEN];
char filename[MAXPATHLEN];
struct stat filestat;
char msg[128]; char msg[128];
int retry = 1; int retry = 1;
bool mounted = false; bool mounted = false;
// halt parsing
parseHalt = true;
while(!LWP_ThreadIsSuspended(parsethread))
usleep(THREAD_SLEEP);
// reset browser // reset browser
dirIter = NULL;
ResetBrowser(); ResetBrowser();
ShowAction("Loading...");
// open the directory // open the directory
while(dir == NULL && retry == 1) while(dirIter == NULL && retry == 1)
{ {
mounted = ChangeInterface(method, NOTSILENT); mounted = ChangeInterface(method, NOTSILENT);
sprintf(fulldir, "%s%s", rootdir, browser.dir); // add device to path sprintf(fulldir, "%s%s", rootdir, browser.dir); // add device to path
if(mounted) dir = diropen(fulldir); if(mounted) dirIter = diropen(fulldir);
if(dir == NULL) if(dirIter == NULL)
{ {
unmountRequired[method] = true; unmountRequired[method] = true;
sprintf(msg, "Error opening %s", fulldir); sprintf(msg, "Error opening %s", fulldir);
@ -348,14 +442,14 @@ ParseDirectory(int method)
} }
// if we can't open the dir, try opening the root dir // if we can't open the dir, try opening the root dir
if (dir == NULL) if (dirIter == NULL)
{ {
if(ChangeInterface(method, SILENT)) if(ChangeInterface(method, SILENT))
{ {
sprintf(browser.dir,"/"); sprintf(browser.dir,"/");
sprintf(fulldir, "%s%s", rootdir, browser.dir); sprintf(fulldir, "%s%s", rootdir, browser.dir);
dir = diropen(fulldir); dirIter = diropen(fulldir);
if (dir == NULL) if (dirIter == NULL)
{ {
sprintf(msg, "Error opening %s", rootdir); sprintf(msg, "Error opening %s", rootdir);
ErrorPrompt(msg); ErrorPrompt(msg);
@ -364,59 +458,11 @@ ParseDirectory(int method)
} }
} }
// index files/folders parseHalt = false;
int entryNum = 0; ParseDirEntries(); // index first 50 entries
LWP_ResumeThread(parsethread); // index remaining entries
while(dirnext(dir,filename,&filestat) == 0) return browser.numEntries;
{
if(strcmp(filename,".") != 0)
{
BROWSERENTRY * newBrowserList = (BROWSERENTRY *)realloc(browserList, (entryNum+1) * sizeof(BROWSERENTRY));
if(!newBrowserList) // failed to allocate required memory
{
ResetBrowser();
ErrorPrompt("Out of memory: too many files!");
entryNum = -1;
break;
}
else
{
browserList = newBrowserList;
}
memset(&(browserList[entryNum]), 0, sizeof(BROWSERENTRY)); // clear the new entry
strncpy(browserList[entryNum].filename, filename, MAXJOLIET);
browserList[entryNum].length = filestat.st_size;
browserList[entryNum].mtime = filestat.st_mtime;
browserList[entryNum].isdir = (filestat.st_mode & _IFDIR) == 0 ? 0 : 1; // flag this as a dir
if(browserList[entryNum].isdir)
{
if(strcmp(filename, "..") == 0)
sprintf(browserList[entryNum].displayname, "Up One Level");
else
strncpy(browserList[entryNum].displayname, browserList[entryNum].filename, MAXJOLIET);
}
else
{
StripExt(browserList[entryNum].displayname, browserList[entryNum].filename); // hide file extension
}
entryNum++;
}
}
// close directory
dirclose(dir);
// Sort the file list
qsort(browserList, entryNum, sizeof(BROWSERENTRY), FileSortCallback);
CancelAction();
browser.numEntries = entryNum;
return entryNum;
} }
/**************************************************************************** /****************************************************************************

View File

@ -908,6 +908,7 @@ class GuiFileBrowser : public GuiElement
GuiButton * fileList[FILE_PAGESIZE]; GuiButton * fileList[FILE_PAGESIZE];
protected: protected:
int selectedItem; int selectedItem;
int numEntries;
bool listChanged; bool listChanged;
GuiText * fileListText[FILE_PAGESIZE]; GuiText * fileListText[FILE_PAGESIZE];

View File

@ -18,6 +18,7 @@ GuiFileBrowser::GuiFileBrowser(int w, int h)
{ {
width = w; width = w;
height = h; height = h;
numEntries = 0;
selectedItem = 0; selectedItem = 0;
selectable = true; selectable = true;
listChanged = true; // trigger an initial list update listChanged = true; // trigger an initial list update
@ -329,7 +330,7 @@ void GuiFileBrowser::Update(GuiTrigger * t)
for(int i=0; i<FILE_PAGESIZE; i++) for(int i=0; i<FILE_PAGESIZE; i++)
{ {
if(listChanged) if(listChanged || numEntries != browser.numEntries)
{ {
if(browser.pageIndex+i < browser.numEntries) if(browser.pageIndex+i < browser.numEntries)
{ {