Add support for Gemini table handler, Monty has checked and approved

Fix bug when read return error
parent 3c484480
monty@tik.mysql.fi
mikef@nslinux.bedford.progress.com
......@@ -117,6 +117,9 @@
/* POSIX readdir_r */
#undef HAVE_READDIR_R
/* Have Gemini db installed */
#undef HAVE_GEMINI_DB
/* POSIX sigwait */
#undef HAVE_SIGWAIT
......
......@@ -941,6 +941,92 @@ dnl ---------------------------------------------------------------------------
dnl END OF MYSQL_CHECK_INNOBASE SECTION
dnl ---------------------------------------------------------------------------
dnl ---------------------------------------------------------------------------
dnl Macro: MYSQL_CHECK_GEMINI
dnl Sets HAVE_GEMINI_DB if --with-gemini is used
dnl ---------------------------------------------------------------------------
AC_DEFUN([MYSQL_CHECK_GEMINI], [
AC_ARG_WITH([gemini],
[\
--with-gemini[=DIR] Use Gemini DB located in DIR],
[gemini="$withval"],
[gemini=no])
AC_MSG_CHECKING([for Gemini DB])
dnl SORT OUT THE SUPPLIED ARGUMENTS TO DETERMINE WHAT TO DO
dnl echo "DBG_GEM1: gemini='$gemini'"
have_gemini_db=no
gemini_includes=
gemini_libs=
case "$gemini" in
no )
AC_MSG_RESULT([Not using Gemini DB])
;;
yes | default | *)
have_gemini_db="yes"
gemini_includes="-I../gemini/incl -I../gemini"
gemini_libs="\
../gemini/api/libapi.a\
../gemini/db/libdb.a\
../gemini/dbut/libdbut.a\
../gemini/vst/libvst.a"
AC_MSG_RESULT([Using Gemini DB])
;;
esac
AC_SUBST(gemini_includes)
AC_SUBST(gemini_libs)
])
dnl ---------------------------------------------------------------------------
dnl END OF MYSQL_CHECK_GEMINI SECTION
dnl ---------------------------------------------------------------------------
dnl ---------------------------------------------------------------------------
dnl Macro: MYSQL_CHECK_GEMINI
dnl Sets HAVE_GEMINI_DB if --with-gemini is used
dnl ---------------------------------------------------------------------------
AC_DEFUN([MYSQL_CHECK_GEMINI], [
AC_ARG_WITH([gemini],
[\
--with-gemini[=DIR] Use Gemini DB located in DIR],
[gemini="$withval"],
[gemini=no])
AC_MSG_CHECKING([for Gemini DB])
dnl SORT OUT THE SUPPLIED ARGUMENTS TO DETERMINE WHAT TO DO
dnl echo "DBG_GEM1: gemini='$gemini'"
have_gemini_db=no
gemini_includes=
gemini_libs=
case "$gemini" in
no )
AC_MSG_RESULT([Not using Gemini DB])
;;
yes | default | *)
have_gemini_db="yes"
gemini_includes="-I../gemini/incl -I../gemini"
gemini_libs="\
../gemini/api/libapi.a\
../gemini/db/libdb.a\
../gemini/dbut/libdbut.a\
../gemini/vst/libvst.a"
AC_MSG_RESULT([Using Gemini DB])
;;
esac
AC_SUBST(gemini_includes)
AC_SUBST(gemini_libs)
])
dnl ---------------------------------------------------------------------------
dnl END OF MYSQL_CHECK_GEMINI SECTION
dnl ---------------------------------------------------------------------------
dnl ---------------------------------------------------------------------------
dnl Got this from the GNU tar 1.13.11 distribution
dnl by Paul Eggert <eggert@twinsun.com>
......
......@@ -211,6 +211,8 @@ enum ha_base_keytype {
#define HA_ERR_WRONG_TABLE_DEF 143
#define HA_ERR_CRASHED_ON_REPAIR 144 /* Last (automatic?) repair failed */
#define HA_ERR_CRASHED_ON_USAGE 145 /* Table must be repaired */
#define HA_ERR_LOCK_WAIT_TIMEOUT 146
#define HA_ERR_LOCK_TABLE_FULL 147
/* Other constants */
......
-- require r/have_gemini.require
show variables like "have_gemini";
id code name
1 1 Tim
2 1 Monty
3 2 David
4 2 Erik
5 3 Sasha
6 3 Jeremy
7 4 Matt
id code name
2 1 Monty
3 2 David
4 2 Erik
5 3 Sasha
6 3 Jeremy
7 4 Matt
8 1 Sinisa
id code name
3 2 David
4 2 Erik
5 3 Sasha
6 3 Jeremy
7 4 Matt
8 1 Sinisa
12 1 Ralph
id parent_id level
8 102 2
9 102 2
15 102 2
id parent_id level
1001 100 0
1003 101 1
1004 101 1
1008 102 2
1009 102 2
1017 103 2
1022 104 2
1024 104 2
1028 105 2
1029 105 2
1030 105 2
1031 106 2
1032 106 2
1033 106 2
1203 107 2
1202 107 2
1020 103 2
1157 100 0
1193 105 2
1040 107 2
1002 101 1
1015 102 2
1006 101 1
1034 106 2
1035 106 2
1016 103 2
1007 101 1
1036 107 2
1018 103 2
1026 105 2
1027 105 2
1183 104 2
1038 107 2
1025 105 2
1037 107 2
1021 104 2
1019 103 2
1005 101 1
1179 105 2
id parent_id level
1001 100 0
1003 101 1
1004 101 1
1008 102 2
1010 102 2
1017 103 2
1023 104 2
1024 104 2
1028 105 2
1029 105 2
1030 105 2
1031 106 2
1032 106 2
1033 106 2
1204 107 2
1203 107 2
1020 103 2
1158 100 0
1194 105 2
1041 107 2
1002 101 1
1015 102 2
1006 101 1
1034 106 2
1035 106 2
1016 103 2
1007 101 1
1036 107 2
1018 103 2
1026 105 2
1027 105 2
1184 104 2
1039 107 2
1025 105 2
1038 107 2
1022 104 2
1019 103 2
1005 101 1
1180 105 2
id parent_id level
1008 102 2
1010 102 2
1015 102 2
table type possible_keys key key_len ref rows Extra
t1 ref level level 1 const 6 where used; Using index
table type possible_keys key key_len ref rows Extra
t1 ref level level 1 const 6 where used
table type possible_keys key key_len ref rows Extra
t1 ref level level 1 const 6 where used
level id
1 1003
1 1004
1 1002
1 1006
1 1007
1 1005
level id parent_id
1 1003 101
1 1004 101
1 1002 101
1 1006 101
1 1007 101
1 1005 101
gesuchnr benutzer_id
1 1
2 1
a
2
user_id name phone ref_email detail
10292 sanjeev 29153373 sansh777@hotmail.com xxx
10292 shirish 2333604 shirish@yahoo.com ddsds
10292 sonali 323232 sonali@bolly.com filmstar
user_id name phone ref_email detail
10292 sanjeev 29153373 sansh777@hotmail.com xxx
10292 shirish 2333604 shirish@yahoo.com ddsds
10292 sonali 323232 sonali@bolly.com filmstar
user_id name phone ref_email detail
10292 sanjeev 29153373 sansh777@hotmail.com xxx
10292 shirish 2333604 shirish@yahoo.com ddsds
10292 sonali 323232 sonali@bolly.com filmstar
10293 shirish 2333604 shirish@yahoo.com ddsds
user_id name phone ref_email detail
10293 shirish 2333604 shirish@yahoo.com ddsds
user_id name phone ref_email detail
10291 sanjeev 29153373 sansh777@hotmail.com xxx
a b
1 3
2 3
3 3
a b
1 3
2 3
3 3
a b
a b
1 3
2 3
3 3
a b
1 3
2 3
3 3
id ggid email passwd
1 test1 xxx
id ggid email passwd
1 test1 xxx
id ggid email passwd
2 test2 yyy
id parent_id level
8 102 2
9 102 2
15 102 2
id parent_id level
1001 100 0
1003 101 1
1004 101 1
1008 102 2
1024 102 2
1017 103 2
1022 104 2
1024 104 2
1028 105 2
1029 105 2
1030 105 2
1031 106 2
1032 106 2
1033 106 2
1203 107 2
1202 107 2
1020 103 2
1157 100 0
1193 105 2
1040 107 2
1002 101 1
1015 102 2
1006 101 1
1034 106 2
1035 106 2
1016 103 2
1007 101 1
1036 107 2
1018 103 2
1026 105 2
1027 105 2
1183 104 2
1038 107 2
1025 105 2
1037 107 2
1021 104 2
1019 103 2
1005 101 1
1179 105 2
id parent_id level
1002 100 0
1004 101 1
1005 101 1
1009 102 2
1025 102 2
1018 103 2
1023 104 2
1025 104 2
1029 105 2
1030 105 2
1031 105 2
1032 106 2
1033 106 2
1034 106 2
1204 107 2
1203 107 2
1021 103 2
1158 100 0
1194 105 2
1041 107 2
1003 101 1
1016 102 2
1007 101 1
1035 106 2
1036 106 2
1017 103 2
1008 101 1
1037 107 2
1019 103 2
1027 105 2
1028 105 2
1184 104 2
1039 107 2
1026 105 2
1038 107 2
1022 104 2
1020 103 2
1006 101 1
1180 105 2
id parent_id level
1009 102 2
1025 102 2
1016 102 2
table type possible_keys key key_len ref rows Extra
t1 ref level level 1 const 6 where used; Using index
level id
1 1004
1 1005
1 1003
1 1007
1 1008
1 1006
level id parent_id
1 1004 101
1 1005 101
1 1003 101
1 1007 101
1 1008 101
1 1006 101
level id
1 1003
1 1004
1 1005
1 1006
1 1007
1 1008
id parent_id level
1002 100 0
1009 102 2
1025 102 2
1018 103 2
1023 104 2
1025 104 2
1029 105 2
1030 105 2
1031 105 2
1032 106 2
1033 106 2
1034 106 2
1204 107 2
1203 107 2
1021 103 2
1158 100 0
1194 105 2
1041 107 2
1016 102 2
1035 106 2
1036 106 2
1017 103 2
1037 107 2
1019 103 2
1027 105 2
1028 105 2
1184 104 2
1039 107 2
1026 105 2
1038 107 2
1022 104 2
1020 103 2
1180 105 2
count(*)
1
a
1
2
3
test for rollback
test for rollback
n after rollback
4 after rollback
n after commit
4 after commit
5 after commit
n after commit
4 after commit
5 after commit
6 after commit
n
4
5
6
7
afterbegin_id afterbegin_nom
1 first
2 hamdouni
afterrollback_id afterrollback_nom
1 first
afterautocommit0_id afterautocommit0_nom
1 first
3 mysql
afterrollback_id afterrollback_nom
1 first
id val
id val
pippo 12
id val
ID NAME
1 Jochen
_userid
marc@anyware.co.uk
_userid
marc@anyware.co.uk
Variable_name Value
have_gemini YES
This diff is collapsed.
......@@ -1377,7 +1377,7 @@ INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1008,"tucked",311,23
INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1009,"gems",447,2374834,9872392);
INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1010,"clinker",512,786542,76234234);
create temporary table tmp select * from t3;
create temporary table tmp type = myisam select * from t3;
insert into t3 select * from tmp;
insert into tmp select * from t3;
......
......@@ -199,6 +199,11 @@ sub new
{
$limits{'max_text_size'} = 8000; # Limit in Innobase
}
if (defined($main::opt_create_options) &&
$main::opt_create_options =~ /type=gemini/i)
{
$limits{'working_blobs'} = 0; # Blobs not implemented yet
}
return $self;
}
......
......@@ -21,7 +21,7 @@ MYSQLDATAdir = $(localstatedir)
MYSQLSHAREdir = $(pkgdatadir)
MYSQLBASEdir= $(prefix)
INCLUDES = @MT_INCLUDES@ \
@bdb_includes@ @innobase_includes@ \
@bdb_includes@ @innobase_includes@ @gemini_includes@ \
-I$(srcdir)/../include \
-I$(srcdir)/../regex \
-I$(srcdir) -I../include -I.. -I.
......@@ -40,7 +40,7 @@ LDADD = ../isam/libnisam.a \
../regex/libregex.a \
../strings/libmystrings.a
mysqld_LDADD = @MYSQLD_EXTRA_LDFLAGS@ \
@bdb_libs@ @innobase_libs@ \
@bdb_libs@ @innobase_libs@ @gemini_libs@ \
$(LDADD) $(CXXLDFLAGS) $(WRAPLIBS)
noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
item_strfunc.h item_timefunc.h item_uniq.h \
......@@ -50,7 +50,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
field.h handler.h \
ha_isammrg.h ha_isam.h ha_myisammrg.h\
ha_heap.h ha_myisam.h ha_berkeley.h ha_innobase.h \
opt_range.h opt_ft.h \
ha_gemini.h opt_range.h opt_ft.h \
sql_select.h structs.h table.h sql_udf.h hash_filo.h\
lex.h lex_symbol.h sql_acl.h sql_crypt.h md5.h \
log_event.h mini_client.h sql_repl.h slave.h
......@@ -71,7 +71,7 @@ mysqld_SOURCES = sql_lex.cc \
records.cc filesort.cc handler.cc \
ha_isam.cc ha_isammrg.cc ha_heap.cc \
ha_myisam.cc ha_myisammrg.cc ha_berkeley.cc \
ha_innobase.cc \
ha_innobase.cc ha_gemini.cc \
sql_db.cc sql_table.cc sql_rename.cc sql_crypt.cc \
sql_load.cc mf_iocache.cc field_conv.cc sql_show.cc \
sql_udf.cc sql_analyse.cc sql_analyse.h sql_cache.cc \
......
This diff is collapsed.
/* Copyright (C) 2000 NuSphere Corporation
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef __GNUC__
#pragma interface /* gcc class implementation */
#endif
#include "dstd.h"
#include "dsmpub.h"
/* class for the the gemini handler */
enum enum_key_string_options{KEY_CREATE,KEY_DELETE,KEY_CHECK};
#define READ_UNCOMMITED 0
#define READ_COMMITED 1
#define REPEATABLE_READ 2
#define SERIALIZEABLE 3
class ha_gemini: public handler
{
/* define file as an int for now until we have a real file struct */
int file;
uint int_option_flag;
int tableNumber;
dsmIndex_t *pindexNumbers; // dsm object numbers for the indexes on this table
unsigned long lastRowid;
uint last_dup_key;
bool fixed_length_row, key_read, using_ignore;
byte *rec_buff;
dsmKey_t *pbracketBase;
dsmKey_t *pbracketLimit;
dsmKey_t *pfoundKey;
dsmMask_t tableStatus; // Crashed/repair status
int index_open(char *tableName);
int pack_row(byte **prow, int *ppackedLength, const byte *record);
void unpack_row(char *record, char *prow);
int findRow(THD *thd, dsmMask_t findMode, byte *buf);
int fetch_row(void *gemini_context, const byte *buf);
int handleIndexEntries(const byte * record, dsmRecid_t recid,
enum_key_string_options option);
int handleIndexEntry(const byte * record, dsmRecid_t recid,
enum_key_string_options option,uint keynr);
int createKeyString(const byte * record, KEY *pkeyinfo,
unsigned char *pkeyBuf, int bufSize,
int *pkeyStringLen, short geminiIndexNumber,
bool *thereIsAnull);
int fullCheck(THD *thd,byte *buf);
int pack_key( uint keynr, dsmKey_t *pkey,
const byte *key_ptr, uint key_length);
void unpack_key(char *record, dsmKey_t *key, uint index);
int key_cmp(uint keynr, const byte * old_row,
const byte * new_row);
short cursorId; /* cursorId of active index cursor if any */
dsmMask_t lockMode; /* Shared or exclusive */
/* FIXFIX Don't know why we need this because I don't know what
store_lock method does but we core dump without this */
THR_LOCK alock;
THR_LOCK_DATA lock;
public:
ha_gemini(TABLE *table): handler(table), file(0),
int_option_flag(HA_READ_NEXT | HA_READ_PREV |
HA_REC_NOT_IN_SEQ |
HA_KEYPOS_TO_RNDPOS | HA_READ_ORDER | HA_LASTKEY_ORDER |
HA_LONGLONG_KEYS | HA_NULL_KEY | HA_HAVE_KEY_READ_ONLY |
HA_NO_BLOBS | HA_NO_TEMP_TABLES |
/* HA_BLOB_KEY | */ /*HA_NOT_EXACT_COUNT | */
/*HA_KEY_READ_WRONG_STR |*/ HA_DROP_BEFORE_CREATE),
pbracketBase(0),pbracketLimit(0),pfoundKey(0),
cursorId(0)
{
}
~ha_gemini() {}
const char *table_type() const { return "Gemini"; }
const char **bas_ext() const;
ulong option_flag() const { return int_option_flag; }
uint max_record_length() const { return MAXRECSZ; }
uint max_keys() const { return MAX_KEY-1; }
uint max_key_parts() const { return MAX_REF_PARTS; }
uint max_key_length() const { return MAXKEYSZ; }
bool fast_key_read() { return 1;}
bool has_transactions() { return 1;}
int open(const char *name, int mode, uint test_if_locked);
int close(void);
double scan_time();
int write_row(byte * buf);
int update_row(const byte * old_data, byte * new_data);
int delete_row(const byte * buf);
int index_init(uint index);
int index_end();
int index_read(byte * buf, const byte * key,
uint key_len, enum ha_rkey_function find_flag);
int index_read_idx(byte * buf, uint index, const byte * key,
uint key_len, enum ha_rkey_function find_flag);
int index_next(byte * buf);
int index_next_same(byte * buf, const byte *key, uint keylen);
int index_prev(byte * buf);
int index_first(byte * buf);
int index_last(byte * buf);
int rnd_init(bool scan=1);
int rnd_end();
int rnd_next(byte *buf);
int rnd_pos(byte * buf, byte *pos);
void position(const byte *record);
void info(uint);
int extra(enum ha_extra_function operation);
int reset(void);
int check(THD* thd, HA_CHECK_OPT* check_opt);
int repair(THD* thd, HA_CHECK_OPT* check_opt);
int external_lock(THD *thd, int lock_type);
virtual longlong get_auto_increment();
void position(byte *record);
ha_rows records_in_range(int inx,
const byte *start_key,uint start_key_len,
enum ha_rkey_function start_search_flag,
const byte *end_key,uint end_key_len,
enum ha_rkey_function end_search_flag);
int create(const char *name, register TABLE *form,
HA_CREATE_INFO *create_info);
int delete_table(const char *name);
int rename_table(const char* from, const char* to);
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type);
};
#define GEMOPT_FLUSH_LOG 0x00000001
#define GEMOPT_UNBUFFERED_IO 0x00000002
#define GEMINI_RECOVERY_FULL 0x00000001
#define GEMINI_RECOVERY_NONE 0x00000002
#define GEMINI_RECOVERY_FORCE 0x00000004
#define GEM_OPTID_SPIN_RETRIES 1
extern bool gemini_skip;
extern long gemini_options;
extern long gemini_buffer_cache;
extern long gemini_io_threads;
extern long gemini_log_cluster_size;
extern long gemini_locktablesize;
extern long gemini_lock_wait_timeout;
extern long gemini_spin_retries;
extern long gemini_connection_limit;
extern TYPELIB gemini_recovery_typelib;
extern ulong gemini_recovery_options;
bool gemini_init(void);
bool gemini_end(void);
bool gemini_flush_logs(void);
int gemini_commit(THD *thd);
int gemini_rollback(THD *thd);
void gemini_disconnect(THD *thd);
int gemini_rollback_to_savepoint(THD *thd);
int gemini_parse_table_name(const char *fullname, char *dbname, char *tabname);
int gemini_is_vst(const char *pname);
int gemini_set_option_long(int optid, long optval);
const int gemini_blocksize = 8192;
const int gemini_recbits = 7;
......@@ -35,6 +35,9 @@
#ifdef HAVE_INNOBASE_DB
#include "ha_innobase.h"
#endif
#ifdef HAVE_GEMINI_DB
#include "ha_gemini.h"
#endif
#include <myisampack.h>
#include <errno.h>
......@@ -49,7 +52,7 @@ ulong ha_read_count, ha_write_count, ha_delete_count, ha_update_count,
const char *ha_table_type[] = {
"", "DIAB_ISAM","HASH","MISAM","PISAM","RMS_ISAM","HEAP", "ISAM",
"MRG_ISAM","MYISAM", "MRG_MYISAM", "BDB", "INNOBASE", "?", "?",NullS
"MRG_ISAM","MYISAM", "MRG_MYISAM", "BDB", "INNOBASE", "GEMINI", "?", "?",NullS
};
const char *ha_row_type[] = {
......@@ -77,6 +80,10 @@ enum db_type ha_checktype(enum db_type database_type)
case DB_TYPE_INNOBASE:
return(innobase_skip ? DB_TYPE_MYISAM : database_type);
#endif
#ifdef HAVE_GEMINI_DB
case DB_TYPE_GEMINI:
return(gemini_skip ? DB_TYPE_MYISAM : database_type);
#endif
#ifndef NO_HASH
case DB_TYPE_HASH:
#endif
......@@ -118,6 +125,10 @@ handler *get_new_handler(TABLE *table, enum db_type db_type)
#ifdef HAVE_INNOBASE_DB
case DB_TYPE_INNOBASE:
return new ha_innobase(table);
#endif
#ifdef HAVE_GEMINI_DB
case DB_TYPE_GEMINI:
return new ha_gemini(table);
#endif
case DB_TYPE_HEAP:
return new ha_heap(table);
......@@ -149,6 +160,15 @@ int ha_init()
if (!innobase_skip) // If we couldn't use handler
opt_using_transactions=1;
}
#endif
#ifdef HAVE_GEMINI_DB
if (!gemini_skip)
{
if (gemini_init())
return -1;
if (!gemini_skip) // If we couldn't use handler
opt_using_transactions=1;
}
#endif
return 0;
}
......@@ -176,6 +196,10 @@ int ha_panic(enum ha_panic_function flag)
#ifdef HAVE_INNOBASE_DB
if (!innobase_skip)
error|=innobase_end();
#endif
#ifdef HAVE_GEMINI_DB
if (!gemini_skip)
error|=gemini_end();
#endif
return error;
} /* ha_panic */
......@@ -187,6 +211,12 @@ void ha_close_connection(THD* thd)
if (!innobase_skip)
innobase_close_connection(thd);
#endif
#ifdef HAVE_GEMINI_DB
if (!gemini_skip && thd->gemini.context)
{
gemini_disconnect(thd);
}
#endif /* HAVE_GEMINI_DB */
}
/*
......@@ -250,6 +280,20 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
error=1;
}
}
#endif
#ifdef HAVE_GEMINI_DB
/* Commit the transaction in behalf of the commit statement
or if we're in auto-commit mode */
if((trans == &thd->transaction.all) ||
(!(thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN))))
{
error=gemini_commit(thd);
if (error)
{
my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
error=1;
}
}
#endif
if (error && trans == &thd->transaction.all && mysql_bin_log.is_open())
sql_print_error("Error: Got error during commit; Binlog is not up to date!");
......@@ -287,6 +331,18 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans)
error=1;
}
}
#endif
#ifdef HAVE_GEMINI_DB
if((trans == &thd->transaction.stmt) &&
(thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN)))
error = gemini_rollback_to_savepoint(thd);
else
error=gemini_rollback(thd);
if (error)
{
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), error);
error=1;
}
#endif
if (trans == &thd->transaction.all)
reinit_io_cache(&thd->transaction.trans_log,
......@@ -678,6 +734,21 @@ int handler::rename_table(const char * from, const char * to)
DBUG_RETURN(0);
}
int ha_commit_rename(THD *thd)
{
int error=0;
#ifdef HAVE_GEMINI_DB
/* Gemini needs to commit the rename; otherwise a rollback will change
** the table names back internally but the physical files will still
** have the new names.
*/
if (ha_commit_stmt(thd))
error= -1;
if (ha_commit(thd))
error= -1;
#endif
return error;
}
int handler::index_next_same(byte *buf, const byte *key, uint keylen)
{
......
......@@ -72,6 +72,7 @@
#define HA_DROP_BEFORE_CREATE (HA_PRIMARY_KEY_IN_READ_INDEX*2)
#define HA_NOT_READ_AFTER_KEY (HA_DROP_BEFORE_CREATE*2)
#define HA_NOT_DELETE_WITH_CACHE (HA_NOT_READ_AFTER_KEY*2)
#define HA_NO_TEMP_TABLES (HA_NOT_DELETE_WITH_CACHE*2)
/* Parameters for open() (in register form->filestat) */
/* HA_GET_INFO does a implicit HA_ABORT_IF_LOCKED */
......@@ -310,6 +311,17 @@ public:
enum thr_lock_type lock_type)=0;
};
#ifdef HAVE_GEMINI_DB
struct st_gemini
{
void *context;
unsigned long savepoint;
bool needSavepoint;
uint tx_isolation;
uint lock_count;
};
#endif
/* Some extern variables used with handlers */
extern const char *ha_row_type[];
......@@ -337,4 +349,4 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans);
int ha_autocommit_or_rollback(THD *thd, int error);
void ha_set_spin_retries(uint retries);
bool ha_flush_logs(void);
int ha_commit_rename(THD *thd);
......@@ -146,6 +146,7 @@ static SYMBOL symbols[] = {
{ "FULLTEXT", SYM(FULLTEXT_SYM),0,0},
{ "FUNCTION", SYM(UDF_SYM),0,0},
{ "GEMINI", SYM(GEMINI_SYM),0,0},
{ "GEMINI_SPIN_RETRIES", SYM(GEMINI_SPIN_RETRIES),0,0},
{ "GLOBAL", SYM(GLOBAL_SYM),0,0},
{ "GRANT", SYM(GRANT),0,0},
{ "GRANTS", SYM(GRANTS),0,0},
......
......@@ -25,6 +25,9 @@
#ifdef HAVE_INNOBASE_DB
#include "ha_innobase.h"
#endif
#ifdef HAVE_GEMINI_DB
#include "ha_gemini.h"
#endif
#include "ha_myisam.h"
#include <nisam.h>
#include <thr_alarm.h>
......@@ -279,6 +282,9 @@ const char *first_keyword="first";
const char **errmesg; /* Error messages */
const char *myisam_recover_options_str="OFF";
enum_tx_isolation default_tx_isolation=ISO_READ_COMMITTED;
#ifdef HAVE_GEMINI_DB
const char *gemini_recovery_options_str="FULL";
#endif
my_string mysql_unix_port=NULL,mysql_tmpdir=NULL;
ulong my_bind_addr; /* the address we bind to */
DATE_FORMAT dayord;
......@@ -2427,7 +2433,9 @@ enum options {
OPT_INNOBASE_FLUSH_LOG_AT_TRX_COMMIT,
OPT_SAFE_SHOW_DB,
OPT_GEMINI_SKIP, OPT_INNOBASE_SKIP,
OPT_TEMP_POOL, OPT_TX_ISOLATION
OPT_TEMP_POOL, OPT_TX_ISOLATION,
OPT_GEMINI_FLUSH_LOG, OPT_GEMINI_RECOVER,
OPT_GEMINI_UNBUFFERED_IO
};
static struct option long_options[] = {
......@@ -2464,6 +2472,11 @@ static struct option long_options[] = {
{"enable-locking", no_argument, 0, (int) OPT_ENABLE_LOCK},
{"exit-info", optional_argument, 0, 'T'},
{"flush", no_argument, 0, (int) OPT_FLUSH},
#ifdef HAVE_GEMINI_DB
{"gemini-flush-log-at-commit",no_argument, 0, (int) OPT_GEMINI_FLUSH_LOG},
{"gemini-recovery", required_argument, 0, (int) OPT_GEMINI_RECOVER},
{"gemini-unbuffered-io", no_argument, 0, (int) OPT_GEMINI_UNBUFFERED_IO},
#endif
/* We must always support this option to make scripts like mysqltest easier
to do */
{"innobase_data_file_path", required_argument, 0,
......@@ -2592,6 +2605,22 @@ CHANGEABLE_VAR changeable_vars[] = {
DELAYED_QUEUE_SIZE, 1, ~0L, 0, 1 },
{ "flush_time", (long*) &flush_time,
FLUSH_TIME, 0, ~0L, 0, 1 },
#ifdef HAVE_GEMINI_DB
{ "gemini_buffer_cache", (long*) &gemini_buffer_cache,
128 * 8192, 16, LONG_MAX, 0, 1 },
{ "gemini_connection_limit", (long*) &gemini_connection_limit,
100, 10, LONG_MAX, 0, 1 },
{ "gemini_io_threads", (long*) &gemini_io_threads,
2, 0, 256, 0, 1 },
{ "gemini_log_cluster_size", (long*) &gemini_log_cluster_size,
256 * 1024, 16 * 1024, LONG_MAX, 0, 1 },
{ "gemini_lock_table_size", (long*) &gemini_locktablesize,
4096, 1024, LONG_MAX, 0, 1 },
{ "gemini_lock_wait_timeout",(long*) &gemini_lock_wait_timeout,
10, 1, LONG_MAX, 0, 1 },
{ "gemini_spin_retries", (long*) &gemini_spin_retries,
1, 0, LONG_MAX, 0, 1 },
#endif
#ifdef HAVE_INNOBASE_DB
{"innobase_mirrored_log_groups",
(long*) &innobase_mirrored_log_groups, 1, 1, 10, 0, 1},
......@@ -2711,6 +2740,16 @@ struct show_var_st init_vars[]= {
{"delayed_queue_size", (char*) &delayed_queue_size, SHOW_LONG},
{"flush", (char*) &myisam_flush, SHOW_MY_BOOL},
{"flush_time", (char*) &flush_time, SHOW_LONG},
#ifdef HAVE_GEMINI_DB
{"gemini_buffer_cache", (char*) &gemini_buffer_cache, SHOW_LONG},
{"gemini_connection_limit", (char*) &gemini_connection_limit, SHOW_LONG},
{"gemini_io_threads", (char*) &gemini_io_threads, SHOW_LONG},
{"gemini_log_cluster_size", (char*) &gemini_log_cluster_size, SHOW_LONG},
{"gemini_lock_table_size", (char*) &gemini_locktablesize, SHOW_LONG},
{"gemini_lock_wait_timeout",(char*) &gemini_lock_wait_timeout, SHOW_LONG},
{"gemini_recovery_options", (char*) &gemini_recovery_options_str, SHOW_CHAR_PTR},
{"gemini_spin_retries", (char*) &gemini_spin_retries, SHOW_LONG},
#endif
{"have_bdb", (char*) &have_berkeley_db, SHOW_HAVE},
{"have_gemini", (char*) &have_gemini, SHOW_HAVE},
{"have_innobase", (char*) &have_innobase, SHOW_HAVE},
......@@ -2974,6 +3013,16 @@ static void usage(void)
--skip-bdb Don't use berkeley db (will save memory)\n\
");
#endif /* HAVE_BERKELEY_DB */
#ifdef HAVE_GEMINI_DB
puts("\
--gemini-recovery=mode Set Crash Recovery operating mode\n\
(FULL, NONE, FORCE - default FULL)
--gemini-flush-log-at-commit\n\
Every commit forces a write to the reovery log\n\
--gemini-unbuffered-io Use unbuffered i/o\n\
--skip-gemini Don't use gemini (will save memory)\n\
");
#endif
#ifdef HAVE_INNOBASE_DB
puts("\
--innobase_data_home_dir=dir The common part for innobase table spaces\n
......@@ -3519,6 +3568,21 @@ static void get_options(int argc,char **argv)
#ifdef HAVE_GEMINI_DB
gemini_skip=1;
have_gemini=SHOW_OPTION_DISABLED;
break;
case OPT_GEMINI_RECOVER:
gemini_recovery_options_str=optarg;
if ((gemini_recovery_options=
find_bit_type(optarg, &gemini_recovery_typelib)) == ~(ulong) 0)
{
fprintf(stderr, "Unknown option to gemini-recovery: %s\n",optarg);
exit(1);
}
break;
case OPT_GEMINI_FLUSH_LOG:
gemini_options |= GEMOPT_FLUSH_LOG;
break;
case OPT_GEMINI_UNBUFFERED_IO:
gemini_options |= GEMOPT_UNBUFFERED_IO;
#endif
break;
case OPT_INNOBASE_SKIP:
......@@ -4002,6 +4066,68 @@ static int get_service_parameters()
{
SET_CHANGEABLE_VARVAL( "thread_concurrency" );
}
#ifdef HAVE_GEMINI_DB
else if ( lstrcmp(szKeyValueName, TEXT("GeminiLazyCommit")) == 0 )
{
CHECK_KEY_TYPE( REG_DWORD, szKeyValueName );
if ( *lpdwValue )
gemini_options |= GEMOPT_FLUSH_LOG;
else
gemini_options &= ~GEMOPT_FLUSH_LOG;
}
else if ( lstrcmp(szKeyValueName, TEXT("GeminiFullRecovery")) == 0 )
{
CHECK_KEY_TYPE( REG_DWORD, szKeyValueName );
if ( *lpdwValue )
gemini_options &= ~GEMOPT_NO_CRASH_PROTECTION;
else
gemini_options |= GEMOPT_NO_CRASH_PROTECTION;
}
else if ( lstrcmp(szKeyValueName, TEXT("GeminiNoRecovery")) == 0 )
{
CHECK_KEY_TYPE( REG_DWORD, szKeyValueName );
if ( *lpdwValue )
gemini_options |= GEMOPT_NO_CRASH_PROTECTION;
else
gemini_options &= ~GEMOPT_NO_CRASH_PROTECTION;
}
else if ( lstrcmp(szKeyValueName, TEXT("GeminiUnbufferedIO")) == 0 )
{
CHECK_KEY_TYPE( REG_DWORD, szKeyValueName );
if ( *lpdwValue )
gemini_options |= GEMOPT_UNBUFFERED_IO;
else
gemini_options &= ~GEMOPT_UNBUFFERED_IO;
}
else if ( lstrcmp(szKeyValueName, TEXT("GeminiLockTableSize")) == 0 )
{
SET_CHANGEABLE_VARVAL( "gemini_lock_table_size" );
}
else if ( lstrcmp(szKeyValueName, TEXT("GeminiBufferCache")) == 0 )
{
SET_CHANGEABLE_VARVAL( "gemini_buffer_cache" );
}
else if ( lstrcmp(szKeyValueName, TEXT("GeminiSpinRetries")) == 0 )
{
SET_CHANGEABLE_VARVAL( "gemini_spin_retries" );
}
else if ( lstrcmp(szKeyValueName, TEXT("GeminiIoThreads")) == 0 )
{
SET_CHANGEABLE_VARVAL( "gemini_io_threads" );
}
else if ( lstrcmp(szKeyValueName, TEXT("GeminiConnectionLimit")) == 0 )
{
SET_CHANGEABLE_VARVAL( "gemini_connection_limit" );
}
else if ( lstrcmp(szKeyValueName, TEXT("GeminiLogClusterSize")) == 0 )
{
SET_CHANGEABLE_VARVAL( "gemini_log_cluster_size" );
}
else if ( lstrcmp(szKeyValueName, TEXT("GeminiLockWaitTimeout")) == 0 )
{
SET_CHANGEABLE_VARVAL( "gemini_lock_wait_timeout" );
}
#endif
else
{
TCHAR szErrorMsg [ 512 ];
......
......@@ -2400,15 +2400,22 @@ int QUICK_SELECT::get_next()
for (;;)
{
int result;
if (range)
{ // Already read through key
int result=((range->flag & EQ_RANGE) ?
result=((range->flag & EQ_RANGE) ?
file->index_next_same(record, (byte*) range->min_key,
range->min_length) :
file->index_next(record));
if (!result && !cmp_next(*it.ref()))
if (!result)
{
if (!cmp_next(*it.ref()))
DBUG_RETURN(0);
}
else if (result != HA_ERR_END_OF_FILE)
DBUG_RETURN(result);
}
if (!(range=it++))
DBUG_RETURN(HA_ERR_END_OF_FILE); // All ranges used
if (range->flag & NO_MIN_RANGE) // Read first record
......@@ -2421,15 +2428,17 @@ int QUICK_SELECT::get_next()
range=0; // To next range
continue;
}
if (file->index_read(record,(byte*) range->min_key,
if ((result = file->index_read(record,(byte*) range->min_key,
range->min_length,
((range->flag & NEAR_MIN) ?
HA_READ_AFTER_KEY:
(range->flag & EQ_RANGE) ?
HA_READ_KEY_EXACT :
HA_READ_KEY_OR_NEXT)))
HA_READ_KEY_OR_NEXT))))
{
if (result != HA_ERR_KEY_NOT_FOUND)
DBUG_RETURN(result);
range=0; // Not found, to next range
continue;
}
......
......@@ -164,25 +164,30 @@ static int rr_sequential(READ_RECORD *info)
static int rr_from_tempfile(READ_RECORD *info)
{
int tmp;
tryNext:
if (my_b_read(info->io_cache,info->ref_pos,info->ref_length))
return -1; /* End of file */
int tmp=info->file->rnd_pos(info->record,info->ref_pos);
tmp=info->file->rnd_pos(info->record,info->ref_pos);
if (tmp)
{
if (tmp == HA_ERR_END_OF_FILE)
tmp= -1;
else if (tmp == HA_ERR_RECORD_DELETED)
goto tryNext;
else if (info->print_error)
info->file->print_error(tmp,MYF(0));
}
return tmp;
} /* rr_from_tempfile */
static int rr_from_pointers(READ_RECORD *info)
{
byte *cache_pos;
tryNext:
if (info->cache_pos == info->cache_end)
return -1; /* End of file */
byte *cache_pos=info->cache_pos;
cache_pos=info->cache_pos;
info->cache_pos+=info->ref_length;
int tmp=info->file->rnd_pos(info->record,cache_pos);
......@@ -190,6 +195,8 @@ static int rr_from_pointers(READ_RECORD *info)
{
if (tmp == HA_ERR_END_OF_FILE)
tmp= -1;
else if (tmp == HA_ERR_RECORD_DELETED)
goto tryNext;
else if (info->print_error)
info->file->print_error(tmp,MYF(0));
}
......
......@@ -105,6 +105,9 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
#ifdef __WIN__
real_id = 0;
#endif
#ifdef HAVE_GEMINI_DB
bzero((char *)&gemini, sizeof(gemini));
#endif
#ifdef SIGNAL_WITH_VIO_CLOSE
active_vio = 0;
pthread_mutex_init(&active_vio_lock, NULL);
......
......@@ -250,6 +250,9 @@ public:
THD_TRANS stmt; /* Trans for current statement */
uint bdb_lock_count;
} transaction;
#ifdef HAVE_GEMINI_DB
struct st_gemini gemini;
#endif
Item *free_list;
CONVERT *convert_set;
Field *dupp_field;
......@@ -265,10 +268,11 @@ public:
max_join_size,sent_row_count;
table_map used_tables;
ulong query_id,version, inactive_timeout,options,thread_id;
ulong gemini_spin_retries;
long dbug_thread_id;
pthread_t real_id;
uint current_tablenr,tmp_table,cond_count,col_access,query_length;
uint server_status,open_options, gemini_spin_retries;
uint server_status,open_options;
enum_tx_isolation tx_isolation, session_tx_isolation;
char scramble[9];
bool slave_thread;
......
......@@ -136,12 +136,12 @@ typedef struct st_lex {
LEX_MASTER_INFO mi; // used by CHANGE MASTER
ulong thread_id,type;
ulong options;
ulong gemini_spin_retries;
enum_sql_command sql_command;
enum lex_states next_state;
enum enum_duplicates duplicates;
enum enum_tx_isolation tx_isolation;
uint in_sum_expr,grant,grant_tot_col,which_columns, sort_default;
uint gemini_spin_retries;
thr_lock_type lock_option;
bool create_refs,drop_primary,drop_if_exists,local_file;
bool in_comment,ignore_space,verbose;
......
......@@ -31,7 +31,7 @@ static TABLE_LIST *rename_tables(THD *thd, TABLE_LIST *table_list,
bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list)
{
bool error=1,got_all_locks=1;
bool error=1,cerror,got_all_locks=1;
TABLE_LIST *lock_table,*ren_table=0;
DBUG_ENTER("mysql_rename_tables");
......@@ -85,7 +85,14 @@ end:
rename_tables(thd, table, 1);
/* Note that lock_table == 0 here, so the unlock loop will work */
}
if (!error)
/* Lets hope this doesn't fail as the result will be messy */
if ((cerror=ha_commit_rename(thd)))
{
my_error(ER_GET_ERRNO,MYF(0),cerror);
error= 1;
}
else if (!error)
{
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
......@@ -95,6 +102,7 @@ end:
}
send_ok(&thd->net);
}
for (TABLE_LIST *table=table_list ; table != lock_table ; table=table->next)
unlock_table_name(thd,table);
pthread_cond_broadcast(&COND_refresh);
......
......@@ -1170,6 +1170,12 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (mysql_rename_table(old_db_type,db,table_name,new_db,new_name))
error= -1;
}
if (!error && (error=ha_commit_rename(thd)))
{
my_error(ER_GET_ERRNO,MYF(0),error);
error=1;
}
VOID(pthread_cond_broadcast(&COND_refresh));
VOID(pthread_mutex_unlock(&LOCK_open));
if (!error)
......@@ -1603,6 +1609,7 @@ end_temporary:
DBUG_RETURN(0);
err:
(void) ha_commit_rename(thd); // Just for safety
DBUG_RETURN(-1);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment