summaryrefslogtreecommitdiff
path: root/mysys/mf_iocache.c
diff options
context:
space:
mode:
authorserg@serg.mysql.com <>2002-06-20 00:55:06 +0000
committerserg@serg.mysql.com <>2002-06-20 00:55:06 +0000
commit099d78d4cbf82dc06e64af7d6ed502a9fe373d88 (patch)
tree43061efc1a2e3133b918b0781d0834c651e539a1 /mysys/mf_iocache.c
parenta3538124d76a53c35f016fb82fc1bd471a957527 (diff)
parent5c83ae3fca5a3a56eb31a6827dae0779a94e52b8 (diff)
downloadmariadb-git-099d78d4cbf82dc06e64af7d6ed502a9fe373d88.tar.gz
resolving
Diffstat (limited to 'mysys/mf_iocache.c')
-rw-r--r--mysys/mf_iocache.c118
1 files changed, 110 insertions, 8 deletions
diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c
index 54dfaf6d993..1a761fa5ed8 100644
--- a/mysys/mf_iocache.c
+++ b/mysys/mf_iocache.c
@@ -86,7 +86,11 @@ init_functions(IO_CACHE* info, enum cache_type type)
info->write_function = 0; /* Force a core if used */
break;
default:
- info->read_function = _my_b_read;
+ info->read_function =
+#ifdef THREAD
+ info->share ? _my_b_read_r :
+#endif
+ _my_b_read;
info->write_function = _my_b_write;
}
@@ -126,6 +130,9 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize,
info->alloced_buffer = 0;
info->buffer=0;
info->seek_not_done= test(file >= 0);
+#ifdef THREAD
+ info->share=0;
+#endif
if (!cachesize)
if (! (cachesize= my_default_record_cache_size))
@@ -213,7 +220,6 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize,
DBUG_RETURN(0);
} /* init_io_cache */
-
/* Wait until current request is ready */
#ifdef HAVE_AIOWAIT
@@ -418,6 +424,90 @@ int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count)
DBUG_RETURN(0);
}
+#ifdef THREAD
+int init_io_cache_share(IO_CACHE *info, IO_CACHE_SHARE *s, uint num_threads)
+{
+ DBUG_ASSERT(info->type == READ_CACHE);
+ pthread_mutex_init(& s->mutex, MY_MUTEX_INIT_FAST);
+ pthread_cond_init (& s->cond, 0);
+ s->count=num_threads;
+ s->active=0; /* to catch errors */
+ info->share=s;
+ info->read_function=_my_b_read_r;
+}
+
+int remove_io_thread(IO_CACHE *info)
+{
+ if (errno=pthread_mutex_lock(& info->share->mutex))
+ return -1;
+ if (! info->share->count--)
+ pthread_cond_signal(& info->share->cond);
+ pthread_mutex_unlock(& info->share->mutex);
+ return 0;
+}
+
+int _my_b_read_r(register IO_CACHE *info, byte *Buffer, uint Count)
+{
+ my_off_t pos_in_file;
+ int length,diff_length,read_len;
+ DBUG_ENTER("_my_b_read_r");
+
+ if ((read_len=(uint) (info->read_end-info->read_pos)))
+ {
+ DBUG_ASSERT(Count >= read_len); /* User is not using my_b_read() */
+ memcpy(Buffer,info->read_pos, (size_t) (read_len));
+ Buffer+=read_len;
+ Count-=read_len;
+ }
+
+#define IO_ROUND_UP(X) (((X)+IO_SIZE-1) & ~(IO_SIZE-1))
+#define IO_ROUND_DN(X) ( (X) & ~(IO_SIZE-1))
+
+ while (Count) {
+ int cnt, len;
+
+ pos_in_file= info->pos_in_file + (uint)(info->read_end - info->buffer);
+ diff_length= pos_in_file & (IO_SIZE-1);
+ length=IO_ROUND_UP(Count+diff_length)-diff_length;
+ length=(length <= info->read_length) ?
+ length + IO_ROUND_DN(info->read_length - length) :
+ length - IO_ROUND_UP(length - info->read_length) ;
+ if (lock_io_cache(info))
+ {
+ info->share->active=info;
+ if (info->seek_not_done) /* File touched, do seek */
+ VOID(my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)));
+ len=my_read(info->file,info->buffer, length, info->myflags);
+ info->read_end=info->buffer + (len == -1 ? 0 : len);
+ info->error=(len == length ? 0 : len);
+ info->pos_in_file=pos_in_file;
+ unlock_io_cache(info);
+ }
+ else
+ {
+ info->error= info->share->active->error;
+ info->read_end= info->share->active->read_end;
+ info->pos_in_file= info->share->active->pos_in_file;
+ len= (info->error == -1 ? -1 : info->read_end-info->buffer);
+ }
+ info->read_pos=info->buffer;
+ info->seek_not_done=0;
+ if (info->error)
+ {
+ info->error=read_len;
+ DBUG_RETURN(1);
+ }
+ cnt=(len > Count) ? Count : len;
+ memcpy(Buffer,info->read_pos, (size_t)cnt);
+ Count -=cnt;
+ Buffer+=cnt;
+ read_len+=cnt;
+ info->read_pos+=cnt;
+ }
+ DBUG_RETURN(0);
+}
+#endif
+
/*
Do sequential read from the SEQ_READ_APPEND cache
we do this in three stages:
@@ -453,7 +543,7 @@ int _my_b_seq_read(register IO_CACHE *info, byte *Buffer, uint Count)
*/
VOID(my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)));
info->seek_not_done=0;
-
+
diff_length=(uint) (pos_in_file & (IO_SIZE-1));
/* now the second stage begins - read from file descriptor */
@@ -509,7 +599,7 @@ int _my_b_seq_read(register IO_CACHE *info, byte *Buffer, uint Count)
memcpy(Buffer,info->buffer,(size_t) length);
Count -= length;
Buffer += length;
-
+
/*
added the line below to make
DBUG_ASSERT(pos_in_file==info->end_of_file) pass.
@@ -543,7 +633,7 @@ read_append_buffer:
/*
TODO: figure out if the assert below is needed or correct.
*/
- DBUG_ASSERT(pos_in_file == info->end_of_file);
+ DBUG_ASSERT(pos_in_file == info->end_of_file);
copy_len=min(Count, len_in_buff);
memcpy(Buffer, info->append_read_pos, copy_len);
info->append_read_pos += copy_len;
@@ -909,7 +999,7 @@ int _flush_io_cache(IO_CACHE *info, int need_append_buffer_lock)
if (!(append_cache = (info->type == SEQ_READ_APPEND)))
need_append_buffer_lock=0;
-
+
if (info->type == WRITE_CACHE || append_cache)
{
if (info->file == -1)
@@ -918,7 +1008,7 @@ int _flush_io_cache(IO_CACHE *info, int need_append_buffer_lock)
DBUG_RETURN((info->error= -1));
}
LOCK_APPEND_BUFFER;
-
+
if ((length=(uint) (info->write_pos - info->write_buffer)))
{
pos_in_file=info->pos_in_file;
@@ -955,7 +1045,7 @@ int _flush_io_cache(IO_CACHE *info, int need_append_buffer_lock)
info->end_of_file+=(info->write_pos-info->append_read_pos);
DBUG_ASSERT(info->end_of_file == my_tell(info->file,MYF(0)));
}
-
+
info->append_read_pos=info->write_pos=info->write_buffer;
UNLOCK_APPEND_BUFFER;
DBUG_RETURN(info->error);
@@ -979,6 +1069,18 @@ int end_io_cache(IO_CACHE *info)
IO_CACHE_CALLBACK pre_close;
DBUG_ENTER("end_io_cache");
+#ifdef THREAD
+ /* simple protection against multi-close: destroying share first */
+ if (info->share)
+ if (pthread_cond_destroy (& info->share->cond) |
+ pthread_mutex_destroy(& info->share->mutex))
+ {
+ DBUG_RETURN(1);
+ }
+ else
+ info->share=0;
+#endif
+
if ((pre_close=info->pre_close))
(*pre_close)(info);
if (info->alloced_buffer)