~percona-toolkit-dev/percona-toolkit/fix-log-parser-writer-bug-963225

« back to all changes in this revision

Viewing changes to lib/MemcachedEvent.pm

  • Committer: Daniel Nichter
  • Date: 2011-06-24 17:22:06 UTC
  • Revision ID: daniel@percona.com-20110624172206-c7q4s4ad6r260zz6
Add lib/, t/lib/, and sandbox/.  All modules are updated and passing on MySQL 5.1.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# This program is copyright 2009-2011 Percona Inc.
 
2
# Feedback and improvements are welcome.
 
3
#
 
4
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
 
5
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 
6
# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
7
#
 
8
# This program is free software; you can redistribute it and/or modify it under
 
9
# the terms of the GNU General Public License as published by the Free Software
 
10
# Foundation, version 2; OR the Perl Artistic License.  On UNIX and similar
 
11
# systems, you can issue `man perlgpl' or `man perlartistic' to read these
 
12
# licenses.
 
13
#
 
14
# You should have received a copy of the GNU General Public License along with
 
15
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
16
# Place, Suite 330, Boston, MA  02111-1307  USA.
 
17
# ###########################################################################
 
18
# MemcachedEvent package $Revision: 7096 $
 
19
# ###########################################################################
 
20
package MemcachedEvent;
 
21
 
 
22
# This package creates events suitable for mk-query-digest
 
23
# from psuedo-events created by MemcachedProtocolParser.
 
24
# Since memcached is not strictly MySQL stuff, we have to
 
25
# fabricate MySQL-like query events from memcached.
 
26
 
27
# See http://code.sixapart.com/svn/memcached/trunk/server/doc/protocol.txt
 
28
# for information about the memcached protocol.
 
29
 
 
30
use strict;
 
31
use warnings FATAL => 'all';
 
32
use English qw(-no_match_vars);
 
33
 
 
34
use Data::Dumper;
 
35
$Data::Dumper::Indent    = 1;
 
36
$Data::Dumper::Sortkeys  = 1;
 
37
$Data::Dumper::Quotekeys = 0;
 
38
 
 
39
use constant MKDEBUG => $ENV{MKDEBUG} || 0;
 
40
 
 
41
# cmds that we know how to handle.
 
42
my %cmds = map { $_ => 1 } qw(
 
43
   set
 
44
   add
 
45
   replace
 
46
   append
 
47
   prepend
 
48
   cas
 
49
   get
 
50
   gets
 
51
   delete
 
52
   incr
 
53
   decr
 
54
);
 
55
 
 
56
my %cmd_handler_for = (
 
57
   set      => \&handle_storage_cmd,
 
58
   add      => \&handle_storage_cmd,
 
59
   replace  => \&handle_storage_cmd,
 
60
   append   => \&handle_storage_cmd,
 
61
   prepend  => \&handle_storage_cmd,
 
62
   cas      => \&handle_storage_cmd,
 
63
   get      => \&handle_retr_cmd,
 
64
   gets     => \&handle_retr_cmd,
 
65
);
 
66
 
 
67
sub new {
 
68
   my ( $class, %args ) = @_;
 
69
   my $self = {};
 
70
   return bless $self, $class;
 
71
}
 
72
 
 
73
# Given an event from MemcachedProtocolParser, returns an event
 
74
# more suitable for mk-query-digest.
 
75
sub parse_event {
 
76
   my ( $self, %args ) = @_;
 
77
   my $event = $args{event};
 
78
   return unless $event;
 
79
 
 
80
   if ( !$event->{cmd} || !$event->{key} ) {
 
81
      MKDEBUG && _d('Event has no cmd or key:', Dumper($event));
 
82
      return;
 
83
   }
 
84
 
 
85
   if ( !$cmds{$event->{cmd}} ) {
 
86
      MKDEBUG && _d("Don't know how to handle cmd:", $event->{cmd});
 
87
      return;
 
88
   }
 
89
 
 
90
   # For a normal event, arg is the query.  For memcached, the "query" is
 
91
   # essentially the cmd and key, so this becomes arg.  E.g.: "set mk_key".
 
92
   $event->{arg}         = "$event->{cmd} $event->{key}";
 
93
   $event->{fingerprint} = $self->fingerprint($event->{arg});
 
94
   $event->{key_print}   = $self->fingerprint($event->{key});
 
95
 
 
96
   # Set every cmd so that aggregated totals will be correct.  If we only
 
97
   # set cmd that we get, then all cmds will show as 100% in the report.
 
98
   # This will create a lot of 0% cmds, but --[no]zero-bool will remove them.
 
99
   # Think of events in a Percona-patched log: the attribs like Full_scan are
 
100
   # present for every event.
 
101
   map { $event->{"Memc_$_"} = 'No' } keys %cmds;
 
102
   $event->{"Memc_$event->{cmd}"} = 'Yes';  # Got this cmd.
 
103
   $event->{Memc_error}           = 'No';  # A handler may change this.
 
104
   $event->{Memc_miss}            = 'No';
 
105
   if ( $event->{res} ) {
 
106
      $event->{Memc_miss}         = 'Yes' if $event->{res} eq 'NOT_FOUND';
 
107
   }
 
108
   else {
 
109
      # This normally happens with incr and decr cmds.
 
110
      MKDEBUG && _d('Event has no res:', Dumper($event));
 
111
   }
 
112
 
 
113
   # Handle special results, errors, etc.  The handler should return the
 
114
   # event on success, or nothing on failure.
 
115
   if ( $cmd_handler_for{$event->{cmd}} ) {
 
116
      return $cmd_handler_for{$event->{cmd}}->($event);
 
117
   }
 
118
 
 
119
   return $event;
 
120
}
 
121
 
 
122
# Replace things that look like placeholders with a ?
 
123
sub fingerprint {
 
124
   my ( $self, $val ) = @_;
 
125
   $val =~ s/[0-9A-Fa-f]{16,}|\d+/?/g;
 
126
   return $val;
 
127
}
 
128
 
 
129
# Possible results for storage cmds:
 
130
# - "STORED\r\n", to indicate success.
 
131
#
 
132
# - "NOT_STORED\r\n" to indicate the data was not stored, but not
 
133
#   because of an error. This normally means that either that the
 
134
#   condition for an "add" or a "replace" command wasn't met, or that the
 
135
#   item is in a delete queue (see the "delete" command below).
 
136
#
 
137
# - "EXISTS\r\n" to indicate that the item you are trying to store with
 
138
#   a "cas" command has been modified since you last fetched it.
 
139
#
 
140
# - "NOT_FOUND\r\n" to indicate that the item you are trying to store
 
141
#   with a "cas" command did not exist or has been deleted.
 
142
sub handle_storage_cmd {
 
143
   my ( $event ) = @_;
 
144
 
 
145
   # There should be a result for any storage cmd.   
 
146
   if ( !$event->{res} ) {
 
147
      MKDEBUG && _d('No result for event:', Dumper($event));
 
148
      return;
 
149
   }
 
150
 
 
151
   $event->{'Memc_Not_Stored'} = $event->{res} eq 'NOT_STORED' ? 'Yes' : 'No';
 
152
   $event->{'Memc_Exists'}     = $event->{res} eq 'EXISTS'     ? 'Yes' : 'No';
 
153
 
 
154
   return $event;
 
155
}
 
156
 
 
157
# Technically, the only results for a retrieval cmd are the values requested.
 
158
#  "If some of the keys appearing in a retrieval request are not sent back
 
159
#   by the server in the item list this means that the server does not
 
160
#   hold items with such keys (because they were never stored, or stored
 
161
#   but deleted to make space for more items, or expired, or explicitly
 
162
#   deleted by a client)."
 
163
# Contrary to this, MemcacedProtocolParser will set res='VALUE' on
 
164
# success, res='NOT_FOUND' on failure, or res='INTERRUPTED' if the get
 
165
# didn't finish.
 
166
sub handle_retr_cmd {
 
167
   my ( $event ) = @_;
 
168
 
 
169
   # There should be a result for any retr cmd.   
 
170
   if ( !$event->{res} ) {
 
171
      MKDEBUG && _d('No result for event:', Dumper($event));
 
172
      return;
 
173
   }
 
174
 
 
175
   $event->{'Memc_error'} = $event->{res} eq 'INTERRUPTED' ? 'Yes' : 'No';
 
176
 
 
177
   return $event;
 
178
}
 
179
 
 
180
# handle_delete() and handle_incr_decr_cmd() are stub subs in case we
 
181
# need them later.
 
182
 
 
183
# Possible results for a delete cmd:
 
184
# - "DELETED\r\n" to indicate success
 
185
#
 
186
# - "NOT_FOUND\r\n" to indicate that the item with this key was not
 
187
#   found.
 
188
sub handle_delete {
 
189
   my ( $event ) = @_;
 
190
   return $event;
 
191
}
 
192
 
 
193
# Possible results for an incr or decr cmd:
 
194
# - "NOT_FOUND\r\n" to indicate the item with this value was not found
 
195
#
 
196
# - <value>\r\n , where <value> is the new value of the item's data,
 
197
#   after the increment/decrement operation was carried out.
 
198
# On success, MemcachedProtocolParser sets res='' and val=the new val.
 
199
# On failure, res=the result and val=''.
 
200
sub handle_incr_decr_cmd {
 
201
   my ( $event ) = @_;
 
202
   return $event;
 
203
}
 
204
 
 
205
sub _d {
 
206
   my ($package, undef, $line) = caller 0;
 
207
   @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; }
 
208
        map { defined $_ ? $_ : 'undef' }
 
209
        @_;
 
210
   print STDERR "# $package:$line $PID ", join(' ', @_), "\n";
 
211
}
 
212
 
 
213
1;
 
214
 
 
215
# ###########################################################################
 
216
# End MemcachedEvent package
 
217
# ###########################################################################