ok, optimize memory sage of directorys, by iteratively creating the directories,
this code needs some serious testing: Note: The song name optimization i think is worth it, saves about 200k of ram on my syste, however, having to create directory names iteratively each time we print probably isn't worth the cpu. We only save about 10k of ram for the computer todo alot more work, and the code maybe a little messier git-svn-id: https://svn.musicpd.org/mpd/trunk@2604 09075e82-0dd4-0310-85a5-a0d7c8717e4f
This commit is contained in:
parent
6e0c4369c3
commit
21b5cde43a
|
@ -60,8 +60,8 @@ int countSongsInDirectory(FILE * fp, Directory * directory, void * data) {
|
|||
}
|
||||
|
||||
int printDirectoryInDirectory(FILE * fp, Directory * directory, void * data) {
|
||||
if(directory->utf8name) {
|
||||
myfprintf(fp,"directory: %s\n",directory->utf8name);
|
||||
if(directory->name) {
|
||||
myfprintf(fp,"directory: %s\n", getDirectoryPath(directory));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -273,13 +273,15 @@ int listAllUniqueTags(FILE * fp, int type, int numConditionals,
|
|||
int sumSavedMemoryInDirectory(FILE * fp, Directory * dir, void * data) {
|
||||
int * sum = data;
|
||||
|
||||
if(!dir->utf8name) return 0;
|
||||
if(!dir->name) return 0;
|
||||
|
||||
*sum += (strlen(dir->utf8name)+1-sizeof(Directory *))*
|
||||
*sum += (strlen(getDirectoryPath(dir))+1-sizeof(Directory *))*
|
||||
dir->songs->numberOfNodes;
|
||||
|
||||
/**sum += (strlen(dir->utf8name)+1)*
|
||||
dir->subDirectories->numberOfNodes;*/
|
||||
*sum += (strlen(getDirectoryPath(dir))+1)*
|
||||
dir->subDirectories->numberOfNodes;
|
||||
|
||||
*sum += strlen(dir->name)+1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
123
src/directory.c
123
src/directory.c
|
@ -250,8 +250,8 @@ Directory * newDirectory(char * dirname, Directory * parent) {
|
|||
|
||||
directory = malloc(sizeof(Directory));
|
||||
|
||||
if(dirname!=NULL) directory->utf8name = strdup(dirname);
|
||||
else directory->utf8name = NULL;
|
||||
if(dirname!=NULL) directory->name = strdup(dirname);
|
||||
else directory->name = NULL;
|
||||
directory->subDirectories = newDirectoryList();
|
||||
directory->songs = newSongList();
|
||||
directory->stat = NULL;
|
||||
|
@ -263,13 +263,14 @@ Directory * newDirectory(char * dirname, Directory * parent) {
|
|||
void freeDirectory(Directory * directory) {
|
||||
freeDirectoryList(directory->subDirectories);
|
||||
freeSongList(directory->songs);
|
||||
if(directory->utf8name) free(directory->utf8name);
|
||||
if(directory->name) free(directory->name);
|
||||
freeDirectoryStatFromDirectory(directory);
|
||||
free(directory);
|
||||
getDirectoryPath(NULL);
|
||||
}
|
||||
|
||||
DirectoryList * newDirectoryList() {
|
||||
return makeList((ListFreeDataFunc *)freeDirectory, 1);
|
||||
return makeList((ListFreeDataFunc *)freeDirectory, 0);
|
||||
}
|
||||
|
||||
void freeDirectoryList(DirectoryList * directoryList) {
|
||||
|
@ -351,7 +352,7 @@ int updateInDirectory(Directory * directory, char * shortname, char * name) {
|
|||
int removeDeletedFromDirectory(Directory * directory, DIR * dir) {
|
||||
char cwd[2];
|
||||
struct dirent * ent;
|
||||
char * dirname = directory->utf8name;
|
||||
char * dirname = getDirectoryPath(directory);
|
||||
List * entList = makeList(free, 1);
|
||||
void * name;
|
||||
char * s;
|
||||
|
@ -372,9 +373,10 @@ int removeDeletedFromDirectory(Directory * directory, DIR * dir) {
|
|||
|
||||
if(!utf8) continue;
|
||||
|
||||
if(directory->utf8name) {
|
||||
s = malloc(strlen(directory->utf8name)+strlen(utf8)+2);
|
||||
sprintf(s,"%s/%s",directory->utf8name,utf8);
|
||||
if(directory->name) {
|
||||
s = malloc(strlen(getDirectoryPath(directory))
|
||||
+strlen(utf8)+2);
|
||||
sprintf(s,"%s/%s", getDirectoryPath(directory), utf8);
|
||||
}
|
||||
else s= strdup(utf8);
|
||||
insertInList(entList,utf8,s);
|
||||
|
@ -393,9 +395,9 @@ int removeDeletedFromDirectory(Directory * directory, DIR * dir) {
|
|||
}
|
||||
else {
|
||||
LOG("removing directory: ");
|
||||
if(directory->utf8name) LOG("%s/",directory->utf8name);
|
||||
LOG("%s/",getDirectoryPath(directory));
|
||||
LOG("%s\n",node->key);
|
||||
deleteFromList(directory->subDirectories,node->key);
|
||||
deleteFromList(directory->subDirectories, node->key);
|
||||
ret = 1;
|
||||
}
|
||||
node = tmpNode;
|
||||
|
@ -451,8 +453,9 @@ Directory * addDirectoryPathToDB(char * utf8path, char ** shortname) {
|
|||
return NULL;
|
||||
}
|
||||
else {
|
||||
directory = newDirectory(utf8path, parentDirectory);
|
||||
insertInList(parentDirectory->subDirectories,*shortname,
|
||||
directory = newDirectory(*shortname, parentDirectory);
|
||||
insertInList(parentDirectory->subDirectories,
|
||||
((Directory *)directory)->name,
|
||||
directory);
|
||||
}
|
||||
}
|
||||
|
@ -596,7 +599,7 @@ int updateDirectory(Directory * directory) {
|
|||
struct dirent * ent;
|
||||
char * s;
|
||||
char * utf8;
|
||||
char * dirname = directory->utf8name;
|
||||
char * dirname = getDirectoryPath(directory);
|
||||
int ret = 0;
|
||||
|
||||
{
|
||||
|
@ -631,9 +634,10 @@ int updateDirectory(Directory * directory) {
|
|||
|
||||
utf8 = strdup(utf8);
|
||||
|
||||
if(directory->utf8name) {
|
||||
s = malloc(strlen(directory->utf8name)+strlen(utf8)+2);
|
||||
sprintf(s,"%s/%s",directory->utf8name,utf8);
|
||||
if(directory->name) {
|
||||
s = malloc(strlen(getDirectoryPath(directory))+
|
||||
strlen(utf8)+2);
|
||||
sprintf(s,"%s/%s", getDirectoryPath(directory), utf8);
|
||||
}
|
||||
else s = strdup(utf8);
|
||||
if(updateInDirectory(directory,utf8,s)>0) ret = 1;
|
||||
|
@ -657,7 +661,7 @@ int exploreDirectory(Directory * directory) {
|
|||
struct dirent * ent;
|
||||
char * s;
|
||||
char * utf8;
|
||||
char * dirname = directory->utf8name;
|
||||
char * dirname = getDirectoryPath(directory);
|
||||
int ret = 0;
|
||||
|
||||
cwd[0] = '.';
|
||||
|
@ -680,9 +684,10 @@ int exploreDirectory(Directory * directory) {
|
|||
|
||||
DEBUG("explore: found: %s (%s)\n",ent->d_name,utf8);
|
||||
|
||||
if(directory->utf8name) {
|
||||
s = malloc(strlen(directory->utf8name)+strlen(utf8)+2);
|
||||
sprintf(s,"%s/%s",directory->utf8name,utf8);
|
||||
if(directory->name) {
|
||||
s = malloc(strlen(getDirectoryPath(directory))+
|
||||
strlen(utf8)+2);
|
||||
sprintf(s,"%s/%s", getDirectoryPath(directory) ,utf8);
|
||||
}
|
||||
else s = strdup(utf8);
|
||||
if(addToDirectory(directory,utf8,s)>0) ret = 1;
|
||||
|
@ -698,7 +703,9 @@ int exploreDirectory(Directory * directory) {
|
|||
int statDirectory(Directory * dir) {
|
||||
struct stat st;
|
||||
|
||||
if(myStat(dir->utf8name ? dir->utf8name : "", &st) < 0) return -1;
|
||||
if(myStat(getDirectoryPath(dir) ? getDirectoryPath(dir) : "", &st) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
dir->stat = newDirectoryStat(&st);
|
||||
|
||||
|
@ -729,7 +736,7 @@ int addSubDirectoryToDirectory(Directory * directory, char * shortname,
|
|||
|
||||
if(inodeFoundInParent(directory, st->st_ino, st->st_dev)) return 0;
|
||||
|
||||
subDirectory = newDirectory(name, directory);
|
||||
subDirectory = newDirectory(shortname, directory);
|
||||
subDirectory->stat = newDirectoryStat(st);
|
||||
|
||||
if(exploreDirectory(subDirectory)<1) {
|
||||
|
@ -737,7 +744,8 @@ int addSubDirectoryToDirectory(Directory * directory, char * shortname,
|
|||
return 0;
|
||||
}
|
||||
|
||||
insertInList(directory->subDirectories,shortname,subDirectory);
|
||||
insertInList(directory->subDirectories, subDirectory->name,
|
||||
subDirectory);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -828,7 +836,8 @@ int printDirectoryList(FILE * fp, DirectoryList * directoryList) {
|
|||
|
||||
while(node!=NULL) {
|
||||
directory = (Directory *)node->data;
|
||||
myfprintf(fp,"%s%s\n",DIRECTORY_DIR,directory->utf8name);
|
||||
myfprintf(fp,"%s%s\n", DIRECTORY_DIR,
|
||||
getDirectoryPath(directory));
|
||||
node = node->nextNode;
|
||||
}
|
||||
|
||||
|
@ -854,8 +863,9 @@ void writeDirectoryInfo(FILE * fp, Directory * directory) {
|
|||
ListNode * node = (directory->subDirectories)->firstNode;
|
||||
Directory * subDirectory;
|
||||
|
||||
if(directory->utf8name) {
|
||||
myfprintf(fp,"%s%s\n",DIRECTORY_BEGIN,directory->utf8name);
|
||||
if(directory->name) {
|
||||
myfprintf(fp,"%s%s\n", DIRECTORY_BEGIN,
|
||||
getDirectoryPath(directory));
|
||||
}
|
||||
|
||||
while(node!=NULL) {
|
||||
|
@ -867,8 +877,9 @@ void writeDirectoryInfo(FILE * fp, Directory * directory) {
|
|||
|
||||
writeSongInfoFromList(fp,directory->songs);
|
||||
|
||||
if(directory->utf8name) {
|
||||
myfprintf(fp,"%s%s\n",DIRECTORY_END,directory->utf8name);
|
||||
if(directory->name) {
|
||||
myfprintf(fp,"%s%s\n", DIRECTORY_END,
|
||||
getDirectoryPath(directory));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -877,7 +888,6 @@ void readDirectoryInfo(FILE * fp,Directory * directory) {
|
|||
int bufferSize = MAXPATHLEN*2;
|
||||
char * key;
|
||||
Directory * subDirectory;
|
||||
char * name;
|
||||
int strcmpRet;
|
||||
ListNode * nextDirNode = directory->subDirectories->firstNode;
|
||||
ListNode * nodeTemp;
|
||||
|
@ -902,7 +912,8 @@ void readDirectoryInfo(FILE * fp,Directory * directory) {
|
|||
ERROR("Error reading db at line: %s\n",buffer);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
name = strdup(&(buffer[strlen(DIRECTORY_BEGIN)]));
|
||||
/* we ignore the name now
|
||||
name = strdup(&(buffer[strlen(DIRECTORY_BEGIN)]));*/
|
||||
|
||||
while(nextDirNode && (strcmpRet =
|
||||
strcmp(key,nextDirNode->key)) > 0) {
|
||||
|
@ -913,8 +924,9 @@ void readDirectoryInfo(FILE * fp,Directory * directory) {
|
|||
}
|
||||
|
||||
if(NULL==nextDirNode) {
|
||||
subDirectory = newDirectory(name, directory);
|
||||
insertInList(directory->subDirectories,key,
|
||||
subDirectory = newDirectory(key, directory);
|
||||
insertInList(directory->subDirectories,
|
||||
subDirectory->name,
|
||||
(void *)subDirectory);
|
||||
}
|
||||
else if(strcmpRet == 0) {
|
||||
|
@ -922,16 +934,15 @@ void readDirectoryInfo(FILE * fp,Directory * directory) {
|
|||
nextDirNode = nextDirNode->nextNode;
|
||||
}
|
||||
else {
|
||||
subDirectory = newDirectory(name, directory);
|
||||
subDirectory = newDirectory(key, directory);
|
||||
insertInListBeforeNode(
|
||||
directory->subDirectories,
|
||||
nextDirNode,
|
||||
key,
|
||||
subDirectory->name,
|
||||
(void *)subDirectory);
|
||||
}
|
||||
|
||||
free(key);
|
||||
free(name);
|
||||
readDirectoryInfo(fp,subDirectory);
|
||||
}
|
||||
else if(0==strncmp(SONG_BEGIN,buffer,strlen(SONG_BEGIN))) {
|
||||
|
@ -1225,3 +1236,45 @@ Song * getSongFromDB(char * file) {
|
|||
time_t getDbModTime() {
|
||||
return directory_dbModTime;
|
||||
}
|
||||
|
||||
/* pass a NULL to this function to clear the static lastDir, this way
|
||||
* if a directory is freed, and then realloced, the wrong name isn't
|
||||
* output */
|
||||
char * getDirectoryPath(Directory * dir) {
|
||||
static char * buffer = NULL;
|
||||
static int bufferSize = 0;
|
||||
static Directory * lastDir = NULL;
|
||||
static int pos = 0;
|
||||
int dlen;
|
||||
|
||||
if(!dir || !dir->name) {
|
||||
lastDir = NULL;
|
||||
return "";
|
||||
}
|
||||
|
||||
if(lastDir == dir) return buffer+pos+1;
|
||||
|
||||
pos = bufferSize-1;
|
||||
|
||||
while(dir && dir->name) {
|
||||
dlen = strlen(dir->name);
|
||||
/* add one for the '/' */
|
||||
pos -= dlen+1;
|
||||
if(pos < 0) {
|
||||
buffer = realloc(buffer, bufferSize-pos);
|
||||
if(bufferSize) {
|
||||
memmove(buffer-pos, buffer, bufferSize);
|
||||
}
|
||||
bufferSize += -pos;
|
||||
buffer[bufferSize-1] = '\0';
|
||||
pos = 0;
|
||||
}
|
||||
strncpy(buffer+pos+1, dir->name, dlen);
|
||||
buffer[pos] = '/';
|
||||
dir = dir->parent;
|
||||
}
|
||||
|
||||
lastDir = dir;
|
||||
|
||||
return buffer+pos+1;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ typedef struct _DirectoryStat {
|
|||
} DirectoryStat;
|
||||
|
||||
typedef struct _Directory {
|
||||
char * utf8name;
|
||||
char * name;
|
||||
DirectoryList * subDirectories;
|
||||
SongList * songs;
|
||||
struct _Directory * parent;
|
||||
|
@ -75,6 +75,9 @@ int traverseAllIn(FILE * fp, char * name,
|
|||
int (*forEachDir)(FILE *, Directory *, void *),
|
||||
void * data);
|
||||
|
||||
/* don't free this */
|
||||
char * getDirectoryPath(Directory * dir);
|
||||
|
||||
/* free the string that is returned */
|
||||
char * catDirAndFileName(Directory * dir, char * filename);
|
||||
|
||||
|
|
22
src/song.c
22
src/song.c
|
@ -29,7 +29,7 @@
|
|||
#define SONG_KEY "key: "
|
||||
#define SONG_FILE "file: "
|
||||
#define SONG_TIME "Time: "
|
||||
#define SONG_MTIME "Mtime: "
|
||||
#define SONG_MTIME "mtime: "
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -83,6 +83,7 @@ void freeJustSong(Song * song) {
|
|||
free(song->url);
|
||||
if(song->tag) freeMpdTag(song->tag);
|
||||
free(song);
|
||||
getSongUrl(NULL);
|
||||
}
|
||||
|
||||
SongList * newSongList() {
|
||||
|
@ -118,8 +119,8 @@ void freeSongList(SongList * list) {
|
|||
|
||||
void printSongUrl(FILE * fp, Song * song) {
|
||||
if(song->parentDir) {
|
||||
myfprintf(fp, "%s%s/%s\n", SONG_FILE, song->parentDir->utf8name,
|
||||
song->url);
|
||||
myfprintf(fp, "%s%s/%s\n", SONG_FILE,
|
||||
getDirectoryPath(song->parentDir), song->url);
|
||||
}
|
||||
else {
|
||||
myfprintf(fp, "%s%s\n", SONG_FILE, song->url);
|
||||
|
@ -299,6 +300,8 @@ Song * songDup(Song * song) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* pass song = NULL to reset, we do this freeJustSong(), so that if
|
||||
* we free and recreate this memory we make sure to print it correctly*/
|
||||
char * getSongUrl(Song * song) {
|
||||
static char * buffer = NULL;
|
||||
static int bufferSize = 0;
|
||||
|
@ -307,13 +310,18 @@ char * getSongUrl(Song * song) {
|
|||
int dlen;
|
||||
int size;
|
||||
|
||||
if(!song->parentDir || !song->parentDir->utf8name) return song->url;
|
||||
if(!song) {
|
||||
lastSong = song;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* be careful with this! */
|
||||
if(!song->parentDir || !song->parentDir->name) return song->url;
|
||||
|
||||
/* be careful with this!*/
|
||||
if(song == lastSong) return buffer;
|
||||
|
||||
slen = strlen(song->url);
|
||||
dlen = strlen(song->parentDir->utf8name);
|
||||
dlen = strlen(getDirectoryPath(song->parentDir));
|
||||
|
||||
size = slen+dlen+2;
|
||||
|
||||
|
@ -322,7 +330,7 @@ char * getSongUrl(Song * song) {
|
|||
bufferSize = size;
|
||||
}
|
||||
|
||||
strcpy(buffer, song->parentDir->utf8name);
|
||||
strcpy(buffer, getDirectoryPath(song->parentDir));
|
||||
buffer[dlen] = '/';
|
||||
strcpy(buffer+dlen+1, song->url);
|
||||
|
||||
|
|
Loading…
Reference in New Issue