dbqp / randgen integration…huzzah!

What is the big deal, you may ask?  Well, read on and all shall be revealed, intrepid reader ; )
As I mentioned an earlier post, our new test-runner – dbqp – allows us to define testing ‘modes’ which all utilize the same system and server management code.

One only has to define a testManager (what does a test look like / how to organize tests) and a testExecutor (how to execute / evaluate a test).  The aim is for dbqp to be a one-stop shop for test execution and to provide a clean and simple way to manage and expand this.

I have just added –mode=randgen to the test-runner.  The random query generator is a significant part of Drizzle’s testing strategy and we use a large number of tests with the tool.  Currently, they are executed and managed by drizzle-automation / Jenkins in our build system, but there has not been an easy way for users to execute these tests (outside of installing / learning drizzle automation or the randgen)…until now >; )

Documentation including requirements and setup instructions for the randgen can be found here
For the cost of about 300 lines of code (the new manager/executor files), we can now execute our randgen tests much the same way as we do our drizzletest suite!

./dbqp –mode=randgen –randgen-path=/home/user/repos/randgen
<snip>
25 Feb 2011 12:14:55 INFO: Using testing mode: randgen
25 Feb 2011 12:14:55 INFO: Processing test suites…
25 Feb 2011 12:14:55 INFO: Found 18 test(s) for execution
25 Feb 2011 12:14:55 INFO: Creating 1 testbot(s)
25 Feb 2011 12:14:55 INFO: Taking clean db snapshot…
25 Feb 2011 12:14:55 INFO: testbot0 server:
25 Feb 2011 12:14:55 INFO: NAME: server0
25 Feb 2011 12:14:55 INFO: MASTER_PORT: 9306
25 Feb 2011 12:14:55 INFO: DRIZZLE_TCP_PORT: 9307
25 Feb 2011 12:14:55 INFO: MC_PORT: 9308
25 Feb 2011 12:14:55 INFO: PBMS_PORT: 9309
25 Feb 2011 12:14:55 INFO: RABBITMQ_NODE_PORT: 9310
25 Feb 2011 12:14:55 INFO: VARDIR: drizzle/tests/workdir/testbot0/server0/var
25 Feb 2011 12:14:55 INFO: STATUS: 1
25 Feb 2011 12:15:00 : ================================================================================
25 Feb 2011 12:15:00 : TEST NAME                                               [ RESULT ]    TIME (ms)
25 Feb 2011 12:15:00 : ================================================================================
25 Feb 2011 12:15:00 : main.basic                                              [ pass ]         4376
25 Feb 2011 12:15:08 : main.blob                                               [ pass ]         7829
25 Feb 2011 12:15:12 : main.collations                                         [ pass ]         3989
25 Feb 2011 12:15:16 : main.combinations                                       [ pass ]         4169
25 Feb 2011 12:15:19 : main.create_drop                                        [ pass ]         3387
25 Feb 2011 12:15:34 : main.drizzledump_restore                                [ pass ]        14726
25 Feb 2011 12:15:42 : main.drizzledump_restore_rand                           [ pass ]         8289
25 Feb 2011 12:15:46 : main.limit_compare                                      [ pass ]         3535
25 Feb 2011 12:15:48 : main.many_indexes                                       [ pass ]         1725
25 Feb 2011 12:15:56 : main.optimizer_subquery                                 [ pass ]         8659
25 Feb 2011 12:16:03 : main.outer_join                                         [ pass ]         6464
25 Feb 2011 12:16:09 : main.outer_join_portable                                [ pass ]         6535
25 Feb 2011 12:16:12 : main.repeatable_read                                    [ pass ]         2906
25 Feb 2011 12:17:42 : main.select_stability_validator                         [ pass ]        90206
25 Feb 2011 12:17:47 : main.subquery                                           [ pass ]         4344
25 Feb 2011 12:19:29 : main.subquery_semijoin                                  [ pass ]       102766
25 Feb 2011 12:19:39 : main.subquery_semijoin_nested                           [ pass ]         9195
25 Feb 2011 12:19:42 : main.varchar                                            [ pass ]         3225
25 Feb 2011 12:19:42 : ================================================================================
25 Feb 2011 12:19:42 INFO: Test execution complete in 286 seconds
25 Feb 2011 12:19:42 INFO: Summary report:
25 Feb 2011 12:19:42 INFO: Executed 18/18 test cases, 100.00 percent
25 Feb 2011 12:19:42 INFO: STATUS: PASS, 18/18 test cases, 100.00 percent executed
25 Feb 2011 12:19:42 INFO: Spent 286 / 286 seconds on: TEST(s)
25 Feb 2011 12:19:42 INFO: Test execution complete
25 Feb 2011 12:19:42 INFO: Stopping all running servers…

Each testcase is a simple .cnf file that defines a few crucial elements:

[test_info]
comment = starts up a master-slave setup.  Still needs some validation work
[test_command]
command = ./gentest.pl –gendata=conf/drizzle/drizzle.zz –grammar=conf/drizzle/optimizer_subquery_drizzle.yy –queries=10 –threads=1
[test_servers]
servers = [[–innodb.replication-log=true],[–plugin-add=slave –slave.config-file=$MASTER_SERVER_SLAVE_CONFIG]]

The test_command is the command line that is passed to the randgen tool itself.  We have created most of these tests and have put together the command lines that serve our testing needs.  By organizing our tests in this fashion, it is now easy for anyone to use the tool to perform meaningful tests.

The test_servers section is interesting – it is a simple list of python lists.  Each sublist contains a set of server options that a server will need.  Servers are started in-order with the first defined server being considered the ‘master_server’.  As we can see in the example to test the new slave plugin, the files are amazingly simple and clean.

Some other added benefits are that dbqp’s –valgrind and –gdb options work the same with randgen tests as they would with drizzletest cases.  Addtionally, we will be able to incorporate the code coverage provided by the randgen in our gcov reports.

One final little feature worth noting is the –gendata option.

The randgen provides a feature called the random data generator / gendata.pl
By passing it a configuration file that defines a set of test tables (see the forge documentation for further details), it will connect to a server, create the test tables, and populate them according to specifications.

While I have other plans for this, one cool use is for ad-hoc testing.  By passing a simple command line + the use of –start-and-exit, one can have a nicely populated test database to play with:

./dbqp –mode=randgen –randgen-path=/home/user/repos/randgen –gendata=/home/user/repos/randgen/conf/drizzle/drizzle.zz –start-and-exit
Setting –no-secure-file-priv=True for randgen mode…
<snip>
25 Feb 2011 13:28:23 INFO: Using testing mode: randgen
25 Feb 2011 13:28:23 INFO: Processing test suites…
25 Feb 2011 13:28:23 INFO: Found 18 test(s) for execution
25 Feb 2011 13:28:23 INFO: Creating 1 testbot(s)
25 Feb 2011 13:28:23 INFO: Taking clean db snapshot…
25 Feb 2011 13:28:23 INFO: testbot0 server:
25 Feb 2011 13:28:23 INFO: NAME: server0
25 Feb 2011 13:28:23 INFO: MASTER_PORT: 9306
25 Feb 2011 13:28:23 INFO: DRIZZLE_TCP_PORT: 9307
25 Feb 2011 13:28:23 INFO: MC_PORT: 9308
25 Feb 2011 13:28:23 INFO: PBMS_PORT: 9309
25 Feb 2011 13:28:23 INFO: RABBITMQ_NODE_PORT: 9310
25 Feb 2011 13:28:23 INFO: VARDIR: drizzle/tests/workdir/testbot0/server0/var
25 Feb 2011 13:28:23 INFO: STATUS: 1
# 2011-02-25T13:28:23 Default schema: test
# 2011-02-25T13:28:23 Executor initialized, id GenTest::Executor::Drizzle 2011.02.2198 ()
# 2011-02-25T13:28:23 # Creating Drizzle table: test.A; engine: ; rows: 0 .
# 2011-02-25T13:28:23 # Creating Drizzle table: test.B; engine: ; rows: 0 .
# 2011-02-25T13:28:23 # Creating Drizzle table: test.C; engine: ; rows: 1 .
# 2011-02-25T13:28:23 # Creating Drizzle table: test.D; engine: ; rows: 1 .
# 2011-02-25T13:28:23 # Creating Drizzle table: test.AA; engine: ; rows: 10 .
# 2011-02-25T13:28:23 # Creating Drizzle table: test.BB; engine: ; rows: 10 .
# 2011-02-25T13:28:24 # Creating Drizzle table: test.CC; engine: ; rows: 100 .
# 2011-02-25T13:28:24 # Creating Drizzle table: test.DD; engine: ; rows: 100 .
25 Feb 2011 13:28:24 INFO: User specified –start-and-exit.  dbqp.py exiting and leaving servers running…
../client/drizzle -uroot -p9306 test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Welcome to the Drizzle client..  Commands end with ; or \g.
Your Drizzle connection id is 3
Connection protocol: mysql
Server version: 2011.02.2198 Source distribution (dbqp_randgen_updates)
Type ‘help;’ or ‘\h’ for help. Type ‘\c’ to clear the buffer.
drizzle> show tables;
+—————-+
| Tables_in_test |
+—————-+
| A              |
| AA             |
| B              |
| BB             |
| C              |
| CC             |
| D              |
| DD             |
+—————-+
8 rows in set (0.001614 sec)
drizzle> select count(*) from dd;
+———-+
| count(*) |
+———-+
|      100 |
+———-+
1 row in set (0.000614 sec)

Please give it a try if you feel so inclined.  We will be working to integrate this better into our build and test systems (Jenkins / make targets / etc).  And remember ./dbqp –mode=cleanup for quick and easy cleanup when you are done playing! ; )

Drizzle’s slave plugin is working!

These are exciting times for the Drizzle team.  We just released our first RC and things are finally coming together into some awesome new features.  I’m excited to bring you latest news from the replication front:

Where to begin?  Well, many moons ago, Brian sent David Shrewsbury and myself out on the task of making the transaction_log plugin rock solid.  This plugin provides a file-based log that captures the server’s state via protobuf messages.  After much blood, sweat, and tears (and *many* bugs), we accomplished our task with *plenty* of help from everyone on the team.  With this task accomplished, we could say that any replication solution using the log would have an accurate representation of the server’s state.  However, this was a long way from actually replicating server-server.

During this time, we were also working on storing the transaction log in an innodb table rather than a file.  Initial sysbench tests show a significant performance gain using this code versus the file based log.  Thanks to the initial work on the file-based log, getting this code up and running wasn’t too painful and it also passes all of our tests with flying colors.  Special mention should be given to Joe Daly, Stewart Smith, and Andrew Hutchings for hacking on this.

Having the transaction log in a database table provides other advantages beyond speed (such as easy, standardized access by other servers), but I’ll leave that to the hackers to discuss (I’d really recommend catching Dave’s UC talk if you are interested!).  The gist is that it has allowed the amazing Mr. Shrewsbury to cook up the slave plugin!

This is a plugin that allows a server to replicate from another server that is using the innodb-trx log.  It is amazingly simple:
master options:  –innodb.replication-log=true
slave options: –plugin-add=slave –slave.config-file=XYZ

The config file may contain the following options in option=value format:
master-host – hostname/ip of the master host
master-port – port used by the master server
master-user – username
master-pass – password
max-reconnects – max # of reconnect attempts if the master disappears
seconds-between-reconnects – how long to wait between reconnect attempts

The code hasn’t yet been merged to trunk, but can be checked out from lp:~dshrews/drizzle/slave
Currently, the plugin is able to replicate *anything* we throw at the master, which is HUGE!

Additionally, our experimental test-runner, dbqp, is sporting randgen integration!  I’ll write more about this in an upcoming post, but I mention it here as you can use the new randgen-mode + –start-and-exit to have yourself a handy-dandy replication setup for ad-hoc testing.  Observe:

./dbqp –mode=randgen –start-and-exit –suite=slave_plugin
Setting –no-secure-file-priv=True for randgen mode…
<snip>
24 Feb 2011 12:25:11 INFO: Using testing mode: randgen
24 Feb 2011 12:25:11 INFO: Processing test suites…
24 Feb 2011 12:25:11 INFO: Found 1 test(s) for execution
24 Feb 2011 12:25:11 INFO: Creating 1 testbot(s)
24 Feb 2011 12:25:11 INFO: Taking clean db snapshot…
24 Feb 2011 12:25:12 INFO: Taking clean db snapshot…
24 Feb 2011 12:25:13 INFO: testbot0 server:
24 Feb 2011 12:25:13 INFO: NAME: server0
24 Feb 2011 12:25:13 INFO: MASTER_PORT: 9316
24 Feb 2011 12:25:13 INFO: DRIZZLE_TCP_PORT: 9317
24 Feb 2011 12:25:13 INFO: MC_PORT: 9318
24 Feb 2011 12:25:13 INFO: PBMS_PORT: 9319
24 Feb 2011 12:25:13 INFO: RABBITMQ_NODE_PORT: 9320
24 Feb 2011 12:25:13 INFO: VARDIR: drizzle/tests/workdir/testbot0/server0/var
24 Feb 2011 12:25:13 INFO: STATUS: 1
24 Feb 2011 12:25:13 INFO: testbot0 server:
24 Feb 2011 12:25:13 INFO: NAME: server1
24 Feb 2011 12:25:13 INFO: MASTER_PORT: 9321
24 Feb 2011 12:25:13 INFO: DRIZZLE_TCP_PORT: 9322
24 Feb 2011 12:25:13 INFO: MC_PORT: 9323
24 Feb 2011 12:25:13 INFO: PBMS_PORT: 9324
24 Feb 2011 12:25:13 INFO: RABBITMQ_NODE_PORT: 9325
24 Feb 2011 12:25:13 INFO: VARDIR: drizzle/tests/workdir/testbot0/server1/var
24 Feb 2011 12:25:13 INFO: STATUS: 1
24 Feb 2011 12:25:13 INFO: User specified –start-and-exit.  dbqp.py exiting and leaving servers running…

We now have two servers running, a master on port 9316 and a slave on port 9321

user@mahmachine:~drizzle/tests$ ../client/drizzle -uroot -p9316 test

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A

Welcome to the Drizzle client..  Commands end with ; or \g.
Your Drizzle connection id is 4
Connection protocol: mysql
Server version: 2011.02.2197 Source distribution (drizzle)

Type ‘help;’ or ‘\h’ for help. Type ‘\c’ to clear the buffer.

drizzle> create table t1 (a int auto_increment not null, primary key(a));
Query OK, 0 rows affected (0.001652 sec)

drizzle> insert into t1 values (),(),();
Query OK, 3 rows affected (0.001182 sec)
Records: 3  Duplicates: 0  Warnings: 0

drizzle> select * from t1;
+—+
| a |
+—+
| 1 |
| 2 |
| 3 |
+—+
3 rows in set (0.000538 sec)

drizzle> exit
Bye
user@mahmachine:~drizzle/tests$ ../client/drizzle -uroot -p9321 test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the Drizzle client..  Commands end with ; or \g.
Your Drizzle connection id is 82
Connection protocol: mysql
Server version: 2011.02.2197 Source distribution (drizzle)

Type ‘help;’ or ‘\h’ for help. Type ‘\c’ to clear the buffer.

drizzle> show tables;
+—————-+
| Tables_in_test |
+—————-+
| t1             |
+—————-+
1 row in set (0.000983 sec)

drizzle> select * from t1;
+—+
| a |
+—+
| 1 |
| 2 |
| 3 |
+—+
3 rows in set (0.00058 sec)

You will likely need to merge with trunk to use this feature in the slave branch, but the actual plugin should be merged soon.

When you are done playing, you can take advantage of a new quality of life feature – cleanup mode.
A pet peeve of mine is needing to clean up / shutdown any servers I may have started during testing.  With dbqp –mode=cleanup, the tool will now kill any server pids it detects in its workdir.  Nothing fancy, but useful, quick, and easy:

./dbqp –mode=cleanup
Setting –start-dirty=True for cleanup mode…
24 Feb 2011 12:32:55 INFO: Using Drizzle source tree:
24 Feb 2011 12:32:55 INFO: basedir: drizzle
24 Feb 2011 12:32:55 INFO: clientbindir: drizzle/client
24 Feb 2011 12:32:55 INFO: testdir: drizzle/tests
24 Feb 2011 12:32:55 INFO: server_version: 2011.02.2197
24 Feb 2011 12:32:55 INFO: server_compile_os: unknown-linux-gnu
24 Feb 2011 12:32:55 INFO: server_platform: x86_64
24 Feb 2011 12:32:55 INFO: server_comment: (Source distribution (drizzle))
24 Feb 2011 12:32:55 INFO: Using –start-dirty, not attempting to touch directories
24 Feb 2011 12:32:55 INFO: Using default-storage-engine: innodb
24 Feb 2011 12:32:55 INFO: Using testing mode: cleanup
24 Feb 2011 12:32:55 INFO: Killing pid 24416 from drizzle/tests/workdir/testbot0/server1/var/run/server1.pid
24 Feb 2011 12:32:55 INFO: Killing pid 24385 from drizzle/tests/workdir/testbot0/server0/var/run/server0.pid
24 Feb 2011 12:32:55 INFO: Stopping all running servers…

Please give it a whirl and help us make the code better by filing any bugs you detect!