List:Internals« Previous MessageNext Message »
From:Martin Friebe Date:December 10 2007 8:34pm
Subject:Re: Proposal for a Test Synchronization Facility
View as plain text  
Nice,

Just a thought, something very similar can be archived using named-locks 
"get_lock('name', timeout)".

And for easier use in testcases the testsuite could provide macros, do 
call the functions.

1) sending a signal, if you have done something:
 do get_lock('mysql_after_sync_insert:inserted', 1');

and check for it with
 select is_free_lock('mysql_after_sync_insert:inserted');

1a) if you want to avoid that the process waiting for the "signal" has 
to poll all the time then you do this:
p1 => process that will send
p2 => process that should wait

# prepare
p1: do get_lock('name : not_yet_send', 1);
#work (next 2 lines in any order)
p1: #do some work
p2: do get_lock('name : not_yet_send', 999999999'); # wait "forever"
# send
p1: do release_lock('name : not_yet_send', 1');
p2 #returns, and know the signal is send

1b) if you wish to recognize that p1 did not die/crash, which would 
release the lock, and send a false signal

#prepare
p1: do get_lock('name : not_yet_send', 1);
#work
p1: #do some work
p2: do get_lock('name : not_yet_send', 999999999'); # wait "forever"
#send
p1: do get_lock('name : now_send', 1); # send the signal
p1: do release_lock('name : not_yet_send', 1');
p2 #returns
p2 select is_used_lock('name : now_send'); # only true if p1 did not die

2)
In the same way, p2 could have gotten a lock, which p1 could then wait 
for, after p1 did send the signal. The only back draw is: you have to 
know in advance, which process will listen for the signal

3)
Of course the above syntax is too complex, but the testsuite could 
provide some macros to archive this.

#prepare
p1: prepare_signal('name')   #select get_lock('name : not_yet_send', 1); 
=> selftest: must return 1
#work (in any order)
p1: #do some work
p2: wait_for_signal('name'); # do get_lock('name : not_yet_send', 
999999); select get_lock('name : now_send'); # select must return 1
#send
p1: send_signal(name);       # do get_lock('name : now_send', 1); do 
release_lock('name : not_yet_send', 1');
p2 #returns and has checked the result of get_lock

4)
p1 should first send, and then wait


p1: prepare_signal('name');
p2: prepare_signal('response');
#
p1 work
p2 wait_for_signal('name')
# send
p1: send_signal(name);
p1: wait_for_signal('response') # already prepared, so will wait
# work in p2
p2 # work
p2: send_signal(response);
# p1 continues


Also in this case, the macros could do more. Instead of "do 
get_lock('name',1)", with a smal ltimeout, when you expect the lock to 
be free, it could do "select get_lock('name', 1);" and check the result 
(must be 1).

Of course
  get_lock('name : not_yet_send', 999999999'); # wait "forever"
is not fail-safe. After 99999999 seconds the test could return a false 
positive. But IMHO for real world, this is quite ignorable.

The advantage is that no changes to the server are needed. So it culd be 
used with current GA servers immediately.

Martin

Ingo Strüwing wrote:
> Hi!
>
> Herewith I propose a new facility to be used in the test suite to make
> race conditions repeatable and get rid of sleeps.
>
> The facility is controlled by user variables. For example, if you have a
> "synchronization point" in the code like this:
>
>     MYSQL_TEST_SYNC(thd, "mysql_test_sync_after_insert");
>
> then you can control it by a user variable in the test case like so:
>
>     SET @mysql_test_sync_after_insert= 'inserted:flushed';
>
> When the code execution in a thread reaches the synchronization point,
> it "sends" the 'inserted' signal (it sets a global String to "inserted"
> and broadcasts a global condition). Then the thread waits until another
> thread sends the 'flushed' signal (sets the global String to "flushed"
> and broadcasts the global condition).
>
> The patch http://lists.mysql.com/commits/39659 contains the main part
> and documentation in item_func.cc. It does also contain functions for
> convenient access to user variable values, an example test case with
> changes to show how to use the facility, and synchronization points used
> by the changed test case. It removes some sleeps and could reduce test
> case execution time from 7 seconds to 0.4 seconds.
>
> Please send me your thoughts. Do you think we should include it in the
> MySQL code?
>
> Regards
> Ingo
>   
Thread
Proposal for a Test Synchronization FacilityIngo Strüwing10 Dec
  • Re: Proposal for a Test Synchronization FacilityMartin Friebe10 Dec
    • Re: Proposal for a Test Synchronization FacilityIngo Strüwing11 Dec
      • Re: Proposal for a Test Synchronization FacilityMartin Friebe11 Dec
Re: Proposal for a Test Synchronization FacilityIngo Strüwing11 Dec