log_event.h 12.2 KB
Newer Older
unknown's avatar
unknown committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
   
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */


#ifndef _LOG_EVENT_H
#define _LOG_EVENT_H

21 22 23 24
#ifdef __EMX__
#undef write  // remove pthread.h macro definition, conflict with write() class member
#endif

unknown's avatar
unknown committed
25 26 27 28 29 30 31 32
#if defined(__GNUC__) && !defined(MYSQL_CLIENT)
#pragma interface			/* gcc class implementation */
#endif

#define LOG_READ_EOF    -1
#define LOG_READ_BOGUS  -2
#define LOG_READ_IO     -3
#define LOG_READ_MEM    -5
unknown's avatar
unknown committed
33
#define LOG_READ_TRUNC  -6
unknown's avatar
unknown committed
34
#define LOG_READ_TOO_LARGE -7
unknown's avatar
unknown committed
35 36

#define LOG_EVENT_OFFSET 4
37
#define BINLOG_VERSION    1
unknown's avatar
unknown committed
38

39
#define LOG_EVENT_HEADER_LEN 13
40 41
#define QUERY_HEADER_LEN     (sizeof(uint32) + sizeof(uint32) + \
 sizeof(uchar) + sizeof(uint16))
42 43 44 45
#define LOAD_HEADER_LEN      (sizeof(uint32) + sizeof(uint32) + \
  + sizeof(uint32) + 2 + sizeof(uint32))
#define EVENT_LEN_OFFSET     9
#define EVENT_TYPE_OFFSET    4
46
#define QUERY_EVENT_OVERHEAD  (LOG_EVENT_HEADER_LEN+QUERY_HEADER_LEN)
47 48 49
#define ROTATE_EVENT_OVERHEAD LOG_EVENT_HEADER_LEN
#define LOAD_EVENT_OVERHEAD   (LOG_EVENT_HEADER_LEN+LOAD_HEADER_LEN+sizeof(sql_ex_info))

unknown's avatar
unknown committed
50
#define BINLOG_MAGIC        "\xfe\x62\x69\x6e"
51

unknown's avatar
unknown committed
52 53 54 55 56 57 58 59 60 61
enum Log_event_type { START_EVENT = 1, QUERY_EVENT =2,
		      STOP_EVENT=3, ROTATE_EVENT = 4, INTVAR_EVENT=5,
                      LOAD_EVENT=6};
enum Int_event_type { INVALID_INT_EVENT = 0, LAST_INSERT_ID_EVENT = 1, INSERT_ID_EVENT = 2
 };

#ifndef MYSQL_CLIENT
class String;
#endif

62
extern ulong server_id;
63

unknown's avatar
unknown committed
64 65 66 67 68
class Log_event
{
public:
  time_t when;
  ulong exec_time;
69 70
  int valid_exec_time; // if false, the exec time setting is bogus 
  uint32 server_id;
unknown's avatar
unknown committed
71

72 73 74 75 76 77 78
  static void *operator new(size_t size)
  {
    return (void*) my_malloc((uint)size, MYF(MY_WME|MY_FAE));
  }

  static void operator delete(void *ptr, size_t size)
  {
79
    my_free((gptr) ptr, MYF(MY_WME|MY_ALLOW_ZERO_PTR));
80 81
  }
  
82 83 84
  int write(IO_CACHE* file);
  int write_header(IO_CACHE* file);
  virtual int write_data(IO_CACHE* file __attribute__((unused))) { return 0; }
unknown's avatar
unknown committed
85 86
  virtual Log_event_type get_type_code() = 0;
  Log_event(time_t when_arg, ulong exec_time_arg = 0,
unknown's avatar
unknown committed
87 88 89
	    int valid_exec_time_arg = 0, uint32 server_id_arg = 0):
    when(when_arg), exec_time(exec_time_arg),
    valid_exec_time(valid_exec_time_arg)
90
  {
unknown's avatar
unknown committed
91
    server_id = server_id_arg ? server_id_arg : (::server_id);
92
  }
unknown's avatar
unknown committed
93

94
  Log_event(const char* buf): valid_exec_time(0)
unknown's avatar
unknown committed
95 96
  {
   when = uint4korr(buf);
97
   server_id = uint4korr(buf + 5);
unknown's avatar
unknown committed
98 99 100 101 102
  }

  virtual ~Log_event() {}

  virtual int get_data_size() { return 0;}
103
  virtual void print(FILE* file, bool short_form = 0, char* last_db = 0) = 0;
unknown's avatar
unknown committed
104

105 106
  void print_timestamp(FILE* file, time_t *ts = 0);
  void print_header(FILE* file);
unknown's avatar
unknown committed
107

unknown's avatar
unknown committed
108
#ifndef MYSQL_CLIENT  
109
  // if mutex is 0, the read will proceed without mutex
110
  static Log_event* read_log_event(IO_CACHE* file, pthread_mutex_t* log_lock);
unknown's avatar
unknown committed
111 112 113
#else // avoid having to link mysqlbinlog against libpthread
  static Log_event* read_log_event(IO_CACHE* file);
#endif  
114
  static Log_event* read_log_event(const char* buf, int event_len);
unknown's avatar
unknown committed
115 116

#ifndef MYSQL_CLIENT
117
  static int read_log_event(IO_CACHE* file, String* packet,
118
			    pthread_mutex_t* log_lock);
unknown's avatar
unknown committed
119 120 121 122 123 124 125 126 127 128 129 130
#endif
  
};


class Query_log_event: public Log_event
{
protected:
  char* data_buf;
public:
  const char* query;
  const char* db;
unknown's avatar
unknown committed
131
  uint32 q_len; // if we already know the length of the query string
unknown's avatar
unknown committed
132 133
  // we pass it here, so we would not have to call strlen()
  // otherwise, set it to 0, in which case, we compute it with strlen()
unknown's avatar
unknown committed
134
  uint32 db_len;
135
  uint16 error_code;
136
  ulong thread_id;
unknown's avatar
unknown committed
137 138
#if !defined(MYSQL_CLIENT)
  THD* thd;
139 140 141
  bool cache_stmt;
  Query_log_event(THD* thd_arg, const char* query_arg, bool using_trans=0):
    Log_event(thd_arg->start_time,0,1,thd_arg->server_id), data_buf(0),
unknown's avatar
unknown committed
142
    query(query_arg),  db(thd_arg->db), q_len(thd_arg->query_length),
143
    error_code(thd_arg->killed ? ER_SERVER_SHUTDOWN: thd_arg->net.last_errno),
144 145 146
    thread_id(thd_arg->thread_id), thd(thd_arg),
    cache_stmt(using_trans &&
	       (thd_arg->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN)))
unknown's avatar
unknown committed
147 148 149
  {
    time_t end_time;
    time(&end_time);
unknown's avatar
unknown committed
150
    exec_time = (ulong) (end_time  - thd->start_time);
unknown's avatar
unknown committed
151
    db_len = (db) ? (uint32) strlen(db) : 0;
152 153 154
    // do not log stray system errors such as EE_WRITE
    if (error_code < ERRMOD)
      error_code = 0; 
unknown's avatar
unknown committed
155 156 157
  }
#endif

unknown's avatar
unknown committed
158
  Query_log_event(IO_CACHE* file, time_t when, uint32 server_id_arg);
159
  Query_log_event(const char* buf, int event_len);
unknown's avatar
unknown committed
160 161 162 163
  ~Query_log_event()
  {
    if (data_buf)
    {
164
      my_free((gptr) data_buf, MYF(0));
unknown's avatar
unknown committed
165 166 167
    }
  }
  Log_event_type get_type_code() { return QUERY_EVENT; }
168 169
  int write(IO_CACHE* file);
  int write_data(IO_CACHE* file); // returns 0 on success, -1 on error
unknown's avatar
unknown committed
170 171 172
  int get_data_size()
  {
    return q_len + db_len + 2 +
unknown's avatar
unknown committed
173 174
      sizeof(uint32) // thread_id
      + sizeof(uint32) // exec_time
175
      + sizeof(uint16) // error_code
unknown's avatar
unknown committed
176 177 178
      ;
  }

179
  void print(FILE* file, bool short_form = 0, char* last_db = 0);
unknown's avatar
unknown committed
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
};

#define DUMPFILE_FLAG 0x1
#define OPT_ENCLOSED_FLAG 0x2
#define REPLACE_FLAG  0x4
#define IGNORE_FLAG   0x8

#define FIELD_TERM_EMPTY 0x1
#define ENCLOSED_EMPTY   0x2
#define LINE_TERM_EMPTY  0x4
#define LINE_START_EMPTY 0x8
#define ESCAPED_EMPTY    0x10


struct sql_ex_info
  {
    char field_term;
    char enclosed;
    char line_term;
    char line_start;
    char escaped;
    char opt_flags; // flags for the options
    char empty_flags; // flags to indicate which of the terminating charact
  } ;

class Load_log_event: public Log_event
{
protected:
  char* data_buf;
209
  void copy_log_event(const char *buf, ulong data_len);
210

unknown's avatar
unknown committed
211
public:
212
  ulong thread_id;
unknown's avatar
unknown committed
213 214 215 216
  uint32 table_name_len;
  uint32 db_len;
  uint32 fname_len;
  uint32 num_fields;
unknown's avatar
unknown committed
217 218
  const char* fields;
  const uchar* field_lens;
unknown's avatar
unknown committed
219
  uint32 field_block_len;
unknown's avatar
unknown committed
220 221 222 223 224
  

  const char* table_name;
  const char* db;
  const char* fname;
unknown's avatar
unknown committed
225
  uint32 skip_lines;
unknown's avatar
unknown committed
226 227 228 229 230 231
  sql_ex_info sql_ex;
  
#if !defined(MYSQL_CLIENT)
  THD* thd;
  String field_lens_buf;
  String fields_buf;
232 233
  Load_log_event(THD* thd, sql_exchange* ex, 
		 const char *db_arg, const char* table_name_arg,
unknown's avatar
unknown committed
234
		 List<Item>& fields_arg, enum enum_duplicates handle_dup ):
unknown's avatar
unknown committed
235 236
    Log_event(thd->start_time),data_buf(0),thread_id(thd->thread_id),
    num_fields(0),fields(0),field_lens(0),field_block_len(0),
237 238
    table_name(table_name_arg ? table_name_arg : ""),
    db(db_arg ? db_arg : ""),
unknown's avatar
unknown committed
239 240 241 242 243
    fname(ex->file_name),
    thd(thd)
  {
    time_t end_time;
    time(&end_time);
unknown's avatar
unknown committed
244
    exec_time = (ulong) (end_time  - thd->start_time);
unknown's avatar
unknown committed
245
    valid_exec_time = 1;
246 247
    db_len = (uint32) strlen(db);
    table_name_len = (uint32) strlen(table_name);
unknown's avatar
unknown committed
248
    fname_len = (fname) ? (uint) strlen(fname) : 0;
unknown's avatar
unknown committed
249 250 251 252 253 254 255 256 257 258 259 260 261
    sql_ex.field_term = (*ex->field_term)[0];
    sql_ex.enclosed = (*ex->enclosed)[0];
    sql_ex.line_term = (*ex->line_term)[0];
    sql_ex.line_start = (*ex->line_start)[0];
    sql_ex.escaped = (*ex->escaped)[0];
    sql_ex.opt_flags = 0;
    if(ex->dumpfile)
      sql_ex.opt_flags |= DUMPFILE_FLAG;
    if(ex->opt_enclosed)
      sql_ex.opt_flags |= OPT_ENCLOSED_FLAG;

    sql_ex.empty_flags = 0;

262 263 264 265 266
    switch(handle_dup) {
    case DUP_IGNORE:  sql_ex.opt_flags |= IGNORE_FLAG;  break;
    case DUP_REPLACE: sql_ex.opt_flags |= REPLACE_FLAG; break;
    case DUP_ERROR: break;	
    }
unknown's avatar
unknown committed
267 268 269 270 271 272 273 274 275 276 277 278 279 280

    if(!ex->field_term->length())
      sql_ex.empty_flags |= FIELD_TERM_EMPTY;
    if(!ex->enclosed->length())
      sql_ex.empty_flags |= ENCLOSED_EMPTY;
    if(!ex->line_term->length())
      sql_ex.empty_flags |= LINE_TERM_EMPTY;
    if(!ex->line_start->length())
      sql_ex.empty_flags |= LINE_START_EMPTY;
    if(!ex->escaped->length())
      sql_ex.empty_flags |= ESCAPED_EMPTY;
    
    skip_lines = ex->skip_lines;

unknown's avatar
unknown committed
281
    List_iterator<Item> li(fields_arg);
unknown's avatar
unknown committed
282 283 284 285 286 287
    field_lens_buf.length(0);
    fields_buf.length(0);
    Item* item;
    while((item = li++))
      {
	num_fields++;
unknown's avatar
unknown committed
288
	uchar len = (uchar) strlen(item->name);
unknown's avatar
unknown committed
289 290 291 292 293 294
	field_block_len += len + 1;
	fields_buf.append(item->name, len + 1);
	field_lens_buf.append((char*)&len, 1);
      }

    field_lens = (const uchar*)field_lens_buf.ptr();
unknown's avatar
unknown committed
295
    fields = fields_buf.ptr();
unknown's avatar
unknown committed
296
  }
unknown's avatar
unknown committed
297
  void set_fields(List<Item> &fields_arg);
unknown's avatar
unknown committed
298 299
#endif

unknown's avatar
unknown committed
300
  Load_log_event(IO_CACHE * file, time_t when, uint32 server_id_arg);
301
  Load_log_event(const char* buf, int event_len);
unknown's avatar
unknown committed
302 303 304 305
  ~Load_log_event()
  {
    if (data_buf)
    {
306
      my_free((gptr) data_buf, MYF(0));
unknown's avatar
unknown committed
307 308 309
    }
  }
  Log_event_type get_type_code() { return LOAD_EVENT; }
310
  int write_data(IO_CACHE* file); // returns 0 on success, -1 on error
unknown's avatar
unknown committed
311 312 313
  int get_data_size()
  {
    return table_name_len + 2 + db_len + 2 + fname_len
314 315 316 317
      + 4 // thread_id
      + 4 // exec_time
      + 4 // skip_lines
      + 4 // field block len
unknown's avatar
unknown committed
318 319 320 321
      + sizeof(sql_ex) + field_block_len + num_fields*sizeof(uchar) ;
      ;
  }

322
  void print(FILE* file, bool short_form = 0, char* last_db = 0);
unknown's avatar
unknown committed
323 324
};

unknown's avatar
unknown committed
325
extern char server_version[SERVER_VERSION_LENGTH];
unknown's avatar
unknown committed
326 327 328 329

class Start_log_event: public Log_event
{
public:
330
  time_t created;
331 332 333 334
  uint16 binlog_version;
  char server_version[50];
  
  Start_log_event() :Log_event(time(NULL)),binlog_version(BINLOG_VERSION)
unknown's avatar
unknown committed
335
  {
336
    created = (time_t) when;
337
    memcpy(server_version, ::server_version, sizeof(server_version));
unknown's avatar
unknown committed
338
  }
unknown's avatar
unknown committed
339 340
  Start_log_event(IO_CACHE* file, time_t when_arg, uint32 server_id_arg) :
    Log_event(when_arg, 0, 0, server_id_arg)
unknown's avatar
unknown committed
341
  {
342
    char buf[sizeof(server_version) + 2 + 4 + 4];
343
    if (my_b_read(file, (byte*) buf, sizeof(buf)))
344
      return;				
345 346
    binlog_version = uint2korr(buf+4);
    memcpy(server_version, buf + 6, sizeof(server_version));
unknown's avatar
unknown committed
347
    server_version[sizeof(server_version)-1]=0;
348
    created = (time_t) uint4korr(buf + 6 + sizeof(server_version));
unknown's avatar
unknown committed
349
  }
350 351
  Start_log_event(const char* buf);
  
unknown's avatar
unknown committed
352 353
  ~Start_log_event() {}
  Log_event_type get_type_code() { return START_EVENT;}
354
  int write_data(IO_CACHE* file);
355 356
  int get_data_size()
  {
357
    // size(binlog_version) + sizeof(server_version) + size(created)
358
    return 2 + sizeof(server_version) + 4;
359
  }
360
  void print(FILE* file, bool short_form = 0, char* last_db = 0);
unknown's avatar
unknown committed
361 362 363 364 365 366 367 368 369 370
};

class Intvar_log_event: public Log_event
{
public:
  ulonglong val;
  uchar type;
  Intvar_log_event(uchar type_arg, ulonglong val_arg)
    :Log_event(time(NULL)),val(val_arg),type(type_arg)
  {}
unknown's avatar
unknown committed
371
  Intvar_log_event(IO_CACHE* file, time_t when, uint32 server_id_arg);
unknown's avatar
unknown committed
372 373 374 375
  Intvar_log_event(const char* buf);
  ~Intvar_log_event() {}
  Log_event_type get_type_code() { return INTVAR_EVENT;}
  int get_data_size() { return  sizeof(type) + sizeof(val);}
376
  int write_data(IO_CACHE* file);
unknown's avatar
unknown committed
377 378
  
  
379
  void print(FILE* file, bool short_form = 0, char* last_db = 0);
unknown's avatar
unknown committed
380 381 382 383 384 385 386
};

class Stop_log_event: public Log_event
{
public:
  Stop_log_event() :Log_event(time(NULL))
  {}
unknown's avatar
unknown committed
387 388
  Stop_log_event(IO_CACHE* file, time_t when_arg, uint32 server_id_arg):
    Log_event(when_arg,0,0,server_id_arg)
unknown's avatar
unknown committed
389
  {
unknown's avatar
unknown committed
390
    byte skip[4];
391
    my_b_read(file, skip, sizeof(skip));	// skip the event length
unknown's avatar
unknown committed
392 393 394 395 396 397
  }
  Stop_log_event(const char* buf):Log_event(buf)
  {
  }
  ~Stop_log_event() {}
  Log_event_type get_type_code() { return STOP_EVENT;}
398
  void print(FILE* file, bool short_form = 0, char* last_db = 0);
unknown's avatar
unknown committed
399 400 401 402 403 404 405 406 407 408 409 410
};

class Rotate_log_event: public Log_event
{
public:
  const char* new_log_ident;
  uchar ident_len;
  bool alloced;
  
  Rotate_log_event(const char* new_log_ident_arg, uint ident_len_arg = 0) :
    Log_event(time(NULL)),
    new_log_ident(new_log_ident_arg),
unknown's avatar
unknown committed
411
    ident_len(ident_len_arg ? ident_len_arg : (uint) strlen(new_log_ident_arg)),
unknown's avatar
unknown committed
412 413 414
    alloced(0)
  {}
  
unknown's avatar
unknown committed
415
  Rotate_log_event(IO_CACHE* file, time_t when, uint32 server_id_arg) ;
416
  Rotate_log_event(const char* buf, int event_len);
unknown's avatar
unknown committed
417 418 419 420 421 422 423
  ~Rotate_log_event()
  {
    if (alloced)
      my_free((gptr) new_log_ident, MYF(0));
  }
  Log_event_type get_type_code() { return ROTATE_EVENT;}
  int get_data_size() { return  ident_len;}
424
  int write_data(IO_CACHE* file);
unknown's avatar
unknown committed
425
  
426
  void print(FILE* file, bool short_form = 0, char* last_db = 0);
unknown's avatar
unknown committed
427 428 429
};

#endif