mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
Fix for Bug #1952
"SHOW TABLE STATUS very slow w/large number of tables" Replaced old algorithm which were used in my_dir() and stored all information about directory entries in one chunk of memory with new one which stores file names and MY_STAT structures in separate memroot, so now we don't need to copy this data during reallocation of dir_entry array. include/my_dir.h: Changed mystat member of FILEINFO structure to pointer since this prevents unneeded memory allocation and initialization. Added comment about new hidden members of MY_DIR structure. mysys/my_lib.c: Replaced old algorithm in my_dir() which stored all information about directory entries in one chunk of memory with new one which stores file names and MY_STAT structures in separate memroot. Now we don't copy this data during reallocation of array with FILEINFO structures. Also tuned sizes of memory chunks during first-other reallocations (we suppose that we either have < 100 files in the directory or > 1000 of them). sql/sql_show.cc: Updated only place in code where mystat member of FILEINFO structure is used.
This commit is contained in:
parent
22c12eaeb2
commit
c545b02645
3 changed files with 190 additions and 166 deletions
|
@ -74,14 +74,21 @@ typedef struct my_stat
|
||||||
|
|
||||||
#endif /* USE_MY_STAT_STRUCT */
|
#endif /* USE_MY_STAT_STRUCT */
|
||||||
|
|
||||||
typedef struct fileinfo /* Struct returned from my_dir & my_stat */
|
/* Struct describing one file returned from my_dir */
|
||||||
|
typedef struct fileinfo
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
MY_STAT mystat;
|
MY_STAT *mystat;
|
||||||
} FILEINFO;
|
} FILEINFO;
|
||||||
|
|
||||||
typedef struct st_my_dir /* Struct returned from my_dir */
|
typedef struct st_my_dir /* Struct returned from my_dir */
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
These members are just copies of parts of DYNAMIC_ARRAY structure,
|
||||||
|
which is allocated right after the end of MY_DIR structure (MEM_ROOT
|
||||||
|
for storing names is also resides there). We've left them here because
|
||||||
|
we don't want to change code that uses my_dir.
|
||||||
|
*/
|
||||||
struct fileinfo *dir_entry;
|
struct fileinfo *dir_entry;
|
||||||
uint number_off_files;
|
uint number_off_files;
|
||||||
} MY_DIR;
|
} MY_DIR;
|
||||||
|
|
343
mysys/my_lib.c
343
mysys/my_lib.c
|
@ -62,8 +62,15 @@
|
||||||
#define READDIR(A,B,C) (!(C=readdir(A)))
|
#define READDIR(A,B,C) (!(C=readdir(A)))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
We are assuming that directory we are reading is either has less than
|
||||||
|
100 files and so can be read in one initial chunk or has more than 1000
|
||||||
|
files and so big increment are suitable.
|
||||||
|
*/
|
||||||
|
#define ENTRIES_START_SIZE (8192/sizeof(FILEINFO))
|
||||||
|
#define ENTRIES_INCREMENT (65536/sizeof(FILEINFO))
|
||||||
|
#define NAMES_START_SIZE 32768
|
||||||
|
|
||||||
#define STARTSIZE ONCE_ALLOC_INIT*8 /* some mallocmargin */
|
|
||||||
|
|
||||||
static int comp_names(struct fileinfo *a,struct fileinfo *b);
|
static int comp_names(struct fileinfo *a,struct fileinfo *b);
|
||||||
|
|
||||||
|
@ -74,7 +81,13 @@ void my_dirend(MY_DIR *buffer)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("my_dirend");
|
DBUG_ENTER("my_dirend");
|
||||||
if (buffer)
|
if (buffer)
|
||||||
|
{
|
||||||
|
delete_dynamic((DYNAMIC_ARRAY*)((char*)buffer +
|
||||||
|
ALIGN_SIZE(sizeof(MY_DIR))));
|
||||||
|
free_root((MEM_ROOT*)((char*)buffer + ALIGN_SIZE(sizeof(MY_DIR)) +
|
||||||
|
ALIGN_SIZE(sizeof(DYNAMIC_ARRAY))), MYF(0));
|
||||||
my_free((gptr) buffer,MYF(0));
|
my_free((gptr) buffer,MYF(0));
|
||||||
|
}
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
} /* my_dirend */
|
} /* my_dirend */
|
||||||
|
|
||||||
|
@ -91,14 +104,14 @@ static int comp_names(struct fileinfo *a, struct fileinfo *b)
|
||||||
|
|
||||||
MY_DIR *my_dir(const char *path, myf MyFlags)
|
MY_DIR *my_dir(const char *path, myf MyFlags)
|
||||||
{
|
{
|
||||||
|
char *buffer;
|
||||||
|
MY_DIR *result= 0;
|
||||||
|
FILEINFO finfo;
|
||||||
|
DYNAMIC_ARRAY *dir_entries_storage;
|
||||||
|
MEM_ROOT *names_storage;
|
||||||
DIR *dirp;
|
DIR *dirp;
|
||||||
struct dirent *dp;
|
struct dirent *dp;
|
||||||
struct fileinfo *fnames;
|
|
||||||
char *buffer, *obuffer, *tempptr;
|
|
||||||
uint fcnt,i,size,firstfcnt, maxfcnt,length;
|
|
||||||
char tmp_path[FN_REFLEN+1],*tmp_file;
|
char tmp_path[FN_REFLEN+1],*tmp_file;
|
||||||
my_ptrdiff_t diff;
|
|
||||||
bool eof;
|
|
||||||
#ifdef THREAD
|
#ifdef THREAD
|
||||||
char dirent_tmp[sizeof(struct dirent)+_POSIX_PATH_MAX+1];
|
char dirent_tmp[sizeof(struct dirent)+_POSIX_PATH_MAX+1];
|
||||||
#endif
|
#endif
|
||||||
|
@ -110,74 +123,72 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dirp = opendir(directory_file_name(tmp_path,(my_string) path));
|
dirp = opendir(directory_file_name(tmp_path,(my_string) path));
|
||||||
size = STARTSIZE;
|
|
||||||
#if defined(__amiga__)
|
#if defined(__amiga__)
|
||||||
if ((dirp->dd_fd) < 0) /* Directory doesn't exists */
|
if ((dirp->dd_fd) < 0) /* Directory doesn't exists */
|
||||||
goto error;
|
goto error;
|
||||||
#endif
|
#endif
|
||||||
if (dirp == NULL || ! (buffer = (char *) my_malloc(size, MyFlags)))
|
if (dirp == NULL ||
|
||||||
|
! (buffer= my_malloc(ALIGN_SIZE(sizeof(MY_DIR)) +
|
||||||
|
ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) +
|
||||||
|
sizeof(MEM_ROOT), MyFlags)))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
fcnt = 0;
|
dir_entries_storage= (DYNAMIC_ARRAY*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)));
|
||||||
|
names_storage= (MEM_ROOT*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)) +
|
||||||
|
ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)));
|
||||||
|
|
||||||
|
if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO),
|
||||||
|
ENTRIES_START_SIZE, ENTRIES_INCREMENT))
|
||||||
|
{
|
||||||
|
my_free((gptr) buffer,MYF(0));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE);
|
||||||
|
|
||||||
|
/* MY_DIR structure is allocated and completly initialized at this point */
|
||||||
|
result= (MY_DIR*)buffer;
|
||||||
|
|
||||||
tmp_file=strend(tmp_path);
|
tmp_file=strend(tmp_path);
|
||||||
firstfcnt = maxfcnt = (size - sizeof(MY_DIR)) /
|
|
||||||
(sizeof(struct fileinfo) + FN_LEN);
|
|
||||||
fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR));
|
|
||||||
tempptr = (char *) (fnames + maxfcnt);
|
|
||||||
|
|
||||||
#ifdef THREAD
|
#ifdef THREAD
|
||||||
dp= (struct dirent*) dirent_tmp;
|
dp= (struct dirent*) dirent_tmp;
|
||||||
#else
|
#else
|
||||||
dp=0;
|
dp=0;
|
||||||
#endif
|
#endif
|
||||||
eof=0;
|
|
||||||
for (;;)
|
while (!(READDIR(dirp,(struct dirent*) dirent_tmp,dp)))
|
||||||
{
|
{
|
||||||
while (fcnt < maxfcnt &&
|
if (!(finfo.name= strdup_root(names_storage, dp->d_name)))
|
||||||
!(eof= READDIR(dirp,(struct dirent*) dirent_tmp,dp)))
|
goto error;
|
||||||
|
|
||||||
|
if (MyFlags & MY_WANT_STAT)
|
||||||
{
|
{
|
||||||
bzero((gptr) (fnames+fcnt),sizeof(fnames[0])); /* for purify */
|
if (!(finfo.mystat= (MY_STAT*)alloc_root(names_storage,
|
||||||
fnames[fcnt].name = tempptr;
|
sizeof(MY_STAT))))
|
||||||
tempptr = strmov(tempptr,dp->d_name) + 1;
|
goto error;
|
||||||
if (MyFlags & MY_WANT_STAT)
|
|
||||||
{
|
bzero(finfo.mystat, sizeof(MY_STAT));
|
||||||
VOID(strmov(tmp_file,dp->d_name));
|
VOID(strmov(tmp_file,dp->d_name));
|
||||||
VOID(my_stat(tmp_path, &fnames[fcnt].mystat, MyFlags));
|
VOID(my_stat(tmp_path, finfo.mystat, MyFlags));
|
||||||
}
|
|
||||||
++fcnt;
|
|
||||||
}
|
}
|
||||||
if (eof)
|
else
|
||||||
break;
|
finfo.mystat= NULL;
|
||||||
size += STARTSIZE; obuffer = buffer;
|
|
||||||
if (!(buffer = (char *) my_realloc((gptr) buffer, size,
|
|
||||||
MyFlags | MY_FREE_ON_ERROR)))
|
|
||||||
goto error; /* No memory */
|
|
||||||
length= (uint) (sizeof(struct fileinfo ) * firstfcnt);
|
|
||||||
diff= PTR_BYTE_DIFF(buffer , obuffer) + (int) length;
|
|
||||||
fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR));
|
|
||||||
tempptr= ADD_TO_PTR(tempptr,diff,char*);
|
|
||||||
for (i = 0; i < maxfcnt; i++)
|
|
||||||
fnames[i].name = ADD_TO_PTR(fnames[i].name,diff,char*);
|
|
||||||
|
|
||||||
/* move filenames upp a bit */
|
if (push_dynamic(dir_entries_storage, (gptr)&finfo))
|
||||||
maxfcnt += firstfcnt;
|
goto error;
|
||||||
bmove_upp(tempptr,tempptr-length,
|
|
||||||
(uint) (tempptr- (char*) (fnames+maxfcnt)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) closedir(dirp);
|
(void) closedir(dirp);
|
||||||
{
|
|
||||||
MY_DIR * s = (MY_DIR *) buffer;
|
|
||||||
s->number_off_files = (uint) fcnt;
|
|
||||||
s->dir_entry = fnames;
|
|
||||||
}
|
|
||||||
if (!(MyFlags & MY_DONT_SORT))
|
|
||||||
qsort((void *) fnames, (size_s) fcnt, sizeof(struct fileinfo),
|
|
||||||
(qsort_cmp) comp_names);
|
|
||||||
#if defined(THREAD) && !defined(HAVE_READDIR_R)
|
#if defined(THREAD) && !defined(HAVE_READDIR_R)
|
||||||
pthread_mutex_unlock(&THR_LOCK_open);
|
pthread_mutex_unlock(&THR_LOCK_open);
|
||||||
#endif
|
#endif
|
||||||
DBUG_RETURN((MY_DIR *) buffer);
|
result->dir_entry= (FILEINFO *)dir_entries_storage->buffer;
|
||||||
|
result->number_off_files= dir_entries_storage->elements;
|
||||||
|
|
||||||
|
if (!(MyFlags & MY_DONT_SORT))
|
||||||
|
qsort((void *) result->dir_entry, result->number_off_files,
|
||||||
|
sizeof(FILEINFO), (qsort_cmp) comp_names);
|
||||||
|
DBUG_RETURN(result);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
#if defined(THREAD) && !defined(HAVE_READDIR_R)
|
#if defined(THREAD) && !defined(HAVE_READDIR_R)
|
||||||
|
@ -186,6 +197,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
|
||||||
my_errno=errno;
|
my_errno=errno;
|
||||||
if (dirp)
|
if (dirp)
|
||||||
(void) closedir(dirp);
|
(void) closedir(dirp);
|
||||||
|
my_dirend(result);
|
||||||
if (MyFlags & (MY_FAE | MY_WME))
|
if (MyFlags & (MY_FAE | MY_WME))
|
||||||
my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,my_errno);
|
my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,my_errno);
|
||||||
DBUG_RETURN((MY_DIR *) NULL);
|
DBUG_RETURN((MY_DIR *) NULL);
|
||||||
|
@ -349,10 +361,11 @@ my_string directory_file_name (my_string dst, const char *src)
|
||||||
|
|
||||||
MY_DIR *my_dir(const char *path, myf MyFlags)
|
MY_DIR *my_dir(const char *path, myf MyFlags)
|
||||||
{
|
{
|
||||||
struct fileinfo *fnames;
|
char *buffer;
|
||||||
char *buffer, *obuffer, *tempptr;
|
MY_DIR *result= 0;
|
||||||
int eof,i,fcnt,firstfcnt,length,maxfcnt;
|
FILEINFO finfo;
|
||||||
uint size;
|
DYNAMIC_ARRAY *dir_entries_storage;
|
||||||
|
MEM_ROOT *names_storage;
|
||||||
#ifdef __BORLANDC__
|
#ifdef __BORLANDC__
|
||||||
struct ffblk find;
|
struct ffblk find;
|
||||||
#else
|
#else
|
||||||
|
@ -360,7 +373,6 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
|
||||||
#endif
|
#endif
|
||||||
ushort mode;
|
ushort mode;
|
||||||
char tmp_path[FN_REFLEN],*tmp_file,attrib;
|
char tmp_path[FN_REFLEN],*tmp_file,attrib;
|
||||||
my_ptrdiff_t diff;
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
__int64 handle;
|
__int64 handle;
|
||||||
#else
|
#else
|
||||||
|
@ -392,85 +404,88 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
|
||||||
goto error;
|
goto error;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
size = STARTSIZE;
|
if (!(buffer= my_malloc(ALIGN_SIZE(sizeof(MY_DIR)) +
|
||||||
firstfcnt = maxfcnt = (size - sizeof(MY_DIR)) /
|
ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) +
|
||||||
(sizeof(struct fileinfo) + FN_LEN);
|
sizeof(MEM_ROOT), MyFlags)))
|
||||||
if ((buffer = (char *) my_malloc(size, MyFlags)) == 0)
|
|
||||||
goto error;
|
goto error;
|
||||||
fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR));
|
|
||||||
tempptr = (char *) (fnames + maxfcnt);
|
|
||||||
|
|
||||||
fcnt = 0;
|
dir_entries_storage= (DYNAMIC_ARRAY*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)));
|
||||||
for (;;)
|
names_storage= (MEM_ROOT*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)) +
|
||||||
|
ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)));
|
||||||
|
|
||||||
|
if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO),
|
||||||
|
ENTRIES_START_SIZE, ENTRIES_INCREMENT))
|
||||||
|
{
|
||||||
|
my_free((gptr) buffer,MYF(0));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE);
|
||||||
|
|
||||||
|
/* MY_DIR structure is allocated and completly initialized at this point */
|
||||||
|
result= (MY_DIR*)buffer;
|
||||||
|
|
||||||
|
do
|
||||||
{
|
{
|
||||||
do
|
|
||||||
{
|
|
||||||
fnames[fcnt].name = tempptr;
|
|
||||||
#ifdef __BORLANDC__
|
#ifdef __BORLANDC__
|
||||||
tempptr = strmov(tempptr,find.ff_name) + 1;
|
if (!(finfo.name= strdup_root(names_storage, find.ff_name)))
|
||||||
fnames[fcnt].mystat.st_size=find.ff_fsize;
|
goto error;
|
||||||
fnames[fcnt].mystat.st_uid=fnames[fcnt].mystat.st_gid=0;
|
#else
|
||||||
|
if (!(finfo.name= strdup_root(names_storage, find.name)))
|
||||||
|
goto error;
|
||||||
|
#endif
|
||||||
|
if (MyFlags & MY_WANT_STAT)
|
||||||
|
{
|
||||||
|
if (!(finfo.mystat= (MY_STAT*)alloc_root(names_storage,
|
||||||
|
sizeof(MY_STAT))))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
bzero(finfo.mystat, sizeof(MY_STAT));
|
||||||
|
#ifdef __BORLANDC__
|
||||||
|
finfo.mystat->st_size=find.ff_fsize;
|
||||||
mode=MY_S_IREAD; attrib=find.ff_attrib;
|
mode=MY_S_IREAD; attrib=find.ff_attrib;
|
||||||
#else
|
#else
|
||||||
tempptr = strmov(tempptr,find.name) + 1;
|
finfo.mystat->st_size=find.size;
|
||||||
fnames[fcnt].mystat.st_size=find.size;
|
|
||||||
fnames[fcnt].mystat.st_uid=fnames[fcnt].mystat.st_gid=0;
|
|
||||||
mode=MY_S_IREAD; attrib=find.attrib;
|
mode=MY_S_IREAD; attrib=find.attrib;
|
||||||
#endif
|
#endif
|
||||||
if (!(attrib & _A_RDONLY))
|
if (!(attrib & _A_RDONLY))
|
||||||
mode|=MY_S_IWRITE;
|
mode|=MY_S_IWRITE;
|
||||||
if (attrib & _A_SUBDIR)
|
if (attrib & _A_SUBDIR)
|
||||||
mode|=MY_S_IFDIR;
|
mode|=MY_S_IFDIR;
|
||||||
fnames[fcnt].mystat.st_mode=mode;
|
finfo.mystat->st_mode=mode;
|
||||||
#ifdef __BORLANDC__
|
#ifdef __BORLANDC__
|
||||||
fnames[fcnt].mystat.st_mtime=((uint32) find.ff_ftime);
|
finfo.mystat->st_mtime=((uint32) find.ff_ftime);
|
||||||
#else
|
#else
|
||||||
fnames[fcnt].mystat.st_mtime=((uint32) find.time_write);
|
finfo.mystat->st_mtime=((uint32) find.time_write);
|
||||||
#endif
|
|
||||||
++fcnt;
|
|
||||||
#ifdef __BORLANDC__
|
|
||||||
} while ((eof= findnext(&find)) == 0 && fcnt < maxfcnt);
|
|
||||||
#else
|
|
||||||
} while ((eof= _findnext(handle,&find)) == 0 && fcnt < maxfcnt);
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
finfo.mystat= NULL;
|
||||||
|
|
||||||
DBUG_PRINT("test",("eof: %d errno: %d",eof,errno));
|
if (push_dynamic(dir_entries_storage, (gptr)&finfo))
|
||||||
if (eof)
|
|
||||||
break;
|
|
||||||
size += STARTSIZE; obuffer = buffer;
|
|
||||||
if (!(buffer = (char *) my_realloc((gptr) buffer, size,
|
|
||||||
MyFlags | MY_FREE_ON_ERROR)))
|
|
||||||
goto error;
|
goto error;
|
||||||
length= sizeof(struct fileinfo ) * firstfcnt;
|
|
||||||
diff= PTR_BYTE_DIFF(buffer , obuffer) +length;
|
#ifdef __BORLANDC__
|
||||||
fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR));
|
} while (findnext(&find) == 0);
|
||||||
tempptr= ADD_TO_PTR(tempptr,diff,char*);
|
#else
|
||||||
for (i = 0; i < maxfcnt; i++)
|
} while (_findnext(handle,&find) == 0);
|
||||||
fnames[i].name = ADD_TO_PTR(fnames[i].name,diff,char*);
|
|
||||||
|
|
||||||
/* move filenames upp a bit */
|
|
||||||
maxfcnt += firstfcnt;
|
|
||||||
bmove_upp(tempptr,ADD_TO_PTR(tempptr,-length,char*),
|
|
||||||
(int) PTR_BYTE_DIFF(tempptr,fnames+maxfcnt));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
MY_DIR * s = (MY_DIR *) buffer;
|
|
||||||
s->number_off_files = (uint) fcnt;
|
|
||||||
s->dir_entry = fnames;
|
|
||||||
}
|
|
||||||
if (!(MyFlags & MY_DONT_SORT))
|
|
||||||
qsort(fnames,fcnt,sizeof(struct fileinfo),(qsort_cmp) comp_names);
|
|
||||||
#ifndef __BORLANDC__
|
|
||||||
_findclose(handle);
|
_findclose(handle);
|
||||||
#endif
|
#endif
|
||||||
DBUG_RETURN((MY_DIR *) buffer);
|
|
||||||
|
|
||||||
|
result->dir_entry= (FILEINFO *)dir_entries_storage->buffer;
|
||||||
|
result->number_off_files= dir_entries_storage->elements;
|
||||||
|
|
||||||
|
if (!(MyFlags & MY_DONT_SORT))
|
||||||
|
qsort((void *) result->dir_entry, result->number_off_files,
|
||||||
|
sizeof(FILEINFO), (qsort_cmp) comp_names);
|
||||||
|
DBUG_RETURN(result);
|
||||||
error:
|
error:
|
||||||
my_errno=errno;
|
my_errno=errno;
|
||||||
#ifndef __BORLANDC__
|
#ifndef __BORLANDC__
|
||||||
if (handle != -1)
|
if (handle != -1)
|
||||||
_findclose(handle);
|
_findclose(handle);
|
||||||
#endif
|
#endif
|
||||||
|
my_dirend(result);
|
||||||
if (MyFlags & MY_FAE+MY_WME)
|
if (MyFlags & MY_FAE+MY_WME)
|
||||||
my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,errno);
|
my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,errno);
|
||||||
DBUG_RETURN((MY_DIR *) NULL);
|
DBUG_RETURN((MY_DIR *) NULL);
|
||||||
|
@ -485,14 +500,14 @@ error:
|
||||||
|
|
||||||
MY_DIR *my_dir(const char* path, myf MyFlags)
|
MY_DIR *my_dir(const char* path, myf MyFlags)
|
||||||
{
|
{
|
||||||
struct fileinfo *fnames;
|
char *buffer;
|
||||||
char *buffer, *obuffer, *tempptr;
|
MY_DIR *result= 0;
|
||||||
int eof,i,fcnt,firstfcnt,length,maxfcnt;
|
FILEINFO finfo;
|
||||||
uint size;
|
DYNAMIC_ARRAY *dir_entries_storage;
|
||||||
|
MEM_ROOT *names_storage;
|
||||||
struct find_t find;
|
struct find_t find;
|
||||||
ushort mode;
|
ushort mode;
|
||||||
char tmp_path[FN_REFLEN],*tmp_file,attrib;
|
char tmp_path[FN_REFLEN],*tmp_file,attrib;
|
||||||
my_ptrdiff_t diff;
|
|
||||||
DBUG_ENTER("my_dir");
|
DBUG_ENTER("my_dir");
|
||||||
DBUG_PRINT("my",("path: '%s' stat: %d MyFlags: %d",path,MyFlags));
|
DBUG_PRINT("my",("path: '%s' stat: %d MyFlags: %d",path,MyFlags));
|
||||||
|
|
||||||
|
@ -514,63 +529,65 @@ MY_DIR *my_dir(const char* path, myf MyFlags)
|
||||||
if (_dos_findfirst(tmp_path,_A_NORMAL | _A_SUBDIR, &find))
|
if (_dos_findfirst(tmp_path,_A_NORMAL | _A_SUBDIR, &find))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
size = STARTSIZE;
|
if (!(buffer= my_malloc(ALIGN_SIZE(sizeof(MY_DIR)) +
|
||||||
firstfcnt = maxfcnt = (size - sizeof(MY_DIR)) /
|
ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) +
|
||||||
(sizeof(struct fileinfo) + FN_LEN);
|
sizeof(MEM_ROOT), MyFlags)))
|
||||||
if ((buffer = (char *) my_malloc(size, MyFlags)) == 0)
|
|
||||||
goto error;
|
goto error;
|
||||||
fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR));
|
|
||||||
tempptr = (char *) (fnames + maxfcnt);
|
|
||||||
|
|
||||||
fcnt = 0;
|
dir_entries_storage= (DYNAMIC_ARRAY*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)));
|
||||||
for (;;)
|
names_storage= (MEM_ROOT*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)) +
|
||||||
|
ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)));
|
||||||
|
|
||||||
|
if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO),
|
||||||
|
ENTRIES_START_SIZE, ENTRIES_INCREMENT))
|
||||||
{
|
{
|
||||||
do
|
my_free((gptr) buffer,MYF(0));
|
||||||
{
|
goto error;
|
||||||
fnames[fcnt].name = tempptr;
|
}
|
||||||
tempptr = strmov(tempptr,find.name) + 1;
|
init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE);
|
||||||
fnames[fcnt].mystat.st_size=find.size;
|
|
||||||
fnames[fcnt].mystat.st_uid=fnames[fcnt].mystat.st_gid=0;
|
/* MY_DIR structure is allocated and completly initialized at this point */
|
||||||
mode=MY_S_IREAD; attrib=find.attrib;
|
result= (MY_DIR*)buffer;
|
||||||
if (!(attrib & _A_RDONLY))
|
|
||||||
mode|=MY_S_IWRITE;
|
do
|
||||||
if (attrib & _A_SUBDIR)
|
{
|
||||||
mode|=MY_S_IFDIR;
|
if (!(finfo.name= strdup_root(names_storage, find.name)))
|
||||||
fnames[fcnt].mystat.st_mode=mode;
|
|
||||||
fnames[fcnt].mystat.st_mtime=((uint32) find.wr_date << 16) +
|
|
||||||
find.wr_time;
|
|
||||||
++fcnt;
|
|
||||||
} while ((eof= _dos_findnext(&find)) == 0 && fcnt < maxfcnt);
|
|
||||||
|
|
||||||
DBUG_PRINT("test",("eof: %d errno: %d",eof,errno));
|
|
||||||
if (eof)
|
|
||||||
break;
|
|
||||||
size += STARTSIZE; obuffer = buffer;
|
|
||||||
if (!(buffer = (char *) my_realloc((gptr) buffer, size,
|
|
||||||
MyFlags | MY_FREE_ON_ERROR)))
|
|
||||||
goto error;
|
goto error;
|
||||||
length= sizeof(struct fileinfo ) * firstfcnt;
|
|
||||||
diff= PTR_BYTE_DIFF(buffer , obuffer) +length;
|
if (MyFlags & MY_WANT_STAT)
|
||||||
fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR));
|
{
|
||||||
tempptr= ADD_TO_PTR(tempptr,diff,char*);
|
if (!(finfo.mystat= (MY_STAT*)alloc_root(names_storage,
|
||||||
for (i = 0; i < maxfcnt; i++)
|
sizeof(MY_STAT))))
|
||||||
fnames[i].name = ADD_TO_PTR(fnames[i].name,diff,char*);
|
goto error;
|
||||||
|
|
||||||
|
bzero(finfo.mystat, sizeof(MY_STAT));
|
||||||
|
finfo.mystat->st_size= find.size;
|
||||||
|
mode= MY_S_IREAD; attrib= find.attrib;
|
||||||
|
if (!(attrib & _A_RDONLY))
|
||||||
|
mode|= MY_S_IWRITE;
|
||||||
|
if (attrib & _A_SUBDIR)
|
||||||
|
mode|= MY_S_IFDIR;
|
||||||
|
finfo.mystat->st_mode= mode;
|
||||||
|
finfo.mystat->st_mtime= ((uint32) find.wr_date << 16) + find.wr_time;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
finfo.mystat= NULL;
|
||||||
|
|
||||||
/* move filenames upp a bit */
|
if (push_dynamic(dir_entries_storage, (gptr)&finfo))
|
||||||
maxfcnt += firstfcnt;
|
goto error;
|
||||||
bmove_upp(tempptr,ADD_TO_PTR(tempptr,-length,char*),
|
|
||||||
(int) PTR_BYTE_DIFF(tempptr,fnames+maxfcnt));
|
} while (_dos_findnext(&find) == 0);
|
||||||
}
|
|
||||||
{
|
result->dir_entry= (FILEINFO *)dir_entries_storage->buffer;
|
||||||
MY_DIR * s = (MY_DIR *) buffer;
|
result->number_off_files= dir_entries_storage->elements;
|
||||||
s->number_off_files = (uint) fcnt;
|
|
||||||
s->dir_entry = fnames;
|
|
||||||
}
|
|
||||||
if (!(MyFlags & MY_DONT_SORT))
|
if (!(MyFlags & MY_DONT_SORT))
|
||||||
qsort(fnames,fcnt,sizeof(struct fileinfo),(qsort_cmp) comp_names);
|
qsort((void *) result->dir_entry, result->number_off_files,
|
||||||
DBUG_RETURN((MY_DIR *) buffer);
|
sizeof(FILEINFO), (qsort_cmp) comp_names);
|
||||||
|
DBUG_RETURN(result);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
my_dirend(result);
|
||||||
if (MyFlags & MY_FAE+MY_WME)
|
if (MyFlags & MY_FAE+MY_WME)
|
||||||
my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,errno);
|
my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,errno);
|
||||||
DBUG_RETURN((MY_DIR *) NULL);
|
DBUG_RETURN((MY_DIR *) NULL);
|
||||||
|
|
|
@ -213,7 +213,7 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (file->name[0] == '.' || !MY_S_ISDIR(file->mystat.st_mode) ||
|
if (file->name[0] == '.' || !MY_S_ISDIR(file->mystat->st_mode) ||
|
||||||
(wild && wild_compare(file->name,wild)))
|
(wild && wild_compare(file->name,wild)))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue