From fa91bde2a5d4110eba6c7027a3bbcbe3775d3919 Mon Sep 17 00:00:00 2001 From: ideal Date: Mon, 13 May 2013 11:58:21 +0800 Subject: [PATCH 01/69] modify src/CMakeLists.txt to add -fPIC when compiling static library to allow it linked into other shared libraries --- src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b0308c1..066d960 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,6 +9,7 @@ set(replication_sources # Configure for building static library add_library(replication_static STATIC ${replication_sources}) +set_target_properties(replication_static PROPERTIES COMPILE_FLAGS -fPIC) target_link_libraries(replication_static crypto pthread) set_target_properties(replication_static PROPERTIES OUTPUT_NAME "replication") From 43255c7c00777b1f7c8f61028465766d86337abf Mon Sep 17 00:00:00 2001 From: ideal Date: Mon, 13 May 2013 16:51:15 +0800 Subject: [PATCH 02/69] comment a cout --- src/protocol.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocol.cpp b/src/protocol.cpp index adace5b..5f94fb4 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -446,7 +446,7 @@ Row_event *proto_rows_event(std::istream &is, Log_event_header *header) bytes_read+=used_column_len; unsigned long row_len= header->event_length - bytes_read - LOG_EVENT_HEADER_SIZE + 1; - std::cout << "Bytes read: " << bytes_read << " Bytes expected: " << row_len << std::endl; + //std::cout << "Bytes read: " << bytes_read << " Bytes expected: " << row_len << std::endl; Protocol_chunk_vector proto_row(rev->row, row_len); is >> proto_row; From 4df67c9d686b2774bd875f7234ab48b988ff2344 Mon Sep 17 00:00:00 2001 From: ideal Date: Tue, 14 May 2013 11:47:01 +0800 Subject: [PATCH 03/69] add install tips to readme and update cmakelists --- CMakeLists.txt | 2 +- README.md | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d86aa26..5c14c16 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,5 +26,5 @@ add_subdirectory(src) include(InstallRequiredSystemLibraries) # installation configuration -install(DIRECTORY include DESTINATION /usr FILES_MATCHING PATTERN "*.h") +install(DIRECTORY include DESTINATION . FILES_MATCHING PATTERN "*.h") diff --git a/README.md b/README.md index 25fdc06..227386f 100644 --- a/README.md +++ b/README.md @@ -6,3 +6,13 @@ A listener to fetch binlog from mysql server. Reference: https://code.launchpad.net/mysql-replication-listener https://github.com/wangmh/mysql-replication-listener + +Install +-------------------- +mysql-replication-listener uses cmake. + +$ cmake . -DCMAKE_INSTALL_PREFIX=/usr + +$ make + +$ sudo make install From f414d4bc76f6d82608cd8509bef3f65254eb66bd Mon Sep 17 00:00:00 2001 From: ideal Date: Tue, 14 May 2013 13:31:59 +0800 Subject: [PATCH 04/69] ignore asio files when installing --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c14c16..00233ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,5 +26,5 @@ add_subdirectory(src) include(InstallRequiredSystemLibraries) # installation configuration -install(DIRECTORY include DESTINATION . FILES_MATCHING PATTERN "*.h") +install(DIRECTORY include DESTINATION . FILES_MATCHING PATTERN "*.h" PATTERN "asio" EXCLUDE) From c38e611c2f880c0a7cdbb0722224cd893c6c9667 Mon Sep 17 00:00:00 2001 From: ideal Date: Sun, 19 May 2013 12:57:24 +0800 Subject: [PATCH 05/69] fix enum,string bugs --- include/field_iterator.h | 4 ++-- include/value.h | 17 +++++++++++++---- src/field_iterator.cpp | 14 +++++++------- src/value.cpp | 24 ++++++++++++++---------- 4 files changed, 36 insertions(+), 23 deletions(-) diff --git a/include/field_iterator.h b/include/field_iterator.h index 294f5a4..456ec21 100644 --- a/include/field_iterator.h +++ b/include/field_iterator.h @@ -33,7 +33,7 @@ namespace mysql { bool is_null(unsigned char *bitmap, int index); int lookup_metadata_field_size(enum mysql::system::enum_field_types field_type); -uint32_t extract_metadata(const Table_map_event *map, int col_no); +uint16_t extract_metadata(const Table_map_event *map, int col_no); template class Row_event_iterator : public std::iterator::fields(Iterator_value_type& fiel { ++row_field_col_index; unsigned int type= m_table_map->columns[col_no]&0xFF; - uint32_t metadata= extract_metadata(m_table_map, col_no); + uint16_t metadata= extract_metadata(m_table_map, col_no); mysql::Value val((enum mysql::system::enum_field_types)type, metadata, (const char *)&m_row_event->row[field_offset]); diff --git a/include/value.h b/include/value.h index f3a4c25..de274e0 100644 --- a/include/value.h +++ b/include/value.h @@ -41,7 +41,7 @@ namespace mysql { @return The size in bytes of a particular field */ int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, - uint32_t metadata); + uint16_t metadata); /** @@ -53,12 +53,21 @@ int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, class Value { public: - Value(enum system::enum_field_types type, uint32_t metadata, const char *storage) : + Value(enum system::enum_field_types type, uint16_t metadata, const char *storage) : m_type(type), m_storage(storage), m_metadata(metadata), m_is_null(false) { m_size = calc_field_size((unsigned char)type, (const unsigned char*)storage, metadata); + switch(type) { + case mysql::system::MYSQL_TYPE_SET: + case mysql::system::MYSQL_TYPE_ENUM: + case mysql::system::MYSQL_TYPE_STRING: + { + m_metadata = (metadata >> 8U); + break; + } + } //std::cout << "TYPE: " << type << " SIZE: " << m_size << std::endl; }; @@ -92,7 +101,7 @@ class Value */ size_t length() const { return m_size; } enum system::enum_field_types type() const { return m_type; } - uint32_t metadata() const { return m_metadata; } + uint16_t metadata() const { return m_metadata; } /** * Returns the integer representation of a storage of a pre-specified @@ -146,7 +155,7 @@ class Value enum system::enum_field_types m_type; size_t m_size; const char *m_storage; - uint32_t m_metadata; + uint16_t m_metadata; bool m_is_null; }; diff --git a/src/field_iterator.cpp b/src/field_iterator.cpp index 1198a11..c3fdc95 100644 --- a/src/field_iterator.cpp +++ b/src/field_iterator.cpp @@ -34,7 +34,7 @@ bool is_null(unsigned char *bitmap, int index) } -uint32_t extract_metadata(const Table_map_event *map, int col_no) +uint16_t extract_metadata(const Table_map_event *map, int col_no) { int offset= 0; @@ -44,19 +44,19 @@ uint32_t extract_metadata(const Table_map_event *map, int col_no) offset += lookup_metadata_field_size((enum mysql::system::enum_field_types)type); } - uint32_t metadata= 0; + uint16_t metadata= 0; unsigned int type= (unsigned int)map->columns[col_no]&0xFF; switch(lookup_metadata_field_size((enum mysql::system::enum_field_types)type)) { case 1: - metadata= map->metadata[offset]; + metadata = (unsigned char)map->metadata[offset]; break; case 2: { - unsigned int tmp= ((unsigned int)map->metadata[offset])&0xFF; - metadata= static_cast(tmp); - tmp= (((unsigned int)map->metadata[offset+1])&0xFF) << 8; - metadata+= static_cast(tmp); + unsigned int tmp= ((unsigned char)map->metadata[offset])&0xFF; + metadata= static_cast(tmp); + tmp= (((unsigned char)map->metadata[offset+1])&0xFF) << 8; + metadata+= static_cast(tmp); } break; } diff --git a/src/value.cpp b/src/value.cpp index 05044a1..fb1534e 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -25,7 +25,7 @@ using namespace mysql; using namespace mysql::system; namespace mysql { -int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, uint32_t metadata) +int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, uint16_t metadata) { uint32_t length; @@ -53,11 +53,10 @@ int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, u case mysql::system::MYSQL_TYPE_ENUM: case mysql::system::MYSQL_TYPE_STRING: { - unsigned char type= metadata >> 8U; - if ((type == mysql::system::MYSQL_TYPE_SET) || (type == mysql::system::MYSQL_TYPE_ENUM)) - length= metadata & 0x00ff; - else - { + unsigned char type = (metadata & 0x00ff); + if ((type == mysql::system::MYSQL_TYPE_SET) || (type == mysql::system::MYSQL_TYPE_ENUM)) { + length = (metadata >> 8U); + } else { /* We are reading the actual size from the master_data record because this field has the actual lengh stored in the first @@ -109,8 +108,8 @@ int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, u If from_bit_len is not 0, add 1 to the length to account for accurate number of bytes needed. */ - uint32_t from_len= (metadata >> 8U) & 0x00ff; - uint32_t from_bit_len= metadata & 0x00ff; + uint16_t from_len= (metadata >> 8U) & 0x00ff; + uint16_t from_bit_len= metadata & 0x00ff; //DBUG_ASSERT(from_bit_len <= 7); length= from_len + ((from_bit_len > 0) ? 1 : 0); break; @@ -207,18 +206,23 @@ char *Value::as_c_str(unsigned long &size) const size = 0; return NULL; } + + if (m_size == 1) { + size = 0; + return const_cast(m_storage); + } /* Length encoded; First byte is length of string. */ - int metadata_length= m_metadata > 255 ? 2 : 1; + int metadata_length = m_metadata > 255 ? 2 : 1; // std::cout << "m_size " << metadata_length << std::endl; /* Size is length of the character string; not of the entire storage */ - size= m_size - metadata_length; + size = m_size - metadata_length; return const_cast(m_storage + metadata_length); } From 6ea807ca10d6068075f657899b978e7891b8aa01 Mon Sep 17 00:00:00 2001 From: ideal Date: Sun, 19 May 2013 13:10:50 +0800 Subject: [PATCH 06/69] remove some print and change m_type of vale when needed --- include/value.h | 2 ++ src/tcp_driver.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/include/value.h b/include/value.h index de274e0..af5af07 100644 --- a/include/value.h +++ b/include/value.h @@ -59,11 +59,13 @@ class Value m_size = calc_field_size((unsigned char)type, (const unsigned char*)storage, metadata); + // metadata: 16bits, lower byte is real type, high byte is length switch(type) { case mysql::system::MYSQL_TYPE_SET: case mysql::system::MYSQL_TYPE_ENUM: case mysql::system::MYSQL_TYPE_STRING: { + m_type = (enum system::enum_field_types)(metadata & 0x00ff); m_metadata = (metadata >> 8U); break; } diff --git a/src/tcp_driver.cpp b/src/tcp_driver.cpp index 1c7e015..556132f 100644 --- a/src/tcp_driver.cpp +++ b/src/tcp_driver.cpp @@ -312,7 +312,7 @@ void Binlog_tcp_driver::handle_net_packet(const asio::error_code& err, std::size if (err) { Binary_log_event * ev= create_incident_event(175, err.message().c_str(), m_binlog_offset); - std::cout << "1:" << err.message() << std::endl; + // std::cout << "1:" << err.message() << std::endl; m_event_queue->push_front(ev); return; } @@ -326,7 +326,7 @@ void Binlog_tcp_driver::handle_net_packet(const asio::error_code& err, std::size << bytes_transferred << " instead."; Binary_log_event * ev= create_incident_event(175, os.str().c_str(), m_binlog_offset); - std::cout << "2:" << os.str() << std::endl; + // std::cout << "2:" << os.str() << std::endl; m_event_queue->push_front(ev); return; } @@ -388,7 +388,7 @@ void Binlog_tcp_driver::handle_net_packet_header(const asio::error_code& err, st if (err) { Binary_log_event * ev= create_incident_event(175, err.message().c_str(), m_binlog_offset); - std::cout << "3:" << err.message() << std::endl; + // std::cout << "3:" << err.message() << std::endl; m_event_queue->push_front(ev); return; } @@ -402,7 +402,7 @@ void Binlog_tcp_driver::handle_net_packet_header(const asio::error_code& err, st << bytes_transferred << " instead."; Binary_log_event * ev= create_incident_event(175, os.str().c_str(), m_binlog_offset); - std::cout << "4:" << os.str() << std::endl; + // std::cout << "4:" << os.str() << std::endl; m_event_queue->push_front(ev); return; } From 9559c7612962f78e93c8541ec935b1f3c4594dab Mon Sep 17 00:00:00 2001 From: ideal Date: Sun, 19 May 2013 21:43:51 +0800 Subject: [PATCH 07/69] remove unused variable --- include/tcp_driver.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/tcp_driver.h b/include/tcp_driver.h index 83134de..5073e8b 100644 --- a/include/tcp_driver.h +++ b/include/tcp_driver.h @@ -216,7 +216,7 @@ class Binlog_tcp_driver : public Binary_log_driver * constructed yet. */ Log_event_header *m_waiting_event; - Log_event_header m_log_event_header; + /** * A ring buffer used to dispatch aggregated events to the user application */ From cd53f6cb697bcd97d58050ef112ef4dc0e793d45 Mon Sep 17 00:00:00 2001 From: ideal Date: Mon, 20 May 2013 10:41:57 +0800 Subject: [PATCH 08/69] add enum and set data type --- src/value.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/value.cpp b/src/value.cpp index fb1534e..3a059cc 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -407,9 +407,11 @@ void Converter::to(std::string &str, const Value &val) const return; case MYSQL_TYPE_BIT: case MYSQL_TYPE_NEWDECIMAL: + str = "not implemented"; + return; case MYSQL_TYPE_ENUM: case MYSQL_TYPE_SET: - str = "not implemented"; + os << (val.length() == 1 ? static_cast(val.as_int8()) : val.as_int16()); return ; case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: @@ -502,10 +504,8 @@ void Converter::to(long long &out, const Value &val) const out= 0; break; case MYSQL_TYPE_ENUM: - out= 0; - break; - case MYSQL_TYPE_SET: - out= 0; + case MYSQL_TYPE_SET: + out = (val.length() == 1 ? static_cast(val.as_int8()) : val.as_int16()); break; case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: @@ -593,10 +593,8 @@ void Converter::to(long &out, const Value &val) const out= 0; break; case MYSQL_TYPE_ENUM: - out= 0; - break; case MYSQL_TYPE_SET: - out= 0; + out = (val.length() == 1 ? static_cast(val.as_int8()) : val.as_int16()); break; case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: From 09dcc9a579d3c8fa81f4f67dde4f42f861f93ca7 Mon Sep 17 00:00:00 2001 From: ideal Date: Mon, 20 May 2013 12:10:25 +0800 Subject: [PATCH 09/69] fix problem --- src/value.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/value.cpp b/src/value.cpp index 3a059cc..abbc787 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -412,7 +412,7 @@ void Converter::to(std::string &str, const Value &val) const case MYSQL_TYPE_ENUM: case MYSQL_TYPE_SET: os << (val.length() == 1 ? static_cast(val.as_int8()) : val.as_int16()); - return ; + break; case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: From c05e94e7eccf2d35f1288df0d35655ebaa787c8a Mon Sep 17 00:00:00 2001 From: ideal Date: Wed, 22 May 2013 23:36:24 +0800 Subject: [PATCH 10/69] processing new decimal type, not ready --- include/value.h | 1 + src/field_iterator.cpp | 22 +++++++++++----------- src/value.cpp | 11 +++++++---- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/include/value.h b/include/value.h index af5af07..61a01e9 100644 --- a/include/value.h +++ b/include/value.h @@ -43,6 +43,7 @@ namespace mysql { int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, uint16_t metadata); +int calc_newdecimal_size(uint8_t m, uint8_t d); /** * A value object class which encapsluate a tuple (value type, metadata, storage) diff --git a/src/field_iterator.cpp b/src/field_iterator.cpp index c3fdc95..b65e9a0 100644 --- a/src/field_iterator.cpp +++ b/src/field_iterator.cpp @@ -48,17 +48,17 @@ uint16_t extract_metadata(const Table_map_event *map, int col_no) unsigned int type= (unsigned int)map->columns[col_no]&0xFF; switch(lookup_metadata_field_size((enum mysql::system::enum_field_types)type)) { - case 1: - metadata = (unsigned char)map->metadata[offset]; - break; - case 2: - { - unsigned int tmp= ((unsigned char)map->metadata[offset])&0xFF; - metadata= static_cast(tmp); - tmp= (((unsigned char)map->metadata[offset+1])&0xFF) << 8; - metadata+= static_cast(tmp); - } - break; + case 1: + metadata = (unsigned char)map->metadata[offset]; + break; + case 2: + { + unsigned int tmp= ((unsigned char)map->metadata[offset])&0xFF; + metadata= static_cast(tmp); + tmp= (((unsigned char)map->metadata[offset+1])&0xFF) << 8; + metadata+= static_cast(tmp); + } + break; } return metadata; } diff --git a/src/value.cpp b/src/value.cpp index abbc787..7cbe0bd 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -25,6 +25,11 @@ using namespace mysql; using namespace mysql::system; namespace mysql { +int calc_newdecimal_size(uint8_t m, uint8_t d) +{ + return 0; +} + int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, uint16_t metadata) { uint32_t length; @@ -32,12 +37,10 @@ int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, u switch (column_type) { case mysql::system::MYSQL_TYPE_VAR_STRING: /* This type is hijacked for result set types. */ - length= metadata; + length = metadata; break; case mysql::system::MYSQL_TYPE_NEWDECIMAL: - //length= my_decimal_get_binary_size(metadata_ptr[col] >> 8, - // metadata_ptr[col] & 0xff); - length= 0; + length = calc_newdecimal_size(metadata & 0xff, metadata >> 8); break; case mysql::system::MYSQL_TYPE_DECIMAL: case mysql::system::MYSQL_TYPE_FLOAT: From ca79782909d00dc4bb9d2687ca46fa798c26514f Mon Sep 17 00:00:00 2001 From: ideal Date: Wed, 22 May 2013 23:53:59 +0800 Subject: [PATCH 11/69] processing new decimal type, not ready --- include/value.h | 2 +- src/value.cpp | 29 +++++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/include/value.h b/include/value.h index 61a01e9..7cb3ac6 100644 --- a/include/value.h +++ b/include/value.h @@ -43,7 +43,7 @@ namespace mysql { int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, uint16_t metadata); -int calc_newdecimal_size(uint8_t m, uint8_t d); +uint8_t calc_newdecimal_size(uint8_t m, uint8_t d); /** * A value object class which encapsluate a tuple (value type, metadata, storage) diff --git a/src/value.cpp b/src/value.cpp index 7cbe0bd..f57ba2b 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -25,9 +25,32 @@ using namespace mysql; using namespace mysql::system; namespace mysql { -int calc_newdecimal_size(uint8_t m, uint8_t d) +// calculate mysql NEW DECIMAL digits's size in bytes +static uint8_t calc_digits_size(uint8_t digits) { - return 0; + uint8_t size = 0; + + while (digits > 9) { + digits -= 9; + size += 4; + } + if (digits >=7) { + size += 4; + } else if (digits >= 5 && digits <= 6) { + size += 3; + } else if (digits >= 3 && digits <= 4) { + size += 2; + } else if (digits >= 1 && digits <= 2) { + size += 1; + } + + return size; +} + +uint8_t calc_newdecimal_size(uint8_t m, uint8_t d) +{ + // (m - d) is left digits + return calc_digits_size(m-d) + calc_digits_size(d); } int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, uint16_t metadata) @@ -40,6 +63,8 @@ int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, u length = metadata; break; case mysql::system::MYSQL_TYPE_NEWDECIMAL: + // higher byte is number of digits to the right of the decimal point + // lower byte is the maximum number of digits length = calc_newdecimal_size(metadata & 0xff, metadata >> 8); break; case mysql::system::MYSQL_TYPE_DECIMAL: From 1ff7c8ca666334d9ea042786c585284887107737 Mon Sep 17 00:00:00 2001 From: ideal Date: Thu, 23 May 2013 12:03:34 +0800 Subject: [PATCH 12/69] check m_waiting_event --- include/binlog_event.h | 4 ++++ src/tcp_driver.cpp | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/include/binlog_event.h b/include/binlog_event.h index b6eeccb..0ed976a 100644 --- a/include/binlog_event.h +++ b/include/binlog_event.h @@ -156,6 +156,8 @@ class Binary_log_event */ Log_event_header *header() { return &m_header; } + virtual bool is_valid() const { return true; } + private: Log_event_header m_header; }; @@ -171,6 +173,8 @@ class Query_event: public Binary_log_event std::string db_name; std::string query; + + bool is_valid() const { return query.length() != 0; } }; class Rotate_event: public Binary_log_event diff --git a/src/tcp_driver.cpp b/src/tcp_driver.cpp index 556132f..7868c21 100644 --- a/src/tcp_driver.cpp +++ b/src/tcp_driver.cpp @@ -279,7 +279,11 @@ void Binlog_tcp_driver::start_binlog_dump(const std::string &binlog_file_name, s if (!m_event_loop) { this->thread_data->tcp_driver = this; m_event_loop = (pthread_t *)malloc(sizeof(pthread_t)); - pthread_create(m_event_loop, NULL, &Binlog_tcp_driver::start, (void *)this->thread_data); + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, + PTHREAD_CREATE_JOINABLE); + pthread_create(m_event_loop, &attr, &Binlog_tcp_driver::start, (void *)this->thread_data); } } @@ -332,6 +336,10 @@ void Binlog_tcp_driver::handle_net_packet(const asio::error_code& err, std::size } //assert(m_waiting_event != 0); + if (!m_waiting_event) { + return; + } + //std::cerr << "Committing '"<< bytes_transferred << "' bytes to the event stream." << std::endl; m_event_stream_buffer.commit(bytes_transferred); /* From eaef4c99eb8d7d4b131f47b1d1d5ba306c12e1b8 Mon Sep 17 00:00:00 2001 From: ideal Date: Thu, 23 May 2013 20:40:58 +0800 Subject: [PATCH 13/69] temp fix a problem... --- src/value.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/value.cpp b/src/value.cpp index f57ba2b..253d1d8 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -97,7 +97,7 @@ int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, u } case mysql::system::MYSQL_TYPE_YEAR: case mysql::system::MYSQL_TYPE_TINY: - length= 1; + length = 1; break; case mysql::system::MYSQL_TYPE_SHORT: length= 2; @@ -351,6 +351,10 @@ void Converter::to(std::string &str, const Value &val) const str = "NULL"; return; } + if (!val.storage()) { + str = "NULL"; + return; + } std::ostringstream os; switch(val.type()) From 0ffb41095db99089a567aa93835c58a6d0a9e56a Mon Sep 17 00:00:00 2001 From: ideal Date: Wed, 29 May 2013 13:05:38 +0800 Subject: [PATCH 14/69] some change... --- src/value.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/value.cpp b/src/value.cpp index 253d1d8..1a53de2 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -144,9 +144,9 @@ int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, u } case mysql::system::MYSQL_TYPE_VARCHAR: { - length= metadata > 255 ? 2 : 1; + length = metadata > 255 ? 2 : 1; - length+= length == 1 ? (uint32_t) *field_ptr : *((uint16_t *)field_ptr); + length += length == 1 ? *((uint8_t *)field_ptr) : *((uint16_t *)field_ptr); break; } @@ -282,8 +282,8 @@ int32_t Value::as_int32() const { return 0; } - uint32_t to_int; - Protocol_chunk prot_integer(to_int); + int32_t to_int; + Protocol_chunk prot_integer(to_int); buffer_source buff(m_storage, m_size); buff >> prot_integer; From 6f8a96d713a6ab0259e41e9b44ab3264c158dd97 Mon Sep 17 00:00:00 2001 From: ideal Date: Wed, 29 May 2013 16:59:22 +0800 Subject: [PATCH 15/69] add date type --- src/value.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/value.cpp b/src/value.cpp index 1a53de2..875fa41 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -390,8 +390,22 @@ void Converter::to(std::string &str, const Value &val) const str = "not implemented"; return; case MYSQL_TYPE_DATE: - str = "not implemented"; + { + const char *storage = val.storage(); + uint32_t date = (storage[0] & 0xff) + ((storage[1] & 0xff) << 8) + ((storage[2] & 0xff) << 16); + // actually date occupies 3 bytes, so below will work + uint16_t year = date >> 9; + date -= (year << 9); + uint16_t month = date >> 5; + date -= (year << 5); + uint16_t day = date; + os << std::setfill('0') << std::setw(4) << year + << std::setw(1) << '-' + << std::setw(2) << month + << std::setw(1) << '-' + << std::setw(2) << day; return; + } case MYSQL_TYPE_DATETIME: { uint64_t timestamp= val.as_int64(); From 8ae0cfbfe3872faf0929ad078ed57e52d8c36138 Mon Sep 17 00:00:00 2001 From: ideal Date: Wed, 29 May 2013 17:07:08 +0800 Subject: [PATCH 16/69] fix ashamed problem :( --- src/value.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/value.cpp b/src/value.cpp index 875fa41..953e7e1 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -397,14 +397,14 @@ void Converter::to(std::string &str, const Value &val) const uint16_t year = date >> 9; date -= (year << 9); uint16_t month = date >> 5; - date -= (year << 5); + date -= (month << 5); uint16_t day = date; os << std::setfill('0') << std::setw(4) << year << std::setw(1) << '-' << std::setw(2) << month << std::setw(1) << '-' << std::setw(2) << day; - return; + break; } case MYSQL_TYPE_DATETIME: { From 6b9bd688b5c1df7945e228156fffeee7ddf7db98 Mon Sep 17 00:00:00 2001 From: ideal Date: Wed, 29 May 2013 21:44:34 +0800 Subject: [PATCH 17/69] add time and year type --- src/value.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/value.cpp b/src/value.cpp index 953e7e1..3fa43a7 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -426,7 +426,30 @@ void Converter::to(std::string &str, const Value &val) const } break; case MYSQL_TYPE_TIME: + { + const char *storage = val.storage(); + uint32_t time = (storage[0] & 0xff) + ((storage[1] & 0xff) << 8) + ((storage[2] & 0xff) << 16); + uint16_t sec = time % 100; + time -= sec; + uint16_t min = (time % 10000) / 100; + uint16_t hour = (time - min) / 10000; + os << std::setfill('0') << std::setw(2) << hour + << std::setw(1) << ':' + << std::setw(2) << min + << std::setw(1) << ':' + << std::setw(2) << sec; + break; + } case MYSQL_TYPE_YEAR: + { + const char *storage = val.storage(); + uint16_t year = (storage[0] & 0xff); + if (year > 0) { + year += 1900; + } + os << std::setfill('0') << std::setw(4) << year; + break; + } case MYSQL_TYPE_NEWDATE: str = "not implemented"; return; From 2b5d609b5745fb53736a309d315d5eb56266c431 Mon Sep 17 00:00:00 2001 From: ideal Date: Fri, 31 May 2013 17:05:05 +0800 Subject: [PATCH 18/69] change master_id in COM_REGISTER_SLAVE --- src/tcp_driver.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/tcp_driver.cpp b/src/tcp_driver.cpp index 7868c21..0b176ed 100644 --- a/src/tcp_driver.cpp +++ b/src/tcp_driver.cpp @@ -173,8 +173,11 @@ tcp::socket *sync_connect_and_authenticate(asio::io_service &io_service, const s Protocol_chunk prot_command(COM_REGISTER_SLAVE); Protocol_chunk prot_connection_port(port); Protocol_chunk prot_rpl_recovery_rank(0); - Protocol_chunk prot_server_id(1); - Protocol_chunk prot_master_server_id(1); + Protocol_chunk prot_server_id(1); // slave server-id + /* + * See document at http://dev.mysql.com/doc/internals/en/replication-protocol.html + */ + Protocol_chunk prot_master_server_id(0); Protocol_chunk prot_report_host_strlen(host.size()); Protocol_chunk prot_user_strlen(user.size()); From 275182756119386e062ef1d65a00d931a6ac2a2c Mon Sep 17 00:00:00 2001 From: ideal Date: Sat, 1 Jun 2013 15:29:06 +0800 Subject: [PATCH 19/69] add new decimal data type --- include/decimal.h | 80 +++++++++ src/CMakeLists.txt | 2 +- src/decimal.cpp | 422 +++++++++++++++++++++++++++++++++++++++++++++ src/value.cpp | 15 +- 4 files changed, 516 insertions(+), 3 deletions(-) create mode 100644 include/decimal.h create mode 100644 src/decimal.cpp diff --git a/include/decimal.h b/include/decimal.h new file mode 100644 index 0000000..8b10055 --- /dev/null +++ b/include/decimal.h @@ -0,0 +1,80 @@ +/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + + 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; version 2 of the License. + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef _decimal_h +#define _decimal_h + +#include +#include + +#if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96) +#define __builtin_expect(x, expected_value) (x) +#endif + +#define likely(x) __builtin_expect((x),1) +#define unlikely(x) __builtin_expect((x),0) + +typedef enum +{ + TRUNCATE=0, + HALF_EVEN, + HALF_UP, + CEILING, + FLOOR +} decimal_round_mode; + +typedef int32_t decimal_digit_t; + +/** + intg is the number of *decimal* digits (NOT number of decimal_digit_t's !) + before the point + frac is the number of decimal digits after the point + len is the length of buf (length of allocated space) in decimal_digit_t's, + not in bytes + sign false means positive, true means negative + buf is an array of decimal_digit_t's + */ +typedef struct st_decimal_t { + int intg, frac, len; + char sign; + decimal_digit_t *buf; +} decimal_t; + +int decimal_bin_size(int precision, int scale); +int decimal2string(const decimal_t *from, char *to, int *to_len, + int fixed_precision, int fixed_decimals, + char filler); + +int bin2decimal(const u_char *from, decimal_t *to, int precision, int scale); + +#define E_DEC_OK 0 +#define E_DEC_TRUNCATED 1 +#define E_DEC_OVERFLOW 2 +#define E_DEC_DIV_ZERO 4 +#define E_DEC_BAD_NUM 8 +#define E_DEC_OOM 16 + +#define E_DEC_ERROR 31 +#define E_DEC_FATAL_ERROR 30 + +#define decimal_make_zero(dec) do { \ + (dec)->buf[0]=0; \ + (dec)->intg=1; \ + (dec)->frac=0; \ + (dec)->sign=0; \ + } while(0) + +#endif + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 066d960..13ed68d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,7 +5,7 @@ set(replication_sources binlog_driver.cpp basic_transaction_parser.cpp tcp_driver.cpp file_driver.cpp binary_log.cpp protocol.cpp value.cpp binlog_event.cpp resultset_iterator.cpp basic_transaction_parser.cpp - basic_content_handler.cpp utilities.cpp) + basic_content_handler.cpp utilities.cpp decimal.cpp) # Configure for building static library add_library(replication_static STATIC ${replication_sources}) diff --git a/src/decimal.cpp b/src/decimal.cpp new file mode 100644 index 0000000..d66adb3 --- /dev/null +++ b/src/decimal.cpp @@ -0,0 +1,422 @@ +/* Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. + + 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; version 2 of the License. + + 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 */ + +#include +#include +#include +#include + +#include "decimal.h" + +typedef decimal_digit_t dec1; +typedef long long dec2; + +#define DBUG_ASSERT(a) assert(a) +#define test(a) ((a) ? 1 : 0) +#define max(a, b) ((a) > (b) ? (a) : (b)) +#define min(a, b) ((a) < (b) ? (a) : (b)) +#define mi_sint1korr(A) ((int8_t)(*A)) +#define mi_uint1korr(A) ((uint8_t)(*A)) +#define mi_sint2korr(A) ((int16_t) (((int16_t) (((u_char*) (A))[1])) +\ + ((int16_t) ((int16_t) ((char *) (A))[0]) << 8))) +#define mi_sint3korr(A) ((int32_t) (((((u_char*) (A))[0]) & 128) ? \ + (((uint32_t) 255L << 24) | \ + (((uint32_t) ((u_char*) (A))[0]) << 16) |\ + (((uint32_t) ((u_char*) (A))[1]) << 8) | \ + ((uint32_t) ((u_char*) (A))[2])) : \ + (((uint32_t) ((u_char*) (A))[0]) << 16) |\ + (((uint32_t) ((u_char*) (A))[1]) << 8) | \ + ((uint32_t) ((u_char*) (A))[2]))) +#define mi_sint4korr(A) ((int32_t) (((int32_t) (((u_char*) (A))[3])) +\ + ((int32_t) (((u_char*) (A))[2]) << 8) +\ + ((int32_t) (((u_char*) (A))[1]) << 16) +\ + ((int32_t) ((int16_t) ((char*) (A))[0]) << 24))) + +#define DIG_PER_DEC1 9 +#define DIG_MASK 100000000 +#define DIG_BASE 1000000000 +#define DIG_MAX (DIG_BASE-1) +#define DIG_BASE2 ((dec2)DIG_BASE * (dec2)DIG_BASE) +#define ROUND_UP(X) (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1) + +static const dec1 powers10[DIG_PER_DEC1+1]={ + 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; + +static const int dig2bytes[DIG_PER_DEC1+1]={0, 1, 1, 2, 2, 3, 3, 4, 4, 4}; + +static const dec1 frac_max[DIG_PER_DEC1-1]={ + 900000000, 990000000, 999000000, + 999900000, 999990000, 999999000, + 999999900, 999999990 }; + +#define sanity(d) DBUG_ASSERT((d)->len >0 && ((d)->buf[0] | \ + (d)->buf[(d)->len-1] | 1)) + +#define FIX_INTG_FRAC_ERROR(len, intg1, frac1, error) \ + do \ + { \ + if (unlikely(intg1+frac1 > (len))) \ + { \ + if (unlikely(intg1 > (len))) \ + { \ + intg1=(len); \ + frac1=0; \ + error=E_DEC_OVERFLOW; \ + } \ + else \ + { \ + frac1=(len)-intg1; \ + error=E_DEC_TRUNCATED; \ + } \ + } \ + else \ + error=E_DEC_OK; \ + } while(0) + +#define ADD(to, from1, from2, carry) /* assume carry <= 1 */ \ + do \ + { \ + dec1 a=(from1)+(from2)+(carry); \ + DBUG_ASSERT((carry) <= 1); \ + if (((carry)= a >= DIG_BASE)) /* no division here! */ \ + a-=DIG_BASE; \ + (to)=a; \ + } while(0) + +#define ADD2(to, from1, from2, carry) \ + do \ + { \ + dec2 a=((dec2)(from1))+(from2)+(carry); \ + if (((carry)= a >= DIG_BASE)) \ + a-=DIG_BASE; \ + if (unlikely(a >= DIG_BASE)) \ + { \ + a-=DIG_BASE; \ + carry++; \ + } \ + (to)=(dec1) a; \ + } while(0) + +#define SUB(to, from1, from2, carry) /* to=from1-from2 */ \ + do \ + { \ + dec1 a=(from1)-(from2)-(carry); \ + if (((carry)= a < 0)) \ + a+=DIG_BASE; \ + (to)=a; \ + } while(0) + +#define SUB2(to, from1, from2, carry) /* to=from1-from2 */ \ + do \ + { \ + dec1 a=(from1)-(from2)-(carry); \ + if (((carry)= a < 0)) \ + a+=DIG_BASE; \ + if (unlikely(a < 0)) \ + { \ + a+=DIG_BASE; \ + carry++; \ + } \ + (to)=a; \ + } while(0) + +static dec1 *remove_leading_zeroes(const decimal_t *from, int *intg_result) +{ + int intg= from->intg, i; + dec1 *buf0= from->buf; + i= ((intg - 1) % DIG_PER_DEC1) + 1; + while (intg > 0 && *buf0 == 0) + { + intg-= i; + i= DIG_PER_DEC1; + buf0++; + } + if (intg > 0) + { + for (i= (intg - 1) % DIG_PER_DEC1; *buf0 < powers10[i--]; intg--) ; + DBUG_ASSERT(intg > 0); + } + else + intg=0; + *intg_result= intg; + return buf0; +} + +/* + Convert decimal to its printable string representation + + SYNOPSIS + decimal2string() + from - value to convert + to - points to buffer where string representation + should be stored + *to_len - in: size of to buffer (incl. terminating '\0') + out: length of the actually written string (excl. '\0') + fixed_precision - 0 if representation can be variable length and + fixed_decimals will not be checked in this case. + Put number as with fixed point position with this + number of digits (sign counted and decimal point is + counted) + fixed_decimals - number digits after point. + filler - character to fill gaps in case of fixed_precision > 0 + + RETURN VALUE + E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW +*/ + +int decimal2string(const decimal_t *from, char *to, int *to_len, + int fixed_precision, int fixed_decimals, + char filler) +{ + /* {intg_len, frac_len} output widths; {intg, frac} places in input */ + int len, intg, frac= from->frac, i, intg_len, frac_len, fill; + /* number digits before decimal point */ + int fixed_intg= (fixed_precision ? + (fixed_precision - fixed_decimals) : 0); + int error=E_DEC_OK; + char *s=to; + dec1 *buf, *buf0=from->buf, tmp; + + DBUG_ASSERT(*to_len >= 2+from->sign); + + /* removing leading zeroes */ + buf0 = remove_leading_zeroes(from, &intg); + if (unlikely(intg+frac==0)) + { + intg=1; + tmp=0; + buf0=&tmp; + } + + if (!(intg_len= fixed_precision ? fixed_intg : intg)) + intg_len= 1; + frac_len= fixed_precision ? fixed_decimals : frac; + len= from->sign + intg_len + test(frac) + frac_len; + if (fixed_precision) + { + if (frac > fixed_decimals) + { + error= E_DEC_TRUNCATED; + frac= fixed_decimals; + } + if (intg > fixed_intg) + { + error= E_DEC_OVERFLOW; + intg= fixed_intg; + } + } + else if (unlikely(len > --*to_len)) /* reserve one byte for \0 */ + { + int j= len-*to_len; + error= (frac && j <= frac + 1) ? E_DEC_TRUNCATED : E_DEC_OVERFLOW; + if (frac && j >= frac + 1) j--; + if (j > frac) + { + intg-= j-frac; + frac= 0; + } + else + frac-=j; + len= from->sign + intg_len + test(frac) + frac_len; + } + *to_len=len; + s[len]=0; + + if (from->sign) + *s++='-'; + + if (frac) + { + char *s1= s + intg_len; + fill= frac_len - frac; + buf=buf0+ROUND_UP(intg); + *s1++='.'; + for (; frac>0; frac-=DIG_PER_DEC1) + { + dec1 x=*buf++; + for (i=min(frac, DIG_PER_DEC1); i; i--) + { + dec1 y=x/DIG_MASK; + *s1++='0'+(u_char)y; + x-=y*DIG_MASK; + x*=10; + } + } + for(; fill; fill--) + *s1++=filler; + } + + fill= intg_len - intg; + if (intg == 0) + fill--; /* symbol 0 before digital point */ + for(; fill; fill--) + *s++=filler; + if (intg) + { + s+=intg; + for (buf=buf0+ROUND_UP(intg); intg>0; intg-=DIG_PER_DEC1) + { + dec1 x=*--buf; + for (i=min(intg, DIG_PER_DEC1); i; i--) + { + dec1 y=x/10; + *--s='0'+(u_char)(x-y*10); + x=y; + } + } + } + else + *s= '0'; + return error; +} + +/* + Restores decimal from its binary fixed-length representation + + SYNOPSIS + bin2decimal() + from - value to convert + to - result + precision/scale - see decimal_bin_size() below + + NOTE + see decimal2bin() + the buffer is assumed to be of the size decimal_bin_size(precision, scale) + + RETURN VALUE + E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW +*/ + +int bin2decimal(const u_char *from, decimal_t *to, int precision, int scale) +{ + int error=E_DEC_OK, intg=precision-scale, + intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1, + intg0x=intg-intg0*DIG_PER_DEC1, frac0x=scale-frac0*DIG_PER_DEC1, + intg1=intg0+(intg0x>0), frac1=frac0+(frac0x>0); + dec1 *buf=to->buf, mask=(*from & 0x80) ? 0 : -1; + const u_char *stop; + u_char *d_copy; + int bin_size= decimal_bin_size(precision, scale); + + sanity(to); + d_copy= (u_char*) malloc(bin_size); + memcpy(d_copy, from, bin_size); + d_copy[0]^= 0x80; + from= d_copy; + + FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error); + if (unlikely(error)) + { + if (intg1 < intg0+(intg0x>0)) + { + from+=dig2bytes[intg0x]+sizeof(dec1)*(intg0-intg1); + frac0=frac0x=intg0x=0; + intg0=intg1; + } + else + { + frac0x=0; + frac0=frac1; + } + } + + to->sign=(mask != 0); + to->intg=intg0*DIG_PER_DEC1+intg0x; + to->frac=frac0*DIG_PER_DEC1+frac0x; + + if (intg0x) + { + int i=dig2bytes[intg0x]; + dec1 x = 0; + switch (i) + { + case 1: x=mi_sint1korr(from); break; + case 2: x=mi_sint2korr(from); break; + case 3: x=mi_sint3korr(from); break; + case 4: x=mi_sint4korr(from); break; + default: DBUG_ASSERT(0); + } + from+=i; + *buf=x ^ mask; + if (((unsigned long long)*buf) >= (unsigned long long) powers10[intg0x+1]) + goto err; + if (buf > to->buf || *buf != 0) + buf++; + else + to->intg-=intg0x; + } + for (stop=from+intg0*sizeof(dec1); from < stop; from+=sizeof(dec1)) + { + DBUG_ASSERT(sizeof(dec1) == 4); + *buf=mi_sint4korr(from) ^ mask; + if (((uint32_t)*buf) > DIG_MAX) + goto err; + if (buf > to->buf || *buf != 0) + buf++; + else + to->intg-=DIG_PER_DEC1; + } + DBUG_ASSERT(to->intg >=0); + for (stop=from+frac0*sizeof(dec1); from < stop; from+=sizeof(dec1)) + { + DBUG_ASSERT(sizeof(dec1) == 4); + *buf=mi_sint4korr(from) ^ mask; + if (((uint32_t)*buf) > DIG_MAX) + goto err; + buf++; + } + if (frac0x) + { + int i=dig2bytes[frac0x]; + dec1 x = 0; + switch (i) + { + case 1: x=mi_sint1korr(from); break; + case 2: x=mi_sint2korr(from); break; + case 3: x=mi_sint3korr(from); break; + case 4: x=mi_sint4korr(from); break; + default: DBUG_ASSERT(0); + } + *buf=(x ^ mask) * powers10[DIG_PER_DEC1 - frac0x]; + if (((uint32_t)*buf) > DIG_MAX) + goto err; + buf++; + } + free(d_copy); + + /* + No digits? We have read the number zero, of unspecified precision. + Make it a proper zero, with non-zero precision. + */ + if (to->intg == 0 && to->frac == 0) + decimal_make_zero(to); + return error; + +err: + free(d_copy); + decimal_make_zero(to); + return(E_DEC_BAD_NUM); +} + +int decimal_bin_size(int precision, int scale) +{ + int intg=precision-scale, + intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1, + intg0x=intg-intg0*DIG_PER_DEC1, frac0x=scale-frac0*DIG_PER_DEC1; + + return intg0*sizeof(dec1)+dig2bytes[intg0x]+ + frac0*sizeof(dec1)+dig2bytes[frac0x]; +} + diff --git a/src/value.cpp b/src/value.cpp index 3fa43a7..e6c5231 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -17,9 +17,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "value.h" #include + +#include "value.h" #include "binlog_event.h" +#include "decimal.h" using namespace mysql; using namespace mysql::system; @@ -476,7 +478,16 @@ void Converter::to(std::string &str, const Value &val) const return; case MYSQL_TYPE_BIT: case MYSQL_TYPE_NEWDECIMAL: - str = "not implemented"; + { + char buffer[100], result[100]; + int len = 100; + decimal_t decimal; + decimal.buf = (decimal_digit_t *)buffer; + decimal.len = sizeof(buffer)/sizeof(decimal_digit_t); + bin2decimal((const u_char *)val.storage(), &decimal, val.metadata() & 0xff, val.metadata() >> 8); + decimal2string(&decimal, result, &len, 0, 0, 0); + str.assign(result, len); + } return; case MYSQL_TYPE_ENUM: case MYSQL_TYPE_SET: From 7fd3800fe7d3a68127fa70784a079b9846edcde8 Mon Sep 17 00:00:00 2001 From: ideal Date: Sun, 2 Jun 2013 10:23:45 +0800 Subject: [PATCH 20/69] Change version number. This is an almost stable version currently. --- CMakeLists.txt | 4 ++-- src/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 00233ad..d4a4962 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,8 +2,8 @@ project (mysql-replication-listener) cmake_minimum_required (VERSION 2.6) set(MySQL_BINLOG_VERSION_MAJOR "0") -set(MySQL_BINLOG_VERSION_MINOR "0.1") -set(MRL_VERSION "${MySQL_BINLOG_VERSION_MAJOR}.${MySQL_BINLOG_VERSION_MINOR}") +set(MySQL_BINLOG_VERSION_MINOR "2") +set(MySQL_BINLOG_VERSION "${MySQL_BINLOG_VERSION_MAJOR}.${MySQL_BINLOG_VERSION_MINOR}") set(CMAKE_VERSION_STRING "${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 13ed68d..68f7c63 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -19,7 +19,7 @@ add_library(replication_shared SHARED ${replication_sources}) target_link_libraries(replication_shared crypto pthread) set_target_properties(replication_shared PROPERTIES - VERSION 0.1 SOVERSION 1 + VERSION ${MySQL_BINLOG_VERSION} SOVERSION 2 OUTPUT_NAME "replication") install(TARGETS replication_shared LIBRARY DESTINATION lib) From 164d6beb822c6742011d7aef530ce14c889fd891 Mon Sep 17 00:00:00 2001 From: ideal Date: Sun, 2 Jun 2013 17:47:43 +0800 Subject: [PATCH 21/69] change version number --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d4a4962..2ec587f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,8 @@ cmake_minimum_required (VERSION 2.6) set(MySQL_BINLOG_VERSION_MAJOR "0") set(MySQL_BINLOG_VERSION_MINOR "2") -set(MySQL_BINLOG_VERSION "${MySQL_BINLOG_VERSION_MAJOR}.${MySQL_BINLOG_VERSION_MINOR}") +set(MySQL_BINLOG_VERSION_PATCH "0") +set(MySQL_BINLOG_VERSION "${MySQL_BINLOG_VERSION_MAJOR}.${MySQL_BINLOG_VERSION_MINOR}.${MySQL_BINLOG_VERSION_PATCH}") set(CMAKE_VERSION_STRING "${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}") From 68ab25b59e42cabcf66094564ce5ea4f63917da1 Mon Sep 17 00:00:00 2001 From: ideal Date: Fri, 14 Jun 2013 10:14:47 +0800 Subject: [PATCH 22/69] add extern C declaration --- include/decimal.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/decimal.h b/include/decimal.h index 8b10055..27f1ad8 100644 --- a/include/decimal.h +++ b/include/decimal.h @@ -52,6 +52,10 @@ typedef struct st_decimal_t { decimal_digit_t *buf; } decimal_t; +#ifdef __cplusplus +extern "C" { +#endif + int decimal_bin_size(int precision, int scale); int decimal2string(const decimal_t *from, char *to, int *to_len, int fixed_precision, int fixed_decimals, @@ -59,6 +63,10 @@ int decimal2string(const decimal_t *from, char *to, int *to_len, int bin2decimal(const u_char *from, decimal_t *to, int precision, int scale); +#ifdef __cplusplus +} +#endif + #define E_DEC_OK 0 #define E_DEC_TRUNCATED 1 #define E_DEC_OVERFLOW 2 From 66f090fa6815985892622b1e1b966b11d92c3714 Mon Sep 17 00:00:00 2001 From: rami-dabain Date: Mon, 1 Jul 2013 02:44:34 -0700 Subject: [PATCH 23/69] Build error fix on latest CMAKE on UBUNTU --- src/CMakeLists.txt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 68f7c63..cb4e580 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,3 +1,4 @@ +cmake_minimum_required(VERSION 2.8) # This configuration file builds both the static and shared version of # the library. set(replication_sources @@ -18,9 +19,11 @@ set_target_properties(replication_static PROPERTIES add_library(replication_shared SHARED ${replication_sources}) target_link_libraries(replication_shared crypto pthread) -set_target_properties(replication_shared PROPERTIES - VERSION ${MySQL_BINLOG_VERSION} SOVERSION 2 - OUTPUT_NAME "replication") +set_target_properties( +replication_shared +PROPERTIES +VERSION "${MySQL_BINLOG_VERSION}" SOVERSION 2 OUTPUT_NAME "replication" +) install(TARGETS replication_shared LIBRARY DESTINATION lib) install(TARGETS replication_static ARCHIVE DESTINATION lib) From 01bf5bcd142fe881c474063f61ab0dfb5cc0d6a4 Mon Sep 17 00:00:00 2001 From: ideal Date: Mon, 1 Jul 2013 18:50:35 +0800 Subject: [PATCH 24/69] change cmake minimum to 2.8 and format in src/CMakeLists.txt --- CMakeLists.txt | 2 +- src/CMakeLists.txt | 5 +---- src/tcp_driver.cpp | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ec587f..1f096ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ project (mysql-replication-listener) -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8) set(MySQL_BINLOG_VERSION_MAJOR "0") set(MySQL_BINLOG_VERSION_MINOR "2") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cb4e580..00fdede 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,3 @@ -cmake_minimum_required(VERSION 2.8) # This configuration file builds both the static and shared version of # the library. set(replication_sources @@ -19,9 +18,7 @@ set_target_properties(replication_static PROPERTIES add_library(replication_shared SHARED ${replication_sources}) target_link_libraries(replication_shared crypto pthread) -set_target_properties( -replication_shared -PROPERTIES +set_target_properties(replication_shared PROPERTIES VERSION "${MySQL_BINLOG_VERSION}" SOVERSION 2 OUTPUT_NAME "replication" ) diff --git a/src/tcp_driver.cpp b/src/tcp_driver.cpp index 0b176ed..538ecd5 100644 --- a/src/tcp_driver.cpp +++ b/src/tcp_driver.cpp @@ -173,7 +173,7 @@ tcp::socket *sync_connect_and_authenticate(asio::io_service &io_service, const s Protocol_chunk prot_command(COM_REGISTER_SLAVE); Protocol_chunk prot_connection_port(port); Protocol_chunk prot_rpl_recovery_rank(0); - Protocol_chunk prot_server_id(1); // slave server-id + Protocol_chunk prot_server_id(2000); // slave server-id /* * See document at http://dev.mysql.com/doc/internals/en/replication-protocol.html */ From df0c774a8e98647aac084227f2dae5ac19c48fdd Mon Sep 17 00:00:00 2001 From: ideal Date: Mon, 1 Jul 2013 19:07:42 +0800 Subject: [PATCH 25/69] revert src/tcp_driver.cpp --- src/tcp_driver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tcp_driver.cpp b/src/tcp_driver.cpp index 538ecd5..0b176ed 100644 --- a/src/tcp_driver.cpp +++ b/src/tcp_driver.cpp @@ -173,7 +173,7 @@ tcp::socket *sync_connect_and_authenticate(asio::io_service &io_service, const s Protocol_chunk prot_command(COM_REGISTER_SLAVE); Protocol_chunk prot_connection_port(port); Protocol_chunk prot_rpl_recovery_rank(0); - Protocol_chunk prot_server_id(2000); // slave server-id + Protocol_chunk prot_server_id(1); // slave server-id /* * See document at http://dev.mysql.com/doc/internals/en/replication-protocol.html */ From 0a1f3c5f721f2ee14fe03abd7b2e67c5eee58467 Mon Sep 17 00:00:00 2001 From: Gu Weigang Date: Fri, 30 Aug 2013 15:10:06 +0800 Subject: [PATCH 26/69] update formats and something else --- include/binlog_api.h | 23 +++--- include/binlog_driver.h | 2 +- include/binlog_event.h | 33 ++++---- include/value.h | 12 +-- src/binary_log.cpp | 14 ++-- src/binlog_driver.cpp | 95 +++++++++++---------- src/binlog_event.cpp | 124 ++++++++++++++-------------- src/resultset_iterator.cpp | 2 +- src/tcp_driver.cpp | 74 ++++++++--------- src/value.cpp | 164 ++++++++++++++++++++++++------------- 10 files changed, 290 insertions(+), 253 deletions(-) diff --git a/include/binlog_api.h b/include/binlog_api.h index c49dee9..68877fd 100644 --- a/include/binlog_api.h +++ b/include/binlog_api.h @@ -49,12 +49,12 @@ enum Error_code { class Dummy_driver : public system::Binary_log_driver { -public: + public: Dummy_driver() : Binary_log_driver("", 0) {} virtual ~Dummy_driver() {} virtual int connect() { return 1; } - + virtual int wait_for_next_event(mysql::Binary_log_event **event) { return ERR_EOF; } @@ -73,16 +73,16 @@ class Content_handler; typedef std::list Content_handler_pipeline; class Binary_log { -private: + private: system::Binary_log_driver *m_driver; Dummy_driver m_dummy_driver; Content_handler_pipeline m_content_handlers; unsigned long m_binlog_position; std::string m_binlog_file; -public: + public: Binary_log(system::Binary_log_driver *drv); ~Binary_log() {} - + int connect(); /** @@ -90,7 +90,6 @@ class Binary_log { */ int wait_for_next_event(Binary_log_event **event); - /** * Inserts/removes content handlers in and out of the chain * The Content_handler_pipeline is a derived std::list @@ -101,9 +100,9 @@ class Binary_log { * Set the binlog position (filename, position) * * @return Error_code - * @retval ERR_OK The position is updated. - * @retval ERR_EOF The position is out-of-range - * @retval >= ERR_CODE_COUNT An unspecified error occurred + * @retval ERR_OK The position is updated. + * @retval ERR_EOF The position is out-of-range + * @retval >= ERR_CODE_COUNT An unspecified error occurred */ int set_position(const std::string &filename, unsigned long position); @@ -112,9 +111,9 @@ class Binary_log { * @param position Requested position * * @return Error_code - * @retval ERR_OK The position is updated. - * @retval ERR_EOF The position is out-of-range - * @retval >= ERR_CODE_COUNT An unspecified error occurred + * @retval ERR_OK The position is updated. + * @retval ERR_EOF The position is out-of-range + * @retval >= ERR_CODE_COUNT An unspecified error occurred */ int set_position(unsigned long position); diff --git a/include/binlog_driver.h b/include/binlog_driver.h index 37774e9..75f47a1 100644 --- a/include/binlog_driver.h +++ b/include/binlog_driver.h @@ -31,7 +31,7 @@ class Binary_log_driver { public: template - Binary_log_driver(const FilenameT& filename = FilenameT(), unsigned int offset = 0) + Binary_log_driver(const FilenameT& filename = FilenameT(), unsigned int offset = 0) : m_binlog_file_name(filename), m_binlog_offset(offset) { } diff --git a/include/binlog_event.h b/include/binlog_event.h index 0ed976a..1578fee 100644 --- a/include/binlog_event.h +++ b/include/binlog_event.h @@ -81,31 +81,32 @@ enum Log_event_type DELETE_ROWS_EVENT = 25, /* - Something out of the ordinary happened on the master + * Something out of the ordinary happened on the master */ INCIDENT_EVENT= 26, - /* - * A user defined event - */ - USER_DEFINED= 27, + /* + * A user defined event + */ + USER_DEFINED= 27, + /* Add new events here - right above this comment! Existing events (except ENUM_END_EVENT) should never change their numbers */ - ENUM_END_EVENT /* end marker */ }; namespace system { -/** - * Convenience function to get the string representation of a binlog event. - */ -const char* get_event_type_str(Log_event_type type); + /** + * Convenience function to get the string representation of a binlog event. + */ + const char* get_event_type_str(Log_event_type type); } // end namespace system #define LOG_EVENT_HEADER_SIZE 20 + class Log_event_header { public: @@ -129,16 +130,16 @@ class Binary_log_event public: Binary_log_event() { - /* - An event length of 0 indicates that the header isn't initialized - */ - m_header.event_length= 0; - m_header.type_code= 0; + /* + An event length of 0 indicates that the header isn't initialized + */ + m_header.event_length = 0; + m_header.type_code = 0; } Binary_log_event(Log_event_header *header) { - m_header= *header; + m_header= *header; } virtual ~Binary_log_event(); diff --git a/include/value.h b/include/value.h index 7cb3ac6..f1fc377 100644 --- a/include/value.h +++ b/include/value.h @@ -40,8 +40,8 @@ namespace mysql { @return The size in bytes of a particular field */ -int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, - uint16_t metadata); +uint32_t calc_field_size(unsigned char column_type, const unsigned char *field_ptr, + uint32_t metadata); uint8_t calc_newdecimal_size(uint8_t m, uint8_t d); @@ -54,12 +54,12 @@ uint8_t calc_newdecimal_size(uint8_t m, uint8_t d); class Value { public: - Value(enum system::enum_field_types type, uint16_t metadata, const char *storage) : + Value(enum system::enum_field_types type, uint32_t metadata, const char *storage) : m_type(type), m_storage(storage), m_metadata(metadata), m_is_null(false) { - m_size = calc_field_size((unsigned char)type, - (const unsigned char*)storage, - metadata); + m_size = calc_field_size((unsigned char) type, + (const unsigned char*) storage, + metadata); // metadata: 16bits, lower byte is real type, high byte is length switch(type) { case mysql::system::MYSQL_TYPE_SET: diff --git a/src/binary_log.cpp b/src/binary_log.cpp index 47b540a..80d68e5 100644 --- a/src/binary_log.cpp +++ b/src/binary_log.cpp @@ -32,9 +32,9 @@ Binary_log::Binary_log(Binary_log_driver *drv) : m_binlog_position(4), m_binlog_ if (drv == NULL) { m_driver= &m_dummy_driver; + } else { + m_driver= drv; } - else - m_driver= drv; } Content_handler_pipeline *Binary_log::content_handler_pipeline(void) @@ -56,12 +56,11 @@ int Binary_log::wait_for_next_event(mysql::Binary_log_event **event_ptr) { event= reinjection_queue.front(); reinjection_queue.pop_front(); - } - else - { + } else { // Return in case of non-ERR_OK. - if(rc= m_driver->wait_for_next_event(&event)) + if(rc= m_driver->wait_for_next_event(&event)) { return rc; + } } m_binlog_position= event->header()->next_position; mysql::Content_handler *handler; @@ -79,8 +78,7 @@ int Binary_log::wait_for_next_event(mysql::Binary_log_event **event_ptr) } } while(event == 0 || !reinjection_queue.empty()); - if (event_ptr) - *event_ptr= event; + if (event_ptr) *event_ptr= event; return 0; } diff --git a/src/binlog_driver.cpp b/src/binlog_driver.cpp index 1495d0f..9f00efa 100644 --- a/src/binlog_driver.cpp +++ b/src/binlog_driver.cpp @@ -20,56 +20,55 @@ #include "binlog_driver.h" -namespace mysql { namespace system { +namespace mysql { -/* -Binary_log_event* Binary_log_driver::parse_event(asio::streambuf - &sbuff, Log_event_header - *header) - */ -Binary_log_event* Binary_log_driver::parse_event(std::istream &is, - Log_event_header *header) -{ - Binary_log_event *parsed_event= 0; + namespace system { - switch (header->type_code) { - case TABLE_MAP_EVENT: - parsed_event= proto_table_map_event(is, header); - break; - case QUERY_EVENT: - parsed_event= proto_query_event(is, header); - break; - case INCIDENT_EVENT: - parsed_event= proto_incident_event(is, header); - break; - case WRITE_ROWS_EVENT: - case UPDATE_ROWS_EVENT: - case DELETE_ROWS_EVENT: - parsed_event= proto_rows_event(is, header); - break; - case ROTATE_EVENT: - { - Rotate_event *rot= proto_rotate_event(is, header); - m_binlog_file_name= rot->binlog_file; - m_binlog_offset= (unsigned long)rot->binlog_pos; - parsed_event= rot; - } - break; - case INTVAR_EVENT: - parsed_event= proto_intvar_event(is, header); - break; - case USER_VAR_EVENT: - parsed_event= proto_uservar_event(is, header); - break; - default: - { - // Create a dummy driver. - parsed_event= new Binary_log_event(header); - } - } + /* Binary_log_event* Binary_log_driver::parse_event(asio::streambuf &sbuff, Log_event_header *header) */ - return parsed_event; -} + Binary_log_event* Binary_log_driver::parse_event(std::istream &is, Log_event_header *header) + { + Binary_log_event *parsed_event= 0; -} + switch (header->type_code) { + case TABLE_MAP_EVENT: + parsed_event= proto_table_map_event(is, header); + break; + case QUERY_EVENT: + parsed_event= proto_query_event(is, header); + break; + case INCIDENT_EVENT: + parsed_event= proto_incident_event(is, header); + break; + case WRITE_ROWS_EVENT: + case UPDATE_ROWS_EVENT: + case DELETE_ROWS_EVENT: + parsed_event= proto_rows_event(is, header); + break; + case ROTATE_EVENT: + { + Rotate_event *rot= proto_rotate_event(is, header); + m_binlog_file_name= rot->binlog_file; + m_binlog_offset= (unsigned long)rot->binlog_pos; + parsed_event= rot; + } + break; + case INTVAR_EVENT: + parsed_event= proto_intvar_event(is, header); + break; + case USER_VAR_EVENT: + parsed_event= proto_uservar_event(is, header); + break; + default: + { + // Create a dummy driver. + parsed_event= new Binary_log_event(header); + } + } + + return parsed_event; + } + + } + } diff --git a/src/binlog_event.cpp b/src/binlog_event.cpp index c2f52c6..67d26aa 100644 --- a/src/binlog_event.cpp +++ b/src/binlog_event.cpp @@ -1,21 +1,21 @@ /* -Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights -reserved. + Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights + reserved. -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; version 2 of -the License. + 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; version 2 of + the License. -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. + 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., 51 Franklin St, Fifth Floor, Boston, MA -02110-1301 USA + 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., 51 Franklin St, Fifth Floor, Boston, MA + 02110-1301 USA */ #include "binlog_event.h" @@ -25,59 +25,59 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA namespace mysql { -namespace system { + namespace system { -const char *get_event_type_str(Log_event_type type) -{ - switch(type) { - case START_EVENT_V3: return "Start_v3"; - case STOP_EVENT: return "Stop"; - case QUERY_EVENT: return "Query"; - case ROTATE_EVENT: return "Rotate"; - case INTVAR_EVENT: return "Intvar"; - case LOAD_EVENT: return "Load"; - case NEW_LOAD_EVENT: return "New_load"; - case SLAVE_EVENT: return "Slave"; - case CREATE_FILE_EVENT: return "Create_file"; - case APPEND_BLOCK_EVENT: return "Append_block"; - case DELETE_FILE_EVENT: return "Delete_file"; - case EXEC_LOAD_EVENT: return "Exec_load"; - case RAND_EVENT: return "RAND"; - case XID_EVENT: return "Xid"; - case USER_VAR_EVENT: return "User var"; - case FORMAT_DESCRIPTION_EVENT: return "Format_desc"; - case TABLE_MAP_EVENT: return "Table_map"; - case PRE_GA_WRITE_ROWS_EVENT: return "Write_rows_event_old"; - case PRE_GA_UPDATE_ROWS_EVENT: return "Update_rows_event_old"; - case PRE_GA_DELETE_ROWS_EVENT: return "Delete_rows_event_old"; - case WRITE_ROWS_EVENT: return "Write_rows"; - case UPDATE_ROWS_EVENT: return "Update_rows"; - case DELETE_ROWS_EVENT: return "Delete_rows"; - case BEGIN_LOAD_QUERY_EVENT: return "Begin_load_query"; - case EXECUTE_LOAD_QUERY_EVENT: return "Execute_load_query"; - case INCIDENT_EVENT: return "Incident"; - case USER_DEFINED: return "User defined"; - default: return "Unknown"; - } -} + const char *get_event_type_str(Log_event_type type) + { + switch(type) { + case START_EVENT_V3: return "Start_v3"; + case STOP_EVENT: return "Stop"; + case QUERY_EVENT: return "Query"; + case ROTATE_EVENT: return "Rotate"; + case INTVAR_EVENT: return "Intvar"; + case LOAD_EVENT: return "Load"; + case NEW_LOAD_EVENT: return "New_load"; + case SLAVE_EVENT: return "Slave"; + case CREATE_FILE_EVENT: return "Create_file"; + case APPEND_BLOCK_EVENT: return "Append_block"; + case DELETE_FILE_EVENT: return "Delete_file"; + case EXEC_LOAD_EVENT: return "Exec_load"; + case RAND_EVENT: return "RAND"; + case XID_EVENT: return "Xid"; + case USER_VAR_EVENT: return "User var"; + case FORMAT_DESCRIPTION_EVENT: return "Format_desc"; + case TABLE_MAP_EVENT: return "Table_map"; + case PRE_GA_WRITE_ROWS_EVENT: return "Write_rows_event_old"; + case PRE_GA_UPDATE_ROWS_EVENT: return "Update_rows_event_old"; + case PRE_GA_DELETE_ROWS_EVENT: return "Delete_rows_event_old"; + case WRITE_ROWS_EVENT: return "Write_rows"; + case UPDATE_ROWS_EVENT: return "Update_rows"; + case DELETE_ROWS_EVENT: return "Delete_rows"; + case BEGIN_LOAD_QUERY_EVENT: return "Begin_load_query"; + case EXECUTE_LOAD_QUERY_EVENT: return "Execute_load_query"; + case INCIDENT_EVENT: return "Incident"; + case USER_DEFINED: return "User defined"; + default: return "Unknown"; + } + } -} // end namespace system + } // end namespace system -Binary_log_event::~Binary_log_event() -{ -} + Binary_log_event::~Binary_log_event() + { + } -Binary_log_event * create_incident_event(unsigned int type, const char *message, unsigned long pos) -{ - Incident_event *incident= new Incident_event(); - incident->header()->type_code= INCIDENT_EVENT; - incident->header()->next_position= pos; - incident->header()->event_length= LOG_EVENT_HEADER_SIZE + 2 + strlen(message); - incident->type= type; - incident->message.append(message); - return incident; -} + Binary_log_event * create_incident_event(unsigned int type, const char *message, unsigned long pos) + { + Incident_event *incident= new Incident_event(); + incident->header()->type_code= INCIDENT_EVENT; + incident->header()->next_position= pos; + incident->header()->event_length= LOG_EVENT_HEADER_SIZE + 2 + strlen(message); + incident->type= type; + incident->message.append(message); + return incident; + } } // end namespace mysql diff --git a/src/resultset_iterator.cpp b/src/resultset_iterator.cpp index 169e3d7..96a6d5b 100644 --- a/src/resultset_iterator.cpp +++ b/src/resultset_iterator.cpp @@ -110,7 +110,7 @@ void digest_result_header(std::istream &is, uint64_t &field_count, uint64_t extr //proto_extra.set_length_encoded_binary(true); is >> proto_field_count; - //>> proto_extra; + //>> proto_extra; } void digest_field_packet(std::istream &is, Field_packet &field_packet) diff --git a/src/tcp_driver.cpp b/src/tcp_driver.cpp index 0b176ed..1ccd83c 100644 --- a/src/tcp_driver.cpp +++ b/src/tcp_driver.cpp @@ -73,13 +73,11 @@ static int hash_sha1(uint8_t *output, ...); { if (fetch_master_status(m_socket, &m_binlog_file_name, &m_binlog_offset)) return 1; - } else - { - m_binlog_file_name=binlog_filename; - m_binlog_offset=offset; + } else { + m_binlog_file_name = binlog_filename; + m_binlog_offset = offset; } - /* We're ready to start the io service and request the binlog dump. */ start_binlog_dump(m_binlog_file_name, m_binlog_offset); @@ -94,31 +92,29 @@ tcp::socket *sync_connect_and_authenticate(asio::io_service &io_service, const s asio::error_code error = asio::error::host_not_found; - if (port == 0) - port= 3306; + if (port == 0) port = 3306; tcp::socket *socket=new tcp::socket(io_service); /* Try each endpoint until we successfully establish a connection. */ try { - tcp::resolver::iterator endpoint_iterator=resolver.resolve(query); - tcp::resolver::iterator end; - - while (error && endpoint_iterator != end) - { - /* - Hack to set port number from a long int instead of a service. - */ - tcp::endpoint endpoint=endpoint_iterator->endpoint(); - endpoint.port(port); + tcp::resolver::iterator endpoint_iterator=resolver.resolve(query); + tcp::resolver::iterator end; - socket->close(); - socket->connect(endpoint, error); - endpoint_iterator++; - } - } catch(...) - { + while (error && endpoint_iterator != end) + { + /* + Hack to set port number from a long int instead of a service. + */ + tcp::endpoint endpoint=endpoint_iterator->endpoint(); + endpoint.port(port); + + socket->close(); + socket->connect(endpoint, error); + endpoint_iterator++; + } + } catch(...) { return 0; } @@ -153,8 +149,7 @@ tcp::socket *sync_connect_and_authenticate(asio::io_service &io_service, const s * Get server handshake package */ std::streamsize inbuffer=server_messages.in_avail(); - if (inbuffer < 0) - inbuffer=0; + if (inbuffer < 0) inbuffer=0; asio::read(*socket, server_messages, asio::transfer_at_least(packet_length - inbuffer)); std::istream server_stream(&server_messages); @@ -162,8 +157,7 @@ tcp::socket *sync_connect_and_authenticate(asio::io_service &io_service, const s proto_get_handshake_package(server_stream, handshake_package, packet_length); - if (authenticate(socket, user, passwd, handshake_package)) - return 0; + if (authenticate(socket, user, passwd, handshake_package)) return 0; /* * Register slave to master @@ -202,12 +196,11 @@ tcp::socket *sync_connect_and_authenticate(asio::io_service &io_service, const s // Send the request. asio::write(*socket, - asio::buffer(command_packet_header, 4), - asio::transfer_at_least(4)); + asio::buffer(command_packet_header, 4), + asio::transfer_at_least(4)); asio::write(*socket, server_messages, - asio::transfer_at_least(size)); - } catch( asio::error_code e) - { + asio::transfer_at_least(size)); + } catch( asio::error_code e) { return 0; } @@ -225,8 +218,7 @@ tcp::socket *sync_connect_and_authenticate(asio::io_service &io_service, const s { struct st_ok_package ok_package; prot_parse_ok_message(cmd_response_stream, ok_package, packet_length); - } else - { + } else { struct st_error_package error_package; prot_parse_error_message(cmd_response_stream, error_package, packet_length); return 0; @@ -284,8 +276,7 @@ void Binlog_tcp_driver::start_binlog_dump(const std::string &binlog_file_name, s m_event_loop = (pthread_t *)malloc(sizeof(pthread_t)); pthread_attr_t attr; pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, - PTHREAD_CREATE_JOINABLE); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); pthread_create(m_event_loop, &attr, &Binlog_tcp_driver::start, (void *)this->thread_data); } } @@ -350,13 +341,13 @@ void Binlog_tcp_driver::handle_net_packet(const asio::error_code& err, std::size hasn't been parsed. If the event stream also contains enough bytes we make the assumption that the next bytes waiting in the stream is the event header and attempt to parse it. - */ + */ if (m_waiting_event->event_length == 0 && m_event_stream_buffer.size() >= 19) { /* Copy and remove from the event stream, the remaining bytes might be dynamic payload. - */ + */ //std::cerr << "Consuming event stream for header. Size before: " << m_event_stream_buffer.size() << std::endl; proto_event_packet_header(m_event_stream_buffer, m_waiting_event); //std::cerr << " Size after: " << m_event_stream_buffer.size() << std::endl; @@ -438,8 +429,8 @@ void Binlog_tcp_driver::handle_net_packet_header(const asio::error_code& err, st read_handler.method = &Binlog_tcp_driver::handle_net_packet; read_handler.tcp_driver = this; asio::async_read(*m_socket, - asio::buffer(m_event_packet, packet_length), - read_handler); + asio::buffer(m_event_packet, packet_length), + read_handler); } int authenticate(tcp::socket *socket, const std::string& user, const std::string& passwd, @@ -537,8 +528,7 @@ int Binlog_tcp_driver::wait_for_next_event(mysql::Binary_log_event **event_ptr) { // poll for new event until one event is found. // return the event - if (event_ptr) - *event_ptr = 0; + if (event_ptr) *event_ptr = 0; m_event_queue->pop_back(event_ptr); return 0; } diff --git a/src/value.cpp b/src/value.cpp index e6c5231..99d3c91 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -45,17 +45,30 @@ static uint8_t calc_digits_size(uint8_t digits) } else if (digits >= 1 && digits <= 2) { size += 1; } - return size; } uint8_t calc_newdecimal_size(uint8_t m, uint8_t d) { - // (m - d) is left digits - return calc_digits_size(m-d) + calc_digits_size(d); + // unsigned char digits_per_bytes[] = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 4 }; + // uint8_t i_digits = m - d; + // uint8_t f_digits = d; + // uint8_t decimal_full_blocks = i_digits / 9; + // uint8_t decimal_last_block_digits = i_digits % 9; + // uint8_t scale_full_blocks = f_digits / 9; + // uint8_t scale_last_block_digits = f_digits % 9; + // uint8_t size = 0; + + // size += decimal_full_blocks * digits_per_bytes[9] + digits_per_bytes[decimal_last_block_digits]; + // size += scale_full_blocks * digits_per_bytes[9] + digits_per_bytes[scale_last_block_digits]; + + // (m - d) is left digits + + return calc_digits_size(m-d) + calc_digits_size(d); + } -int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, uint16_t metadata) +uint32_t calc_field_size(unsigned char column_type, const unsigned char *field_ptr, uint32_t metadata) { uint32_t length; @@ -68,6 +81,7 @@ int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, u // higher byte is number of digits to the right of the decimal point // lower byte is the maximum number of digits length = calc_newdecimal_size(metadata & 0xff, metadata >> 8); + // length = 0; break; case mysql::system::MYSQL_TYPE_DECIMAL: case mysql::system::MYSQL_TYPE_FLOAT: @@ -83,9 +97,9 @@ int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, u case mysql::system::MYSQL_TYPE_ENUM: case mysql::system::MYSQL_TYPE_STRING: { - unsigned char type = (metadata & 0x00ff); + unsigned char type = metadata >> 8U; if ((type == mysql::system::MYSQL_TYPE_SET) || (type == mysql::system::MYSQL_TYPE_ENUM)) { - length = (metadata >> 8U); + length = metadata & 0x00ff; } else { /* We are reading the actual size from the master_data record @@ -133,14 +147,14 @@ int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, u { /* Decode the size of the bit field from the master. - from_len is the length in bytes from the master - from_bit_len is the number of extra bits stored in the master record + from_len is the length in bytes from the master + from_bit_len is the number of extra bits stored in the master record If from_bit_len is not 0, add 1 to the length to account for accurate number of bytes needed. */ - uint16_t from_len= (metadata >> 8U) & 0x00ff; - uint16_t from_bit_len= metadata & 0x00ff; - //DBUG_ASSERT(from_bit_len <= 7); + uint32_t from_len= (metadata >> 8U) & 0x00ff; + uint32_t from_bit_len= metadata & 0x00ff; + // DBUG_ASSERT(from_bit_len <= 7); length= from_len + ((from_bit_len > 0) ? 1 : 0); break; } @@ -148,7 +162,7 @@ int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, u { length = metadata > 255 ? 2 : 1; - length += length == 1 ? *((uint8_t *)field_ptr) : *((uint16_t *)field_ptr); + length += length == 1 ? (uint32_t) *field_ptr : *((uint16_t *)field_ptr); break; } @@ -158,7 +172,7 @@ int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, u case mysql::system::MYSQL_TYPE_BLOB: case mysql::system::MYSQL_TYPE_GEOMETRY: { - switch (metadata) + switch (metadata) { case 1: length= 1+ (uint32_t) field_ptr[0]; @@ -359,57 +373,89 @@ void Converter::to(std::string &str, const Value &val) const } std::ostringstream os; + switch(val.type()) { case MYSQL_TYPE_DECIMAL: + { str = "not implemented"; - return; + str = os.str(); + break; + } case MYSQL_TYPE_TINY: + { os << static_cast(val.as_int8()); + str = os.str(); break; + } case MYSQL_TYPE_SHORT: + { os << val.as_int16(); + str = os.str(); break; + } case MYSQL_TYPE_LONG: + { os << val.as_int32(); + str = os.str(); break; + } case MYSQL_TYPE_FLOAT: + { os << val.as_float(); + str = os.str(); break; + } case MYSQL_TYPE_DOUBLE: + { os << val.as_double(); + str = os.str(); break; + } case MYSQL_TYPE_NULL: + { str = "not implemented"; - return; + str = os.str(); + break; + } case MYSQL_TYPE_TIMESTAMP: + { os << (uint32_t)val.as_int32(); + str = os.str(); break; + } case MYSQL_TYPE_LONGLONG: + { os << val.as_int64(); + str = os.str(); break; + } case MYSQL_TYPE_INT24: + { str = "not implemented"; - return; + str = os.str(); + break; + } case MYSQL_TYPE_DATE: - { + { const char *storage = val.storage(); uint32_t date = (storage[0] & 0xff) + ((storage[1] & 0xff) << 8) + ((storage[2] & 0xff) << 16); // actually date occupies 3 bytes, so below will work - uint16_t year = date >> 9; + uint32_t year = date >> 9; date -= (year << 9); - uint16_t month = date >> 5; + uint32_t month = date >> 5; date -= (month << 5); - uint16_t day = date; + uint32_t day = date; os << std::setfill('0') << std::setw(4) << year << std::setw(1) << '-' << std::setw(2) << month << std::setw(1) << '-' << std::setw(2) << day; + str = os.str(); break; - } + } case MYSQL_TYPE_DATETIME: - { + { uint64_t timestamp= val.as_int64(); unsigned long d= timestamp / 1000000; unsigned long t= timestamp % 1000000; @@ -425,57 +471,60 @@ void Converter::to(std::string &str, const Value &val) const << std::setw(2) << (t % 10000) / 100 << std::setw(1) << ':' << std::setw(2) << t % 100; - } + str = os.str(); break; + } case MYSQL_TYPE_TIME: { const char *storage = val.storage(); uint32_t time = (storage[0] & 0xff) + ((storage[1] & 0xff) << 8) + ((storage[2] & 0xff) << 16); - uint16_t sec = time % 100; + uint32_t sec = time % 100; time -= sec; - uint16_t min = (time % 10000) / 100; - uint16_t hour = (time - min) / 10000; + uint32_t min = (time % 10000) / 100; + uint32_t hour = (time - min) / 10000; os << std::setfill('0') << std::setw(2) << hour << std::setw(1) << ':' << std::setw(2) << min << std::setw(1) << ':' << std::setw(2) << sec; + str = os.str(); break; - } + } case MYSQL_TYPE_YEAR: - { + { const char *storage = val.storage(); - uint16_t year = (storage[0] & 0xff); + uint32_t year = (storage[0] & 0xff); if (year > 0) { year += 1900; } os << std::setfill('0') << std::setw(4) << year; + str = os.str(); break; - } + } case MYSQL_TYPE_NEWDATE: + { str = "not implemented"; - return; + break; + } case MYSQL_TYPE_VARCHAR: { unsigned long size; - char *ptr= val.as_c_str(size); - - str.assign(ptr, size); + str.append(ptr, size); + break; } - return; case MYSQL_TYPE_VAR_STRING: { - str.assign(val.storage(), val.length()); + str.append(val.storage(), val.length()); + break; } - return; case MYSQL_TYPE_STRING: { unsigned long size; char *ptr = val.as_c_str(size); - str.assign(ptr, size); + str.append(ptr, size); + break; } - return; case MYSQL_TYPE_BIT: case MYSQL_TYPE_NEWDECIMAL: { @@ -486,13 +535,16 @@ void Converter::to(std::string &str, const Value &val) const decimal.len = sizeof(buffer)/sizeof(decimal_digit_t); bin2decimal((const u_char *)val.storage(), &decimal, val.metadata() & 0xff, val.metadata() >> 8); decimal2string(&decimal, result, &len, 0, 0, 0); - str.assign(result, len); + str.append(result, len); + break; } - return; case MYSQL_TYPE_ENUM: case MYSQL_TYPE_SET: + { os << (val.length() == 1 ? static_cast(val.as_int8()) : val.as_int16()); + str = os.str(); break; + } case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: @@ -500,30 +552,28 @@ void Converter::to(std::string &str, const Value &val) const { unsigned long size; unsigned char *ptr= val.as_blob(size); - str.assign((const char *)ptr, size); + str.append((const char *)ptr, size); + break; } - return; case MYSQL_TYPE_GEOMETRY: default: str = "not implemented"; - return; + break; } - str = os.str(); } void Converter::to(float &out, const Value &val) const { switch(val.type()) { - case MYSQL_TYPE_FLOAT: - out= val.as_float(); - break; - default: - out= 0; + case MYSQL_TYPE_FLOAT: + out= val.as_float(); + break; + default: + out= 0; } } - void Converter::to(long long &out, const Value &val) const { switch(val.type()) @@ -584,8 +634,8 @@ void Converter::to(long long &out, const Value &val) const out= 0; break; case MYSQL_TYPE_ENUM: - case MYSQL_TYPE_SET: - out = (val.length() == 1 ? static_cast(val.as_int8()) : val.as_int16()); + case MYSQL_TYPE_SET: + out = (val.length() == 1 ? static_cast(val.as_int8()) : val.as_int16()); break; case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: @@ -595,10 +645,10 @@ void Converter::to(long long &out, const Value &val) const break; case MYSQL_TYPE_VAR_STRING: { - std::string str; - str.append(val.storage(), val.length()); - std::istringstream is(str); - is >> out; + std::string str; + str.append(val.storage(), val.length()); + std::istringstream is(str); + is >> out; } break; case MYSQL_TYPE_STRING: From b3a2c73c401b65528b1d9e841f2c6d888c82271c Mon Sep 17 00:00:00 2001 From: ideal Date: Mon, 2 Sep 2013 20:24:50 +0800 Subject: [PATCH 27/69] fix bug in computing size of field char --- include/field_iterator.h | 4 ++-- include/value.h | 3 +-- src/field_iterator.cpp | 8 +++----- src/value.cpp | 25 +++++++++++++++---------- 4 files changed, 21 insertions(+), 19 deletions(-) diff --git a/include/field_iterator.h b/include/field_iterator.h index 456ec21..0554bed 100644 --- a/include/field_iterator.h +++ b/include/field_iterator.h @@ -87,8 +87,8 @@ size_t Row_event_iterator::fields(Iterator_value_type& fiel for(unsigned col_no=0; col_no < m_table_map->columns.size(); ++col_no) { ++row_field_col_index; - unsigned int type= m_table_map->columns[col_no]&0xFF; - uint16_t metadata= extract_metadata(m_table_map, col_no); + unsigned int type = m_table_map->columns[col_no]&0xFF; + uint16_t metadata = extract_metadata(m_table_map, col_no); mysql::Value val((enum mysql::system::enum_field_types)type, metadata, (const char *)&m_row_event->row[field_offset]); diff --git a/include/value.h b/include/value.h index 7cb3ac6..68b6d9e 100644 --- a/include/value.h +++ b/include/value.h @@ -64,9 +64,8 @@ class Value switch(type) { case mysql::system::MYSQL_TYPE_SET: case mysql::system::MYSQL_TYPE_ENUM: - case mysql::system::MYSQL_TYPE_STRING: { - m_type = (enum system::enum_field_types)(metadata & 0x00ff); + m_type = (enum system::enum_field_types)(metadata & 0xff); m_metadata = (metadata >> 8U); break; } diff --git a/src/field_iterator.cpp b/src/field_iterator.cpp index b65e9a0..6f4dba7 100644 --- a/src/field_iterator.cpp +++ b/src/field_iterator.cpp @@ -49,14 +49,12 @@ uint16_t extract_metadata(const Table_map_event *map, int col_no) switch(lookup_metadata_field_size((enum mysql::system::enum_field_types)type)) { case 1: - metadata = (unsigned char)map->metadata[offset]; + metadata = (unsigned char)map->metadata[offset]; break; case 2: { - unsigned int tmp= ((unsigned char)map->metadata[offset])&0xFF; - metadata= static_cast(tmp); - tmp= (((unsigned char)map->metadata[offset+1])&0xFF) << 8; - metadata+= static_cast(tmp); + metadata = ((unsigned char)map->metadata[offset]) & 0xFF; + metadata += ((((unsigned char)map->metadata[offset+1]) & 0xFF) << 8); } break; } diff --git a/src/value.cpp b/src/value.cpp index e6c5231..187c074 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -81,19 +81,24 @@ int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, u */ case mysql::system::MYSQL_TYPE_SET: case mysql::system::MYSQL_TYPE_ENUM: + { + unsigned char type = (metadata & 0xff); + length = (metadata >> 8U); + break; + } case mysql::system::MYSQL_TYPE_STRING: { - unsigned char type = (metadata & 0x00ff); - if ((type == mysql::system::MYSQL_TYPE_SET) || (type == mysql::system::MYSQL_TYPE_ENUM)) { - length = (metadata >> 8U); + /* + We are reading the actual size from the master_data record + because this field has the actual lengh stored in the first + byte. + */ + uint8_t lower = metadata & 0xFF; + uint8_t higher = metadata >> 8U; + if ((lower & 0x30) != 0x30) { + length = (((lower & 0x30) ^ 0x30) << 4) + higher; } else { - /* - We are reading the actual size from the master_data record - because this field has the actual lengh stored in the first - byte. - */ - length= (unsigned int) *field_ptr+1; - //DBUG_ASSERT(length != 0); + length = higher; } break; } From 838a214d250c025d16ef7ade9cdac2ccc15e32b3 Mon Sep 17 00:00:00 2001 From: Gu Weigang Date: Tue, 3 Sep 2013 13:03:53 +0800 Subject: [PATCH 28/69] fix mysql_type_char --- include/value.h | 22 +++++++++++++--------- src/value.cpp | 27 +++++++++++++++++---------- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/include/value.h b/include/value.h index f1fc377..1bdb36a 100644 --- a/include/value.h +++ b/include/value.h @@ -62,16 +62,20 @@ class Value metadata); // metadata: 16bits, lower byte is real type, high byte is length switch(type) { - case mysql::system::MYSQL_TYPE_SET: - case mysql::system::MYSQL_TYPE_ENUM: - case mysql::system::MYSQL_TYPE_STRING: - { - m_type = (enum system::enum_field_types)(metadata & 0x00ff); - m_metadata = (metadata >> 8U); - break; - } + case mysql::system::MYSQL_TYPE_SET: + case mysql::system::MYSQL_TYPE_ENUM: + { + m_type = (enum system::enum_field_types)(metadata & 0x00ff); + m_metadata = (metadata >> 8U); + break; + } + case mysql::system::MYSQL_TYPE_STRING: + { + m_type = (enum system::enum_field_types)(metadata & 0x00ff | 0x30); + break; + } } - //std::cout << "TYPE: " << type << " SIZE: " << m_size << std::endl; + // std::cout << "TYPE: " << type << " SIZE: " << m_size << std::endl; }; Value() diff --git a/src/value.cpp b/src/value.cpp index 99d3c91..3bd3f1b 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -95,22 +95,27 @@ uint32_t calc_field_size(unsigned char column_type, const unsigned char *field_p */ case mysql::system::MYSQL_TYPE_SET: case mysql::system::MYSQL_TYPE_ENUM: - case mysql::system::MYSQL_TYPE_STRING: { unsigned char type = metadata >> 8U; if ((type == mysql::system::MYSQL_TYPE_SET) || (type == mysql::system::MYSQL_TYPE_ENUM)) { length = metadata & 0x00ff; - } else { - /* - We are reading the actual size from the master_data record - because this field has the actual lengh stored in the first - byte. - */ - length= (unsigned int) *field_ptr+1; - //DBUG_ASSERT(length != 0); } break; } + + // case mysql::system::MYSQL_TYPE_STRING: + // { + // /* + // We are reading the actual size from the master_data record + // because this field has the actual lengh stored in the first + // byte. + // */ + // length= (unsigned int) *field_ptr+1; + // break; + + // //DBUG_ASSERT(length != 0); + // } + case mysql::system::MYSQL_TYPE_YEAR: case mysql::system::MYSQL_TYPE_TINY: length = 1; @@ -158,6 +163,7 @@ uint32_t calc_field_size(unsigned char column_type, const unsigned char *field_p length= from_len + ((from_bit_len > 0) ? 1 : 0); break; } + case mysql::system::MYSQL_TYPE_STRING: case mysql::system::MYSQL_TYPE_VARCHAR: { length = metadata > 255 ? 2 : 1; @@ -373,7 +379,7 @@ void Converter::to(std::string &str, const Value &val) const } std::ostringstream os; - + switch(val.type()) { case MYSQL_TYPE_DECIMAL: @@ -523,6 +529,7 @@ void Converter::to(std::string &str, const Value &val) const unsigned long size; char *ptr = val.as_c_str(size); str.append(ptr, size); + // std::cout << str << std::endl; break; } case MYSQL_TYPE_BIT: From 193e675d5116c81b9197a9d3a9f20b5f1468ece2 Mon Sep 17 00:00:00 2001 From: Gu Weigang Date: Tue, 3 Sep 2013 13:19:12 +0800 Subject: [PATCH 29/69] revert mysql_type_set and mysql_type_enum --- src/value.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/value.cpp b/src/value.cpp index 3bd3f1b..6be3929 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -96,9 +96,9 @@ uint32_t calc_field_size(unsigned char column_type, const unsigned char *field_p case mysql::system::MYSQL_TYPE_SET: case mysql::system::MYSQL_TYPE_ENUM: { - unsigned char type = metadata >> 8U; + unsigned char type = (metadata & 0x00ff); if ((type == mysql::system::MYSQL_TYPE_SET) || (type == mysql::system::MYSQL_TYPE_ENUM)) { - length = metadata & 0x00ff; + length = (metadata >> 8U); } break; } From ae5d7f660e5a0d28d5d4385cab241716024d381d Mon Sep 17 00:00:00 2001 From: ideal Date: Tue, 3 Sep 2013 14:44:42 +0800 Subject: [PATCH 30/69] fix bug in char column --- include/field_iterator.h | 2 -- include/value.h | 23 +++++++++++------------ src/value.cpp | 35 +++++++++++++---------------------- 3 files changed, 24 insertions(+), 36 deletions(-) diff --git a/include/field_iterator.h b/include/field_iterator.h index 0554bed..32b9dee 100644 --- a/include/field_iterator.h +++ b/include/field_iterator.h @@ -71,8 +71,6 @@ class Row_event_iterator : public std::iterator size_t Row_event_iterator::fields(Iterator_value_type& fields_vector ) { diff --git a/include/value.h b/include/value.h index 68b6d9e..12956b9 100644 --- a/include/value.h +++ b/include/value.h @@ -40,7 +40,7 @@ namespace mysql { @return The size in bytes of a particular field */ -int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, +int calc_field_size(enum mysql::system::enum_field_types column_type, const unsigned char *field_ptr, uint16_t metadata); uint8_t calc_newdecimal_size(uint8_t m, uint8_t d); @@ -57,17 +57,16 @@ class Value Value(enum system::enum_field_types type, uint16_t metadata, const char *storage) : m_type(type), m_storage(storage), m_metadata(metadata), m_is_null(false) { - m_size = calc_field_size((unsigned char)type, + m_size = calc_field_size(type, (const unsigned char*)storage, metadata); // metadata: 16bits, lower byte is real type, high byte is length - switch(type) { - case mysql::system::MYSQL_TYPE_SET: - case mysql::system::MYSQL_TYPE_ENUM: - { - m_type = (enum system::enum_field_types)(metadata & 0xff); + if (type == mysql::system::MYSQL_TYPE_STRING) { + enum system::enum_field_types lower = (enum system::enum_field_types)(metadata & 0xFF); + if (lower == mysql::system::MYSQL_TYPE_SET + || lower == mysql::system::MYSQL_TYPE_ENUM) { + m_type = lower; m_metadata = (metadata >> 8U); - break; } } //std::cout << "TYPE: " << type << " SIZE: " << m_size << std::endl; @@ -75,10 +74,10 @@ class Value Value() { - m_size= 0; - m_storage= 0; - m_metadata= 0; - m_is_null= false; + m_size = 0; + m_storage = 0; + m_metadata = 0; + m_is_null = false; } /** diff --git a/src/value.cpp b/src/value.cpp index 187c074..0be4600 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -55,7 +55,7 @@ uint8_t calc_newdecimal_size(uint8_t m, uint8_t d) return calc_digits_size(m-d) + calc_digits_size(d); } -int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, uint16_t metadata) +int calc_field_size(enum mysql::system::enum_field_types column_type, const unsigned char *field_ptr, uint16_t metadata) { uint32_t length; @@ -78,28 +78,30 @@ int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, u The cases for SET and ENUM are include for completeness, however both are mapped to type MYSQL_TYPE_STRING and their real types are encoded in the field metadata. + + THIS WILL NEVER BE EXECUTED. */ case mysql::system::MYSQL_TYPE_SET: case mysql::system::MYSQL_TYPE_ENUM: { - unsigned char type = (metadata & 0xff); length = (metadata >> 8U); break; } case mysql::system::MYSQL_TYPE_STRING: { - /* - We are reading the actual size from the master_data record - because this field has the actual lengh stored in the first - byte. - */ - uint8_t lower = metadata & 0xFF; - uint8_t higher = metadata >> 8U; + uint32_t maxlen = 0; + uint8_t lower = metadata & 0xFF; + if (lower == mysql::system::MYSQL_TYPE_SET || lower == mysql::system::MYSQL_TYPE_ENUM) { + length = (metadata >> 8U); + break; + } + uint8_t higher = metadata >> 8U; if ((lower & 0x30) != 0x30) { - length = (((lower & 0x30) ^ 0x30) << 4) + higher; + maxlen = (((lower & 0x30) ^ 0x30) << 4) + higher; } else { - length = higher; + maxlen = higher; } + length = maxlen > 256 ? (uint16_t)(*field_ptr) + 2 : (uint8_t) (*field_ptr) + 1; break; } case mysql::system::MYSQL_TYPE_YEAR: @@ -191,17 +193,6 @@ int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, u return length; } -/* -Value::Value(Value &val) -{ - m_size= val.length(); - m_storage= val.storage(); - m_type= val.type(); - m_metadata= val.metadata(); - m_is_null= val.is_null(); -} -*/ - Value::Value(const Value& val) { m_size= val.m_size; From 8b548f74731927a0c12b69a4dbfc5cb41bc57e71 Mon Sep 17 00:00:00 2001 From: ideal Date: Wed, 4 Sep 2013 11:35:29 +0800 Subject: [PATCH 31/69] change format and change declaration of metadata to uint16_t --- include/value.h | 2 +- src/value.cpp | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/include/value.h b/include/value.h index bd2fb40..52930fe 100644 --- a/include/value.h +++ b/include/value.h @@ -54,7 +54,7 @@ uint8_t calc_newdecimal_size(uint8_t m, uint8_t d); class Value { public: - Value(enum system::enum_field_types type, uint32_t metadata, const char *storage) : + Value(enum system::enum_field_types type, uint16_t metadata, const char *storage) : m_type(type), m_storage(storage), m_metadata(metadata), m_is_null(false) { m_size = calc_field_size(type, diff --git a/src/value.cpp b/src/value.cpp index 597104b..acb02a3 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -159,10 +159,9 @@ int calc_field_size(enum mysql::system::enum_field_types column_type, const unsi If from_bit_len is not 0, add 1 to the length to account for accurate number of bytes needed. */ - uint32_t from_len= (metadata >> 8U) & 0x00ff; - uint32_t from_bit_len= metadata & 0x00ff; - // DBUG_ASSERT(from_bit_len <= 7); - length= from_len + ((from_bit_len > 0) ? 1 : 0); + uint8_t from_len = metadata >> 8U; + uint8_t from_bit_len = metadata & 0xff; + length = from_len + ((from_bit_len > 0) ? 1 : 0); break; } case mysql::system::MYSQL_TYPE_VARCHAR: @@ -452,9 +451,9 @@ void Converter::to(std::string &str, const Value &val) const } case MYSQL_TYPE_DATETIME: { - uint64_t timestamp= val.as_int64(); - unsigned long d= timestamp / 1000000; - unsigned long t= timestamp % 1000000; + uint64_t timestamp = val.as_int64(); + unsigned long d = timestamp / 1000000; + unsigned long t = timestamp % 1000000; os << std::setfill('0') << std::setw(4) << d / 10000 << std::setw(1) << '-' From 590da724a46b823a55c068ac016ed3e4ea9e7861 Mon Sep 17 00:00:00 2001 From: Gu Weigang Date: Fri, 6 Sep 2013 23:34:14 +0800 Subject: [PATCH 32/69] change as_c_str --- include/value.h | 2 +- src/value.cpp | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/include/value.h b/include/value.h index bd2fb40..2551167 100644 --- a/include/value.h +++ b/include/value.h @@ -164,7 +164,7 @@ class Converter { public: - void to(long long &out, const Value &val) const; + void to(long long &out, const Value &val) const; /** * Converts and copies the sql value to a std::string object. * @param[out] str The target string diff --git a/src/value.cpp b/src/value.cpp index 597104b..ab18acd 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -111,11 +111,12 @@ int calc_field_size(enum mysql::system::enum_field_types column_type, const unsi } uint8_t higher = metadata >> 8U; if ((lower & 0x30) != 0x30) { - maxlen = (((lower & 0x30) ^ 0x30) << 4) + higher; + maxlen = (((lower & 0x30) ^ 0x30) << 4) | higher; } else { maxlen = higher; } - length = maxlen > 256 ? (uint16_t)(*field_ptr) + 2 : (uint8_t) (*field_ptr) + 1; + length = maxlen >= 256 ? (uint16_t)(*field_ptr) + 2 : (uint8_t) (*field_ptr) + 1; + // std::cout << "Len: " << length << std::endl; break; } case mysql::system::MYSQL_TYPE_YEAR: @@ -241,21 +242,20 @@ bool Value::operator!=(const Value &val) const char *Value::as_c_str(unsigned long &size) const { - if (m_is_null || m_size == 0) - { + if (m_is_null || m_size == 0) { size = 0; return NULL; } if (m_size == 1) { - size = 0; - return const_cast(m_storage); + size = 0; + return const_cast(m_storage); } /* Length encoded; First byte is length of string. */ - int metadata_length = m_metadata > 255 ? 2 : 1; + int metadata_length = m_size > 251 ? 2 : 1; // std::cout << "m_size " << metadata_length << std::endl; @@ -264,6 +264,8 @@ char *Value::as_c_str(unsigned long &size) const */ size = m_size - metadata_length; + // std::cout << "Len: " << m_size << " Metadata: " << m_metadata << " Size: " << size << std::endl; + return const_cast(m_storage + metadata_length); } @@ -519,7 +521,6 @@ void Converter::to(std::string &str, const Value &val) const unsigned long size; char *ptr = val.as_c_str(size); str.append(ptr, size); - // std::cout << str << std::endl; break; } case MYSQL_TYPE_BIT: From ac43cae7d8eb14929e6829360fcfa30227f8d96d Mon Sep 17 00:00:00 2001 From: Gu Weigang Date: Sat, 7 Sep 2013 00:51:33 +0800 Subject: [PATCH 33/69] update for as_c_str --- src/value.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/value.cpp b/src/value.cpp index ab18acd..2efb4be 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -255,16 +255,28 @@ char *Value::as_c_str(unsigned long &size) const Length encoded; First byte is length of string. */ - int metadata_length = m_size > 251 ? 2 : 1; - - // std::cout << "m_size " << metadata_length << std::endl; + uint32_t maxlen = 0; + + if(m_type == mysql::system::MYSQL_TYPE_STRING) { + uint8_t lower = m_metadata & 0xFF; + uint8_t higher = m_metadata >> 8U; + if ((lower & 0x30) != 0x30) { + maxlen = (((lower & 0x30) ^ 0x30) << 4) | higher; + } else { + maxlen = higher; + } + } else { + maxlen = m_metadata; + } + + int metadata_length = maxlen > 255 ? 2 : 1; /* Size is length of the character string; not of the entire storage */ size = m_size - metadata_length; - // std::cout << "Len: " << m_size << " Metadata: " << m_metadata << " Size: " << size << std::endl; + // std::cout << "Len: " << m_size << " Metadata: " << m_metadata << " Size: " << size << " Max Len: " << maxlen << std::endl; return const_cast(m_storage + metadata_length); } From ea1565f68715e3c01a33d4e0f74f81ec913faf6b Mon Sep 17 00:00:00 2001 From: Gu Weigang Date: Thu, 12 Sep 2013 22:28:53 +0800 Subject: [PATCH 34/69] change CMakeLists to copy asio to bianry/include --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f096ad..5a1cfe3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,5 +27,5 @@ add_subdirectory(src) include(InstallRequiredSystemLibraries) # installation configuration -install(DIRECTORY include DESTINATION . FILES_MATCHING PATTERN "*.h" PATTERN "asio" EXCLUDE) +install(DIRECTORY include DESTINATION . FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp") From 9357d34b024743f2c1b2c1489dcefed043e20bfb Mon Sep 17 00:00:00 2001 From: Gu Weigang Date: Thu, 12 Sep 2013 22:38:09 +0800 Subject: [PATCH 35/69] add notice for usage --- README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 227386f..309bfa4 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,20 @@ Install -------------------- mysql-replication-listener uses cmake. -$ cmake . -DCMAKE_INSTALL_PREFIX=/usr +$ cmake . -DCMAKE_INSTALL_PREFIX=/path/to/install $ make $ sudo make install + + +Notice +-------------------- +We need to make mysql server to dump binlog-stream to us, so we need **REPLICATION SLAVE** privilege. +And We need to get master status, so we need "REPLICATION CLIENT" privilege. + +If you want to set_position to a specified binlog-file and the position, we need to ensure the binlog-file and it's position are legal, so we need to excute "SHOW BINARY LOGS" on the server. Unfortunately, + In MySQL 5.1.63 and earlier, the SUPER privilege was required to use this statement. Starting with MYSQL 5.1.64, a user with the REPLICATION CLIENT privilege may also execute this statement. + +So If you use MySQL 5.1.63 and earlier, you need "SUPER" privilege too. + From 65499f4f12231ea290982982e50a9850d5a2fa4d Mon Sep 17 00:00:00 2001 From: Gu Weigang Date: Thu, 12 Sep 2013 22:39:19 +0800 Subject: [PATCH 36/69] add notice for usage --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 309bfa4..8b33e4e 100644 --- a/README.md +++ b/README.md @@ -21,10 +21,10 @@ $ sudo make install Notice -------------------- We need to make mysql server to dump binlog-stream to us, so we need **REPLICATION SLAVE** privilege. -And We need to get master status, so we need "REPLICATION CLIENT" privilege. +And We need to get master status, so we need **REPLICATION CLIENT** privilege. If you want to set_position to a specified binlog-file and the position, we need to ensure the binlog-file and it's position are legal, so we need to excute "SHOW BINARY LOGS" on the server. Unfortunately, In MySQL 5.1.63 and earlier, the SUPER privilege was required to use this statement. Starting with MYSQL 5.1.64, a user with the REPLICATION CLIENT privilege may also execute this statement. -So If you use MySQL 5.1.63 and earlier, you need "SUPER" privilege too. +So If you use MySQL 5.1.63 and earlier, you need **SUPER** privilege too.1;10;0c From 057cee070e66e9677d93c7ad4859ff71c6785001 Mon Sep 17 00:00:00 2001 From: Gu Weigang Date: Thu, 12 Sep 2013 22:40:11 +0800 Subject: [PATCH 37/69] add notice for usage --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8b33e4e..c7fe112 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ We need to make mysql server to dump binlog-stream to us, so we need **REPLICATI And We need to get master status, so we need **REPLICATION CLIENT** privilege. If you want to set_position to a specified binlog-file and the position, we need to ensure the binlog-file and it's position are legal, so we need to excute "SHOW BINARY LOGS" on the server. Unfortunately, - In MySQL 5.1.63 and earlier, the SUPER privilege was required to use this statement. Starting with MYSQL 5.1.64, a user with the REPLICATION CLIENT privilege may also execute this statement. + In MySQL 5.1.63 and earlier, the SUPER privilege was required to use this statement. Starting with MYSQL 5.1.64, a user with the **REPLICATION CLIENT** privilege may also execute this statement. So If you use MySQL 5.1.63 and earlier, you need **SUPER** privilege too.1;10;0c From dada973082a2e98d994a896d1569c9dcfcf81114 Mon Sep 17 00:00:00 2001 From: Gu Weigang Date: Thu, 12 Sep 2013 22:40:52 +0800 Subject: [PATCH 38/69] add notice for usage --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c7fe112..301c655 100644 --- a/README.md +++ b/README.md @@ -26,5 +26,5 @@ And We need to get master status, so we need **REPLICATION CLIENT** privilege. If you want to set_position to a specified binlog-file and the position, we need to ensure the binlog-file and it's position are legal, so we need to excute "SHOW BINARY LOGS" on the server. Unfortunately, In MySQL 5.1.63 and earlier, the SUPER privilege was required to use this statement. Starting with MYSQL 5.1.64, a user with the **REPLICATION CLIENT** privilege may also execute this statement. -So If you use MySQL 5.1.63 and earlier, you need **SUPER** privilege too.1;10;0c +So If you use MySQL 5.1.63 and earlier, you need **SUPER** privilege too. From a9284e514ddad58505acb81d616dd24f0d04ea88 Mon Sep 17 00:00:00 2001 From: Gu Weigang Date: Sun, 22 Sep 2013 18:35:14 +0800 Subject: [PATCH 39/69] add disconnect and server_id --- CMakeLists.txt | 2 +- include/binlog_api.h | 10 ++++++++++ include/binlog_driver.h | 5 ++++- include/file_driver.h | 1 + include/tcp_driver.h | 21 ++++++++++++--------- src/binary_log.cpp | 10 ++++++++++ src/file_driver.cpp | 4 ++++ src/protocol.cpp | 23 +++++++++++++---------- src/tcp_driver.cpp | 33 ++++++++++++++++++++------------- 9 files changed, 75 insertions(+), 34 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5a1cfe3..41188b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,5 +27,5 @@ add_subdirectory(src) include(InstallRequiredSystemLibraries) # installation configuration -install(DIRECTORY include DESTINATION . FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp") +install(DIRECTORY include DESTINATION . FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp" PATTERN "*.ipp") diff --git a/include/binlog_api.h b/include/binlog_api.h index 68877fd..0db751e 100644 --- a/include/binlog_api.h +++ b/include/binlog_api.h @@ -54,6 +54,10 @@ class Dummy_driver : public system::Binary_log_driver virtual ~Dummy_driver() {} virtual int connect() { return 1; } + + virtual int disconnect() { return ERR_OK; } + + virtual int set_server_id(int server_id) { return server_id; } virtual int wait_for_next_event(mysql::Binary_log_event **event) { return ERR_EOF; @@ -66,6 +70,7 @@ class Dummy_driver : public system::Binary_log_driver virtual int get_position(std::string *str, unsigned long *position) { return ERR_OK; } + }; class Content_handler; @@ -85,6 +90,8 @@ class Binary_log { int connect(); + int disconnect(); + /** * Blocking attempt to get the next binlog event from the stream */ @@ -117,6 +124,9 @@ class Binary_log { */ int set_position(unsigned long position); + + int set_server_id(int server_id); + /** * Fetch the binlog position for the current file */ diff --git a/include/binlog_driver.h b/include/binlog_driver.h index 75f47a1..4656c3d 100644 --- a/include/binlog_driver.h +++ b/include/binlog_driver.h @@ -44,9 +44,12 @@ class Binary_log_driver * @retval 0 Success * @retval >0 Error code (to be specified) */ - virtual int connect()= 0; + virtual int connect() = 0; + virtual int disconnect() = 0; + virtual int set_server_id(int server_id) = 0; + /** * Blocking attempt to get the next binlog event from the stream * @param event [out] Pointer to a binary log event to be fetched. diff --git a/include/file_driver.h b/include/file_driver.h index 3c711bb..7019b8b 100644 --- a/include/file_driver.h +++ b/include/file_driver.h @@ -48,6 +48,7 @@ class Binlog_file_driver } int connect(); + int set_server_id(int server_id); int disconnect(); int wait_for_next_event(mysql::Binary_log_event **event); int set_position(const std::string &str, unsigned long position); diff --git a/include/tcp_driver.h b/include/tcp_driver.h index 5073e8b..f31ec6a 100644 --- a/include/tcp_driver.h +++ b/include/tcp_driver.h @@ -44,12 +44,12 @@ class Binlog_tcp_driver : public Binary_log_driver { public: - Binlog_tcp_driver(const std::string& user, const std::string& passwd, - const std::string& host, unsigned long port) - : Binary_log_driver("", 4), m_host(host), m_user(user), m_passwd(passwd), - m_port(port), m_socket(NULL), m_waiting_event(0), m_event_loop(0), - m_total_bytes_transferred(0), m_shutdown(false), - m_event_queue(new bounded_buffer(50)) + Binlog_tcp_driver(const std::string& user, const std::string& passwd, + const std::string& host, unsigned long port) + : Binary_log_driver("", 4), m_host(host), m_user(user), m_passwd(passwd), + m_port(port), m_socket(NULL), m_waiting_event(0), m_event_loop(0), + m_total_bytes_transferred(0), m_shutdown(false), m_server_id(1), + m_event_queue(new bounded_buffer(50)) { } @@ -77,6 +77,8 @@ class Binlog_tcp_driver : public Binary_log_driver int get_position(std::string *str, unsigned long *position); + int set_server_id(int server_id); + const std::string& user() const { return m_user; } const std::string& password() const { return m_passwd; } const std::string& host() const { return m_host; } @@ -162,7 +164,7 @@ class Binlog_tcp_driver : public Binary_log_driver * this function is called. * The event queue is emptied. */ - void disconnect(void); + int disconnect(); /** * Terminates the io service and sets the shudown flag. @@ -174,7 +176,8 @@ class Binlog_tcp_driver : public Binary_log_driver asio::io_service m_io_service; tcp::socket *m_socket; bool m_shutdown; - + // slave server id + int m_server_id; /** * Temporary storage for a handshake package */ @@ -272,7 +275,7 @@ int authenticate(tcp::socket *socket, const std::string& user, tcp::socket * sync_connect_and_authenticate(asio::io_service &io_service, const std::string &user, - const std::string &passwd, const std::string &host, long port); + const std::string &passwd, const std::string &host, long port, int server_id); } } diff --git a/src/binary_log.cpp b/src/binary_log.cpp index 80d68e5..3575d2a 100644 --- a/src/binary_log.cpp +++ b/src/binary_log.cpp @@ -118,4 +118,14 @@ int Binary_log::connect() return m_driver->connect(); } +int Binary_log::disconnect() +{ + return m_driver->disconnect(); +} + +int Binary_log::set_server_id(int server_id) +{ + return m_driver->set_server_id(server_id); +} + } diff --git a/src/file_driver.cpp b/src/file_driver.cpp index cfdc267..e502522 100644 --- a/src/file_driver.cpp +++ b/src/file_driver.cpp @@ -70,6 +70,10 @@ using namespace std; return ERR_OK; } + int Binlog_file_driver::set_server_id(int server_id) + { + return server_id; + } int Binlog_file_driver::set_position(const string &str, unsigned long position) { diff --git a/src/protocol.cpp b/src/protocol.cpp index 5f94fb4..8727e6b 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -96,18 +96,22 @@ void prot_parse_error_message(std::istream &is, struct st_error_package &err, int packet_length) { uint8_t marker; - + int message_size; + Protocol_chunk prot_errno(err.error_code); Protocol_chunk prot_marker(marker); - Protocol_chunk prot_sql_state(err.sql_state,5); is >> prot_errno - >> prot_marker - >> prot_sql_state; - - // TODO is the number of bytes read = is.tellg() ? - - int message_size= packet_length -2 -1 -5; // the remaining part of the package + >> prot_marker; + + // TODO is the number of bytes read = is.tellg() ? + if(marker == '#') { + Protocol_chunk prot_sql_state(err.sql_state,5); + is >> prot_sql_state; + message_size = packet_length - 2 - 1 - 5; + } else { + message_size= packet_length - 2 - 1; // the remaining part of the package + } Protocol_chunk_string prot_message(err.message, message_size); is >> prot_message; err.message[message_size]= '\0'; @@ -115,8 +119,7 @@ void prot_parse_error_message(std::istream &is, struct st_error_package &err, void prot_parse_ok_message(std::istream &is, struct st_ok_package &ok, int packet_length) { - // TODO: Assure that zero length messages can be but on the input stream. - + // TODO: Assure that zero length messages can be but on the input stream. //Protocol_chunk prot_result_type(result_type); Protocol_chunk prot_affected_rows(ok.affected_rows); Protocol_chunk prot_insert_id(ok.insert_id); diff --git a/src/tcp_driver.cpp b/src/tcp_driver.cpp index 1ccd83c..56b8460 100644 --- a/src/tcp_driver.cpp +++ b/src/tcp_driver.cpp @@ -51,9 +51,15 @@ static int encrypt_password(uint8_t *reply, /* buffer at least EVP_MAX_MD_SIZE const char *pass); static int hash_sha1(uint8_t *output, ...); - int Binlog_tcp_driver::connect(const std::string& user, const std::string& passwd, - const std::string& host, long port, - const std::string& binlog_filename, size_t offset) +int Binlog_tcp_driver::set_server_id(int server_id) +{ + m_server_id = server_id; + return m_server_id; +} + +int Binlog_tcp_driver::connect(const std::string& user, const std::string& passwd, + const std::string& host, long port, + const std::string& binlog_filename, size_t offset) { m_user=user; m_passwd=passwd; @@ -62,7 +68,7 @@ static int hash_sha1(uint8_t *output, ...); if (!m_socket) { - if ((m_socket=sync_connect_and_authenticate(m_io_service, user, passwd, host, port)) == 0) + if ((m_socket=sync_connect_and_authenticate(m_io_service, user, passwd, host, port, m_server_id)) == 0) return 1; } @@ -84,7 +90,7 @@ static int hash_sha1(uint8_t *output, ...); return 0; } -tcp::socket *sync_connect_and_authenticate(asio::io_service &io_service, const std::string &user, const std::string &passwd, const std::string &host, long port) +tcp::socket *sync_connect_and_authenticate(asio::io_service &io_service, const std::string &user, const std::string &passwd, const std::string &host, long port, int server_id) { tcp::resolver resolver(io_service); @@ -167,7 +173,7 @@ tcp::socket *sync_connect_and_authenticate(asio::io_service &io_service, const s Protocol_chunk prot_command(COM_REGISTER_SLAVE); Protocol_chunk prot_connection_port(port); Protocol_chunk prot_rpl_recovery_rank(0); - Protocol_chunk prot_server_id(1); // slave server-id + Protocol_chunk prot_server_id(server_id); // slave server-id /* * See document at http://dev.mysql.com/doc/internals/en/replication-protocol.html */ @@ -211,7 +217,7 @@ tcp::socket *sync_connect_and_authenticate(asio::io_service &io_service, const s uint8_t result_type; Protocol_chunk prot_result_type(result_type); - + // printf("Result type:\t%x\n", result_type); cmd_response_stream >> prot_result_type; if (result_type == 0) @@ -237,7 +243,7 @@ void Binlog_tcp_driver::start_binlog_dump(const std::string &binlog_file_name, s Protocol_chunk prot_command(COM_BINLOG_DUMP); Protocol_chunk prot_binlog_offset(offset); // binlog position to start at Protocol_chunk prot_binlog_flags(0); // not used - Protocol_chunk prot_server_id(1); // must not be 0; see handshake package + Protocol_chunk prot_server_id(m_server_id); // must not be 0; see handshake package command_request_stream << prot_command @@ -588,7 +594,7 @@ void Binlog_tcp_driver::reconnect() connect(m_user, m_passwd, m_host, m_port); } -void Binlog_tcp_driver::disconnect() +int Binlog_tcp_driver::disconnect() { Binary_log_event * event; m_waiting_event= 0; @@ -598,9 +604,10 @@ void Binlog_tcp_driver::disconnect() m_event_queue->pop_back(&event); delete(event); } - if (m_socket) - m_socket->close(); + if (m_socket) m_socket->close(); m_socket= 0; + + return ERR_OK; } @@ -620,7 +627,7 @@ int Binlog_tcp_driver::set_position(const std::string &str, unsigned long positi asio::io_service io_service; tcp::socket *socket; - if ((socket= sync_connect_and_authenticate(io_service, m_user, m_passwd, m_host, m_port)) == 0) + if ((socket= sync_connect_and_authenticate(io_service, m_user, m_passwd, m_host, m_port, m_server_id)) == 0) return ERR_FAIL; std::map binlog_map; @@ -676,7 +683,7 @@ int Binlog_tcp_driver::get_position(std::string *filename_ptr, unsigned long *po tcp::socket *socket; - if ((socket=sync_connect_and_authenticate(io_service, m_user, m_passwd, m_host, m_port)) == 0) + if ((socket=sync_connect_and_authenticate(io_service, m_user, m_passwd, m_host, m_port, m_server_id)) == 0) return ERR_FAIL; if (fetch_master_status(socket, &m_binlog_file_name, &m_binlog_offset)) From 46e6d607a5305ccc474ac9f9e76a82cfe72bb1db Mon Sep 17 00:00:00 2001 From: Gu Weigang Date: Sun, 22 Sep 2013 21:23:47 +0800 Subject: [PATCH 40/69] fillfull tcp_driver:disconnect --- src/tcp_driver.cpp | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/src/tcp_driver.cpp b/src/tcp_driver.cpp index 56b8460..2cb3d4f 100644 --- a/src/tcp_driver.cpp +++ b/src/tcp_driver.cpp @@ -606,6 +606,23 @@ int Binlog_tcp_driver::disconnect() } if (m_socket) m_socket->close(); m_socket= 0; + + /* + By posting to the io service we guarantee that the operations are + executed in the same thread as the io_service is running in. + */ + // shut down io service + Shutdown_handler shutdown_handler; + shutdown_handler.method = &Binlog_tcp_driver::shutdown; + shutdown_handler.tcp_driver = this; + m_io_service.post(shutdown_handler); + + // free pthread + if (m_event_loop) { + pthread_join(*m_event_loop, NULL); + free(m_event_loop); + } + m_event_loop= 0; return ERR_OK; } @@ -631,7 +648,7 @@ int Binlog_tcp_driver::set_position(const std::string &str, unsigned long positi return ERR_FAIL; std::map binlog_map; - fetch_binlogs_name_and_size(socket, binlog_map); + if(fetch_binlogs_name_and_size(socket, binlog_map)) return ERR_FAIL; socket->close(); delete socket; @@ -655,16 +672,16 @@ int Binlog_tcp_driver::set_position(const std::string &str, unsigned long positi By posting to the io service we guarantee that the operations are executed in the same thread as the io_service is running in. */ - Shutdown_handler shutdown_handler; - shutdown_handler.method = &Binlog_tcp_driver::shutdown; - shutdown_handler.tcp_driver = this; - m_io_service.post(shutdown_handler); - if (m_event_loop) - { - pthread_join(*m_event_loop, NULL); - free(m_event_loop); - } - m_event_loop= 0; + // Shutdown_handler shutdown_handler; + // shutdown_handler.method = &Binlog_tcp_driver::shutdown; + // shutdown_handler.tcp_driver = this; + // m_io_service.post(shutdown_handler); + // if (m_event_loop) + // { + // pthread_join(*m_event_loop, NULL); + // free(m_event_loop); + // } + // m_event_loop= 0; disconnect(); /* Uppon return of connect we only know if we succesfully authenticated From 4e152fe2d67ec8577d5f1dc8f6f898fa89c2c7d1 Mon Sep 17 00:00:00 2001 From: Gu Weigang Date: Tue, 24 Sep 2013 18:29:28 +0800 Subject: [PATCH 41/69] fix memory leak in result_set destructor --- include/protocol.h | 4 +++- include/resultset_iterator.h | 8 +++++++- src/resultset_iterator.cpp | 20 +++++++++++++------- src/tcp_driver.cpp | 4 ++++ 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/include/protocol.h b/include/protocol.h index bf27f5b..c05fcfb 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -315,7 +315,7 @@ class Protocol_chunk_string //: public Protocol_chunk_uint8 m_str= &chunk; m_str->assign(size,'*'); } - + ~ Protocol_chunk_string() {} virtual unsigned int size() const { return m_str->size(); } virtual const char *data() const { return m_str->data(); } virtual void collapse_size(unsigned int new_size) @@ -380,6 +380,8 @@ class Protocol_chunk_string_len m_storage= &str; } + ~Protocol_chunk_string_len() {} + private: friend std::istream &operator>>(std::istream &is, Protocol_chunk_string_len &lenstr); std::string *m_storage; diff --git a/include/resultset_iterator.h b/include/resultset_iterator.h index b23c676..b793b0e 100644 --- a/include/resultset_iterator.h +++ b/include/resultset_iterator.h @@ -52,7 +52,7 @@ struct Field_packet //uint64_t default_value; // Length coded binary; only in table descr. }; -typedef std::list String_storage; +typedef std::list String_storage; namespace system { void digest_result_header(std::istream &is, uint64_t &field_count, uint64_t extra); @@ -76,6 +76,12 @@ class Result_set iterator end(); const_iterator begin() const; const_iterator end() const; + ~Result_set() { + for (String_storage::iterator it=m_storage.begin(); it != m_storage.end(); ++it) { + delete *it; + } + m_storage.clear(); + } private: void digest_row_set(); diff --git a/src/resultset_iterator.cpp b/src/resultset_iterator.cpp index 96a6d5b..58ca058 100644 --- a/src/resultset_iterator.cpp +++ b/src/resultset_iterator.cpp @@ -78,10 +78,9 @@ void Result_set::digest_row_set() bool is_eof= false; Row_of_fields row(0); system::digest_row_content(response_stream, m_field_count, row, m_storage, is_eof); - if (is_eof) + if (is_eof) { m_current_state= EOF_PACKET; - else - { + } else { m_rows.push_back(row); ++m_row_count; } @@ -154,6 +153,7 @@ void digest_marker(std::istream &is) void digest_row_content(std::istream &is, int field_count, Row_of_fields &row, String_storage &storage, bool &is_eof) { uint8_t size; + Protocol_chunk proto_size(size); is >> proto_size; if (size == 0xfe) @@ -167,12 +167,18 @@ void digest_row_content(std::istream &is, int field_count, Row_of_fields &row, S is.putback((char)size); for(int field_no=0; field_no < field_count; ++field_no) { - std::string *storage= new std::string; + // std::string storage_str; + std::string *storage_str = new std::string; - Protocol_chunk_string_len proto_value(*storage); + // Protocol_chunk_string_len proto_value(storage_str); + Protocol_chunk_string_len proto_value(*storage_str); + is >> proto_value; - - Value value(MYSQL_TYPE_VAR_STRING, storage->length(), storage->c_str()); + storage.push_back(storage_str); + + // Value value(MYSQL_TYPE_VAR_STRING, storage.back().length(), storage.back().c_str()); + Value value(MYSQL_TYPE_VAR_STRING, storage.back()->length(), storage.back()->c_str()); + row.push_back(value); } } diff --git a/src/tcp_driver.cpp b/src/tcp_driver.cpp index 2cb3d4f..8c16e84 100644 --- a/src/tcp_driver.cpp +++ b/src/tcp_driver.cpp @@ -53,6 +53,9 @@ static int hash_sha1(uint8_t *output, ...); int Binlog_tcp_driver::set_server_id(int server_id) { + if(server_id < 0) { + server_id = 1; + } m_server_id = server_id; return m_server_id; } @@ -808,6 +811,7 @@ int hash_sha1(uint8_t *output, ...) EVP_DigestUpdate(hash_context, data, length); } EVP_DigestFinal_ex(hash_context, (unsigned char *)output, (unsigned int *)&result); + EVP_MD_CTX_destroy(hash_context); va_end(ap); return result; } From b83e09bc3f84d0caf87f23fc87d954764641ab22 Mon Sep 17 00:00:00 2001 From: ideal Date: Fri, 27 Sep 2013 13:53:56 +0800 Subject: [PATCH 42/69] it is better using while() --- include/bounded_buffer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/bounded_buffer.h b/include/bounded_buffer.h index 46649f1..8ec6dfa 100644 --- a/include/bounded_buffer.h +++ b/include/bounded_buffer.h @@ -50,7 +50,7 @@ class bounded_buffer void push_front(const value_type& item) { pthread_mutex_lock(&m_mutex); - if (m_unread == capacity) + while (m_unread == capacity) pthread_cond_wait(&m_not_full, &m_mutex); for (int i = m_unread; i > 0; i--) { m_container[i] = m_container[i-1]; From 48098d2fe37140c82539441b86f3ccdb70a42e1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A1=BE=E4=BC=9F=E5=88=9A?= Date: Sun, 29 Sep 2013 20:55:19 +0800 Subject: [PATCH 43/69] Update README.md update readme --- README.md | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 301c655..a93684b 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,25 @@ -mysql-replication-listener +MySQL Replication Listener ========================= A listener to fetch binlog from mysql server. Reference: -https://code.launchpad.net/mysql-replication-listener -https://github.com/wangmh/mysql-replication-listener + - Source repo: https://code.launchpad.net/mysql-replication-listener + - We forked from: https://github.com/wangmh/mysql-replication-listener Install -------------------- -mysql-replication-listener uses cmake. +mysql-replication-listener uses cmake, so you need cmake first. + +We use asio for socket communication, and it involes some **boost** libraries, so maybe you need install boost(1.47 and newer). + +And then: $ cmake . -DCMAKE_INSTALL_PREFIX=/path/to/install $ make -$ sudo make install +$ make install Notice @@ -26,5 +30,8 @@ And We need to get master status, so we need **REPLICATION CLIENT** privilege. If you want to set_position to a specified binlog-file and the position, we need to ensure the binlog-file and it's position are legal, so we need to excute "SHOW BINARY LOGS" on the server. Unfortunately, In MySQL 5.1.63 and earlier, the SUPER privilege was required to use this statement. Starting with MYSQL 5.1.64, a user with the **REPLICATION CLIENT** privilege may also execute this statement. -So If you use MySQL 5.1.63 and earlier, you need **SUPER** privilege too. +So If you use MySQL 5.1.63 and earlier, you need **SUPER** privilege too. + +Also, We auth privilege before binlog_dump, so we will access database **mysql** for accout checking... That means you have to give at least **READ** privilege for database mysql ... + From e1bda44226b7c46454220042c9d39a98fa371111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A1=BE=E4=BC=9F=E5=88=9A?= Date: Mon, 30 Sep 2013 16:14:24 +0800 Subject: [PATCH 44/69] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a93684b..6de778c 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ MySQL Replication Listener A listener to fetch binlog from mysql server. Reference: - - Source repo: https://code.launchpad.net/mysql-replication-listener + - Origin repo: https://code.launchpad.net/mysql-replication-listener - We forked from: https://github.com/wangmh/mysql-replication-listener Install From 4454996543f4eae5ad3016b9d5febba9a3113ddc Mon Sep 17 00:00:00 2001 From: Gu Weigang Date: Mon, 14 Oct 2013 17:20:38 +0800 Subject: [PATCH 45/69] add get_next_position --- include/binlog_event.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/binlog_event.h b/include/binlog_event.h index 1578fee..e863c66 100644 --- a/include/binlog_event.h +++ b/include/binlog_event.h @@ -152,6 +152,11 @@ class Binary_log_event return (enum Log_event_type) m_header.type_code; } + uint32_t get_next_position() const + { + return m_header.next_position; + } + /** * Return a pointer to the header of the log event */ From b50a6c219ca337d158a6221579f7d9eae433ad98 Mon Sep 17 00:00:00 2001 From: Gu Weigang Date: Sat, 19 Oct 2013 01:00:52 +0800 Subject: [PATCH 46/69] it make no sense to compare server_id and 0, if you give 0, you will get an random id between 10000, 20000 --- src/tcp_driver.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tcp_driver.cpp b/src/tcp_driver.cpp index 8c16e84..bebcc23 100644 --- a/src/tcp_driver.cpp +++ b/src/tcp_driver.cpp @@ -53,8 +53,9 @@ static int hash_sha1(uint8_t *output, ...); int Binlog_tcp_driver::set_server_id(int server_id) { - if(server_id < 0) { - server_id = 1; + if(server_id < 1) { + srand((unsigned int)(time(NULL))); + server_id = rand() % 10000 + 10000; } m_server_id = server_id; return m_server_id; From 59a0890ecfd19c09346c5f3c36d0db371712ff5f Mon Sep 17 00:00:00 2001 From: ideal Date: Wed, 30 Oct 2013 14:02:25 +0800 Subject: [PATCH 47/69] copy data to fix bug on some systems --- include/protocol.h | 39 ++++++++++++++++++++++++++++----------- src/protocol.cpp | 2 +- src/tcp_driver.cpp | 15 ++++++++++++++- 3 files changed, 43 insertions(+), 13 deletions(-) diff --git a/include/protocol.h b/include/protocol.h index c05fcfb..908b988 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -220,6 +220,9 @@ class Protocol { public: Protocol() { m_length_encoded_binary= false; } + + virtual ~Protocol() { } + /** Return the number of bytes which is read or written by this protocol chunk. The default size is equal to the underlying storage data type. @@ -261,20 +264,23 @@ class Protocol_chunk : public Protocol Protocol_chunk() : Protocol() { - m_size= 0; - m_data= 0; + m_size = 0; + m_data = 0; + m_need_free = true; } Protocol_chunk(T &chunk) : Protocol() { - m_data= (const char *)&chunk; - m_size= sizeof(T); + m_size = sizeof(T); + m_data = (char *) new char[m_size]; + std::memcpy(m_data, &chunk, m_size); } Protocol_chunk(const T &chunk) : Protocol () { - m_data= (const char *) &chunk; - m_size= sizeof(T); + m_size = sizeof(T); + m_data = (char *) new char[m_size]; + std::memcpy(m_data, &chunk, m_size); } /** @@ -286,8 +292,16 @@ class Protocol_chunk : public Protocol */ Protocol_chunk(T *buffer, unsigned long size) : Protocol () { - m_data= (const char *)buffer; - m_size= size; + m_data = (char *)buffer; + m_size = size; + m_need_free = false; + } + + virtual ~Protocol_chunk() + { + if (m_need_free) { + delete [] m_data; + } } virtual unsigned int size() { return m_size; } @@ -296,11 +310,14 @@ class Protocol_chunk : public Protocol { //assert(new_size <= m_size); memset((char *)m_data+new_size,'\0', m_size-new_size); - m_size= new_size; + m_size = new_size; } + private: - const char *m_data; - unsigned long m_size; + + char *m_data; + unsigned long m_size; + bool m_need_free; }; std::ostream &operator<<(std::ostream &os, Protocol &chunk); diff --git a/src/protocol.cpp b/src/protocol.cpp index 8727e6b..2f1695f 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -318,7 +318,7 @@ std::istream &operator>>(std::istream &is, Protocol_chunk_string_len &lenstr) std::ostream &operator<<(std::ostream &os, Protocol &chunk) { if (!os.bad()) - os.write((const char *) chunk.data(),chunk.size()); + os.write((const char *) chunk.data(), chunk.size()); return os; } diff --git a/src/tcp_driver.cpp b/src/tcp_driver.cpp index bebcc23..ed3ac13 100644 --- a/src/tcp_driver.cpp +++ b/src/tcp_driver.cpp @@ -200,6 +200,16 @@ tcp::socket *sync_connect_and_authenticate(asio::io_service &io_service, const s << prot_master_server_id; int size=server_messages.size(); + + /* + char *contents = new char [size]; + server_messages.sgetn(contents, size); + for (int i = 0; i < size; i++) { + printf("%02x:", contents[i]); + } + delete [] contents; + */ + char command_packet_header[4]; try { write_packet_header(command_packet_header, size, 0); // packet_no= 0 @@ -725,7 +735,8 @@ bool fetch_master_status(tcp::socket *socket, std::string *filename, unsigned lo std::ostream command_request_stream(&server_messages); - Protocol_chunk prot_command(COM_QUERY); + uint8_t command = COM_QUERY; + Protocol_chunk prot_command(command); command_request_stream << prot_command << "SHOW MASTER STATUS"; @@ -734,6 +745,7 @@ bool fetch_master_status(tcp::socket *socket, std::string *filename, unsigned lo char command_packet_header[4]; write_packet_header(command_packet_header, size, 0); + printf("xxxxxxxxxxxxxxxxx\n"); // Send the request. asio::write(*socket, asio::buffer(command_packet_header, 4), asio::transfer_at_least(4)); asio::write(*socket, server_messages, asio::transfer_at_least(size)); @@ -752,6 +764,7 @@ bool fetch_master_status(tcp::socket *socket, std::string *filename, unsigned lo conv.to(pos, row[1]); *position= (unsigned long)pos; } + printf("xxxxxxxxxxxxxxxxx\n"); return false; } From db92154113a560eb3e26c9ef363dacf5fc16909c Mon Sep 17 00:00:00 2001 From: ideal Date: Wed, 30 Oct 2013 14:09:52 +0800 Subject: [PATCH 48/69] fix wrong commited file --- src/tcp_driver.cpp | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/tcp_driver.cpp b/src/tcp_driver.cpp index ed3ac13..272356e 100644 --- a/src/tcp_driver.cpp +++ b/src/tcp_driver.cpp @@ -201,15 +201,6 @@ tcp::socket *sync_connect_and_authenticate(asio::io_service &io_service, const s int size=server_messages.size(); - /* - char *contents = new char [size]; - server_messages.sgetn(contents, size); - for (int i = 0; i < size; i++) { - printf("%02x:", contents[i]); - } - delete [] contents; - */ - char command_packet_header[4]; try { write_packet_header(command_packet_header, size, 0); // packet_no= 0 @@ -735,8 +726,7 @@ bool fetch_master_status(tcp::socket *socket, std::string *filename, unsigned lo std::ostream command_request_stream(&server_messages); - uint8_t command = COM_QUERY; - Protocol_chunk prot_command(command); + Protocol_chunk prot_command(COM_QUERY); command_request_stream << prot_command << "SHOW MASTER STATUS"; @@ -745,7 +735,6 @@ bool fetch_master_status(tcp::socket *socket, std::string *filename, unsigned lo char command_packet_header[4]; write_packet_header(command_packet_header, size, 0); - printf("xxxxxxxxxxxxxxxxx\n"); // Send the request. asio::write(*socket, asio::buffer(command_packet_header, 4), asio::transfer_at_least(4)); asio::write(*socket, server_messages, asio::transfer_at_least(size)); @@ -764,7 +753,6 @@ bool fetch_master_status(tcp::socket *socket, std::string *filename, unsigned lo conv.to(pos, row[1]); *position= (unsigned long)pos; } - printf("xxxxxxxxxxxxxxxxx\n"); return false; } From 28391e2fed5e31b4b3a2635a5282e13bba32e1a6 Mon Sep 17 00:00:00 2001 From: ideal Date: Wed, 30 Oct 2013 15:40:17 +0800 Subject: [PATCH 49/69] fix bug in protocol_chunk --- include/protocol.h | 38 ++++++++++++++++++++++++++------------ src/tcp_driver.cpp | 28 ++++++++++++++-------------- 2 files changed, 40 insertions(+), 26 deletions(-) diff --git a/include/protocol.h b/include/protocol.h index 908b988..b8907c1 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -165,6 +165,7 @@ enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY, }; + #define int3store(T,A) do { *(T)= (unsigned char) ((A));\ *(T+1)=(unsigned char) (((unsigned int) (A) >> 8));\ *(T+2)=(unsigned char) (((A) >> 16)); } while (0) @@ -257,6 +258,11 @@ class Protocol friend std::istream &operator>>(std::istream &is, std::string &str); }; +enum enum_pchunk_memory { + NEED_NOT_ALLOC, + NEED_ALLOC, +}; + template class Protocol_chunk : public Protocol { @@ -266,21 +272,29 @@ class Protocol_chunk : public Protocol { m_size = 0; m_data = 0; - m_need_free = true; + m_alloc = NEED_NOT_ALLOC; } - Protocol_chunk(T &chunk) : Protocol() + Protocol_chunk(T &chunk, enum enum_pchunk_memory alloc = NEED_NOT_ALLOC) : Protocol(), m_alloc(alloc) { m_size = sizeof(T); - m_data = (char *) new char[m_size]; - std::memcpy(m_data, &chunk, m_size); + if (m_alloc == NEED_ALLOC) { + m_data = (char *) new char[m_size]; + std::memcpy(m_data, &chunk, m_size); + } else { + m_data = (char *) &chunk; + } } - Protocol_chunk(const T &chunk) : Protocol () + Protocol_chunk(const T &chunk, enum enum_pchunk_memory alloc = NEED_NOT_ALLOC) : Protocol (), m_alloc(alloc) { m_size = sizeof(T); - m_data = (char *) new char[m_size]; - std::memcpy(m_data, &chunk, m_size); + if (m_alloc == NEED_ALLOC) { + m_data = (char *) new char[m_size]; + std::memcpy(m_data, &chunk, m_size); + } else { + m_data = (char *) &chunk; + } } /** @@ -292,14 +306,14 @@ class Protocol_chunk : public Protocol */ Protocol_chunk(T *buffer, unsigned long size) : Protocol () { - m_data = (char *)buffer; - m_size = size; - m_need_free = false; + m_data = (char *)buffer; + m_size = size; + m_alloc = NEED_NOT_ALLOC; } virtual ~Protocol_chunk() { - if (m_need_free) { + if (m_alloc == NEED_ALLOC) { delete [] m_data; } } @@ -317,7 +331,7 @@ class Protocol_chunk : public Protocol char *m_data; unsigned long m_size; - bool m_need_free; + enum enum_pchunk_memory m_alloc; }; std::ostream &operator<<(std::ostream &os, Protocol &chunk); diff --git a/src/tcp_driver.cpp b/src/tcp_driver.cpp index 272356e..7f68588 100644 --- a/src/tcp_driver.cpp +++ b/src/tcp_driver.cpp @@ -174,7 +174,7 @@ tcp::socket *sync_connect_and_authenticate(asio::io_service &io_service, const s */ std::ostream command_request_stream(&server_messages); - Protocol_chunk prot_command(COM_REGISTER_SLAVE); + Protocol_chunk prot_command(COM_REGISTER_SLAVE, NEED_ALLOC); Protocol_chunk prot_connection_port(port); Protocol_chunk prot_rpl_recovery_rank(0); Protocol_chunk prot_server_id(server_id); // slave server-id @@ -183,9 +183,9 @@ tcp::socket *sync_connect_and_authenticate(asio::io_service &io_service, const s */ Protocol_chunk prot_master_server_id(0); - Protocol_chunk prot_report_host_strlen(host.size()); - Protocol_chunk prot_user_strlen(user.size()); - Protocol_chunk prot_passwd_strlen(passwd.size()); + Protocol_chunk prot_report_host_strlen(host.size(), NEED_ALLOC); + Protocol_chunk prot_user_strlen(user.size(), NEED_ALLOC); + Protocol_chunk prot_passwd_strlen(passwd.size(), NEED_ALLOC); command_request_stream << prot_command << prot_server_id @@ -245,7 +245,7 @@ void Binlog_tcp_driver::start_binlog_dump(const std::string &binlog_file_name, s std::ostream command_request_stream(&server_messages); - Protocol_chunk prot_command(COM_BINLOG_DUMP); + Protocol_chunk prot_command(COM_BINLOG_DUMP, NEED_ALLOC); Protocol_chunk prot_binlog_offset(offset); // binlog position to start at Protocol_chunk prot_binlog_flags(0); // not used Protocol_chunk prot_server_id(m_server_id); // must not be 0; see handshake package @@ -308,12 +308,12 @@ static void proto_event_packet_header(asio::streambuf &event_src, Log_event_head Protocol_chunk prot_flags(h->flags); is >> prot_marker - >> prot_timestamp - >> prot_type_code - >> prot_server_id - >> prot_event_length - >> prot_next_position - >> prot_flags; + >> prot_timestamp + >> prot_type_code + >> prot_server_id + >> prot_event_length + >> prot_next_position + >> prot_flags; } void Binlog_tcp_driver::handle_net_packet(const asio::error_code& err, std::size_t bytes_transferred) @@ -726,7 +726,7 @@ bool fetch_master_status(tcp::socket *socket, std::string *filename, unsigned lo std::ostream command_request_stream(&server_messages); - Protocol_chunk prot_command(COM_QUERY); + Protocol_chunk prot_command(COM_QUERY, NEED_ALLOC); command_request_stream << prot_command << "SHOW MASTER STATUS"; @@ -747,7 +747,7 @@ bool fetch_master_status(tcp::socket *socket, std::string *filename, unsigned lo it++) { Row_of_fields row(*it); - *filename= ""; + *filename = ""; conv.to(*filename, row[0]); long pos; conv.to(pos, row[1]); @@ -762,7 +762,7 @@ bool fetch_binlogs_name_and_size(tcp::socket *socket, std::map prot_command(COM_QUERY); + Protocol_chunk prot_command(COM_QUERY, NEED_ALLOC); command_request_stream << prot_command << "SHOW BINARY LOGS"; From c63a23b1bd2dd7cc6d6a55ae35714c7e99002b40 Mon Sep 17 00:00:00 2001 From: ideal Date: Wed, 30 Oct 2013 17:10:14 +0800 Subject: [PATCH 50/69] make offset NEED_ALLOC --- src/tcp_driver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tcp_driver.cpp b/src/tcp_driver.cpp index 7f68588..ba9639e 100644 --- a/src/tcp_driver.cpp +++ b/src/tcp_driver.cpp @@ -246,7 +246,7 @@ void Binlog_tcp_driver::start_binlog_dump(const std::string &binlog_file_name, s std::ostream command_request_stream(&server_messages); Protocol_chunk prot_command(COM_BINLOG_DUMP, NEED_ALLOC); - Protocol_chunk prot_binlog_offset(offset); // binlog position to start at + Protocol_chunk prot_binlog_offset(offset, NEED_ALLOC); // binlog position to start at Protocol_chunk prot_binlog_flags(0); // not used Protocol_chunk prot_server_id(m_server_id); // must not be 0; see handshake package From 287f23d2f8412abd11cedb8d7bcadd3dbd2cd870 Mon Sep 17 00:00:00 2001 From: ideal Date: Wed, 30 Oct 2013 17:29:43 +0800 Subject: [PATCH 51/69] add more NEED_ALLOC --- src/tcp_driver.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/tcp_driver.cpp b/src/tcp_driver.cpp index ba9639e..1d6b415 100644 --- a/src/tcp_driver.cpp +++ b/src/tcp_driver.cpp @@ -174,14 +174,14 @@ tcp::socket *sync_connect_and_authenticate(asio::io_service &io_service, const s */ std::ostream command_request_stream(&server_messages); - Protocol_chunk prot_command(COM_REGISTER_SLAVE, NEED_ALLOC); - Protocol_chunk prot_connection_port(port); - Protocol_chunk prot_rpl_recovery_rank(0); - Protocol_chunk prot_server_id(server_id); // slave server-id + Protocol_chunk prot_command(COM_REGISTER_SLAVE, NEED_ALLOC); + Protocol_chunk prot_connection_port((uint16_t)port, NEED_ALLOC); + Protocol_chunk prot_rpl_recovery_rank(0, NEED_ALLOC); + Protocol_chunk prot_server_id(server_id, NEED_ALLOC); // slave server-id /* * See document at http://dev.mysql.com/doc/internals/en/replication-protocol.html */ - Protocol_chunk prot_master_server_id(0); + Protocol_chunk prot_master_server_id(0, NEED_ALLOC); Protocol_chunk prot_report_host_strlen(host.size(), NEED_ALLOC); Protocol_chunk prot_user_strlen(user.size(), NEED_ALLOC); From 07bc60a40e6613c236f2d12bf65ea15165c95f98 Mon Sep 17 00:00:00 2001 From: Gu Weigang Date: Wed, 30 Oct 2013 17:40:09 +0800 Subject: [PATCH 52/69] add need_alloc for m_server_id --- src/tcp_driver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tcp_driver.cpp b/src/tcp_driver.cpp index 1d6b415..80012b0 100644 --- a/src/tcp_driver.cpp +++ b/src/tcp_driver.cpp @@ -248,7 +248,7 @@ void Binlog_tcp_driver::start_binlog_dump(const std::string &binlog_file_name, s Protocol_chunk prot_command(COM_BINLOG_DUMP, NEED_ALLOC); Protocol_chunk prot_binlog_offset(offset, NEED_ALLOC); // binlog position to start at Protocol_chunk prot_binlog_flags(0); // not used - Protocol_chunk prot_server_id(m_server_id); // must not be 0; see handshake package + Protocol_chunk prot_server_id(m_server_id, NEED_ALLOC); // must not be 0; see handshake package command_request_stream << prot_command From 1968755c486a20e06274e9c51b1d16ec91e07954 Mon Sep 17 00:00:00 2001 From: ideal Date: Wed, 30 Oct 2013 18:29:58 +0800 Subject: [PATCH 53/69] add another NEED_ALLOC --- src/tcp_driver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tcp_driver.cpp b/src/tcp_driver.cpp index 80012b0..86b0b61 100644 --- a/src/tcp_driver.cpp +++ b/src/tcp_driver.cpp @@ -247,7 +247,7 @@ void Binlog_tcp_driver::start_binlog_dump(const std::string &binlog_file_name, s Protocol_chunk prot_command(COM_BINLOG_DUMP, NEED_ALLOC); Protocol_chunk prot_binlog_offset(offset, NEED_ALLOC); // binlog position to start at - Protocol_chunk prot_binlog_flags(0); // not used + Protocol_chunk prot_binlog_flags(0, NEED_ALLOC); // not used Protocol_chunk prot_server_id(m_server_id, NEED_ALLOC); // must not be 0; see handshake package command_request_stream From dc0e29767333b4fbec6833dd9d1395bc0470c118 Mon Sep 17 00:00:00 2001 From: ideal Date: Fri, 1 Nov 2013 10:52:13 +0800 Subject: [PATCH 54/69] update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6dee9d2..18b7dd8 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ CMakeFiles cmake_install.cmake lib tags +install_manifest.txt From 04dcc9e485484491dfa6f9f9e548078da71e8e5c Mon Sep 17 00:00:00 2001 From: ideal Date: Thu, 7 Nov 2013 12:27:59 +0800 Subject: [PATCH 55/69] add notice for setting server-id --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6de778c..c9ec815 100644 --- a/README.md +++ b/README.md @@ -34,4 +34,5 @@ So If you use MySQL 5.1.63 and earlier, you need **SUPER** privilege too. Also, We auth privilege before binlog_dump, so we will access database **mysql** for accout checking... That means you have to give at least **READ** privilege for database mysql ... +Also notice that besides `log-bin` and `binlog-format` set in mysqld section, you should also set a `server-id` for mysql master. From 6189ad8a79b46ef6b0357eb00eb5291b968728cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A1=BE=E4=BC=9F=E5=88=9A?= Date: Sat, 11 Jan 2014 19:36:50 +0800 Subject: [PATCH 56/69] Update README.md Fix typo --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c9ec815..a0c22f7 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,8 @@ Notice We need to make mysql server to dump binlog-stream to us, so we need **REPLICATION SLAVE** privilege. And We need to get master status, so we need **REPLICATION CLIENT** privilege. -If you want to set_position to a specified binlog-file and the position, we need to ensure the binlog-file and it's position are legal, so we need to excute "SHOW BINARY LOGS" on the server. Unfortunately, - In MySQL 5.1.63 and earlier, the SUPER privilege was required to use this statement. Starting with MYSQL 5.1.64, a user with the **REPLICATION CLIENT** privilege may also execute this statement. +If you want to set_position to a specified binlog-file and the position, we need to ensure the binlog-file and it's position are legal, so we need to execute "SHOW BINARY LOGS" on the server. Unfortunately, + In MySQL 5.1.63 and earlier, the **SUPER** privilege was required to use this statement. Starting with MYSQL 5.1.64, a user with the **REPLICATION CLIENT** privilege may also execute this statement. So If you use MySQL 5.1.63 and earlier, you need **SUPER** privilege too. From 71465961a45091d22bf5a27c312512433dd6ab18 Mon Sep 17 00:00:00 2001 From: Gu Weigang Date: Thu, 23 Jan 2014 15:30:09 +0800 Subject: [PATCH 57/69] add a judgement for set_position --- src/tcp_driver.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tcp_driver.cpp b/src/tcp_driver.cpp index 86b0b61..df05ca5 100644 --- a/src/tcp_driver.cpp +++ b/src/tcp_driver.cpp @@ -646,6 +646,11 @@ int Binlog_tcp_driver::set_position(const std::string &str, unsigned long positi position we won't know if it succeded because the binlog dump is running in another thread asynchronously. */ + + if(position >= m_binlog_offset) { + return ERR_FAIL; + } + asio::io_service io_service; tcp::socket *socket; From 368d403933be6769d841b8b632569bf704c6524b Mon Sep 17 00:00:00 2001 From: Shang Yuanchun Date: Thu, 15 May 2014 16:14:34 +0800 Subject: [PATCH 58/69] remove use of boost config.hpp --- include/asio/detail/config.hpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/include/asio/detail/config.hpp b/include/asio/detail/config.hpp index 3aa7b48..6264a81 100644 --- a/include/asio/detail/config.hpp +++ b/include/asio/detail/config.hpp @@ -11,7 +11,15 @@ #ifndef ASIO_DETAIL_CONFIG_HPP #define ASIO_DETAIL_CONFIG_HPP -#include +#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define BOOST_WINDOWS +# if !defined(__GNUC__) && !defined(BOOST_HAS_DECLSPEC) +# define BOOST_HAS_DECLSPEC +# endif +# ifdef _MSC_VER +# define BOOST_MSVC _MSC_VER +# endif +#endif // Default to a header-only implementation. The user must specifically request // separate compilation by defining either ASIO_SEPARATE_COMPILATION or From ccb42922d2e44c66cb938227887bd6d1cfb532d2 Mon Sep 17 00:00:00 2001 From: Shang Yuanchun Date: Fri, 16 May 2014 12:04:50 +0800 Subject: [PATCH 59/69] add check for boost --- include/asio/detail/config.hpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/include/asio/detail/config.hpp b/include/asio/detail/config.hpp index 6264a81..df0dca3 100644 --- a/include/asio/detail/config.hpp +++ b/include/asio/detail/config.hpp @@ -11,13 +11,17 @@ #ifndef ASIO_DETAIL_CONFIG_HPP #define ASIO_DETAIL_CONFIG_HPP -#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) -# define BOOST_WINDOWS -# if !defined(__GNUC__) && !defined(BOOST_HAS_DECLSPEC) -# define BOOST_HAS_DECLSPEC -# endif -# ifdef _MSC_VER +#ifdef HAVE_BOOST +# include +#else +# if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define BOOST_WINDOWS +# if !defined(__GNUC__) && !defined(BOOST_HAS_DECLSPEC) +# define BOOST_HAS_DECLSPEC +# endif +# ifdef _MSC_VER # define BOOST_MSVC _MSC_VER +# endif # endif #endif From 5d524352726ffedf799e92165eaf408d71ae8459 Mon Sep 17 00:00:00 2001 From: ideal Date: Tue, 20 May 2014 23:18:19 +0800 Subject: [PATCH 60/69] add travis ci --- .travis.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..3a28df8 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,17 @@ +language: cpp +compiler: + - gcc + +before_install: + - echo $LANG + - echo $LC_ALL + - cmake --version + - gcc -v + +script: + - mkdir build && cd build && cmake .. && make + +notifications: + email: + - guweigang@bullsoft.org + - shangyuanchun@bullsoft.org From 66f7da94a249cf1bc6c9005a840d45fca401f97f Mon Sep 17 00:00:00 2001 From: ideal Date: Tue, 20 May 2014 23:20:28 +0800 Subject: [PATCH 61/69] add travis ci image --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index a0c22f7..40007e2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ MySQL Replication Listener ========================= +[![Build Status](https://secure.travis-ci.org/BullSoft/mysql-replication-listener.png?branch=master)](http://travis-ci.org/BullSoft/mysql-replication-listener) + A listener to fetch binlog from mysql server. Reference: From af3b18c18df59ee16e948b9cbf2f3015d3f93d84 Mon Sep 17 00:00:00 2001 From: ideal Date: Tue, 20 May 2014 23:29:03 +0800 Subject: [PATCH 62/69] currently we need boost header files --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 3a28df8..f69f90a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,7 @@ before_install: - echo $LC_ALL - cmake --version - gcc -v + - sudo apt-get install -y libboost-dev script: - mkdir build && cd build && cmake .. && make From 0f35f7b66a876e11e182f5704e661d7de412f3f2 Mon Sep 17 00:00:00 2001 From: ideal Date: Thu, 22 May 2014 12:17:16 +0800 Subject: [PATCH 63/69] add clang compiler --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index f69f90a..1e316b0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ language: cpp compiler: - gcc + - clang before_install: - echo $LANG From 6cb40f5291934830be449bb92aac40b64515b8e8 Mon Sep 17 00:00:00 2001 From: ideal Date: Sun, 25 May 2014 10:14:04 +0800 Subject: [PATCH 64/69] check if boost exists --- CMakeLists.txt | 10 +++++++--- include/asio/basic_socket_iostream.hpp | 14 +++++++++----- include/asio/basic_socket_streambuf.hpp | 14 +++++++++----- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 41188b3..cb8aed4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,9 +15,13 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) include_directories(include) link_directories(${PROJECT_BINARY_DIR}/lib) -# TODO: order: find asio -> allow to define asio directory -> use include/asio -# For ASIO headers -INCLUDE_DIRECTORIES(include/asio) +find_package(Boost) +if(Boost_FOUND) + include_directories(Boost_INCLUDE_DIRS) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_BOOST") +else(Boost_FOUND) + message(INFO "No Boost found, will not use Boost") +endif(Boost_FOUND) # --------- Find crypt ------------------------------------------ FIND_LIBRARY(LIB_CRYPTO crypto /opt/local/lib /opt/lib /usr/lib /usr/local/lib) diff --git a/include/asio/basic_socket_iostream.hpp b/include/asio/basic_socket_iostream.hpp index e90f9ae..1c70f5a 100644 --- a/include/asio/basic_socket_iostream.hpp +++ b/include/asio/basic_socket_iostream.hpp @@ -19,11 +19,15 @@ #if !defined(BOOST_NO_IOSTREAM) -#include -#include -#include -#include -#include +#ifdef HAVE_BOOST +# include +# include +# include +# include +# include +#else +#endif + #include "asio/basic_socket_streambuf.hpp" #include "asio/stream_socket_service.hpp" diff --git a/include/asio/basic_socket_streambuf.hpp b/include/asio/basic_socket_streambuf.hpp index 91b9d3c..7d08be3 100644 --- a/include/asio/basic_socket_streambuf.hpp +++ b/include/asio/basic_socket_streambuf.hpp @@ -20,11 +20,15 @@ #if !defined(BOOST_NO_IOSTREAM) #include -#include -#include -#include -#include -#include +#ifdef HAVE_BOOST +# include +# include +# include +# include +# include +#else +#endif + #include "asio/basic_socket.hpp" #include "asio/deadline_timer_service.hpp" #include "asio/detail/array.hpp" From 2963c61333e6a467026e17d1441cb73699c7cfa4 Mon Sep 17 00:00:00 2001 From: ideal Date: Sun, 25 May 2014 10:27:07 +0800 Subject: [PATCH 65/69] check if boost exists --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cb8aed4..6cf8619 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ link_directories(${PROJECT_BINARY_DIR}/lib) find_package(Boost) if(Boost_FOUND) - include_directories(Boost_INCLUDE_DIRS) + include_directories(${Boost_INCLUDE_DIRS}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_BOOST") else(Boost_FOUND) message(INFO "No Boost found, will not use Boost") From 3316e4ad3e10c234e93b167fd2d299387d8be605 Mon Sep 17 00:00:00 2001 From: ideal Date: Sun, 25 May 2014 21:07:59 +0800 Subject: [PATCH 66/69] add base_from_member --- include/asio/basic_socket_streambuf.hpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/asio/basic_socket_streambuf.hpp b/include/asio/basic_socket_streambuf.hpp index 7d08be3..c2c884c 100644 --- a/include/asio/basic_socket_streambuf.hpp +++ b/include/asio/basic_socket_streambuf.hpp @@ -27,6 +27,22 @@ # include # include #else +namespace boost { + template + class base_from_member + { + protected: + MemberType member; + + base_from_member(): member() + { + } + }; +} +# ifndef BOOST_PP_CAT +# define BOOST_PP_CAT(a, b) a ## b +# endif +# define BOOST_PP_INC(x) (x) #endif #include "asio/basic_socket.hpp" From f74523902737c84fad9411a654baea85e40034d5 Mon Sep 17 00:00:00 2001 From: ideal Date: Fri, 4 Jul 2014 16:35:58 +0800 Subject: [PATCH 67/69] fix php ext build error temporarily --- include/binlog_api.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/binlog_api.h b/include/binlog_api.h index 0db751e..277652b 100644 --- a/include/binlog_api.h +++ b/include/binlog_api.h @@ -21,6 +21,11 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA #ifndef _REPEVENT_H #define _REPEVENT_H +// temp fix +#ifndef HAVE_BOOST +#define HAVE_BOOST +#endif + #include #include #include From 4ce5647ab429bb70432ea276a17430236d383771 Mon Sep 17 00:00:00 2001 From: ideal Date: Thu, 4 Sep 2014 11:07:50 +0800 Subject: [PATCH 68/69] for cmake policy CMP0042 (see cmake --help-policy CMP0042) --- src/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 00fdede..d456193 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -22,5 +22,9 @@ set_target_properties(replication_shared PROPERTIES VERSION "${MySQL_BINLOG_VERSION}" SOVERSION 2 OUTPUT_NAME "replication" ) +if(APPLE) +set_target_properties(replication_shared PROPERTIES MACOSX_RPATH ON) +endif(APPLE) + install(TARGETS replication_shared LIBRARY DESTINATION lib) install(TARGETS replication_static ARCHIVE DESTINATION lib) From 5cc3d35fc28a9861f9f0b56386259c0822dc2da0 Mon Sep 17 00:00:00 2001 From: ideal Date: Sun, 9 Nov 2014 17:07:35 +0800 Subject: [PATCH 69/69] change a build status icon --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 40007e2..ee5ee57 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ MySQL Replication Listener ========================= -[![Build Status](https://secure.travis-ci.org/BullSoft/mysql-replication-listener.png?branch=master)](http://travis-ci.org/BullSoft/mysql-replication-listener) +[![Build Status](https://img.shields.io/travis/BullSoft/mysql-replication-listener/master.svg?style=flat)](http://travis-ci.org/BullSoft/mysql-replication-listener) A listener to fetch binlog from mysql server.