/** * read binlog info * * A mysql binlog file is begin with a head "/xfebin" and then log evnets. The * first event is a format description event, the last event is a rotate event. * * For more infomation about mysql binlog format, see http://forge.mysql.com/wiki/MySQL_Internals_Binary_Log */ class BinlogInfo { const EVENT_HEAD_SIZE = 19; const FORMAT_DESCRIPTION_EVENT_DATA_SIZE = 59; const BINLOG_HEAD = "/xfebin"; const FORMAT_DESCRIPTION_EVENT = 15; const ROTATE_EVENT = 4;
/** * @param resource $file * * Mysql binlog file begin with a 4 bytes head: "/xfebin". */ protected function isBinlog($file) { rewind($file); $head = fread($file, strlen(self::BINLOG_HEAD)); return $head == self::BINLOG_HEAD; }
/** * @param resource $file * * Format description event is the first event of a binlog file */ protected function readFormatDescriptionEvent($file) { fseek($file, strlen(self::BINLOG_HEAD), SEEK_SET); $head_str = fread($file, self::EVENT_HEAD_SIZE); $head = unpack($this->eventHeadPackStr, $head_str); if ($head['type_code'] != self::FORMAT_DESCRIPTION_EVENT) { return null; } $data_str= fread($file, self::FORMAT_DESCRIPTION_EVENT_DATA_SIZE); $data = unpack($this->formatDescriptionEventDataPackStr, $data_str);
return array('head'=>$head, 'data'=>$data); }
/** * @param resource $file * * Rotate event is the last event of a binglog. * After event header, there is a bit int indicate the first event * position of next binlog file and next binlog file name without /0 at end. * The position is always be 4 (hex: 0400000000000000). * */ protected function readRotateEvent($file) { /** * Rotate event size is 19(head size) + 8(pos) + len(filename). * 100 bytes can contain a filename which length less than 73 bytes and * it is short than the length of format description event so filesize - * bufsize will never be negative. */ $bufsize = 100; $size_pos = 8; fseek($file, -$bufsize, SEEK_END); $buf = fread($file, $bufsize); $min_begin = strlen(self::BINLOG_HEAD) + self::EVENT_HEAD_SIZE + $size_pos; $ok = false; for ($i = $bufsize - 1; $i > $min_begin; $i--) { if ($buf[$i] == "/0") { $ok = true; break; } } if (!$ok) { return null; } $next_filename = substr($buf, $i + 1);