summaryrefslogtreecommitdiff
path: root/mysys/my_lib.c
diff options
context:
space:
mode:
authorunknown <dlenev@mysql.com>2003-12-12 03:39:29 +0300
committerunknown <dlenev@mysql.com>2003-12-12 03:39:29 +0300
commitc545b02645cbc09e33a211955a8dbcc09a994b77 (patch)
tree27e4c621a8cb1797bd140a3d7b363f4e2eb8629c /mysys/my_lib.c
parent22c12eaeb296b55d6121531bea44a97fb5297f04 (diff)
downloadmariadb-git-c545b02645cbc09e33a211955a8dbcc09a994b77.tar.gz
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.
Diffstat (limited to 'mysys/my_lib.c')
-rw-r--r--mysys/my_lib.c339
1 files changed, 178 insertions, 161 deletions
diff --git a/mysys/my_lib.c b/mysys/my_lib.c
index 426acedc646..055e00d2efc 100644
--- a/mysys/my_lib.c
+++ b/mysys/my_lib.c
@@ -62,8 +62,15 @@
#define READDIR(A,B,C) (!(C=readdir(A)))
#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);
@@ -74,7 +81,13 @@ void my_dirend(MY_DIR *buffer)
{
DBUG_ENTER("my_dirend");
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));
+ }
DBUG_VOID_RETURN;
} /* 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)
{
+ char *buffer;
+ MY_DIR *result= 0;
+ FILEINFO finfo;
+ DYNAMIC_ARRAY *dir_entries_storage;
+ MEM_ROOT *names_storage;
DIR *dirp;
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;
- my_ptrdiff_t diff;
- bool eof;
#ifdef THREAD
char dirent_tmp[sizeof(struct dirent)+_POSIX_PATH_MAX+1];
#endif
@@ -110,74 +123,72 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
#endif
dirp = opendir(directory_file_name(tmp_path,(my_string) path));
- size = STARTSIZE;
#if defined(__amiga__)
if ((dirp->dd_fd) < 0) /* Directory doesn't exists */
goto error;
#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;
+
+ 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;
- fcnt = 0;
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
dp= (struct dirent*) dirent_tmp;
#else
dp=0;
#endif
- eof=0;
- for (;;)
+
+ while (!(READDIR(dirp,(struct dirent*) dirent_tmp,dp)))
{
- while (fcnt < maxfcnt &&
- !(eof= READDIR(dirp,(struct dirent*) dirent_tmp,dp)))
+ if (!(finfo.name= strdup_root(names_storage, dp->d_name)))
+ goto error;
+
+ if (MyFlags & MY_WANT_STAT)
{
- bzero((gptr) (fnames+fcnt),sizeof(fnames[0])); /* for purify */
- fnames[fcnt].name = tempptr;
- tempptr = strmov(tempptr,dp->d_name) + 1;
- if (MyFlags & MY_WANT_STAT)
- {
- VOID(strmov(tmp_file,dp->d_name));
- VOID(my_stat(tmp_path, &fnames[fcnt].mystat, MyFlags));
- }
- ++fcnt;
+ if (!(finfo.mystat= (MY_STAT*)alloc_root(names_storage,
+ sizeof(MY_STAT))))
+ goto error;
+
+ bzero(finfo.mystat, sizeof(MY_STAT));
+ VOID(strmov(tmp_file,dp->d_name));
+ VOID(my_stat(tmp_path, finfo.mystat, MyFlags));
}
- if (eof)
- break;
- 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 */
- maxfcnt += firstfcnt;
- bmove_upp(tempptr,tempptr-length,
- (uint) (tempptr- (char*) (fnames+maxfcnt)));
+ else
+ finfo.mystat= NULL;
+
+ if (push_dynamic(dir_entries_storage, (gptr)&finfo))
+ goto error;
}
(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)
pthread_mutex_unlock(&THR_LOCK_open);
#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:
#if defined(THREAD) && !defined(HAVE_READDIR_R)
@@ -186,6 +197,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
my_errno=errno;
if (dirp)
(void) closedir(dirp);
+ my_dirend(result);
if (MyFlags & (MY_FAE | MY_WME))
my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,my_errno);
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)
{
- struct fileinfo *fnames;
- char *buffer, *obuffer, *tempptr;
- int eof,i,fcnt,firstfcnt,length,maxfcnt;
- uint size;
+ char *buffer;
+ MY_DIR *result= 0;
+ FILEINFO finfo;
+ DYNAMIC_ARRAY *dir_entries_storage;
+ MEM_ROOT *names_storage;
#ifdef __BORLANDC__
struct ffblk find;
#else
@@ -360,7 +373,6 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
#endif
ushort mode;
char tmp_path[FN_REFLEN],*tmp_file,attrib;
- my_ptrdiff_t diff;
#ifdef _WIN64
__int64 handle;
#else
@@ -392,85 +404,88 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
goto error;
#endif
- size = STARTSIZE;
- firstfcnt = maxfcnt = (size - sizeof(MY_DIR)) /
- (sizeof(struct fileinfo) + FN_LEN);
- if ((buffer = (char *) my_malloc(size, MyFlags)) == 0)
+ if (!(buffer= my_malloc(ALIGN_SIZE(sizeof(MY_DIR)) +
+ ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) +
+ sizeof(MEM_ROOT), MyFlags)))
goto error;
- fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR));
- tempptr = (char *) (fnames + maxfcnt);
- fcnt = 0;
- for (;;)
+ 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))
{
- do
+ 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
+ {
+#ifdef __BORLANDC__
+ if (!(finfo.name= strdup_root(names_storage, find.ff_name)))
+ goto error;
+#else
+ if (!(finfo.name= strdup_root(names_storage, find.name)))
+ goto error;
+#endif
+ if (MyFlags & MY_WANT_STAT)
{
- fnames[fcnt].name = tempptr;
+ if (!(finfo.mystat= (MY_STAT*)alloc_root(names_storage,
+ sizeof(MY_STAT))))
+ goto error;
+
+ bzero(finfo.mystat, sizeof(MY_STAT));
#ifdef __BORLANDC__
- tempptr = strmov(tempptr,find.ff_name) + 1;
- fnames[fcnt].mystat.st_size=find.ff_fsize;
- fnames[fcnt].mystat.st_uid=fnames[fcnt].mystat.st_gid=0;
+ finfo.mystat->st_size=find.ff_fsize;
mode=MY_S_IREAD; attrib=find.ff_attrib;
#else
- tempptr = strmov(tempptr,find.name) + 1;
- fnames[fcnt].mystat.st_size=find.size;
- fnames[fcnt].mystat.st_uid=fnames[fcnt].mystat.st_gid=0;
+ finfo.mystat->st_size=find.size;
mode=MY_S_IREAD; attrib=find.attrib;
#endif
if (!(attrib & _A_RDONLY))
mode|=MY_S_IWRITE;
if (attrib & _A_SUBDIR)
mode|=MY_S_IFDIR;
- fnames[fcnt].mystat.st_mode=mode;
+ finfo.mystat->st_mode=mode;
#ifdef __BORLANDC__
- fnames[fcnt].mystat.st_mtime=((uint32) find.ff_ftime);
+ finfo.mystat->st_mtime=((uint32) find.ff_ftime);
#else
- fnames[fcnt].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);
+ finfo.mystat->st_mtime=((uint32) find.time_write);
#endif
+ }
+ else
+ finfo.mystat= NULL;
- 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)))
+ if (push_dynamic(dir_entries_storage, (gptr)&finfo))
goto error;
- length= sizeof(struct fileinfo ) * firstfcnt;
- diff= PTR_BYTE_DIFF(buffer , obuffer) +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 */
- 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__
+
+#ifdef __BORLANDC__
+ } while (findnext(&find) == 0);
+#else
+ } while (_findnext(handle,&find) == 0);
+
_findclose(handle);
#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:
my_errno=errno;
#ifndef __BORLANDC__
if (handle != -1)
_findclose(handle);
#endif
+ my_dirend(result);
if (MyFlags & MY_FAE+MY_WME)
my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,errno);
DBUG_RETURN((MY_DIR *) NULL);
@@ -485,14 +500,14 @@ error:
MY_DIR *my_dir(const char* path, myf MyFlags)
{
- struct fileinfo *fnames;
- char *buffer, *obuffer, *tempptr;
- int eof,i,fcnt,firstfcnt,length,maxfcnt;
- uint size;
+ char *buffer;
+ MY_DIR *result= 0;
+ FILEINFO finfo;
+ DYNAMIC_ARRAY *dir_entries_storage;
+ MEM_ROOT *names_storage;
struct find_t find;
ushort mode;
char tmp_path[FN_REFLEN],*tmp_file,attrib;
- my_ptrdiff_t diff;
DBUG_ENTER("my_dir");
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))
goto error;
- size = STARTSIZE;
- firstfcnt = maxfcnt = (size - sizeof(MY_DIR)) /
- (sizeof(struct fileinfo) + FN_LEN);
- if ((buffer = (char *) my_malloc(size, MyFlags)) == 0)
+ if (!(buffer= my_malloc(ALIGN_SIZE(sizeof(MY_DIR)) +
+ ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) +
+ sizeof(MEM_ROOT), MyFlags)))
goto error;
- fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR));
- tempptr = (char *) (fnames + maxfcnt);
- fcnt = 0;
- for (;;)
+ 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))
{
- do
+ 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
+ {
+ if (!(finfo.name= strdup_root(names_storage, find.name)))
+ goto error;
+
+ if (MyFlags & MY_WANT_STAT)
{
- fnames[fcnt].name = tempptr;
- tempptr = strmov(tempptr,find.name) + 1;
- 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;
+ if (!(finfo.mystat= (MY_STAT*)alloc_root(names_storage,
+ sizeof(MY_STAT))))
+ 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;
+ mode|= MY_S_IWRITE;
if (attrib & _A_SUBDIR)
- mode|=MY_S_IFDIR;
- 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)))
+ 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;
+
+ if (push_dynamic(dir_entries_storage, (gptr)&finfo))
goto error;
- length= sizeof(struct fileinfo ) * firstfcnt;
- diff= PTR_BYTE_DIFF(buffer , obuffer) +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 */
- 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;
- }
+
+ } while (_dos_findnext(&find) == 0);
+
+ result->dir_entry= (FILEINFO *)dir_entries_storage->buffer;
+ result->number_off_files= dir_entries_storage->elements;
+
if (!(MyFlags & MY_DONT_SORT))
- qsort(fnames,fcnt,sizeof(struct fileinfo),(qsort_cmp) comp_names);
- DBUG_RETURN((MY_DIR *) buffer);
+ qsort((void *) result->dir_entry, result->number_off_files,
+ sizeof(FILEINFO), (qsort_cmp) comp_names);
+ DBUG_RETURN(result);
error:
+ my_dirend(result);
if (MyFlags & MY_FAE+MY_WME)
my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,errno);
DBUG_RETURN((MY_DIR *) NULL);