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

Proposed by Vlad Lesin on 2012-06-20
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 2012-06-20 Pending
Review via email: mp+111163@code.launchpad.net
To post a comment you must log in.
98. By Vlad Lesin on 2012-06-20

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 on 2012-06-20

Free drizzle result in ConnectionState destructor.

100. By Vlad Lesin on 2012-06-20

Fix for memory leak in tcpdump plugin.

101. By Vlad Lesin on 2012-06-20

Don't use all caps in labels.

102. By Vlad Lesin on 2012-06-20

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

103. By Vlad Lesin on 2012-06-20

License header is added to dispatcher source.

104. By Vlad Lesin on 2012-07-02

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

105. By Vlad Lesin on 2012-07-02

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

106. By Vlad Lesin on 2012-07-02

Use standard libdrizzle-1.0 instead of modified

107. By Vlad Lesin on 2012-07-02

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: