├── .gitignore ├── assets ├── chat.png ├── effect.gif └── architecture.png ├── src ├── CanalClient.php ├── ICanalConnector.php ├── Message.php ├── CanalConnectorFactory.php ├── sample │ └── client.php ├── adapter │ ├── clue │ │ └── CanalConnector.php │ ├── swoole │ │ └── CanalConnector.php │ ├── socket │ │ ├── CanalConnector.php │ │ └── TcpClient.php │ └── CanalConnectorBase.php ├── protocol │ ├── Com │ │ └── Alibaba │ │ │ └── Otter │ │ │ └── Canal │ │ │ └── Protocol │ │ │ ├── Type.php │ │ │ ├── Compression.php │ │ │ ├── Pair.php │ │ │ ├── EntryType.php │ │ │ ├── HeartBeat.php │ │ │ ├── Messages.php │ │ │ ├── Ack.php │ │ │ ├── Sub.php │ │ │ ├── ClientAck.php │ │ │ ├── Unsub.php │ │ │ ├── ClientRollback.php │ │ │ ├── Dump.php │ │ │ ├── PacketType.php │ │ │ ├── Handshake.php │ │ │ ├── EventType.php │ │ │ ├── Entry.php │ │ │ ├── TransactionEnd.php │ │ │ ├── RowData.php │ │ │ ├── TransactionBegin.php │ │ │ ├── Packet.php │ │ │ ├── Get.php │ │ │ ├── ClientAuth.php │ │ │ ├── RowChange.php │ │ │ ├── Column.php │ │ │ └── Header.php │ ├── CanalProtocol.proto │ ├── EntryProtocol.proto │ └── GPBMetadata │ │ ├── CanalProtocol.php │ │ └── EntryProtocol.php └── Fmt.php ├── composer.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | composer.lock 2 | .idea/ 3 | test/ 4 | vendor/ 5 | .php_cs.cache -------------------------------------------------------------------------------- /assets/chat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xingwenge/canal-php/HEAD/assets/chat.png -------------------------------------------------------------------------------- /assets/effect.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xingwenge/canal-php/HEAD/assets/effect.gif -------------------------------------------------------------------------------- /assets/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xingwenge/canal-php/HEAD/assets/architecture.png -------------------------------------------------------------------------------- /src/CanalClient.php: -------------------------------------------------------------------------------- 1 | =5.6", 16 | "clue/socket-raw": "^1.4" 17 | }, 18 | "autoload": { 19 | "psr-4": { 20 | "Com\\Alibaba\\Otter\\Canal\\Protocol\\": "src/protocol/Com/Alibaba/Otter/Canal/Protocol/", 21 | "GPBMetadata\\": "src/protocol/GPBMetadata/", 22 | "xingwenge\\canal_php\\": "src/" 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Message.php: -------------------------------------------------------------------------------- 1 | id; 19 | } 20 | 21 | /** 22 | * @param int $id 23 | */ 24 | public function setId( $id ) 25 | { 26 | $this->id = $id; 27 | } 28 | 29 | /** 30 | * @return array 31 | */ 32 | public function getEntries() 33 | { 34 | return $this->entries; 35 | } 36 | 37 | /** 38 | * @param Entry $entry 39 | */ 40 | public function addEntries( $entry ) 41 | { 42 | $this->entries[] = $entry; 43 | } 44 | } -------------------------------------------------------------------------------- /src/CanalConnectorFactory.php: -------------------------------------------------------------------------------- 1 | connect("127.0.0.1", 11111); 18 | $client->subscribe("1001", "example", ".*\\..*"); 19 | # $client->subscribe("1001", "example", "db_name.tb_name"); # 设置过滤 20 | 21 | while (true) { 22 | $message = $client->get(100); 23 | if ($entries = $message->getEntries()) { 24 | foreach ($entries as $entry) { 25 | Fmt::println($entry); 26 | } 27 | } 28 | sleep(1); 29 | } 30 | 31 | $client->disConnect(); 32 | } catch (\Exception $e) { 33 | echo $e->getMessage(), PHP_EOL; 34 | } -------------------------------------------------------------------------------- /src/adapter/clue/CanalConnector.php: -------------------------------------------------------------------------------- 1 | client = $factory->createClient(sprintf("tcp://%s:%s", $host, $port), $connectionTimeout); 24 | } 25 | 26 | protected function readNextPacket() 27 | { 28 | $data = $this->client->read($this->packetLen); 29 | $dataLen = unpack("N", $data)[1]; 30 | return $this->client->recv($dataLen, MSG_WAITALL); 31 | } 32 | 33 | protected function writeWithHeader($data) 34 | { 35 | $this->client->write(pack("N", strlen($data))); 36 | $this->client->write($data); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/adapter/swoole/CanalConnector.php: -------------------------------------------------------------------------------- 1 | client = new \swoole_client(SWOOLE_SOCK_TCP); 26 | if (!$this->client->connect($host, $port, $connectionTimeout)) { 27 | throw new \Exception("connect failed. Error: {$this->client->errCode}"); 28 | } 29 | } 30 | 31 | protected function readNextPacket() 32 | { 33 | $data = $this->client->recv($this->packetLen); 34 | $dataLen = unpack("N", $data)[1]; 35 | return $this->client->recv($dataLen, true); 36 | } 37 | 38 | protected function writeWithHeader($data) 39 | { 40 | $this->client->send(pack("N", strlen($data))); 41 | $this->client->send($data); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/adapter/socket/CanalConnector.php: -------------------------------------------------------------------------------- 1 | client = new TcpClient($host, $port, true); 22 | $this->client->setConnectTimeout($connectionTimeout); 23 | $this->client->setRecvTimeout($readTimeout); 24 | $this->client->setSendTimeout($writeTimeout); 25 | $this->client->open(); 26 | } 27 | 28 | /** 29 | * @return string 30 | * @throws \Exception 31 | */ 32 | protected function readNextPacket() 33 | { 34 | $data = $this->client->read($this->packetLen); 35 | $dataLen = unpack("N", $data)[1]; 36 | return $this->client->read($dataLen); 37 | } 38 | 39 | /** 40 | * @param $data 41 | * @throws \Exception 42 | */ 43 | protected function writeWithHeader( $data ) 44 | { 45 | $this->client->write(pack("N", strlen($data))); 46 | $this->client->write($data); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/protocol/Com/Alibaba/Otter/Canal/Protocol/Type.php: -------------------------------------------------------------------------------- 1 | com.alibaba.otter.canal.protocol.Type 13 | */ 14 | class Type 15 | { 16 | /** 17 | * Generated from protobuf enum TYPECOMPATIBLEPROTO2 = 0; 18 | */ 19 | const TYPECOMPATIBLEPROTO2 = 0; 20 | /** 21 | * Generated from protobuf enum ORACLE = 1; 22 | */ 23 | const ORACLE = 1; 24 | /** 25 | * Generated from protobuf enum MYSQL = 2; 26 | */ 27 | const MYSQL = 2; 28 | /** 29 | * Generated from protobuf enum PGSQL = 3; 30 | */ 31 | const PGSQL = 3; 32 | 33 | private static $valueToName = [ 34 | self::TYPECOMPATIBLEPROTO2 => 'TYPECOMPATIBLEPROTO2', 35 | self::ORACLE => 'ORACLE', 36 | self::MYSQL => 'MYSQL', 37 | self::PGSQL => 'PGSQL', 38 | ]; 39 | 40 | public static function name($value) 41 | { 42 | if (!isset(self::$valueToName[$value])) { 43 | throw new UnexpectedValueException(sprintf( 44 | 'Enum %s has no name defined for value %s', __CLASS__, $value)); 45 | } 46 | return self::$valueToName[$value]; 47 | } 48 | 49 | 50 | public static function value($name) 51 | { 52 | $const = __CLASS__ . '::' . strtoupper($name); 53 | if (!defined($const)) { 54 | throw new UnexpectedValueException(sprintf( 55 | 'Enum %s has no value defined for name %s', __CLASS__, $name)); 56 | } 57 | return constant($const); 58 | } 59 | } 60 | 61 | -------------------------------------------------------------------------------- /src/protocol/Com/Alibaba/Otter/Canal/Protocol/Compression.php: -------------------------------------------------------------------------------- 1 | com.alibaba.otter.canal.protocol.Compression 11 | */ 12 | class Compression 13 | { 14 | /** 15 | * Generated from protobuf enum COMPRESSIONCOMPATIBLEPROTO2 = 0; 16 | */ 17 | const COMPRESSIONCOMPATIBLEPROTO2 = 0; 18 | /** 19 | * Generated from protobuf enum NONE = 1; 20 | */ 21 | const NONE = 1; 22 | /** 23 | * Generated from protobuf enum ZLIB = 2; 24 | */ 25 | const ZLIB = 2; 26 | /** 27 | * Generated from protobuf enum GZIP = 3; 28 | */ 29 | const GZIP = 3; 30 | /** 31 | * Generated from protobuf enum LZF = 4; 32 | */ 33 | const LZF = 4; 34 | 35 | private static $valueToName = [ 36 | self::COMPRESSIONCOMPATIBLEPROTO2 => 'COMPRESSIONCOMPATIBLEPROTO2', 37 | self::NONE => 'NONE', 38 | self::ZLIB => 'ZLIB', 39 | self::GZIP => 'GZIP', 40 | self::LZF => 'LZF', 41 | ]; 42 | 43 | public static function name($value) 44 | { 45 | if (!isset(self::$valueToName[$value])) { 46 | throw new UnexpectedValueException(sprintf( 47 | 'Enum %s has no name defined for value %s', __CLASS__, $value)); 48 | } 49 | return self::$valueToName[$value]; 50 | } 51 | 52 | 53 | public static function value($name) 54 | { 55 | $const = __CLASS__ . '::' . strtoupper($name); 56 | if (!defined($const)) { 57 | throw new UnexpectedValueException(sprintf( 58 | 'Enum %s has no value defined for name %s', __CLASS__, $name)); 59 | } 60 | return constant($const); 61 | } 62 | } 63 | 64 | -------------------------------------------------------------------------------- /src/protocol/Com/Alibaba/Otter/Canal/Protocol/Pair.php: -------------------------------------------------------------------------------- 1 | com.alibaba.otter.canal.protocol.Pair 15 | */ 16 | final class Pair extends \Google\Protobuf\Internal\Message 17 | { 18 | /** 19 | * Generated from protobuf field string key = 1; 20 | */ 21 | private $key = ''; 22 | /** 23 | * Generated from protobuf field string value = 2; 24 | */ 25 | private $value = ''; 26 | 27 | /** 28 | * Constructor. 29 | * 30 | * @param array $data { 31 | * Optional. Data for populating the Message object. 32 | * 33 | * @type string $key 34 | * @type string $value 35 | * } 36 | */ 37 | public function __construct($data = NULL) { 38 | \GPBMetadata\EntryProtocol::initOnce(); 39 | parent::__construct($data); 40 | } 41 | 42 | /** 43 | * Generated from protobuf field string key = 1; 44 | * @return string 45 | */ 46 | public function getKey() 47 | { 48 | return $this->key; 49 | } 50 | 51 | /** 52 | * Generated from protobuf field string key = 1; 53 | * @param string $var 54 | * @return $this 55 | */ 56 | public function setKey($var) 57 | { 58 | GPBUtil::checkString($var, True); 59 | $this->key = $var; 60 | 61 | return $this; 62 | } 63 | 64 | /** 65 | * Generated from protobuf field string value = 2; 66 | * @return string 67 | */ 68 | public function getValue() 69 | { 70 | return $this->value; 71 | } 72 | 73 | /** 74 | * Generated from protobuf field string value = 2; 75 | * @param string $var 76 | * @return $this 77 | */ 78 | public function setValue($var) 79 | { 80 | GPBUtil::checkString($var, True); 81 | $this->value = $var; 82 | 83 | return $this; 84 | } 85 | 86 | } 87 | 88 | -------------------------------------------------------------------------------- /src/Fmt.php: -------------------------------------------------------------------------------- 1 | getEntryType()) { 20 | case EntryType::TRANSACTIONBEGIN: 21 | case EntryType::TRANSACTIONEND: 22 | return; 23 | break; 24 | } 25 | 26 | $rowChange = new RowChange(); 27 | $rowChange->mergeFromString($entry->getStoreValue()); 28 | $evenType = $rowChange->getEventType(); 29 | $header = $entry->getHeader(); 30 | 31 | echo sprintf("================> binlog[%s : %d],name[%s,%s], eventType: %s", $header->getLogfileName(), $header->getLogfileOffset(), $header->getSchemaName(), $header->getTableName(), $header->getEventType()), PHP_EOL; 32 | echo $rowChange->getSql(), PHP_EOL; 33 | 34 | /** @var RowData $rowData */ 35 | foreach ($rowChange->getRowDatas() as $rowData) { 36 | switch ($evenType) { 37 | case EventType::DELETE: 38 | self::ptColumn($rowData->getBeforeColumns()); 39 | break; 40 | case EventType::INSERT: 41 | self::ptColumn($rowData->getAfterColumns()); 42 | break; 43 | default: 44 | echo '-------> before', PHP_EOL; 45 | self::ptColumn($rowData->getBeforeColumns()); 46 | echo '-------> after', PHP_EOL; 47 | self::ptColumn($rowData->getAfterColumns()); 48 | break; 49 | } 50 | } 51 | } 52 | 53 | private static function ptColumn($columns) { 54 | /** @var Column $column */ 55 | foreach ($columns as $column) { 56 | echo sprintf("%s : %s update= %s", $column->getName(), $column->getValue(), var_export($column->getUpdated(), true)), PHP_EOL; 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /src/protocol/Com/Alibaba/Otter/Canal/Protocol/EntryType.php: -------------------------------------------------------------------------------- 1 | com.alibaba.otter.canal.protocol.EntryType 13 | */ 14 | class EntryType 15 | { 16 | /** 17 | * Generated from protobuf enum ENTRYTYPECOMPATIBLEPROTO2 = 0; 18 | */ 19 | const ENTRYTYPECOMPATIBLEPROTO2 = 0; 20 | /** 21 | * Generated from protobuf enum TRANSACTIONBEGIN = 1; 22 | */ 23 | const TRANSACTIONBEGIN = 1; 24 | /** 25 | * Generated from protobuf enum ROWDATA = 2; 26 | */ 27 | const ROWDATA = 2; 28 | /** 29 | * Generated from protobuf enum TRANSACTIONEND = 3; 30 | */ 31 | const TRANSACTIONEND = 3; 32 | /** 33 | ** 心跳类型,内部使用,外部暂不可见,可忽略 * 34 | * 35 | * Generated from protobuf enum HEARTBEAT = 4; 36 | */ 37 | const HEARTBEAT = 4; 38 | /** 39 | * Generated from protobuf enum GTIDLOG = 5; 40 | */ 41 | const GTIDLOG = 5; 42 | 43 | private static $valueToName = [ 44 | self::ENTRYTYPECOMPATIBLEPROTO2 => 'ENTRYTYPECOMPATIBLEPROTO2', 45 | self::TRANSACTIONBEGIN => 'TRANSACTIONBEGIN', 46 | self::ROWDATA => 'ROWDATA', 47 | self::TRANSACTIONEND => 'TRANSACTIONEND', 48 | self::HEARTBEAT => 'HEARTBEAT', 49 | self::GTIDLOG => 'GTIDLOG', 50 | ]; 51 | 52 | public static function name($value) 53 | { 54 | if (!isset(self::$valueToName[$value])) { 55 | throw new UnexpectedValueException(sprintf( 56 | 'Enum %s has no name defined for value %s', __CLASS__, $value)); 57 | } 58 | return self::$valueToName[$value]; 59 | } 60 | 61 | 62 | public static function value($name) 63 | { 64 | $const = __CLASS__ . '::' . strtoupper($name); 65 | if (!defined($const)) { 66 | throw new UnexpectedValueException(sprintf( 67 | 'Enum %s has no value defined for name %s', __CLASS__, $name)); 68 | } 69 | return constant($const); 70 | } 71 | } 72 | 73 | -------------------------------------------------------------------------------- /src/protocol/Com/Alibaba/Otter/Canal/Protocol/HeartBeat.php: -------------------------------------------------------------------------------- 1 | com.alibaba.otter.canal.protocol.HeartBeat 13 | */ 14 | final class HeartBeat extends \Google\Protobuf\Internal\Message 15 | { 16 | /** 17 | * Generated from protobuf field int64 send_timestamp = 1; 18 | */ 19 | private $send_timestamp = 0; 20 | /** 21 | * Generated from protobuf field int64 start_timestamp = 2; 22 | */ 23 | private $start_timestamp = 0; 24 | 25 | /** 26 | * Constructor. 27 | * 28 | * @param array $data { 29 | * Optional. Data for populating the Message object. 30 | * 31 | * @type int|string $send_timestamp 32 | * @type int|string $start_timestamp 33 | * } 34 | */ 35 | public function __construct($data = NULL) { 36 | \GPBMetadata\CanalProtocol::initOnce(); 37 | parent::__construct($data); 38 | } 39 | 40 | /** 41 | * Generated from protobuf field int64 send_timestamp = 1; 42 | * @return int|string 43 | */ 44 | public function getSendTimestamp() 45 | { 46 | return $this->send_timestamp; 47 | } 48 | 49 | /** 50 | * Generated from protobuf field int64 send_timestamp = 1; 51 | * @param int|string $var 52 | * @return $this 53 | */ 54 | public function setSendTimestamp($var) 55 | { 56 | GPBUtil::checkInt64($var); 57 | $this->send_timestamp = $var; 58 | 59 | return $this; 60 | } 61 | 62 | /** 63 | * Generated from protobuf field int64 start_timestamp = 2; 64 | * @return int|string 65 | */ 66 | public function getStartTimestamp() 67 | { 68 | return $this->start_timestamp; 69 | } 70 | 71 | /** 72 | * Generated from protobuf field int64 start_timestamp = 2; 73 | * @param int|string $var 74 | * @return $this 75 | */ 76 | public function setStartTimestamp($var) 77 | { 78 | GPBUtil::checkInt64($var); 79 | $this->start_timestamp = $var; 80 | 81 | return $this; 82 | } 83 | 84 | } 85 | 86 | -------------------------------------------------------------------------------- /src/protocol/Com/Alibaba/Otter/Canal/Protocol/Messages.php: -------------------------------------------------------------------------------- 1 | com.alibaba.otter.canal.protocol.Messages 14 | */ 15 | final class Messages extends \Google\Protobuf\Internal\Message 16 | { 17 | /** 18 | * Generated from protobuf field int64 batch_id = 1; 19 | */ 20 | private $batch_id = 0; 21 | /** 22 | * Generated from protobuf field repeated bytes messages = 2; 23 | */ 24 | private $messages; 25 | 26 | /** 27 | * Constructor. 28 | * 29 | * @param array $data { 30 | * Optional. Data for populating the Message object. 31 | * 32 | * @type int|string $batch_id 33 | * @type string[]|\Google\Protobuf\Internal\RepeatedField $messages 34 | * } 35 | */ 36 | public function __construct($data = NULL) { 37 | \GPBMetadata\CanalProtocol::initOnce(); 38 | parent::__construct($data); 39 | } 40 | 41 | /** 42 | * Generated from protobuf field int64 batch_id = 1; 43 | * @return int|string 44 | */ 45 | public function getBatchId() 46 | { 47 | return $this->batch_id; 48 | } 49 | 50 | /** 51 | * Generated from protobuf field int64 batch_id = 1; 52 | * @param int|string $var 53 | * @return $this 54 | */ 55 | public function setBatchId($var) 56 | { 57 | GPBUtil::checkInt64($var); 58 | $this->batch_id = $var; 59 | 60 | return $this; 61 | } 62 | 63 | /** 64 | * Generated from protobuf field repeated bytes messages = 2; 65 | * @return \Google\Protobuf\Internal\RepeatedField 66 | */ 67 | public function getMessages() 68 | { 69 | return $this->messages; 70 | } 71 | 72 | /** 73 | * Generated from protobuf field repeated bytes messages = 2; 74 | * @param string[]|\Google\Protobuf\Internal\RepeatedField $var 75 | * @return $this 76 | */ 77 | public function setMessages($var) 78 | { 79 | $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::BYTES); 80 | $this->messages = $arr; 81 | 82 | return $this; 83 | } 84 | 85 | } 86 | 87 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # canal-php 2 | 3 | ## 一.canal-php 简介 4 | 5 | canal-php 是阿里巴巴开源项目 [Canal](https://github.com/alibaba/canal)是阿里巴巴mysql数据库binlog的增量订阅&消费组件 的 php 客户端。为 php 开发者提供一个更友好的使用 Canal 的方式。Canal 是mysql数据库binlog的增量订阅&消费组件。 6 | 7 | 基于日志增量订阅&消费支持的业务: 8 | 9 | 1. 数据库镜像 10 | 2. 数据库实时备份 11 | 3. 多级索引 (卖家和买家各自分库索引) 12 | 4. search build 13 | 5. 业务cache刷新 14 | 6. 价格变化等重要业务消息 15 | 16 | 关于 Canal 的更多信息请访问 https://github.com/alibaba/canal/wiki 17 | 18 | ## 二.应用场景 19 | 20 | canal-php 作为Canal的客户端,其应用场景就是Canal的应用场景。关于应用场景在Canal介绍一节已有概述。举一些实际的使用例子: 21 | 22 | 1.代替使用轮询数据库方式来监控数据库变更,有效改善轮询耗费数据库资源。 23 | 24 | 2.根据数据库的变更实时更新搜索引擎,比如电商场景下商品信息发生变更,实时同步到商品搜索引擎 Elasticsearch、solr等 25 | 26 | 3.根据数据库的变更实时更新缓存,比如电商场景下商品价格、库存发生变更实时同步到redis 27 | 28 | 4.数据库异地备份、数据同步 29 | 30 | 5.根据数据库变更触发某种业务,比如电商场景下,创建订单超过xx时间未支付被自动取消,我们获取到这条订单数据的状态变更即可向用户推送消息。 31 | 32 | 6.将数据库变更整理成自己的数据格式发送到kafka等消息队列,供消息队列的消费者进行消费。 33 | 34 | ## 三.工作原理 35 | 36 | canal-php 是 Canal 的 php 客户端,它与 Canal 是采用的Socket来进行通信的,传输协议是TCP,交互协议采用的是 Google Protocol Buffer 3.0。 37 | 38 | ## 四.工作流程 39 | 40 | 1.Canal连接到mysql数据库,模拟slave 41 | 42 | 2.canal-php 与 Canal 建立连接 43 | 44 | 3.数据库发生变更写入到binlog 45 | 46 | 4.Canal向数据库发送dump请求,获取binlog并解析 47 | 48 | 5.canal-php 向 Canal 请求数据库变更 49 | 50 | 6.Canal 发送解析后的数据给canal-php 51 | 52 | 7.canal-php收到数据,消费成功,发送回执。(可选) 53 | 54 | 8.Canal记录消费位置。 55 | 56 | ![架构图](assets/architecture.png) 57 | 58 | ## 五.快速启动 59 | 60 | ### 安装Canal 61 | 62 | Canal 的安装以及配置使用请查看 https://github.com/alibaba/canal/wiki/QuickStart 63 | 64 | 65 | ### 构建canal php客户端 66 | 67 | ````shell 68 | $ composer require xingwenge/canal_php 69 | 70 | or 71 | 72 | $ git clone https://github.com/xingwenge/canal-php.git 73 | $ cd canal-php 74 | $ composer update 75 | ```` 76 | 77 | ### 建立与Canal的连接 78 | ````php 79 | try { 80 | $client = CanalConnectorFactory::createClient(CanalClient::TYPE_SOCKET_CLUE); 81 | # $client = CanalConnectorFactory::createClient(CanalClient::TYPE_SWOOLE); 82 | 83 | $client->connect("127.0.0.1", 11111); 84 | $client->checkValid(); 85 | $client->subscribe("1001", "example", ".*\\..*"); 86 | # $client->subscribe("1001", "example", "db_name.tb_name"); # 设置过滤 87 | 88 | while (true) { 89 | $message = $client->get(100); 90 | if ($entries = $message->getEntries()) { 91 | foreach ($entries as $entry) { 92 | Fmt::println($entry); 93 | } 94 | } 95 | sleep(1); 96 | } 97 | 98 | $client->disConnect(); 99 | } catch (\Exception $e) { 100 | echo $e->getMessage(), PHP_EOL; 101 | } 102 | ```` 103 | 104 | ![运行效果图](assets/effect.gif) 105 | 106 | 更多详情请查看 [Sample](https://github.com/xingwenge/canal-php/blob/master/src/sample/client.php) 107 | 108 | ### 性能 109 | 本地开发环境 110 | 111 | 消费速度:sql insert 10000 事件,32秒消耗完成。消费速度 312.5 条/s。 112 | 113 | 内存使用:4 M。 114 | -------------------------------------------------------------------------------- /src/protocol/Com/Alibaba/Otter/Canal/Protocol/Ack.php: -------------------------------------------------------------------------------- 1 | com.alibaba.otter.canal.protocol.Ack 13 | */ 14 | final class Ack extends \Google\Protobuf\Internal\Message 15 | { 16 | /** 17 | * if something like compression is not supported, erorr_message will tell about it. 18 | * 19 | * Generated from protobuf field string error_message = 2; 20 | */ 21 | private $error_message = ''; 22 | protected $error_code_present; 23 | 24 | /** 25 | * Constructor. 26 | * 27 | * @param array $data { 28 | * Optional. Data for populating the Message object. 29 | * 30 | * @type int $error_code 31 | * @type string $error_message 32 | * if something like compression is not supported, erorr_message will tell about it. 33 | * } 34 | */ 35 | public function __construct($data = NULL) { 36 | \GPBMetadata\CanalProtocol::initOnce(); 37 | parent::__construct($data); 38 | } 39 | 40 | /** 41 | * Generated from protobuf field int32 error_code = 1; 42 | * @return int 43 | */ 44 | public function getErrorCode() 45 | { 46 | return $this->readOneof(1); 47 | } 48 | 49 | /** 50 | * Generated from protobuf field int32 error_code = 1; 51 | * @param int $var 52 | * @return $this 53 | */ 54 | public function setErrorCode($var) 55 | { 56 | GPBUtil::checkInt32($var); 57 | $this->writeOneof(1, $var); 58 | 59 | return $this; 60 | } 61 | 62 | /** 63 | * if something like compression is not supported, erorr_message will tell about it. 64 | * 65 | * Generated from protobuf field string error_message = 2; 66 | * @return string 67 | */ 68 | public function getErrorMessage() 69 | { 70 | return $this->error_message; 71 | } 72 | 73 | /** 74 | * if something like compression is not supported, erorr_message will tell about it. 75 | * 76 | * Generated from protobuf field string error_message = 2; 77 | * @param string $var 78 | * @return $this 79 | */ 80 | public function setErrorMessage($var) 81 | { 82 | GPBUtil::checkString($var, True); 83 | $this->error_message = $var; 84 | 85 | return $this; 86 | } 87 | 88 | /** 89 | * @return string 90 | */ 91 | public function getErrorCodePresent() 92 | { 93 | return $this->whichOneof("error_code_present"); 94 | } 95 | 96 | } 97 | 98 | -------------------------------------------------------------------------------- /src/protocol/Com/Alibaba/Otter/Canal/Protocol/Sub.php: -------------------------------------------------------------------------------- 1 | com.alibaba.otter.canal.protocol.Sub 15 | */ 16 | final class Sub extends \Google\Protobuf\Internal\Message 17 | { 18 | /** 19 | * Generated from protobuf field string destination = 1; 20 | */ 21 | private $destination = ''; 22 | /** 23 | * Generated from protobuf field string client_id = 2; 24 | */ 25 | private $client_id = ''; 26 | /** 27 | * Generated from protobuf field string filter = 7; 28 | */ 29 | private $filter = ''; 30 | 31 | /** 32 | * Constructor. 33 | * 34 | * @param array $data { 35 | * Optional. Data for populating the Message object. 36 | * 37 | * @type string $destination 38 | * @type string $client_id 39 | * @type string $filter 40 | * } 41 | */ 42 | public function __construct($data = NULL) { 43 | \GPBMetadata\CanalProtocol::initOnce(); 44 | parent::__construct($data); 45 | } 46 | 47 | /** 48 | * Generated from protobuf field string destination = 1; 49 | * @return string 50 | */ 51 | public function getDestination() 52 | { 53 | return $this->destination; 54 | } 55 | 56 | /** 57 | * Generated from protobuf field string destination = 1; 58 | * @param string $var 59 | * @return $this 60 | */ 61 | public function setDestination($var) 62 | { 63 | GPBUtil::checkString($var, True); 64 | $this->destination = $var; 65 | 66 | return $this; 67 | } 68 | 69 | /** 70 | * Generated from protobuf field string client_id = 2; 71 | * @return string 72 | */ 73 | public function getClientId() 74 | { 75 | return $this->client_id; 76 | } 77 | 78 | /** 79 | * Generated from protobuf field string client_id = 2; 80 | * @param string $var 81 | * @return $this 82 | */ 83 | public function setClientId($var) 84 | { 85 | GPBUtil::checkString($var, True); 86 | $this->client_id = $var; 87 | 88 | return $this; 89 | } 90 | 91 | /** 92 | * Generated from protobuf field string filter = 7; 93 | * @return string 94 | */ 95 | public function getFilter() 96 | { 97 | return $this->filter; 98 | } 99 | 100 | /** 101 | * Generated from protobuf field string filter = 7; 102 | * @param string $var 103 | * @return $this 104 | */ 105 | public function setFilter($var) 106 | { 107 | GPBUtil::checkString($var, True); 108 | $this->filter = $var; 109 | 110 | return $this; 111 | } 112 | 113 | } 114 | 115 | -------------------------------------------------------------------------------- /src/protocol/Com/Alibaba/Otter/Canal/Protocol/ClientAck.php: -------------------------------------------------------------------------------- 1 | com.alibaba.otter.canal.protocol.ClientAck 13 | */ 14 | final class ClientAck extends \Google\Protobuf\Internal\Message 15 | { 16 | /** 17 | * Generated from protobuf field string destination = 1; 18 | */ 19 | private $destination = ''; 20 | /** 21 | * Generated from protobuf field string client_id = 2; 22 | */ 23 | private $client_id = ''; 24 | /** 25 | * Generated from protobuf field int64 batch_id = 3; 26 | */ 27 | private $batch_id = 0; 28 | 29 | /** 30 | * Constructor. 31 | * 32 | * @param array $data { 33 | * Optional. Data for populating the Message object. 34 | * 35 | * @type string $destination 36 | * @type string $client_id 37 | * @type int|string $batch_id 38 | * } 39 | */ 40 | public function __construct($data = NULL) { 41 | \GPBMetadata\CanalProtocol::initOnce(); 42 | parent::__construct($data); 43 | } 44 | 45 | /** 46 | * Generated from protobuf field string destination = 1; 47 | * @return string 48 | */ 49 | public function getDestination() 50 | { 51 | return $this->destination; 52 | } 53 | 54 | /** 55 | * Generated from protobuf field string destination = 1; 56 | * @param string $var 57 | * @return $this 58 | */ 59 | public function setDestination($var) 60 | { 61 | GPBUtil::checkString($var, True); 62 | $this->destination = $var; 63 | 64 | return $this; 65 | } 66 | 67 | /** 68 | * Generated from protobuf field string client_id = 2; 69 | * @return string 70 | */ 71 | public function getClientId() 72 | { 73 | return $this->client_id; 74 | } 75 | 76 | /** 77 | * Generated from protobuf field string client_id = 2; 78 | * @param string $var 79 | * @return $this 80 | */ 81 | public function setClientId($var) 82 | { 83 | GPBUtil::checkString($var, True); 84 | $this->client_id = $var; 85 | 86 | return $this; 87 | } 88 | 89 | /** 90 | * Generated from protobuf field int64 batch_id = 3; 91 | * @return int|string 92 | */ 93 | public function getBatchId() 94 | { 95 | return $this->batch_id; 96 | } 97 | 98 | /** 99 | * Generated from protobuf field int64 batch_id = 3; 100 | * @param int|string $var 101 | * @return $this 102 | */ 103 | public function setBatchId($var) 104 | { 105 | GPBUtil::checkInt64($var); 106 | $this->batch_id = $var; 107 | 108 | return $this; 109 | } 110 | 111 | } 112 | 113 | -------------------------------------------------------------------------------- /src/protocol/Com/Alibaba/Otter/Canal/Protocol/Unsub.php: -------------------------------------------------------------------------------- 1 | com.alibaba.otter.canal.protocol.Unsub 15 | */ 16 | final class Unsub extends \Google\Protobuf\Internal\Message 17 | { 18 | /** 19 | * Generated from protobuf field string destination = 1; 20 | */ 21 | private $destination = ''; 22 | /** 23 | * Generated from protobuf field string client_id = 2; 24 | */ 25 | private $client_id = ''; 26 | /** 27 | * Generated from protobuf field string filter = 7; 28 | */ 29 | private $filter = ''; 30 | 31 | /** 32 | * Constructor. 33 | * 34 | * @param array $data { 35 | * Optional. Data for populating the Message object. 36 | * 37 | * @type string $destination 38 | * @type string $client_id 39 | * @type string $filter 40 | * } 41 | */ 42 | public function __construct($data = NULL) { 43 | \GPBMetadata\CanalProtocol::initOnce(); 44 | parent::__construct($data); 45 | } 46 | 47 | /** 48 | * Generated from protobuf field string destination = 1; 49 | * @return string 50 | */ 51 | public function getDestination() 52 | { 53 | return $this->destination; 54 | } 55 | 56 | /** 57 | * Generated from protobuf field string destination = 1; 58 | * @param string $var 59 | * @return $this 60 | */ 61 | public function setDestination($var) 62 | { 63 | GPBUtil::checkString($var, True); 64 | $this->destination = $var; 65 | 66 | return $this; 67 | } 68 | 69 | /** 70 | * Generated from protobuf field string client_id = 2; 71 | * @return string 72 | */ 73 | public function getClientId() 74 | { 75 | return $this->client_id; 76 | } 77 | 78 | /** 79 | * Generated from protobuf field string client_id = 2; 80 | * @param string $var 81 | * @return $this 82 | */ 83 | public function setClientId($var) 84 | { 85 | GPBUtil::checkString($var, True); 86 | $this->client_id = $var; 87 | 88 | return $this; 89 | } 90 | 91 | /** 92 | * Generated from protobuf field string filter = 7; 93 | * @return string 94 | */ 95 | public function getFilter() 96 | { 97 | return $this->filter; 98 | } 99 | 100 | /** 101 | * Generated from protobuf field string filter = 7; 102 | * @param string $var 103 | * @return $this 104 | */ 105 | public function setFilter($var) 106 | { 107 | GPBUtil::checkString($var, True); 108 | $this->filter = $var; 109 | 110 | return $this; 111 | } 112 | 113 | } 114 | 115 | -------------------------------------------------------------------------------- /src/protocol/Com/Alibaba/Otter/Canal/Protocol/ClientRollback.php: -------------------------------------------------------------------------------- 1 | com.alibaba.otter.canal.protocol.ClientRollback 13 | */ 14 | final class ClientRollback extends \Google\Protobuf\Internal\Message 15 | { 16 | /** 17 | * Generated from protobuf field string destination = 1; 18 | */ 19 | private $destination = ''; 20 | /** 21 | * Generated from protobuf field string client_id = 2; 22 | */ 23 | private $client_id = ''; 24 | /** 25 | * Generated from protobuf field int64 batch_id = 3; 26 | */ 27 | private $batch_id = 0; 28 | 29 | /** 30 | * Constructor. 31 | * 32 | * @param array $data { 33 | * Optional. Data for populating the Message object. 34 | * 35 | * @type string $destination 36 | * @type string $client_id 37 | * @type int|string $batch_id 38 | * } 39 | */ 40 | public function __construct($data = NULL) { 41 | \GPBMetadata\CanalProtocol::initOnce(); 42 | parent::__construct($data); 43 | } 44 | 45 | /** 46 | * Generated from protobuf field string destination = 1; 47 | * @return string 48 | */ 49 | public function getDestination() 50 | { 51 | return $this->destination; 52 | } 53 | 54 | /** 55 | * Generated from protobuf field string destination = 1; 56 | * @param string $var 57 | * @return $this 58 | */ 59 | public function setDestination($var) 60 | { 61 | GPBUtil::checkString($var, True); 62 | $this->destination = $var; 63 | 64 | return $this; 65 | } 66 | 67 | /** 68 | * Generated from protobuf field string client_id = 2; 69 | * @return string 70 | */ 71 | public function getClientId() 72 | { 73 | return $this->client_id; 74 | } 75 | 76 | /** 77 | * Generated from protobuf field string client_id = 2; 78 | * @param string $var 79 | * @return $this 80 | */ 81 | public function setClientId($var) 82 | { 83 | GPBUtil::checkString($var, True); 84 | $this->client_id = $var; 85 | 86 | return $this; 87 | } 88 | 89 | /** 90 | * Generated from protobuf field int64 batch_id = 3; 91 | * @return int|string 92 | */ 93 | public function getBatchId() 94 | { 95 | return $this->batch_id; 96 | } 97 | 98 | /** 99 | * Generated from protobuf field int64 batch_id = 3; 100 | * @param int|string $var 101 | * @return $this 102 | */ 103 | public function setBatchId($var) 104 | { 105 | GPBUtil::checkInt64($var); 106 | $this->batch_id = $var; 107 | 108 | return $this; 109 | } 110 | 111 | } 112 | 113 | -------------------------------------------------------------------------------- /src/protocol/Com/Alibaba/Otter/Canal/Protocol/Dump.php: -------------------------------------------------------------------------------- 1 | com.alibaba.otter.canal.protocol.Dump 15 | */ 16 | final class Dump extends \Google\Protobuf\Internal\Message 17 | { 18 | /** 19 | * Generated from protobuf field string journal = 1; 20 | */ 21 | private $journal = ''; 22 | /** 23 | * Generated from protobuf field int64 position = 2; 24 | */ 25 | private $position = 0; 26 | protected $timestamp_present; 27 | 28 | /** 29 | * Constructor. 30 | * 31 | * @param array $data { 32 | * Optional. Data for populating the Message object. 33 | * 34 | * @type string $journal 35 | * @type int|string $position 36 | * @type int|string $timestamp 37 | * } 38 | */ 39 | public function __construct($data = NULL) { 40 | \GPBMetadata\CanalProtocol::initOnce(); 41 | parent::__construct($data); 42 | } 43 | 44 | /** 45 | * Generated from protobuf field string journal = 1; 46 | * @return string 47 | */ 48 | public function getJournal() 49 | { 50 | return $this->journal; 51 | } 52 | 53 | /** 54 | * Generated from protobuf field string journal = 1; 55 | * @param string $var 56 | * @return $this 57 | */ 58 | public function setJournal($var) 59 | { 60 | GPBUtil::checkString($var, True); 61 | $this->journal = $var; 62 | 63 | return $this; 64 | } 65 | 66 | /** 67 | * Generated from protobuf field int64 position = 2; 68 | * @return int|string 69 | */ 70 | public function getPosition() 71 | { 72 | return $this->position; 73 | } 74 | 75 | /** 76 | * Generated from protobuf field int64 position = 2; 77 | * @param int|string $var 78 | * @return $this 79 | */ 80 | public function setPosition($var) 81 | { 82 | GPBUtil::checkInt64($var); 83 | $this->position = $var; 84 | 85 | return $this; 86 | } 87 | 88 | /** 89 | * Generated from protobuf field int64 timestamp = 3; 90 | * @return int|string 91 | */ 92 | public function getTimestamp() 93 | { 94 | return $this->readOneof(3); 95 | } 96 | 97 | /** 98 | * Generated from protobuf field int64 timestamp = 3; 99 | * @param int|string $var 100 | * @return $this 101 | */ 102 | public function setTimestamp($var) 103 | { 104 | GPBUtil::checkInt64($var); 105 | $this->writeOneof(3, $var); 106 | 107 | return $this; 108 | } 109 | 110 | /** 111 | * @return string 112 | */ 113 | public function getTimestampPresent() 114 | { 115 | return $this->whichOneof("timestamp_present"); 116 | } 117 | 118 | } 119 | 120 | -------------------------------------------------------------------------------- /src/protocol/Com/Alibaba/Otter/Canal/Protocol/PacketType.php: -------------------------------------------------------------------------------- 1 | com.alibaba.otter.canal.protocol.PacketType 11 | */ 12 | class PacketType 13 | { 14 | /** 15 | *compatible 16 | * 17 | * Generated from protobuf enum PACKAGETYPECOMPATIBLEPROTO2 = 0; 18 | */ 19 | const PACKAGETYPECOMPATIBLEPROTO2 = 0; 20 | /** 21 | * Generated from protobuf enum HANDSHAKE = 1; 22 | */ 23 | const HANDSHAKE = 1; 24 | /** 25 | * Generated from protobuf enum CLIENTAUTHENTICATION = 2; 26 | */ 27 | const CLIENTAUTHENTICATION = 2; 28 | /** 29 | * Generated from protobuf enum ACK = 3; 30 | */ 31 | const ACK = 3; 32 | /** 33 | * Generated from protobuf enum SUBSCRIPTION = 4; 34 | */ 35 | const SUBSCRIPTION = 4; 36 | /** 37 | * Generated from protobuf enum UNSUBSCRIPTION = 5; 38 | */ 39 | const UNSUBSCRIPTION = 5; 40 | /** 41 | * Generated from protobuf enum GET = 6; 42 | */ 43 | const GET = 6; 44 | /** 45 | * Generated from protobuf enum MESSAGES = 7; 46 | */ 47 | const MESSAGES = 7; 48 | /** 49 | * Generated from protobuf enum CLIENTACK = 8; 50 | */ 51 | const CLIENTACK = 8; 52 | /** 53 | * management part 54 | * 55 | * Generated from protobuf enum SHUTDOWN = 9; 56 | */ 57 | const SHUTDOWN = 9; 58 | /** 59 | * integration 60 | * 61 | * Generated from protobuf enum DUMP = 10; 62 | */ 63 | const DUMP = 10; 64 | /** 65 | * Generated from protobuf enum HEARTBEAT = 11; 66 | */ 67 | const HEARTBEAT = 11; 68 | /** 69 | * Generated from protobuf enum CLIENTROLLBACK = 12; 70 | */ 71 | const CLIENTROLLBACK = 12; 72 | 73 | private static $valueToName = [ 74 | self::PACKAGETYPECOMPATIBLEPROTO2 => 'PACKAGETYPECOMPATIBLEPROTO2', 75 | self::HANDSHAKE => 'HANDSHAKE', 76 | self::CLIENTAUTHENTICATION => 'CLIENTAUTHENTICATION', 77 | self::ACK => 'ACK', 78 | self::SUBSCRIPTION => 'SUBSCRIPTION', 79 | self::UNSUBSCRIPTION => 'UNSUBSCRIPTION', 80 | self::GET => 'GET', 81 | self::MESSAGES => 'MESSAGES', 82 | self::CLIENTACK => 'CLIENTACK', 83 | self::SHUTDOWN => 'SHUTDOWN', 84 | self::DUMP => 'DUMP', 85 | self::HEARTBEAT => 'HEARTBEAT', 86 | self::CLIENTROLLBACK => 'CLIENTROLLBACK', 87 | ]; 88 | 89 | public static function name($value) 90 | { 91 | if (!isset(self::$valueToName[$value])) { 92 | throw new UnexpectedValueException(sprintf( 93 | 'Enum %s has no name defined for value %s', __CLASS__, $value)); 94 | } 95 | return self::$valueToName[$value]; 96 | } 97 | 98 | 99 | public static function value($name) 100 | { 101 | $const = __CLASS__ . '::' . strtoupper($name); 102 | if (!defined($const)) { 103 | throw new UnexpectedValueException(sprintf( 104 | 'Enum %s has no value defined for name %s', __CLASS__, $name)); 105 | } 106 | return constant($const); 107 | } 108 | } 109 | 110 | -------------------------------------------------------------------------------- /src/protocol/Com/Alibaba/Otter/Canal/Protocol/Handshake.php: -------------------------------------------------------------------------------- 1 | com.alibaba.otter.canal.protocol.Handshake 13 | */ 14 | final class Handshake extends \Google\Protobuf\Internal\Message 15 | { 16 | /** 17 | * Generated from protobuf field bytes seeds = 2; 18 | */ 19 | private $seeds = ''; 20 | /** 21 | * Generated from protobuf field .com.alibaba.otter.canal.protocol.Compression supported_compressions = 3; 22 | */ 23 | private $supported_compressions = 0; 24 | protected $communication_encoding_present; 25 | 26 | /** 27 | * Constructor. 28 | * 29 | * @param array $data { 30 | * Optional. Data for populating the Message object. 31 | * 32 | * @type string $communication_encoding 33 | * @type string $seeds 34 | * @type int $supported_compressions 35 | * } 36 | */ 37 | public function __construct($data = NULL) { 38 | \GPBMetadata\CanalProtocol::initOnce(); 39 | parent::__construct($data); 40 | } 41 | 42 | /** 43 | * Generated from protobuf field string communication_encoding = 1; 44 | * @return string 45 | */ 46 | public function getCommunicationEncoding() 47 | { 48 | return $this->readOneof(1); 49 | } 50 | 51 | /** 52 | * Generated from protobuf field string communication_encoding = 1; 53 | * @param string $var 54 | * @return $this 55 | */ 56 | public function setCommunicationEncoding($var) 57 | { 58 | GPBUtil::checkString($var, True); 59 | $this->writeOneof(1, $var); 60 | 61 | return $this; 62 | } 63 | 64 | /** 65 | * Generated from protobuf field bytes seeds = 2; 66 | * @return string 67 | */ 68 | public function getSeeds() 69 | { 70 | return $this->seeds; 71 | } 72 | 73 | /** 74 | * Generated from protobuf field bytes seeds = 2; 75 | * @param string $var 76 | * @return $this 77 | */ 78 | public function setSeeds($var) 79 | { 80 | GPBUtil::checkString($var, False); 81 | $this->seeds = $var; 82 | 83 | return $this; 84 | } 85 | 86 | /** 87 | * Generated from protobuf field .com.alibaba.otter.canal.protocol.Compression supported_compressions = 3; 88 | * @return int 89 | */ 90 | public function getSupportedCompressions() 91 | { 92 | return $this->supported_compressions; 93 | } 94 | 95 | /** 96 | * Generated from protobuf field .com.alibaba.otter.canal.protocol.Compression supported_compressions = 3; 97 | * @param int $var 98 | * @return $this 99 | */ 100 | public function setSupportedCompressions($var) 101 | { 102 | GPBUtil::checkEnum($var, \Com\Alibaba\Otter\Canal\Protocol\Compression::class); 103 | $this->supported_compressions = $var; 104 | 105 | return $this; 106 | } 107 | 108 | /** 109 | * @return string 110 | */ 111 | public function getCommunicationEncodingPresent() 112 | { 113 | return $this->whichOneof("communication_encoding_present"); 114 | } 115 | 116 | } 117 | 118 | -------------------------------------------------------------------------------- /src/protocol/CanalProtocol.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package com.alibaba.otter.canal.protocol; 3 | 4 | option java_package = "com.alibaba.otter.canal.protocol"; 5 | option java_outer_classname = "CanalPacket"; 6 | option optimize_for = SPEED; 7 | 8 | enum Compression { 9 | COMPRESSIONCOMPATIBLEPROTO2 = 0; 10 | NONE = 1; 11 | ZLIB = 2; 12 | GZIP = 3; 13 | LZF = 4; 14 | } 15 | 16 | enum PacketType { 17 | //compatible 18 | PACKAGETYPECOMPATIBLEPROTO2 = 0; 19 | HANDSHAKE = 1; 20 | CLIENTAUTHENTICATION = 2; 21 | ACK = 3; 22 | SUBSCRIPTION = 4; 23 | UNSUBSCRIPTION = 5; 24 | GET = 6; 25 | MESSAGES = 7; 26 | CLIENTACK = 8; 27 | // management part 28 | SHUTDOWN = 9; 29 | // integration 30 | DUMP = 10; 31 | HEARTBEAT = 11; 32 | CLIENTROLLBACK = 12; 33 | } 34 | 35 | message Packet { 36 | //[default = 17]; 37 | oneof magic_number_present { 38 | int32 magic_number = 1; 39 | } 40 | //[default = 1]; 41 | oneof version_present { 42 | int32 version = 2; 43 | }; 44 | PacketType type = 3; 45 | //[default = NONE]; 46 | oneof compression_present { 47 | Compression compression = 4; 48 | } 49 | 50 | bytes body = 5; 51 | } 52 | 53 | message HeartBeat { 54 | int64 send_timestamp = 1; 55 | int64 start_timestamp = 2; 56 | } 57 | 58 | message Handshake { 59 | // [default = "utf8"]; 60 | oneof communication_encoding_present { 61 | string communication_encoding = 1; 62 | } 63 | bytes seeds = 2; 64 | Compression supported_compressions = 3; 65 | } 66 | 67 | // client authentication 68 | message ClientAuth { 69 | string username = 1; 70 | bytes password = 2; // hashed password with seeds from Handshake message 71 | // [default = 0] 72 | oneof net_read_timeout_present { 73 | int32 net_read_timeout = 3; // in seconds 74 | } 75 | // [default = 0]; 76 | oneof net_write_timeout_present { 77 | int32 net_write_timeout = 4; // in seconds 78 | } 79 | string destination = 5; 80 | string client_id = 6; 81 | string filter = 7; 82 | int64 start_timestamp = 8; 83 | } 84 | 85 | message Ack { 86 | //[default = 0] 87 | oneof error_code_present { 88 | int32 error_code = 1; 89 | } 90 | string error_message = 2; // if something like compression is not supported, erorr_message will tell about it. 91 | } 92 | 93 | message ClientAck { 94 | string destination = 1; 95 | string client_id = 2; 96 | int64 batch_id = 3; 97 | } 98 | 99 | // subscription 100 | message Sub { 101 | string destination = 1; 102 | string client_id = 2; 103 | string filter = 7; 104 | } 105 | 106 | // Unsubscription 107 | message Unsub { 108 | string destination = 1; 109 | string client_id = 2; 110 | string filter = 7; 111 | } 112 | 113 | // PullRequest 114 | message Get { 115 | string destination = 1; 116 | string client_id = 2; 117 | int32 fetch_size = 3; 118 | //[default = -1] 119 | oneof timeout_present { 120 | int64 timeout = 4; // 默认-1时代表不控制 121 | } 122 | //[default = 2] 123 | oneof unit_present { 124 | int32 unit = 5;// 数字类型,0:纳秒,1:毫秒,2:微秒,3:秒,4:分钟,5:小时,6:天 125 | } 126 | //[default = false] 127 | oneof auto_ack_present { 128 | bool auto_ack = 6; // 是否自动ack 129 | } 130 | 131 | } 132 | 133 | // 134 | message Messages { 135 | int64 batch_id = 1; 136 | repeated bytes messages = 2; 137 | } 138 | 139 | // TBD when new packets are required 140 | message Dump{ 141 | string journal = 1; 142 | int64 position = 2; 143 | // [default = 0] 144 | oneof timestamp_present { 145 | int64 timestamp = 3; 146 | } 147 | 148 | } 149 | 150 | message ClientRollback{ 151 | string destination = 1; 152 | string client_id = 2; 153 | int64 batch_id = 3; 154 | } -------------------------------------------------------------------------------- /src/protocol/Com/Alibaba/Otter/Canal/Protocol/EventType.php: -------------------------------------------------------------------------------- 1 | com.alibaba.otter.canal.protocol.EventType 13 | */ 14 | class EventType 15 | { 16 | /** 17 | * Generated from protobuf enum EVENTTYPECOMPATIBLEPROTO2 = 0; 18 | */ 19 | const EVENTTYPECOMPATIBLEPROTO2 = 0; 20 | /** 21 | * Generated from protobuf enum INSERT = 1; 22 | */ 23 | const INSERT = 1; 24 | /** 25 | * Generated from protobuf enum UPDATE = 2; 26 | */ 27 | const UPDATE = 2; 28 | /** 29 | * Generated from protobuf enum DELETE = 3; 30 | */ 31 | const DELETE = 3; 32 | /** 33 | * Generated from protobuf enum CREATE = 4; 34 | */ 35 | const CREATE = 4; 36 | /** 37 | * Generated from protobuf enum ALTER = 5; 38 | */ 39 | const ALTER = 5; 40 | /** 41 | * Generated from protobuf enum ERASE = 6; 42 | */ 43 | const ERASE = 6; 44 | /** 45 | * Generated from protobuf enum QUERY = 7; 46 | */ 47 | const QUERY = 7; 48 | /** 49 | * Generated from protobuf enum TRUNCATE = 8; 50 | */ 51 | const TRUNCATE = 8; 52 | /** 53 | * Generated from protobuf enum RENAME = 9; 54 | */ 55 | const RENAME = 9; 56 | /** 57 | **CREATE INDEX* 58 | * 59 | * Generated from protobuf enum CINDEX = 10; 60 | */ 61 | const CINDEX = 10; 62 | /** 63 | * Generated from protobuf enum DINDEX = 11; 64 | */ 65 | const DINDEX = 11; 66 | /** 67 | * Generated from protobuf enum GTID = 12; 68 | */ 69 | const GTID = 12; 70 | /** 71 | ** XA * 72 | * 73 | * Generated from protobuf enum XACOMMIT = 13; 74 | */ 75 | const XACOMMIT = 13; 76 | /** 77 | * Generated from protobuf enum XAROLLBACK = 14; 78 | */ 79 | const XAROLLBACK = 14; 80 | /** 81 | ** MASTER HEARTBEAT * 82 | * 83 | * Generated from protobuf enum MHEARTBEAT = 15; 84 | */ 85 | const MHEARTBEAT = 15; 86 | 87 | private static $valueToName = [ 88 | self::EVENTTYPECOMPATIBLEPROTO2 => 'EVENTTYPECOMPATIBLEPROTO2', 89 | self::INSERT => 'INSERT', 90 | self::UPDATE => 'UPDATE', 91 | self::DELETE => 'DELETE', 92 | self::CREATE => 'CREATE', 93 | self::ALTER => 'ALTER', 94 | self::ERASE => 'ERASE', 95 | self::QUERY => 'QUERY', 96 | self::TRUNCATE => 'TRUNCATE', 97 | self::RENAME => 'RENAME', 98 | self::CINDEX => 'CINDEX', 99 | self::DINDEX => 'DINDEX', 100 | self::GTID => 'GTID', 101 | self::XACOMMIT => 'XACOMMIT', 102 | self::XAROLLBACK => 'XAROLLBACK', 103 | self::MHEARTBEAT => 'MHEARTBEAT', 104 | ]; 105 | 106 | public static function name($value) 107 | { 108 | if (!isset(self::$valueToName[$value])) { 109 | throw new UnexpectedValueException(sprintf( 110 | 'Enum %s has no name defined for value %s', __CLASS__, $value)); 111 | } 112 | return self::$valueToName[$value]; 113 | } 114 | 115 | 116 | public static function value($name) 117 | { 118 | $const = __CLASS__ . '::' . strtoupper($name); 119 | if (!defined($const)) { 120 | throw new UnexpectedValueException(sprintf( 121 | 'Enum %s has no value defined for name %s', __CLASS__, $name)); 122 | } 123 | return constant($const); 124 | } 125 | } 126 | 127 | -------------------------------------------------------------------------------- /src/protocol/Com/Alibaba/Otter/Canal/Protocol/Entry.php: -------------------------------------------------------------------------------- 1 | com.alibaba.otter.canal.protocol.Entry 18 | */ 19 | final class Entry extends \Google\Protobuf\Internal\Message 20 | { 21 | /** 22 | **协议头部信息* 23 | * 24 | * Generated from protobuf field .com.alibaba.otter.canal.protocol.Header header = 1; 25 | */ 26 | private $header = null; 27 | /** 28 | **传输的二进制数组* 29 | * 30 | * Generated from protobuf field bytes storeValue = 3; 31 | */ 32 | private $storeValue = ''; 33 | protected $entryType_present; 34 | 35 | /** 36 | * Constructor. 37 | * 38 | * @param array $data { 39 | * Optional. Data for populating the Message object. 40 | * 41 | * @type \Com\Alibaba\Otter\Canal\Protocol\Header $header 42 | * *协议头部信息* 43 | * @type int $entryType 44 | * @type string $storeValue 45 | * *传输的二进制数组* 46 | * } 47 | */ 48 | public function __construct($data = NULL) { 49 | \GPBMetadata\EntryProtocol::initOnce(); 50 | parent::__construct($data); 51 | } 52 | 53 | /** 54 | **协议头部信息* 55 | * 56 | * Generated from protobuf field .com.alibaba.otter.canal.protocol.Header header = 1; 57 | * @return \Com\Alibaba\Otter\Canal\Protocol\Header 58 | */ 59 | public function getHeader() 60 | { 61 | return $this->header; 62 | } 63 | 64 | /** 65 | **协议头部信息* 66 | * 67 | * Generated from protobuf field .com.alibaba.otter.canal.protocol.Header header = 1; 68 | * @param \Com\Alibaba\Otter\Canal\Protocol\Header $var 69 | * @return $this 70 | */ 71 | public function setHeader($var) 72 | { 73 | GPBUtil::checkMessage($var, \Com\Alibaba\Otter\Canal\Protocol\Header::class); 74 | $this->header = $var; 75 | 76 | return $this; 77 | } 78 | 79 | /** 80 | * Generated from protobuf field .com.alibaba.otter.canal.protocol.EntryType entryType = 2; 81 | * @return int 82 | */ 83 | public function getEntryType() 84 | { 85 | return $this->readOneof(2); 86 | } 87 | 88 | /** 89 | * Generated from protobuf field .com.alibaba.otter.canal.protocol.EntryType entryType = 2; 90 | * @param int $var 91 | * @return $this 92 | */ 93 | public function setEntryType($var) 94 | { 95 | GPBUtil::checkEnum($var, \Com\Alibaba\Otter\Canal\Protocol\EntryType::class); 96 | $this->writeOneof(2, $var); 97 | 98 | return $this; 99 | } 100 | 101 | /** 102 | **传输的二进制数组* 103 | * 104 | * Generated from protobuf field bytes storeValue = 3; 105 | * @return string 106 | */ 107 | public function getStoreValue() 108 | { 109 | return $this->storeValue; 110 | } 111 | 112 | /** 113 | **传输的二进制数组* 114 | * 115 | * Generated from protobuf field bytes storeValue = 3; 116 | * @param string $var 117 | * @return $this 118 | */ 119 | public function setStoreValue($var) 120 | { 121 | GPBUtil::checkString($var, False); 122 | $this->storeValue = $var; 123 | 124 | return $this; 125 | } 126 | 127 | /** 128 | * @return string 129 | */ 130 | public function getEntryTypePresent() 131 | { 132 | return $this->whichOneof("entryType_present"); 133 | } 134 | 135 | } 136 | 137 | -------------------------------------------------------------------------------- /src/protocol/Com/Alibaba/Otter/Canal/Protocol/TransactionEnd.php: -------------------------------------------------------------------------------- 1 | com.alibaba.otter.canal.protocol.TransactionEnd 15 | */ 16 | final class TransactionEnd extends \Google\Protobuf\Internal\Message 17 | { 18 | /** 19 | **已废弃,请使用header里的executeTime* 20 | * 21 | * Generated from protobuf field int64 executeTime = 1; 22 | */ 23 | private $executeTime = 0; 24 | /** 25 | **事务号* 26 | * 27 | * Generated from protobuf field string transactionId = 2; 28 | */ 29 | private $transactionId = ''; 30 | /** 31 | **预留扩展* 32 | * 33 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.Pair props = 3; 34 | */ 35 | private $props; 36 | 37 | /** 38 | * Constructor. 39 | * 40 | * @param array $data { 41 | * Optional. Data for populating the Message object. 42 | * 43 | * @type int|string $executeTime 44 | * *已废弃,请使用header里的executeTime* 45 | * @type string $transactionId 46 | * *事务号* 47 | * @type \Com\Alibaba\Otter\Canal\Protocol\Pair[]|\Google\Protobuf\Internal\RepeatedField $props 48 | * *预留扩展* 49 | * } 50 | */ 51 | public function __construct($data = NULL) { 52 | \GPBMetadata\EntryProtocol::initOnce(); 53 | parent::__construct($data); 54 | } 55 | 56 | /** 57 | **已废弃,请使用header里的executeTime* 58 | * 59 | * Generated from protobuf field int64 executeTime = 1; 60 | * @return int|string 61 | */ 62 | public function getExecuteTime() 63 | { 64 | return $this->executeTime; 65 | } 66 | 67 | /** 68 | **已废弃,请使用header里的executeTime* 69 | * 70 | * Generated from protobuf field int64 executeTime = 1; 71 | * @param int|string $var 72 | * @return $this 73 | */ 74 | public function setExecuteTime($var) 75 | { 76 | GPBUtil::checkInt64($var); 77 | $this->executeTime = $var; 78 | 79 | return $this; 80 | } 81 | 82 | /** 83 | **事务号* 84 | * 85 | * Generated from protobuf field string transactionId = 2; 86 | * @return string 87 | */ 88 | public function getTransactionId() 89 | { 90 | return $this->transactionId; 91 | } 92 | 93 | /** 94 | **事务号* 95 | * 96 | * Generated from protobuf field string transactionId = 2; 97 | * @param string $var 98 | * @return $this 99 | */ 100 | public function setTransactionId($var) 101 | { 102 | GPBUtil::checkString($var, True); 103 | $this->transactionId = $var; 104 | 105 | return $this; 106 | } 107 | 108 | /** 109 | **预留扩展* 110 | * 111 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.Pair props = 3; 112 | * @return \Google\Protobuf\Internal\RepeatedField 113 | */ 114 | public function getProps() 115 | { 116 | return $this->props; 117 | } 118 | 119 | /** 120 | **预留扩展* 121 | * 122 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.Pair props = 3; 123 | * @param \Com\Alibaba\Otter\Canal\Protocol\Pair[]|\Google\Protobuf\Internal\RepeatedField $var 124 | * @return $this 125 | */ 126 | public function setProps($var) 127 | { 128 | $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Com\Alibaba\Otter\Canal\Protocol\Pair::class); 129 | $this->props = $arr; 130 | 131 | return $this; 132 | } 133 | 134 | } 135 | 136 | -------------------------------------------------------------------------------- /src/protocol/Com/Alibaba/Otter/Canal/Protocol/RowData.php: -------------------------------------------------------------------------------- 1 | com.alibaba.otter.canal.protocol.RowData 13 | */ 14 | final class RowData extends \Google\Protobuf\Internal\Message 15 | { 16 | /** 17 | ** 字段信息,增量数据(修改前,删除前) * 18 | * 19 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.Column beforeColumns = 1; 20 | */ 21 | private $beforeColumns; 22 | /** 23 | ** 字段信息,增量数据(修改后,新增后) * 24 | * 25 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.Column afterColumns = 2; 26 | */ 27 | private $afterColumns; 28 | /** 29 | **预留扩展* 30 | * 31 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.Pair props = 3; 32 | */ 33 | private $props; 34 | 35 | /** 36 | * Constructor. 37 | * 38 | * @param array $data { 39 | * Optional. Data for populating the Message object. 40 | * 41 | * @type \Com\Alibaba\Otter\Canal\Protocol\Column[]|\Google\Protobuf\Internal\RepeatedField $beforeColumns 42 | * * 字段信息,增量数据(修改前,删除前) * 43 | * @type \Com\Alibaba\Otter\Canal\Protocol\Column[]|\Google\Protobuf\Internal\RepeatedField $afterColumns 44 | * * 字段信息,增量数据(修改后,新增后) * 45 | * @type \Com\Alibaba\Otter\Canal\Protocol\Pair[]|\Google\Protobuf\Internal\RepeatedField $props 46 | * *预留扩展* 47 | * } 48 | */ 49 | public function __construct($data = NULL) { 50 | \GPBMetadata\EntryProtocol::initOnce(); 51 | parent::__construct($data); 52 | } 53 | 54 | /** 55 | ** 字段信息,增量数据(修改前,删除前) * 56 | * 57 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.Column beforeColumns = 1; 58 | * @return \Google\Protobuf\Internal\RepeatedField 59 | */ 60 | public function getBeforeColumns() 61 | { 62 | return $this->beforeColumns; 63 | } 64 | 65 | /** 66 | ** 字段信息,增量数据(修改前,删除前) * 67 | * 68 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.Column beforeColumns = 1; 69 | * @param \Com\Alibaba\Otter\Canal\Protocol\Column[]|\Google\Protobuf\Internal\RepeatedField $var 70 | * @return $this 71 | */ 72 | public function setBeforeColumns($var) 73 | { 74 | $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Com\Alibaba\Otter\Canal\Protocol\Column::class); 75 | $this->beforeColumns = $arr; 76 | 77 | return $this; 78 | } 79 | 80 | /** 81 | ** 字段信息,增量数据(修改后,新增后) * 82 | * 83 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.Column afterColumns = 2; 84 | * @return \Google\Protobuf\Internal\RepeatedField 85 | */ 86 | public function getAfterColumns() 87 | { 88 | return $this->afterColumns; 89 | } 90 | 91 | /** 92 | ** 字段信息,增量数据(修改后,新增后) * 93 | * 94 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.Column afterColumns = 2; 95 | * @param \Com\Alibaba\Otter\Canal\Protocol\Column[]|\Google\Protobuf\Internal\RepeatedField $var 96 | * @return $this 97 | */ 98 | public function setAfterColumns($var) 99 | { 100 | $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Com\Alibaba\Otter\Canal\Protocol\Column::class); 101 | $this->afterColumns = $arr; 102 | 103 | return $this; 104 | } 105 | 106 | /** 107 | **预留扩展* 108 | * 109 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.Pair props = 3; 110 | * @return \Google\Protobuf\Internal\RepeatedField 111 | */ 112 | public function getProps() 113 | { 114 | return $this->props; 115 | } 116 | 117 | /** 118 | **预留扩展* 119 | * 120 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.Pair props = 3; 121 | * @param \Com\Alibaba\Otter\Canal\Protocol\Pair[]|\Google\Protobuf\Internal\RepeatedField $var 122 | * @return $this 123 | */ 124 | public function setProps($var) 125 | { 126 | $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Com\Alibaba\Otter\Canal\Protocol\Pair::class); 127 | $this->props = $arr; 128 | 129 | return $this; 130 | } 131 | 132 | } 133 | 134 | -------------------------------------------------------------------------------- /src/protocol/Com/Alibaba/Otter/Canal/Protocol/TransactionBegin.php: -------------------------------------------------------------------------------- 1 | com.alibaba.otter.canal.protocol.TransactionBegin 15 | */ 16 | final class TransactionBegin extends \Google\Protobuf\Internal\Message 17 | { 18 | /** 19 | **已废弃,请使用header里的executeTime* 20 | * 21 | * Generated from protobuf field int64 executeTime = 1; 22 | */ 23 | private $executeTime = 0; 24 | /** 25 | **已废弃,Begin里不提供事务id* 26 | * 27 | * Generated from protobuf field string transactionId = 2; 28 | */ 29 | private $transactionId = ''; 30 | /** 31 | **预留扩展* 32 | * 33 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.Pair props = 3; 34 | */ 35 | private $props; 36 | /** 37 | **执行的thread Id* 38 | * 39 | * Generated from protobuf field int64 threadId = 4; 40 | */ 41 | private $threadId = 0; 42 | 43 | /** 44 | * Constructor. 45 | * 46 | * @param array $data { 47 | * Optional. Data for populating the Message object. 48 | * 49 | * @type int|string $executeTime 50 | * *已废弃,请使用header里的executeTime* 51 | * @type string $transactionId 52 | * *已废弃,Begin里不提供事务id* 53 | * @type \Com\Alibaba\Otter\Canal\Protocol\Pair[]|\Google\Protobuf\Internal\RepeatedField $props 54 | * *预留扩展* 55 | * @type int|string $threadId 56 | * *执行的thread Id* 57 | * } 58 | */ 59 | public function __construct($data = NULL) { 60 | \GPBMetadata\EntryProtocol::initOnce(); 61 | parent::__construct($data); 62 | } 63 | 64 | /** 65 | **已废弃,请使用header里的executeTime* 66 | * 67 | * Generated from protobuf field int64 executeTime = 1; 68 | * @return int|string 69 | */ 70 | public function getExecuteTime() 71 | { 72 | return $this->executeTime; 73 | } 74 | 75 | /** 76 | **已废弃,请使用header里的executeTime* 77 | * 78 | * Generated from protobuf field int64 executeTime = 1; 79 | * @param int|string $var 80 | * @return $this 81 | */ 82 | public function setExecuteTime($var) 83 | { 84 | GPBUtil::checkInt64($var); 85 | $this->executeTime = $var; 86 | 87 | return $this; 88 | } 89 | 90 | /** 91 | **已废弃,Begin里不提供事务id* 92 | * 93 | * Generated from protobuf field string transactionId = 2; 94 | * @return string 95 | */ 96 | public function getTransactionId() 97 | { 98 | return $this->transactionId; 99 | } 100 | 101 | /** 102 | **已废弃,Begin里不提供事务id* 103 | * 104 | * Generated from protobuf field string transactionId = 2; 105 | * @param string $var 106 | * @return $this 107 | */ 108 | public function setTransactionId($var) 109 | { 110 | GPBUtil::checkString($var, True); 111 | $this->transactionId = $var; 112 | 113 | return $this; 114 | } 115 | 116 | /** 117 | **预留扩展* 118 | * 119 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.Pair props = 3; 120 | * @return \Google\Protobuf\Internal\RepeatedField 121 | */ 122 | public function getProps() 123 | { 124 | return $this->props; 125 | } 126 | 127 | /** 128 | **预留扩展* 129 | * 130 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.Pair props = 3; 131 | * @param \Com\Alibaba\Otter\Canal\Protocol\Pair[]|\Google\Protobuf\Internal\RepeatedField $var 132 | * @return $this 133 | */ 134 | public function setProps($var) 135 | { 136 | $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Com\Alibaba\Otter\Canal\Protocol\Pair::class); 137 | $this->props = $arr; 138 | 139 | return $this; 140 | } 141 | 142 | /** 143 | **执行的thread Id* 144 | * 145 | * Generated from protobuf field int64 threadId = 4; 146 | * @return int|string 147 | */ 148 | public function getThreadId() 149 | { 150 | return $this->threadId; 151 | } 152 | 153 | /** 154 | **执行的thread Id* 155 | * 156 | * Generated from protobuf field int64 threadId = 4; 157 | * @param int|string $var 158 | * @return $this 159 | */ 160 | public function setThreadId($var) 161 | { 162 | GPBUtil::checkInt64($var); 163 | $this->threadId = $var; 164 | 165 | return $this; 166 | } 167 | 168 | } 169 | 170 | -------------------------------------------------------------------------------- /src/protocol/Com/Alibaba/Otter/Canal/Protocol/Packet.php: -------------------------------------------------------------------------------- 1 | com.alibaba.otter.canal.protocol.Packet 13 | */ 14 | final class Packet extends \Google\Protobuf\Internal\Message 15 | { 16 | /** 17 | * Generated from protobuf field .com.alibaba.otter.canal.protocol.PacketType type = 3; 18 | */ 19 | private $type = 0; 20 | /** 21 | * Generated from protobuf field bytes body = 5; 22 | */ 23 | private $body = ''; 24 | protected $magic_number_present; 25 | protected $version_present; 26 | protected $compression_present; 27 | 28 | /** 29 | * Constructor. 30 | * 31 | * @param array $data { 32 | * Optional. Data for populating the Message object. 33 | * 34 | * @type int $magic_number 35 | * @type int $version 36 | * @type int $type 37 | * @type int $compression 38 | * @type string $body 39 | * } 40 | */ 41 | public function __construct($data = NULL) { 42 | \GPBMetadata\CanalProtocol::initOnce(); 43 | parent::__construct($data); 44 | } 45 | 46 | /** 47 | * Generated from protobuf field int32 magic_number = 1; 48 | * @return int 49 | */ 50 | public function getMagicNumber() 51 | { 52 | return $this->readOneof(1); 53 | } 54 | 55 | /** 56 | * Generated from protobuf field int32 magic_number = 1; 57 | * @param int $var 58 | * @return $this 59 | */ 60 | public function setMagicNumber($var) 61 | { 62 | GPBUtil::checkInt32($var); 63 | $this->writeOneof(1, $var); 64 | 65 | return $this; 66 | } 67 | 68 | /** 69 | * Generated from protobuf field int32 version = 2; 70 | * @return int 71 | */ 72 | public function getVersion() 73 | { 74 | return $this->readOneof(2); 75 | } 76 | 77 | /** 78 | * Generated from protobuf field int32 version = 2; 79 | * @param int $var 80 | * @return $this 81 | */ 82 | public function setVersion($var) 83 | { 84 | GPBUtil::checkInt32($var); 85 | $this->writeOneof(2, $var); 86 | 87 | return $this; 88 | } 89 | 90 | /** 91 | * Generated from protobuf field .com.alibaba.otter.canal.protocol.PacketType type = 3; 92 | * @return int 93 | */ 94 | public function getType() 95 | { 96 | return $this->type; 97 | } 98 | 99 | /** 100 | * Generated from protobuf field .com.alibaba.otter.canal.protocol.PacketType type = 3; 101 | * @param int $var 102 | * @return $this 103 | */ 104 | public function setType($var) 105 | { 106 | GPBUtil::checkEnum($var, \Com\Alibaba\Otter\Canal\Protocol\PacketType::class); 107 | $this->type = $var; 108 | 109 | return $this; 110 | } 111 | 112 | /** 113 | * Generated from protobuf field .com.alibaba.otter.canal.protocol.Compression compression = 4; 114 | * @return int 115 | */ 116 | public function getCompression() 117 | { 118 | return $this->readOneof(4); 119 | } 120 | 121 | /** 122 | * Generated from protobuf field .com.alibaba.otter.canal.protocol.Compression compression = 4; 123 | * @param int $var 124 | * @return $this 125 | */ 126 | public function setCompression($var) 127 | { 128 | GPBUtil::checkEnum($var, \Com\Alibaba\Otter\Canal\Protocol\Compression::class); 129 | $this->writeOneof(4, $var); 130 | 131 | return $this; 132 | } 133 | 134 | /** 135 | * Generated from protobuf field bytes body = 5; 136 | * @return string 137 | */ 138 | public function getBody() 139 | { 140 | return $this->body; 141 | } 142 | 143 | /** 144 | * Generated from protobuf field bytes body = 5; 145 | * @param string $var 146 | * @return $this 147 | */ 148 | public function setBody($var) 149 | { 150 | GPBUtil::checkString($var, False); 151 | $this->body = $var; 152 | 153 | return $this; 154 | } 155 | 156 | /** 157 | * @return string 158 | */ 159 | public function getMagicNumberPresent() 160 | { 161 | return $this->whichOneof("magic_number_present"); 162 | } 163 | 164 | /** 165 | * @return string 166 | */ 167 | public function getVersionPresent() 168 | { 169 | return $this->whichOneof("version_present"); 170 | } 171 | 172 | /** 173 | * @return string 174 | */ 175 | public function getCompressionPresent() 176 | { 177 | return $this->whichOneof("compression_present"); 178 | } 179 | 180 | } 181 | 182 | -------------------------------------------------------------------------------- /src/protocol/EntryProtocol.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package com.alibaba.otter.canal.protocol; 3 | 4 | option java_package = "com.alibaba.otter.canal.protocol"; 5 | option java_outer_classname = "CanalEntry"; 6 | option optimize_for = SPEED; 7 | 8 | /**************************************************************** 9 | * message model 10 | *如果要在Enum中新增类型,确保以前的类型的下标值不变. 11 | ****************************************************************/ 12 | message Entry { 13 | /**协议头部信息**/ 14 | Header header = 1; 15 | ///**打散后的事件类型**/ [default = ROWDATA] 16 | oneof entryType_present{ 17 | EntryType entryType = 2; 18 | } 19 | 20 | /**传输的二进制数组**/ 21 | bytes storeValue = 3; 22 | } 23 | 24 | /**message Header**/ 25 | message Header { 26 | /**协议的版本号**/ //[default = 1] 27 | oneof version_present { 28 | int32 version = 1; 29 | } 30 | 31 | 32 | /**binlog/redolog 文件名**/ 33 | string logfileName = 2; 34 | 35 | /**binlog/redolog 文件的偏移位置**/ 36 | int64 logfileOffset = 3; 37 | 38 | /**服务端serverId**/ 39 | int64 serverId = 4; 40 | 41 | /** 变更数据的编码 **/ 42 | string serverenCode = 5; 43 | 44 | /**变更数据的执行时间 **/ 45 | int64 executeTime = 6; 46 | 47 | /** 变更数据的来源**/ //[default = MYSQL] 48 | oneof sourceType_present { 49 | Type sourceType = 7; 50 | } 51 | 52 | 53 | /** 变更数据的schemaname**/ 54 | string schemaName = 8; 55 | 56 | /**变更数据的tablename**/ 57 | string tableName = 9; 58 | 59 | /**每个event的长度**/ 60 | int64 eventLength = 10; 61 | 62 | /**数据变更类型**/ // [default = UPDATE] 63 | oneof eventType_present { 64 | EventType eventType = 11; 65 | } 66 | 67 | 68 | /**预留扩展**/ 69 | repeated Pair props = 12; 70 | 71 | /**当前事务的gitd**/ 72 | string gtid = 13; 73 | } 74 | 75 | /**每个字段的数据结构**/ 76 | message Column { 77 | /**字段下标**/ 78 | int32 index = 1; 79 | 80 | /**字段java中类型**/ 81 | int32 sqlType = 2; 82 | 83 | /**字段名称(忽略大小写),在mysql中是没有的**/ 84 | string name = 3; 85 | 86 | /**是否是主键**/ 87 | bool isKey = 4; 88 | 89 | /**如果EventType=UPDATE,用于标识这个字段值是否有修改**/ 90 | bool updated = 5; 91 | 92 | /** 标识是否为空 **/ //[default = false] 93 | oneof isNull_present { 94 | bool isNull = 6; 95 | } 96 | 97 | 98 | /**预留扩展**/ 99 | repeated Pair props = 7; 100 | 101 | /** 字段值,timestamp,Datetime是一个时间格式的文本 **/ 102 | string value = 8; 103 | 104 | /** 对应数据对象原始长度 **/ 105 | int32 length = 9; 106 | 107 | /**字段mysql类型**/ 108 | string mysqlType = 10; 109 | } 110 | 111 | message RowData { 112 | 113 | /** 字段信息,增量数据(修改前,删除前) **/ 114 | repeated Column beforeColumns = 1; 115 | 116 | /** 字段信息,增量数据(修改后,新增后) **/ 117 | repeated Column afterColumns = 2; 118 | 119 | /**预留扩展**/ 120 | repeated Pair props = 3; 121 | } 122 | 123 | /**message row 每行变更数据的数据结构**/ 124 | message RowChange { 125 | 126 | /**tableId,由数据库产生**/ 127 | int64 tableId = 1; 128 | 129 | 130 | /**数据变更类型**/ //[default = UPDATE] 131 | oneof eventType_present { 132 | EventType eventType = 2; 133 | } 134 | 135 | 136 | /** 标识是否是ddl语句 **/ // [default = false] 137 | oneof isDdl_present { 138 | bool isDdl = 10; 139 | } 140 | 141 | 142 | /** ddl/query的sql语句 **/ 143 | string sql = 11; 144 | 145 | /** 一次数据库变更可能存在多行 **/ 146 | repeated RowData rowDatas = 12; 147 | 148 | /**预留扩展**/ 149 | repeated Pair props = 13; 150 | 151 | /** ddl/query的schemaName,会存在跨库ddl,需要保留执行ddl的当前schemaName **/ 152 | string ddlSchemaName = 14; 153 | } 154 | 155 | /**开始事务的一些信息**/ 156 | message TransactionBegin{ 157 | 158 | /**已废弃,请使用header里的executeTime**/ 159 | int64 executeTime = 1; 160 | 161 | /**已废弃,Begin里不提供事务id**/ 162 | string transactionId = 2; 163 | 164 | /**预留扩展**/ 165 | repeated Pair props = 3; 166 | 167 | /**执行的thread Id**/ 168 | int64 threadId = 4; 169 | } 170 | 171 | /**结束事务的一些信息**/ 172 | message TransactionEnd{ 173 | 174 | /**已废弃,请使用header里的executeTime**/ 175 | int64 executeTime = 1; 176 | 177 | /**事务号**/ 178 | string transactionId = 2; 179 | 180 | /**预留扩展**/ 181 | repeated Pair props = 3; 182 | } 183 | 184 | /**预留扩展**/ 185 | message Pair{ 186 | string key = 1; 187 | string value = 2; 188 | } 189 | 190 | /**打散后的事件类型,主要用于标识事务的开始,变更数据,结束**/ 191 | enum EntryType{ 192 | ENTRYTYPECOMPATIBLEPROTO2 = 0; 193 | TRANSACTIONBEGIN = 1; 194 | ROWDATA = 2; 195 | TRANSACTIONEND = 3; 196 | /** 心跳类型,内部使用,外部暂不可见,可忽略 **/ 197 | HEARTBEAT = 4; 198 | GTIDLOG = 5; 199 | } 200 | 201 | /** 事件类型 **/ 202 | enum EventType { 203 | EVENTTYPECOMPATIBLEPROTO2 = 0; 204 | INSERT = 1; 205 | UPDATE = 2; 206 | DELETE = 3; 207 | CREATE = 4; 208 | ALTER = 5; 209 | ERASE = 6; 210 | QUERY = 7; 211 | TRUNCATE = 8; 212 | RENAME = 9; 213 | /**CREATE INDEX**/ 214 | CINDEX = 10; 215 | DINDEX = 11; 216 | GTID = 12; 217 | /** XA **/ 218 | XACOMMIT = 13; 219 | XAROLLBACK = 14; 220 | /** MASTER HEARTBEAT **/ 221 | MHEARTBEAT = 15; 222 | } 223 | 224 | /**数据库类型**/ 225 | enum Type { 226 | TYPECOMPATIBLEPROTO2 = 0; 227 | ORACLE = 1; 228 | MYSQL = 2; 229 | PGSQL = 3; 230 | } -------------------------------------------------------------------------------- /src/protocol/GPBMetadata/CanalProtocol.php: -------------------------------------------------------------------------------- 1 | internalAddGeneratedFile(hex2bin( 18 | "0ab20e0a1343616e616c50726f746f636f6c2e70726f746f1220636f6d2e" . 19 | "616c69626162612e6f747465722e63616e616c2e70726f746f636f6c2285" . 20 | "020a065061636b657412160a0c6d616769635f6e756d6265721801200128" . 21 | "05480012110a0776657273696f6e1802200128054801123a0a0474797065" . 22 | "18032001280e322c2e636f6d2e616c69626162612e6f747465722e63616e" . 23 | "616c2e70726f746f636f6c2e5061636b65745479706512440a0b636f6d70" . 24 | "72657373696f6e18042001280e322d2e636f6d2e616c69626162612e6f74" . 25 | "7465722e63616e616c2e70726f746f636f6c2e436f6d7072657373696f6e" . 26 | "4802120c0a04626f647918052001280c42160a146d616769635f6e756d62" . 27 | "65725f70726573656e7442110a0f76657273696f6e5f70726573656e7442" . 28 | "150a13636f6d7072657373696f6e5f70726573656e74223c0a0948656172" . 29 | "744265617412160a0e73656e645f74696d657374616d7018012001280312" . 30 | "170a0f73746172745f74696d657374616d7018022001280322ad010a0948" . 31 | "616e647368616b6512200a16636f6d6d756e69636174696f6e5f656e636f" . 32 | "64696e671801200128094800120d0a05736565647318022001280c124d0a" . 33 | "16737570706f727465645f636f6d7072657373696f6e7318032001280e32" . 34 | "2d2e636f6d2e616c69626162612e6f747465722e63616e616c2e70726f74" . 35 | "6f636f6c2e436f6d7072657373696f6e42200a1e636f6d6d756e69636174" . 36 | "696f6e5f656e636f64696e675f70726573656e7422f3010a0a436c69656e" . 37 | "744175746812100a08757365726e616d6518012001280912100a08706173" . 38 | "73776f726418022001280c121a0a106e65745f726561645f74696d656f75" . 39 | "741803200128054800121b0a116e65745f77726974655f74696d656f7574" . 40 | "180420012805480112130a0b64657374696e6174696f6e18052001280912" . 41 | "110a09636c69656e745f6964180620012809120e0a0666696c7465721807" . 42 | "2001280912170a0f73746172745f74696d657374616d7018082001280342" . 43 | "1a0a186e65745f726561645f74696d656f75745f70726573656e74421b0a" . 44 | "196e65745f77726974655f74696d656f75745f70726573656e7422480a03" . 45 | "41636b12140a0a6572726f725f636f6465180120012805480012150a0d65" . 46 | "72726f725f6d65737361676518022001280942140a126572726f725f636f" . 47 | "64655f70726573656e7422450a09436c69656e7441636b12130a0b646573" . 48 | "74696e6174696f6e18012001280912110a09636c69656e745f6964180220" . 49 | "01280912100a0862617463685f6964180320012803223d0a035375621213" . 50 | "0a0b64657374696e6174696f6e18012001280912110a09636c69656e745f" . 51 | "6964180220012809120e0a0666696c746572180720012809223f0a05556e" . 52 | "73756212130a0b64657374696e6174696f6e18012001280912110a09636c" . 53 | "69656e745f6964180220012809120e0a0666696c74657218072001280922" . 54 | "af010a0347657412130a0b64657374696e6174696f6e1801200128091211" . 55 | "0a09636c69656e745f696418022001280912120a0a66657463685f73697a" . 56 | "6518032001280512110a0774696d656f75741804200128034800120e0a04" . 57 | "756e6974180520012805480112120a086175746f5f61636b180620012808" . 58 | "480242110a0f74696d656f75745f70726573656e74420e0a0c756e69745f" . 59 | "70726573656e7442120a106175746f5f61636b5f70726573656e74222e0a" . 60 | "084d6573736167657312100a0862617463685f696418012001280312100a" . 61 | "086d6573736167657318022003280c22530a0444756d70120f0a076a6f75" . 62 | "726e616c18012001280912100a08706f736974696f6e1802200128031213" . 63 | "0a0974696d657374616d70180320012803480042130a1174696d65737461" . 64 | "6d705f70726573656e74224a0a0e436c69656e74526f6c6c6261636b1213" . 65 | "0a0b64657374696e6174696f6e18012001280912110a09636c69656e745f" . 66 | "696418022001280912100a0862617463685f69641803200128032a550a0b" . 67 | "436f6d7072657373696f6e121f0a1b434f4d5052455353494f4e434f4d50" . 68 | "415449424c4550524f544f32100012080a044e4f4e45100112080a045a4c" . 69 | "4942100212080a04475a4950100312070a034c5a4610042ae6010a0a5061" . 70 | "636b657454797065121f0a1b5041434b41474554595045434f4d50415449" . 71 | "424c4550524f544f321000120d0a0948414e445348414b45100112180a14" . 72 | "434c49454e5441555448454e5449434154494f4e100212070a0341434b10" . 73 | "0312100a0c535542534352495054494f4e100412120a0e554e5355425343" . 74 | "52495054494f4e100512070a034745541006120c0a084d45535341474553" . 75 | "1007120d0a09434c49454e5441434b1008120c0a0853485554444f574e10" . 76 | "0912080a0444554d50100a120d0a09484541525442454154100b12120a0e" . 77 | "434c49454e54524f4c4c4241434b100c42310a20636f6d2e616c69626162" . 78 | "612e6f747465722e63616e616c2e70726f746f636f6c420b43616e616c50" . 79 | "61636b65744801620670726f746f33" 80 | ), true); 81 | 82 | static::$is_initialized = true; 83 | } 84 | } 85 | 86 | -------------------------------------------------------------------------------- /src/protocol/Com/Alibaba/Otter/Canal/Protocol/Get.php: -------------------------------------------------------------------------------- 1 | com.alibaba.otter.canal.protocol.Get 15 | */ 16 | final class Get extends \Google\Protobuf\Internal\Message 17 | { 18 | /** 19 | * Generated from protobuf field string destination = 1; 20 | */ 21 | private $destination = ''; 22 | /** 23 | * Generated from protobuf field string client_id = 2; 24 | */ 25 | private $client_id = ''; 26 | /** 27 | * Generated from protobuf field int32 fetch_size = 3; 28 | */ 29 | private $fetch_size = 0; 30 | protected $timeout_present; 31 | protected $unit_present; 32 | protected $auto_ack_present; 33 | 34 | /** 35 | * Constructor. 36 | * 37 | * @param array $data { 38 | * Optional. Data for populating the Message object. 39 | * 40 | * @type string $destination 41 | * @type string $client_id 42 | * @type int $fetch_size 43 | * @type int|string $timeout 44 | * 默认-1时代表不控制 45 | * @type int $unit 46 | * 数字类型,0:纳秒,1:毫秒,2:微秒,3:秒,4:分钟,5:小时,6:天 47 | * @type bool $auto_ack 48 | * 是否自动ack 49 | * } 50 | */ 51 | public function __construct($data = NULL) { 52 | \GPBMetadata\CanalProtocol::initOnce(); 53 | parent::__construct($data); 54 | } 55 | 56 | /** 57 | * Generated from protobuf field string destination = 1; 58 | * @return string 59 | */ 60 | public function getDestination() 61 | { 62 | return $this->destination; 63 | } 64 | 65 | /** 66 | * Generated from protobuf field string destination = 1; 67 | * @param string $var 68 | * @return $this 69 | */ 70 | public function setDestination($var) 71 | { 72 | GPBUtil::checkString($var, True); 73 | $this->destination = $var; 74 | 75 | return $this; 76 | } 77 | 78 | /** 79 | * Generated from protobuf field string client_id = 2; 80 | * @return string 81 | */ 82 | public function getClientId() 83 | { 84 | return $this->client_id; 85 | } 86 | 87 | /** 88 | * Generated from protobuf field string client_id = 2; 89 | * @param string $var 90 | * @return $this 91 | */ 92 | public function setClientId($var) 93 | { 94 | GPBUtil::checkString($var, True); 95 | $this->client_id = $var; 96 | 97 | return $this; 98 | } 99 | 100 | /** 101 | * Generated from protobuf field int32 fetch_size = 3; 102 | * @return int 103 | */ 104 | public function getFetchSize() 105 | { 106 | return $this->fetch_size; 107 | } 108 | 109 | /** 110 | * Generated from protobuf field int32 fetch_size = 3; 111 | * @param int $var 112 | * @return $this 113 | */ 114 | public function setFetchSize($var) 115 | { 116 | GPBUtil::checkInt32($var); 117 | $this->fetch_size = $var; 118 | 119 | return $this; 120 | } 121 | 122 | /** 123 | * 默认-1时代表不控制 124 | * 125 | * Generated from protobuf field int64 timeout = 4; 126 | * @return int|string 127 | */ 128 | public function getTimeout() 129 | { 130 | return $this->readOneof(4); 131 | } 132 | 133 | /** 134 | * 默认-1时代表不控制 135 | * 136 | * Generated from protobuf field int64 timeout = 4; 137 | * @param int|string $var 138 | * @return $this 139 | */ 140 | public function setTimeout($var) 141 | { 142 | GPBUtil::checkInt64($var); 143 | $this->writeOneof(4, $var); 144 | 145 | return $this; 146 | } 147 | 148 | /** 149 | * 数字类型,0:纳秒,1:毫秒,2:微秒,3:秒,4:分钟,5:小时,6:天 150 | * 151 | * Generated from protobuf field int32 unit = 5; 152 | * @return int 153 | */ 154 | public function getUnit() 155 | { 156 | return $this->readOneof(5); 157 | } 158 | 159 | /** 160 | * 数字类型,0:纳秒,1:毫秒,2:微秒,3:秒,4:分钟,5:小时,6:天 161 | * 162 | * Generated from protobuf field int32 unit = 5; 163 | * @param int $var 164 | * @return $this 165 | */ 166 | public function setUnit($var) 167 | { 168 | GPBUtil::checkInt32($var); 169 | $this->writeOneof(5, $var); 170 | 171 | return $this; 172 | } 173 | 174 | /** 175 | * 是否自动ack 176 | * 177 | * Generated from protobuf field bool auto_ack = 6; 178 | * @return bool 179 | */ 180 | public function getAutoAck() 181 | { 182 | return $this->readOneof(6); 183 | } 184 | 185 | /** 186 | * 是否自动ack 187 | * 188 | * Generated from protobuf field bool auto_ack = 6; 189 | * @param bool $var 190 | * @return $this 191 | */ 192 | public function setAutoAck($var) 193 | { 194 | GPBUtil::checkBool($var); 195 | $this->writeOneof(6, $var); 196 | 197 | return $this; 198 | } 199 | 200 | /** 201 | * @return string 202 | */ 203 | public function getTimeoutPresent() 204 | { 205 | return $this->whichOneof("timeout_present"); 206 | } 207 | 208 | /** 209 | * @return string 210 | */ 211 | public function getUnitPresent() 212 | { 213 | return $this->whichOneof("unit_present"); 214 | } 215 | 216 | /** 217 | * @return string 218 | */ 219 | public function getAutoAckPresent() 220 | { 221 | return $this->whichOneof("auto_ack_present"); 222 | } 223 | 224 | } 225 | 226 | -------------------------------------------------------------------------------- /src/protocol/GPBMetadata/EntryProtocol.php: -------------------------------------------------------------------------------- 1 | internalAddGeneratedFile(hex2bin( 18 | "0a8e110a13456e74727950726f746f636f6c2e70726f746f1220636f6d2e" . 19 | "616c69626162612e6f747465722e63616e616c2e70726f746f636f6c22ac" . 20 | "010a05456e74727912380a0668656164657218012001280b32282e636f6d" . 21 | "2e616c69626162612e6f747465722e63616e616c2e70726f746f636f6c2e" . 22 | "48656164657212400a09656e7472795479706518022001280e322b2e636f" . 23 | "6d2e616c69626162612e6f747465722e63616e616c2e70726f746f636f6c" . 24 | "2e456e74727954797065480012120a0a73746f726556616c756518032001" . 25 | "280c42130a11656e747279547970655f70726573656e7422c3030a064865" . 26 | "6164657212110a0776657273696f6e180120012805480012130a0b6c6f67" . 27 | "66696c654e616d6518022001280912150a0d6c6f6766696c654f66667365" . 28 | "7418032001280312100a08736572766572496418042001280312140a0c73" . 29 | "6572766572656e436f646518052001280912130a0b657865637574655469" . 30 | "6d65180620012803123c0a0a736f757263655479706518072001280e3226" . 31 | "2e636f6d2e616c69626162612e6f747465722e63616e616c2e70726f746f" . 32 | "636f6c2e54797065480112120a0a736368656d614e616d65180820012809" . 33 | "12110a097461626c654e616d6518092001280912130a0b6576656e744c65" . 34 | "6e677468180a2001280312400a096576656e7454797065180b2001280e32" . 35 | "2b2e636f6d2e616c69626162612e6f747465722e63616e616c2e70726f74" . 36 | "6f636f6c2e4576656e7454797065480212350a0570726f7073180c200328" . 37 | "0b32262e636f6d2e616c69626162612e6f747465722e63616e616c2e7072" . 38 | "6f746f636f6c2e50616972120c0a0467746964180d2001280942110a0f76" . 39 | "657273696f6e5f70726573656e7442140a12736f75726365547970655f70" . 40 | "726573656e7442130a116576656e74547970655f70726573656e7422e301" . 41 | "0a06436f6c756d6e120d0a05696e646578180120012805120f0a0773716c" . 42 | "54797065180220012805120c0a046e616d65180320012809120d0a056973" . 43 | "4b6579180420012808120f0a077570646174656418052001280812100a06" . 44 | "69734e756c6c180620012808480012350a0570726f707318072003280b32" . 45 | "262e636f6d2e616c69626162612e6f747465722e63616e616c2e70726f74" . 46 | "6f636f6c2e50616972120d0a0576616c7565180820012809120e0a066c65" . 47 | "6e67746818092001280512110a096d7973716c54797065180a2001280942" . 48 | "100a0e69734e756c6c5f70726573656e7422c1010a07526f774461746112" . 49 | "3f0a0d6265666f7265436f6c756d6e7318012003280b32282e636f6d2e61" . 50 | "6c69626162612e6f747465722e63616e616c2e70726f746f636f6c2e436f" . 51 | "6c756d6e123e0a0c6166746572436f6c756d6e7318022003280b32282e63" . 52 | "6f6d2e616c69626162612e6f747465722e63616e616c2e70726f746f636f" . 53 | "6c2e436f6c756d6e12350a0570726f707318032003280b32262e636f6d2e" . 54 | "616c69626162612e6f747465722e63616e616c2e70726f746f636f6c2e50" . 55 | "61697222ad020a09526f774368616e6765120f0a077461626c6549641801" . 56 | "2001280312400a096576656e745479706518022001280e322b2e636f6d2e" . 57 | "616c69626162612e6f747465722e63616e616c2e70726f746f636f6c2e45" . 58 | "76656e74547970654800120f0a05697344646c180a200128084801120b0a" . 59 | "0373716c180b20012809123b0a08726f774461746173180c2003280b3229" . 60 | "2e636f6d2e616c69626162612e6f747465722e63616e616c2e70726f746f" . 61 | "636f6c2e526f774461746112350a0570726f7073180d2003280b32262e63" . 62 | "6f6d2e616c69626162612e6f747465722e63616e616c2e70726f746f636f" . 63 | "6c2e5061697212150a0d64646c536368656d614e616d65180e2001280942" . 64 | "130a116576656e74547970655f70726573656e74420f0a0d697344646c5f" . 65 | "70726573656e742287010a105472616e73616374696f6e426567696e1213" . 66 | "0a0b6578656375746554696d6518012001280312150a0d7472616e736163" . 67 | "74696f6e496418022001280912350a0570726f707318032003280b32262e" . 68 | "636f6d2e616c69626162612e6f747465722e63616e616c2e70726f746f63" . 69 | "6f6c2e5061697212100a08746872656164496418042001280322730a0e54" . 70 | "72616e73616374696f6e456e6412130a0b6578656375746554696d651801" . 71 | "2001280312150a0d7472616e73616374696f6e496418022001280912350a" . 72 | "0570726f707318032003280b32262e636f6d2e616c69626162612e6f7474" . 73 | "65722e63616e616c2e70726f746f636f6c2e5061697222220a0450616972" . 74 | "120b0a036b6579180120012809120d0a0576616c75651802200128092a7d" . 75 | "0a09456e74727954797065121d0a19454e54525954595045434f4d504154" . 76 | "49424c4550524f544f32100012140a105452414e53414354494f4e424547" . 77 | "494e1001120b0a07524f5744415441100212120a0e5452414e5341435449" . 78 | "4f4e454e441003120d0a094845415254424541541004120b0a0747544944" . 79 | "4c4f4710052ae5010a094576656e7454797065121d0a194556454e545459" . 80 | "5045434f4d50415449424c4550524f544f321000120a0a06494e53455254" . 81 | "1001120a0a065550444154451002120a0a0644454c4554451003120a0a06" . 82 | "435245415445100412090a05414c544552100512090a0545524153451006" . 83 | "12090a0551554552591007120c0a085452554e434154451008120a0a0652" . 84 | "454e414d451009120a0a0643494e444558100a120a0a0644494e44455810" . 85 | "0b12080a0447544944100c120c0a085841434f4d4d4954100d120e0a0a58" . 86 | "41524f4c4c4241434b100e120e0a0a4d484541525442454154100f2a420a" . 87 | "045479706512180a1454595045434f4d50415449424c4550524f544f3210" . 88 | "00120a0a064f5241434c45100112090a054d5953514c100212090a055047" . 89 | "53514c100342300a20636f6d2e616c69626162612e6f747465722e63616e" . 90 | "616c2e70726f746f636f6c420a43616e616c456e7472794801620670726f" . 91 | "746f33" 92 | ), true); 93 | 94 | static::$is_initialized = true; 95 | } 96 | } 97 | 98 | -------------------------------------------------------------------------------- /src/protocol/Com/Alibaba/Otter/Canal/Protocol/ClientAuth.php: -------------------------------------------------------------------------------- 1 | com.alibaba.otter.canal.protocol.ClientAuth 15 | */ 16 | final class ClientAuth extends \Google\Protobuf\Internal\Message 17 | { 18 | /** 19 | * Generated from protobuf field string username = 1; 20 | */ 21 | private $username = ''; 22 | /** 23 | * hashed password with seeds from Handshake message 24 | * 25 | * Generated from protobuf field bytes password = 2; 26 | */ 27 | private $password = ''; 28 | /** 29 | * Generated from protobuf field string destination = 5; 30 | */ 31 | private $destination = ''; 32 | /** 33 | * Generated from protobuf field string client_id = 6; 34 | */ 35 | private $client_id = ''; 36 | /** 37 | * Generated from protobuf field string filter = 7; 38 | */ 39 | private $filter = ''; 40 | /** 41 | * Generated from protobuf field int64 start_timestamp = 8; 42 | */ 43 | private $start_timestamp = 0; 44 | protected $net_read_timeout_present; 45 | protected $net_write_timeout_present; 46 | 47 | /** 48 | * Constructor. 49 | * 50 | * @param array $data { 51 | * Optional. Data for populating the Message object. 52 | * 53 | * @type string $username 54 | * @type string $password 55 | * hashed password with seeds from Handshake message 56 | * @type int $net_read_timeout 57 | * in seconds 58 | * @type int $net_write_timeout 59 | * in seconds 60 | * @type string $destination 61 | * @type string $client_id 62 | * @type string $filter 63 | * @type int|string $start_timestamp 64 | * } 65 | */ 66 | public function __construct($data = NULL) { 67 | \GPBMetadata\CanalProtocol::initOnce(); 68 | parent::__construct($data); 69 | } 70 | 71 | /** 72 | * Generated from protobuf field string username = 1; 73 | * @return string 74 | */ 75 | public function getUsername() 76 | { 77 | return $this->username; 78 | } 79 | 80 | /** 81 | * Generated from protobuf field string username = 1; 82 | * @param string $var 83 | * @return $this 84 | */ 85 | public function setUsername($var) 86 | { 87 | GPBUtil::checkString($var, True); 88 | $this->username = $var; 89 | 90 | return $this; 91 | } 92 | 93 | /** 94 | * hashed password with seeds from Handshake message 95 | * 96 | * Generated from protobuf field bytes password = 2; 97 | * @return string 98 | */ 99 | public function getPassword() 100 | { 101 | return $this->password; 102 | } 103 | 104 | /** 105 | * hashed password with seeds from Handshake message 106 | * 107 | * Generated from protobuf field bytes password = 2; 108 | * @param string $var 109 | * @return $this 110 | */ 111 | public function setPassword($var) 112 | { 113 | GPBUtil::checkString($var, False); 114 | $this->password = $var; 115 | 116 | return $this; 117 | } 118 | 119 | /** 120 | * in seconds 121 | * 122 | * Generated from protobuf field int32 net_read_timeout = 3; 123 | * @return int 124 | */ 125 | public function getNetReadTimeout() 126 | { 127 | return $this->readOneof(3); 128 | } 129 | 130 | /** 131 | * in seconds 132 | * 133 | * Generated from protobuf field int32 net_read_timeout = 3; 134 | * @param int $var 135 | * @return $this 136 | */ 137 | public function setNetReadTimeout($var) 138 | { 139 | GPBUtil::checkInt32($var); 140 | $this->writeOneof(3, $var); 141 | 142 | return $this; 143 | } 144 | 145 | /** 146 | * in seconds 147 | * 148 | * Generated from protobuf field int32 net_write_timeout = 4; 149 | * @return int 150 | */ 151 | public function getNetWriteTimeout() 152 | { 153 | return $this->readOneof(4); 154 | } 155 | 156 | /** 157 | * in seconds 158 | * 159 | * Generated from protobuf field int32 net_write_timeout = 4; 160 | * @param int $var 161 | * @return $this 162 | */ 163 | public function setNetWriteTimeout($var) 164 | { 165 | GPBUtil::checkInt32($var); 166 | $this->writeOneof(4, $var); 167 | 168 | return $this; 169 | } 170 | 171 | /** 172 | * Generated from protobuf field string destination = 5; 173 | * @return string 174 | */ 175 | public function getDestination() 176 | { 177 | return $this->destination; 178 | } 179 | 180 | /** 181 | * Generated from protobuf field string destination = 5; 182 | * @param string $var 183 | * @return $this 184 | */ 185 | public function setDestination($var) 186 | { 187 | GPBUtil::checkString($var, True); 188 | $this->destination = $var; 189 | 190 | return $this; 191 | } 192 | 193 | /** 194 | * Generated from protobuf field string client_id = 6; 195 | * @return string 196 | */ 197 | public function getClientId() 198 | { 199 | return $this->client_id; 200 | } 201 | 202 | /** 203 | * Generated from protobuf field string client_id = 6; 204 | * @param string $var 205 | * @return $this 206 | */ 207 | public function setClientId($var) 208 | { 209 | GPBUtil::checkString($var, True); 210 | $this->client_id = $var; 211 | 212 | return $this; 213 | } 214 | 215 | /** 216 | * Generated from protobuf field string filter = 7; 217 | * @return string 218 | */ 219 | public function getFilter() 220 | { 221 | return $this->filter; 222 | } 223 | 224 | /** 225 | * Generated from protobuf field string filter = 7; 226 | * @param string $var 227 | * @return $this 228 | */ 229 | public function setFilter($var) 230 | { 231 | GPBUtil::checkString($var, True); 232 | $this->filter = $var; 233 | 234 | return $this; 235 | } 236 | 237 | /** 238 | * Generated from protobuf field int64 start_timestamp = 8; 239 | * @return int|string 240 | */ 241 | public function getStartTimestamp() 242 | { 243 | return $this->start_timestamp; 244 | } 245 | 246 | /** 247 | * Generated from protobuf field int64 start_timestamp = 8; 248 | * @param int|string $var 249 | * @return $this 250 | */ 251 | public function setStartTimestamp($var) 252 | { 253 | GPBUtil::checkInt64($var); 254 | $this->start_timestamp = $var; 255 | 256 | return $this; 257 | } 258 | 259 | /** 260 | * @return string 261 | */ 262 | public function getNetReadTimeoutPresent() 263 | { 264 | return $this->whichOneof("net_read_timeout_present"); 265 | } 266 | 267 | /** 268 | * @return string 269 | */ 270 | public function getNetWriteTimeoutPresent() 271 | { 272 | return $this->whichOneof("net_write_timeout_present"); 273 | } 274 | 275 | } 276 | 277 | -------------------------------------------------------------------------------- /src/protocol/Com/Alibaba/Otter/Canal/Protocol/RowChange.php: -------------------------------------------------------------------------------- 1 | com.alibaba.otter.canal.protocol.RowChange 15 | */ 16 | final class RowChange extends \Google\Protobuf\Internal\Message 17 | { 18 | /** 19 | **tableId,由数据库产生* 20 | * 21 | * Generated from protobuf field int64 tableId = 1; 22 | */ 23 | private $tableId = 0; 24 | /** 25 | ** ddl/query的sql语句 * 26 | * 27 | * Generated from protobuf field string sql = 11; 28 | */ 29 | private $sql = ''; 30 | /** 31 | ** 一次数据库变更可能存在多行 * 32 | * 33 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.RowData rowDatas = 12; 34 | */ 35 | private $rowDatas; 36 | /** 37 | **预留扩展* 38 | * 39 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.Pair props = 13; 40 | */ 41 | private $props; 42 | /** 43 | ** ddl/query的schemaName,会存在跨库ddl,需要保留执行ddl的当前schemaName * 44 | * 45 | * Generated from protobuf field string ddlSchemaName = 14; 46 | */ 47 | private $ddlSchemaName = ''; 48 | protected $eventType_present; 49 | protected $isDdl_present; 50 | 51 | /** 52 | * Constructor. 53 | * 54 | * @param array $data { 55 | * Optional. Data for populating the Message object. 56 | * 57 | * @type int|string $tableId 58 | * *tableId,由数据库产生* 59 | * @type int $eventType 60 | * @type bool $isDdl 61 | * @type string $sql 62 | * * ddl/query的sql语句 * 63 | * @type \Com\Alibaba\Otter\Canal\Protocol\RowData[]|\Google\Protobuf\Internal\RepeatedField $rowDatas 64 | * * 一次数据库变更可能存在多行 * 65 | * @type \Com\Alibaba\Otter\Canal\Protocol\Pair[]|\Google\Protobuf\Internal\RepeatedField $props 66 | * *预留扩展* 67 | * @type string $ddlSchemaName 68 | * * ddl/query的schemaName,会存在跨库ddl,需要保留执行ddl的当前schemaName * 69 | * } 70 | */ 71 | public function __construct($data = NULL) { 72 | \GPBMetadata\EntryProtocol::initOnce(); 73 | parent::__construct($data); 74 | } 75 | 76 | /** 77 | **tableId,由数据库产生* 78 | * 79 | * Generated from protobuf field int64 tableId = 1; 80 | * @return int|string 81 | */ 82 | public function getTableId() 83 | { 84 | return $this->tableId; 85 | } 86 | 87 | /** 88 | **tableId,由数据库产生* 89 | * 90 | * Generated from protobuf field int64 tableId = 1; 91 | * @param int|string $var 92 | * @return $this 93 | */ 94 | public function setTableId($var) 95 | { 96 | GPBUtil::checkInt64($var); 97 | $this->tableId = $var; 98 | 99 | return $this; 100 | } 101 | 102 | /** 103 | * Generated from protobuf field .com.alibaba.otter.canal.protocol.EventType eventType = 2; 104 | * @return int 105 | */ 106 | public function getEventType() 107 | { 108 | return $this->readOneof(2); 109 | } 110 | 111 | /** 112 | * Generated from protobuf field .com.alibaba.otter.canal.protocol.EventType eventType = 2; 113 | * @param int $var 114 | * @return $this 115 | */ 116 | public function setEventType($var) 117 | { 118 | GPBUtil::checkEnum($var, \Com\Alibaba\Otter\Canal\Protocol\EventType::class); 119 | $this->writeOneof(2, $var); 120 | 121 | return $this; 122 | } 123 | 124 | /** 125 | * Generated from protobuf field bool isDdl = 10; 126 | * @return bool 127 | */ 128 | public function getIsDdl() 129 | { 130 | return $this->readOneof(10); 131 | } 132 | 133 | /** 134 | * Generated from protobuf field bool isDdl = 10; 135 | * @param bool $var 136 | * @return $this 137 | */ 138 | public function setIsDdl($var) 139 | { 140 | GPBUtil::checkBool($var); 141 | $this->writeOneof(10, $var); 142 | 143 | return $this; 144 | } 145 | 146 | /** 147 | ** ddl/query的sql语句 * 148 | * 149 | * Generated from protobuf field string sql = 11; 150 | * @return string 151 | */ 152 | public function getSql() 153 | { 154 | return $this->sql; 155 | } 156 | 157 | /** 158 | ** ddl/query的sql语句 * 159 | * 160 | * Generated from protobuf field string sql = 11; 161 | * @param string $var 162 | * @return $this 163 | */ 164 | public function setSql($var) 165 | { 166 | GPBUtil::checkString($var, True); 167 | $this->sql = $var; 168 | 169 | return $this; 170 | } 171 | 172 | /** 173 | ** 一次数据库变更可能存在多行 * 174 | * 175 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.RowData rowDatas = 12; 176 | * @return \Google\Protobuf\Internal\RepeatedField 177 | */ 178 | public function getRowDatas() 179 | { 180 | return $this->rowDatas; 181 | } 182 | 183 | /** 184 | ** 一次数据库变更可能存在多行 * 185 | * 186 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.RowData rowDatas = 12; 187 | * @param \Com\Alibaba\Otter\Canal\Protocol\RowData[]|\Google\Protobuf\Internal\RepeatedField $var 188 | * @return $this 189 | */ 190 | public function setRowDatas($var) 191 | { 192 | $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Com\Alibaba\Otter\Canal\Protocol\RowData::class); 193 | $this->rowDatas = $arr; 194 | 195 | return $this; 196 | } 197 | 198 | /** 199 | **预留扩展* 200 | * 201 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.Pair props = 13; 202 | * @return \Google\Protobuf\Internal\RepeatedField 203 | */ 204 | public function getProps() 205 | { 206 | return $this->props; 207 | } 208 | 209 | /** 210 | **预留扩展* 211 | * 212 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.Pair props = 13; 213 | * @param \Com\Alibaba\Otter\Canal\Protocol\Pair[]|\Google\Protobuf\Internal\RepeatedField $var 214 | * @return $this 215 | */ 216 | public function setProps($var) 217 | { 218 | $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Com\Alibaba\Otter\Canal\Protocol\Pair::class); 219 | $this->props = $arr; 220 | 221 | return $this; 222 | } 223 | 224 | /** 225 | ** ddl/query的schemaName,会存在跨库ddl,需要保留执行ddl的当前schemaName * 226 | * 227 | * Generated from protobuf field string ddlSchemaName = 14; 228 | * @return string 229 | */ 230 | public function getDdlSchemaName() 231 | { 232 | return $this->ddlSchemaName; 233 | } 234 | 235 | /** 236 | ** ddl/query的schemaName,会存在跨库ddl,需要保留执行ddl的当前schemaName * 237 | * 238 | * Generated from protobuf field string ddlSchemaName = 14; 239 | * @param string $var 240 | * @return $this 241 | */ 242 | public function setDdlSchemaName($var) 243 | { 244 | GPBUtil::checkString($var, True); 245 | $this->ddlSchemaName = $var; 246 | 247 | return $this; 248 | } 249 | 250 | /** 251 | * @return string 252 | */ 253 | public function getEventTypePresent() 254 | { 255 | return $this->whichOneof("eventType_present"); 256 | } 257 | 258 | /** 259 | * @return string 260 | */ 261 | public function getIsDdlPresent() 262 | { 263 | return $this->whichOneof("isDdl_present"); 264 | } 265 | 266 | } 267 | 268 | -------------------------------------------------------------------------------- /src/adapter/socket/TcpClient.php: -------------------------------------------------------------------------------- 1 | host_ = $host; 75 | $this->port_ = $port; 76 | $this->persist_ = $persist; 77 | } 78 | 79 | /** 80 | * 81 | * @param resource $handle 82 | * @return void 83 | */ 84 | public function setHandle($handle) 85 | { 86 | $this->handle_ = $handle; 87 | } 88 | 89 | /** 90 | * Sets the send timeout. 91 | * 92 | * @param int $timeout 93 | * Timeout in milliseconds. 94 | */ 95 | public function setSendTimeout($timeout) 96 | { 97 | $this->sendTimeout = $timeout; 98 | } 99 | 100 | /** 101 | * Sets the receive timeout. 102 | * 103 | * @param int $timeout 104 | * Timeout in milliseconds. 105 | */ 106 | public function setRecvTimeout($timeout) 107 | { 108 | $this->recvTimeout = $timeout; 109 | } 110 | 111 | /** 112 | * @return unknown 113 | */ 114 | public function getConnectTimeout() 115 | { 116 | return $this->connectTimeout; 117 | } 118 | 119 | /** 120 | * @param $connectTimeout 121 | * Timeout in seconds. 122 | */ 123 | public function setConnectTimeout($connectTimeout) 124 | { 125 | $this->connectTimeout = $connectTimeout; 126 | } 127 | 128 | /** 129 | * Get the host that this socket is connected to 130 | * 131 | * @return string host 132 | */ 133 | public function getHost() 134 | { 135 | return $this->host_; 136 | } 137 | 138 | /** 139 | * Get the remote port that this socket is connected to 140 | * 141 | * @return int port 142 | */ 143 | public function getPort() 144 | { 145 | return $this->port_; 146 | } 147 | 148 | /** 149 | * Tests whether this is open 150 | * 151 | * @return bool true if the socket is open 152 | */ 153 | public function isOpen() 154 | { 155 | return is_resource($this->handle_); 156 | } 157 | 158 | /** 159 | * Connects the socket. 160 | * 161 | * @throws \Exception 162 | */ 163 | public function open() 164 | { 165 | if ($this->isOpen()) { 166 | throw new \Exception('Socket already connected'); 167 | } 168 | 169 | if (empty($this->host_)) { 170 | throw new \Exception('Cannot open null host'); 171 | } 172 | 173 | if ($this->port_ <= 0) { 174 | throw new \Exception('Cannot open without port'); 175 | } 176 | 177 | if ($this->persist_) { 178 | $this->handle_ = @pfsockopen($this->host_, $this->port_, $errno, $errstr, $this->connectTimeout); 179 | } else { 180 | $this->handle_ = @fsockopen($this->host_, $this->port_, $errno, $errstr, $this->connectTimeout); 181 | } 182 | 183 | // Connect failed? 184 | if ($this->handle_ === false) { 185 | $error = 'Socket: Could not connect to ' . $this->host_ . ':' . $this->port_ . ' (' . $errstr . ' [' . $errno . '])'; 186 | throw new \Exception($error, 10); 187 | } 188 | 189 | stream_set_timeout($this->handle_, 0, $this->sendTimeout); 190 | $this->sendTimeoutSet_ = true; 191 | } 192 | 193 | /** 194 | * Closes the socket. 195 | */ 196 | public function close() 197 | { 198 | if (! $this->persist_) { 199 | @fclose($this->handle_); 200 | $this->handle_ = null; 201 | } 202 | } 203 | 204 | /** 205 | * Uses stream get contents to do the reading 206 | * 207 | * @param int $len How many bytes 208 | * @return string Binary data 209 | * @throws \Exception 210 | */ 211 | public function read($len) 212 | { 213 | if ($this->sendTimeoutSet_) { 214 | stream_set_timeout($this->handle_, 0, $this->recvTimeout * 1000000); 215 | $this->sendTimeoutSet_ = false; 216 | } 217 | // This call does not obey stream_set_timeout values! 218 | // $buf = @stream_get_contents($this->handle_, $len); 219 | 220 | $pre = null; 221 | while (true) { 222 | $buf = @fread($this->handle_, $len); 223 | if ($buf === false || $buf === '') { 224 | $md = stream_get_meta_data($this->handle_); 225 | if ($md['timed_out']) { 226 | throw new \Exception('TSocket: timed out reading ' . $len . ' bytes from ' . $this->host_ . ':' . $this->port_); 227 | } else { 228 | throw new \Exception('TSocket: Could not read ' . $len . ' bytes from ' . $this->host_ . ':' . $this->port_); 229 | } 230 | } elseif (($sz = strlen($buf)) < $len) { 231 | $md = stream_get_meta_data($this->handle_); 232 | if ($md['timed_out']) { 233 | throw new \Exception('TSocket: timed out reading ' . $len . ' bytes from ' . $this->host_ . ':' . $this->port_); 234 | } else { 235 | $pre .= $buf; 236 | $len -= $sz; 237 | } 238 | } else { 239 | return $pre . $buf; 240 | } 241 | } 242 | } 243 | 244 | /** 245 | * @param string|false $buf Binary data 246 | * @throws \Exception 247 | */ 248 | public function write($buf) 249 | { 250 | if (! $this->sendTimeoutSet_) { 251 | stream_set_timeout($this->handle_, 0, $this->sendTimeout); 252 | $this->sendTimeoutSet_ = true; 253 | } 254 | while (strlen($buf) > 0) { 255 | $got = @fwrite($this->handle_, $buf); 256 | if ($got === 0 || $got === false) { 257 | $md = stream_get_meta_data($this->handle_); 258 | if ($md['timed_out']) { 259 | throw new \Exception('TSocket: timed out writing ' . strlen($buf) . ' bytes from ' . $this->host_ . ':' . $this->port_); 260 | } else { 261 | throw new \Exception('TSocket: Could not write ' . strlen($buf) . ' bytes ' . $this->host_ . ':' . $this->port_); 262 | } 263 | } 264 | $buf = substr($buf, $got); 265 | } 266 | } 267 | 268 | /** 269 | * Flush output to the socket. 270 | * @throws \Exception 271 | */ 272 | public function flush() 273 | { 274 | $ret = fflush($this->handle_); 275 | if ($ret === false) { 276 | throw new \Exception('TSocket: Could not flush: ' . $this->host_ . ':' . $this->port_); 277 | } 278 | } 279 | } 280 | -------------------------------------------------------------------------------- /src/protocol/Com/Alibaba/Otter/Canal/Protocol/Column.php: -------------------------------------------------------------------------------- 1 | com.alibaba.otter.canal.protocol.Column 15 | */ 16 | final class Column extends \Google\Protobuf\Internal\Message 17 | { 18 | /** 19 | **字段下标* 20 | * 21 | * Generated from protobuf field int32 index = 1; 22 | */ 23 | private $index = 0; 24 | /** 25 | **字段java中类型* 26 | * 27 | * Generated from protobuf field int32 sqlType = 2; 28 | */ 29 | private $sqlType = 0; 30 | /** 31 | **字段名称(忽略大小写),在mysql中是没有的* 32 | * 33 | * Generated from protobuf field string name = 3; 34 | */ 35 | private $name = ''; 36 | /** 37 | **是否是主键* 38 | * 39 | * Generated from protobuf field bool isKey = 4; 40 | */ 41 | private $isKey = false; 42 | /** 43 | **如果EventType=UPDATE,用于标识这个字段值是否有修改* 44 | * 45 | * Generated from protobuf field bool updated = 5; 46 | */ 47 | private $updated = false; 48 | /** 49 | **预留扩展* 50 | * 51 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.Pair props = 7; 52 | */ 53 | private $props; 54 | /** 55 | ** 字段值,timestamp,Datetime是一个时间格式的文本 * 56 | * 57 | * Generated from protobuf field string value = 8; 58 | */ 59 | private $value = ''; 60 | /** 61 | ** 对应数据对象原始长度 * 62 | * 63 | * Generated from protobuf field int32 length = 9; 64 | */ 65 | private $length = 0; 66 | /** 67 | **字段mysql类型* 68 | * 69 | * Generated from protobuf field string mysqlType = 10; 70 | */ 71 | private $mysqlType = ''; 72 | protected $isNull_present; 73 | 74 | /** 75 | * Constructor. 76 | * 77 | * @param array $data { 78 | * Optional. Data for populating the Message object. 79 | * 80 | * @type int $index 81 | * *字段下标* 82 | * @type int $sqlType 83 | * *字段java中类型* 84 | * @type string $name 85 | * *字段名称(忽略大小写),在mysql中是没有的* 86 | * @type bool $isKey 87 | * *是否是主键* 88 | * @type bool $updated 89 | * *如果EventType=UPDATE,用于标识这个字段值是否有修改* 90 | * @type bool $isNull 91 | * @type \Com\Alibaba\Otter\Canal\Protocol\Pair[]|\Google\Protobuf\Internal\RepeatedField $props 92 | * *预留扩展* 93 | * @type string $value 94 | * * 字段值,timestamp,Datetime是一个时间格式的文本 * 95 | * @type int $length 96 | * * 对应数据对象原始长度 * 97 | * @type string $mysqlType 98 | * *字段mysql类型* 99 | * } 100 | */ 101 | public function __construct($data = NULL) { 102 | \GPBMetadata\EntryProtocol::initOnce(); 103 | parent::__construct($data); 104 | } 105 | 106 | /** 107 | **字段下标* 108 | * 109 | * Generated from protobuf field int32 index = 1; 110 | * @return int 111 | */ 112 | public function getIndex() 113 | { 114 | return $this->index; 115 | } 116 | 117 | /** 118 | **字段下标* 119 | * 120 | * Generated from protobuf field int32 index = 1; 121 | * @param int $var 122 | * @return $this 123 | */ 124 | public function setIndex($var) 125 | { 126 | GPBUtil::checkInt32($var); 127 | $this->index = $var; 128 | 129 | return $this; 130 | } 131 | 132 | /** 133 | **字段java中类型* 134 | * 135 | * Generated from protobuf field int32 sqlType = 2; 136 | * @return int 137 | */ 138 | public function getSqlType() 139 | { 140 | return $this->sqlType; 141 | } 142 | 143 | /** 144 | **字段java中类型* 145 | * 146 | * Generated from protobuf field int32 sqlType = 2; 147 | * @param int $var 148 | * @return $this 149 | */ 150 | public function setSqlType($var) 151 | { 152 | GPBUtil::checkInt32($var); 153 | $this->sqlType = $var; 154 | 155 | return $this; 156 | } 157 | 158 | /** 159 | **字段名称(忽略大小写),在mysql中是没有的* 160 | * 161 | * Generated from protobuf field string name = 3; 162 | * @return string 163 | */ 164 | public function getName() 165 | { 166 | return $this->name; 167 | } 168 | 169 | /** 170 | **字段名称(忽略大小写),在mysql中是没有的* 171 | * 172 | * Generated from protobuf field string name = 3; 173 | * @param string $var 174 | * @return $this 175 | */ 176 | public function setName($var) 177 | { 178 | GPBUtil::checkString($var, True); 179 | $this->name = $var; 180 | 181 | return $this; 182 | } 183 | 184 | /** 185 | **是否是主键* 186 | * 187 | * Generated from protobuf field bool isKey = 4; 188 | * @return bool 189 | */ 190 | public function getIsKey() 191 | { 192 | return $this->isKey; 193 | } 194 | 195 | /** 196 | **是否是主键* 197 | * 198 | * Generated from protobuf field bool isKey = 4; 199 | * @param bool $var 200 | * @return $this 201 | */ 202 | public function setIsKey($var) 203 | { 204 | GPBUtil::checkBool($var); 205 | $this->isKey = $var; 206 | 207 | return $this; 208 | } 209 | 210 | /** 211 | **如果EventType=UPDATE,用于标识这个字段值是否有修改* 212 | * 213 | * Generated from protobuf field bool updated = 5; 214 | * @return bool 215 | */ 216 | public function getUpdated() 217 | { 218 | return $this->updated; 219 | } 220 | 221 | /** 222 | **如果EventType=UPDATE,用于标识这个字段值是否有修改* 223 | * 224 | * Generated from protobuf field bool updated = 5; 225 | * @param bool $var 226 | * @return $this 227 | */ 228 | public function setUpdated($var) 229 | { 230 | GPBUtil::checkBool($var); 231 | $this->updated = $var; 232 | 233 | return $this; 234 | } 235 | 236 | /** 237 | * Generated from protobuf field bool isNull = 6; 238 | * @return bool 239 | */ 240 | public function getIsNull() 241 | { 242 | return $this->readOneof(6); 243 | } 244 | 245 | /** 246 | * Generated from protobuf field bool isNull = 6; 247 | * @param bool $var 248 | * @return $this 249 | */ 250 | public function setIsNull($var) 251 | { 252 | GPBUtil::checkBool($var); 253 | $this->writeOneof(6, $var); 254 | 255 | return $this; 256 | } 257 | 258 | /** 259 | **预留扩展* 260 | * 261 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.Pair props = 7; 262 | * @return \Google\Protobuf\Internal\RepeatedField 263 | */ 264 | public function getProps() 265 | { 266 | return $this->props; 267 | } 268 | 269 | /** 270 | **预留扩展* 271 | * 272 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.Pair props = 7; 273 | * @param \Com\Alibaba\Otter\Canal\Protocol\Pair[]|\Google\Protobuf\Internal\RepeatedField $var 274 | * @return $this 275 | */ 276 | public function setProps($var) 277 | { 278 | $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Com\Alibaba\Otter\Canal\Protocol\Pair::class); 279 | $this->props = $arr; 280 | 281 | return $this; 282 | } 283 | 284 | /** 285 | ** 字段值,timestamp,Datetime是一个时间格式的文本 * 286 | * 287 | * Generated from protobuf field string value = 8; 288 | * @return string 289 | */ 290 | public function getValue() 291 | { 292 | return $this->value; 293 | } 294 | 295 | /** 296 | ** 字段值,timestamp,Datetime是一个时间格式的文本 * 297 | * 298 | * Generated from protobuf field string value = 8; 299 | * @param string $var 300 | * @return $this 301 | */ 302 | public function setValue($var) 303 | { 304 | GPBUtil::checkString($var, True); 305 | $this->value = $var; 306 | 307 | return $this; 308 | } 309 | 310 | /** 311 | ** 对应数据对象原始长度 * 312 | * 313 | * Generated from protobuf field int32 length = 9; 314 | * @return int 315 | */ 316 | public function getLength() 317 | { 318 | return $this->length; 319 | } 320 | 321 | /** 322 | ** 对应数据对象原始长度 * 323 | * 324 | * Generated from protobuf field int32 length = 9; 325 | * @param int $var 326 | * @return $this 327 | */ 328 | public function setLength($var) 329 | { 330 | GPBUtil::checkInt32($var); 331 | $this->length = $var; 332 | 333 | return $this; 334 | } 335 | 336 | /** 337 | **字段mysql类型* 338 | * 339 | * Generated from protobuf field string mysqlType = 10; 340 | * @return string 341 | */ 342 | public function getMysqlType() 343 | { 344 | return $this->mysqlType; 345 | } 346 | 347 | /** 348 | **字段mysql类型* 349 | * 350 | * Generated from protobuf field string mysqlType = 10; 351 | * @param string $var 352 | * @return $this 353 | */ 354 | public function setMysqlType($var) 355 | { 356 | GPBUtil::checkString($var, True); 357 | $this->mysqlType = $var; 358 | 359 | return $this; 360 | } 361 | 362 | /** 363 | * @return string 364 | */ 365 | public function getIsNullPresent() 366 | { 367 | return $this->whichOneof("isNull_present"); 368 | } 369 | 370 | } 371 | 372 | -------------------------------------------------------------------------------- /src/adapter/CanalConnectorBase.php: -------------------------------------------------------------------------------- 1 | disConnect(); 38 | } 39 | 40 | /** 41 | * @param string $host 42 | * @param int $port 43 | * @param int $connectionTimeout 44 | * @param int $readTimeout 45 | * @param int $writeTimeout 46 | * @throws \Exception 47 | */ 48 | public function connect($host = "127.0.0.1", $port = 11111, $user = "", $password = "", $connectionTimeout = 10, $readTimeout = 30, $writeTimeout = 30) 49 | { 50 | $this->doConnect($host, $port, $connectionTimeout, $readTimeout, $writeTimeout); 51 | 52 | $this->readTimeout = $readTimeout; 53 | $this->writeTimeout = $writeTimeout; 54 | 55 | $data = $this->readNextPacket(); 56 | $packet = new Packet(); 57 | $packet->mergeFromString($data); 58 | 59 | // 密码需要通过握手包返回的seed进行哈希 60 | if ($user && $password) { 61 | $handShake = new Handshake(); 62 | $handShake->mergeFromString($packet->getBody()); 63 | $password = bin2hex($this->scramble411($password, $handShake->getSeeds())); 64 | } 65 | $this->checkValid($user, $password); 66 | 67 | if ($packet->getType() != PacketType::HANDSHAKE) { 68 | throw new \Exception("connect error."); 69 | } 70 | } 71 | 72 | 73 | /** 74 | * @param string $password 75 | * @param string $seed 76 | * @return false|string 77 | */ 78 | public function scramble411($password, $seed) 79 | { 80 | $pwd1 = sha1($password, true); 81 | $pwd2 = sha1($pwd1, true); 82 | $pwd3 = sha1($seed . $pwd2, true); 83 | 84 | $pwd1Bytes = $this->stringToBytes($pwd1); 85 | $pwd3Bytes = $this->stringToBytes($pwd3); 86 | foreach ($pwd3Bytes as $key => $pwd3Byte) { 87 | $pwd3Bytes[$key] ^= $pwd1Bytes[$key]; 88 | } 89 | return $this->bytesToString($pwd3Bytes); 90 | } 91 | 92 | /** 93 | * @param string $string 94 | * @return array|false 95 | */ 96 | public function stringToBytes($string) 97 | { 98 | return unpack("C*", $string); 99 | } 100 | 101 | /** 102 | * @param array $bytes 103 | * @return false|string 104 | */ 105 | public function bytesToString($bytes) 106 | { 107 | return pack("C*", ...$bytes); 108 | } 109 | 110 | public function disConnect() 111 | { 112 | if ($this->client) { 113 | $this->rollback(0); 114 | } 115 | } 116 | 117 | /** 118 | * @param string $username 119 | * @param string $password 120 | * @throws \Exception 121 | */ 122 | public function checkValid($username="", $password="") 123 | { 124 | $ca = new ClientAuth(); 125 | $ca->setUsername($username); 126 | $ca->setPassword($password); 127 | $ca->setNetReadTimeout($this->readTimeout * 1000); 128 | $ca->setNetWriteTimeout($this->writeTimeout * 1000); 129 | 130 | $packet = new Packet(); 131 | $packet->setType(PacketType::CLIENTAUTHENTICATION); 132 | $packet->setBody($ca->serializeToString()); 133 | $this->writeWithHeader($packet->serializeToString()); 134 | 135 | $data = $this->readNextPacket(); 136 | $packet = new Packet(); 137 | $packet->mergeFromString($data); 138 | if ($packet->getType() != PacketType::ACK) { 139 | throw new \Exception("Auth error."); 140 | } 141 | $ack = new Ack(); 142 | $ack->mergeFromString($packet->getBody()); 143 | if ($ack->getErrorCode() > 0) { 144 | throw new \Exception(sprintf("something goes wrong when doing authentication. error code:%s, error message:%s", $ack->getErrorCode(), $ack->getErrorMessage())); 145 | } 146 | } 147 | 148 | /** 149 | * @param int $clientId 150 | * @param string $destination 151 | * @param string $filter 152 | * @throws \Exception 153 | */ 154 | public function subscribe($clientId=1001, $destination = "example", $filter = ".*\\..*") 155 | { 156 | $this->clientId = $clientId; 157 | $this->destination = $destination; 158 | 159 | $this->rollback(0); 160 | 161 | $sub = new Sub(); 162 | $sub->setDestination($this->destination); 163 | $sub->setClientId($this->clientId); 164 | $sub->setFilter($filter); 165 | 166 | $packet = new Packet(); 167 | $packet->setType(PacketType::SUBSCRIPTION); 168 | $packet->setBody($sub->serializeToString()); 169 | $this->writeWithHeader($packet->serializeToString()); 170 | 171 | $data = $this->readNextPacket(); 172 | $packet = new Packet(); 173 | $packet->mergeFromString($data); 174 | 175 | if ($packet->getType() != PacketType::ACK) { 176 | throw new \Exception("Subscribe error."); 177 | } 178 | 179 | $ack = new Ack(); 180 | $ack->mergeFromString($packet->getBody()); 181 | if ($ack->getErrorCode() > 0) { 182 | throw new \Exception(sprintf("Failed to subscribe. error code:%s, error message:%s", $ack->getErrorCode(), $ack->getErrorMessage())); 183 | } 184 | } 185 | 186 | public function unSubscribe() 187 | { 188 | // TODO: Implement unSubscribe() method. 189 | } 190 | 191 | /** 192 | * @param int $size 193 | * @return Message 194 | * @throws \Exception 195 | */ 196 | public function get($size=100) 197 | { 198 | $message = $this->getWithoutAck($size); 199 | $this->ack($message->getId()); 200 | return $message; 201 | } 202 | 203 | /** 204 | * @param int $batchSize 205 | * @param int $timeout 206 | * @param int $unit 207 | * @return Message 208 | * @throws \Exception 209 | */ 210 | public function getWithoutAck($batchSize=10, $timeout=-1, $unit=-1) 211 | { 212 | $get = new Get(); 213 | $get->setClientId($this->clientId); 214 | $get->setDestination($this->destination); 215 | $get->setAutoAck(false); 216 | $get->setFetchSize($batchSize); 217 | $get->setTimeout($timeout); 218 | $get->setUnit($unit); 219 | 220 | $packet = new Packet(); 221 | $packet->setType(PacketType::GET); 222 | $packet->setBody($get->serializeToString()); 223 | 224 | $this->writeWithHeader($packet->serializeToString()); 225 | 226 | $data = $this->readNextPacket(); 227 | $packet = new Packet(); 228 | $packet->mergeFromString($data); 229 | 230 | $message = new Message(); 231 | 232 | switch ($packet->getType()) { 233 | case PacketType::MESSAGES: 234 | $messages = new Messages(); 235 | $messages->mergeFromString($packet->getBody()); 236 | 237 | if ($messages->getBatchId() > 0) { 238 | $message->setId($messages->getBatchId()); 239 | 240 | foreach ($messages->getMessages()->getIterator() as $v) { 241 | $entry = new Entry(); 242 | $entry->mergeFromString($v); 243 | $message->addEntries($entry); 244 | } 245 | } 246 | 247 | break; 248 | case PacketType::ACK: 249 | $ack = new Ack(); 250 | $ack->mergeFromString($packet->getBody()); 251 | if ($ack->getErrorCode() > 0) { 252 | throw new \Exception(sprintf("get data error. error code:%s, error message:%s", $ack->getErrorCode(), $ack->getErrorMessage())); 253 | } 254 | break; 255 | default: 256 | throw new \Exception(sprintf("unexpected packet type:%s", $packet->getType())); 257 | break; 258 | } 259 | 260 | return $message; 261 | } 262 | 263 | public function ack($messageId=0) 264 | { 265 | if ($messageId) { 266 | $clientAck = new ClientAck(); 267 | $clientAck->setDestination($this->destination); 268 | $clientAck->setClientId($this->clientId); 269 | $clientAck->setBatchId($messageId); 270 | 271 | $packet = new Packet(); 272 | $packet->setType(PacketType::CLIENTACK); 273 | $packet->setBody($clientAck->serializeToString()); 274 | 275 | $this->writeWithHeader($packet->serializeToString()); 276 | } 277 | } 278 | 279 | public function rollback($batchId=0) 280 | { 281 | $cb = new ClientRollback(); 282 | $cb->setBatchId($batchId); 283 | $cb->setClientId($this->clientId); 284 | $cb->setDestination($this->destination); 285 | 286 | $packet = new Packet(); 287 | $packet->setType(PacketType::CLIENTROLLBACK); 288 | $packet->setBody($cb->serializeToString()); 289 | 290 | $this->writeWithHeader($packet->serializeToString()); 291 | } 292 | 293 | abstract protected function doConnect($host="127.0.0.1", $port=11111, $connectionTimeout=10, $readTimeout = 30, $writeTimeout = 30); 294 | 295 | abstract protected function readNextPacket(); 296 | 297 | abstract protected function writeWithHeader($data); 298 | } -------------------------------------------------------------------------------- /src/protocol/Com/Alibaba/Otter/Canal/Protocol/Header.php: -------------------------------------------------------------------------------- 1 | com.alibaba.otter.canal.protocol.Header 15 | */ 16 | final class Header extends \Google\Protobuf\Internal\Message 17 | { 18 | /** 19 | **binlog/redolog 文件名* 20 | * 21 | * Generated from protobuf field string logfileName = 2; 22 | */ 23 | private $logfileName = ''; 24 | /** 25 | **binlog/redolog 文件的偏移位置* 26 | * 27 | * Generated from protobuf field int64 logfileOffset = 3; 28 | */ 29 | private $logfileOffset = 0; 30 | /** 31 | **服务端serverId* 32 | * 33 | * Generated from protobuf field int64 serverId = 4; 34 | */ 35 | private $serverId = 0; 36 | /** 37 | ** 变更数据的编码 * 38 | * 39 | * Generated from protobuf field string serverenCode = 5; 40 | */ 41 | private $serverenCode = ''; 42 | /** 43 | **变更数据的执行时间 * 44 | * 45 | * Generated from protobuf field int64 executeTime = 6; 46 | */ 47 | private $executeTime = 0; 48 | /** 49 | ** 变更数据的schemaname* 50 | * 51 | * Generated from protobuf field string schemaName = 8; 52 | */ 53 | private $schemaName = ''; 54 | /** 55 | **变更数据的tablename* 56 | * 57 | * Generated from protobuf field string tableName = 9; 58 | */ 59 | private $tableName = ''; 60 | /** 61 | **每个event的长度* 62 | * 63 | * Generated from protobuf field int64 eventLength = 10; 64 | */ 65 | private $eventLength = 0; 66 | /** 67 | **预留扩展* 68 | * 69 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.Pair props = 12; 70 | */ 71 | private $props; 72 | /** 73 | **当前事务的gitd* 74 | * 75 | * Generated from protobuf field string gtid = 13; 76 | */ 77 | private $gtid = ''; 78 | protected $version_present; 79 | protected $sourceType_present; 80 | protected $eventType_present; 81 | 82 | /** 83 | * Constructor. 84 | * 85 | * @param array $data { 86 | * Optional. Data for populating the Message object. 87 | * 88 | * @type int $version 89 | * @type string $logfileName 90 | * *binlog/redolog 文件名* 91 | * @type int|string $logfileOffset 92 | * *binlog/redolog 文件的偏移位置* 93 | * @type int|string $serverId 94 | * *服务端serverId* 95 | * @type string $serverenCode 96 | * * 变更数据的编码 * 97 | * @type int|string $executeTime 98 | * *变更数据的执行时间 * 99 | * @type int $sourceType 100 | * @type string $schemaName 101 | * * 变更数据的schemaname* 102 | * @type string $tableName 103 | * *变更数据的tablename* 104 | * @type int|string $eventLength 105 | * *每个event的长度* 106 | * @type int $eventType 107 | * @type \Com\Alibaba\Otter\Canal\Protocol\Pair[]|\Google\Protobuf\Internal\RepeatedField $props 108 | * *预留扩展* 109 | * @type string $gtid 110 | * *当前事务的gitd* 111 | * } 112 | */ 113 | public function __construct($data = NULL) { 114 | \GPBMetadata\EntryProtocol::initOnce(); 115 | parent::__construct($data); 116 | } 117 | 118 | /** 119 | * Generated from protobuf field int32 version = 1; 120 | * @return int 121 | */ 122 | public function getVersion() 123 | { 124 | return $this->readOneof(1); 125 | } 126 | 127 | /** 128 | * Generated from protobuf field int32 version = 1; 129 | * @param int $var 130 | * @return $this 131 | */ 132 | public function setVersion($var) 133 | { 134 | GPBUtil::checkInt32($var); 135 | $this->writeOneof(1, $var); 136 | 137 | return $this; 138 | } 139 | 140 | /** 141 | **binlog/redolog 文件名* 142 | * 143 | * Generated from protobuf field string logfileName = 2; 144 | * @return string 145 | */ 146 | public function getLogfileName() 147 | { 148 | return $this->logfileName; 149 | } 150 | 151 | /** 152 | **binlog/redolog 文件名* 153 | * 154 | * Generated from protobuf field string logfileName = 2; 155 | * @param string $var 156 | * @return $this 157 | */ 158 | public function setLogfileName($var) 159 | { 160 | GPBUtil::checkString($var, True); 161 | $this->logfileName = $var; 162 | 163 | return $this; 164 | } 165 | 166 | /** 167 | **binlog/redolog 文件的偏移位置* 168 | * 169 | * Generated from protobuf field int64 logfileOffset = 3; 170 | * @return int|string 171 | */ 172 | public function getLogfileOffset() 173 | { 174 | return $this->logfileOffset; 175 | } 176 | 177 | /** 178 | **binlog/redolog 文件的偏移位置* 179 | * 180 | * Generated from protobuf field int64 logfileOffset = 3; 181 | * @param int|string $var 182 | * @return $this 183 | */ 184 | public function setLogfileOffset($var) 185 | { 186 | GPBUtil::checkInt64($var); 187 | $this->logfileOffset = $var; 188 | 189 | return $this; 190 | } 191 | 192 | /** 193 | **服务端serverId* 194 | * 195 | * Generated from protobuf field int64 serverId = 4; 196 | * @return int|string 197 | */ 198 | public function getServerId() 199 | { 200 | return $this->serverId; 201 | } 202 | 203 | /** 204 | **服务端serverId* 205 | * 206 | * Generated from protobuf field int64 serverId = 4; 207 | * @param int|string $var 208 | * @return $this 209 | */ 210 | public function setServerId($var) 211 | { 212 | GPBUtil::checkInt64($var); 213 | $this->serverId = $var; 214 | 215 | return $this; 216 | } 217 | 218 | /** 219 | ** 变更数据的编码 * 220 | * 221 | * Generated from protobuf field string serverenCode = 5; 222 | * @return string 223 | */ 224 | public function getServerenCode() 225 | { 226 | return $this->serverenCode; 227 | } 228 | 229 | /** 230 | ** 变更数据的编码 * 231 | * 232 | * Generated from protobuf field string serverenCode = 5; 233 | * @param string $var 234 | * @return $this 235 | */ 236 | public function setServerenCode($var) 237 | { 238 | GPBUtil::checkString($var, True); 239 | $this->serverenCode = $var; 240 | 241 | return $this; 242 | } 243 | 244 | /** 245 | **变更数据的执行时间 * 246 | * 247 | * Generated from protobuf field int64 executeTime = 6; 248 | * @return int|string 249 | */ 250 | public function getExecuteTime() 251 | { 252 | return $this->executeTime; 253 | } 254 | 255 | /** 256 | **变更数据的执行时间 * 257 | * 258 | * Generated from protobuf field int64 executeTime = 6; 259 | * @param int|string $var 260 | * @return $this 261 | */ 262 | public function setExecuteTime($var) 263 | { 264 | GPBUtil::checkInt64($var); 265 | $this->executeTime = $var; 266 | 267 | return $this; 268 | } 269 | 270 | /** 271 | * Generated from protobuf field .com.alibaba.otter.canal.protocol.Type sourceType = 7; 272 | * @return int 273 | */ 274 | public function getSourceType() 275 | { 276 | return $this->readOneof(7); 277 | } 278 | 279 | /** 280 | * Generated from protobuf field .com.alibaba.otter.canal.protocol.Type sourceType = 7; 281 | * @param int $var 282 | * @return $this 283 | */ 284 | public function setSourceType($var) 285 | { 286 | GPBUtil::checkEnum($var, \Com\Alibaba\Otter\Canal\Protocol\Type::class); 287 | $this->writeOneof(7, $var); 288 | 289 | return $this; 290 | } 291 | 292 | /** 293 | ** 变更数据的schemaname* 294 | * 295 | * Generated from protobuf field string schemaName = 8; 296 | * @return string 297 | */ 298 | public function getSchemaName() 299 | { 300 | return $this->schemaName; 301 | } 302 | 303 | /** 304 | ** 变更数据的schemaname* 305 | * 306 | * Generated from protobuf field string schemaName = 8; 307 | * @param string $var 308 | * @return $this 309 | */ 310 | public function setSchemaName($var) 311 | { 312 | GPBUtil::checkString($var, True); 313 | $this->schemaName = $var; 314 | 315 | return $this; 316 | } 317 | 318 | /** 319 | **变更数据的tablename* 320 | * 321 | * Generated from protobuf field string tableName = 9; 322 | * @return string 323 | */ 324 | public function getTableName() 325 | { 326 | return $this->tableName; 327 | } 328 | 329 | /** 330 | **变更数据的tablename* 331 | * 332 | * Generated from protobuf field string tableName = 9; 333 | * @param string $var 334 | * @return $this 335 | */ 336 | public function setTableName($var) 337 | { 338 | GPBUtil::checkString($var, True); 339 | $this->tableName = $var; 340 | 341 | return $this; 342 | } 343 | 344 | /** 345 | **每个event的长度* 346 | * 347 | * Generated from protobuf field int64 eventLength = 10; 348 | * @return int|string 349 | */ 350 | public function getEventLength() 351 | { 352 | return $this->eventLength; 353 | } 354 | 355 | /** 356 | **每个event的长度* 357 | * 358 | * Generated from protobuf field int64 eventLength = 10; 359 | * @param int|string $var 360 | * @return $this 361 | */ 362 | public function setEventLength($var) 363 | { 364 | GPBUtil::checkInt64($var); 365 | $this->eventLength = $var; 366 | 367 | return $this; 368 | } 369 | 370 | /** 371 | * Generated from protobuf field .com.alibaba.otter.canal.protocol.EventType eventType = 11; 372 | * @return int 373 | */ 374 | public function getEventType() 375 | { 376 | return $this->readOneof(11); 377 | } 378 | 379 | /** 380 | * Generated from protobuf field .com.alibaba.otter.canal.protocol.EventType eventType = 11; 381 | * @param int $var 382 | * @return $this 383 | */ 384 | public function setEventType($var) 385 | { 386 | GPBUtil::checkEnum($var, \Com\Alibaba\Otter\Canal\Protocol\EventType::class); 387 | $this->writeOneof(11, $var); 388 | 389 | return $this; 390 | } 391 | 392 | /** 393 | **预留扩展* 394 | * 395 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.Pair props = 12; 396 | * @return \Google\Protobuf\Internal\RepeatedField 397 | */ 398 | public function getProps() 399 | { 400 | return $this->props; 401 | } 402 | 403 | /** 404 | **预留扩展* 405 | * 406 | * Generated from protobuf field repeated .com.alibaba.otter.canal.protocol.Pair props = 12; 407 | * @param \Com\Alibaba\Otter\Canal\Protocol\Pair[]|\Google\Protobuf\Internal\RepeatedField $var 408 | * @return $this 409 | */ 410 | public function setProps($var) 411 | { 412 | $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Com\Alibaba\Otter\Canal\Protocol\Pair::class); 413 | $this->props = $arr; 414 | 415 | return $this; 416 | } 417 | 418 | /** 419 | **当前事务的gitd* 420 | * 421 | * Generated from protobuf field string gtid = 13; 422 | * @return string 423 | */ 424 | public function getGtid() 425 | { 426 | return $this->gtid; 427 | } 428 | 429 | /** 430 | **当前事务的gitd* 431 | * 432 | * Generated from protobuf field string gtid = 13; 433 | * @param string $var 434 | * @return $this 435 | */ 436 | public function setGtid($var) 437 | { 438 | GPBUtil::checkString($var, True); 439 | $this->gtid = $var; 440 | 441 | return $this; 442 | } 443 | 444 | /** 445 | * @return string 446 | */ 447 | public function getVersionPresent() 448 | { 449 | return $this->whichOneof("version_present"); 450 | } 451 | 452 | /** 453 | * @return string 454 | */ 455 | public function getSourceTypePresent() 456 | { 457 | return $this->whichOneof("sourceType_present"); 458 | } 459 | 460 | /** 461 | * @return string 462 | */ 463 | public function getEventTypePresent() 464 | { 465 | return $this->whichOneof("eventType_present"); 466 | } 467 | 468 | } 469 | 470 | --------------------------------------------------------------------------------