summaryrefslogtreecommitdiff
path: root/mysys
diff options
context:
space:
mode:
Diffstat (limited to 'mysys')
-rw-r--r--mysys/default.c12
-rw-r--r--mysys/my_delete.c1
-rw-r--r--mysys/thr_lock.c125
3 files changed, 136 insertions, 2 deletions
diff --git a/mysys/default.c b/mysys/default.c
index 08653b1a3c4..ddf4b8afa3f 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -87,6 +87,12 @@ static char my_defaults_extra_file_buffer[FN_REFLEN];
static my_bool defaults_already_read= FALSE;
+#ifdef WITH_WSREP
+/* The only purpose of this global array is to hold full name of my.cnf
+ * which seems to be otherwise unavailable */
+char wsrep_defaults_file[FN_REFLEN + 10]={0,};
+#endif /* WITH_WREP */
+
/* Which directories are searched for options (and in which order) */
#define MAX_DEFAULT_DIRS 6
@@ -803,6 +809,12 @@ static int search_default_file_with_ext(Process_option_func opt_handler,
if (!(fp= mysql_file_fopen(key_file_cnf, name, O_RDONLY, MYF(0))))
return 1; /* Ignore wrong files */
+#ifdef WITH_WSREP
+ /* make sure we do this only once - for top-level file */
+ if ('\0' == wsrep_defaults_file[0])
+ strncpy(wsrep_defaults_file, name, sizeof(wsrep_defaults_file) - 1);
+#endif /* WITH_WSREP */
+
while (mysql_file_fgets(buff, sizeof(buff) - 1, fp))
{
line++;
diff --git a/mysys/my_delete.c b/mysys/my_delete.c
index 155e925e9ba..881bcad9459 100644
--- a/mysys/my_delete.c
+++ b/mysys/my_delete.c
@@ -151,3 +151,4 @@ error:
DBUG_RETURN(-1);
}
#endif
+
diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c
index a7cbfa07db2..914990551b0 100644
--- a/mysys/thr_lock.c
+++ b/mysys/thr_lock.c
@@ -94,7 +94,24 @@ be any number of TL_WRITE_CONCURRENT_INSERT locks aktive at the same time.
my_bool thr_lock_inited=0;
ulong locks_immediate = 0L, locks_waited = 0L;
enum thr_lock_type thr_upgraded_concurrent_insert_lock = TL_WRITE;
-
+#ifdef WITH_WSREP
+static wsrep_thd_is_brute_force_fun wsrep_thd_is_brute_force= NULL;
+static wsrep_abort_thd_fun wsrep_abort_thd= NULL;
+static my_bool wsrep_debug;
+static my_bool wsrep_convert_LOCK_to_trx;
+static wsrep_on_fun wsrep_on = NULL;
+
+void wsrep_thr_lock_init(
+ wsrep_thd_is_brute_force_fun bf_fun, wsrep_abort_thd_fun abort_fun,
+ my_bool debug, my_bool convert_LOCK_to_trx, wsrep_on_fun on_fun
+) {
+ wsrep_thd_is_brute_force = bf_fun;
+ wsrep_abort_thd = abort_fun;
+ wsrep_debug = debug;
+ wsrep_convert_LOCK_to_trx= convert_LOCK_to_trx;
+ wsrep_on = on_fun;
+}
+#endif
/* The following constants are only for debug output */
#define MAX_THREADS 1000
#define MAX_LOCKS 1000
@@ -645,8 +662,111 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
DBUG_RETURN(result);
}
+#ifdef WITH_WSREP
+/*
+ * If brute force applier would need to wait for a thr lock,
+ * it needs to make sure that it will get the lock without (too much)
+ * delay.
+ * We identify here the owners of blocking locks and ask them to
+ * abort. We then put our lock request in the first place in the
+ * wait queue. When lock holders abort (one by one) the lock release
+ * algorithm should grant the lock to us. We rely on this and proceed
+ * to wait_for_locks().
+ * wsrep_break_locks() should be called in all the cases, where lock
+ * wait would happen.
+ *
+ * TODO: current implementation might not cover all possible lock wait
+ * situations. This needs an review still.
+ * TODO: lock release, might favor some other lock (instead our bf).
+ * This needs an condition to check for bf locks first.
+ * TODO: we still have a debug fprintf, this should be removed
+ */
+static inline my_bool
+wsrep_break_lock(
+ THR_LOCK_DATA *data, struct st_lock_list *lock_queue1,
+ struct st_lock_list *lock_queue2, struct st_lock_list *wait_queue)
+{
+ if (wsrep_on(data->owner->mysql_thd) &&
+ wsrep_thd_is_brute_force &&
+ wsrep_thd_is_brute_force(data->owner->mysql_thd, TRUE))
+ {
+ THR_LOCK_DATA *holder;
-static enum enum_thr_lock_result
+ /* if locking session conversion to transaction has been enabled,
+ we know that this conflicting lock must be read lock and furthermore,
+ lock holder is read-only. It is safe to wait for him.
+ */
+#ifdef TODO
+ if (wsrep_convert_LOCK_to_trx &&
+ (THD*)(data->owner->mysql_thd)->in_lock_tables)
+ {
+ if (wsrep_debug)
+ fprintf(stderr,"WSREP wsrep_break_lock read lock untouched\n");
+ return FALSE;
+ }
+#endif
+ if (wsrep_debug)
+ fprintf(stderr,"WSREP wsrep_break_lock aborting locks\n");
+
+ /* aborting lock holder(s) here */
+ for (holder=(lock_queue1) ? lock_queue1->data : NULL;
+ holder;
+ holder=holder->next)
+ {
+ if (!wsrep_thd_is_brute_force(holder->owner->mysql_thd, TRUE))
+ {
+ wsrep_abort_thd(data->owner->mysql_thd,
+ holder->owner->mysql_thd, FALSE);
+ }
+ else
+ {
+ if (wsrep_debug)
+ fprintf(stderr,"WSREP wsrep_break_lock skipping BF lock conflict\n");
+ return FALSE;
+ }
+ }
+ for (holder=(lock_queue2) ? lock_queue2->data : NULL;
+ holder;
+ holder=holder->next)
+ {
+ if (!wsrep_thd_is_brute_force(holder->owner->mysql_thd, TRUE))
+ {
+ wsrep_abort_thd(data->owner->mysql_thd,
+ holder->owner->mysql_thd, FALSE);
+ }
+ else
+ {
+ if (wsrep_debug)
+ fprintf(stderr,"WSREP wsrep_break_lock skipping BF lock conflict\n");
+ return FALSE;
+ }
+ }
+
+ /* Add our lock to the head of the wait queue */
+ if (*(wait_queue->last)==wait_queue->data)
+ {
+ wait_queue->last=&data->next;
+ assert(wait_queue->data==0);
+ }
+ else
+ {
+ assert(wait_queue->data!=0);
+ wait_queue->data->prev=&data->next;
+ }
+ data->next=wait_queue->data;
+ data->prev=&wait_queue->data;
+ wait_queue->data=data;
+ data->cond=get_cond();
+
+ statistic_increment(locks_immediate,&THR_LOCK_lock);
+ return TRUE;
+ }
+ return FALSE;
+}
+#endif
+
+static
+ enum enum_thr_lock_result
thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout)
{
THR_LOCK *lock=data->lock;
@@ -1148,6 +1268,7 @@ static void sort_locks(THR_LOCK_DATA **data,uint count)
}
+
enum enum_thr_lock_result
thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_INFO *owner,
ulong lock_wait_timeout)