Merge lp:~vlad-lesin/percona-playback/tcpdump-parsing into lp:percona-playback

Proposed by Vlad Lesin
Status: Merged
Merged at revision: 121
Proposed branch: lp:~vlad-lesin/percona-playback/tcpdump-parsing
Merge into: lp:percona-playback
Diff against target: 2069 lines (+1710/-68) (has conflicts)
26 files modified
.bzrignore (+11/-0)
Makefile.am (+36/-2)
configure.ac (+5/-0)
m4/pandora_have_libdrizzle-1.0.m4 (+74/-0)
m4/pandora_have_libdrizzle.m4 (+0/-61)
m4/pandora_have_libmysqlclient.m4 (+103/-0)
percona_playback/dispatcher.cc (+14/-0)
percona_playback/percona_playback.cc (+21/-0)
percona_playback/query_result.h (+7/-0)
percona_playback/tcpdump/connection_state.cc (+325/-0)
percona_playback/tcpdump/connection_state.h (+186/-0)
percona_playback/tcpdump/pcap_packets_parser.cc (+134/-0)
percona_playback/tcpdump/pcap_packets_parser.h (+64/-0)
percona_playback/tcpdump/plugin.ac (+1/-1)
percona_playback/tcpdump/plugin.ini (+3/-1)
percona_playback/tcpdump/sniff_headers.h (+59/-0)
percona_playback/tcpdump/tcpdump.cc (+122/-3)
percona_playback/tcpdump/tcpdump.h (+17/-0)
percona_playback/tcpdump/tcpdump_mysql_parser_stats.h (+33/-0)
percona_playback/tcpdump/tcpdump_query_entries.cc (+129/-0)
percona_playback/tcpdump/tcpdump_query_entries.h (+73/-0)
percona_playback/test/tcpdump_accuracy.cc (+69/-0)
percona_playback/test/tcpdump_fragmented_packet.cc (+56/-0)
percona_playback/test/tcpdump_multiple_connections.cc (+56/-0)
percona_playback/test/tcpdump_stress_test.cc (+56/-0)
percona_playback/test/tcpdump_without_handshake.cc (+56/-0)
Text conflict in Makefile.am
Text conflict in configure.ac
Conflict adding file m4/pandora_have_libmysqlclient.m4.  Moved existing file to m4/pandora_have_libmysqlclient.m4.moved.
Text conflict in percona_playback/percona_playback.cc
Text conflict in percona_playback/tcpdump/tcpdump.h
To merge this branch: bzr merge lp:~vlad-lesin/percona-playback/tcpdump-parsing
Reviewer Review Type Date Requested Status
Stewart Smith Pending
Review via email: mp+111163@code.launchpad.net
To post a comment you must log in.
98. By Vlad Lesin

Add pandora_have_libmysqlclient.m4 pandora_have_libpcap.m4 to the project because it shouldn't depend on pandora-build being installed.

99. By Vlad Lesin

Free drizzle result in ConnectionState destructor.

100. By Vlad Lesin

Fix for memory leak in tcpdump plugin.

101. By Vlad Lesin

Don't use all caps in labels.

102. By Vlad Lesin

One more memory leak fix. See https://bugs.launchpad.net/drizzle/+bug/1015576.

103. By Vlad Lesin

License header is added to dispatcher source.

104. By Vlad Lesin

Merge with 91..94 revisions of trunk(use autoreconf, add gettext support, add po to Makefile subdirs)

105. By Vlad Lesin

Rename pandora_have_libdrizzle.m4 to pandora_have_libdrizzle-1.0.m4 as it finds libdrizzle-1.0 library

106. By Vlad Lesin

Use standard libdrizzle-1.0 instead of modified

107. By Vlad Lesin

Avoid compilation errors in 'set drizzle result options' code

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2011-12-30 01:47:04 +0000
3+++ .bzrignore 2012-07-02 18:23:18 +0000
4@@ -40,3 +40,14 @@
5 percona_playback/test/crashme-slow
6 percona_playback/test/sqlbench-transactions-slow
7 percona_playback/test/sysbench-slow
8+m4/libtool.m4
9+m4/ltoptions.m4
10+m4/ltversion.m4
11+m4/lt~obsolete.m4
12+percona_playback/test/preserve_query_time
13+percona_playback/test/tcpdump_accuracy
14+percona_playback/test/tcpdump_fragmented_packet
15+percona_playback/test/tcpdump_multiple_connections
16+percona_playback/test/tcpdump_stress_test
17+percona_playback/test/tcpdump_without_handshake
18+tags
19
20=== modified file 'Makefile.am'
21--- Makefile.am 2012-06-22 05:12:15 +0000
22+++ Makefile.am 2012-07-02 18:23:18 +0000
23@@ -39,6 +39,11 @@
24 percona_playback/test/sqlbench-transactions-slow.log \
25 percona_playback/test/sysbench-slow.log \
26 percona_playback/test/preserve_query_time.log \
27+ percona_playback/test/tcpdump_without_handshake.dump \
28+ percona_playback/test/tcpdump_fragmented_packet.dump \
29+ percona_playback/test/tcpdump_multiple_connections.dump \
30+ percona_playback/test/tcpdump_stress_test.dump \
31+ percona_playback/test/tcpdump_accuracy.dump \
32 test_run.sh
33
34 include config/pandora-plugin.am
35@@ -71,9 +76,15 @@
36 $(AM_CXXFLAGS) \
37 -DBUILDING_PERCONA_PLAYBACK
38
39+<<<<<<< TREE
40 libpercona_playback_la_LIBADD = $(LIBDL_LIBS) $(BOOST_LIBS) $(TBB_LIBS)
41 libpercona_playback_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(LIBPERCONA_PLAYBACK_VERSION) $(BOOST_LIBS) $(TBB_LIBS) $(pandora_plugin_libs)
42 libpercona_playback_la_DEPENDENCIES = ${noinst_LTLIBRARIES} $(pandora_plugin_libs)
43+=======
44+libpercona_playback_la_LIBADD = $(LIBDL_LIBS) $(BOOST_LIBS) $(LTLIBTBB)
45+libpercona_playback_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(LIBPERCONA_PLAYBACK_VERSION) $(BOOST_LIBS) $(LTLIBTBB) $(pandora_plugin_libs)
46+libpercona_playback_la_DEPENDENCIES = ${noinst_LTLIBRARIES} $(pandora_plugin_libs)
47+>>>>>>> MERGE-SOURCE
48
49 check_PROGRAMS += \
50 percona_playback/test/basic \
51@@ -82,6 +93,11 @@
52 percona_playback/test/sqlbench-transactions-slow \
53 percona_playback/test/sysbench-slow \
54 percona_playback/test/preserve_query_time \
55+ percona_playback/test/tcpdump_without_handshake \
56+ percona_playback/test/tcpdump_fragmented_packet \
57+ percona_playback/test/tcpdump_multiple_connections \
58+ percona_playback/test/tcpdump_stress_test \
59+ percona_playback/test/tcpdump_accuracy \
60 percona_playback/test/help
61
62 percona_playback_test_basic_CXXFLAGS= $(AM_CXXFLAGS) -DSRCDIR=\"${srcdir}\"
63@@ -90,6 +106,11 @@
64 percona_playback_test_sqlbench_transactions_slow_CXXFLAGS= $(AM_CXXFLAGS) -DSRCDIR=\"${srcdir}\"
65 percona_playback_test_sysbench_slow_CXXFLAGS= $(AM_CXXFLAGS) -DSRCDIR=\"${srcdir}\"
66 percona_playback_test_preserve_query_time_CXXFLAGS= $(AM_CXXFLAGS) -DSRCDIR=\"${srcdir}\"
67+percona_playback_test_tcpdump_without_handshake_CXXFLAGS= $(AM_CXXFLAGS) -DSRCDIR=\"${srcdir}\"
68+percona_playback_test_tcpdump_fragmented_packet_CXXFLAGS= $(AM_CXXFLAGS) -DSRCDIR=\"${srcdir}\"
69+percona_playback_test_tcpdump_multiple_connections_CXXFLAGS= $(AM_CXXFLAGS) -DSRCDIR=\"${srcdir}\"
70+percona_playback_test_tcpdump_stress_test_CXXFLAGS= $(AM_CXXFLAGS) -DSRCDIR=\"${srcdir}\"
71+percona_playback_test_tcpdump_accuracy_CXXFLAGS= $(AM_CXXFLAGS) -DSRCDIR=\"${srcdir}\"
72
73 percona_playback_test_help_SOURCES= percona_playback/test/help.cc
74 percona_playback_test_help_LDADD= $(LDADD) $(MYSQL_LIBS)
75@@ -112,7 +133,20 @@
76 percona_playback_test_preserve_query_time_SOURCES= percona_playback/test/preserve_query_time.cc
77 percona_playback_test_preserve_query_time_LDADD= $(LDADD) $(MYSQL_LIBS)
78
79-
80+percona_playback_test_tcpdump_without_handshake_SOURCES= percona_playback/test/tcpdump_without_handshake.cc
81+percona_playback_test_tcpdump_without_handshake_LDADD= $(LDADD) $(MYSQL_LIBS)
82+
83+percona_playback_test_tcpdump_fragmented_packet_SOURCES= percona_playback/test/tcpdump_fragmented_packet.cc
84+percona_playback_test_tcpdump_fragmented_packet_LDADD= $(LDADD) $(MYSQL_LIBS)
85+
86+percona_playback_test_tcpdump_multiple_connections_SOURCES= percona_playback/test/tcpdump_multiple_connections.cc
87+percona_playback_test_tcpdump_multiple_connections_LDADD= $(LDADD) $(MYSQL_LIBS)
88+
89+percona_playback_test_tcpdump_stress_test_SOURCES= percona_playback/test/tcpdump_stress_test.cc
90+percona_playback_test_tcpdump_stress_test_LDADD= $(LDADD) $(MYSQL_LIBS)
91+
92+percona_playback_test_tcpdump_accuracy_SOURCES= percona_playback/test/tcpdump_accuracy.cc
93+percona_playback_test_tcpdump_accuracy_LDADD= $(LDADD) $(MYSQL_LIBS)
94
95 #
96 # Simple percona_playback application
97@@ -120,7 +154,7 @@
98
99 bin_PROGRAMS += bin/percona_playback
100 bin_percona_playback_SOURCES = bin/percona_playback.cc
101-bin_percona_playback_LDADD= $(BOOST_LIBS) $(LDADD) $(TBB_LIBS) $(MYSQL_LIBS) $(pandora_plugin_libs) $(PANDORA_DYNAMIC_LDADDS)
102+bin_percona_playback_LDADD= $(BOOST_LIBS) $(LDADD) $(LTLIBTBB) $(MYSQL_LIBS) $(pandora_plugin_libs) $(PANDORA_DYNAMIC_LDADDS)
103
104 include docs/include.am
105
106
107=== modified file 'configure.ac'
108--- configure.ac 2012-06-24 04:28:41 +0000
109+++ configure.ac 2012-07-02 18:23:18 +0000
110@@ -58,8 +58,13 @@
111
112 AC_DEFINE_UNQUOTED([PERCONA_PLAYBACK_MODULE_EXT], ["$acl_cv_shlibext"],
113 [Extension to use for modules.])
114+<<<<<<< TREE
115 AM_CXXFLAGS="${AM_CXXFLAGS} ${NO_EFF_CXX} ${NO_OLD_STYLE_CAST} ${NO_VISIBILITY}"
116 AC_CONFIG_FILES(Makefile dnl po/Makefile.in
117+=======
118+AM_CXXFLAGS="${NO_EFF_CXX}"
119+AC_CONFIG_FILES(Makefile dnl po/Makefile.in
120+>>>>>>> MERGE-SOURCE
121 percona_playback/version.h dnl
122 docs/header.html)
123
124
125=== added file 'm4/pandora_have_libdrizzle-1.0.m4'
126--- m4/pandora_have_libdrizzle-1.0.m4 1970-01-01 00:00:00 +0000
127+++ m4/pandora_have_libdrizzle-1.0.m4 2012-07-02 18:23:18 +0000
128@@ -0,0 +1,74 @@
129+dnl Copyright (C) 2009 Sun Microsystems, Inc.
130+dnl This file is free software; Sun Microsystems, Inc.
131+dnl gives unlimited permission to copy and/or distribute it,
132+dnl with or without modifications, as long as this notice is preserved.
133+
134+AC_DEFUN([_PANDORA_SEARCH_LIBDRIZZLE_1_0],[
135+ AC_REQUIRE([AC_LIB_PREFIX])
136+
137+ dnl --------------------------------------------------------------------
138+ dnl Check for libdrizzle
139+ dnl --------------------------------------------------------------------
140+
141+ AC_ARG_ENABLE([libdrizzle],
142+ [AS_HELP_STRING([--disable-libdrizzle],
143+ [Build with libdrizzle support @<:@default=on@:>@])],
144+ [ac_enable_libdrizzle="$enableval"],
145+ [ac_enable_libdrizzle="yes"])
146+
147+ AS_IF([test "x$ac_enable_libdrizzle" = "xyes"],[
148+ AC_LIB_HAVE_LINKFLAGS(drizzle,,[
149+ #include <libdrizzle/drizzle_client.h>
150+ ],[
151+ drizzle_st drizzle;
152+ drizzle_version();
153+ ])
154+ ],[
155+ ac_cv_libdrizzle="no"
156+ ])
157+
158+ AS_IF([test "${ac_cv_libdrizzle}" = "no" -a "${ac_enable_libdrizzle}" = "yes"],[
159+ PKG_CHECK_MODULES([LIBDRIZZLE], [libdrizzle-1.0], [
160+ ac_cv_libdrizzle=yes
161+ LTLIBDRIZZLE=${LIBDRIZZLE_LIBS}
162+ LIBDRIZZLE=${LIBDRIZZLE_LIBS}
163+ CPPFLAGS=${LIBDRIZZLE_CFLAGS} ${CPPFLAGS}
164+ HAVE_LIBDRIZZLE="yes"
165+ AC_SUBST(HAVE_LIBDRIZZLE)
166+ AC_SUBST(LIBDRIZZLE)
167+ AC_SUBST(LTLIBDRIZZLE)
168+ ],[])
169+ ])
170+
171+ AM_CONDITIONAL(HAVE_LIBDRIZZLE, [test "x${ac_cv_libdrizzle}" = "xyes"])
172+])
173+
174+AC_DEFUN([PANDORA_HAVE_LIBDRIZZLE_1_0],[
175+ AC_REQUIRE([_PANDORA_SEARCH_LIBDRIZZLE_1_0])
176+])
177+
178+AC_DEFUN([PANDORA_REQUIRE_LIBDRIZZLE_1_0],[
179+ AC_REQUIRE([PANDORA_HAVE_LIBDRIZZLE_1_0])
180+ AS_IF([test "x${ac_cv_libdrizzle}" = "xno"],[
181+ AC_MSG_ERROR([libdrizzle is required for ${PACKAGE}])
182+ ],[
183+ dnl We need at least 0.8 on Solaris non-sparc
184+ AS_IF([test "$target_cpu" != "sparc" -a "x${TARGET_SOLARIS}" = "xtrue"],[
185+ PANDORA_LIBDRIZZLE_RECENT
186+ ])
187+ ])
188+])
189+
190+AC_DEFUN([PANDORA_LIBDRIZZLE_RECENT],[
191+ AC_CACHE_CHECK([if libdrizzle is recent enough],
192+ [pandora_cv_libdrizzle_recent],
193+ [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
194+#include <libdrizzle/drizzle.h>
195+drizzle_con_options_t foo= DRIZZLE_CON_EXPERIMENTAL;
196+ ]])],
197+ [pandora_cv_libdrizzle_recent=yes],
198+ [pandora_cv_libdrizzle_recent=no])])
199+ AS_IF([test "$pandora_cv_libdrizzle_recent" = "no"],[
200+ AC_MSG_ERROR([Your version of libdrizzle is too old. ${PACKAGE} requires at least version 0.8])
201+ ])
202+])
203
204=== removed file 'm4/pandora_have_libdrizzle.m4'
205--- m4/pandora_have_libdrizzle.m4 2012-04-03 05:13:48 +0000
206+++ m4/pandora_have_libdrizzle.m4 1970-01-01 00:00:00 +0000
207@@ -1,61 +0,0 @@
208-dnl Copyright (C) 2009 Sun Microsystems, Inc.
209-dnl This file is free software; Sun Microsystems, Inc.
210-dnl gives unlimited permission to copy and/or distribute it,
211-dnl with or without modifications, as long as this notice is preserved.
212-
213-AC_DEFUN([_PANDORA_SEARCH_LIBDRIZZLE],[
214- AC_REQUIRE([AC_LIB_PREFIX])
215-
216- dnl --------------------------------------------------------------------
217- dnl Check for libdrizzle
218- dnl --------------------------------------------------------------------
219-
220- AC_ARG_ENABLE([libdrizzle],
221- [AS_HELP_STRING([--disable-libdrizzle],
222- [Build with libdrizzle support @<:@default=on@:>@])],
223- [ac_enable_libdrizzle="$enableval"],
224- [ac_enable_libdrizzle="yes"])
225-
226- AS_IF([test "x$ac_enable_libdrizzle" = "xyes"],[
227- AC_LIB_HAVE_LINKFLAGS(drizzle,,[
228- #include <libdrizzle/drizzle_client.h>
229- ],[
230- drizzle_st drizzle;
231- drizzle_version();
232- ])
233- ],[
234- ac_cv_libdrizzle="no"
235- ])
236-
237- AM_CONDITIONAL(HAVE_LIBDRIZZLE, [test "x${ac_cv_libdrizzle}" = "xyes"])
238-])
239-
240-AC_DEFUN([PANDORA_HAVE_LIBDRIZZLE],[
241- AC_REQUIRE([_PANDORA_SEARCH_LIBDRIZZLE])
242-])
243-
244-AC_DEFUN([PANDORA_REQUIRE_LIBDRIZZLE],[
245- AC_REQUIRE([PANDORA_HAVE_LIBDRIZZLE])
246- AS_IF([test "x${ac_cv_libdrizzle}" = "xno"],[
247- AC_MSG_ERROR([libdrizzle is required for ${PACKAGE}])
248- ],[
249- dnl We need at least 0.8 on Solaris non-sparc
250- AS_IF([test "$target_cpu" != "sparc" -a "x${TARGET_SOLARIS}" = "xtrue"],[
251- PANDORA_LIBDRIZZLE_RECENT
252- ])
253- ])
254-])
255-
256-AC_DEFUN([PANDORA_LIBDRIZZLE_RECENT],[
257- AC_CACHE_CHECK([if libdrizzle is recent enough],
258- [pandora_cv_libdrizzle_recent],
259- [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
260-#include <libdrizzle/drizzle.h>
261-drizzle_con_options_t foo= DRIZZLE_CON_EXPERIMENTAL;
262- ]])],
263- [pandora_cv_libdrizzle_recent=yes],
264- [pandora_cv_libdrizzle_recent=no])])
265- AS_IF([test "$pandora_cv_libdrizzle_recent" = "no"],[
266- AC_MSG_ERROR([Your version of libdrizzle is too old. ${PACKAGE} requires at least version 0.8])
267- ])
268-])
269
270=== added file 'm4/pandora_have_libmysqlclient.m4'
271--- m4/pandora_have_libmysqlclient.m4 1970-01-01 00:00:00 +0000
272+++ m4/pandora_have_libmysqlclient.m4 2012-07-02 18:23:18 +0000
273@@ -0,0 +1,103 @@
274+dnl -*- mode: m4; c-basic-offset: 2; indent-tabs-mode: nil; -*-
275+dnl vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
276+dnl
277+dnl Copyright (C) 2010 Monty Taylor
278+dnl This file is free software; Sun Microsystems
279+dnl gives unlimited permission to copy and/or distribute it,
280+dnl with or without modifications, as long as this notice is preserved.
281+dnl
282+
283+AC_DEFUN([PANDORA_WITH_MYSQL],[
284+ AC_ARG_WITH([mysql],
285+ [AS_HELP_STRING([--with-mysql=PATH],
286+ [path to mysql_config binary or mysql prefix dir])],
287+ [with_mysql=$withval],
288+ [with_mysql=":"])
289+
290+ dnl There are three possibilities:
291+ dnl 1) nothing is given: we will search for mysql_config in PATH
292+ dnl 2) the location of mysql_config is given: we'll use that to determine
293+ dnl 3) a directory argument is given: that will be mysql_base
294+
295+
296+ dnl option 1: nothing, we need to insert something into MYSQL_CONFIG
297+ AS_IF([test "x$with_mysql" = "x:"],[
298+ AC_CHECK_PROGS(MYSQL_CONFIG,[mysql_config])
299+ ],[
300+ MYSQL_CONFIG="${with_mysql}"
301+ ])
302+
303+ AC_CACHE_CHECK([for MySQL Base Location],[pandora_cv_mysql_base],[
304+
305+ dnl option 2: something in MYSQL_CONFIG now, use that to get a base dir
306+ AS_IF([test -f "${MYSQL_CONFIG}" -a -x "${MYSQL_CONFIG}"],[
307+ pandora_cv_mysql_base=$(dirname $(${MYSQL_CONFIG} --include | sed 's/-I//'))
308+ MYSQL_INCLUDES=$(${MYSQL_CONFIG} --include)
309+ MYSQL_INCLUDES="$MYSQL_INCLUDES $(echo $MYSQL_INCLUDES|sed -e 's/-I/-isystem /')"
310+ MYSQL_LIBS=$(${MYSQL_CONFIG} --libs_r)
311+ ],[
312+ dnl option 1: a directory
313+ AS_IF([test -d $with_mysql],
314+ [
315+ pandora_cv_mysql_base=$with_mysql
316+ IBASE="-I${with_mysql}"
317+ MYSQL_CONFIG="${with_mysql}/bin/mysql_config"
318+ MYSQL_INCLUDES="$IBASE/include/mysql -isystem $IBASE/include/mysql"
319+ MYSQL_LIBS="-L${with_mysql}/lib -L${with_mysql}/lib/mysql -lmysqlclient_r"
320+ ],
321+ [
322+ pandora_cv_mysql_base=""
323+ ])
324+ ])
325+ ])
326+ AC_SUBST(MYSQL_CONFIG)
327+ AC_SUBST(MYSQL_INCLUDES)
328+ AC_SUBST(MYSQL_LIBS)
329+])
330+
331+AC_DEFUN([_PANDORA_SEARCH_LIBMYSQLCLIENT],[
332+ AC_REQUIRE([AC_LIB_PREFIX])
333+
334+ AC_ARG_ENABLE([libmysqlclient],
335+ [AS_HELP_STRING([--disable-libmysqlclient],
336+ [Build with libmysqlclient support @<:@default=on@:>@])],
337+ [ac_enable_libmysqlclient="$enableval"],
338+ [ac_enable_libmysqlclient="yes"])
339+
340+ AS_IF([test "x$ac_enable_libmysqlclient" = "xyes"],[
341+ AC_LIB_HAVE_LINKFLAGS(mysqlclient_r,,[
342+#include <mysql/mysql.h>
343+ ],[
344+MYSQL mysql;
345+ ])],[
346+ ac_cv_libmysqlclient_r="no"
347+ ])
348+
349+ AM_CONDITIONAL(HAVE_LIBMYSQLCLIENT, [test "x${ac_cv_libmysqlclient_r}" = "xyes"])
350+
351+ AS_IF([test "x$MYSQL_CONFIG" = "xISDIR"],[
352+ IBASE="-I${with_mysql}"
353+ MYSQL_CONFIG="${with_mysql}/scripts/mysql_config"
354+ ADDIFLAGS="$IBASE/include -isystem $IBASE/include"
355+ ADDLDFLAGS="-L${with_mysql}/libmysql_r/.libs/ -L${with_mysql}/mysys/.libs -L${with_mysql}/mysys -L${with_mysql}/strings/.libs -L${with_mysql}/strings "
356+ ],[
357+ MYSQL_INCLUDES=$(${MYSQL_CONFIG} --include)
358+ MYSQL_INCLUDES="$MYSQL_INCLUDES $(echo $MYSQL_INCLUDES|sed -e 's/-I/-isystem /')"
359+ MYSQL_LIBS=$(${MYSQL_CONFIG} --libs_r)
360+ ])
361+
362+ AC_SUBST(MYSQL_CONFIG)
363+ AC_SUBST(MYSQL_INCLUDES)
364+ AC_SUBST(MYSQL_LIBS)
365+])
366+
367+AC_DEFUN([PANDORA_HAVE_LIBMYSQLCLIENT],[
368+ AC_REQUIRE([_PANDORA_SEARCH_LIBMYSQLCLIENT])
369+])
370+
371+AC_DEFUN([PANDORA_REQUIRE_LIBMYSQLCLIENT],[
372+ AC_REQUIRE([PANDORA_HAVE_LIBMYSQLCLIENT])
373+ AS_IF([test "x${ac_cv_libmysqlclient_r}" = "xno"],
374+ PANDORA_MSG_ERROR([libmysqlclient_r is required for ${PACKAGE}]))
375+])
376+
377
378=== renamed file 'm4/pandora_have_libmysqlclient.m4' => 'm4/pandora_have_libmysqlclient.m4.moved'
379=== modified file 'percona_playback/dispatcher.cc'
380--- percona_playback/dispatcher.cc 2012-06-22 06:20:44 +0000
381+++ percona_playback/dispatcher.cc 2012-07-02 18:23:18 +0000
382@@ -1,3 +1,17 @@
383+/* BEGIN LICENSE
384+ * Copyright (C) 2011-2012 Percona Inc.
385+ * This program is free software: you can redistribute it and/or modify it
386+ * under the terms of the GNU General Public License version 2, as published
387+ * by the Free Software Foundation.
388+ *
389+ * This program is distributed in the hope that it will be useful, but
390+ * WITHOUT ANY WARRANTY; without even the implied warranties of
391+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
392+ * PURPOSE. See the GNU General Public License for more details.
393+ *
394+ * You should have received a copy of the GNU General Public License along
395+ * with this program. If not, see <http://www.gnu.org/licenses/>.
396+ * END LICENSE */
397 #include "percona_playback/dispatcher.h"
398 #include "percona_playback/db_thread.h"
399 #include "percona_playback/plugin.h"
400
401=== modified file 'percona_playback/percona_playback.cc'
402--- percona_playback/percona_playback.cc 2012-06-24 04:28:41 +0000
403+++ percona_playback/percona_playback.cc 2012-07-02 18:23:18 +0000
404@@ -90,18 +90,30 @@
405 std::cerr << std::endl;
406 std::cerr << options_description << std::endl;
407 std::cerr << std::endl;
408+<<<<<<< TREE
409 std::cerr << _("Bugs: ") << PACKAGE_BUGREPORT << std::endl;
410 std::cerr << _("Loaded plugins: ");
411 BOOST_FOREACH(const std::string &plugin_name, PluginRegistry::singleton().loaded_plugin_names)
412+=======
413+ std::cerr << _("Bugs: ") << PACKAGE_BUGREPORT << std::endl;
414+ std::cerr << _("Loaded plugins: ");
415+ BOOST_FOREACH(const std::string &plugin_name, percona_playback::PluginRegistry::singleton().loaded_plugin_names)
416+>>>>>>> MERGE-SOURCE
417 {
418 std::cerr << plugin_name << " ";
419 }
420
421 std::cerr << std::endl;
422
423+<<<<<<< TREE
424 std::cerr << std::endl << _("Loaded DB Plugins: ");
425 for(PluginRegistry::DBClientPluginMap::iterator it= PluginRegistry::singleton().dbclient_plugins.begin();
426 it != PluginRegistry::singleton().dbclient_plugins.end();
427+=======
428+ std::cerr << std::endl << _("Loaded DB Plugins: ");
429+ for(percona_playback::PluginRegistry::DBClientPluginMap::iterator it= percona_playback::PluginRegistry::singleton().dbclient_plugins.begin();
430+ it != percona_playback::PluginRegistry::singleton().dbclient_plugins.end();
431+>>>>>>> MERGE-SOURCE
432 it++)
433 {
434 std::cerr << it->first << " ";
435@@ -110,12 +122,21 @@
436 std::cerr << std::endl;
437
438 assert(g_dbclient_plugin);
439+<<<<<<< TREE
440 std::cerr << _("Selected DB Plugin: ") << g_dbclient_plugin->name << std::endl;
441
442 std::cerr << std::endl << _("Loaded Input Plugins: ");
443
444 BOOST_FOREACH(const PluginRegistry::InputPluginPair &pp,
445 PluginRegistry::singleton().input_plugins)
446+=======
447+ std::cerr << _("Selected DB Plugin: ") << g_dbclient_plugin->name << std::endl;
448+
449+ std::cerr << std::endl << _("Loaded Input Plugins: ");
450+
451+ BOOST_FOREACH(const percona_playback::PluginRegistry::InputPluginPair &pp,
452+ percona_playback::PluginRegistry::singleton().input_plugins)
453+>>>>>>> MERGE-SOURCE
454 {
455 std::cerr << pp.first << " ";
456 }
457
458=== modified file 'percona_playback/query_result.h'
459--- percona_playback/query_result.h 2012-06-18 23:59:46 +0000
460+++ percona_playback/query_result.h 2012-07-02 18:23:18 +0000
461@@ -40,6 +40,13 @@
462 {
463 }
464
465+ void clear()
466+ {
467+ _rows_sent= _rows_examined= 0;
468+ _error= _warning_count= 0;
469+ _duration= boost::posix_time::time_duration();
470+ }
471+
472 void setRowsSent(const uint64_t &rows) {
473 _rows_sent= rows;
474 }
475
476=== added file 'percona_playback/tcpdump/connection_state.cc'
477--- percona_playback/tcpdump/connection_state.cc 1970-01-01 00:00:00 +0000
478+++ percona_playback/tcpdump/connection_state.cc 2012-07-02 18:23:18 +0000
479@@ -0,0 +1,325 @@
480+/* BEGIN LICENSE
481+ * Copyright (C) 2011-2012 Percona Inc.
482+ * This program is free software: you can redistribute it and/or modify it
483+ * under the terms of the GNU General Public License version 2, as published
484+ * by the Free Software Foundation.
485+ *
486+ * This program is distributed in the hope that it will be useful, but
487+ * WITHOUT ANY WARRANTY; without even the implied warranties of
488+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
489+ * PURPOSE. See the GNU General Public License for more details.
490+ *
491+ * You should have received a copy of the GNU General Public License along
492+ * with this program. If not, see <http://www.gnu.org/licenses/>.
493+ * END LICENSE */
494+#include <pcap.h>
495+#include <iostream>
496+#include <libdrizzle/drizzle_server.h>
497+#include <libdrizzle/row_client.h>
498+#include <stdio.h>
499+#include <stdint.h>
500+#include <assert.h>
501+
502+#include "connection_state.h"
503+#include "tcpdump_query_entries.h"
504+#include "percona_playback/plugin.h"
505+
506+extern percona_playback::DBClientPlugin *g_dbclient_plugin;
507+
508+void
509+ConnectionState::ProcessMysqlPkts(const u_char *pkts,
510+ u_int pkts_len,
511+ const timeval &ts,
512+ const AddrPort &addr_port,
513+ OUT TcpdumpMysqlParserStats &stats)
514+{
515+
516+ u_int used_len= 0;
517+ struct MysqlPkt *m;
518+
519+ assert(pkts);
520+
521+ // If last pkt was fragmented, merge with current pkts
522+ if (fragmented)
523+ {
524+ fragmented= false;
525+ size_t old_frag_buff_size= frag_buff.size();
526+ frag_buff.insert(frag_buff.end(), pkts, pkts + pkts_len);
527+ pkts= &frag_buff[0];
528+ pkts_len+= old_frag_buff_size;
529+ }
530+
531+ for(;;)
532+ {
533+ m= (struct MysqlPkt *)pkts; // Packet header
534+
535+ // Check if pkts > len of pkts actually received (last pkt is fragmented)
536+ used_len+= m->full_length();
537+
538+ if (used_len > pkts_len) {
539+ fragmented= true;
540+
541+ size_t frag_len= m->full_length() - (used_len - pkts_len);
542+
543+ UCharBuffer new_frag_buff(pkts, pkts + frag_len);
544+ frag_buff.swap(new_frag_buff);
545+
546+ break;
547+ }
548+
549+ if (m->data_length())
550+ {
551+ UCharBuffer buff(pkts, pkts + m->full_length());
552+ std::string query;
553+ PktResult retval= ParseMysqlPkt(buff, query);
554+ switch(retval)
555+ {
556+ case PKT_QUERY:
557+ if (!query.empty())
558+ DispatchQuery(ts, query, addr_port);
559+ ++stats.nr_of_parsed_queries;
560+ ++stats.nr_of_parsed_packets;
561+ break;
562+
563+ case PKT_RESULT:
564+ DispatchResult(ts, addr_port);
565+ ++stats.nr_of_parsed_packets;
566+ break;
567+
568+ case PKT_ERROR:
569+ ++stats.nr_of_parsing_errors;
570+ break;
571+
572+ default:
573+ ++stats.nr_of_parsed_packets;
574+ }
575+ }
576+
577+ pkts += m->full_length(); // Next pkt header
578+
579+ if (used_len == pkts_len)
580+ break;
581+
582+ }
583+
584+ if (!fragmented)
585+ frag_buff.clear();
586+
587+}
588+
589+void
590+ConnectionState::ProcessFinishConnection()
591+{
592+ db_thread->queries.push(QueryEntryPtr(new FinishEntry()));
593+}
594+
595+PktResult
596+ConnectionState::ParseMysqlPkt(IN UCharBuffer &buff,
597+ OUT std::string &query)
598+{
599+ if (current_origin == CLIENT)
600+ return ClientPacket(buff, query);
601+
602+ if (current_origin == SERVER && was_query)
603+ return ServerPacket(buff);
604+
605+ return PKT_UNKNOWN;
606+}
607+
608+PktResult
609+ConnectionState::ServerPacket(IN UCharBuffer &buff)
610+{
611+ PktResult retval= PKT_OK;
612+
613+ drizzle_return_t ret;
614+
615+ drizzle_con->buffer_ptr= &buff[0];
616+ drizzle_con->buffer_size= buff.size();
617+
618+ /*
619+ Check if we should continue parsing result set or
620+ we can start a new loop of result parsing.
621+ */
622+ if (!drizzle_con->result)
623+ {
624+ /*
625+ If there are not any parsed results then it can be "Ok",
626+ "Error" or "Results set header" packets.
627+ */
628+ last_query_result.clear();
629+
630+ drizzle_result_st *res= drizzle_result_read(drizzle_con.get(),
631+ NULL,
632+ &ret);
633+ /* Check if the packet is "Error" packet */
634+ if (ret == DRIZZLE_RETURN_ERROR_CODE)
635+ {
636+ last_query_result.setError(drizzle_result_error_code(res));
637+ retval= PKT_RESULT;
638+ /*
639+ The text representation of error can be got with
640+ drizzle_result_error(res)
641+ */
642+ goto free_and_return;
643+ }
644+ else if(ret == DRIZZLE_RETURN_OK)
645+ {
646+ /* Check if the packet is "Ok" packet */
647+ if (!drizzle_result_column_count(res))
648+ {
649+ last_query_result.setRowsSent(drizzle_result_row_count(res));
650+ last_query_result.setRowsExamined(drizzle_result_affected_rows(res));
651+ last_query_result.setWarningCount(drizzle_result_warning_count(res));
652+ retval= PKT_RESULT;
653+ goto free_and_return;
654+ }
655+ /* Else this is "Result set header" packet */
656+ }
657+ else
658+ {
659+ std::cerr << "Unknown packet type from server" << std::endl;
660+ retval= PKT_ERROR;
661+ goto free_and_return;
662+ }
663+ }
664+ /* Parse result set */
665+ else
666+ {
667+ /* "Field" packets */
668+ if (eof_count == 0)
669+ {
670+ drizzle_column_st *column= drizzle_column_read(drizzle_con->result,
671+ NULL,
672+ &ret);
673+ if (ret == DRIZZLE_RETURN_OK)
674+ {
675+ /* "EOF" packet */
676+ if (column == NULL)
677+ ++eof_count;
678+ retval= PKT_OK;
679+ }
680+ else
681+ {
682+ std::cerr << "Parse column error" << std::endl;
683+ retval= PKT_ERROR;
684+ goto free_and_return;
685+ }
686+ }
687+ /* "Row" packets */
688+ else if (eof_count == 1)
689+ {
690+ uint8_t old_packet_number= drizzle_con->packet_number;
691+ uint64_t row= drizzle_row_read(drizzle_con->result, &ret);
692+ if (ret != DRIZZLE_RETURN_OK)
693+ {
694+ std::cerr << "Error in parsing row" << std::endl;
695+ retval= PKT_ERROR;
696+ goto free_and_return;
697+ }
698+ else
699+ ++sent_rows_count;
700+ /* "EOF" packet */
701+ if (!row)
702+ {
703+ eof_count= 0;
704+
705+ drizzle_con->buffer_ptr= &buff[0];
706+ drizzle_con->buffer_size= buff.size();
707+
708+ drizzle_result_free_all(drizzle_con.get());
709+ drizzle_con->packet_number= old_packet_number;
710+ drizzle_result_st *res= drizzle_result_read(drizzle_con.get(),
711+ NULL,
712+ &ret);
713+ /*
714+ Setting DRIZZLE_RESULT_ALLOCATED in result options
715+ helps to avoid memory leak.
716+ See https://bugs.launchpad.net/drizzle/+bug/1015576
717+ */
718+ res->options=
719+ (drizzle_result_options_t)
720+ ((uint64_t)(res->options) | (uint64_t)DRIZZLE_RESULT_ALLOCATED);
721+ last_query_result.setWarningCount(drizzle_result_warning_count(res));
722+ /* Don't count the last EOF packet */
723+ last_query_result.setRowsSent(sent_rows_count - 1);
724+
725+ sent_rows_count= 0;
726+ retval= PKT_RESULT;
727+ goto free_and_return;
728+ }
729+ else
730+ retval= PKT_OK;
731+ }
732+ }
733+
734+ return retval;
735+
736+free_and_return:
737+ drizzle_result_free_all(drizzle_con.get());
738+ drizzle_con->result= NULL;
739+ was_query= false;
740+ return retval;
741+}
742+
743+PktResult
744+ConnectionState::ClientPacket(IN UCharBuffer &buff,
745+ OUT std::string &query)
746+{
747+ drizzle_command_t command;
748+ drizzle_return_t ret;
749+ size_t total;
750+ uint8_t *data;
751+ PktResult result= PKT_UNKNOWN;
752+
753+ drizzle_con->buffer_ptr= &buff[0];
754+ drizzle_con->buffer_size= buff.size();
755+ data= (uint8_t *)drizzle_con_command_buffer(drizzle_con.get(),
756+ &command,
757+ &total,
758+ &ret);
759+ if (ret == DRIZZLE_RETURN_OK)
760+ {
761+ switch(command)
762+ {
763+ case DRIZZLE_COMMAND_QUERY:
764+ query.assign((const char *)data);
765+ was_query= true;
766+ result= PKT_QUERY;
767+ break;
768+
769+ case DRIZZLE_COMMAND_INIT_DB:
770+ query.assign("use ");
771+ query+= (const char *)data;
772+ was_query= true;
773+ result= PKT_QUERY;
774+ break;
775+
776+ default:;
777+ }
778+ }
779+
780+ free(data);
781+ return result;
782+}
783+
784+void
785+ConnectionState::DispatchQuery(const timeval &ts,
786+ const std::string &query,
787+ const AddrPort &addr_port)
788+{
789+ boost::shared_ptr<TcpdumpQueryEntry>
790+ query_entry(new TcpdumpQueryEntry(ts,
791+ query,
792+ addr_port));
793+ db_thread->queries.push(query_entry);
794+}
795+
796+void
797+ConnectionState::DispatchResult(const timeval &ts,
798+ const AddrPort &addr_port)
799+{
800+ boost::shared_ptr<TcpdumpResultEntry>
801+ result_entry(new TcpdumpResultEntry(addr_port, ts, last_query_result));
802+ db_thread->queries.push(result_entry);
803+}
804+
805
806=== added file 'percona_playback/tcpdump/connection_state.h'
807--- percona_playback/tcpdump/connection_state.h 1970-01-01 00:00:00 +0000
808+++ percona_playback/tcpdump/connection_state.h 2012-07-02 18:23:18 +0000
809@@ -0,0 +1,186 @@
810+/* BEGIN LICENSE
811+ * Copyright (C) 2011 Percona Inc.
812+ * This program is free software: you can redistribute it and/or modify it
813+ * under the terms of the GNU General Public License version 2, as published
814+ * by the Free Software Foundation.
815+ *
816+ * This program is distributed in the hope that it will be useful, but
817+ * WITHOUT ANY WARRANTY; without even the implied warranties of
818+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
819+ * PURPOSE. See the GNU General Public License for more details.
820+ *
821+ * You should have received a copy of the GNU General Public License along
822+ * with this program. If not, see <http://www.gnu.org/licenses/>.
823+ * END LICENSE */
824+
825+#ifndef PERCONA_PLAYBACK_CONNECTION_STATE_H
826+#define PERCONA_PLAYBACK_CONNECTION_STATE_H
827+
828+#include <stdlib.h>
829+#include <sys/time.h>
830+#include <vector>
831+#include <string>
832+#include <string.h>
833+#include <boost/shared_ptr.hpp>
834+#include <libdrizzle/drizzle_client.h>
835+
836+#include "percona_playback/query_result.h"
837+#include "percona_playback/db_thread.h"
838+#include "tcpdump_mysql_parser_stats.h"
839+
840+enum PktResult
841+{
842+ PKT_QUERY,
843+ PKT_RESULT,
844+ PKT_OK,
845+ PKT_UNKNOWN,
846+ PKT_ERROR
847+};
848+
849+#define IN
850+#define OUT
851+
852+#pragma pack(push, 1)
853+// Every logical MySQL packet starts w/ this 4 byte header
854+struct MysqlPkt {
855+ uint16_t length_low;
856+ uint8_t length_high;
857+ uint8_t id;
858+ uint8_t data[0];
859+
860+ size_t data_length() const
861+ {
862+ return (size_t)length_low | ((size_t)length_high << 16);
863+ }
864+
865+ size_t full_length() const
866+ {
867+ return data_length() + header_size();
868+ }
869+
870+ static size_t header_size()
871+ {
872+ return offsetof(MysqlPkt, data);
873+ }
874+};
875+#pragma pack(pop)
876+
877+struct AddrPort
878+{
879+ AddrPort() : address(0), port(0) {}
880+ AddrPort(uint32_t address, uint16_t port) : address(address), port(port) {}
881+ uint32_t address;
882+ uint16_t port;
883+ uint64_t ThreadId() const
884+ {
885+ return (uint64_t)address | ((uint64_t)port << 32);
886+ }
887+};
888+
889+struct LastExecutedQueryInfo
890+{
891+ std::string query;
892+ QueryResult result;
893+ timeval begin_pcap_timestamp;
894+ timeval end_pcap_timestamp;
895+ timeval end_timestamp;
896+
897+ LastExecutedQueryInfo()
898+ {
899+ memset(&begin_pcap_timestamp, 0, sizeof(begin_pcap_timestamp));
900+ memset(&end_pcap_timestamp, 0, sizeof(end_pcap_timestamp));
901+ memset(&end_timestamp, 0, sizeof(end_timestamp));
902+ }
903+};
904+
905+
906+class ConnectionState : public DBThreadState
907+
908+{
909+
910+public:
911+
912+ enum Origin
913+ {
914+ UNDEF,
915+ CLIENT,
916+ SERVER
917+ };
918+
919+ ConnectionState() :
920+ current_origin(UNDEF),
921+ fragmented(false),
922+ handshake_from_client(false),
923+ was_query(false),
924+ eof_count(0),
925+ sent_rows_count(0),
926+ drizzle(drizzle_create(NULL), drizzle_free),
927+ drizzle_con(
928+ drizzle_con_add_tcp(drizzle.get(),
929+ NULL,
930+ "localhost",
931+ 3306,
932+ "user",
933+ "password",
934+ "db",
935+ (drizzle_con_options_t)
936+ DRIZZLE_CON_MYSQL),
937+ drizzle_con_free),
938+ db_thread(NULL)
939+ {
940+ drizzle_con->result= NULL;
941+ }
942+
943+ ~ConnectionState()
944+ {
945+ drizzle_result_free_all(drizzle_con.get());
946+ }
947+
948+ void ProcessMysqlPkts(const u_char *pkts,
949+ u_int total_len,
950+ const timeval &ts,
951+ const AddrPort &addr_port,
952+ OUT TcpdumpMysqlParserStats &stats);
953+
954+ void ProcessFinishConnection();
955+
956+ void SetCurrentOrigin(Origin o) { current_origin = o; }
957+
958+ void SetDBThread(DBThread *t) { db_thread= t; }
959+
960+ LastExecutedQueryInfo last_executed_query_info;
961+
962+private:
963+
964+ typedef std::vector<unsigned char> UCharBuffer;
965+
966+ PktResult ParseMysqlPkt(IN UCharBuffer &buff, OUT std::string &query);
967+
968+ PktResult ServerPacket(IN UCharBuffer &buff);
969+ PktResult ClientPacket(IN UCharBuffer &buff, OUT std::string &query);
970+
971+ void DispatchQuery(const timeval &ts,
972+ const std::string &query,
973+ const AddrPort &addr_port);
974+
975+ void DispatchResult(const timeval &ts,
976+ const AddrPort &addr_port);
977+
978+ Origin current_origin;
979+ bool fragmented;
980+ UCharBuffer frag_buff;
981+ bool handshake_from_client;
982+ bool was_query;
983+ size_t eof_count;
984+ size_t sent_rows_count;
985+
986+ boost::shared_ptr<drizzle_st> drizzle;
987+ boost::shared_ptr<drizzle_con_st> drizzle_con;
988+
989+ QueryResult last_query_result;
990+
991+ DBThread *db_thread;
992+
993+};
994+
995+#endif // PERCONA_PLAYBACK_CONNECTION_STATE_H
996
997=== added file 'percona_playback/tcpdump/pcap_packets_parser.cc'
998--- percona_playback/tcpdump/pcap_packets_parser.cc 1970-01-01 00:00:00 +0000
999+++ percona_playback/tcpdump/pcap_packets_parser.cc 2012-07-02 18:23:18 +0000
1000@@ -0,0 +1,134 @@
1001+/* BEGIN LICENSE
1002+ * Copyright (C) 2011-2012 Percona Inc.
1003+ * This program is free software: you can redistribute it and/or modify it
1004+ * under the terms of the GNU General Public License version 2, as published
1005+ * by the Free Software Foundation.
1006+ *
1007+ * This program is distributed in the hope that it will be useful, but
1008+ * WITHOUT ANY WARRANTY; without even the implied warranties of
1009+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1010+ * PURPOSE. See the GNU General Public License for more details.
1011+ *
1012+ * You should have received a copy of the GNU General Public License along
1013+ * with this program. If not, see <http://www.gnu.org/licenses/>.
1014+ * END LICENSE */
1015+#include "pcap_packets_parser.h"
1016+#include "sniff_headers.h"
1017+#include "tcpdump.h"
1018+
1019+#include "percona_playback/db_thread.h"
1020+#include "percona_playback/plugin.h"
1021+#include "percona_playback/dispatcher.h"
1022+
1023+#include <netinet/in.h>
1024+#include <arpa/inet.h>
1025+#include <iostream>
1026+#include <boost/foreach.hpp>
1027+#include <assert.h>
1028+
1029+#define SNAP_LEN 16500 // pcap's max capture size
1030+
1031+extern percona_playback::DBClientPlugin *g_dbclient_plugin;
1032+
1033+void
1034+PcapPacketsParser::ParsePkt(const struct pcap_pkthdr *header,
1035+ const u_char *packet)
1036+{
1037+ ConnectionState::Origin origin= ConnectionState::UNDEF;
1038+ const struct sniff_ethernet *ethernet;
1039+ const struct sniff_ip *ip;
1040+ const struct sniff_tcp *tcp;
1041+ const uint8_t *mysql;
1042+ size_t size_ip;
1043+ size_t size_tcp;
1044+ size_t size_mysql;
1045+
1046+ assert(header);
1047+ assert(packet);
1048+
1049+ if(header->len > SNAP_LEN) {
1050+ std::cerr << "Captured packet too large: "
1051+ << header->len
1052+ << " bytes, Max capture packet size: "
1053+ << SNAP_LEN << " bytes" << std::endl;
1054+ return;
1055+ }
1056+
1057+ ethernet= (struct sniff_ethernet*)(packet);
1058+ ip= (struct sniff_ip*)(packet + SIZE_ETHERNET);
1059+ size_ip= IP_HL(ip) * 4;
1060+ tcp= (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip);
1061+ size_tcp= TH_OFF(tcp) * 4;
1062+ mysql= (packet + SIZE_ETHERNET + size_ip + size_tcp);
1063+ size_mysql= ntohs(ip->ip_len) - size_ip - size_tcp;
1064+
1065+
1066+ AddrPort addr_port;
1067+
1068+ if (ntohs(tcp->th_sport) == g_tcpdump_port)
1069+ {
1070+ addr_port.address= ip->ip_dst.s_addr;
1071+ addr_port.port= tcp->th_dport;
1072+ origin= ConnectionState::SERVER;
1073+ }
1074+ else
1075+ {
1076+ addr_port.address= ip->ip_src.s_addr;
1077+ addr_port.port= tcp->th_sport;
1078+ origin= ConnectionState::CLIENT;
1079+ }
1080+
1081+ /* The connection was closed. */
1082+ if (size_mysql == 0 &&
1083+ ((tcp->th_flags & TH_FIN) || (tcp->th_flags & TH_RST)))
1084+ {
1085+ g_dispatcher.finish(addr_port.ThreadId());
1086+ return;
1087+ }
1088+
1089+ /* The mysql packet is too small. It may be due to tcp service packets. */
1090+ if (size_mysql < MysqlPkt::header_size())
1091+ return;
1092+
1093+ if (!was_first_packet)
1094+ {
1095+ gettimeofday(&first_packet_timestamp, 0);
1096+ first_packet_pcap_timestamp= header->ts;
1097+ was_first_packet= true;
1098+ }
1099+
1100+ /* If there is no DBThread with such id create it */
1101+ boost::shared_ptr<DBThreadState>
1102+ state= g_dispatcher.get_thread_state(addr_port.ThreadId(),
1103+ boost::bind(&PcapPacketsParser::CreateConnectionState,
1104+ this,
1105+ _1));
1106+
1107+ assert(state.get());
1108+
1109+ ((ConnectionState *)state.get())->SetCurrentOrigin(origin);
1110+ ((ConnectionState *)state.get())->ProcessMysqlPkts(mysql,
1111+ size_mysql,
1112+ header->ts,
1113+ addr_port,
1114+ stats);
1115+}
1116+
1117+void
1118+PcapPacketsParser::WaitForUnfinishedTasks()
1119+{
1120+ g_dispatcher.finish_all_and_wait();
1121+}
1122+
1123+void
1124+PcapPacketsParser::CreateConnectionState(DBThread *db_thread)
1125+{
1126+ assert(db_thread);
1127+ boost::shared_ptr<ConnectionState> state(new ConnectionState());
1128+ state->last_executed_query_info.end_pcap_timestamp=
1129+ first_packet_pcap_timestamp;
1130+ state->last_executed_query_info.end_timestamp=
1131+ first_packet_timestamp;
1132+ db_thread->set_state(state);
1133+ state->SetDBThread(db_thread);
1134+}
1135
1136=== added file 'percona_playback/tcpdump/pcap_packets_parser.h'
1137--- percona_playback/tcpdump/pcap_packets_parser.h 1970-01-01 00:00:00 +0000
1138+++ percona_playback/tcpdump/pcap_packets_parser.h 2012-07-02 18:23:18 +0000
1139@@ -0,0 +1,64 @@
1140+/* BEGIN LICENSE
1141+ * Copyright (C) 2011 Percona Inc.
1142+ * This program is free software: you can redistribute it and/or modify it
1143+ * under the terms of the GNU General Public License version 2, as published
1144+ * by the Free Software Foundation.
1145+ *
1146+ * This program is distributed in the hope that it will be useful, but
1147+ * WITHOUT ANY WARRANTY; without even the implied warranties of
1148+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1149+ * PURPOSE. See the GNU General Public License for more details.
1150+ *
1151+ * You should have received a copy of the GNU General Public License along
1152+ * with this program. If not, see <http://www.gnu.org/licenses/>.
1153+ * END LICENSE */
1154+
1155+#ifndef PERCONA_PLAYBACK_PCAP_PACKETS_PARSER_H
1156+#define PERCONA_PLAYBACK_PCAP_PACKETS_PARSER_H
1157+
1158+#include "connection_state.h"
1159+#include "tcpdump_mysql_parser_stats.h"
1160+
1161+#include <pcap.h>
1162+#include <tbb/concurrent_queue.h>
1163+#include <boost/thread.hpp>
1164+#include <boost/bind.hpp>
1165+
1166+class DBThread;
1167+
1168+class PcapPacketsParser
1169+{
1170+ TcpdumpMysqlParserStats stats;
1171+ timeval first_packet_timestamp;
1172+ timeval first_packet_pcap_timestamp;
1173+ bool was_first_packet;
1174+
1175+public:
1176+
1177+ PcapPacketsParser() : was_first_packet(false)
1178+ {
1179+ first_packet_timestamp.tv_sec= first_packet_timestamp.tv_usec= 0;
1180+ first_packet_pcap_timestamp.tv_sec= first_packet_pcap_timestamp.tv_usec= 0;
1181+ }
1182+
1183+ static void Process(u_char *arg,
1184+ const struct pcap_pkthdr *header,
1185+ const u_char *packet)
1186+ {
1187+ ((PcapPacketsParser *)arg)->ParsePkt(header, packet);
1188+ }
1189+
1190+ const TcpdumpMysqlParserStats &GetStats() const { return stats; }
1191+
1192+ void WaitForUnfinishedTasks();
1193+
1194+ void CreateConnectionState(DBThread *db_thread);
1195+
1196+private:
1197+
1198+ void ParsePkt(const struct pcap_pkthdr *header,
1199+ const u_char *packet);
1200+
1201+};
1202+
1203+#endif //PERCONA_PLAYBACK_PCAP_PACKETS_PARSER_H
1204
1205=== modified file 'percona_playback/tcpdump/plugin.ac'
1206--- percona_playback/tcpdump/plugin.ac 2012-06-19 01:09:31 +0000
1207+++ percona_playback/tcpdump/plugin.ac 2012-07-02 18:23:18 +0000
1208@@ -1,2 +1,2 @@
1209 PANDORA_HAVE_LIBPCAP
1210-PANDORA_HAVE_LIBDRIZZLE
1211+PANDORA_HAVE_LIBDRIZZLE_1_0
1212
1213=== modified file 'percona_playback/tcpdump/plugin.ini'
1214--- percona_playback/tcpdump/plugin.ini 2012-06-19 01:09:31 +0000
1215+++ percona_playback/tcpdump/plugin.ini 2012-07-02 18:23:18 +0000
1216@@ -6,4 +6,6 @@
1217 headers=tcpdump.h
1218 load_by_default=yes
1219 ldflags=${PCAP_LIBS} ${LTLIBDRIZZLE} ${LDFLAGS}
1220-cppflags=${PCAP_INCLUDES} ${CPPFLAGS}
1221+cppflags=${PCAP_INCLUDES} ${CPPFLAGS}
1222+headers=tcpdump.h sniff_headers.h connection_state.h pcap_packets_parser.h tcpdump_query_entries.h tcpdump_mysql_parser_stats.h
1223+sources=tcpdump.cc connection_state.cc pcap_packets_parser.cc tcpdump_query_entries.cc
1224
1225=== added file 'percona_playback/tcpdump/sniff_headers.h'
1226--- percona_playback/tcpdump/sniff_headers.h 1970-01-01 00:00:00 +0000
1227+++ percona_playback/tcpdump/sniff_headers.h 2012-07-02 18:23:18 +0000
1228@@ -0,0 +1,59 @@
1229+/* ethernet headers are always exactly 14 bytes [1] */
1230+#define SIZE_ETHERNET 14
1231+
1232+/* Ethernet addresses are 6 bytes */
1233+#define ETHER_ADDR_LEN 6
1234+
1235+//#pragma pack(push, 1)
1236+/* Ethernet header */
1237+struct sniff_ethernet {
1238+ u_char ether_dhost[ETHER_ADDR_LEN]; /* destination host address */
1239+ u_char ether_shost[ETHER_ADDR_LEN]; /* source host address */
1240+ u_short ether_type; /* IP? ARP? RARP? etc */
1241+};
1242+
1243+/* IP header */
1244+struct sniff_ip {
1245+ u_char ip_vhl; /* version << 4 | header length >> 2 */
1246+ u_char ip_tos; /* type of service */
1247+ u_short ip_len; /* total length */
1248+ u_short ip_id; /* identification */
1249+ u_short ip_off; /* fragment offset field */
1250+ #define IP_RF 0x8000 /* reserved fragment flag */
1251+ #define IP_DF 0x4000 /* dont fragment flag */
1252+ #define IP_MF 0x2000 /* more fragments flag */
1253+ #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
1254+ u_char ip_ttl; /* time to live */
1255+ u_char ip_p; /* protocol */
1256+ u_short ip_sum; /* checksum */
1257+ struct in_addr ip_src,ip_dst; /* source and dest address */
1258+};
1259+#define IP_HL(ip) (((ip)->ip_vhl) & 0x0f)
1260+#define IP_V(ip) (((ip)->ip_vhl) >> 4)
1261+
1262+/* TCP header */
1263+typedef u_int tcp_seq;
1264+
1265+struct sniff_tcp {
1266+ u_short th_sport; /* source port */
1267+ u_short th_dport; /* destination port */
1268+ tcp_seq th_seq; /* sequence number */
1269+ tcp_seq th_ack; /* acknowledgement number */
1270+ u_char th_offx2; /* data offset, rsvd */
1271+#define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4)
1272+ u_char th_flags;
1273+ #define TH_FIN 0x01
1274+ #define TH_SYN 0x02
1275+ #define TH_RST 0x04
1276+ #define TH_PUSH 0x08
1277+ #define TH_ACK 0x10
1278+ #define TH_URG 0x20
1279+ #define TH_ECE 0x40
1280+ #define TH_CWR 0x80
1281+ #define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
1282+ u_short th_win; /* window */
1283+ u_short th_sum; /* checksum */
1284+ u_short th_urp; /* urgent pointer */
1285+};
1286+
1287+//#pragma pack(pop)
1288
1289=== modified file 'percona_playback/tcpdump/tcpdump.cc'
1290--- percona_playback/tcpdump/tcpdump.cc 2012-06-19 01:09:31 +0000
1291+++ percona_playback/tcpdump/tcpdump.cc 2012-07-02 18:23:18 +0000
1292@@ -14,15 +14,54 @@
1293 * END LICENSE */
1294
1295 #include "tcpdump.h"
1296+#include "pcap_packets_parser.h"
1297+
1298+#include "percona_playback/percona_playback.h"
1299+
1300 #include <stdio.h>
1301+#include <pcap.h>
1302+
1303+#define FILTER_EXP_SIZE 11 // max filter expression size
1304+
1305+std::string g_tcpdump_file_name;
1306+uint16_t g_tcpdump_port;
1307+TcpdumpPluginMode g_tcpdump_mode;
1308+
1309+std::istream& operator>>(std::istream& in, TcpdumpPluginMode& unit)
1310+{
1311+ std::string token;
1312+ in >> token;
1313+ if (token == "fast")
1314+ unit = TCPDUMP_MODE_FAST;
1315+ else if (token == "accurate")
1316+ unit = TCPDUMP_MODE_ACCURATE;
1317+ else
1318+ throw
1319+ boost::program_options::validation_error(
1320+ "Allowed input-type values are (fast|accurate)"
1321+ );
1322+ return in;
1323+}
1324
1325 boost::program_options::options_description*
1326 TcpDumpParserPlugin::getProgramOptions()
1327 {
1328 options.add_options()
1329 ("tcpdump-file",
1330- boost::program_options::value<std::string>(&file_name),
1331- "Tcpdump file name");
1332+ boost::program_options::value<std::string>(&g_tcpdump_file_name),
1333+ "Tcpdump file name")
1334+ ("tcpdump-port",
1335+ boost::program_options::value<uint16_t>(&g_tcpdump_port)
1336+ ->default_value(3306),
1337+ "Tcpdump port")
1338+ ("tcpdump-mode",
1339+ boost::program_options::value<TcpdumpPluginMode>(&g_tcpdump_mode)
1340+ ->multitoken()->default_value(TCPDUMP_MODE_FAST, "fast"),
1341+ "The mode of tcpdump plugin (fast|accurate), in 'fast' mode "
1342+ "the plugin executes queries as fast as it can whereas in "
1343+ "'accurate' mode the plugin preserves queries execution time "
1344+ "and pauses between queries")
1345+ ;
1346
1347 return &options;
1348 }
1349@@ -32,7 +71,9 @@
1350 boost::program_options::variables_map &vm)
1351 {
1352 if (!active &&
1353- (vm.count("tcpdump-file")))
1354+ (vm.count("tcpdump-file") ||
1355+ !vm["tcpdump-port"].defaulted() ||
1356+ !vm["tcpdump-mode"].defaulted()))
1357 {
1358 fprintf(stderr,
1359 gettext("tcpdump plugin is not selected, "
1360@@ -40,9 +81,87 @@
1361 "command line options\n"));
1362 return -1;
1363 }
1364+
1365+ if (!active)
1366+ return 0;
1367+
1368+ if (!vm.count("tcpdump-file"))
1369+ {
1370+ fprintf(stderr,
1371+ gettext("tcpdump-file argument is requred\n"));
1372+ return -1;
1373+ }
1374+
1375 return 0;
1376 }
1377
1378+void
1379+TcpDumpParserPlugin::run(percona_playback_run_result &r)
1380+{
1381+ char errbuf[PCAP_ERRBUF_SIZE];
1382+ pcap_t *handle;
1383+ struct bpf_program fp;
1384+ char filter_exp[11];
1385+ PcapPacketsParser packets_parser;
1386+
1387+
1388+ if (g_tcpdump_file_name.empty())
1389+ {
1390+ r.err= -1;
1391+ return;
1392+ }
1393+
1394+ handle = pcap_open_offline(g_tcpdump_file_name.c_str(), errbuf);
1395+
1396+ if (handle == NULL)
1397+ {
1398+ std::cerr << "Couldn't open file " << g_tcpdump_file_name << ": "
1399+ << errbuf << std::endl;
1400+ r.err= -1;
1401+ return;
1402+ }
1403+
1404+ snprintf(filter_exp, FILTER_EXP_SIZE, "port %u", (unsigned)g_tcpdump_port);
1405+
1406+ if(pcap_compile(handle, &fp, filter_exp, 0, 0) == -1)
1407+ {
1408+ std::cerr << "Couldn't parse filter " << filter_exp << ": "
1409+ << pcap_geterr(handle) << std::endl;
1410+ r.err= -1;
1411+ return;
1412+ }
1413+
1414+ if (pcap_setfilter(handle, &fp) == -1)
1415+ {
1416+ std::cerr << "Couldn't install filter " << filter_exp << ": "
1417+ << pcap_geterr(handle) << std::endl;
1418+ r.err= -1;
1419+ return;
1420+ }
1421+
1422+ if (pcap_loop(handle,
1423+ -1,
1424+ PcapPacketsParser::Process,
1425+ (u_char *)&packets_parser) < 0)
1426+ {
1427+ std::cerr << "pcap_loop error "
1428+ << pcap_geterr(handle) << std::endl;
1429+ r.err= -1;
1430+ return;
1431+ }
1432+
1433+ /* Wait for unfinished DBThreads */
1434+ packets_parser.WaitForUnfinishedTasks();
1435+
1436+ const TcpdumpMysqlParserStats &stats= packets_parser.GetStats();
1437+
1438+ r.n_log_entries= stats.nr_of_parsed_packets;
1439+ r.n_queries= stats.nr_of_parsed_queries;
1440+ r.err= stats.nr_of_parsing_errors;
1441+
1442+ return;
1443+}
1444+
1445 static void init_plugin(percona_playback::PluginRegistry &r)
1446 {
1447 r.add("tcpdump", new TcpDumpParserPlugin("tcpdump"));
1448
1449=== modified file 'percona_playback/tcpdump/tcpdump.h'
1450--- percona_playback/tcpdump/tcpdump.h 2012-06-24 04:28:41 +0000
1451+++ percona_playback/tcpdump/tcpdump.h 2012-07-02 18:23:18 +0000
1452@@ -19,9 +19,17 @@
1453 #include <percona_playback/plugin.h>
1454
1455 #include <boost/program_options.hpp>
1456+#include <string>
1457+
1458+enum TcpdumpPluginMode
1459+{
1460+ TCPDUMP_MODE_FAST,
1461+ TCPDUMP_MODE_ACCURATE
1462+};
1463
1464 class TcpDumpParserPlugin : public percona_playback::InputPlugin
1465 {
1466+ boost::program_options::options_description options;
1467
1468 public:
1469 TcpDumpParserPlugin(const std::string &_name) :
1470@@ -33,11 +41,20 @@
1471
1472 virtual int processOptions(boost::program_options::variables_map &vm);
1473
1474+<<<<<<< TREE
1475 virtual void run(percona_playback_run_result &) {}
1476
1477
1478 std::string file_name;
1479 boost::program_options::options_description options;
1480+=======
1481+ virtual void run(percona_playback_run_result &result);
1482+>>>>>>> MERGE-SOURCE
1483 };
1484
1485+extern std::string g_tcpdump_file_name;
1486+extern uint16_t g_tcpdump_port;
1487+extern TcpdumpPluginMode g_tcpdump_mode;
1488+
1489+
1490 #endif /* PERCONA_PLAYBACK_TCPDUMP_PARSER_H */
1491
1492=== added file 'percona_playback/tcpdump/tcpdump_mysql_parser_stats.h'
1493--- percona_playback/tcpdump/tcpdump_mysql_parser_stats.h 1970-01-01 00:00:00 +0000
1494+++ percona_playback/tcpdump/tcpdump_mysql_parser_stats.h 2012-07-02 18:23:18 +0000
1495@@ -0,0 +1,33 @@
1496+/* BEGIN LICENSE
1497+ * Copyright (C) 2011 Percona Inc.
1498+ * This program is free software: you can redistribute it and/or modify it
1499+ * under the terms of the GNU General Public License version 2, as published
1500+ * by the Free Software Foundation.
1501+ *
1502+ * This program is distributed in the hope that it will be useful, but
1503+ * WITHOUT ANY WARRANTY; without even the implied warranties of
1504+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1505+ * PURPOSE. See the GNU General Public License for more details.
1506+ *
1507+ * You should have received a copy of the GNU General Public License along
1508+ * with this program. If not, see <http://www.gnu.org/licenses/>.
1509+ * END LICENSE */
1510+
1511+#ifndef PERCONA_PLAYBACK_TCPDUMP_MYSQL_PARSER_STATS_H
1512+#define PERCONA_PLAYBACK_TCPDUMP_MYSQL_PARSER_STATS_H
1513+
1514+struct TcpdumpMysqlParserStats
1515+{
1516+ size_t nr_of_parsed_packets;
1517+ size_t nr_of_parsed_queries;
1518+ size_t nr_of_parsing_errors;
1519+
1520+ TcpdumpMysqlParserStats() :
1521+ nr_of_parsed_packets(0),
1522+ nr_of_parsed_queries(0),
1523+ nr_of_parsing_errors(0)
1524+ {}
1525+
1526+};
1527+
1528+#endif //PERCONA_PLAYBACK_TCPDUMP_MYSQL_PARSER_STATS_H
1529
1530=== added file 'percona_playback/tcpdump/tcpdump_query_entries.cc'
1531--- percona_playback/tcpdump/tcpdump_query_entries.cc 1970-01-01 00:00:00 +0000
1532+++ percona_playback/tcpdump/tcpdump_query_entries.cc 2012-07-02 18:23:18 +0000
1533@@ -0,0 +1,129 @@
1534+/* BEGIN LICENSE
1535+ * Copyright (C) 2011-2012 Percona Inc.
1536+ * This program is free software: you can redistribute it and/or modify it
1537+ * under the terms of the GNU General Public License version 2, as published
1538+ * by the Free Software Foundation.
1539+ *
1540+ * This program is distributed in the hope that it will be useful, but
1541+ * WITHOUT ANY WARRANTY; without even the implied warranties of
1542+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1543+ * PURPOSE. See the GNU General Public License for more details.
1544+ *
1545+ * You should have received a copy of the GNU General Public License along
1546+ * with this program. If not, see <http://www.gnu.org/licenses/>.
1547+ * END LICENSE */
1548+#include "tcpdump_query_entries.h"
1549+#include "tcpdump.h"
1550+#include "percona_playback/db_thread.h"
1551+#include "percona_playback/plugin.h"
1552+
1553+#include <boost/date_time/posix_time/posix_time.hpp>
1554+#include <boost/foreach.hpp>
1555+#include <boost/shared_ptr.hpp>
1556+#include <string.h>
1557+#include <iostream>
1558+#include <assert.h>
1559+
1560+void
1561+TcpdumpQueryEntry::execute(DBThread *t)
1562+{
1563+ QueryResult expected_result;
1564+ boost::posix_time::ptime start_time;
1565+ boost::posix_time::ptime end_time;
1566+ boost::shared_ptr<DBThreadState> thr_state;
1567+
1568+ assert(t);
1569+
1570+ thr_state= t->get_state();
1571+
1572+ assert(thr_state.get());
1573+
1574+ ConnectionState &state= (ConnectionState &)*thr_state;
1575+
1576+ LastExecutedQueryInfo &last_query_info= state.last_executed_query_info;
1577+
1578+ if (g_tcpdump_mode == TCPDUMP_MODE_ACCURATE &&
1579+ last_query_info.end_timestamp.tv_sec != 0 &&
1580+ last_query_info.end_timestamp.tv_usec != 0 &&
1581+ last_query_info.end_pcap_timestamp.tv_sec != 0 &&
1582+ last_query_info.end_pcap_timestamp.tv_usec != 0)
1583+ {
1584+ timeval current_timestamp;
1585+ timeval pause_time;
1586+ timeval pcap_pause_time;
1587+
1588+ gettimeofday(&current_timestamp, NULL);
1589+ timersub(&current_timestamp, &last_query_info.end_timestamp, &pause_time);
1590+
1591+ timersub(&pcap_timestamp,
1592+ &last_query_info.end_pcap_timestamp,
1593+ &pcap_pause_time);
1594+
1595+ if (timercmp(&pause_time, &pcap_pause_time, <))
1596+ {
1597+ timeval time_to_sleep;
1598+ timersub(&pcap_pause_time,
1599+ &pause_time,
1600+ &time_to_sleep);
1601+ usleep(time_to_sleep.tv_sec*1000000 + time_to_sleep.tv_usec);
1602+ }
1603+ }
1604+
1605+ last_query_info.result.clear();
1606+
1607+ start_time= boost::posix_time::microsec_clock::universal_time();
1608+ t->execute_query(query, &last_query_info.result, expected_result);
1609+ end_time= boost::posix_time::microsec_clock::universal_time();
1610+
1611+ boost::posix_time::time_period duration(start_time, end_time);
1612+ last_query_info.result.setDuration(duration.length());
1613+ last_query_info.begin_pcap_timestamp= pcap_timestamp;
1614+ last_query_info.query= query;
1615+}
1616+
1617+void
1618+TcpdumpResultEntry::execute(DBThread *t)
1619+{
1620+ timeval query_execution_time;
1621+ boost::shared_ptr<DBThreadState> thr_state;
1622+
1623+ assert(t);
1624+
1625+ thr_state= t->get_state();
1626+
1627+ assert(thr_state.get());
1628+
1629+
1630+ ConnectionState &state= (ConnectionState &)*thr_state;
1631+ LastExecutedQueryInfo &last_query_info= state.last_executed_query_info;
1632+
1633+ timersub(&pcap_timestamp,
1634+ &last_query_info.begin_pcap_timestamp,
1635+ &query_execution_time);
1636+
1637+ expected_result.setDuration(
1638+ boost::posix_time::microseconds(
1639+ query_execution_time.tv_usec +
1640+ query_execution_time.tv_sec*1000000));
1641+
1642+ if (g_tcpdump_mode == TCPDUMP_MODE_ACCURATE &&
1643+ (expected_result.getDuration() > last_query_info.result.getDuration()))
1644+ {
1645+ boost::posix_time::time_duration us_sleep_time=
1646+ expected_result.getDuration() - last_query_info.result.getDuration();
1647+
1648+ usleep(us_sleep_time.total_microseconds());
1649+ }
1650+
1651+ gettimeofday(&last_query_info.end_timestamp, NULL);
1652+ last_query_info.end_pcap_timestamp= pcap_timestamp;
1653+
1654+ BOOST_FOREACH(const percona_playback::PluginRegistry::ReportPluginPair pp,
1655+ percona_playback::PluginRegistry::singleton().report_plugins)
1656+ {
1657+ pp.second->query_execution(getThreadId(),
1658+ last_query_info.query,
1659+ expected_result,
1660+ last_query_info.result);
1661+ }
1662+}
1663
1664=== added file 'percona_playback/tcpdump/tcpdump_query_entries.h'
1665--- percona_playback/tcpdump/tcpdump_query_entries.h 1970-01-01 00:00:00 +0000
1666+++ percona_playback/tcpdump/tcpdump_query_entries.h 2012-07-02 18:23:18 +0000
1667@@ -0,0 +1,73 @@
1668+/* BEGIN LICENSE
1669+ * Copyright (C) 2011 Percona Inc.
1670+ * This program is free software: you can redistribute it and/or modify it
1671+ * under the terms of the GNU General Public License version 2, as published
1672+ * by the Free Software Foundation.
1673+ *
1674+ * This program is distributed in the hope that it will be useful, but
1675+ * WITHOUT ANY WARRANTY; without even the implied warranties of
1676+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1677+ * PURPOSE. See the GNU General Public License for more details.
1678+ *
1679+ * You should have received a copy of the GNU General Public License along
1680+ * with this program. If not, see <http://www.gnu.org/licenses/>.
1681+ * END LICENSE */
1682+
1683+#ifndef PERCONA_PLAYBACK_TCPDUMP_QUERY_ENTRIES_H
1684+#define PERCONA_PLAYBACK_TCPDUMP_QUERY_ENTRIES_H
1685+
1686+#include "percona_playback/query_entry.h"
1687+#include "percona_playback/query_result.h"
1688+#include "connection_state.h"
1689+
1690+#include <sys/time.h>
1691+
1692+class TcpdumpQueryEntry : public QueryEntry
1693+{
1694+ timeval pcap_timestamp;
1695+ std::string query;
1696+
1697+public:
1698+
1699+ TcpdumpQueryEntry()
1700+ {
1701+ pcap_timestamp.tv_sec= pcap_timestamp.tv_usec= 0;
1702+ }
1703+
1704+ TcpdumpQueryEntry(const timeval &pcap_timestamp,
1705+ const std::string &query,
1706+ const AddrPort &addr_port) :
1707+ QueryEntry(addr_port.ThreadId(), false),
1708+ pcap_timestamp(pcap_timestamp),
1709+ query(query)
1710+ {}
1711+
1712+ bool is_quit() { return false; }
1713+
1714+ void execute(DBThread *t);
1715+};
1716+
1717+class TcpdumpResultEntry : public QueryEntry
1718+{
1719+
1720+ timeval pcap_timestamp;
1721+ QueryResult expected_result;
1722+
1723+public:
1724+ TcpdumpResultEntry() {}
1725+ TcpdumpResultEntry(const AddrPort &addr_port,
1726+ const timeval &pcap_timestamp,
1727+ const QueryResult &expected_result) :
1728+ QueryEntry(addr_port.ThreadId(), false),
1729+ pcap_timestamp(pcap_timestamp),
1730+ expected_result(expected_result)
1731+ {}
1732+
1733+ bool is_quit() { return false; }
1734+
1735+ void execute(DBThread *t);
1736+
1737+};
1738+
1739+#endif// PERCONA_PLAYBACK_TCPDUMP_QUERY_ENTRIES_H
1740+
1741
1742=== added file 'percona_playback/test/tcpdump_accuracy.cc'
1743--- percona_playback/test/tcpdump_accuracy.cc 1970-01-01 00:00:00 +0000
1744+++ percona_playback/test/tcpdump_accuracy.cc 2012-07-02 18:23:18 +0000
1745@@ -0,0 +1,69 @@
1746+/* BEGIN LICENSE
1747+ * Copyright (C) 2011-2012 Percona Inc.
1748+ * This program is free software: you can redistribute it and/or modify it
1749+ * under the terms of the GNU General Public License version 3, as published
1750+ * by the Free Software Foundation.
1751+ *
1752+ * This program is distributed in the hope that it will be useful, but
1753+ * WITHOUT ANY WARRANTY; without even the implied warranties of
1754+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1755+ * PURPOSE. See the GNU General Public License for more details.
1756+ *
1757+ * You should have received a copy of the GNU General Public License along
1758+ * with this program. If not, see <http://www.gnu.org/licenses/>.
1759+ * END LICENSE */
1760+
1761+#include "config.h"
1762+#include <iostream>
1763+#include <assert.h>
1764+#include <boost/date_time/posix_time/posix_time.hpp>
1765+
1766+#include "percona_playback/percona_playback.h"
1767+#include "percona_playback/plugin.h"
1768+
1769+const size_t pp_argc= 5;
1770+
1771+int main(int, char **argv)
1772+{
1773+ percona_playback_st *the_percona_playback= percona_playback_create("test_Percona Playback");
1774+ assert(the_percona_playback);
1775+
1776+ char *pp_argv[pp_argc];
1777+ char pp_argv_0[]= "--db-plugin=null";
1778+ char pp_argv_1[]= "--input-plugin=tcpdump";
1779+ char pp_argv_2[]= "--tcpdump-file="
1780+ SRCDIR
1781+ "/percona_playback/test"
1782+ "/tcpdump_accuracy.dump";
1783+ char pp_argv_3[]= "--tcpdump-mode=accurate";
1784+
1785+ pp_argv[0]= argv[0];
1786+ pp_argv[1]= pp_argv_0;
1787+ pp_argv[2]= pp_argv_1;
1788+ pp_argv[3]= pp_argv_2;
1789+ pp_argv[4]= pp_argv_3;
1790+
1791+ assert(0 == percona_playback_argv(the_percona_playback,
1792+ pp_argc,
1793+ pp_argv));
1794+
1795+ boost::posix_time::ptime start_time;
1796+ start_time= boost::posix_time::microsec_clock::universal_time();
1797+
1798+ struct percona_playback_run_result *r=
1799+ percona_playback_run(the_percona_playback);
1800+
1801+ boost::posix_time::ptime end_time;
1802+ end_time= boost::posix_time::microsec_clock::universal_time();
1803+
1804+ boost::posix_time::time_period duration(start_time, end_time);
1805+
1806+ assert(duration.length().total_microseconds() > 4000000);
1807+
1808+ assert(r->err == 0);
1809+ assert(r->n_queries == 60);
1810+ assert(r->n_log_entries == 480);
1811+
1812+ percona_playback_destroy(&the_percona_playback);
1813+ return r->err;
1814+}
1815
1816=== added file 'percona_playback/test/tcpdump_accuracy.dump'
1817Binary files percona_playback/test/tcpdump_accuracy.dump 1970-01-01 00:00:00 +0000 and percona_playback/test/tcpdump_accuracy.dump 2012-07-02 18:23:18 +0000 differ
1818=== added file 'percona_playback/test/tcpdump_fragmented_packet.cc'
1819--- percona_playback/test/tcpdump_fragmented_packet.cc 1970-01-01 00:00:00 +0000
1820+++ percona_playback/test/tcpdump_fragmented_packet.cc 2012-07-02 18:23:18 +0000
1821@@ -0,0 +1,56 @@
1822+/* BEGIN LICENSE
1823+ * Copyright (C) 2011-2012 Percona Inc.
1824+ * This program is free software: you can redistribute it and/or modify it
1825+ * under the terms of the GNU General Public License version 3, as published
1826+ * by the Free Software Foundation.
1827+ *
1828+ * This program is distributed in the hope that it will be useful, but
1829+ * WITHOUT ANY WARRANTY; without even the implied warranties of
1830+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1831+ * PURPOSE. See the GNU General Public License for more details.
1832+ *
1833+ * You should have received a copy of the GNU General Public License along
1834+ * with this program. If not, see <http://www.gnu.org/licenses/>.
1835+ * END LICENSE */
1836+
1837+#include "config.h"
1838+#include <iostream>
1839+#include <assert.h>
1840+#include "percona_playback/percona_playback.h"
1841+#include "percona_playback/plugin.h"
1842+
1843+const size_t pp_argc= 4;
1844+
1845+int main(int, char **argv)
1846+{
1847+ percona_playback_st *the_percona_playback= percona_playback_create("test_Percona Playback");
1848+ assert(the_percona_playback);
1849+
1850+ char *pp_argv[pp_argc];
1851+ char pp_argv_0[]= "--db-plugin=null";
1852+ char pp_argv_1[]= "--input-plugin=tcpdump";
1853+ char pp_argv_2[]= "--tcpdump-file="
1854+ SRCDIR
1855+ "/percona_playback/test"
1856+ "/tcpdump_fragmented_packet.dump";
1857+
1858+
1859+ pp_argv[0]= argv[0];
1860+ pp_argv[1]= pp_argv_0;
1861+ pp_argv[2]= pp_argv_1;
1862+ pp_argv[3]= pp_argv_2;
1863+
1864+ assert(0 == percona_playback_argv(the_percona_playback,
1865+ pp_argc,
1866+ pp_argv));
1867+
1868+ struct percona_playback_run_result *r=
1869+ percona_playback_run(the_percona_playback);
1870+
1871+ assert(r->err == 0);
1872+ assert(r->n_queries == 1);
1873+ assert(r->n_log_entries == 6);
1874+
1875+ percona_playback_destroy(&the_percona_playback);
1876+ return r->err;
1877+}
1878
1879=== added file 'percona_playback/test/tcpdump_fragmented_packet.dump'
1880Binary files percona_playback/test/tcpdump_fragmented_packet.dump 1970-01-01 00:00:00 +0000 and percona_playback/test/tcpdump_fragmented_packet.dump 2012-07-02 18:23:18 +0000 differ
1881=== added file 'percona_playback/test/tcpdump_multiple_connections.cc'
1882--- percona_playback/test/tcpdump_multiple_connections.cc 1970-01-01 00:00:00 +0000
1883+++ percona_playback/test/tcpdump_multiple_connections.cc 2012-07-02 18:23:18 +0000
1884@@ -0,0 +1,56 @@
1885+/* BEGIN LICENSE
1886+ * Copyright (C) 2011-2012 Percona Inc.
1887+ * This program is free software: you can redistribute it and/or modify it
1888+ * under the terms of the GNU General Public License version 3, as published
1889+ * by the Free Software Foundation.
1890+ *
1891+ * This program is distributed in the hope that it will be useful, but
1892+ * WITHOUT ANY WARRANTY; without even the implied warranties of
1893+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1894+ * PURPOSE. See the GNU General Public License for more details.
1895+ *
1896+ * You should have received a copy of the GNU General Public License along
1897+ * with this program. If not, see <http://www.gnu.org/licenses/>.
1898+ * END LICENSE */
1899+
1900+#include "config.h"
1901+#include <iostream>
1902+#include <assert.h>
1903+#include "percona_playback/percona_playback.h"
1904+#include "percona_playback/plugin.h"
1905+
1906+const size_t pp_argc= 4;
1907+
1908+int main(int, char **argv)
1909+{
1910+ percona_playback_st *the_percona_playback= percona_playback_create("test_Percona Playback");
1911+ assert(the_percona_playback);
1912+
1913+ char *pp_argv[pp_argc];
1914+ char pp_argv_0[]= "--db-plugin=null";
1915+ char pp_argv_1[]= "--input-plugin=tcpdump";
1916+ char pp_argv_2[]= "--tcpdump-file="
1917+ SRCDIR
1918+ "/percona_playback/test"
1919+ "/tcpdump_multiple_connections.dump";
1920+
1921+
1922+ pp_argv[0]= argv[0];
1923+ pp_argv[1]= pp_argv_0;
1924+ pp_argv[2]= pp_argv_1;
1925+ pp_argv[3]= pp_argv_2;
1926+
1927+ assert(0 == percona_playback_argv(the_percona_playback,
1928+ pp_argc,
1929+ pp_argv));
1930+
1931+ struct percona_playback_run_result *r=
1932+ percona_playback_run(the_percona_playback);
1933+
1934+ assert(r->err == 0);
1935+ assert(r->n_queries == 2000);
1936+ assert(r->n_log_entries == 16000);
1937+
1938+ percona_playback_destroy(&the_percona_playback);
1939+ return r->err;
1940+}
1941
1942=== added file 'percona_playback/test/tcpdump_multiple_connections.dump'
1943Binary files percona_playback/test/tcpdump_multiple_connections.dump 1970-01-01 00:00:00 +0000 and percona_playback/test/tcpdump_multiple_connections.dump 2012-07-02 18:23:18 +0000 differ
1944=== added file 'percona_playback/test/tcpdump_stress_test.cc'
1945--- percona_playback/test/tcpdump_stress_test.cc 1970-01-01 00:00:00 +0000
1946+++ percona_playback/test/tcpdump_stress_test.cc 2012-07-02 18:23:18 +0000
1947@@ -0,0 +1,56 @@
1948+/* BEGIN LICENSE
1949+ * Copyright (C) 2011-2012 Percona Inc.
1950+ * This program is free software: you can redistribute it and/or modify it
1951+ * under the terms of the GNU General Public License version 3, as published
1952+ * by the Free Software Foundation.
1953+ *
1954+ * This program is distributed in the hope that it will be useful, but
1955+ * WITHOUT ANY WARRANTY; without even the implied warranties of
1956+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1957+ * PURPOSE. See the GNU General Public License for more details.
1958+ *
1959+ * You should have received a copy of the GNU General Public License along
1960+ * with this program. If not, see <http://www.gnu.org/licenses/>.
1961+ * END LICENSE */
1962+
1963+#include "config.h"
1964+#include <iostream>
1965+#include <assert.h>
1966+#include "percona_playback/percona_playback.h"
1967+#include "percona_playback/plugin.h"
1968+
1969+const size_t pp_argc= 4;
1970+
1971+int main(int, char **argv)
1972+{
1973+ percona_playback_st *the_percona_playback= percona_playback_create("test_Percona Playback");
1974+ assert(the_percona_playback);
1975+
1976+ char *pp_argv[pp_argc];
1977+ char pp_argv_0[]= "--db-plugin=null";
1978+ char pp_argv_1[]= "--input-plugin=tcpdump";
1979+ char pp_argv_2[]= "--tcpdump-file="
1980+ SRCDIR
1981+ "/percona_playback/test"
1982+ "/tcpdump_stress_test.dump";
1983+
1984+
1985+ pp_argv[0]= argv[0];
1986+ pp_argv[1]= pp_argv_0;
1987+ pp_argv[2]= pp_argv_1;
1988+ pp_argv[3]= pp_argv_2;
1989+
1990+ assert(0 == percona_playback_argv(the_percona_playback,
1991+ pp_argc,
1992+ pp_argv));
1993+
1994+ struct percona_playback_run_result *r=
1995+ percona_playback_run(the_percona_playback);
1996+
1997+ assert(r->err == 0);
1998+ assert(r->n_queries == 9088);
1999+ assert(r->n_log_entries == 62306);
2000+
2001+ percona_playback_destroy(&the_percona_playback);
2002+ return r->err;
2003+}
2004
2005=== added file 'percona_playback/test/tcpdump_stress_test.dump'
2006Binary files percona_playback/test/tcpdump_stress_test.dump 1970-01-01 00:00:00 +0000 and percona_playback/test/tcpdump_stress_test.dump 2012-07-02 18:23:18 +0000 differ
2007=== added file 'percona_playback/test/tcpdump_without_handshake.cc'
2008--- percona_playback/test/tcpdump_without_handshake.cc 1970-01-01 00:00:00 +0000
2009+++ percona_playback/test/tcpdump_without_handshake.cc 2012-07-02 18:23:18 +0000
2010@@ -0,0 +1,56 @@
2011+/* BEGIN LICENSE
2012+ * Copyright (C) 2011-2012 Percona Inc.
2013+ * This program is free software: you can redistribute it and/or modify it
2014+ * under the terms of the GNU General Public License version 3, as published
2015+ * by the Free Software Foundation.
2016+ *
2017+ * This program is distributed in the hope that it will be useful, but
2018+ * WITHOUT ANY WARRANTY; without even the implied warranties of
2019+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
2020+ * PURPOSE. See the GNU General Public License for more details.
2021+ *
2022+ * You should have received a copy of the GNU General Public License along
2023+ * with this program. If not, see <http://www.gnu.org/licenses/>.
2024+ * END LICENSE */
2025+
2026+#include "config.h"
2027+#include <iostream>
2028+#include <assert.h>
2029+#include "percona_playback/percona_playback.h"
2030+#include "percona_playback/plugin.h"
2031+
2032+const size_t pp_argc= 4;
2033+
2034+int main(int, char **argv)
2035+{
2036+ percona_playback_st *the_percona_playback= percona_playback_create("test_Percona Playback");
2037+ assert(the_percona_playback);
2038+
2039+ char *pp_argv[pp_argc];
2040+ char pp_argv_0[]= "--db-plugin=null";
2041+ char pp_argv_1[]= "--input-plugin=tcpdump";
2042+ char pp_argv_2[]= "--tcpdump-file="
2043+ SRCDIR
2044+ "/percona_playback/test"
2045+ "/tcpdump_without_handshake.dump";
2046+
2047+
2048+ pp_argv[0]= argv[0];
2049+ pp_argv[1]= pp_argv_0;
2050+ pp_argv[2]= pp_argv_1;
2051+ pp_argv[3]= pp_argv_2;
2052+
2053+ assert(0 == percona_playback_argv(the_percona_playback,
2054+ pp_argc,
2055+ pp_argv));
2056+
2057+ struct percona_playback_run_result *r=
2058+ percona_playback_run(the_percona_playback);
2059+
2060+ assert(r->err == 0);
2061+ assert(r->n_queries == 7);
2062+ assert(r->n_log_entries == 44);
2063+
2064+ percona_playback_destroy(&the_percona_playback);
2065+ return r->err;
2066+}
2067
2068=== added file 'percona_playback/test/tcpdump_without_handshake.dump'
2069Binary files percona_playback/test/tcpdump_without_handshake.dump 1970-01-01 00:00:00 +0000 and percona_playback/test/tcpdump_without_handshake.dump 2012-07-02 18:23:18 +0000 differ

Subscribers

People subscribed via source and target branches

to all changes: