Full Code of alibaba/canal for AI

master 69a06dba095e cached
1316 files
41.6 MB
2.1M tokens
10888 symbols
1 requests
Download .txt
Showing preview only (8,203K chars total). Download the full file or copy to clipboard to get everything.
Repository: alibaba/canal
Branch: master
Commit: 69a06dba095e
Files: 1316
Total size: 41.6 MB

Directory structure:
gitextract_xcssslhk/

├── .codecov.yml
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── any-questions-on-canal.md
│   │   ├── bug-report-for-canal.md
│   │   └── feature-request-of-canal.md
│   └── workflows/
│       └── maven.yml
├── .gitignore
├── .mvn/
│   └── wrapper/
│       ├── maven-wrapper.jar
│       └── maven-wrapper.properties
├── .travis.yml
├── LICENSE.txt
├── README.md
├── RELEASE.txt
├── SECURITY.md
├── admin/
│   ├── admin-ui/
│   │   ├── .editorconfig
│   │   ├── .eslintignore
│   │   ├── .eslintrc.js
│   │   ├── .gitignore
│   │   ├── .travis.yml
│   │   ├── LICENSE
│   │   ├── babel.config.js
│   │   ├── build/
│   │   │   └── index.js
│   │   ├── jest.config.js
│   │   ├── mock/
│   │   │   ├── index.js
│   │   │   ├── mock-server.js
│   │   │   ├── table.js
│   │   │   └── user.js
│   │   ├── node/
│   │   │   └── node
│   │   ├── package.json
│   │   ├── pom.xml
│   │   ├── postcss.config.js
│   │   ├── public/
│   │   │   └── index.html
│   │   ├── src/
│   │   │   ├── App.vue
│   │   │   ├── api/
│   │   │   │   ├── canalCluster.js
│   │   │   │   ├── canalConfig.js
│   │   │   │   ├── canalInstance.js
│   │   │   │   ├── nodeServer.js
│   │   │   │   ├── table.js
│   │   │   │   └── user.js
│   │   │   ├── components/
│   │   │   │   ├── Breadcrumb/
│   │   │   │   │   └── index.vue
│   │   │   │   ├── Hamburger/
│   │   │   │   │   └── index.vue
│   │   │   │   ├── Pagination/
│   │   │   │   │   └── index.vue
│   │   │   │   └── SvgIcon/
│   │   │   │       └── index.vue
│   │   │   ├── icons/
│   │   │   │   ├── index.js
│   │   │   │   └── svgo.yml
│   │   │   ├── layout/
│   │   │   │   ├── components/
│   │   │   │   │   ├── AppMain.vue
│   │   │   │   │   ├── Navbar.vue
│   │   │   │   │   ├── Sidebar/
│   │   │   │   │   │   ├── FixiOSBug.js
│   │   │   │   │   │   ├── Item.vue
│   │   │   │   │   │   ├── Link.vue
│   │   │   │   │   │   ├── Logo.vue
│   │   │   │   │   │   ├── SidebarItem.vue
│   │   │   │   │   │   └── index.vue
│   │   │   │   │   └── index.js
│   │   │   │   ├── index.vue
│   │   │   │   └── mixin/
│   │   │   │       └── ResizeHandler.js
│   │   │   ├── main.js
│   │   │   ├── permission.js
│   │   │   ├── router/
│   │   │   │   └── index.js
│   │   │   ├── settings.js
│   │   │   ├── store/
│   │   │   │   ├── getters.js
│   │   │   │   ├── index.js
│   │   │   │   └── modules/
│   │   │   │       ├── app.js
│   │   │   │       ├── settings.js
│   │   │   │       └── user.js
│   │   │   ├── styles/
│   │   │   │   ├── element-ui.scss
│   │   │   │   ├── index.scss
│   │   │   │   ├── mixin.scss
│   │   │   │   ├── sidebar.scss
│   │   │   │   ├── transition.scss
│   │   │   │   └── variables.scss
│   │   │   ├── utils/
│   │   │   │   ├── auth.js
│   │   │   │   ├── get-page-title.js
│   │   │   │   ├── index.js
│   │   │   │   ├── request.js
│   │   │   │   ├── scrollTo.js
│   │   │   │   └── validate.js
│   │   │   └── views/
│   │   │       ├── 404.vue
│   │   │       ├── canalServer/
│   │   │       │   ├── CanalCluster.vue
│   │   │       │   ├── CanalConfig.vue
│   │   │       │   ├── CanalInstance.vue
│   │   │       │   ├── CanalInstanceAdd.vue
│   │   │       │   ├── CanalInstanceLogDetail.vue
│   │   │       │   ├── CanalInstanceUpdate.vue
│   │   │       │   ├── CanalLogDetail.vue
│   │   │       │   └── NodeServer.vue
│   │   │       ├── dashboard/
│   │   │       │   └── index.vue
│   │   │       ├── login/
│   │   │       │   └── index.vue
│   │   │       └── sys/
│   │   │           └── UserInfo.vue
│   │   ├── tests/
│   │   │   └── unit/
│   │   │       ├── .eslintrc.js
│   │   │       ├── components/
│   │   │       │   ├── Breadcrumb.spec.js
│   │   │       │   ├── Hamburger.spec.js
│   │   │       │   └── SvgIcon.spec.js
│   │   │       └── utils/
│   │   │           ├── formatTime.spec.js
│   │   │           ├── parseTime.spec.js
│   │   │           └── validate.spec.js
│   │   └── vue.config.js
│   ├── admin-web/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   ├── assembly/
│   │       │   │   ├── dev.xml
│   │       │   │   └── release.xml
│   │       │   ├── bin/
│   │       │   │   ├── restart.sh
│   │       │   │   ├── startup.bat
│   │       │   │   ├── startup.sh
│   │       │   │   └── stop.sh
│   │       │   ├── java/
│   │       │   │   └── com/
│   │       │   │       └── alibaba/
│   │       │   │           └── otter/
│   │       │   │               └── canal/
│   │       │   │                   └── admin/
│   │       │   │                       ├── CanalAdminApplication.java
│   │       │   │                       ├── common/
│   │       │   │                       │   ├── DaemonThreadFactory.java
│   │       │   │                       │   ├── TemplateConfigLoader.java
│   │       │   │                       │   ├── Threads.java
│   │       │   │                       │   └── exception/
│   │       │   │                       │       └── ServiceException.java
│   │       │   │                       ├── config/
│   │       │   │                       │   ├── EbeanConfig.java
│   │       │   │                       │   ├── SpringContext.java
│   │       │   │                       │   └── WebConfig.java
│   │       │   │                       ├── connector/
│   │       │   │                       │   ├── AdminConnector.java
│   │       │   │                       │   ├── SimpleAdminConnector.java
│   │       │   │                       │   └── SimpleAdminConnectors.java
│   │       │   │                       ├── controller/
│   │       │   │                       │   ├── CanalClusterController.java
│   │       │   │                       │   ├── CanalConfigController.java
│   │       │   │                       │   ├── CanalInstanceController.java
│   │       │   │                       │   ├── NodeServerController.java
│   │       │   │                       │   ├── PollingConfigController.java
│   │       │   │                       │   └── UserController.java
│   │       │   │                       ├── handler/
│   │       │   │                       │   └── CustomExceptionHandler.java
│   │       │   │                       ├── model/
│   │       │   │                       │   ├── BaseModel.java
│   │       │   │                       │   ├── CanalCluster.java
│   │       │   │                       │   ├── CanalConfig.java
│   │       │   │                       │   ├── CanalInstanceConfig.java
│   │       │   │                       │   ├── Model.java
│   │       │   │                       │   ├── NodeServer.java
│   │       │   │                       │   ├── Pager.java
│   │       │   │                       │   └── User.java
│   │       │   │                       └── service/
│   │       │   │                           ├── CanalClusterService.java
│   │       │   │                           ├── CanalConfigService.java
│   │       │   │                           ├── CanalInstanceService.java
│   │       │   │                           ├── NodeServerService.java
│   │       │   │                           ├── PollingConfigService.java
│   │       │   │                           ├── UserService.java
│   │       │   │                           └── impl/
│   │       │   │                               ├── CanalClusterServiceImpl.java
│   │       │   │                               ├── CanalConfigServiceImpl.java
│   │       │   │                               ├── CanalInstanceServiceImpl.java
│   │       │   │                               ├── NodeServerServiceImpl.java
│   │       │   │                               ├── PollingConfigServiceImpl.java
│   │       │   │                               └── UserServiceImpl.java
│   │       │   └── resources/
│   │       │       ├── application.yml
│   │       │       ├── canal-template.properties
│   │       │       ├── canal_manager.sql
│   │       │       ├── instance-template.properties
│   │       │       ├── logback.xml
│   │       │       └── public/
│   │       │           ├── index.html
│   │       │           └── static/
│   │       │               ├── css/
│   │       │               │   ├── app.bb951cb3.css
│   │       │               │   ├── chunk-101fc062.fad9926f.css
│   │       │               │   ├── chunk-14b5f7a4.f3e06673.css
│   │       │               │   ├── chunk-22553be3.f3e06673.css
│   │       │               │   ├── chunk-2301924a.160e7b4a.css
│   │       │               │   ├── chunk-2b9b6c5c.c89f8844.css
│   │       │               │   ├── chunk-37c49cbf.efc21a9c.css
│   │       │               │   ├── chunk-49959c8b.e8e2beee.css
│   │       │               │   ├── chunk-4f09fed2.70ec0b86.css
│   │       │               │   ├── chunk-5afa45f5.a34bb177.css
│   │       │               │   ├── chunk-5b373aad.b966d36b.css
│   │       │               │   ├── chunk-69386cf0.741ff14e.css
│   │       │               │   ├── chunk-7ec889b7.c0585512.css
│   │       │               │   ├── chunk-98f505d0.5280f88f.css
│   │       │               │   ├── chunk-bd1d44ee.1528199a.css
│   │       │               │   ├── chunk-da289616.c89f8844.css
│   │       │               │   ├── chunk-elementUI.18b11d0e.css
│   │       │               │   └── chunk-libs.5cf311f0.css
│   │       │               └── js/
│   │       │                   ├── app.6845b228.js
│   │       │                   ├── app.eee35d99.js
│   │       │                   ├── chunk-0dca2f22.a2bc28b8.js
│   │       │                   ├── chunk-101fc062.372a5ca5.js
│   │       │                   ├── chunk-101fc062.bc898027.js
│   │       │                   ├── chunk-14b5f7a4.013449e9.js
│   │       │                   ├── chunk-22553be3.e6d72de5.js
│   │       │                   ├── chunk-2301924a.1774b851.js
│   │       │                   ├── chunk-2b9b6c5c.cc2181b9.js
│   │       │                   ├── chunk-37c49cbf.64d26540.js
│   │       │                   ├── chunk-37c49cbf.92ebe0ae.js
│   │       │                   ├── chunk-49959c8b.058266cb.js
│   │       │                   ├── chunk-49959c8b.6d226f70.js
│   │       │                   ├── chunk-4f09fed2.d107437b.js
│   │       │                   ├── chunk-4f09fed2.ff28d88d.js
│   │       │                   ├── chunk-55380ff2.430ee174.js
│   │       │                   ├── chunk-55380ff2.681c71c9.js
│   │       │                   ├── chunk-5afa45f5.79ddcc04.js
│   │       │                   ├── chunk-5b373aad.90a2d8e7.js
│   │       │                   ├── chunk-69386cf0.76d77f5c.js
│   │       │                   ├── chunk-69386cf0.bdbe3f0c.js
│   │       │                   ├── chunk-7ec889b7.5f730d9b.js
│   │       │                   ├── chunk-7ec889b7.bd1ca803.js
│   │       │                   ├── chunk-98f505d0.f3096ce7.js
│   │       │                   ├── chunk-bd1d44ee.8c8282cc.js
│   │       │                   ├── chunk-bd1d44ee.8e2c4851.js
│   │       │                   ├── chunk-da289616.7def925e.js
│   │       │                   ├── chunk-elementUI.667f4c87.js
│   │       │                   └── chunk-libs.c04beefc.js
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── alibaba/
│   │                       └── otter/
│   │                           └── canal/
│   │                               └── admin/
│   │                                   └── SimpleAdminConnectorTest.java
│   └── pom.xml
├── charts/
│   ├── README.md
│   ├── canal-admin/
│   │   ├── .helmignore
│   │   ├── Chart.yaml
│   │   ├── templates/
│   │   │   ├── NOTES.txt
│   │   │   ├── _helpers.tpl
│   │   │   ├── deployment.yaml
│   │   │   ├── hpa.yaml
│   │   │   ├── ingress.yaml
│   │   │   ├── secret.yaml
│   │   │   ├── service.yaml
│   │   │   ├── serviceaccount.yaml
│   │   │   └── tests/
│   │   │       └── test-connection.yaml
│   │   └── values.yaml
│   ├── canal-server/
│   │   ├── .helmignore
│   │   ├── Chart.yaml
│   │   ├── templates/
│   │   │   ├── NOTES.txt
│   │   │   ├── _helpers.tpl
│   │   │   ├── hpa.yaml
│   │   │   ├── secret.yaml
│   │   │   ├── service.yaml
│   │   │   ├── serviceaccount.yaml
│   │   │   ├── statefulsets.yaml
│   │   │   └── tests/
│   │   │       └── test-connection.yaml
│   │   └── values.yaml
│   └── tests/
│       ├── admin-values.yaml
│       ├── server-values.yaml
│       └── test.sh
├── client/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── alibaba/
│       │               └── otter/
│       │                   └── canal/
│       │                       └── client/
│       │                           ├── CanalConnector.java
│       │                           ├── CanalConnectors.java
│       │                           ├── CanalMQConnector.java
│       │                           ├── CanalMessageDeserializer.java
│       │                           ├── CanalNodeAccessStrategy.java
│       │                           ├── ConsumerBatchMessage.java
│       │                           ├── impl/
│       │                           │   ├── ClusterCanalConnector.java
│       │                           │   ├── ClusterNodeAccessStrategy.java
│       │                           │   ├── ServerNotFoundException.java
│       │                           │   ├── SimpleCanalConnector.java
│       │                           │   ├── SimpleNodeAccessStrategy.java
│       │                           │   └── running/
│       │                           │       ├── ClientRunningData.java
│       │                           │       ├── ClientRunningListener.java
│       │                           │       └── ClientRunningMonitor.java
│       │                           ├── kafka/
│       │                           │   ├── KafkaCanalConnector.java
│       │                           │   ├── KafkaOffsetCanalConnector.java
│       │                           │   ├── MessageDeserializer.java
│       │                           │   └── protocol/
│       │                           │       ├── KafkaFlatMessage.java
│       │                           │       └── KafkaMessage.java
│       │                           ├── pulsarmq/
│       │                           │   └── PulsarMQCanalConnector.java
│       │                           ├── rabbitmq/
│       │                           │   ├── AliyunCredentialsProvider.java
│       │                           │   └── RabbitMQCanalConnector.java
│       │                           └── rocketmq/
│       │                               └── RocketMQCanalConnector.java
│       └── test/
│           └── java/
│               ├── com/
│               │   └── alibaba/
│               │       └── otter/
│               │           └── canal/
│               │               └── client/
│               │                   └── running/
│               │                       ├── AbstractZkTest.java
│               │                       └── ClientRunningTest.java
│               └── logback.xml
├── client-adapter/
│   ├── README.md
│   ├── clickhouse/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   ├── java/
│   │       │   │   └── com/
│   │       │   │       └── alibaba/
│   │       │   │           └── otter/
│   │       │   │               └── canal/
│   │       │   │                   └── client/
│   │       │   │                       └── adapter/
│   │       │   │                           └── clickhouse/
│   │       │   │                               ├── ClickHouseAdapter.java
│   │       │   │                               ├── config/
│   │       │   │                               │   ├── ConfigLoader.java
│   │       │   │                               │   ├── MappingConfig.java
│   │       │   │                               │   └── MirrorDbConfig.java
│   │       │   │                               ├── monitor/
│   │       │   │                               │   └── ClickHouseConfigMonitor.java
│   │       │   │                               ├── service/
│   │       │   │                               │   ├── ClickHouseBatchSyncService.java
│   │       │   │                               │   ├── ClickHouseEtlService.java
│   │       │   │                               │   └── ClickHouseMirrorDbBatchSyncService.java
│   │       │   │                               └── support/
│   │       │   │                                   ├── BatchExecutor.java
│   │       │   │                                   ├── SingleDml.java
│   │       │   │                                   └── SyncUtil.java
│   │       │   └── resources/
│   │       │       ├── META-INF/
│   │       │       │   └── canal/
│   │       │       │       └── com.alibaba.otter.canal.client.adapter.OuterAdapter
│   │       │       └── clickhouse/
│   │       │           └── mytest_user.yml
│   │       └── test/
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── alibaba/
│   │           │           └── otter/
│   │           │               └── canal/
│   │           │                   └── client/
│   │           │                       └── adapter/
│   │           │                           └── clickhouse/
│   │           │                               ├── ClickHouseBatchSyncServiceTest.java
│   │           │                               ├── ClickHouseBatchSyncThreadSafeTest.java
│   │           │                               ├── TestConstant.java
│   │           │                               └── sync/
│   │           │                                   └── Common.java
│   │           └── resources/
│   │               └── clickhouse/
│   │                   ├── mytest_customer.yml
│   │                   └── mytest_user.yml
│   ├── common/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       └── com/
│   │       │           └── alibaba/
│   │       │               └── otter/
│   │       │                   └── canal/
│   │       │                       └── client/
│   │       │                           └── adapter/
│   │       │                               ├── OuterAdapter.java
│   │       │                               ├── ProxyOuterAdapter.java
│   │       │                               └── support/
│   │       │                                   ├── AbstractEtlService.java
│   │       │                                   ├── AdapterConfig.java
│   │       │                                   ├── CanalClientConfig.java
│   │       │                                   ├── Constant.java
│   │       │                                   ├── DaemonThreadFactory.java
│   │       │                                   ├── DatasourceConfig.java
│   │       │                                   ├── Dml.java
│   │       │                                   ├── EtlResult.java
│   │       │                                   ├── ExtensionLoader.java
│   │       │                                   ├── FileName2KeyMapping.java
│   │       │                                   ├── JdbcTypeUtil.java
│   │       │                                   ├── MappingConfigsLoader.java
│   │       │                                   ├── MessageUtil.java
│   │       │                                   ├── OuterAdapterConfig.java
│   │       │                                   ├── Result.java
│   │       │                                   ├── SPI.java
│   │       │                                   ├── URLClassExtensionLoader.java
│   │       │                                   ├── Util.java
│   │       │                                   └── YamlUtils.java
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── alibaba/
│   │                       └── otter/
│   │                           └── canal/
│   │                               └── client/
│   │                                   └── adapter/
│   │                                       └── support/
│   │                                           ├── JdbcTypeUtilTest.java
│   │                                           ├── UtilTest.java
│   │                                           └── YamlUtilsTest.java
│   ├── es6x/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   ├── java/
│   │       │   │   ├── com/
│   │       │   │   │   └── alibaba/
│   │       │   │   │       └── otter/
│   │       │   │   │           └── canal/
│   │       │   │   │               └── client/
│   │       │   │   │                   └── adapter/
│   │       │   │   │                       └── es6x/
│   │       │   │   │                           ├── ES6xAdapter.java
│   │       │   │   │                           ├── etl/
│   │       │   │   │                           │   └── ESEtlService.java
│   │       │   │   │                           └── support/
│   │       │   │   │                               ├── ES6xTemplate.java
│   │       │   │   │                               └── ESConnection.java
│   │       │   │   └── org/
│   │       │   │       └── elasticsearch/
│   │       │   │           └── client/
│   │       │   │               ├── RequestConvertersExt.java
│   │       │   │               └── RestHighLevelClientExt.java
│   │       │   └── resources/
│   │       │       ├── META-INF/
│   │       │       │   └── canal/
│   │       │       │       └── com.alibaba.otter.canal.client.adapter.OuterAdapter
│   │       │       └── es6/
│   │       │           ├── biz_order.yml
│   │       │           ├── customer.yml
│   │       │           └── mytest_user.yml
│   │       └── test/
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── alibaba/
│   │           │           └── otter/
│   │           │               └── canal/
│   │           │                   └── client/
│   │           │                       └── adapter/
│   │           │                           └── es6x/
│   │           │                               └── test/
│   │           │                                   ├── ConfigLoadTest.java
│   │           │                                   ├── ESTest.java
│   │           │                                   ├── SqlParseTest.java
│   │           │                                   ├── TestConstant.java
│   │           │                                   └── sync/
│   │           │                                       ├── Common.java
│   │           │                                       ├── LabelSyncJoinSub2Test.java
│   │           │                                       ├── LabelSyncJoinSubTest.java
│   │           │                                       ├── RoleSyncJoinOne2Test.java
│   │           │                                       ├── RoleSyncJoinOneTest.java
│   │           │                                       ├── UserSyncJoinOneTest.java
│   │           │                                       ├── UserSyncSingleTest.java
│   │           │                                       ├── db_schema.sql
│   │           │                                       └── es_mapping.json
│   │           └── resources/
│   │               ├── es6/
│   │               │   └── mytest_user_single.yml
│   │               ├── log4j2-test.xml
│   │               └── logback-test.xml
│   ├── es7x/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   ├── java/
│   │       │   │   └── com/
│   │       │   │       └── alibaba/
│   │       │   │           └── otter/
│   │       │   │               └── canal/
│   │       │   │                   └── client/
│   │       │   │                       └── adapter/
│   │       │   │                           └── es7x/
│   │       │   │                               ├── ES7xAdapter.java
│   │       │   │                               ├── etl/
│   │       │   │                               │   └── ESEtlService.java
│   │       │   │                               └── support/
│   │       │   │                                   ├── ES7xTemplate.java
│   │       │   │                                   └── ESConnection.java
│   │       │   └── resources/
│   │       │       ├── META-INF/
│   │       │       │   └── canal/
│   │       │       │       └── com.alibaba.otter.canal.client.adapter.OuterAdapter
│   │       │       └── es7/
│   │       │           ├── biz_order.yml
│   │       │           ├── customer.yml
│   │       │           └── mytest_user.yml
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── alibaba/
│   │                       └── otter/
│   │                           └── canal/
│   │                               └── client/
│   │                                   └── adapter/
│   │                                       └── es7x/
│   │                                           └── test/
│   │                                               ├── ES7xTest.java
│   │                                               ├── ESConnectionTest.java
│   │                                               └── TestConstant.java
│   ├── es8x/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   ├── java/
│   │       │   │   └── com/
│   │       │   │       └── alibaba/
│   │       │   │           └── otter/
│   │       │   │               └── canal/
│   │       │   │                   └── client/
│   │       │   │                       └── adapter/
│   │       │   │                           └── es8x/
│   │       │   │                               ├── ES8xAdapter.java
│   │       │   │                               ├── etl/
│   │       │   │                               │   └── ESEtlService.java
│   │       │   │                               └── support/
│   │       │   │                                   ├── ES8xTemplate.java
│   │       │   │                                   └── ESConnection.java
│   │       │   └── resources/
│   │       │       ├── META-INF/
│   │       │       │   └── canal/
│   │       │       │       └── com.alibaba.otter.canal.client.adapter.OuterAdapter
│   │       │       └── es8/
│   │       │           ├── biz_order.yml
│   │       │           ├── customer.yml
│   │       │           └── mytest_user.yml
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── alibaba/
│   │                       └── otter/
│   │                           └── canal/
│   │                               └── client/
│   │                                   └── adapter/
│   │                                       └── es8x/
│   │                                           └── test/
│   │                                               ├── ESConnectionTest.java
│   │                                               └── TestConstant.java
│   ├── escore/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       └── com/
│   │       │           └── alibaba/
│   │       │               └── otter/
│   │       │                   └── canal/
│   │       │                       └── client/
│   │       │                           └── adapter/
│   │       │                               └── es/
│   │       │                                   └── core/
│   │       │                                       ├── ESAdapter.java
│   │       │                                       ├── config/
│   │       │                                       │   ├── ESSyncConfig.java
│   │       │                                       │   ├── ESSyncConfigLoader.java
│   │       │                                       │   ├── SchemaItem.java
│   │       │                                       │   └── SqlParser.java
│   │       │                                       ├── monitor/
│   │       │                                       │   └── ESConfigMonitor.java
│   │       │                                       ├── service/
│   │       │                                       │   └── ESSyncService.java
│   │       │                                       └── support/
│   │       │                                           ├── ESBulkRequest.java
│   │       │                                           ├── ESSyncUtil.java
│   │       │                                           └── ESTemplate.java
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── alibaba/
│   │                       └── otter/
│   │                           └── canal/
│   │                               └── client/
│   │                                   └── adapter/
│   │                                       └── es/
│   │                                           └── core/
│   │                                               └── support/
│   │                                                   └── ESSyncUtilTest.java
│   ├── hbase/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   ├── java/
│   │       │   │   └── com/
│   │       │   │       └── alibaba/
│   │       │   │           └── otter/
│   │       │   │               └── canal/
│   │       │   │                   └── client/
│   │       │   │                       └── adapter/
│   │       │   │                           └── hbase/
│   │       │   │                               ├── HbaseAdapter.java
│   │       │   │                               ├── config/
│   │       │   │                               │   ├── MappingConfig.java
│   │       │   │                               │   └── MappingConfigLoader.java
│   │       │   │                               ├── monitor/
│   │       │   │                               │   └── HbaseConfigMonitor.java
│   │       │   │                               ├── service/
│   │       │   │                               │   ├── HbaseEtlService.java
│   │       │   │                               │   └── HbaseSyncService.java
│   │       │   │                               └── support/
│   │       │   │                                   ├── HRow.java
│   │       │   │                                   ├── HbaseTemplate.java
│   │       │   │                                   ├── PhType.java
│   │       │   │                                   ├── PhTypeUtil.java
│   │       │   │                                   ├── Type.java
│   │       │   │                                   └── TypeUtil.java
│   │       │   └── resources/
│   │       │       ├── META-INF/
│   │       │       │   └── canal/
│   │       │       │       └── com.alibaba.otter.canal.client.adapter.OuterAdapter
│   │       │       └── hbase/
│   │       │           └── mytest_person2.yml
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── alibaba/
│   │                       └── otter/
│   │                           └── canal/
│   │                               └── client/
│   │                                   └── adapter/
│   │                                       └── hbase/
│   │                                           └── test/
│   │                                               └── HBaseConnectionTest.java
│   ├── kudu/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   ├── java/
│   │       │   │   └── com/
│   │       │   │       └── alibaba/
│   │       │   │           └── otter/
│   │       │   │               └── canal/
│   │       │   │                   └── client/
│   │       │   │                       └── adapter/
│   │       │   │                           └── kudu/
│   │       │   │                               ├── KuduAdapter.java
│   │       │   │                               ├── config/
│   │       │   │                               │   ├── KuduMappingConfig.java
│   │       │   │                               │   └── KuduMappingConfigLoader.java
│   │       │   │                               ├── monitor/
│   │       │   │                               │   └── KuduConfigMonitor.java
│   │       │   │                               ├── service/
│   │       │   │                               │   ├── KuduEtlService.java
│   │       │   │                               │   └── KuduSyncService.java
│   │       │   │                               └── support/
│   │       │   │                                   ├── KuduTemplate.java
│   │       │   │                                   └── SyncUtil.java
│   │       │   └── resources/
│   │       │       ├── META-INF.canal/
│   │       │       │   └── com.alibaba.otter.canal.client.adapter.OuterAdapter
│   │       │       └── kudu/
│   │       │           └── kudutest_user.yml
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── alibaba/
│   │                       └── otter/
│   │                           └── canal/
│   │                               └── client/
│   │                                   └── adapter/
│   │                                       └── kudu/
│   │                                           └── test/
│   │                                               ├── KuduConnectionTest.java
│   │                                               ├── TestConfig.java
│   │                                               ├── TestConstant.java
│   │                                               └── sync/
│   │                                                   ├── Common.java
│   │                                                   └── TestSyncKudu.java
│   ├── launcher/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           ├── assembly/
│   │           │   ├── dev.xml
│   │           │   └── release.xml
│   │           ├── bin/
│   │           │   ├── restart.sh
│   │           │   ├── startup.bat
│   │           │   ├── startup.sh
│   │           │   └── stop.sh
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── alibaba/
│   │           │           └── otter/
│   │           │               └── canal/
│   │           │                   └── adapter/
│   │           │                       └── launcher/
│   │           │                           ├── CanalAdapterApplication.java
│   │           │                           ├── common/
│   │           │                           │   ├── EtlLock.java
│   │           │                           │   ├── Mode.java
│   │           │                           │   └── SyncSwitch.java
│   │           │                           ├── config/
│   │           │                           │   ├── AdapterCanalConfig.java
│   │           │                           │   ├── AdapterConfigHolder.java
│   │           │                           │   ├── BootstrapConfiguration.java
│   │           │                           │   ├── CuratorClient.java
│   │           │                           │   ├── DruidConfig.java
│   │           │                           │   └── SpringContext.java
│   │           │                           ├── loader/
│   │           │                           │   ├── AdapterProcessor.java
│   │           │                           │   ├── CanalAdapterLoader.java
│   │           │                           │   └── CanalAdapterService.java
│   │           │                           ├── monitor/
│   │           │                           │   ├── ApplicationConfigMonitor.java
│   │           │                           │   └── remote/
│   │           │                           │       ├── ConfigItem.java
│   │           │                           │       ├── DbRemoteConfigLoader.java
│   │           │                           │       ├── RemoteAdapterMonitor.java
│   │           │                           │       ├── RemoteAdapterMonitorImpl.java
│   │           │                           │       ├── RemoteConfigLoader.java
│   │           │                           │       └── RemoteConfigLoaderFactory.java
│   │           │                           ├── prometheus/
│   │           │                           │   ├── CanalAdapterExports.java
│   │           │                           │   └── PrometheusService.java
│   │           │                           └── rest/
│   │           │                               └── CommonRest.java
│   │           └── resources/
│   │               ├── META-INF/
│   │               │   └── spring.factories
│   │               ├── application.yml
│   │               ├── bootstrap.yml
│   │               └── logback.xml
│   ├── logger/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── alibaba/
│   │           │           └── otter/
│   │           │               └── canal/
│   │           │                   └── client/
│   │           │                       └── adapter/
│   │           │                           └── logger/
│   │           │                               └── LoggerAdapterExample.java
│   │           └── resources/
│   │               └── META-INF/
│   │                   └── canal/
│   │                       └── com.alibaba.otter.canal.client.adapter.OuterAdapter
│   ├── phoenix/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   ├── java/
│   │       │   │   └── com/
│   │       │   │       └── alibaba/
│   │       │   │           └── otter/
│   │       │   │               └── canal/
│   │       │   │                   └── client/
│   │       │   │                       └── adapter/
│   │       │   │                           └── phoenix/
│   │       │   │                               ├── PhoenixAdapter.java
│   │       │   │                               ├── config/
│   │       │   │                               │   ├── ConfigLoader.java
│   │       │   │                               │   ├── ConfigurationManager.java
│   │       │   │                               │   └── MappingConfig.java
│   │       │   │                               ├── monitor/
│   │       │   │                               │   └── PhoenixConfigMonitor.java
│   │       │   │                               ├── service/
│   │       │   │                               │   ├── PhoenixEtlService.java
│   │       │   │                               │   └── PhoenixSyncService.java
│   │       │   │                               └── support/
│   │       │   │                                   ├── BatchExecutor.java
│   │       │   │                                   ├── PhoenixSupportUtil.java
│   │       │   │                                   ├── SingleDml.java
│   │       │   │                                   ├── SyncUtil.java
│   │       │   │                                   └── TypeUtil.java
│   │       │   └── resources/
│   │       │       ├── META-INF/
│   │       │       │   └── canal/
│   │       │       │       └── com.alibaba.otter.canal.client.adapter.OuterAdapter
│   │       │       ├── hbase-site.xml
│   │       │       └── phoenix/
│   │       │           ├── phoenix_common.properties
│   │       │           └── phoenixtest_user.yml
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── alibaba/
│   │                       └── otter/
│   │                           └── canal/
│   │                               └── client/
│   │                                   └── adapter/
│   │                                       └── phoenix/
│   │                                           └── test/
│   │                                               ├── PhoenixConnectionTest.java
│   │                                               ├── TestConfigLoad.java
│   │                                               ├── TestConstant.java
│   │                                               └── sync/
│   │                                                   ├── Common.java
│   │                                                   └── PhoenixSyncTest.java
│   ├── pom.xml
│   ├── rdb/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   ├── java/
│   │       │   │   └── com/
│   │       │   │       └── alibaba/
│   │       │   │           └── otter/
│   │       │   │               └── canal/
│   │       │   │                   └── client/
│   │       │   │                       └── adapter/
│   │       │   │                           └── rdb/
│   │       │   │                               ├── RdbAdapter.java
│   │       │   │                               ├── config/
│   │       │   │                               │   ├── ConfigLoader.java
│   │       │   │                               │   ├── MappingConfig.java
│   │       │   │                               │   └── MirrorDbConfig.java
│   │       │   │                               ├── monitor/
│   │       │   │                               │   └── RdbConfigMonitor.java
│   │       │   │                               ├── service/
│   │       │   │                               │   ├── RdbEtlService.java
│   │       │   │                               │   ├── RdbMirrorDbSyncService.java
│   │       │   │                               │   └── RdbSyncService.java
│   │       │   │                               └── support/
│   │       │   │                                   ├── BatchExecutor.java
│   │       │   │                                   ├── SingleDml.java
│   │       │   │                                   └── SyncUtil.java
│   │       │   └── resources/
│   │       │       ├── META-INF/
│   │       │       │   └── canal/
│   │       │       │       └── com.alibaba.otter.canal.client.adapter.OuterAdapter
│   │       │       └── rdb/
│   │       │           └── mytest_user.yml
│   │       └── test/
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── alibaba/
│   │           │           └── otter/
│   │           │               └── canal/
│   │           │                   └── client/
│   │           │                       └── adapter/
│   │           │                           └── rdb/
│   │           │                               └── test/
│   │           │                                   ├── ConfigLoadTest.java
│   │           │                                   ├── DBTest.java
│   │           │                                   ├── SqlParserTest.java
│   │           │                                   ├── TestConstant.java
│   │           │                                   └── sync/
│   │           │                                       ├── Common.java
│   │           │                                       └── OracleSyncTest.java
│   │           └── resources/
│   │               ├── log4j2-test.xml
│   │               ├── logback-test.xml
│   │               └── rdb/
│   │                   └── mytest_user.yml
│   └── tablestore/
│       ├── pom.xml
│       └── src/
│           └── main/
│               ├── java/
│               │   └── com/
│               │       └── alibaba/
│               │           └── otter/
│               │               └── canal/
│               │                   └── client/
│               │                       └── adapter/
│               │                           └── tablestore/
│               │                               ├── TablestoreAdapter.java
│               │                               ├── common/
│               │                               │   └── PropertyConstants.java
│               │                               ├── config/
│               │                               │   ├── ConfigLoader.java
│               │                               │   └── MappingConfig.java
│               │                               ├── enums/
│               │                               │   └── TablestoreFieldType.java
│               │                               ├── service/
│               │                               │   ├── TablestoreEtlService.java
│               │                               │   └── TablestoreSyncService.java
│               │                               └── support/
│               │                                   └── SyncUtil.java
│               └── resources/
│                   ├── META-INF/
│                   │   └── canal/
│                   │       └── com.alibaba.otter.canal.client.adapter.OuterAdapter
│                   └── tablestore/
│                       └── test.yml
├── codeformat.xml
├── codetemplates.xml
├── common/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           ├── alibaba/
│       │           │   └── otter/
│       │           │       └── canal/
│       │           │           └── common/
│       │           │               ├── AbstractCanalLifeCycle.java
│       │           │               ├── CanalException.java
│       │           │               ├── CanalLifeCycle.java
│       │           │               ├── alarm/
│       │           │               │   ├── CanalAlarmHandler.java
│       │           │               │   └── LogAlarmHandler.java
│       │           │               ├── utils/
│       │           │               │   ├── AddressUtils.java
│       │           │               │   ├── BooleanMutex.java
│       │           │               │   ├── CanalToStringStyle.java
│       │           │               │   ├── CommonUtils.java
│       │           │               │   ├── ExecutorTemplate.java
│       │           │               │   ├── FileUtils.java
│       │           │               │   ├── JsonUtils.java
│       │           │               │   ├── MQUtil.java
│       │           │               │   ├── NamedThreadFactory.java
│       │           │               │   ├── PropertiesUtils.java
│       │           │               │   └── UriUtils.java
│       │           │               └── zookeeper/
│       │           │                   ├── ByteSerializer.java
│       │           │                   ├── StringSerializer.java
│       │           │                   ├── ZkClientx.java
│       │           │                   ├── ZooKeeperx.java
│       │           │                   ├── ZookeeperPathUtils.java
│       │           │                   └── running/
│       │           │                       ├── ServerRunningData.java
│       │           │                       ├── ServerRunningListener.java
│       │           │                       ├── ServerRunningMonitor.java
│       │           │                       └── ServerRunningMonitors.java
│       │           └── google/
│       │               └── common/
│       │                   └── collect/
│       │                       └── MigrateMap.java
│       └── test/
│           └── java/
│               ├── com/
│               │   └── alibaba/
│               │       └── otter/
│               │           └── canal/
│               │               └── common/
│               │                   ├── AbstractZkTest.java
│               │                   ├── JsonUtilsTest.java
│               │                   ├── ServerRunningTest.java
│               │                   └── utils/
│               │                       └── BooleanMutexTest.java
│               └── logback.xml
├── connector/
│   ├── core/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           └── java/
│   │               └── com/
│   │                   └── alibaba/
│   │                       └── otter/
│   │                           └── canal/
│   │                               └── connector/
│   │                                   └── core/
│   │                                       ├── config/
│   │                                       │   ├── CanalConstants.java
│   │                                       │   └── MQProperties.java
│   │                                       ├── consumer/
│   │                                       │   └── CommonMessage.java
│   │                                       ├── filter/
│   │                                       │   ├── AviaterRegexFilter.java
│   │                                       │   ├── PatternUtils.java
│   │                                       │   └── RegexFunction.java
│   │                                       ├── producer/
│   │                                       │   ├── AbstractMQProducer.java
│   │                                       │   ├── MQDestination.java
│   │                                       │   └── MQMessageUtils.java
│   │                                       ├── spi/
│   │                                       │   ├── CanalMQProducer.java
│   │                                       │   ├── CanalMsgConsumer.java
│   │                                       │   ├── ExtensionLoader.java
│   │                                       │   ├── ProxyCanalMQProducer.java
│   │                                       │   ├── ProxyCanalMsgConsumer.java
│   │                                       │   ├── SPI.java
│   │                                       │   └── URLClassExtensionLoader.java
│   │                                       └── util/
│   │                                           ├── Callback.java
│   │                                           ├── CanalMessageSerializerUtil.java
│   │                                           ├── DateUtil.java
│   │                                           ├── JdbcTypeUtil.java
│   │                                           ├── MessageUtil.java
│   │                                           └── TimeZone.java
│   ├── kafka-connector/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   ├── java/
│   │       │   │   └── com/
│   │       │   │       └── alibaba/
│   │       │   │           └── otter/
│   │       │   │               └── canal/
│   │       │   │                   └── connector/
│   │       │   │                       └── kafka/
│   │       │   │                           ├── config/
│   │       │   │                           │   ├── KafkaConstants.java
│   │       │   │                           │   └── KafkaProducerConfig.java
│   │       │   │                           ├── consumer/
│   │       │   │                           │   ├── CanalKafkaConsumer.java
│   │       │   │                           │   └── KafkaMessageDeserializer.java
│   │       │   │                           └── producer/
│   │       │   │                               ├── CanalKafkaProducer.java
│   │       │   │                               └── KafkaMessageSerializer.java
│   │       │   └── resources/
│   │       │       └── META-INF/
│   │       │           └── canal/
│   │       │               ├── com.alibaba.otter.canal.connector.core.spi.CanalMQProducer
│   │       │               └── com.alibaba.otter.canal.connector.core.spi.CanalMsgConsumer
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── alibaba/
│   │                       └── otter/
│   │                           └── canal/
│   │                               └── connector/
│   │                                   └── kafka/
│   │                                       └── test/
│   │                                           └── CanalKafkaProducerTest.java
│   ├── pom.xml
│   ├── pulsarmq-connector/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   ├── java/
│   │       │   │   └── com/
│   │       │   │       └── alibaba/
│   │       │   │           └── otter/
│   │       │   │               └── canal/
│   │       │   │                   └── connector/
│   │       │   │                       └── pulsarmq/
│   │       │   │                           ├── config/
│   │       │   │                           │   ├── PulsarMQConstants.java
│   │       │   │                           │   └── PulsarMQProducerConfig.java
│   │       │   │                           ├── consumer/
│   │       │   │                           │   └── CanalPulsarMQConsumer.java
│   │       │   │                           └── producer/
│   │       │   │                               └── CanalPulsarMQProducer.java
│   │       │   └── resources/
│   │       │       └── META-INF/
│   │       │           └── canal/
│   │       │               ├── com.alibaba.otter.canal.connector.core.spi.CanalMQProducer
│   │       │               └── com.alibaba.otter.canal.connector.core.spi.CanalMsgConsumer
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── alibaba/
│   │                       └── otter/
│   │                           └── canal/
│   │                               └── connector/
│   │                                   └── pulsarmq/
│   │                                       └── consumer/
│   │                                           └── CanalPulsarMQConsumerTest.java
│   ├── rabbitmq-connector/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── alibaba/
│   │           │           └── otter/
│   │           │               └── canal/
│   │           │                   └── connector/
│   │           │                       └── rabbitmq/
│   │           │                           ├── config/
│   │           │                           │   ├── RabbitMQConstants.java
│   │           │                           │   └── RabbitMQProducerConfig.java
│   │           │                           ├── consumer/
│   │           │                           │   ├── CanalRabbitMQConsumer.java
│   │           │                           │   └── ConsumerBatchMessage.java
│   │           │                           └── producer/
│   │           │                               ├── AliyunCredentialsProvider.java
│   │           │                               └── CanalRabbitMQProducer.java
│   │           └── resources/
│   │               └── META-INF/
│   │                   └── canal/
│   │                       ├── com.alibaba.otter.canal.connector.core.spi.CanalMQProducer
│   │                       └── com.alibaba.otter.canal.connector.core.spi.CanalMsgConsumer
│   ├── rocketmq-connector/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── alibaba/
│   │           │           └── otter/
│   │           │               └── canal/
│   │           │                   └── connector/
│   │           │                       └── rocketmq/
│   │           │                           ├── config/
│   │           │                           │   ├── RocketMQConstants.java
│   │           │                           │   └── RocketMQProducerConfig.java
│   │           │                           ├── consumer/
│   │           │                           │   ├── CanalRocketMQConsumer.java
│   │           │                           │   └── ConsumerBatchMessage.java
│   │           │                           └── producer/
│   │           │                               └── CanalRocketMQProducer.java
│   │           └── resources/
│   │               └── META-INF/
│   │                   └── canal/
│   │                       ├── com.alibaba.otter.canal.connector.core.spi.CanalMQProducer
│   │                       └── com.alibaba.otter.canal.connector.core.spi.CanalMsgConsumer
│   └── tcp-connector/
│       ├── pom.xml
│       └── src/
│           └── main/
│               ├── java/
│               │   └── com/
│               │       └── alibaba/
│               │           └── otter/
│               │               └── canal/
│               │                   └── connector/
│               │                       └── tcp/
│               │                           ├── config/
│               │                           │   └── TCPConstants.java
│               │                           └── consumer/
│               │                               └── CanalTCPConsumer.java
│               └── resources/
│                   └── META-INF/
│                       └── canal/
│                           └── com.alibaba.otter.canal.connector.core.spi.CanalMsgConsumer
├── dbsync/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── taobao/
│       │               └── tddl/
│       │                   └── dbsync/
│       │                       └── binlog/
│       │                           ├── CharsetConversion.java
│       │                           ├── DirectLogFetcher.java
│       │                           ├── FileLogFetcher.java
│       │                           ├── JsonConversion.java
│       │                           ├── JsonDiffConversion.java
│       │                           ├── LogBuffer.java
│       │                           ├── LogContext.java
│       │                           ├── LogDecoder.java
│       │                           ├── LogEvent.java
│       │                           ├── LogFetcher.java
│       │                           ├── LogPosition.java
│       │                           ├── NameCache.java
│       │                           ├── event/
│       │                           │   ├── AppendBlockLogEvent.java
│       │                           │   ├── BeginLoadQueryLogEvent.java
│       │                           │   ├── CreateFileLogEvent.java
│       │                           │   ├── DeleteFileLogEvent.java
│       │                           │   ├── DeleteRowsLogEvent.java
│       │                           │   ├── ExecuteLoadLogEvent.java
│       │                           │   ├── ExecuteLoadQueryLogEvent.java
│       │                           │   ├── FormatDescriptionLogEvent.java
│       │                           │   ├── GtidLogEvent.java
│       │                           │   ├── HeartbeatLogEvent.java
│       │                           │   ├── HeartbeatV2LogEvent.java
│       │                           │   ├── IgnorableLogEvent.java
│       │                           │   ├── IncidentLogEvent.java
│       │                           │   ├── IntvarLogEvent.java
│       │                           │   ├── LoadLogEvent.java
│       │                           │   ├── LogHeader.java
│       │                           │   ├── PreviousGtidsLogEvent.java
│       │                           │   ├── QueryLogEvent.java
│       │                           │   ├── RandLogEvent.java
│       │                           │   ├── RotateLogEvent.java
│       │                           │   ├── RowsLogBuffer.java
│       │                           │   ├── RowsLogEvent.java
│       │                           │   ├── RowsQueryLogEvent.java
│       │                           │   ├── StartLogEventV3.java
│       │                           │   ├── StopLogEvent.java
│       │                           │   ├── TableMapLogEvent.java
│       │                           │   ├── TransactionContextLogEvent.java
│       │                           │   ├── TransactionPayloadLogEvent.java
│       │                           │   ├── UnknownLogEvent.java
│       │                           │   ├── UpdateRowsLogEvent.java
│       │                           │   ├── UserVarLogEvent.java
│       │                           │   ├── ViewChangeEvent.java
│       │                           │   ├── WriteRowsLogEvent.java
│       │                           │   ├── XaPrepareLogEvent.java
│       │                           │   ├── XidLogEvent.java
│       │                           │   └── mariadb/
│       │                           │       ├── AnnotateRowsEvent.java
│       │                           │       ├── BinlogCheckPointLogEvent.java
│       │                           │       ├── DeleteRowsCompressLogEvent.java
│       │                           │       ├── MariaGtidListLogEvent.java
│       │                           │       ├── MariaGtidLogEvent.java
│       │                           │       ├── QueryCompressedLogEvent.java
│       │                           │       ├── StartEncryptionLogEvent.java
│       │                           │       ├── UpdateRowsCompressLogEvent.java
│       │                           │       └── WriteRowsCompressLogEvent.java
│       │                           └── exception/
│       │                               └── TableIdNotFoundException.java
│       └── test/
│           ├── java/
│           │   └── com/
│           │       └── taobao/
│           │           └── tddl/
│           │               └── dbsync/
│           │                   ├── FetcherPerformanceTest.java
│           │                   └── binlog/
│           │                       ├── BaseLogFetcherTest.java
│           │                       ├── DirectLogFetcherTest.java
│           │                       ├── FileLogFetcherTest.java
│           │                       ├── JsonConversion_Json_ValueTest.java
│           │                       ├── JsonDiffConversionTest.java
│           │                       ├── LogEventTest.java
│           │                       └── event/
│           │                           └── LogHeaderTest.java
│           └── resources/
│               ├── binlog/
│               │   └── mysql-bin.000001
│               └── dummy.txt
├── deployer/
│   ├── pom.xml
│   └── src/
│       └── main/
│           ├── assembly/
│           │   ├── dev.xml
│           │   └── release.xml
│           ├── bin/
│           │   ├── restart.sh
│           │   ├── startup.bat
│           │   ├── startup.sh
│           │   └── stop.sh
│           ├── java/
│           │   └── com/
│           │       └── alibaba/
│           │           └── otter/
│           │               └── canal/
│           │                   └── deployer/
│           │                       ├── CanalConstants.java
│           │                       ├── CanalController.java
│           │                       ├── CanalLauncher.java
│           │                       ├── CanalStarter.java
│           │                       ├── InstanceConfig.java
│           │                       ├── admin/
│           │                       │   └── CanalAdminController.java
│           │                       └── monitor/
│           │                           ├── InstanceAction.java
│           │                           ├── InstanceConfigMonitor.java
│           │                           ├── ManagerInstanceConfigMonitor.java
│           │                           └── SpringInstanceConfigMonitor.java
│           └── resources/
│               ├── canal.properties
│               ├── canal_local.properties
│               ├── example/
│               │   └── instance.properties
│               ├── logback.xml
│               ├── metrics/
│               │   └── Canal_instances_tmpl.json
│               └── spring/
│                   ├── base-instance.xml
│                   ├── default-instance.xml
│                   ├── file-instance.xml
│                   ├── group-instance.xml
│                   ├── memory-instance.xml
│                   └── tsdb/
│                       ├── h2-tsdb.xml
│                       ├── mysql-tsdb.xml
│                       ├── sql/
│                       │   └── create_table.sql
│                       └── sql-map/
│                           ├── sqlmap-config.xml
│                           ├── sqlmap_history.xml
│                           └── sqlmap_snapshot.xml
├── docker/
│   ├── Dockerfile
│   ├── Dockerfile_admin
│   ├── base/
│   │   ├── README.md
│   │   ├── amd64/
│   │   │   ├── Dockerfile
│   │   │   ├── Dockerfile_admin
│   │   │   └── yum/
│   │   │       └── CentOS-Base.repo
│   │   └── arm64/
│   │       ├── Dockerfile
│   │       ├── Dockerfile_admin
│   │       └── yum/
│   │           └── CentOS-Base.repo
│   ├── build.sh
│   ├── image/
│   │   ├── admin/
│   │   │   ├── bin/
│   │   │   │   ├── clean_log
│   │   │   │   └── clean_log.sh
│   │   │   └── health.sh
│   │   ├── alidata/
│   │   │   ├── bin/
│   │   │   │   ├── exec_rc_local.sh
│   │   │   │   ├── lark-wait
│   │   │   │   └── main.sh
│   │   │   ├── init/
│   │   │   │   ├── 02init-sshd.sh
│   │   │   │   └── fix-hosts.py
│   │   │   └── lib/
│   │   │       └── proc.sh
│   │   ├── app.sh
│   │   ├── app_admin.sh
│   │   └── canal_manager.sql
│   ├── run.sh
│   └── run_admin.sh
├── driver/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── alibaba/
│       │               └── otter/
│       │                   └── canal/
│       │                       └── parse/
│       │                           └── driver/
│       │                               └── mysql/
│       │                                   ├── MysqlConnector.java
│       │                                   ├── MysqlQueryExecutor.java
│       │                                   ├── MysqlUpdateExecutor.java
│       │                                   ├── packets/
│       │                                   │   ├── Capability.java
│       │                                   │   ├── CommandPacket.java
│       │                                   │   ├── GTIDSet.java
│       │                                   │   ├── HeaderPacket.java
│       │                                   │   ├── IPacket.java
│       │                                   │   ├── MariaGTIDSet.java
│       │                                   │   ├── MariaGtid.java
│       │                                   │   ├── MysqlGTIDSet.java
│       │                                   │   ├── PacketWithHeaderPacket.java
│       │                                   │   ├── UUIDSet.java
│       │                                   │   ├── client/
│       │                                   │   │   ├── AuthSwitchResponsePacket.java
│       │                                   │   │   ├── BinlogDumpCommandPacket.java
│       │                                   │   │   ├── BinlogDumpGTIDCommandPacket.java
│       │                                   │   │   ├── ClientAuthenticationPacket.java
│       │                                   │   │   ├── ClientAuthenticationSHA2Packet.java
│       │                                   │   │   ├── QueryCommandPacket.java
│       │                                   │   │   ├── QuitCommandPacket.java
│       │                                   │   │   ├── RegisterSlaveCommandPacket.java
│       │                                   │   │   ├── SemiAckCommandPacket.java
│       │                                   │   │   └── SslRequestCommandPacket.java
│       │                                   │   └── server/
│       │                                   │       ├── AuthSwitchRequestMoreData.java
│       │                                   │       ├── AuthSwitchRequestPacket.java
│       │                                   │       ├── DataPacket.java
│       │                                   │       ├── EOFPacket.java
│       │                                   │       ├── ErrorPacket.java
│       │                                   │       ├── FieldPacket.java
│       │                                   │       ├── HandshakeInitializationPacket.java
│       │                                   │       ├── OKPacket.java
│       │                                   │       ├── Reply323Packet.java
│       │                                   │       ├── ResultSetHeaderPacket.java
│       │                                   │       ├── ResultSetPacket.java
│       │                                   │       └── RowDataPacket.java
│       │                                   ├── socket/
│       │                                   │   ├── BioSocketChannel.java
│       │                                   │   ├── BioSocketChannelPool.java
│       │                                   │   ├── NettySocketChannel.java
│       │                                   │   ├── NettySocketChannelPool.java
│       │                                   │   ├── SocketChannel.java
│       │                                   │   └── SocketChannelPool.java
│       │                                   ├── ssl/
│       │                                   │   ├── SslInfo.java
│       │                                   │   └── SslMode.java
│       │                                   └── utils/
│       │                                       ├── BinlogDumpCommandBuilder.java
│       │                                       ├── ByteHelper.java
│       │                                       ├── ChannelBufferHelper.java
│       │                                       ├── CharsetUtil.java
│       │                                       ├── GtidUtil.java
│       │                                       ├── LengthCodedStringReader.java
│       │                                       ├── MSC.java
│       │                                       ├── MySQLPasswordEncrypter.java
│       │                                       └── PacketManager.java
│       └── test/
│           └── java/
│               └── com/
│                   └── alibaba/
│                       └── otter/
│                           └── canal/
│                               └── parse/
│                                   └── driver/
│                                       └── mysql/
│                                           ├── CharsetUtilTest.java
│                                           ├── MysqlConnectorTest.java
│                                           ├── MysqlGTIDSetTest.java
│                                           ├── UUIDSetTest.java
│                                           ├── packets/
│                                           │   └── client/
│                                           │       └── RegisterSlaveCommandPacketTest.java
│                                           └── utils/
│                                               ├── ByteHelperTest.java
│                                               └── MySQLPasswordEncrypterTest.java
├── example/
│   ├── pom.xml
│   └── src/
│       └── main/
│           ├── assembly/
│           │   ├── dev.xml
│           │   └── release.xml
│           ├── bin/
│           │   ├── init.sh
│           │   ├── startup.bat
│           │   ├── startup.sh
│           │   └── stop.sh
│           ├── java/
│           │   └── com/
│           │       └── alibaba/
│           │           └── otter/
│           │               └── canal/
│           │                   └── example/
│           │                       ├── AbstractCanalClientTest.java
│           │                       ├── BaseCanalClientTest.java
│           │                       ├── ClusterCanalClientTest.java
│           │                       ├── SimpleCanalClientPermanceTest.java
│           │                       ├── SimpleCanalClientTest.java
│           │                       ├── kafka/
│           │                       │   ├── AbstractKafkaTest.java
│           │                       │   ├── CanalKafkaClientExample.java
│           │                       │   ├── CanalKafkaClientFlatMessageExample.java
│           │                       │   ├── CanalKafkaOffsetClientExample.java
│           │                       │   └── KafkaClientRunningTest.java
│           │                       └── rocketmq/
│           │                           ├── AbstractRocektMQTest.java
│           │                           ├── CanalRocketMQClientExample.java
│           │                           └── CanalRocketMQClientFlatMessageExample.java
│           └── resources/
│               └── logback.xml
├── filter/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── alibaba/
│       │               └── otter/
│       │                   └── canal/
│       │                       └── filter/
│       │                           ├── CanalEventFilter.java
│       │                           ├── PatternUtils.java
│       │                           ├── aviater/
│       │                           │   ├── AviaterELFilter.java
│       │                           │   ├── AviaterRegexFilter.java
│       │                           │   ├── AviaterSimpleFilter.java
│       │                           │   └── RegexFunction.java
│       │                           └── exception/
│       │                               └── CanalFilterException.java
│       └── test/
│           └── java/
│               └── com/
│                   └── alibaba/
│                       └── otter/
│                           └── canal/
│                               └── filter/
│                                   ├── AviaterFilterTest.java
│                                   └── MutliAviaterFilterTest.java
├── instance/
│   ├── core/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           └── java/
│   │               └── com/
│   │                   └── alibaba/
│   │                       └── otter/
│   │                           └── canal/
│   │                               └── instance/
│   │                                   └── core/
│   │                                       ├── AbstractCanalInstance.java
│   │                                       ├── CanalInstance.java
│   │                                       ├── CanalInstanceGenerator.java
│   │                                       └── CanalMQConfig.java
│   ├── manager/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       └── com/
│   │       │           └── alibaba/
│   │       │               └── otter/
│   │       │                   └── canal/
│   │       │                       └── instance/
│   │       │                           └── manager/
│   │       │                               ├── CanalConfigClient.java
│   │       │                               ├── CanalInstanceWithManager.java
│   │       │                               ├── ManagerCanalInstanceGenerator.java
│   │       │                               ├── PlainCanalInstanceGenerator.java
│   │       │                               ├── model/
│   │       │                               │   ├── Canal.java
│   │       │                               │   ├── CanalParameter.java
│   │       │                               │   └── CanalStatus.java
│   │       │                               └── plain/
│   │       │                                   ├── HttpHelper.java
│   │       │                                   ├── PlainCanal.java
│   │       │                                   └── PlainCanalConfigClient.java
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── alibaba/
│   │                       └── otter/
│   │                           └── canal/
│   │                               └── instance/
│   │                                   └── manager/
│   │                                       └── PlainCanalConfigClientIntegration.java
│   ├── pom.xml
│   └── spring/
│       ├── pom.xml
│       └── src/
│           ├── main/
│           │   └── java/
│           │       └── com/
│           │           └── alibaba/
│           │               └── otter/
│           │                   └── canal/
│           │                       └── instance/
│           │                           └── spring/
│           │                               ├── CanalInstanceWithSpring.java
│           │                               ├── SpringCanalInstanceGenerator.java
│           │                               └── support/
│           │                                   ├── PropertyPlaceholderConfigurer.java
│           │                                   └── SocketAddressEditor.java
│           └── test/
│               ├── java/
│               │   └── com/
│               │       └── alibaba/
│               │           └── otter/
│               │               └── canal/
│               │                   └── instance/
│               │                       └── spring/
│               │                           └── integrated/
│               │                               ├── DefaultSpringInstanceTest.java
│               │                               ├── GroupSpringInstanceTest.java
│               │                               └── MemorySpringInstanceTest.java
│               └── resources/
│                   ├── canal.properties
│                   ├── retl/
│                   │   └── instance.properties
│                   └── spring/
│                       ├── default-instance.xml
│                       ├── file-instance.xml
│                       ├── group-instance.xml
│                       └── memory-instance.xml
├── meta/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── alibaba/
│       │               └── otter/
│       │                   └── canal/
│       │                       └── meta/
│       │                           ├── CanalMetaManager.java
│       │                           ├── FileMixedMetaManager.java
│       │                           ├── MemoryMetaManager.java
│       │                           ├── MixedMetaManager.java
│       │                           ├── PeriodMixedMetaManager.java
│       │                           ├── ZooKeeperMetaManager.java
│       │                           └── exception/
│       │                               └── CanalMetaManagerException.java
│       └── test/
│           └── java/
│               └── com/
│                   └── alibaba/
│                       └── otter/
│                           └── canal/
│                               └── meta/
│                                   ├── AbstractMetaManagerTest.java
│                                   ├── AbstractZkTest.java
│                                   ├── FileMixedMetaManagerTest.java
│                                   ├── MemoryMetaManagerTest.java
│                                   ├── MixedMetaManagerTest.java
│                                   ├── PeriodMixedMetaManagerTest.java
│                                   └── ZooKeeperMetaManagerTest.java
├── mvnw
├── parse/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── alibaba/
│       │   │           └── otter/
│       │   │               └── canal/
│       │   │                   └── parse/
│       │   │                       ├── CanalEventParser.java
│       │   │                       ├── CanalHASwitchable.java
│       │   │                       ├── exception/
│       │   │                       │   ├── CanalHAException.java
│       │   │                       │   ├── CanalParseException.java
│       │   │                       │   ├── PositionNotFoundException.java
│       │   │                       │   ├── ServerIdNotMatchException.java
│       │   │                       │   └── ServerLogPurgedException.java
│       │   │                       ├── ha/
│       │   │                       │   ├── CanalHAController.java
│       │   │                       │   └── HeartBeatHAController.java
│       │   │                       ├── inbound/
│       │   │                       │   ├── AbstractBinlogParser.java
│       │   │                       │   ├── AbstractEventParser.java
│       │   │                       │   ├── BinlogParser.java
│       │   │                       │   ├── ErosaConnection.java
│       │   │                       │   ├── EventTransactionBuffer.java
│       │   │                       │   ├── HeartBeatCallback.java
│       │   │                       │   ├── MultiStageCoprocessor.java
│       │   │                       │   ├── ParserExceptionHandler.java
│       │   │                       │   ├── SinkFunction.java
│       │   │                       │   ├── TableMeta.java
│       │   │                       │   ├── group/
│       │   │                       │   │   └── GroupEventParser.java
│       │   │                       │   └── mysql/
│       │   │                       │       ├── AbstractMysqlEventParser.java
│       │   │                       │       ├── DbsyncMysqlEventParser.java
│       │   │                       │       ├── LocalBinLogConnection.java
│       │   │                       │       ├── LocalBinlogEventParser.java
│       │   │                       │       ├── MysqlConnection.java
│       │   │                       │       ├── MysqlEventParser.java
│       │   │                       │       ├── MysqlMultiStageCoprocessor.java
│       │   │                       │       ├── SlaveEntryPosition.java
│       │   │                       │       ├── dbsync/
│       │   │                       │       │   ├── DirectLogFetcher.java
│       │   │                       │       │   ├── LogEventConvert.java
│       │   │                       │       │   └── TableMetaCache.java
│       │   │                       │       ├── ddl/
│       │   │                       │       │   ├── DdlResult.java
│       │   │                       │       │   ├── DruidDdlParser.java
│       │   │                       │       │   └── SimpleDdlParser.java
│       │   │                       │       ├── local/
│       │   │                       │       │   ├── BinLogFileQueue.java
│       │   │                       │       │   └── BufferedFileDataInput.java
│       │   │                       │       ├── rds/
│       │   │                       │       │   ├── BinlogDownloadQueue.java
│       │   │                       │       │   ├── HttpHelper.java
│       │   │                       │       │   ├── RdsBinlogEventParserProxy.java
│       │   │                       │       │   ├── RdsBinlogOpenApi.java
│       │   │                       │       │   ├── RdsLocalBinlogEventParser.java
│       │   │                       │       │   ├── data/
│       │   │                       │       │   │   ├── BinlogFile.java
│       │   │                       │       │   │   ├── DescribeBinlogFileResult.java
│       │   │                       │       │   │   ├── RdsBackupPolicy.java
│       │   │                       │       │   │   └── RdsItem.java
│       │   │                       │       │   └── request/
│       │   │                       │       │       ├── AbstractRequest.java
│       │   │                       │       │       ├── DescribeBackupPolicyRequest.java
│       │   │                       │       │       └── DescribeBinlogFilesRequest.java
│       │   │                       │       └── tsdb/
│       │   │                       │           ├── DatabaseTableMeta.java
│       │   │                       │           ├── DefaultTableMetaTSDBFactory.java
│       │   │                       │           ├── MemoryTableMeta.java
│       │   │                       │           ├── TableMetaTSDB.java
│       │   │                       │           ├── TableMetaTSDBBuilder.java
│       │   │                       │           ├── TableMetaTSDBFactory.java
│       │   │                       │           └── dao/
│       │   │                       │               ├── MetaBaseDAO.java
│       │   │                       │               ├── MetaHistoryDAO.java
│       │   │                       │               ├── MetaHistoryDO.java
│       │   │                       │               ├── MetaHistoryMapper.java
│       │   │                       │               ├── MetaSnapshotDAO.java
│       │   │                       │               ├── MetaSnapshotDO.java
│       │   │                       │               └── MetaSnapshotMapper.java
│       │   │                       ├── index/
│       │   │                       │   ├── AbstractLogPositionManager.java
│       │   │                       │   ├── CanalLogPositionManager.java
│       │   │                       │   ├── FailbackLogPositionManager.java
│       │   │                       │   ├── FileMixedLogPositionManager.java
│       │   │                       │   ├── MemoryLogPositionManager.java
│       │   │                       │   ├── MetaLogPositionManager.java
│       │   │                       │   ├── MixedLogPositionManager.java
│       │   │                       │   ├── PeriodMixedLogPositionManager.java
│       │   │                       │   └── ZooKeeperLogPositionManager.java
│       │   │                       └── support/
│       │   │                           ├── AuthenticationInfo.java
│       │   │                           └── HaAuthenticationInfo.java
│       │   └── resources/
│       │       └── ddl/
│       │           ├── derby/
│       │           │   ├── meta_history.sql
│       │           │   └── meta_snapshot.sql
│       │           ├── h2/
│       │           │   ├── meta_history.sql
│       │           │   └── meta_snapshot.sql
│       │           └── mysql/
│       │               ├── meta_history.sql
│       │               └── meta_snapshot.sql
│       └── test/
│           ├── java/
│           │   └── com/
│           │       └── alibaba/
│           │           └── otter/
│           │               └── canal/
│           │                   └── parse/
│           │                       ├── DirectLogFetcherTest.java
│           │                       ├── MysqlBinlogDumpPerformanceTest.java
│           │                       ├── MysqlBinlogEventPerformanceTest.java
│           │                       ├── MysqlBinlogParsePerformanceTest.java
│           │                       ├── helper/
│           │                       │   └── TimeoutChecker.java
│           │                       ├── inbound/
│           │                       │   ├── EventTransactionBufferTest.java
│           │                       │   ├── TableMetaCacheTest.java
│           │                       │   ├── group/
│           │                       │   │   ├── DummyEventStore.java
│           │                       │   │   └── GroupEventPaserTest.java
│           │                       │   └── mysql/
│           │                       │       ├── DruidDdlParserTest.java
│           │                       │       ├── LocalBinlogDumpTest.java
│           │                       │       ├── LocalBinlogEventParserTest.java
│           │                       │       ├── MysqlDumpTest.java
│           │                       │       ├── MysqlEventParserTest.java
│           │                       │       ├── RdsBinlogEventParserProxyTest.java
│           │                       │       ├── RdsBinlogOpenApiTest.java
│           │                       │       ├── RdsLocalBinlogDumpTest.java
│           │                       │       ├── SimpleDdlParserTest.java
│           │                       │       ├── ddl/
│           │                       │       │   └── DdlResultTest.java
│           │                       │       └── tsdb/
│           │                       │           ├── FastsqlSchemaTest.java
│           │                       │           ├── MemoryTableMetaTest.java
│           │                       │           ├── MemoryTableMeta_DDL_Test.java
│           │                       │           ├── MemoryTableMeta_Random_DDL_Test.java
│           │                       │           ├── MetaHistoryDAOTest.java
│           │                       │           ├── MetaSnapshotDAOTest.java
│           │                       │           ├── TableMetaManagerBuilderTest.java
│           │                       │           └── TableMetaManagerTest.java
│           │                       ├── index/
│           │                       │   ├── AbstractLogPositionManagerTest.java
│           │                       │   ├── AbstractZkTest.java
│           │                       │   ├── FileMixedLogPositionManagerTest.java
│           │                       │   ├── MemoryLogPositionManagerTest.java
│           │                       │   ├── MetaLogPositionManagerTest.java
│           │                       │   ├── MixedLogPositionManagerTest.java
│           │                       │   ├── PeriodMixedLogPositionManagerTest.java
│           │                       │   └── ZooKeeperLogPositionManagerTest.java
│           │                       └── stub/
│           │                           └── AbstractCanalEventSinkTest.java
│           └── resources/
│               ├── binlog/
│               │   ├── mysql-bin.000001
│               │   ├── mysql-bin.000002
│               │   └── tsdb/
│               │       ├── mysql-bin.000001
│               │       ├── mysql-bin.000002
│               │       └── mysql-bin.000003
│               ├── ddl/
│               │   ├── alter/
│               │   │   ├── mysql_1.sql
│               │   │   ├── mysql_10.sql
│               │   │   ├── mysql_11.sql
│               │   │   ├── mysql_12.sql
│               │   │   ├── mysql_13.sql
│               │   │   ├── mysql_14.sql
│               │   │   ├── mysql_15.sql
│               │   │   ├── mysql_16.sql
│               │   │   ├── mysql_17.sql
│               │   │   ├── mysql_18.sql
│               │   │   ├── mysql_19.sql
│               │   │   ├── mysql_2.sql
│               │   │   ├── mysql_20.sql
│               │   │   ├── mysql_21.sql
│               │   │   ├── mysql_22.sql
│               │   │   ├── mysql_23.sql
│               │   │   ├── mysql_24.sql
│               │   │   ├── mysql_25.sql
│               │   │   ├── mysql_26.sql
│               │   │   ├── mysql_27.sql
│               │   │   ├── mysql_28.sql
│               │   │   ├── mysql_29.sql
│               │   │   ├── mysql_3.sql
│               │   │   ├── mysql_30.sql
│               │   │   ├── mysql_31.sql
│               │   │   ├── mysql_32.sql
│               │   │   ├── mysql_33.sql
│               │   │   ├── mysql_34.sql
│               │   │   ├── mysql_35.sql
│               │   │   ├── mysql_36.sql
│               │   │   ├── mysql_37.sql
│               │   │   ├── mysql_38.sql
│               │   │   ├── mysql_39.sql
│               │   │   ├── mysql_4.sql
│               │   │   ├── mysql_40.sql
│               │   │   ├── mysql_41.sql
│               │   │   ├── mysql_42.sql
│               │   │   ├── mysql_43.sql
│               │   │   ├── mysql_44.sql
│               │   │   ├── mysql_45.sql
│               │   │   ├── mysql_46.sql
│               │   │   ├── mysql_47.sql
│               │   │   ├── mysql_48.sql
│               │   │   ├── mysql_49.sql
│               │   │   ├── mysql_5.sql
│               │   │   ├── mysql_50.sql
│               │   │   ├── mysql_51.sql
│               │   │   ├── mysql_52.sql
│               │   │   ├── mysql_53.sql
│               │   │   ├── mysql_54.sql
│               │   │   ├── mysql_55.sql
│               │   │   ├── mysql_56.sql
│               │   │   ├── mysql_57.sql
│               │   │   ├── mysql_58.sql
│               │   │   ├── mysql_59.sql
│               │   │   ├── mysql_6.sql
│               │   │   ├── mysql_60.sql
│               │   │   ├── mysql_61.sql
│               │   │   ├── mysql_62.sql
│               │   │   ├── mysql_63.sql
│               │   │   ├── mysql_64.sql
│               │   │   ├── mysql_65.sql
│               │   │   ├── mysql_66.sql
│               │   │   ├── mysql_67.sql
│               │   │   ├── mysql_68.sql
│               │   │   ├── mysql_69.sql
│               │   │   ├── mysql_7.sql
│               │   │   ├── mysql_70.sql
│               │   │   ├── mysql_71.sql
│               │   │   ├── mysql_72.sql
│               │   │   ├── mysql_73.sql
│               │   │   ├── mysql_74.sql
│               │   │   ├── mysql_75.sql
│               │   │   ├── mysql_76.sql
│               │   │   ├── mysql_77.sql
│               │   │   ├── mysql_78.sql
│               │   │   ├── mysql_79.sql
│               │   │   ├── mysql_8.sql
│               │   │   ├── mysql_80.sql
│               │   │   ├── mysql_9.sql
│               │   │   ├── test_1.sql
│               │   │   ├── test_10.sql
│               │   │   ├── test_11.sql
│               │   │   ├── test_12.sql
│               │   │   ├── test_13.sql
│               │   │   ├── test_14.sql
│               │   │   ├── test_15.sql
│               │   │   ├── test_16.sql
│               │   │   ├── test_17.sql
│               │   │   ├── test_18.sql
│               │   │   ├── test_19.sql
│               │   │   ├── test_2.sql
│               │   │   ├── test_20.sql
│               │   │   ├── test_21.sql
│               │   │   ├── test_22.sql
│               │   │   ├── test_23.sql
│               │   │   ├── test_24.sql
│               │   │   ├── test_25.sql
│               │   │   ├── test_26.sql
│               │   │   ├── test_27.sql
│               │   │   ├── test_28.sql
│               │   │   ├── test_29.sql
│               │   │   ├── test_3.sql
│               │   │   ├── test_30.sql
│               │   │   ├── test_31.sql
│               │   │   ├── test_32.sql
│               │   │   ├── test_33.sql
│               │   │   ├── test_34.sql
│               │   │   ├── test_35.sql
│               │   │   ├── test_36.sql
│               │   │   ├── test_37.sql
│               │   │   ├── test_38.sql
│               │   │   ├── test_39.sql
│               │   │   ├── test_4.sql
│               │   │   ├── test_40.sql
│               │   │   ├── test_41.sql
│               │   │   ├── test_42.sql
│               │   │   ├── test_43.sql
│               │   │   ├── test_44.sql
│               │   │   ├── test_45.sql
│               │   │   ├── test_46.sql
│               │   │   ├── test_47.sql
│               │   │   ├── test_48.sql
│               │   │   ├── test_49.sql
│               │   │   ├── test_5.sql
│               │   │   ├── test_50.sql
│               │   │   ├── test_51.sql
│               │   │   ├── test_52.sql
│               │   │   ├── test_53.sql
│               │   │   ├── test_54.sql
│               │   │   ├── test_55.sql
│               │   │   ├── test_56.sql
│               │   │   ├── test_57.sql
│               │   │   ├── test_58.sql
│               │   │   ├── test_59.sql
│               │   │   ├── test_6.sql
│               │   │   ├── test_60.sql
│               │   │   ├── test_61.sql
│               │   │   ├── test_62.sql
│               │   │   ├── test_63.sql
│               │   │   ├── test_64.sql
│               │   │   ├── test_65.sql
│               │   │   ├── test_66.sql
│               │   │   ├── test_67.sql
│               │   │   ├── test_68.sql
│               │   │   ├── test_69.sql
│               │   │   ├── test_7.sql
│               │   │   ├── test_70.sql
│               │   │   ├── test_71.sql
│               │   │   ├── test_72.sql
│               │   │   ├── test_73.sql
│               │   │   ├── test_74.sql
│               │   │   ├── test_75.sql
│               │   │   ├── test_76.sql
│               │   │   ├── test_77.sql
│               │   │   ├── test_78.sql
│               │   │   ├── test_79.sql
│               │   │   ├── test_8.sql
│               │   │   ├── test_80.sql
│               │   │   └── test_9.sql
│               │   ├── create.sql
│               │   ├── ddl_any.sql
│               │   ├── ddl_create_function_index.sql
│               │   ├── ddl_create_if_not_exist.sql
│               │   ├── ddl_test1.sql
│               │   ├── ddl_test2.sql
│               │   ├── ddl_test3.sql
│               │   ├── ddl_test4.sql
│               │   └── table/
│               │       ├── mysql_1.sql
│               │       ├── mysql_10.sql
│               │       ├── mysql_11.sql
│               │       ├── mysql_12.sql
│               │       ├── mysql_13.sql
│               │       ├── mysql_14.sql
│               │       ├── mysql_15.sql
│               │       ├── mysql_16.sql
│               │       ├── mysql_17.sql
│               │       ├── mysql_18.sql
│               │       ├── mysql_19.sql
│               │       ├── mysql_2.sql
│               │       ├── mysql_20.sql
│               │       ├── mysql_21.sql
│               │       ├── mysql_22.sql
│               │       ├── mysql_23.sql
│               │       ├── mysql_24.sql
│               │       ├── mysql_25.sql
│               │       ├── mysql_26.sql
│               │       ├── mysql_27.sql
│               │       ├── mysql_28.sql
│               │       ├── mysql_29.sql
│               │       ├── mysql_3.sql
│               │       ├── mysql_30.sql
│               │       ├── mysql_31.sql
│               │       ├── mysql_32.sql
│               │       ├── mysql_33.sql
│               │       ├── mysql_34.sql
│               │       ├── mysql_35.sql
│               │       ├── mysql_36.sql
│               │       ├── mysql_37.sql
│               │       ├── mysql_38.sql
│               │       ├── mysql_39.sql
│               │       ├── mysql_4.sql
│               │       ├── mysql_5.sql
│               │       ├── mysql_6.sql
│               │       ├── mysql_7.sql
│               │       ├── mysql_8.sql
│               │       ├── mysql_9.sql
│               │       ├── test_1.sql
│               │       ├── test_10.sql
│               │       ├── test_11.sql
│               │       ├── test_12.sql
│               │       ├── test_13.sql
│               │       ├── test_14.sql
│               │       ├── test_15.sql
│               │       ├── test_16.sql
│               │       ├── test_17.sql
│               │       ├── test_18.sql
│               │       ├── test_19.sql
│               │       ├── test_2.sql
│               │       ├── test_20.sql
│               │       ├── test_21.sql
│               │       ├── test_22.sql
│               │       ├── test_23.sql
│               │       ├── test_24.sql
│               │       ├── test_25.sql
│               │       ├── test_26.sql
│               │       ├── test_27.sql
│               │       ├── test_28.sql
│               │       ├── test_29.sql
│               │       ├── test_3.sql
│               │       ├── test_30.sql
│               │       ├── test_31.sql
│               │       ├── test_32.sql
│               │       ├── test_33.sql
│               │       ├── test_34.sql
│               │       ├── test_35.sql
│               │       ├── test_36.sql
│               │       ├── test_37.sql
│               │       ├── test_38.sql
│               │       ├── test_39.sql
│               │       ├── test_4.sql
│               │       ├── test_5.sql
│               │       ├── test_6.sql
│               │       ├── test_7.sql
│               │       ├── test_8.sql
│               │       └── test_9.sql
│               ├── dummy.txt
│               └── tsdb/
│                   ├── derby-tsdb.xml
│                   ├── h2-tsdb.xml
│                   ├── mysql-tsdb.xml
│                   └── sql-map/
│                       ├── sqlmap-config.xml
│                       ├── sqlmap_history.xml
│                       └── sqlmap_snapshot.xml
├── pom.xml
├── prometheus/
│   ├── pom.xml
│   └── src/
│       └── main/
│           ├── java/
│           │   └── com/
│           │       └── alibaba/
│           │           └── otter/
│           │               └── canal/
│           │                   └── prometheus/
│           │                       ├── CanalInstanceExports.java
│           │                       ├── InstanceRegistry.java
│           │                       ├── PrometheusProvider.java
│           │                       ├── PrometheusService.java
│           │                       └── impl/
│           │                           ├── EntryCollector.java
│           │                           ├── MetaCollector.java
│           │                           ├── ParserCollector.java
│           │                           ├── PrometheusCanalEventDownStreamHandler.java
│           │                           ├── PrometheusClientInstanceProfiler.java
│           │                           ├── SinkCollector.java
│           │                           └── StoreCollector.java
│           └── resources/
│               └── META-INF/
│                   └── services/
│                       └── com.alibaba.otter.canal.spi.CanalMetricsProvider
├── protocol/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── alibaba/
│       │               └── otter/
│       │                   └── canal/
│       │                       └── protocol/
│       │                           ├── AdminPacket.java
│       │                           ├── AdminProtocol.proto
│       │                           ├── CanalEntry.java
│       │                           ├── CanalPacket.java
│       │                           ├── CanalProtocol.proto
│       │                           ├── ClientIdentity.java
│       │                           ├── EntryProtocol.proto
│       │                           ├── FlatMessage.java
│       │                           ├── Message.java
│       │                           ├── SecurityUtil.java
│       │                           ├── exception/
│       │                           │   └── CanalClientException.java
│       │                           └── position/
│       │                               ├── EntryPosition.java
│       │                               ├── LogIdentity.java
│       │                               ├── LogPosition.java
│       │                               ├── MetaqPosition.java
│       │                               ├── Position.java
│       │                               ├── PositionRange.java
│       │                               └── TimePosition.java
│       └── test/
│           └── java/
│               └── com/
│                   └── alibaba/
│                       └── otter/
│                           └── canal/
│                               └── protocol/
│                                   ├── ProtocolTest.java
│                                   └── SecurityUtilTest.java
├── server/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── alibaba/
│       │               └── otter/
│       │                   └── canal/
│       │                       ├── admin/
│       │                       │   ├── CanalAdmin.java
│       │                       │   ├── handler/
│       │                       │   │   ├── ClientAuthenticationHandler.java
│       │                       │   │   ├── HandshakeInitializationHandler.java
│       │                       │   │   └── SessionHandler.java
│       │                       │   └── netty/
│       │                       │       ├── AdminNettyUtils.java
│       │                       │       └── CanalAdminWithNetty.java
│       │                       ├── server/
│       │                       │   ├── CanalMQStarter.java
│       │                       │   ├── CanalServer.java
│       │                       │   ├── CanalServerStarter.java
│       │                       │   ├── CanalService.java
│       │                       │   ├── embedded/
│       │                       │   │   └── CanalServerWithEmbedded.java
│       │                       │   ├── exception/
│       │                       │   │   └── CanalServerException.java
│       │                       │   └── netty/
│       │                       │       ├── CanalServerWithNetty.java
│       │                       │       ├── CanalServerWithNettyProfiler.java
│       │                       │       ├── ClientInstanceProfiler.java
│       │                       │       ├── NettyUtils.java
│       │                       │       ├── handler/
│       │                       │       │   ├── ClientAuthenticationHandler.java
│       │                       │       │   ├── FixedHeaderFrameDecoder.java
│       │                       │       │   ├── HandshakeInitializationHandler.java
│       │                       │       │   └── SessionHandler.java
│       │                       │       └── listener/
│       │                       │           └── ChannelFutureAggregator.java
│       │                       └── spi/
│       │                           ├── CanalMetricsProvider.java
│       │                           ├── CanalMetricsService.java
│       │                           └── NopCanalMetricsService.java
│       └── test/
│           └── java/
│               └── com/
│                   └── alibaba/
│                       └── otter/
│                           └── canal/
│                               └── server/
│                                   ├── CanalServerTest.java
│                                   └── embedded/
│                                       ├── BaseCanalServerWithEmbededTest.java
│                                       ├── CanalServerWithEmbedded_FileModeTest.java
│                                       ├── CanalServerWithEmbedded_StandaloneTest.java
│                                       └── CanalServerWithEmbedded_StandbyTest.java
├── sink/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── alibaba/
│       │               └── otter/
│       │                   └── canal/
│       │                       └── sink/
│       │                           ├── AbstractCanalEventDownStreamHandler.java
│       │                           ├── AbstractCanalEventSink.java
│       │                           ├── CanalEventDownStreamHandler.java
│       │                           ├── CanalEventSink.java
│       │                           ├── entry/
│       │                           │   ├── EntryEventSink.java
│       │                           │   ├── HeartBeatEntryEventHandler.java
│       │                           │   └── group/
│       │                           │       ├── GroupBarrier.java
│       │                           │       ├── GroupEventSink.java
│       │                           │       ├── TimelineBarrier.java
│       │                           │       └── TimelineTransactionBarrier.java
│       │                           └── exception/
│       │                               └── CanalSinkException.java
│       └── test/
│           └── java/
│               └── com/
│                   └── alibaba/
│                       └── otter/
│                           └── canal/
│                               └── sink/
│                                   ├── GroupEventSinkTest.java
│                                   └── stub/
│                                       └── DummyEventStore.java
└── store/
    ├── pom.xml
    └── src/
        ├── main/
        │   └── java/
        │       └── com/
        │           └── alibaba/
        │               └── otter/
        │                   └── canal/
        │                       └── store/
        │                           ├── AbstractCanalGroupStore.java
        │                           ├── AbstractCanalStoreScavenge.java
        │                           ├── CanalEventStore.java
        │                           ├── CanalGroupEventStore.java
        │                           ├── CanalStoreConstants.java
        │                           ├── CanalStoreException.java
        │                           ├── CanalStoreScavenge.java
        │                           ├── StoreInfo.java
        │                           ├── helper/
        │                           │   └── CanalEventUtils.java
        │                           ├── memory/
        │                           │   └── MemoryEventStoreWithBuffer.java
        │                           └── model/
        │                               ├── BatchMode.java
        │                               ├── Event.java
        │                               └── Events.java
        └── test/
            └── java/
                └── com/
                    └── alibaba/
                        └── otter/
                            └── canal/
                                └── store/
                                    └── memory/
                                        └── buffer/
                                            ├── MemoryEventStoreBase.java
                                            ├── MemoryEventStoreMemBatchTest.java
                                            ├── MemoryEventStoreMultiThreadTest.java
                                            ├── MemoryEventStorePutAndGetTest.java
                                            └── MemoryEventStoreRollbackAndAckTest.java

================================================
FILE CONTENTS
================================================

================================================
FILE: .codecov.yml
================================================
coverage:
  status:
    # pull-requests only
    patch:
      default:
        threshold: 0.1%


================================================
FILE: .github/ISSUE_TEMPLATE/any-questions-on-canal.md
================================================
---
name: Any Questions on Canal
about: Ask whatever you want to know or confusion about Canal

---

## Question
<!-- You can ask any question about this project -->


================================================
FILE: .github/ISSUE_TEMPLATE/bug-report-for-canal.md
================================================
---
name: Bug Report for Canal
about: Create a report to help us improve

---

- [ ] I have searched the [issues](https://github.com/alibaba/canal/issues) of this repository and believe that this is not a duplicate.
- [ ] I have checked the [FAQ](https://github.com/alibaba/canal/wiki/FAQ) of this repository and believe that this is not a duplicate.

### environment

* canal version
* mysql version

### Issue Description


### Steps to reproduce

### Expected behaviour

### Actual behaviour


If there is an exception, please attach the exception trace:

```
Just put your stack trace here!
```

================================================
FILE: .github/ISSUE_TEMPLATE/feature-request-of-canal.md
================================================
---
name: Feature Request of Canal
about: Suggest an idea for this project

---

## Why you need it?
<!-- Is your feature request related to a problem? Please describe in details  -->


## How it could be?
<!--A clear and concise description of what you want to happen. For a computer fan,  you can explain more about input of the feature, and output of it.-->


## Other related information
<!-- Add any other context or screenshots about the feature request here.-->


================================================
FILE: .github/workflows/maven.yml
================================================
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

name: Java CI with Maven

on:
  push:
    branches: [ "master" ]
  pull_request:
    branches: [ "master" ]

permissions:
  contents: read

jobs:
  test:
    runs-on: ${{ matrix.os }}
    permissions:
      contents: read
    strategy:
      matrix:
        os: [ ubuntu-latest ]
        java: [ 8, 11, 17, 21 ]
      fail-fast: false
      max-parallel: 16
    name: Test JDK ${{ matrix.java }}, ${{ matrix.os }}

    steps:
      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
      - name: Set up JDK
        uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
        with:
          distribution: 'temurin'
          java-version: ${{ matrix.java }}
          cache: 'maven'
      - name: Build with Maven if test jdk8
        if: ${{ matrix.java == '8' || matrix.java == '11'}}
        run: ./mvnw -Pgen-javadoc clean package -B
      - name: Build with Maven if test jdk17
        if: ${{ matrix.java == '17' || matrix.java == '21' }}
        run: ./mvnw -Penable-for-jdk17+,gen-code-cov clean package -B


================================================
FILE: .gitignore
================================================
.svn/
target/
test-output/
*.class
.classpath
.project
.settings/
tmp
temp
logs/
*.log
antx.properties
otter.properties
jtester.properties
.idea/
*.iml
.DS_Store
*.tar.gz
*.rpm
client-adapter/example/
*.dat
conf/
canal-admin/canal-admin-ui/dist/
canal-admin/canal-admin-ui/node/
canal-admin/canal-admin-ui/node_modules/
canal-admin/canal-admin-server/src/main/resources/conf/


================================================
FILE: .mvn/wrapper/maven-wrapper.properties
================================================
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.0/apache-maven-3.5.0-bin.zip


================================================
FILE: .travis.yml
================================================
language: java
sudo: false # faster builds

jdk:
  - oraclejdk12
  - openjdk11
  - oraclejdk11
  - openjdk8

cache:
  directories:
    - $HOME/.m2

install: true

script:
  - travis_wait 30 ./mvnw -T 1C clean install -DskipTests=false -Dcheckstyle.skip=true -Dmaven.javadoc.skip=true

after_success:
  - bash <(curl -s https://codecov.io/bash)

after_failure:
  - if [ -f canal.log ]; then echo "------TAIL of canal.log------"; tail -n 1000 canal.log; echo "------END of canal.log------"; fi


================================================
FILE: LICENSE.txt
================================================

                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: README.md
================================================
[![build status](https://travis-ci.com/alibaba/canal.svg?branch=master)](https://travis-ci.com/alibaba/canal)
[![codecov](https://codecov.io/gh/alibaba/canal/branch/master/graph/badge.svg)](https://codecov.io/gh/alibaba/canal)
![maven](https://img.shields.io/maven-central/v/com.alibaba.otter/canal.svg)
![license](https://img.shields.io/github/license/alibaba/canal.svg)
[![average time to resolve an issue](http://isitmaintained.com/badge/resolution/alibaba/canal.svg)](http://isitmaintained.com/project/alibaba/canal "average time to resolve an issue")
[![percentage of issues still open](http://isitmaintained.com/badge/open/alibaba/canal.svg)](http://isitmaintained.com/project/alibaba/canal "percentage of issues still open")
[![Leaderboard](https://img.shields.io/badge/Canal-%E6%9F%A5%E7%9C%8B%E8%B4%A1%E7%8C%AE%E6%8E%92%E8%A1%8C%E6%A6%9C-orange)](https://opensource.alibaba.com/contribution_leaderboard/details?projectValue=canal)


## 简介

![](https://img-blog.csdnimg.cn/20191104101735947.png)

**canal [kə'næl]**,译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费

早期阿里巴巴因为杭州和美国双机房部署,存在跨机房同步的业务需求,实现方式主要是基于业务 trigger 获取增量变更。从 2010 年开始,业务逐步尝试数据库日志解析获取增量变更进行同步,由此衍生出了大量的数据库增量订阅和消费业务。

基于日志增量订阅和消费的业务包括
- 数据库镜像
- 数据库实时备份
- 索引构建和实时维护(拆分异构索引、倒排索引等)
- 业务 cache 刷新
- 带业务逻辑的增量数据处理

当前的 canal 支持源端 MySQL 版本包括 5.1.x , 5.5.x , 5.6.x , 5.7.x , 8.0.x

## 工作原理

#### MySQL主备复制原理
![](http://dl.iteye.com/upload/attachment/0080/3086/468c1a14-e7ad-3290-9d3d-44ac501a7227.jpg)

- MySQL master 将数据变更写入二进制日志( binary log, 其中记录叫做二进制日志事件binary log events,可以通过 show binlog events 进行查看)
- MySQL slave 将 master 的 binary log events 拷贝到它的中继日志(relay log)
- MySQL slave 重放 relay log 中事件,将数据变更反映它自己的数据

#### canal 工作原理

- canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送dump 协议
- MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal )
- canal 解析 binary log 对象(原始为 byte 流)

## 重要版本更新说明

1. canal 1.1.x 版本([release_note](https://github.com/alibaba/canal/releases)),性能与功能层面有较大的突破,重要提升包括:

- 整体性能测试&优化,提升了150%. #726 参考: [Performance](https://github.com/alibaba/canal/wiki/Performance)
- 原生支持prometheus监控 #765 [Prometheus QuickStart](https://github.com/alibaba/canal/wiki/Prometheus-QuickStart)
- 原生支持kafka消息投递 #695 [Canal Kafka/RocketMQ QuickStart](https://github.com/alibaba/canal/wiki/Canal-Kafka-RocketMQ-QuickStart)
- 原生支持aliyun rds的binlog订阅 (解决自动主备切换/oss binlog离线解析) 参考: [Aliyun RDS QuickStart](https://github.com/alibaba/canal/wiki/aliyun-RDS-QuickStart)
- 原生支持docker镜像 #801 参考: [Docker QuickStart](https://github.com/alibaba/canal/wiki/Docker-QuickStart)

2.  canal 1.1.4版本,迎来最重要的WebUI能力,引入canal-admin工程,支持面向WebUI的canal动态管理能力,支持配置、任务、日志等在线白屏运维能力,具体文档:[Canal Admin Guide](https://github.com/alibaba/canal/wiki/Canal-Admin-Guide)

## 文档

- [Home](https://github.com/alibaba/canal/wiki/Home)
- [Introduction](https://github.com/alibaba/canal/wiki/Introduction)
- [QuickStart](https://github.com/alibaba/canal/wiki/QuickStart)
  - [Docker QuickStart](https://github.com/alibaba/canal/wiki/Docker-QuickStart)
  - [Canal Kafka/RocketMQ QuickStart](https://github.com/alibaba/canal/wiki/Canal-Kafka-RocketMQ-QuickStart")
  - [Aliyun RDS for MySQL QuickStart](https://github.com/alibaba/canal/wiki/aliyun-RDS-QuickStart)
  - [Prometheus QuickStart](https://github.com/alibaba/canal/wiki/Prometheus-QuickStart)
- Canal Admin
  - [Canal Admin QuickStart](https://github.com/alibaba/canal/wiki/Canal-Admin-QuickStart)
  - [Canal Admin Guide](https://github.com/alibaba/canal/wiki/Canal-Admin-Guide)
  - [Canal Admin ServerGuide](https://github.com/alibaba/canal/wiki/Canal-Admin-ServerGuide)
  - [Canal Admin Docker](https://github.com/alibaba/canal/wiki/Canal-Admin-Docker)
- [AdminGuide](https://github.com/alibaba/canal/wiki/AdminGuide)
- [ClientExample](https://github.com/alibaba/canal/wiki/ClientExample)
- [ClientAPI](https://github.com/alibaba/canal/wiki/ClientAPI)
- [Performance](https://github.com/alibaba/canal/wiki/Performance)
- [DevGuide](https://github.com/alibaba/canal/wiki/DevGuide)
- [BinlogChange(MySQL 5.6)](https://github.com/alibaba/canal/wiki/BinlogChange%28mysql5.6%29)
- [BinlogChange(MariaDB)](https://github.com/alibaba/canal/wiki/BinlogChange%28MariaDB%29)
- [TableMetaTSDB](https://github.com/alibaba/canal/wiki/TableMetaTSDB)
- [ReleaseNotes](http://alibaba.github.com/canal/release.html)
- [Download](https://github.com/alibaba/canal/releases)
- [FAQ](https://github.com/alibaba/canal/wiki/FAQ)

## 多语言

canal 特别设计了 client-server 模式,交互协议使用 protobuf 3.0 , client 端可采用不同语言实现不同的消费逻辑,欢迎大家提交 pull request 
  
- canal java 客户端: [https://github.com/alibaba/canal/wiki/ClientExample](https://github.com/alibaba/canal/wiki/ClientExample)
- canal c# 客户端: [https://github.com/dotnetcore/CanalSharp](https://github.com/dotnetcore/CanalSharp)
- canal go客户端: [https://github.com/CanalClient/canal-go](https://github.com/CanalClient/canal-go)
- canal php客户端: [https://github.com/xingwenge/canal-php](https://github.com/xingwenge/canal-php)
- canal Python客户端:[https://github.com/haozi3156666/canal-python](https://github.com/haozi3156666/canal-python)
- canal Rust客户端:[https://github.com/laohanlinux/canal-rs](https://github.com/laohanlinux/canal-rs)
- canal Nodejs客户端:[https://github.com/marmot-z/canal-nodejs](https://github.com/marmot-z/canal-nodejs)

canal 作为 MySQL binlog 增量获取和解析工具,可将变更记录投递到 MQ 系统中,比如 Kafka/RocketMQ,可以借助于 MQ 的多语言能力 

- 参考文档: [Canal Kafka/RocketMQ QuickStart](https://github.com/alibaba/canal/wiki/Canal-Kafka-RocketMQ-QuickStart)

## 基于canal开发的工具

-  canal2sql(基于binlog生成SQL) : [https://github.com/zhuchao941/canal2sql]

## 相关开源&产品

- [canal 消费端开源项目: Otter](http://github.com/alibaba/otter)
- [阿里巴巴去 Oracle 数据迁移同步工具: yugong](http://github.com/alibaba/yugong)
- [阿里巴巴离线同步开源项目 DataX](https://github.com/alibaba/datax)
- [阿里巴巴数据库连接池开源项目 Druid](https://github.com/alibaba/druid)
- [阿里巴巴实时数据同步工具 DTS](https://www.aliyun.com/product/dts)

## 问题反馈
- 报告 issue: [github issues](https://github.com/alibaba/canal/issues)

本项目的Issues会被同步沉淀至[阿里云开发者社区](https://developer.aliyun.com/ask)


================================================
FILE: RELEASE.txt
================================================
release link : https://alibaba.github.com/canal/release.html

download link : https://github.com/alibaba/canal/releases


================================================
FILE: SECURITY.md
================================================
# 漏洞奖励计划 
## 报告
如果您认为自己在本程序中发现了任何安全(技术)漏洞,欢迎您通过 https://security.alibaba.com 向我们提交漏洞报告。
如果您报告任何安全漏洞,请注意您可能包含以下信息(合格报告):
* git程序URL地址,运行的环境
* 包含必要屏幕截图的详细说明
* 重现漏洞的步骤以及修复漏洞的建议。
* 其他有用信息

## 处理
ASRC(Alibaba Security Response Center阿里安全响应中心)将尽快审核并回复您的提交内容,并在我们努力修复您提交的漏洞时随时通知您。如有必要,我们可能会与您联系以获取更多信息。


## 条款和条件
1. 仅接受技术漏洞并对其进行评级
2. 出于安全原因,上报者同意与ASRC合作完成他/她提交的漏洞,不向任何第三方透露任何漏洞信息
3. 如果不止一个人报告相同的安全漏洞,奖励将给予完成合格报告的第一个人
4. 为了保护程序的用户,请在修复之前不要直接提交git的issue,也不要在社区讨论任何漏洞信息
5. 所有奖励和声誉积分将提供给仅向ASRC提交其安全漏洞的上报者
6. 安全漏洞奖励的解释权利归ASRC所有

## 收集范围
我们的主要收集漏洞类别是:
* 服务器端请求伪造(SSRF)
* SQL注入
* 拒绝服务攻击
* 远程执行代码(RCE)
* XML外部实体攻击(XXE)
* 访问控制问题(不安全的直接对象参考问题等)
* 敏感目录遍历问题
* 本地文件读取(LFD)
* 敏感信息泄露(密钥,Cookie,Session等)

## 奖励
* 可直接导致严重问题的每个漏洞奖励7000元人民币
* 存在限制及需要一定特殊环境下才能利用的问题将给予700-5600元人民币不等的奖励,比如需要用户主动点击才会触发的问题或需要admin权限
* 只有在指定环境下才可以运行的利用将有可能被收纳但不给予奖励,或直接被忽略,比如只在fastjson+linux特定版本才会出现的问题

## 不在收集范围的报告
* 影响过时浏览器或平台用户的漏洞
* Self-XSS
* 会话固定
* 内容欺骗
* 缺少cookie标记
* 混合内容警告
* SSL / TLS问题
* Clickjacking 
* 基于Flash的漏洞
* 反射文件下载攻击(RFD)
* 物理或社会工程攻击
* 未验证自动化工具或扫描仪的结果
* 登录/注销/未认证/低影响CSRF
* 需要MITM或物理访问用户设备的攻击
* 与网络协议或行业标准相关的问题
* 不能用于直接攻击的错误信息泄露
* 缺少与安全相关的HTTP标头等





# Vulnerability Reward Program
## Reporting
If you believe you have found any security (technical) vulnerability in the Program, you are welcomed to submit a vulnerability report to us at https://security.alibaba.com 
In case of reporting any security vulnerability, please be noted that you may including following information (Qualified Reporting):
* The git program URL and running version 
* A detailed description with necessary screenshots
* Steps to reappearance the vulnerability and your advice to fix it
* Other useful information


## Processing
ASRC (Alibaba Security Response Center) will review and respond as quickly as possible to your submission, and keep you informed as we work to fix the vulnerability you submitted. We may contact you for further information if necessary.


## Terms and Conditions
1. ONLY technical vulnerabilities will be accepted and rated.
2. With regarding to security reasons, reporters agree to cooperate with ASRC exclusively on the vulnerability he/she submitted and not disclose any information of vulnerability to any third-parties.
3. In the case that more than one person report the same security vulnerability, the reward will be given to the first person who accomplish a Qualified Reporting.
4. To protect users of the program, please do not directly submit issue on github or discuss anything with the community 
5. All Rewards and Reputation Credits are given to the reporters who submit his/her security vulnerabilities ONLY to ASRC.
6. All rights for the security vulnerability rewards are reserved by ASRC.

## Scope of Collecting
The main categories of vulnerabilities that we are sincerely looking for are:
* Server-Side Request Forgery (SSRF)
* SQL Injection
* Denial of Service Attack
* Remote Code Execution (RCE)
* XML External Entity Attacks (XXE)
* Access Control Issues (Insecure Direct Object Reference issues, etc.)
* Directory Traversal Issues
* Local File Disclosure (LFD)
* Sensitive Information Leakage (Key, Cookie, Session etc.)

## Reward
* $1,000 for one valid report
* $100-$800 for Vuls which is limited. For example, Vuls that need user interactions or administrator authority
* Vuls which only work on the special version will be accepted but no reward, or directly rejected. For example, Vul runs only on a special linux version

## Ineligible Reports
* Vulnerabilities affecting users of outdated browsers or platforms
* "Self" XSS
* Session fixation
* Content Spoofing
* Missing cookie flags
* Mixed content warnings
* SSL/TLS best practices
* Clickjacking/UI redressing
* Flash-based vulnerabilities
* Reflected file download attacks (RFD)
* Physical or social engineering attacks
* Unverified Results of automated tools or scanners
* Login/logout/unauthenticated/low-impact CSRF
* Attacks requiring MITM or physical access to a user's device
* Issues related to networking protocols or industry standards
* Error information disclosure that cannot be used to make a direct attack
* Missing security-related HTTP headers which do not lead directly to a vulnerability


================================================
FILE: admin/admin-ui/.editorconfig
================================================
# http://editorconfig.org
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
insert_final_newline = false
trim_trailing_whitespace = false


================================================
FILE: admin/admin-ui/.eslintignore
================================================
build/*.js
src/assets
public
dist


================================================
FILE: admin/admin-ui/.eslintrc.js
================================================
module.exports = {
  root: true,
  parserOptions: {
    parser: 'babel-eslint',
    sourceType: 'module'
  },
  env: {
    browser: true,
    node: true,
    es6: true,
  },
  extends: ['plugin:vue/recommended', 'eslint:recommended'],

  // add your custom rules here
  //it is base on https://github.com/vuejs/eslint-config-vue
  rules: {
    "vue/max-attributes-per-line": [2, {
      "singleline": 10,
      "multiline": {
        "max": 1,
        "allowFirstLine": false
      }
    }],
    "vue/singleline-html-element-content-newline": "off",
    "vue/multiline-html-element-content-newline":"off",
    "vue/name-property-casing": ["error", "PascalCase"],
    "vue/no-v-html": "off",
    'accessor-pairs': 2,
    'arrow-spacing': [2, {
      'before': true,
      'after': true
    }],
    'block-spacing': [2, 'always'],
    'brace-style': [2, '1tbs', {
      'allowSingleLine': true
    }],
    'camelcase': [0, {
      'properties': 'always'
    }],
    'comma-dangle': [2, 'never'],
    'comma-spacing': [2, {
      'before': false,
      'after': true
    }],
    'comma-style': [2, 'last'],
    'constructor-super': 2,
    'curly': [2, 'multi-line'],
    'dot-location': [2, 'property'],
    'eol-last': 2,
    'eqeqeq': ["error", "always", {"null": "ignore"}],
    'generator-star-spacing': [2, {
      'before': true,
      'after': true
    }],
    'handle-callback-err': [2, '^(err|error)$'],
    'indent': [2, 2, {
      'SwitchCase': 1
    }],
    'jsx-quotes': [2, 'prefer-single'],
    'key-spacing': [2, {
      'beforeColon': false,
      'afterColon': true
    }],
    'keyword-spacing': [2, {
      'before': true,
      'after': true
    }],
    'new-cap': [2, {
      'newIsCap': true,
      'capIsNew': false
    }],
    'new-parens': 2,
    'no-array-constructor': 2,
    'no-caller': 2,
    'no-console': 'off',
    'no-class-assign': 2,
    'no-cond-assign': 2,
    'no-const-assign': 2,
    'no-control-regex': 0,
    'no-delete-var': 2,
    'no-dupe-args': 2,
    'no-dupe-class-members': 2,
    'no-dupe-keys': 2,
    'no-duplicate-case': 2,
    'no-empty-character-class': 2,
    'no-empty-pattern': 2,
    'no-eval': 2,
    'no-ex-assign': 2,
    'no-extend-native': 2,
    'no-extra-bind': 2,
    'no-extra-boolean-cast': 2,
    'no-extra-parens': [2, 'functions'],
    'no-fallthrough': 2,
    'no-floating-decimal': 2,
    'no-func-assign': 2,
    'no-implied-eval': 2,
    'no-inner-declarations': [2, 'functions'],
    'no-invalid-regexp': 2,
    'no-irregular-whitespace': 2,
    'no-iterator': 2,
    'no-label-var': 2,
    'no-labels': [2, {
      'allowLoop': false,
      'allowSwitch': false
    }],
    'no-lone-blocks': 2,
    'no-mixed-spaces-and-tabs': 2,
    'no-multi-spaces': 2,
    'no-multi-str': 2,
    'no-multiple-empty-lines': [2, {
      'max': 1
    }],
    'no-native-reassign': 2,
    'no-negated-in-lhs': 2,
    'no-new-object': 2,
    'no-new-require': 2,
    'no-new-symbol': 2,
    'no-new-wrappers': 2,
    'no-obj-calls': 2,
    'no-octal': 2,
    'no-octal-escape': 2,
    'no-path-concat': 2,
    'no-proto': 2,
    'no-redeclare': 2,
    'no-regex-spaces': 2,
    'no-return-assign': [2, 'except-parens'],
    'no-self-assign': 2,
    'no-self-compare': 2,
    'no-sequences': 2,
    'no-shadow-restricted-names': 2,
    'no-spaced-func': 2,
    'no-sparse-arrays': 2,
    'no-this-before-super': 2,
    'no-throw-literal': 2,
    'no-trailing-spaces': 2,
    'no-undef': 2,
    'no-undef-init': 2,
    'no-unexpected-multiline': 2,
    'no-unmodified-loop-condition': 2,
    'no-unneeded-ternary': [2, {
      'defaultAssignment': false
    }],
    'no-unreachable': 2,
    'no-unsafe-finally': 2,
    'no-unused-vars': [2, {
      'vars': 'all',
      'args': 'none'
    }],
    'no-useless-call': 2,
    'no-useless-computed-key': 2,
    'no-useless-constructor': 2,
    'no-useless-escape': 0,
    'no-whitespace-before-property': 2,
    'no-with': 2,
    'one-var': [2, {
      'initialized': 'never'
    }],
    'operator-linebreak': [2, 'after', {
      'overrides': {
        '?': 'before',
        ':': 'before'
      }
    }],
    'padded-blocks': [2, 'never'],
    'quotes': [2, 'single', {
      'avoidEscape': true,
      'allowTemplateLiterals': true
    }],
    'semi': [2, 'never'],
    'semi-spacing': [2, {
      'before': false,
      'after': true
    }],
    'space-before-blocks': [2, 'always'],
    'space-before-function-paren': [2, 'never'],
    'space-in-parens': [2, 'never'],
    'space-infix-ops': 2,
    'space-unary-ops': [2, {
      'words': true,
      'nonwords': false
    }],
    'spaced-comment': [2, 'always', {
      'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
    }],
    'template-curly-spacing': [2, 'never'],
    'use-isnan': 2,
    'valid-typeof': 2,
    'wrap-iife': [2, 'any'],
    'yield-star-spacing': [2, 'both'],
    'yoda': [2, 'never'],
    'prefer-const': 2,
    'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
    'object-curly-spacing': [2, 'always', {
      objectsInObjects: false
    }],
    'array-bracket-spacing': [2, 'never']
  }
}


================================================
FILE: admin/admin-ui/.gitignore
================================================
.DS_Store
node_modules/
dist/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
package-lock.json
tests/**/coverage/
target/

# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln


================================================
FILE: admin/admin-ui/.travis.yml
================================================
language: node_js
node_js: 10
script: npm run test
notifications:
  email: false


================================================
FILE: admin/admin-ui/LICENSE
================================================
MIT License

Copyright (c) 2017-present PanJiaChen

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: admin/admin-ui/babel.config.js
================================================
module.exports = {
  presets: [
    '@vue/app'
  ]
}


================================================
FILE: admin/admin-ui/build/index.js
================================================
const { run } = require('runjs')
const chalk = require('chalk')
const config = require('../vue.config.js')
const rawArgv = process.argv.slice(2)
const args = rawArgv.join(' ')

if (process.env.npm_config_preview || rawArgv.includes('--preview')) {
  const report = rawArgv.includes('--report')

  run(`vue-cli-service build ${args}`)

  const port = 9526
  const publicPath = config.publicPath

  var connect = require('connect')
  var serveStatic = require('serve-static')
  const app = connect()

  app.use(
    publicPath,
    serveStatic('./target/dist', {
      index: ['index.html', '/']
    })
  )

  app.listen(port, function () {
    console.log(chalk.green(`> Preview at  http://localhost:${port}${publicPath}`))
    if (report) {
      console.log(chalk.green(`> Report at  http://localhost:${port}${publicPath}report.html`))
    }

  })
} else {
  run(`vue-cli-service build ${args}`)
}


================================================
FILE: admin/admin-ui/jest.config.js
================================================
module.exports = {
  moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
  transform: {
    '^.+\\.vue$': 'vue-jest',
    '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
      'jest-transform-stub',
    '^.+\\.jsx?$': 'babel-jest'
  },
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1'
  },
  snapshotSerializers: ['jest-serializer-vue'],
  testMatch: [
    '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
  ],
  collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'],
  coverageDirectory: '<rootDir>/tests/unit/coverage',
  // 'collectCoverage': true,
  'coverageReporters': [
    'lcov',
    'text-summary'
  ],
  testURL: 'http://localhost/'
}


================================================
FILE: admin/admin-ui/mock/index.js
================================================
import Mock from 'mockjs'
import { param2Obj } from '../src/utils'

import user from './user'
import table from './table'

const mocks = [
  ...user,
  ...table
]

// for front mock
// please use it cautiously, it will redefine XMLHttpRequest,
// which will cause many of your third-party libraries to be invalidated(like progress event).
export function mockXHR() {
  // mock patch
  // https://github.com/nuysoft/Mock/issues/300
  Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
  Mock.XHR.prototype.send = function() {
    if (this.custom.xhr) {
      this.custom.xhr.withCredentials = this.withCredentials || false

      if (this.responseType) {
        this.custom.xhr.responseType = this.responseType
      }
    }
    this.proxy_send(...arguments)
  }

  function XHR2ExpressReqWrap(respond) {
    return function(options) {
      let result = null
      if (respond instanceof Function) {
        const { body, type, url } = options
        // https://expressjs.com/en/4x/api.html#req
        result = respond({
          method: type,
          body: JSON.parse(body),
          query: param2Obj(url)
        })
      } else {
        result = respond
      }
      return Mock.mock(result)
    }
  }

  for (const i of mocks) {
    Mock.mock(new RegExp(i.url), i.type || 'get', XHR2ExpressReqWrap(i.response))
  }
}

// for mock server
const responseFake = (url, type, respond) => {
  return {
    url: new RegExp(`/mock${url}`),
    type: type || 'get',
    response(req, res) {
      res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond))
    }
  }
}

export default mocks.map(route => {
  return responseFake(route.url, route.type, route.response)
})


================================================
FILE: admin/admin-ui/mock/mock-server.js
================================================
const chokidar = require('chokidar')
const bodyParser = require('body-parser')
const chalk = require('chalk')
const path = require('path')

const mockDir = path.join(process.cwd(), 'mock')

function registerRoutes(app) {
  let mockLastIndex
  const { default: mocks } = require('./index.js')
  for (const mock of mocks) {
    app[mock.type](mock.url, mock.response)
    mockLastIndex = app._router.stack.length
  }
  const mockRoutesLength = Object.keys(mocks).length
  return {
    mockRoutesLength: mockRoutesLength,
    mockStartIndex: mockLastIndex - mockRoutesLength
  }
}

function unregisterRoutes() {
  Object.keys(require.cache).forEach(i => {
    if (i.includes(mockDir)) {
      delete require.cache[require.resolve(i)]
    }
  })
}

module.exports = app => {
  // es6 polyfill
  require('@babel/register')

  // parse app.body
  // https://expressjs.com/en/4x/api.html#req.body
  app.use(bodyParser.json())
  app.use(bodyParser.urlencoded({
    extended: true
  }))

  const mockRoutes = registerRoutes(app)
  var mockRoutesLength = mockRoutes.mockRoutesLength
  var mockStartIndex = mockRoutes.mockStartIndex

  // watch files, hot reload mock server
  chokidar.watch(mockDir, {
    ignored: /mock-server/,
    ignoreInitial: true
  }).on('all', (event, path) => {
    if (event === 'change' || event === 'add') {
      try {
        // remove mock routes stack
        app._router.stack.splice(mockStartIndex, mockRoutesLength)

        // clear routes cache
        unregisterRoutes()

        const mockRoutes = registerRoutes(app)
        mockRoutesLength = mockRoutes.mockRoutesLength
        mockStartIndex = mockRoutes.mockStartIndex

        console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed  ${path}`))
      } catch (error) {
        console.log(chalk.redBright(error))
      }
    }
  })
}


================================================
FILE: admin/admin-ui/mock/table.js
================================================
import Mock from 'mockjs'

const data = Mock.mock({
  'items|30': [{
    id: '@id',
    title: '@sentence(10, 20)',
    'status|1': ['published', 'draft', 'deleted'],
    author: 'name',
    display_time: '@datetime',
    pageviews: '@integer(300, 5000)'
  }]
})

export default [
  {
    url: '/table/list',
    type: 'get',
    response: config => {
      const items = data.items
      return {
        code: 20000,
        data: {
          total: items.length,
          items: items
        }
      }
    }
  }
]


================================================
FILE: admin/admin-ui/mock/user.js
================================================

const tokens = {
  admin: {
    token: 'admin-token'
  },
  editor: {
    token: 'editor-token'
  }
}

const users = {
  'admin-token': {
    roles: ['admin'],
    introduction: 'I am a super administrator',
    avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
    name: 'Super Admin'
  },
  'editor-token': {
    roles: ['editor'],
    introduction: 'I am an editor',
    avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
    name: 'Normal Editor'
  }
}

export default [
  // user login
  {
    url: '/user/login',
    type: 'post',
    response: config => {
      const { username } = config.body
      const token = tokens[username]

      // mock error
      if (!token) {
        return {
          code: 60204,
          message: 'Account and password are incorrect.'
        }
      }

      return {
        code: 20000,
        data: token
      }
    }
  },

  // get user info
  {
    url: '/user/info\.*',
    type: 'get',
    response: config => {
      const { token } = config.query
      const info = users[token]

      // mock error
      if (!info) {
        return {
          code: 50008,
          message: 'Login failed, unable to get user details.'
        }
      }

      return {
        code: 20000,
        data: info
      }
    }
  },

  // user logout
  {
    url: '/user/logout',
    type: 'post',
    response: _ => {
      return {
        code: 20000,
        data: 'success'
      }
    }
  }
]


================================================
FILE: admin/admin-ui/node/node
================================================
[File too large to display: 34.1 MB]

================================================
FILE: admin/admin-ui/package.json
================================================
{
  "name": "canal-admin-ui",
  "version": "1.1.4",
  "description": "A canal-admin ui with Element UI & axios & iconfont & permission control & lint",
  "author": "Machengyuan <rewerma@163.com>",
  "license": "MIT",
  "scripts": {
    "dev": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "build:stage": "vue-cli-service build --mode staging",
    "preview": "node build/index.js --preview",
    "lint": "eslint --ext .js,.vue src",
    "test:unit": "jest --clearCache && vue-cli-service test:unit",
    "test:ci": "npm run lint && npm run test:unit",
    "svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml"
  },
  "dependencies": {
    "axios": "0.18.1",
    "element-ui": "2.7.2",
    "js-cookie": "2.2.0",
    "normalize.css": "7.0.0",
    "nprogress": "0.2.0",
    "path-to-regexp": "2.4.0",
    "vue": "2.6.10",
    "vue-router": "3.0.6",
    "vuex": "3.1.0"
  },
  "devDependencies": {
    "@babel/core": "7.0.0",
    "@babel/register": "7.0.0",
    "@vue/cli-plugin-babel": "3.6.0",
    "@vue/cli-plugin-eslint": "^3.9.1",
    "@vue/cli-plugin-unit-jest": "3.6.3",
    "@vue/cli-service": "3.6.0",
    "@vue/test-utils": "1.0.0-beta.29",
    "autoprefixer": "^9.5.1",
    "babel-core": "7.0.0-bridge.0",
    "babel-eslint": "10.0.1",
    "babel-jest": "23.6.0",
    "chalk": "2.4.2",
    "connect": "3.6.6",
    "eslint": "5.15.3",
    "eslint-plugin-vue": "5.2.2",
    "html-webpack-plugin": "3.2.0",
    "mockjs": "1.0.1-beta3",
    "node-sass": "^4.9.0",
    "runjs": "^4.3.2",
    "sass-loader": "^7.1.0",
    "script-ext-html-webpack-plugin": "2.1.3",
    "script-loader": "0.7.2",
    "serve-static": "^1.13.2",
    "svg-sprite-loader": "4.1.3",
    "svgo": "1.2.2",
    "vue-template-compiler": "2.6.10",
    "vue2-ace-editor": "^0.0.13"
  },
  "engines": {
    "node": ">=8.9",
    "npm": ">= 3.0.0"
  },
  "browserslist": [
    "> 1%",
    "last 2 versions"
  ]
}


================================================
FILE: admin/admin-ui/pom.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <parent>
    <artifactId>canal.admin</artifactId>
    <groupId>com.alibaba.otter</groupId>
    <version>1.1.9-SNAPSHOT</version>
  </parent>
  <modelVersion>4.0.0</modelVersion>

  <artifactId>canal.admin-ui</artifactId>
  <name>canal admin-ui module for otter ${project.version}</name>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <frontend-maven-plugin.version>1.6</frontend-maven-plugin.version>
  </properties>

  <profiles>
    <profile>
      <id>npm</id>
      <activation>
        <property>
          <name>env</name>
          <value>npm</value>
        </property>
      </activation>
      <build>
        <plugins>
          <plugin>
            <groupId>com.github.eirslett</groupId>
            <artifactId>frontend-maven-plugin</artifactId>
            <version>${frontend-maven-plugin.version}</version>
            <executions>
              <execution>
                <id>install node and npm</id>
                <goals>
                  <goal>install-node-and-npm</goal>
                </goals>
                <configuration>
                  <nodeVersion>v9.11.1</nodeVersion>
                </configuration>
              </execution>
              <!-- Install all project dependencies -->
              <execution>
                <id>npm install</id>
                <goals>
                  <goal>npm</goal>
                </goals>
                <!-- optional: default phase is "generate-resources" -->
                <phase>generate-resources</phase>
                <!-- Optional configuration which provides for running any npm command -->
                <configuration>
                  <arguments>install</arguments>
                </configuration>
              </execution>
              <!-- Build and minify static files -->
              <execution>
                <id>npm run build</id>
                <goals>
                  <goal>npm</goal>
                </goals>
                <configuration>
                  <arguments>run build</arguments>
                </configuration>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    </profile>
  </profiles>
</project>


================================================
FILE: admin/admin-ui/postcss.config.js
================================================
// https://github.com/michael-ciniawsky/postcss-load-config

module.exports = {
  'plugins': {
    // to edit target browsers: use "browserslist" field in package.json
    'autoprefixer': {}
  }
}


================================================
FILE: admin/admin-ui/public/index.html
================================================
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title><%= webpackConfig.name %></title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but <%= webpackConfig.name %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>


================================================
FILE: admin/admin-ui/src/App.vue
================================================
<template>
  <div id="app">
    <router-view />
  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>


================================================
FILE: admin/admin-ui/src/api/canalCluster.js
================================================
import request from '@/utils/request'

export function getCanalClusters(params) {
  return request({
    url: '/canal/clusters',
    method: 'get',
    params: params
  })
}

export function addCanalCluster(data) {
  return request({
    url: '/canal/cluster',
    method: 'post',
    data
  })
}

export function canalClusterDetail(id) {
  return request({
    url: '/canal/cluster/' + id,
    method: 'get'
  })
}

export function updateCanalCluster(data) {
  return request({
    url: '/canal/cluster',
    method: 'put',
    data
  })
}

export function deleteCanalCluster(id) {
  return request({
    url: '/canal/cluster/' + id,
    method: 'delete'
  })
}

export function getClustersAndServers() {
  return request({
    url: '/canal/clustersAndServers',
    method: 'get'
  })
}


================================================
FILE: admin/admin-ui/src/api/canalConfig.js
================================================
import request from '@/utils/request'

export function getCanalConfig(clusterId, serverId) {
  return request({
    url: '/canal/config/' + clusterId + '/' + serverId,
    method: 'get'
  })
}

export function updateCanalConfig(data) {
  return request({
    url: '/canal/config',
    method: 'put',
    data
  })
}

export function getTemplateConfig() {
  return request({
    url: '/canal/config/template',
    method: 'get'
  })
}


================================================
FILE: admin/admin-ui/src/api/canalInstance.js
================================================
import request from '@/utils/request'

export function getCanalInstances(params) {
  return request({
    url: '/canal/instances',
    method: 'get',
    params: params
  })
}

export function canalInstanceDetail(id) {
  return request({
    url: '/canal/instance/' + id,
    method: 'get'
  })
}

export function updateCanalInstance(data) {
  return request({
    url: '/canal/instance',
    method: 'put',
    data
  })
}

export function addCanalInstance(data) {
  return request({
    url: '/canal/instance',
    method: 'post',
    data
  })
}

export function deleteCanalInstance(id) {
  return request({
    url: '/canal/instance/' + id,
    method: 'delete'
  })
}

export function startInstance(id, nodeId) {
  return request({
    url: '/canal/instance/start/' + id + '/' + nodeId,
    method: 'put'
  })
}

export function stopInstance(id, nodeId) {
  return request({
    url: '/canal/instance/stop/' + id + '/' + nodeId,
    method: 'put'
  })
}

export function instanceLog(id, nodeId) {
  return request({
    url: '/canal/instance/log/' + id + '/' + nodeId,
    method: 'get'
  })
}

export function instanceStatus(id, option) {
  return request({
    url: '/canal/instance/status/' + id + '?option=' + option,
    method: 'put'
  })
}

export function getActiveInstances(serverId) {
  return request({
    url: '/canal/active/instances/' + serverId,
    method: 'get'
  })
}

export function getTemplateInstance() {
  return request({
    url: '/canal/instance/template',
    method: 'get'
  })
}


================================================
FILE: admin/admin-ui/src/api/nodeServer.js
================================================
import request from '@/utils/request'

export function getNodeServers(params) {
  return request({
    url: '/nodeServers',
    method: 'get',
    params: params
  })
}

export function addNodeServer(data) {
  return request({
    url: '/nodeServer',
    method: 'post',
    data
  })
}

export function nodeServerDetail(id) {
  return request({
    url: '/nodeServer/' + id,
    method: 'get'
  })
}

export function updateNodeServer(data) {
  return request({
    url: '/nodeServer',
    method: 'put',
    data
  })
}

export function deleteNodeServer(id) {
  return request({
    url: '/nodeServer/' + id,
    method: 'delete'
  })
}

export function startNodeServer(id) {
  return request({
    url: '/nodeServer/start/' + id,
    method: 'put'
  })
}

export function stopNodeServer(id) {
  return request({
    url: '/nodeServer/stop/' + id,
    method: 'put'
  })
}

export function nodeServerLog(id) {
  return request({
    url: '/nodeServer/log/' + id,
    method: 'get'
  })
}


================================================
FILE: admin/admin-ui/src/api/table.js
================================================
import request from '@/utils/request'

export function getList(params) {
  return request({
    url: '/table/list',
    method: 'get',
    params
  })
}


================================================
FILE: admin/admin-ui/src/api/user.js
================================================
import request from '@/utils/request'

export function login(data) {
  return request({
    url: '/user/login',
    method: 'post',
    data
  })
}

export function getInfo(token) {
  return request({
    url: '/user/info',
    method: 'get',
    params: { token }
  })
}

export function logout() {
  return request({
    url: '/user/logout',
    method: 'post'
  })
}

export function updateUser(data) {
  return request({
    url: '/user',
    method: 'put',
    data
  })
}


================================================
FILE: admin/admin-ui/src/components/Breadcrumb/index.vue
================================================
<template>
  <el-breadcrumb class="app-breadcrumb" separator="/">
    <transition-group name="breadcrumb">
      <el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
        <span v-if="item.redirect==='noRedirect'||index==levelList.length-1" class="no-redirect">{{ item.meta.title }}</span>
        <a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
      </el-breadcrumb-item>
    </transition-group>
  </el-breadcrumb>
</template>

<script>
import pathToRegexp from 'path-to-regexp'

export default {
  data() {
    return {
      levelList: null
    }
  },
  watch: {
    $route() {
      this.getBreadcrumb()
    }
  },
  created() {
    this.getBreadcrumb()
  },
  methods: {
    getBreadcrumb() {
      // only show routes with meta.title
      let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
      const first = matched[0]

      if (!this.isDashboard(first)) {
        matched = [{ path: '/dashboard', meta: { title: '主页' }}].concat(matched)
      }

      this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
    },
    isDashboard(route) {
      const name = route && route.name
      if (!name) {
        return false
      }
      return name.trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase()
    },
    pathCompile(path) {
      // To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
      const { params } = this.$route
      var toPath = pathToRegexp.compile(path)
      return toPath(params)
    },
    handleLink(item) {
      const { redirect, path } = item
      if (redirect) {
        this.$router.push(redirect)
        return
      }
      this.$router.push(this.pathCompile(path))
    }
  }
}
</script>

<style lang="scss" scoped>
.app-breadcrumb.el-breadcrumb {
  display: inline-block;
  font-size: 14px;
  line-height: 50px;
  margin-left: 8px;

  .no-redirect {
    color: #97a8be;
    cursor: text;
  }
}
</style>


================================================
FILE: admin/admin-ui/src/components/Hamburger/index.vue
================================================
<template>
  <div style="padding: 0 15px;" @click="toggleClick">
    <svg
      :class="{'is-active':isActive}"
      class="hamburger"
      viewBox="0 0 1024 1024"
      xmlns="http://www.w3.org/2000/svg"
      width="64"
      height="64"
    >
      <path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" />
    </svg>
  </div>
</template>

<script>
export default {
  name: 'Hamburger',
  props: {
    isActive: {
      type: Boolean,
      default: false
    }
  },
  methods: {
    toggleClick() {
      this.$emit('toggleClick')
    }
  }
}
</script>

<style scoped>
.hamburger {
  display: inline-block;
  vertical-align: middle;
  width: 20px;
  height: 20px;
}

.hamburger.is-active {
  transform: rotate(180deg);
}
</style>


================================================
FILE: admin/admin-ui/src/components/Pagination/index.vue
================================================
<template>
  <div :class="{'hidden':hidden}" class="pagination-container">
    <el-pagination
      :background="background"
      :current-page.sync="currentPage"
      :page-size.sync="pageSize"
      :layout="layout"
      :page-sizes="pageSizes"
      :total="total"
      v-bind="$attrs"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
  </div>
</template>

<script>
import { scrollTo } from '@/utils/scrollTo'

export default {
  name: 'Pagination',
  props: {
    total: {
      required: true,
      type: Number
    },
    page: {
      type: Number,
      default: 1
    },
    limit: {
      type: Number,
      default: 20
    },
    pageSizes: {
      type: Array,
      default() {
        return [10, 20, 30, 50]
      }
    },
    layout: {
      type: String,
      default: 'total, sizes, prev, pager, next, jumper'
    },
    background: {
      type: Boolean,
      default: true
    },
    autoScroll: {
      type: Boolean,
      default: true
    },
    hidden: {
      type: Boolean,
      default: false
    }
  },
  computed: {
    currentPage: {
      get() {
        return this.page
      },
      set(val) {
        this.$emit('update:page', val)
      }
    },
    pageSize: {
      get() {
        return this.limit
      },
      set(val) {
        this.$emit('update:limit', val)
      }
    }
  },
  methods: {
    handleSizeChange(val) {
      this.$emit('pagination', { page: this.currentPage, limit: val })
      if (this.autoScroll) {
        scrollTo(0, 800)
      }
    },
    handleCurrentChange(val) {
      this.$emit('pagination', { page: val, limit: this.pageSize })
      if (this.autoScroll) {
        scrollTo(0, 800)
      }
    }
  }
}
</script>

<style scoped>
.pagination-container {
  background: #fff;
  padding: 32px 16px;
}
.pagination-container.hidden {
  display: none;
}
</style>


================================================
FILE: admin/admin-ui/src/components/SvgIcon/index.vue
================================================
<template>
  <div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
  <svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
    <use :xlink:href="iconName" />
  </svg>
</template>

<script>
// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
import { isExternal } from '@/utils/validate'

export default {
  name: 'SvgIcon',
  props: {
    iconClass: {
      type: String,
      required: true
    },
    className: {
      type: String,
      default: ''
    }
  },
  computed: {
    isExternal() {
      return isExternal(this.iconClass)
    },
    iconName() {
      return `#icon-${this.iconClass}`
    },
    svgClass() {
      if (this.className) {
        return 'svg-icon ' + this.className
      } else {
        return 'svg-icon'
      }
    },
    styleExternalIcon() {
      return {
        mask: `url(${this.iconClass}) no-repeat 50% 50%`,
        '-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
      }
    }
  }
}
</script>

<style scoped>
.svg-icon {
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  fill: currentColor;
  overflow: hidden;
}

.svg-external-icon {
  background-color: currentColor;
  mask-size: cover!important;
  display: inline-block;
}
</style>


================================================
FILE: admin/admin-ui/src/icons/index.js
================================================
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon'// svg component

// register globally
Vue.component('svg-icon', SvgIcon)

const req = require.context('./svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req)


================================================
FILE: admin/admin-ui/src/icons/svgo.yml
================================================
# replace default config

# multipass: true
# full: true

plugins:

  # - name
  #
  # or:
  # - name: false
  # - name: true
  #
  # or:
  # - name:
  #     param1: 1
  #     param2: 2

- removeAttrs:
    attrs:
      - 'fill'
      - 'fill-rule'


================================================
FILE: admin/admin-ui/src/layout/components/AppMain.vue
================================================
<template>
  <section class="app-main">
    <transition name="fade-transform" mode="out-in">
      <router-view :key="key" />
    </transition>
  </section>
</template>

<script>
export default {
  name: 'AppMain',
  computed: {
    key() {
      return this.$route.path
    }
  }
}
</script>

<style scoped>
.app-main {
  /*50 = navbar  */
  min-height: calc(100vh - 50px);
  width: 100%;
  position: relative;
  overflow: hidden;
}
.fixed-header+.app-main {
  padding-top: 50px;
}
</style>

<style lang="scss">
// fix css style bug in open el-dialog
.el-popup-parent--hidden {
  .fixed-header {
    padding-right: 15px;
  }
}
</style>


================================================
FILE: admin/admin-ui/src/layout/components/Navbar.vue
================================================
<template>
  <div class="navbar">
    <hamburger :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />

    <breadcrumb class="breadcrumb-container" />

    <div class="right-menu">
      <el-dropdown class="avatar-container" trigger="click">
        <div class="avatar-wrapper">
          <!-- avatar+'?imageView2/1/w/80/h/80' -->
          <img :src="avat+'?imageView2/1/w/80/h/80'" class="user-avatar">
          <i class="el-icon-caret-bottom" />
        </div>
        <el-dropdown-menu slot="dropdown" class="user-dropdown">
          <router-link to="/">
            <el-dropdown-item>
              主页
            </el-dropdown-item>
          </router-link>
          <router-link to="/sys/user">
            <el-dropdown-item>账号管理</el-dropdown-item>
          </router-link>
          <el-dropdown-item divided>
            <span style="display:block;" @click="logout">退出</span>
          </el-dropdown-item>
        </el-dropdown-menu>
      </el-dropdown>
    </div>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'
import Breadcrumb from '@/components/Breadcrumb'
import Hamburger from '@/components/Hamburger'

export default {
  components: {
    Breadcrumb,
    Hamburger
  },
  data() {
    return {
      avat: './avatar.gif'
    }
  },
  computed: {
    ...mapGetters([
      'sidebar',
      'avatar'
    ])
  },
  methods: {
    toggleSideBar() {
      this.$store.dispatch('app/toggleSideBar')
    },
    async logout() {
      await this.$store.dispatch('user/logout')
      this.$router.push(`/login?redirect=${this.$route.fullPath}`)
    }
  }
}
</script>

<style lang="scss" scoped>
.navbar {
  height: 50px;
  overflow: hidden;
  position: relative;
  background: #fff;
  box-shadow: 0 1px 4px rgba(0,21,41,.08);

  .hamburger-container {
    line-height: 46px;
    height: 100%;
    float: left;
    cursor: pointer;
    transition: background .3s;
    -webkit-tap-highlight-color:transparent;

    &:hover {
      background: rgba(0, 0, 0, .025)
    }
  }

  .breadcrumb-container {
    float: left;
  }

  .right-menu {
    float: right;
    height: 100%;
    line-height: 50px;

    &:focus {
      outline: none;
    }

    .right-menu-item {
      display: inline-block;
      padding: 0 8px;
      height: 100%;
      font-size: 18px;
      color: #5a5e66;
      vertical-align: text-bottom;

      &.hover-effect {
        cursor: pointer;
        transition: background .3s;

        &:hover {
          background: rgba(0, 0, 0, .025)
        }
      }
    }

    .avatar-container {
      margin-right: 30px;

      .avatar-wrapper {
        margin-top: 5px;
        position: relative;

        .user-avatar {
          cursor: pointer;
          width: 40px;
          height: 40px;
          border-radius: 10px;
        }

        .el-icon-caret-bottom {
          cursor: pointer;
          position: absolute;
          right: -20px;
          top: 25px;
          font-size: 12px;
        }
      }
    }
  }
}
</style>


================================================
FILE: admin/admin-ui/src/layout/components/Sidebar/FixiOSBug.js
================================================
export default {
  computed: {
    device() {
      return this.$store.state.app.device
    }
  },
  mounted() {
    // In order to fix the click on menu on the ios device will trigger the mouseleave bug
    // https://github.com/PanJiaChen/vue-element-admin/issues/1135
    this.fixBugIniOS()
  },
  methods: {
    fixBugIniOS() {
      const $subMenu = this.$refs.subMenu
      if ($subMenu) {
        const handleMouseleave = $subMenu.handleMouseleave
        $subMenu.handleMouseleave = (e) => {
          if (this.device === 'mobile') {
            return
          }
          handleMouseleave(e)
        }
      }
    }
  }
}


================================================
FILE: admin/admin-ui/src/layout/components/Sidebar/Item.vue
================================================
<script>
export default {
  name: 'MenuItem',
  functional: true,
  props: {
    icon: {
      type: String,
      default: ''
    },
    title: {
      type: String,
      default: ''
    }
  },
  render(h, context) {
    const { icon, title } = context.props
    const vnodes = []

    if (icon) {
      vnodes.push(<svg-icon icon-class={icon}/>)
    }

    if (title) {
      vnodes.push(<span slot='title'>{(title)}</span>)
    }
    return vnodes
  }
}
</script>


================================================
FILE: admin/admin-ui/src/layout/components/Sidebar/Link.vue
================================================

<template>
  <!-- eslint-disable vue/require-component-is -->
  <component v-bind="linkProps(to)">
    <slot />
  </component>
</template>

<script>
import { isExternal } from '@/utils/validate'

export default {
  props: {
    to: {
      type: String,
      required: true
    }
  },
  methods: {
    linkProps(url) {
      if (isExternal(url)) {
        return {
          is: 'a',
          href: url,
          target: '_blank',
          rel: 'noopener'
        }
      }
      return {
        is: 'router-link',
        to: url
      }
    }
  }
}
</script>


================================================
FILE: admin/admin-ui/src/layout/components/Sidebar/Logo.vue
================================================
<template>
  <div class="sidebar-logo-container" :class="{'collapse':collapse}">
    <transition name="sidebarLogoFade">
      <router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
        <img v-if="logo" :src="logo" class="sidebar-logo">
        <h1 v-else class="sidebar-title">{{ title }} </h1>
      </router-link>
      <router-link v-else key="expand" class="sidebar-logo-link" to="/">
        <img v-if="logo" :src="logo" class="sidebar-logo">
        <h1 class="sidebar-title">{{ title }} </h1>
      </router-link>
    </transition>
  </div>
</template>

<script>
export default {
  name: 'SidebarLogo',
  props: {
    collapse: {
      type: Boolean,
      required: true
    }
  },
  data() {
    return {
      title: '',
      logo: './logo.png'
    }
  }
}
</script>

<style lang="scss" scoped>
.sidebarLogoFade-enter-active {
  transition: opacity 1.5s;
}

.sidebarLogoFade-enter,
.sidebarLogoFade-leave-to {
  opacity: 0;
}

.sidebar-logo-container {
  position: relative;
  width: 100%;
  height: 50px;
  line-height: 50px;
  background: #2b2f3a;
  text-align: center;
  overflow: hidden;

  & .sidebar-logo-link {
    height: 100%;
    width: 100%;

    & .sidebar-logo {
      width: 55px;
      // height: 32px;
      vertical-align: middle;
      margin-right: 12px;
    }

    & .sidebar-title {
      display: inline-block;
      margin: 0;
      color: #fff;
      font-weight: 600;
      line-height: 50px;
      font-size: 14px;
      font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
      vertical-align: middle;
    }
  }

  &.collapse {
    .sidebar-logo {
      margin-right: 0px;
    }
  }
}
</style>


================================================
FILE: admin/admin-ui/src/layout/components/Sidebar/SidebarItem.vue
================================================
<template>
  <div v-if="!item.hidden" class="menu-wrapper">
    <template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
      <app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
        <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
          <item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="onlyOneChild.meta.title" />
        </el-menu-item>
      </app-link>
    </template>

    <el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
      <template slot="title">
        <item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
      </template>
      <sidebar-item
        v-for="child in item.children"
        :key="child.path"
        :is-nest="true"
        :item="child"
        :base-path="resolvePath(child.path)"
        class="nest-menu"
      />
    </el-submenu>
  </div>
</template>

<script>
import path from 'path'
import { isExternal } from '@/utils/validate'
import Item from './Item'
import AppLink from './Link'
import FixiOSBug from './FixiOSBug'

export default {
  name: 'SidebarItem',
  components: { Item, AppLink },
  mixins: [FixiOSBug],
  props: {
    // route object
    item: {
      type: Object,
      required: true
    },
    isNest: {
      type: Boolean,
      default: false
    },
    basePath: {
      type: String,
      default: ''
    }
  },
  data() {
    // To fix https://github.com/PanJiaChen/vue-admin-template/issues/237
    // TODO: refactor with render function
    this.onlyOneChild = null
    return {}
  },
  methods: {
    hasOneShowingChild(children = [], parent) {
      const showingChildren = children.filter(item => {
        if (item.hidden) {
          return false
        } else {
          // Temp set(will be used if only has one showing child)
          this.onlyOneChild = item
          return true
        }
      })

      // When there is only one child router, the child router is displayed by default
      if (showingChildren.length === 1) {
        return true
      }

      // Show parent if there are no child router to display
      if (showingChildren.length === 0) {
        this.onlyOneChild = { ... parent, path: '', noShowingChildren: true }
        return true
      }

      return false
    },
    resolvePath(routePath) {
      if (isExternal(routePath)) {
        return routePath
      }
      if (isExternal(this.basePath)) {
        return this.basePath
      }
      return path.resolve(this.basePath, routePath)
    }
  }
}
</script>


================================================
FILE: admin/admin-ui/src/layout/components/Sidebar/index.vue
================================================
<template>
  <div :class="{'has-logo':showLogo}">
    <logo v-if="showLogo" :collapse="isCollapse" />
    <el-scrollbar wrap-class="scrollbar-wrapper">
      <el-menu
        :default-active="activeMenu"
        :collapse="isCollapse"
        :background-color="variables.menuBg"
        :text-color="variables.menuText"
        :unique-opened="false"
        :active-text-color="variables.menuActiveText"
        :collapse-transition="false"
        mode="vertical"
      >
        <sidebar-item v-for="route in routes" :key="route.path" :item="route" :base-path="route.path" />
      </el-menu>
    </el-scrollbar>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'
import Logo from './Logo'
import SidebarItem from './SidebarItem'
import variables from '@/styles/variables.scss'

export default {
  components: { SidebarItem, Logo },
  computed: {
    ...mapGetters([
      'sidebar'
    ]),
    routes() {
      return this.$router.options.routes
    },
    activeMenu() {
      const route = this.$route
      const { meta, path } = route
      // if set path, the sidebar will highlight the path you set
      if (meta.activeMenu) {
        return meta.activeMenu
      }
      return path
    },
    showLogo() {
      return this.$store.state.settings.sidebarLogo
    },
    variables() {
      return variables
    },
    isCollapse() {
      return !this.sidebar.opened
    }
  }
}
</script>


================================================
FILE: admin/admin-ui/src/layout/components/index.js
================================================
export { default as Navbar } from './Navbar'
export { default as Sidebar } from './Sidebar'
export { default as AppMain } from './AppMain'


================================================
FILE: admin/admin-ui/src/layout/index.vue
================================================
<template>
  <div :class="classObj" class="app-wrapper">
    <div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
    <sidebar class="sidebar-container" />
    <div class="main-container">
      <div :class="{'fixed-header':fixedHeader}">
        <navbar />
      </div>
      <app-main />
    </div>
  </div>
</template>

<script>
import { Navbar, Sidebar, AppMain } from './components'
import ResizeMixin from './mixin/ResizeHandler'

export default {
  name: 'Layout',
  components: {
    Navbar,
    Sidebar,
    AppMain
  },
  mixins: [ResizeMixin],
  computed: {
    sidebar() {
      return this.$store.state.app.sidebar
    },
    device() {
      return this.$store.state.app.device
    },
    fixedHeader() {
      return this.$store.state.settings.fixedHeader
    },
    classObj() {
      return {
        hideSidebar: !this.sidebar.opened,
        openSidebar: this.sidebar.opened,
        withoutAnimation: this.sidebar.withoutAnimation,
        mobile: this.device === 'mobile'
      }
    }
  },
  methods: {
    handleClickOutside() {
      this.$store.dispatch('app/closeSideBar', { withoutAnimation: false })
    }
  }
}
</script>

<style lang="scss" scoped>
  @import "~@/styles/mixin.scss";
  @import "~@/styles/variables.scss";

  .app-wrapper {
    @include clearfix;
    position: relative;
    height: 100%;
    width: 100%;
    &.mobile.openSidebar{
      position: fixed;
      top: 0;
    }
  }
  .drawer-bg {
    background: #000;
    opacity: 0.3;
    width: 100%;
    top: 0;
    height: 100%;
    position: absolute;
    z-index: 999;
  }

  .fixed-header {
    position: fixed;
    top: 0;
    right: 0;
    z-index: 9;
    width: calc(100% - #{$sideBarWidth});
    transition: width 0.28s;
  }

  .hideSidebar .fixed-header {
    width: calc(100% - 54px)
  }

  .mobile .fixed-header {
    width: 100%;
  }
</style>


================================================
FILE: admin/admin-ui/src/layout/mixin/ResizeHandler.js
================================================
import store from '@/store'

const { body } = document
const WIDTH = 992 // refer to Bootstrap's responsive design

export default {
  watch: {
    $route(route) {
      if (this.device === 'mobile' && this.sidebar.opened) {
        store.dispatch('app/closeSideBar', { withoutAnimation: false })
      }
    }
  },
  beforeMount() {
    window.addEventListener('resize', this.$_resizeHandler)
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.$_resizeHandler)
  },
  mounted() {
    const isMobile = this.$_isMobile()
    if (isMobile) {
      store.dispatch('app/toggleDevice', 'mobile')
      store.dispatch('app/closeSideBar', { withoutAnimation: true })
    }
  },
  methods: {
    // use $_ for mixins properties
    // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
    $_isMobile() {
      const rect = body.getBoundingClientRect()
      return rect.width - 1 < WIDTH
    },
    $_resizeHandler() {
      if (!document.hidden) {
        const isMobile = this.$_isMobile()
        store.dispatch('app/toggleDevice', isMobile ? 'mobile' : 'desktop')

        if (isMobile) {
          store.dispatch('app/closeSideBar', { withoutAnimation: true })
        }
      }
    }
  }
}


================================================
FILE: admin/admin-ui/src/main.js
================================================
import Vue from 'vue'

import 'normalize.css/normalize.css' // A modern alternative to CSS resets

import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import locale from 'element-ui/lib/locale/lang/en' // lang i18n

import '@/styles/index.scss' // global css

import App from './App'
import store from './store'
import router from './router'

import '@/icons' // icon
import '@/permission' // permission control

/**
 * If you don't want to use mock-server
 * you want to use MockJs for mock api
 * you can execute: mockXHR()
 *
 * Currently MockJs will be used in the production environment,
 * please remove it before going online! ! !
 */
// import { mockXHR } from '../mock'
// if (process.env.NODE_ENV === 'production') {
//   mockXHR()
// }

// set ElementUI lang to EN
Vue.use(ElementUI, {
  size: 'small',
  locale
})

Vue.config.productionTip = false

new Vue({
  el: '#app',
  router,
  store,
  render: h => h(App)
})


================================================
FILE: admin/admin-ui/src/permission.js
================================================
import router from './router'
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
import { getToken } from '@/utils/auth' // get token from cookie
import getPageTitle from '@/utils/get-page-title'

NProgress.configure({ showSpinner: false }) // NProgress Configuration

const whiteList = ['/login'] // no redirect whitelist

router.beforeEach(async(to, from, next) => {
  // start progress bar
  NProgress.start()

  // set page title
  document.title = getPageTitle(to.meta.title)

  // determine whether the user has logged in
  const hasToken = getToken()

  if (hasToken) {
    if (to.path === '/login') {
      // if is logged in, redirect to the home page
      next({ path: '/' })
      NProgress.done()
    } else {
      const hasGetUserInfo = store.getters.name
      if (hasGetUserInfo) {
        next()
      } else {
        try {
          // get user info
          await store.dispatch('user/getInfo')

          next()
        } catch (error) {
          // remove token and go to login page to re-login
          await store.dispatch('user/resetToken')
          Message.error(error || 'Has Error')
          next(`/login?redirect=${to.path}`)
          NProgress.done()
        }
      }
    }
  } else {
    /* has no token*/

    if (whiteList.indexOf(to.path) !== -1) {
      // in the free login whitelist, go directly
      next()
    } else {
      // other pages that do not have permission to access are redirected to the login page.
      next(`/login?redirect=${to.path}`)
      NProgress.done()
    }
  }
})

router.afterEach(() => {
  // finish progress bar
  NProgress.done()
})


================================================
FILE: admin/admin-ui/src/router/index.js
================================================
import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

/* Layout */
import Layout from '@/layout'

/**
 * Note: sub-menu only appear when route children.length >= 1
 * Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html
 *
 * hidden: true                   if set true, item will not show in the sidebar(default is false)
 * alwaysShow: true               if set true, will always show the root menu
 *                                if not set alwaysShow, when item has more than one children route,
 *                                it will becomes nested mode, otherwise not show the root menu
 * redirect: noRedirect           if set noRedirect will no redirect in the breadcrumb
 * name:'router-name'             the name is used by <keep-alive> (must set!!!)
 * meta : {
    roles: ['admin','editor']    control the page roles (you can set multiple roles)
    title: 'title'               the name show in sidebar and breadcrumb (recommend set)
    icon: 'svg-name'             the icon show in the sidebar
    breadcrumb: false            if set false, the item will hidden in breadcrumb(default is true)
    activeMenu: '/example/list'  if set path, the sidebar will highlight the path you set
  }
 */

/**
 * constantRoutes
 * a base page that does not have permission requirements
 * all roles can be accessed
 */
export const constantRoutes = [
  {
    path: '/login',
    component: () => import('@/views/login/index'),
    hidden: true
  },

  {
    path: '/404',
    component: () => import('@/views/404'),
    hidden: true
  },

  {
    path: '/',
    component: Layout,
    redirect: '/dashboard',
    children: [{
      path: 'dashboard',
      name: '主页',
      component: () => import('@/views/dashboard/index'),
      meta: { title: '主页', icon: 'dashboard' }
    }],
    hidden: true
  },

  {
    path: '/sys',
    component: Layout,
    redirect: '/user',
    children: [{
      path: 'user',
      name: '用户信息',
      component: () => import('@/views/sys/UserInfo'),
      meta: { title: '用户信息' }
    }],
    hidden: true
  },

  {
    path: '/canalServer',
    component: Layout,
    redirect: '/canalServer/nodeServers',
    name: 'Canal Server',
    meta: { title: 'Canal Server', icon: 'example' },
    children: [
      {
        path: 'canalClusters',
        name: 'Canal 集群管理',
        component: () => import('@/views/canalServer/CanalCluster'),
        meta: { title: '集群管理', icon: 'tree' }
      },
      {
        path: 'nodeServers',
        name: 'Server 状态',
        component: () => import('@/views/canalServer/NodeServer'),
        meta: { title: 'Server 管理', icon: 'form' }
      },
      {
        path: 'nodeServer/config',
        name: 'Server 配置',
        component: () => import('@/views/canalServer/CanalConfig'),
        meta: { title: 'Server 配置' },
        hidden: true
      },
      {
        path: 'canalInstances',
        name: 'Instance 管理',
        component: () => import('@/views/canalServer/CanalInstance'),
        meta: { title: 'Instance 管理', icon: 'nested' }
      },
      {
        path: 'canalInstance/add',
        name: '新建Instance配置',
        component: () => import('@/views/canalServer/CanalInstanceAdd'),
        meta: { title: '新建Instance配置' },
        hidden: true
      },
      {
        path: 'canalInstance/modify',
        name: '修改Instance配置',
        component: () => import('@/views/canalServer/CanalInstanceUpdate'),
        meta: { title: '修改Instance配置' },
        hidden: true
      },
      {
        path: 'nodeServer/log',
        name: 'Server 日志',
        component: () => import('@/views/canalServer/CanalLogDetail'),
        meta: { title: 'Server 日志' },
        hidden: true
      },
      {
        path: 'canalInstance/log',
        name: 'Instance 日志',
        component: () => import('@/views/canalServer/CanalInstanceLogDetail'),
        meta: { title: 'Instance 日志' },
        hidden: true
      }
    ]
  },

  // 404 page must be placed at the end !!!
  { path: '*', redirect: '/404', hidden: true }
]

const createRouter = () => new Router({
  // mode: 'history', // require service support
  scrollBehavior: () => ({ y: 0 }),
  routes: constantRoutes
})

const router = createRouter()

// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export function resetRouter() {
  const newRouter = createRouter()
  router.matcher = newRouter.matcher // reset router
}

export default router


================================================
FILE: admin/admin-ui/src/settings.js
================================================
module.exports = {

  title: 'Canal Admin',

  /**
   * @type {boolean} true | false
   * @description Whether fix the header
   */
  fixedHeader: true,

  /**
   * @type {boolean} true | false
   * @description Whether show the logo in sidebar
   */
  sidebarLogo: true
}


================================================
FILE: admin/admin-ui/src/store/getters.js
================================================
const getters = {
  sidebar: state => state.app.sidebar,
  device: state => state.app.device,
  token: state => state.user.token,
  avatar: state => state.user.avatar,
  name: state => state.user.name
}
export default getters


================================================
FILE: admin/admin-ui/src/store/index.js
================================================
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
import app from './modules/app'
import settings from './modules/settings'
import user from './modules/user'

Vue.use(Vuex)

const store = new Vuex.Store({
  modules: {
    app,
    settings,
    user
  },
  getters
})

export default store


================================================
FILE: admin/admin-ui/src/store/modules/app.js
================================================
import Cookies from 'js-cookie'

const state = {
  sidebar: {
    opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true,
    withoutAnimation: false
  },
  device: 'desktop'
}

const mutations = {
  TOGGLE_SIDEBAR: state => {
    state.sidebar.opened = !state.sidebar.opened
    state.sidebar.withoutAnimation = false
    if (state.sidebar.opened) {
      Cookies.set('sidebarStatus', 1)
    } else {
      Cookies.set('sidebarStatus', 0)
    }
  },
  CLOSE_SIDEBAR: (state, withoutAnimation) => {
    Cookies.set('sidebarStatus', 0)
    state.sidebar.opened = false
    state.sidebar.withoutAnimation = withoutAnimation
  },
  TOGGLE_DEVICE: (state, device) => {
    state.device = device
  }
}

const actions = {
  toggleSideBar({ commit }) {
    commit('TOGGLE_SIDEBAR')
  },
  closeSideBar({ commit }, { withoutAnimation }) {
    commit('CLOSE_SIDEBAR', withoutAnimation)
  },
  toggleDevice({ commit }, device) {
    commit('TOGGLE_DEVICE', device)
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}


================================================
FILE: admin/admin-ui/src/store/modules/settings.js
================================================
import defaultSettings from '@/settings'

const { showSettings, fixedHeader, sidebarLogo } = defaultSettings

const state = {
  showSettings: showSettings,
  fixedHeader: fixedHeader,
  sidebarLogo: sidebarLogo
}

const mutations = {
  CHANGE_SETTING: (state, { key, value }) => {
    if (state.hasOwnProperty(key)) {
      state[key] = value
    }
  }
}

const actions = {
  changeSetting({ commit }, data) {
    commit('CHANGE_SETTING', data)
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}



================================================
FILE: admin/admin-ui/src/store/modules/user.js
================================================
import { login, logout, getInfo } from '@/api/user'
import { getToken, setToken, removeToken } from '@/utils/auth'
import { resetRouter } from '@/router'

const state = {
  token: getToken(),
  name: '',
  avatar: ''
}

const mutations = {
  SET_TOKEN: (state, token) => {
    state.token = token
  },
  SET_NAME: (state, name) => {
    state.name = name
  },
  SET_AVATAR: (state, avatar) => {
    state.avatar = avatar
  }
}

const actions = {
  // user login
  login({ commit }, userInfo) {
    const { username, password } = userInfo
    return new Promise((resolve, reject) => {
      login({ username: username.trim(), password: password }).then(response => {
        const { data } = response
        commit('SET_TOKEN', data.token)
        setToken(data.token)
        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },

  // get user info
  getInfo({ commit, state }) {
    return new Promise((resolve, reject) => {
      getInfo(state.token).then(response => {
        const { data } = response

        if (!data) {
          reject('Verification failed, please Login again.')
        }

        const { name, avatar } = data

        commit('SET_NAME', name)
        commit('SET_AVATAR', avatar)
        resolve(data)
      }).catch(error => {
        reject(error)
      })
    })
  },

  // user logout
  logout({ commit, state }) {
    return new Promise((resolve, reject) => {
      logout(state.token).then(() => {
        commit('SET_TOKEN', '')
        removeToken()
        resetRouter()
        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },

  // remove token
  resetToken({ commit }) {
    return new Promise(resolve => {
      commit('SET_TOKEN', '')
      removeToken()
      resolve()
    })
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}



================================================
FILE: admin/admin-ui/src/styles/element-ui.scss
================================================
// cover some element-ui styles

.el-breadcrumb__inner,
.el-breadcrumb__inner a {
  font-weight: 400 !important;
}

.el-upload {
  input[type="file"] {
    display: none !important;
  }
}

.el-upload__input {
  display: none;
}


// to fixed https://github.com/ElemeFE/element/issues/2461
.el-dialog {
  transform: none;
  left: 0;
  position: relative;
  margin: 0 auto;
}

// refine element ui upload
.upload-container {
  .el-upload {
    width: 100%;

    .el-upload-dragger {
      width: 100%;
      height: 200px;
    }
  }
}

// dropdown
.el-dropdown-menu {
  a {
    display: block
  }
}


================================================
FILE: admin/admin-ui/src/styles/index.scss
================================================
@import './variables.scss';
@import './mixin.scss';
@import './transition.scss';
@import './element-ui.scss';
@import './sidebar.scss';

body {
  height: 100%;
  -moz-osx-font-smoothing: grayscale;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
}

label {
  font-weight: 700;
}

html {
  height: 100%;
  box-sizing: border-box;
}

#app {
  height: 100%;
}

*,
*:before,
*:after {
  box-sizing: inherit;
}

a:focus,
a:active {
  outline: none;
}

a,
a:focus,
a:hover {
  cursor: pointer;
  color: inherit;
  text-decoration: none;
}

div:focus {
  outline: none;
}

.clearfix {
  &:after {
    visibility: hidden;
    display: block;
    font-size: 0;
    content: " ";
    clear: both;
    height: 0;
  }
}

// main-container global css
.app-container {
  padding: 20px;
}

.filter-container {
  padding-bottom: 10px;
  .filter-item {
    display: inline-block;
    vertical-align: middle;
    margin-bottom: 10px;
  }
}

================================================
FILE: admin/admin-ui/src/styles/mixin.scss
================================================
@mixin clearfix {
  &:after {
    content: "";
    display: table;
    clear: both;
  }
}

@mixin scrollBar {
  &::-webkit-scrollbar-track-piece {
    background: #d3dce6;
  }

  &::-webkit-scrollbar {
    width: 6px;
  }

  &::-webkit-scrollbar-thumb {
    background: #99a9bf;
    border-radius: 20px;
  }
}

@mixin relative {
  position: relative;
  width: 100%;
  height: 100%;
}


================================================
FILE: admin/admin-ui/src/styles/sidebar.scss
================================================
#app {

  .main-container {
    min-height: 100%;
    transition: margin-left .28s;
    margin-left: $sideBarWidth;
    position: relative;
  }

  .sidebar-container {
    transition: width 0.28s;
    width: $sideBarWidth !important;
    background-color: $menuBg;
    height: 100%;
    position: fixed;
    font-size: 0px;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 1001;
    overflow: hidden;

    // reset element-ui css
    .horizontal-collapse-transition {
      transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
    }

    .scrollbar-wrapper {
      overflow-x: hidden !important;
    }

    .el-scrollbar__bar.is-vertical {
      right: 0px;
    }

    .el-scrollbar {
      height: 100%;
    }

    &.has-logo {
      .el-scrollbar {
        height: calc(100% - 50px);
      }
    }

    .is-horizontal {
      display: none;
    }

    a {
      display: inline-block;
      width: 100%;
      overflow: hidden;
    }

    .svg-icon {
      margin-right: 16px;
    }

    .el-menu {
      border: none;
      height: 100%;
      width: 100% !important;
    }

    // menu hover
    .submenu-title-noDropdown,
    .el-submenu__title {
      &:hover {
        background-color: $menuHover !important;
      }
    }

    .is-active>.el-submenu__title {
      color: $subMenuActiveText !important;
    }

    & .nest-menu .el-submenu>.el-submenu__title,
    & .el-submenu .el-menu-item {
      min-width: $sideBarWidth !important;
      background-color: $subMenuBg !important;

      &:hover {
        background-color: $subMenuHover !important;
      }
    }
  }

  .hideSidebar {
    .sidebar-container {
      width: 54px !important;
    }

    .main-container {
      margin-left: 54px;
    }

    .submenu-title-noDropdown {
      padding: 0 !important;
      position: relative;

      .el-tooltip {
        padding: 0 !important;

        .svg-icon {
          margin-left: 20px;
        }
      }
    }

    .el-submenu {
      overflow: hidden;

      &>.el-submenu__title {
        padding: 0 !important;

        .svg-icon {
          margin-left: 20px;
        }

        .el-submenu__icon-arrow {
          display: none;
        }
      }
    }

    .el-menu--collapse {
      .el-submenu {
        &>.el-submenu__title {
          &>span {
            height: 0;
            width: 0;
            overflow: hidden;
            visibility: hidden;
            display: inline-block;
          }
        }
      }
    }
  }

  .el-menu--collapse .el-menu .el-submenu {
    min-width: $sideBarWidth !important;
  }

  // mobile responsive
  .mobile {
    .main-container {
      margin-left: 0px;
    }

    .sidebar-container {
      transition: transform .28s;
      width: $sideBarWidth !important;
    }

    &.hideSidebar {
      .sidebar-container {
        pointer-events: none;
        transition-duration: 0.3s;
        transform: translate3d(-$sideBarWidth, 0, 0);
      }
    }
  }

  .withoutAnimation {

    .main-container,
    .sidebar-container {
      transition: none;
    }
  }
}

// when menu collapsed
.el-menu--vertical {
  &>.el-menu {
    .svg-icon {
      margin-right: 16px;
    }
  }

  .nest-menu .el-submenu>.el-submenu__title,
  .el-menu-item {
    &:hover {
      // you can use $subMenuHover
      background-color: $menuHover !important;
    }
  }

  // the scroll bar appears when the subMenu is too long
  >.el-menu--popup {
    max-height: 100vh;
    overflow-y: auto;

    &::-webkit-scrollbar-track-piece {
      background: #d3dce6;
    }

    &::-webkit-scrollbar {
      width: 6px;
    }

    &::-webkit-scrollbar-thumb {
      background: #99a9bf;
      border-radius: 20px;
    }
  }
}


================================================
FILE: admin/admin-ui/src/styles/transition.scss
================================================
// global transition css

/* fade */
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.28s;
}

.fade-enter,
.fade-leave-active {
  opacity: 0;
}

/* fade-transform */
.fade-transform-leave-active,
.fade-transform-enter-active {
  transition: all .5s;
}

.fade-transform-enter {
  opacity: 0;
  transform: translateX(-30px);
}

.fade-transform-leave-to {
  opacity: 0;
  transform: translateX(30px);
}

/* breadcrumb transition */
.breadcrumb-enter-active,
.breadcrumb-leave-active {
  transition: all .5s;
}

.breadcrumb-enter,
.breadcrumb-leave-active {
  opacity: 0;
  transform: translateX(20px);
}

.breadcrumb-move {
  transition: all .5s;
}

.breadcrumb-leave-active {
  position: absolute;
}


================================================
FILE: admin/admin-ui/src/styles/variables.scss
================================================
// sidebar
$menuText:#bfcbd9;
$menuActiveText:#409EFF;
$subMenuActiveText:#f4f4f5; //https://github.com/ElemeFE/element/issues/12951

$menuBg:#304156;
$menuHover:#263445;

$subMenuBg:#1f2d3d;
$subMenuHover:#001528;

$sideBarWidth: 210px;

// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
:export {
  menuText: $menuText;
  menuActiveText: $menuActiveText;
  subMenuActiveText: $subMenuActiveText;
  menuBg: $menuBg;
  menuHover: $menuHover;
  subMenuBg: $subMenuBg;
  subMenuHover: $subMenuHover;
  sideBarWidth: $sideBarWidth;
}


================================================
FILE: admin/admin-ui/src/utils/auth.js
================================================
import Cookies from 'js-cookie'

const TokenKey = 'canal_admin_token'

export function getToken() {
  return Cookies.get(TokenKey)
}

export function setToken(token) {
  return Cookies.set(TokenKey, token, { maxAge: 0 })
}

export function removeToken() {
  return Cookies.remove(TokenKey)
}


================================================
FILE: admin/admin-ui/src/utils/get-page-title.js
================================================
import defaultSettings from '@/settings'

const title = defaultSettings.title || 'Vue Admin Template'

export default function getPageTitle(pageTitle) {
  if (pageTitle) {
    return `${pageTitle} - ${title}`
  }
  return `${title}`
}


================================================
FILE: admin/admin-ui/src/utils/index.js
================================================
/**
 * Created by PanJiaChen on 16/11/18.
 */

/**
 * Parse the time to string
 * @param {(Object|string|number)} time
 * @param {string} cFormat
 * @returns {string}
 */
export function parseTime(time, cFormat) {
  if (arguments.length === 0) {
    return null
  }
  const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
  let date
  if (typeof time === 'object') {
    date = time
  } else {
    if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
      time = parseInt(time)
    }
    if ((typeof time === 'number') && (time.toString().length === 10)) {
      time = time * 1000
    }
    date = new Date(time)
  }
  const formatObj = {
    y: date.getFullYear(),
    m: date.getMonth() + 1,
    d: date.getDate(),
    h: date.getHours(),
    i: date.getMinutes(),
    s: date.getSeconds(),
    a: date.getDay()
  }
  const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
    let value = formatObj[key]
    // Note: getDay() returns 0 on Sunday
    if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ] }
    if (result.length > 0 && value < 10) {
      value = '0' + value
    }
    return value || 0
  })
  return time_str
}

/**
 * @param {number} time
 * @param {string} option
 * @returns {string}
 */
export function formatTime(time, option) {
  if (('' + time).length === 10) {
    time = parseInt(time) * 1000
  } else {
    time = +time
  }
  const d = new Date(time)
  const now = Date.now()

  const diff = (now - d) / 1000

  if (diff < 30) {
    return '刚刚'
  } else if (diff < 3600) {
    // less 1 hour
    return Math.ceil(diff / 60) + '分钟前'
  } else if (diff < 3600 * 24) {
    return Math.ceil(diff / 3600) + '小时前'
  } else if (diff < 3600 * 24 * 2) {
    return '1天前'
  }
  if (option) {
    return parseTime(time, option)
  } else {
    return (
      d.getMonth() +
      1 +
      '月' +
      d.getDate() +
      '日' +
      d.getHours() +
      '时' +
      d.getMinutes() +
      '分'
    )
  }
}

/**
 * @param {string} url
 * @returns {Object}
 */
export function param2Obj(url) {
  const search = url.split('?')[1]
  if (!search) {
    return {}
  }
  return JSON.parse(
    '{"' +
      decodeURIComponent(search)
        .replace(/"/g, '\\"')
        .replace(/&/g, '","')
        .replace(/=/g, '":"')
        .replace(/\+/g, ' ') +
      '"}'
  )
}


================================================
FILE: admin/admin-ui/src/utils/request.js
================================================
import axios from 'axios'
import { MessageBox, Message } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'

// create an axios instance
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  // withCredentials: true, // send cookies when cross-domain requests
  timeout: 60000 // request timeout
})

// request interceptor
service.interceptors.request.use(
  config => {
    // do something before request is sent

    if (store.getters.token) {
      // let each request carry token
      // ['X-Token'] is a custom headers key
      // please modify it according to the actual situation
      config.headers['X-Token'] = getToken()
    }
    return config
  },
  error => {
    // do something with request error
    console.log(error) // for debug
    return Promise.reject(error)
  }
)

// response interceptor
service.interceptors.response.use(
  /**
   * If you want to get http information such as headers or status
   * Please return  response => response
  */

  /**
   * Determine the request status by custom code
   * Here is just an example
   * You can also judge the status by HTTP Status Code
   */
  response => {
    const res = response.data

    // if the custom code is not 20000, it is judged as an error.
    if (res.code !== 20000) {
      Message({
        message: res.message || 'Error',
        type: 'error',
        duration: 5 * 1000
      })

      // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
      if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
        // to re-login
        MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
          confirmButtonText: 'Re-Login',
          cancelButtonText: 'Cancel',
          type: 'warning'
        }).then(() => {
          store.dispatch('user/resetToken').then(() => {
            location.reload()
          })
        })
      }
      return Promise.reject(new Error(res.message || 'Error'))
    } else {
      return res
    }
  },
  error => {
    console.log('err' + error) // for debug
    Message({
      message: error.message,
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
  }
)

export default service


================================================
FILE: admin/admin-ui/src/utils/scrollTo.js
================================================
Math.easeInOutQuad = function(t, b, c, d) {
  t /= d / 2
  if (t < 1) {
    return c / 2 * t * t + b
  }
  t--
  return -c / 2 * (t * (t - 2) - 1) + b
}

// requestAnimationFrame for Smart Animating http://goo.gl/sx5sts
var requestAnimFrame = (function() {
  return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) { window.setTimeout(callback, 1000 / 60) }
})()

// because it's so fucking difficult to detect the scrolling element, just move them all
function move(amount) {
  document.documentElement.scrollTop = amount
  document.body.parentNode.scrollTop = amount
  document.body.scrollTop = amount
}

function position() {
  return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop
}

export function scrollTo(to, duration, callback) {
  const start = position()
  const change = to - start
  const increment = 20
  let currentTime = 0
  duration = (typeof (duration) === 'undefined') ? 500 : duration
  var animateScroll = function() {
    // increment the time
    currentTime += increment
    // find the value with the quadratic in-out easing function
    var val = Math.easeInOutQuad(currentTime, start, change, duration)
    // move the document.body
    move(val)
    // do the animation unless its over
    if (currentTime < duration) {
      requestAnimFrame(animateScroll)
    } else {
      if (callback && typeof (callback) === 'function') {
        // the animation is done so lets callback
        callback()
      }
    }
  }
  animateScroll()
}


================================================
FILE: admin/admin-ui/src/utils/validate.js
================================================
/**
 * Created by PanJiaChen on 16/11/18.
 */

/**
 * @param {string} path
 * @returns {Boolean}
 */
export function isExternal(path) {
  return /^(https?:|mailto:|tel:)/.test(path)
}

/**
 * @param {string} str
 * @returns {Boolean}
 */
export function validUsername(str) {
  const valid_map = ['admin', 'editor']
  return valid_map.indexOf(str.trim()) >= 0
}


================================================
FILE: admin/admin-ui/src/views/404.vue
================================================
<template>
  <div class="wscn-http404-container">
    <div class="wscn-http404">
      <div class="pic-404">
        <img class="pic-404__parent" src="@/assets/404_images/404.png" alt="404">
        <img class="pic-404__child left" src="@/assets/404_images/404_cloud.png" alt="404">
        <img class="pic-404__child mid" src="@/assets/404_images/404_cloud.png" alt="404">
        <img class="pic-404__child right" src="@/assets/404_images/404_cloud.png" alt="404">
      </div>
      <div class="bullshit">
        <div class="bullshit__oops">OOPS!</div>
        <div class="bullshit__info">All rights reserved
          <a style="color:#20a0ff" href="https://wallstreetcn.com" target="_blank">wallstreetcn</a>
        </div>
        <div class="bullshit__headline">{{ message }}</div>
        <div class="bullshit__info">Please check that the URL you entered is correct, or click the button below to return to the homepage.</div>
        <a href="" class="bullshit__return-home">Back to home</a>
      </div>
    </div>
  </div>
</template>

<script>

export default {
  name: 'Page404',
  computed: {
    message() {
      return 'The webmaster said that you can not enter this page...'
    }
  }
}
</script>

<style lang="scss" scoped>
.wscn-http404-container{
  transform: translate(-50%,-50%);
  position: absolute;
  top: 40%;
  left: 50%;
}
.wscn-http404 {
  position: relative;
  width: 1200px;
  padding: 0 50px;
  overflow: hidden;
  .pic-404 {
    position: relative;
    float: left;
    width: 600px;
    overflow: hidden;
    &__parent {
      width: 100%;
    }
    &__child {
      position: absolute;
      &.left {
        width: 80px;
        top: 17px;
        left: 220px;
        opacity: 0;
        animation-name: cloudLeft;
        animation-duration: 2s;
        animation-timing-function: linear;
        animation-fill-mode: forwards;
        animation-delay: 1s;
      }
      &.mid {
        width: 46px;
        top: 10px;
        left: 420px;
        opacity: 0;
        animation-name: cloudMid;
        animation-duration: 2s;
        animation-timing-function: linear;
        animation-fill-mode: forwards;
        animation-delay: 1.2s;
      }
      &.right {
        width: 62px;
        top: 100px;
        left: 500px;
        opacity: 0;
        animation-name: cloudRight;
        animation-duration: 2s;
        animation-timing-function: linear;
        animation-fill-mode: forwards;
        animation-delay: 1s;
      }
      @keyframes cloudLeft {
        0% {
          top: 17px;
          left: 220px;
          opacity: 0;
        }
        20% {
          top: 33px;
          left: 188px;
          opacity: 1;
        }
        80% {
          top: 81px;
          left: 92px;
          opacity: 1;
        }
        100% {
          top: 97px;
          left: 60px;
          opacity: 0;
        }
      }
      @keyframes cloudMid {
        0% {
          top: 10px;
          left: 420px;
          opacity: 0;
        }
        20% {
          top: 40px;
          left: 360px;
          opacity: 1;
        }
        70% {
          top: 130px;
          left: 180px;
          opacity: 1;
        }
        100% {
          top: 160px;
          left: 120px;
          opacity: 0;
        }
      }
      @keyframes cloudRight {
        0% {
          top: 100px;
          left: 500px;
          opacity: 0;
        }
        20% {
          top: 120px;
          left: 460px;
          opacity: 1;
        }
        80% {
          top: 180px;
          left: 340px;
          opacity: 1;
        }
        100% {
          top: 200px;
          left: 300px;
          opacity: 0;
        }
      }
    }
  }
  .bullshit {
    position: relative;
    float: left;
    width: 300px;
    padding: 30px 0;
    overflow: hidden;
    &__oops {
      font-size: 32px;
      font-weight: bold;
      line-height: 40px;
      color: #1482f0;
      opacity: 0;
      margin-bottom: 20px;
      animation-name: slideUp;
      animation-duration: 0.5s;
      animation-fill-mode: forwards;
    }
    &__headline {
      font-size: 20px;
      line-height: 24px;
      color: #222;
      font-weight: bold;
      opacity: 0;
      margin-bottom: 10px;
      animation-name: slideUp;
      animation-duration: 0.5s;
      animation-delay: 0.1s;
      animation-fill-mode: forwards;
    }
    &__info {
      font-size: 13px;
      line-height: 21px;
      color: grey;
      opacity: 0;
      margin-bottom: 30px;
      animation-name: slideUp;
      animation-duration: 0.5s;
      animation-delay: 0.2s;
      animation-fill-mode: forwards;
    }
    &__return-home {
      display: block;
      float: left;
      width: 110px;
      height: 36px;
      background: #1482f0;
      border-radius: 100px;
      text-align: center;
      color: #ffffff;
      opacity: 0;
      font-size: 14px;
      line-height: 36px;
      cursor: pointer;
      animation-name: slideUp;
      animation-duration: 0.5s;
      animation-delay: 0.3s;
      animation-fill-mode: forwards;
    }
    @keyframes slideUp {
      0% {
        transform: translateY(60px);
        opacity: 0;
      }
      100% {
        transform: translateY(0);
        opacity: 1;
      }
    }
  }
}
</style>


================================================
FILE: admin/admin-ui/src/views/canalServer/CanalCluster.vue
================================================
<template>
  <div class="app-container">
    <div class="filter-container">
      <!-- <el-input v-model="listQuery.name" placeholder="Server 名称" style="width: 200px;" class="filter-item" />
      <el-input v-model="listQuery.ip" placeholder="Server IP" style="width: 200px;" class="filter-item" />
      <el-button class="filter-item" type="primary" icon="el-icon-search" plain @click="fetchData()">查询</el-button> -->
      <el-button class="filter-item" type="primary" @click="handleCreate()">新建集群</el-button>
    </div>
    <el-table
      v-loading="listLoading"
      :data="list"
      element-loading-text="Loading"
      border
      fit
      highlight-current-row
    >
      <el-table-column label="集群名称" min-width="200" align="center">
        <template slot-scope="scope">
          {{ scope.row.name }}
        </template>
      </el-table-column>
      <el-table-column label="ZK地址" min-width="300" align="center">
        <template slot-scope="scope">
          <span>{{ scope.row.zkHosts }}</span>
        </template>
      </el-table-column>
      <el-table-column align="center" prop="created_at" label="操作" min-width="150">
        <template slot-scope="scope">
          <el-dropdown trigger="click">
            <el-button type="primary" size="mini">
              操作<i class="el-icon-arrow-down el-icon--right" />
            </el-button>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item @click.native="handleConfig(scope.row)">主配置</el-dropdown-item>
              <el-dropdown-item @click.native="handleUpdate(scope.row)">修改集群</el-dropdown-item>
              <el-dropdown-item @click.native="handleDelete(scope.row)">删除集群</el-dropdown-item>
              <el-dropdown-item @click.native="handleView(scope.row)">查看Server</el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
        </template>
      </el-table-column>
    </el-table>
    <el-dialog :visible.sync="dialogFormVisible" :title="textMap[dialogStatus]" width="600px">
      <el-form ref="dataForm" :rules="rules" :model="canalCluster" label-position="left" label-width="120px" style="width: 400px; margin-left:30px;">
        <el-form-item label="集群名称" prop="name">
          <el-input v-model="canalCluster.name" />
        </el-form-item>
        <el-form-item label="ZK地址" prop="zkHosts">
          <el-input v-model="canalCluster.zkHosts" />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取消</el-button>
        <el-button type="primary" @click="dataOperation()">确定</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { addCanalCluster, getCanalClusters, updateCanalCluster, deleteCanalCluster } from '@/api/canalCluster'

export default {
  filters: {
    statusFilter(status) {
      const statusMap = {
        '1': 'success',
        '0': 'gray',
        '-1': 'danger'
      }
      return statusMap[status]
    },
    statusLabel(status) {
      const statusMap = {
        '1': '启动',
        '0': '停止',
        '-1': '断开'
      }
      return statusMap[status]
    }
  },
  data() {
    return {
      list: null,
      listLoading: true,
      listQuery: {
        name: '',
        ip: ''
      },
      dialogFormVisible: false,
      textMap: {
        create: '新建集群信息',
        update: '修改集群信息'
      },
      canalCluster: {
        id: null,
        name: null,
        zkHosts: null
      },
      rules: {
        name: [{ required: true, message: '集群名称不能为空', trigger: 'change' }],
        zkHosts: [{ required: true, message: 'zk地址不能为空', trigger: 'change' }]
      },
      dialogStatus: 'create'
    }
  },
  created() {
    this.fetchData()
  },
  methods: {
    fetchData() {
      this.listLoading = true
      getCanalClusters(this.listQuery).then(res => {
        this.list = res.data
      }).finally(() => {
        this.listLoading = false
      })
    },
    resetModel() {
      this.canalCluster = {
        id: null,
        name: null,
        zkHosts: null
      }
    },
    handleCreate() {
      this.resetModel()
      this.dialogStatus = 'create'
      this.dialogFormVisible = true
      this.$nextTick(() => {
        this.$refs['dataForm'].clearValidate()
      })
    },
    dataOperation() {
      this.$refs['dataForm'].validate((valid) => {
        if (valid) {
          if (this.dialogStatus === 'create') {
            addCanalCluster(this.canalCluster).then(res => {
              this.operationRes(res)
            })
          }
          if (this.dialogStatus === 'update') {
            updateCanalCluster(this.canalCluster).then(res => {
              this.operationRes(res)
            })
          }
        }
      })
    },
    operationRes(res) {
      if (res.data === 'success') {
        this.fetchData()
        this.dialogFormVisible = false
        this.$message({
          message: this.textMap[this.dialogStatus] + '成功',
          type: 'success'
        })
      } else {
        this.$message({
          message: this.textMap[this.dialogStatus] + '失败',
          type: 'error'
        })
      }
    },
    handleView(row) {
      this.$router.push('/canalServer/nodeServers?clusterId=' + row.id)
    },
    handleConfig(row) {
      this.$router.push('/canalServer/nodeServer/config?clusterId=' + row.id)
    },
    handleUpdate(row) {
      this.resetModel()
      this.canalCluster = Object.assign({}, row)
      this.dialogStatus = 'update'
      this.dialogFormVisible = true
      this.$nextTick(() => {
        this.$refs['dataForm'].clearValidate()
      })
    },
    handleDelete(row) {
      this.$confirm('删除集群信息会导致服务停止', '确定删除集群信息', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        deleteCanalCluster(row.id).then((res) => {
          if (res.data === 'success') {
            this.fetchData()
            this.$message({
              message: '删除集群信息成功',
              type: 'success'
            })
          } else {
            this.$message({
              message: '删除集群信息失败',
              type: 'error'
            })
          }
        })
      })
    }
  }
}
</script>


================================================
FILE: admin/admin-ui/src/views/canalServer/CanalConfig.vue
================================================
<template>
  <div>
    <el-form ref="form" :model="form">
      <div style="padding-left: 10px;padding-top: 20px;">
        <el-form-item>
          {{ form.name }}&nbsp;&nbsp;&nbsp;&nbsp;
          <el-button type="primary" @click="onSubmit">保存</el-button>
          <el-button type="warning" @click="onCancel">重置</el-button>
          <el-button type="success" @click="onLoadTemplate">载入模板</el-button>
          <el-button type="info" @click="onBack">返回</el-button>
        </el-form-item>
      </div>
      <editor v-model="form.content" lang="properties" theme="chrome" width="100%" :height="800" @init="editorInit" />
    </el-form>
  </div>
</template>

<script>
import { getCanalConfig, updateCanalConfig, getTemplateConfig } from '@/api/canalConfig'

export default {
  components: {
    editor: require('vue2-ace-editor')
  },
  data() {
    return {
      form: {
        id: null,
        name: '',
        content: '',
        serverId: null,
        clusterId: null
      }
    }
  },
  created() {
    this.loadCanalConfig()
  },
  methods: {
    editorInit() {
      require('brace/ext/language_tools')
      require('brace/mode/html')
      require('brace/mode/yaml')
      require('brace/mode/properties')
      require('brace/mode/javascript')
      require('brace/mode/less')
      require('brace/theme/chrome')
      require('brace/snippets/javascript')
    },
    loadCanalConfig() {
      let clusterId = 0
      let serverId = 0
      if (this.$route.query.clusterId) {
        clusterId = this.$route.query.clusterId
      } else if (this.$route.query.serverId) {
        serverId = this.$route.query.serverId
      }
      getCanalConfig(clusterId, serverId).then(response => {
        const data = response.data
        this.form.id = data.id
        this.form.name = data.name
        this.form.content = data.content
        this.form.serverId = this.$route.query.serverId
        this.form.clusterId = this.$route.query.clusterId
      })
    },
    onSubmit() {
      if (this.form.content === null || this.form.content === '') {
        this.$message({
          message: '配置内容不能为空',
          type: 'error'
        })
        return
      }
      this.$confirm(
        '修改主配置可能会导致Server重启,是否继续?',
        '确定修改',
        {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }
      ).then(() => {
        updateCanalConfig(this.form).then(response => {
          if (response.data === 'success') {
            this.$message({
              message: '保存成功',
              type: 'success'
            })
            this.loadCanalConfig()
          } else {
            this.$message({
              message: '保存失败',
              type: 'error'
            })
          }
        })
      })
    },
    onCancel() {
      this.loadCanalConfig()
    },
    onBack() {
      history.go(-1)
    },
    onLoadTemplate() {
      getTemplateConfig().then(res => {
        this.form.content = res.data
      })
    }
  }
}
</script>

<style scoped>
.line{
  text-align: center;
}
</style>



================================================
FILE: admin/admin-ui/src/views/canalServer/CanalInstance.vue
================================================
<template>
  <div class="app-container">
    <div class="filter-container">
      <el-input v-model="listQuery.name" placeholder="Instance 名称" style="width: 200px;" class="filter-item" />
      <el-select v-model="listQuery.clusterServerId" placeholder="所属集群/主机" class="filter-item">
        <el-option key="" label="所属集群/主机" value="" />
        <el-option-group v-for="group in options" :key="group.label" :label="group.label">
          <el-option v-for="item in group.options" :key="item.value" :label="item.label" :value="item.value" />
        </el-option-group>
      </el-select>
      <el-button class="filter-item" type="primary" icon="el-icon-search" plain @click="queryData()">查询</el-button>
      &nbsp;&nbsp;
      <el-button class="filter-item" type="primary" @click="handleCreate()">新建 Instance</el-button>
      <el-button class="filter-item" type="info" @click="fetchData()">刷新列表</el-button>
    </div>
    <el-table
      v-loading="listLoading"
      :data="list"
      element-loading-text="Loading"
      border
      fit
      highlight-current-row
    >
      <el-table-column label="Instance 名称" min-width="200" align="center">
        <template slot-scope="scope">
          {{ scope.row.name }}
        </template>
      </el-table-column>
      <el-table-column label="所属集群" min-width="200" align="center">
        <template slot-scope="scope">
          <span v-if="scope.row.canalCluster !== null">
            {{ scope.row.canalCluster.name }}
          </span>
          <span v-else>-</span>
        </template>
      </el-table-column>
      <el-table-column label="所属主机" min-width="200" align="center">
        <template slot-scope="scope">
          <span v-if="scope.row.nodeServer !== null">
            {{ scope.row.nodeServer.name }}
          </span>
          <span v-else>-</span>
        </template>
      </el-table-column>
      <el-table-column class-name="status-col" label="状态" min-width="150" align="center">
        <template slot-scope="scope">
          <el-tag :type="scope.row.runningStatus | statusFilter">{{ scope.row.runningStatus | statusLabel }}</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="修改时间" min-width="200" align="center">
        <template slot-scope="scope">
          {{ scope.row.modifiedTime }}
        </template>
      </el-table-column>
      <el-table-column align="center" prop="created_at" label="操作" min-width="150">
        <template slot-scope="scope">
          <el-dropdown trigger="click">
            <el-button type="primary" size="mini">
              操作<i class="el-icon-arrow-down el-icon--right" />
            </el-button>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item @click.native="handleUpdate(scope.row)">修改</el-dropdown-item>
              <el-dropdown-item @click.native="handleDelete(scope.row)">删除</el-dropdown-item>
              <el-dropdown-item @click.native="handleStart(scope.row)">启动</el-dropdown-item>
              <el-dropdown-item @click.native="handleStop(scope.row)">停止</el-dropdown-item>
              <el-dropdown-item @click.native="handleLog(scope.row)">日志</el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
        </template>
      </el-table-column>
    </el-table>
    <pagination v-show="count>0" :total="count" :page.sync="listQuery.page" :limit.sync="listQuery.size" @pagination="fetchData()" />
  </div>
</template>

<script>
import { getCanalInstances, deleteCanalInstance, instanceStatus } from '@/api/canalInstance'
import Pagination from '@/components/Pagination'
import { getClustersAndServers } from '@/api/canalCluster'

export default {
  components: { Pagination },
  filters: {
    statusFilter(status) {
      const statusMap = {
        '1': 'success',
        '0': 'gray'
      }
      return statusMap[status]
    },
    statusLabel(status) {
      const statusMap = {
        '1': '启动',
        '0': '停止'
      }
      return statusMap[status]
    }
  },
  data() {
    return {
      list: null,
      listLoading: true,
      dialogFormVisible: false,
      nodeServices: [],
      count: 0,
      options: [],
      listQuery: {
        name: '',
        clusterServerId: '',
        page: 1,
        size: 20
      },
      currentId: null,
      rules: {
        id: [{ required: true, message: '请选择运行Server', trigger: 'change' }]
      }
    }
  },
  created() {
    getClustersAndServers().then((res) => {
      this.options = res.data
    })
    this.fetchData()
  },
  methods: {
    queryData() {
      this.listQuery.page = 1
      this.fetchData()
    },
    fetchData() {
      this.listLoading = true
      getCanalInstances(this.listQuery).then(res => {
        this.list = res.data.items
        this.count = res.data.count
      }).finally(() => {
        this.listLoading = false
      })
    },
    handleCreate() {
      this.$router.push('/canalServer/canalInstance/add')
    },
    handleUpdate(row) {
      this.$router.push('/canalServer/canalInstance/modify?id=' + row.id)
    },
    handleDelete(row) {
      this.$confirm('删除Instance配置会导致停止', '确定删除Instance信息', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        deleteCanalInstance(row.id).then((res) => {
          if (res.data === 'success') {
            this.fetchData()
            this.$message({
              message: '删除Instance信息成功',
              type: 'success'
            })
          } else {
            this.$message({
              message: '删除Instance信息失败',
              type: 'error'
            })
          }
        })
      })
    },
    handleStart(row) {
      // if (row.runningStatus === '1') {
      //   this.$message({ message: '当前Instance已处于启动状态!', type: 'error' })
      //   return
      // }
      this.$confirm('启动Instance: ' + row.name, '确定启动Instance服务', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        instanceStatus(row.id, 'start').then((res) => {
          if (res.data) {
            this.fetchData()
            this.$message({
              message: '启动成功, 稍后请刷新列表查看状态',
              type: 'success'
            })
          } else {
            this.$message({
              message: '启动Instance出现异常',
              type: 'error'
            })
          }
        })
      })
    },
    handleStop(row) {
      // if (row.runningStatus === '0') {
      //   this.$message({ message: '当前Instance已处于停止状态!', type: 'error' })
      //   return
      // }
      this.$confirm('停止Instance: ' + row.name, '确定停止Instance服务', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        instanceStatus(row.id, 'stop').then((res) => {
          if (res.data) {
            this.fetchData()
            this.$message({
              message: '停止成功, 稍后请刷新列表查看状态',
              type: 'success'
            })
          } else {
            this.$message({
              message: '停止Instance出现异常',
              type: 'error'
            })
          }
        })
      })
    },
    handleLog(row) {
      if (row.nodeId === null) {
        this.$message({ message: '当前Instance不是启动状态,无法查看日志', type: 'warning' })
        return
      }
      this.$router.push('canalInstance/log?id=' + row.id + '&nodeId=' + row.nodeServer.id)
    }
  }
}
</script>


================================================
FILE: admin/admin-ui/src/views/canalServer/CanalInstanceAdd.vue
================================================
<template>
  <div>
    <el-form ref="form" :model="form">
      <div class="filter-container" style="padding-left: 10px;padding-top: 20px;">
        <el-input v-model="form.name" placeholder="Instance名称" style="width: 200px;" class="filter-item" />
        <el-select v-model="form.clusterServerId" placeholder="所属集群/主机" class="filter-item">
          <el-option-group v-for="group in options" :key="group.label" :label="group.label">
            <el-option v-for="item in group.options" :key="item.value" :label="item.label" :value="item.value" />
          </el-option-group>
        </el-select>
        <el-button class="filter-item" type="primary" @click="onSubmit">保存</el-button>
        <el-button class="filter-item" type="success" @click="onLoadTemplate">载入模板</el-button>
        <el-button class="filter-item" type="info" @click="onBack">返回</el-button>
      </div>
      <editor v-model="form.content" lang="properties" theme="chrome" width="100%" :height="800" @init="editorInit" />
    </el-form>
  </div>
</template>

<script>
import { addCanalInstance, getTemplateInstance } from '@/api/canalInstance'
import { getClustersAndServers } from '@/api/canalCluster'

export default {
  components: {
    editor: require('vue2-ace-editor')
  },
  data() {
    return {
      options: [],
      form: {
        name: '',
        content: '',
        clusterServerId: ''
      }
    }
  },
  created() {
    getClustersAndServers().then((res) => {
      this.options = res.data
    })
  },
  methods: {
    editorInit() {
      require('brace/ext/language_tools')
      require('brace/mode/html')
      require('brace/mode/yaml')
      require('brace/mode/properties')
      require('brace/mode/javascript')
      require('brace/mode/less')
      require('brace/theme/chrome')
      require('brace/snippets/javascript')
    },
    onSubmit() {
      if (this.form.name === '') {
        this.$message({
          message: '请输入Instance名称',
          type: 'error'
        })
        return
      }
      if (this.form.clusterServerId === '') {
        this.$message({
          message: '请选择所属集群/主机',
          type: 'error'
        })
        return
      }
      if (this.form.content === null || this.form.content === '') {
        this.$message({
          message: '请输入配置内容',
          type: 'error'
        })
        return
      }
      this.$confirm(
        '确定新建',
        '确定新建',
        {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }
      ).then(() => {
        addCanalInstance(this.form).then(response => {
          if (response.data === 'success') {
            this.$message({
              message: '新建成功',
              type: 'success'
            })
            this.$router.push('/canalServer/canalInstances')
          } else {
            this.$message({
              message: '新建失败',
              type: 'error'
            })
          }
        })
      })
    },
    onBack() {
      history.go(-1)
    },
    onLoadTemplate() {
      getTemplateInstance().then(res => {
        this.form.content = res.data
      })
    }
  }
}
</script>

<style scoped>
.line{
  text-align: center;
}
</style>



================================================
FILE: admin/admin-ui/src/views/canalServer/CanalInstanceLogDetail.vue
================================================
<template>
  <div>
    <el-form ref="form" :model="form">
      <div style="padding-left: 10px;padding-right: 10px;padding-top: 20px;">
        <el-form-item>
          {{ form.instance }}&nbsp;&nbsp;&nbsp;&nbsp;
          <el-button type="primary" @click="onRefresh">刷新</el-button>
          <el-button type="info" @click="onBack">返回</el-button>
        </el-form-item>
        <el-input v-model="form.desc" :rows="35" :readonly="'readonly'" type="textarea" />
      </div>
    </el-form>
  </div>
</template>

<script>
import { instanceLog } from '@/api/canalInstance'

export default {
  data() {
    return {
      form: {
        instance: '',
        desc: ''
      }
    }
  },
  created() {
    this.fetchData()
  },
  methods: {
    fetchData() {
      instanceLog(this.$route.query.id, this.$route.query.nodeId).then(res => {
        this.form.instance = res.data.instance + '.log'
        this.form.desc = res.data.log
      })
    },
    onRefresh() {
      this.fetchData()
    },
    onBack() {
      history.go(-1)
    }
  }
}
</script>

<style scoped>
.line{
  text-align: center;
}
</style>



================================================
FILE: admin/admin-ui/src/views/canalServer/CanalInstanceUpdate.vue
================================================
<template>
  <div>
    <el-form ref="form" :model="form">
      <div style="padding-left: 10px;padding-top: 20px;">
        <el-form-item>
          {{ form.name }}&nbsp;&nbsp;&nbsp;&nbsp;
          <el-select v-model="form.clusterServerId" placeholder="所属集群/主机" class="filter-item">
            <el-option-group v-for="group in options" :key="group.label" :label="group.label">
              <el-option v-for="item in group.options" :key="item.value" :label="item.label" :value="item.value" />
            </el-option-group>
          </el-select>
          <el-button type="primary" @click="onSubmit">修改</el-button>
          <el-button type="warning" @click="onCancel">重置</el-button>
          <el-button type="info" @click="onBack">返回</el-button>
        </el-form-item>
      </div>
      <editor v-model="form.content" lang="properties" theme="chrome" width="100%" :height="800" @init="editorInit" />
    </el-form>
  </div>
</template>

<script>
import { canalInstanceDetail, updateCanalInstance } from '@/api/canalInstance'
import { getClustersAndServers } from '@/api/canalCluster'

export default {
  components: {
    editor: require('vue2-ace-editor')
  },
  data() {
    return {
      options: [],
      form: {
        id: null,
        name: '',
        content: '',
        clusterServerId: ''
      }
    }
  },
  created() {
    this.loadCanalConfig()
    getClustersAndServers().then((res) => {
      this.options = res.data
    })
  },
  methods: {
    editorInit() {
      require('brace/ext/language_tools')
      require('brace/mode/html')
      require('brace/mode/yaml')
      require('brace/mode/properties')
      require('brace/mode/javascript')
      require('brace/mode/less')
      require('brace/theme/chrome')
      require('brace/snippets/javascript')
    },
    loadCanalConfig() {
      canalInstanceDetail(this.$route.query.id).then(response => {
        const data = response.data
        this.form.id = data.id
        this.form.name = data.name + '/instance.properties'
        this.form.content = data.content
        this.form.clusterServerId = data.clusterServerId
      })
    },
    onSubmit() {
      this.$confirm(
        '修改Instance配置可能会导致重启,是否继续?',
        '确定修改',
        {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }
      ).then(() => {
        updateCanalInstance(this.form).then(response => {
          if (response.data === 'success') {
            this.$message({
              message: '修改成功',
              type: 'success'
            })
            this.loadCanalConfig()
          } else {
            this.$message({
              message: '修改失败',
              type: 'error'
            })
          }
        })
      })
    },
    onCancel() {
      this.loadCanalConfig()
    },
    onBack() {
      history.go(-1)
    }
  }
}
</script>

<style scoped>
.line{
  text-align: center;
}
</style>



================================================
FILE: admin/admin-ui/src/views/canalServer/CanalLogDetail.vue
================================================
<template>
  <div>
    <el-form ref="form" :model="form">
      <div style="padding-left: 10px;padding-right: 10px;padding-top: 20px;">
        <el-form-item>
          canal.log&nbsp;&nbsp;&nbsp;&nbsp;
          <el-button type="primary" @click="onRefresh">刷新</el-button>
          <el-button type="info" @click="onBack">返回</el-button>
        </el-form-item>
        <el-input v-model="form.desc" :rows="35" :readonly="'readonly'" type="textarea" />
      </div>
    </el-form>
  </div>
</template>

<script>
import { nodeServerLog } from '@/api/nodeServer'

export default {
  data() {
    return {
      form: {
        desc: ''
      }
    }
  },
  created() {
    this.fetchData()
  },
  methods: {
    fetchData() {
      nodeServerLog(this.$route.query.id).then(res => {
        this.form.desc = res.data
      })
    },
    onRefresh() {
      this.fetchData()
    },
    onBack() {
      history.go(-1)
    }
  }
}
</script>

<style scoped>
.line{
  text-align: center;
}
</style>



================================================
FILE: admin/admin-ui/src/views/canalServer/NodeServer.vue
================================================
<template>
  <div class="app-container">
    <div class="filter-container">
      <!--<el-input v-model="listQuery.name" placeholder="Server 名称" style="width: 200px;" class="filter-item" />-->
      <el-select v-model="listQuery.clusterId" placeholder="所属集群" class="filter-item">
        <el-option key="" label="所属集群" value="" />
        <el-option key="-1" label="单机" value="-1" />
        <el-option v-for="item in canalClusters" :key="item.id" :label="item.name" :value="item.id" />
      </el-select>
      <el-input v-model="listQuery.ip" placeholder="Server IP" style="width: 200px;" class="filter-item" />
      <el-button class="filter-item" type="primary" icon="el-icon-search" plain @click="queryData()">查询</el-button>
      <el-button class="filter-item" type="primary" @click="handleCreate()">新建Server</el-button>
      <el-button class="filter-item" type="info" @click="fetchData()">刷新列表</el-button>
    </div>
    <el-table
      v-loading="listLoading"
      :data="list"
      element-loading-text="Loading"
      border
      fit
      highlight-current-row
    >
      <el-table-column label="所属集群" min-width="200" align="center">
        <template slot-scope="scope">
          <span v-if="scope.row.canalCluster !== null">
            {{ scope.row.canalCluster.name }}
          </span>
          <span v-else>
            -
          </span>
        </template>
      </el-table-column>
      <el-table-column label="Server 名称" min-width="200" align="center">
        <template slot-scope="scope">
          {{ scope.row.name }}
        </template>
      </el-table-column>
      <el-table-column label="Server IP" min-width="200" align="center">
        <template slot-scope="scope">
          <span>{{ scope.row.ip }}</span>
        </template>
      </el-table-column>
      <el-table-column label="admin 端口" min-width="100" align="center">
        <template slot-scope="scope">
          {{ scope.row.adminPort }}
        </template>
      </el-table-column>
      <el-table-column label="tcp 端口" min-width="100" align="center">
        <template slot-scope="scope">
          {{ scope.row.tcpPort }}
        </template>
      </el-table-column>
      <el-table-column label="metric 端口" min-width="100" align="center">
        <template slot-scope="scope">
          {{ scope.row.metricPort }}
        </template>
      </el-table-column>
      <el-table-column class-name="status-col" label="状态" min-width="150" align="center">
        <template slot-scope="scope">
          <el-tag :type="scope.row.status | statusFilter">{{ scope.row.status | statusLabel }}</el-tag>
        </template>
      </el-table-column>
      <el-table-column align="center" prop="created_at" label="操作" min-width="150">
        <template slot-scope="scope">
          <el-dropdown trigger="click">
            <el-button type="primary" size="mini">
              操作<i class="el-icon-arrow-down el-icon--right" />
            </el-button>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item @click.native="handleConfig(scope.row)">配置</el-dropdown-item>
              <el-dropdown-item @click.native="handleUpdate(scope.row)">修改</el-dropdown-item>
              <el-dropdown-item @click.native="handleDelete(scope.row)">删除</el-dropdown-item>
              <el-dropdown-item @click.native="handleStart(scope.row)">启动</el-dropdown-item>
              <el-dropdown-item @click.native="handleStop(scope.row)">停止</el-dropdown-item>
              <el-dropdown-item @click.native="handleInstances(scope.row)">详情</el-dropdown-item>
              <el-dropdown-item @click.native="handleLog(scope.row)">日志</el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
        </template>
      </el-table-column>
    </el-table>
    <pagination v-show="count>0" :total="count" :page.sync="listQuery.page" :limit.sync="listQuery.size" @pagination="fetchData()" />
    <el-dialog :visible.sync="dialogFormVisible" :title="textMap[dialogStatus]" width="600px">
      <el-form ref="dataForm" :rules="rules" :model="nodeModel" label-position="left" label-width="120px" style="width: 400px; margin-left:30px;">
        <el-form-item label="所属集群" prop="clusterId">
          <el-select v-if="dialogStatus === 'create'" v-model="nodeModel.clusterId" placeholder="选择所属集群">
            <el-option key="" label="单机" value="" />
            <el-option v-for="item in canalClusters" :key="item.id" :label="item.name" :value="item.id" />
          </el-select>
          <el-select v-else v-model="nodeModel.clusterId" placeholder="选择所属集群" disabled="disabled">
            <el-option key="" label="单机" value="" />
            <el-option v-for="item in canalClusters" :key="item.id" :label="item.name" :value="item.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="Server 名称" prop="name">
          <el-input v-model="nodeModel.name" />
        </el-form-item>
        <el-form-item label="Server IP" prop="ip">
          <el-input v-model="nodeModel.ip" />
        </el-form-item>
        <el-form-item label="admin 端口" prop="adminPort">
          <el-input v-model="nodeModel.adminPort" placeholder="11110" type="number" />
        </el-form-item>
        <el-form-item label="tcp 端口" prop="tcpPort">
          <el-input v-model="nodeModel.tcpPort" placeholder="11111" type="number" />
        </el-form-item>
        <el-form-item label="metric 端口" prop="metricPort">
          <el-input v-model="nodeModel.metricPort" placeholder="11112" type="number" />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取消</el-button>
        <el-button type="primary" @click="dataOperation()">确定</el-button>
      </div>
    </el-dialog>
    <el-dialog :visible.sync="dialogInstances" title="instance 列表" width="800px">
      <div class="filter-container">
        <el-button class="filter-item" type="info" @click="activeInstances()">刷新列表</el-button>
      </div>
      <el-table
        v-loading="listLoading2"
        :data="instanceList"
        element-loading-text="Loading"
        border
        fit
        highlight-current-row
      >
        <el-table-column label="Instance 名称" min-width="200" align="center">
          <template slot-scope="scope">
            {{ scope.row.name }}
          </template>
        </el-table-column>
        <el-table-column label="状态" min-width="200" align="center">
          <template slot-scope="scope">
            <el-tag :type="scope.row.runningStatus | statusFilter">{{ scope.row.runningStatus | statusLabel }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="操作" min-width="200" align="center">
          <template slot-scope="scope">
            <el-dropdown trigger="click">
              <el-button type="primary" size="mini">
                操作<i class="el-icon-arrow-down el-icon--right" />
              </el-button>
              <el-dropdown-menu slot="dropdown">
                <el-dropdown-item @click.native="handleStartInstance(scope.row)">启动</el-dropdown-item>
                <el-dropdown-item @click.native="handleStopInstance(scope.row)">停止</el-dropdown-item>
              </el-dropdown-menu>
            </el-dropdown>
          </template>
        </el-table-column>
      </el-table>
    </el-dialog>
  </div>
</template>

<script>
import { addNodeServer, getNodeServers, updateNodeServer, deleteNodeServer, startNodeServer, stopNodeServer } from '@/api/nodeServer'
import { getActiveInstances, stopInstance, startInstance } from '@/api/canalInstance'
import { getCanalClusters } from '@/api/canalCluster'
import Pagination from '@/components/Pagination'

export default {
  components: { Pagination },
  filters: {
    statusFilter(status) {
      const statusMap = {
        '1': 'success',
        '0': 'gray',
        '-1': 'danger'
      }
      return statusMap[status]
    },
    statusLabel(status) {
      const statusMap = {
        '1': '启动',
        '0': '停止',
        '-1': '断开'
      }
      return statusMap[status]
    }
  },
  data() {
    return {
      list: null,
      instanceList: null,
      listLoading: true,
      listLoading2: true,
      serverIdTmp: null,
      canalClusters: [],
      count: 0,
      listQuery: {
        name: '',
        ip: '',
        clusterId: null,
        page: 1,
        size: 20
      },
      dialogFormVisible: false,
      dialogInstances: false,
      textMap: {
        create: '新建Server信息',
        update: '修改Server信息'
      },
      nodeModel: {
        id: undefined,
        clusterId: null,
        name: null,
        ip: null,
        adminPort: 11110,
        tcpPort: 11111,
        metricPort: 11112
      },
      rules: {
        name: [{ required: true, message: 'Server 名称不能为空', trigger: 'change' }],
        ip: [{ required: true, message: 'Server IP不能为空', trigger: 'change' }],
        adminPort: [{ required: true, message: 'Server admin端口不能为空', trigger: 'change' }]
      },
      dialogStatus: 'create'
    }
  },
  // { min: 2, max: 5, message: '长度在 2 到 5 个字符', trigger: 'change' }
  created() {
    getCanalClusters().then((res) => {
      this.canalClusters = res.data
    })
    if (this.$route.query.clusterId) {
      try {
        this.listQuery.clusterId = Number(this.$route.query.clusterId)
      } catch (e) {
        console.log(e)
      }
    }
    this.fetchData()
  },
  methods: {
    fetchData() {
      this.listLoading = true
      getNodeServers(this.listQuery).then(res => {
        this.list = res.data.items
        this.count = res.data.count
      }).finally(() => {
        this.listLoading = false
      })
    },
    queryData() {
      this.listQuery.page = 1
      this.fetchData()
    },
    resetModel() {
      this.nodeModel = {
        id: undefined,
        clusterId: null,
        name: null,
        ip: null,
        adminPort: null,
        tcpPort: null,
        metricPort: null
      }
    },
    handleCreate() {
      this.resetModel()
      this.dialogStatus = 'create'
      this.dialogFormVisible = true
      this.$nextTick(() => {
        this.$refs['dataForm'].clearValidate()
      })
    },
    handleInstances(row) {
      this.serverIdTmp = row.id
      this.activeInstances()
    },
    activeInstances() {
      this.listLoading2 = true
      this.dialogInstances = true
      getActiveInstances(this.serverIdTmp).then(res => {
        this.instanceList = res.data
      }).finally(() => {
        this.listLoading2 = false
      })
    },
    dataOperation() {
      this.$refs['dataForm'].validate((valid) => {
        if (valid) {
          if (this.dialogStatus === 'create') {
            addNodeServer(this.nodeModel).then(res => {
              this.operationRes(res)
            })
          }
          if (this.dialogStatus === 'update') {
            updateNodeServer(this.nodeModel).then(res => {
              this.operationRes(res)
            })
          }
        }
      })
    },
    operationRes(res) {
      if (res.data === 'success') {
        this.fetchData()
        this.dialogFormVisible = false
        this.$message({
          message: this.textMap[this.dialogStatus] + '成功',
          type: 'success'
        })
      } else {
        this.$message({
          message: this.textMap[this.dialogStatus] + '失败',
          type: 'error'
        })
      }
    },
    handleConfig(row) {
      if (row.canalCluster !== null) {
        this.$message({ message: '集群模式Server不允许单独变更配置,请在集群配置变更', type: 'error' })
        return
      }
      this.$router.push('/canalServer/nodeServer/config?serverId=' + row.id)
    },
    handleUpdate(row) {
      this.resetModel()
      this.nodeModel = Object.assign({}, row)
      this.dialogStatus = 'update'
      this.dialogFormVisible = true
      this.$nextTick(() => {
        this.$refs['dataForm'].clearValidate()
      })
    },
    handleDelete(row) {
      this.$confirm('删除Server信息会导致节点服务停止', '确定删除Server信息', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        deleteNodeServer(row.id).then((res) => {
          if (res.data === 'success') {
            this.fetchData()
            this.$message({
              message: '删除Server信息成功',
              type: 'success'
            })
          } else {
            this.$message({
              message: '删除Server信息失败',
              type: 'error'
            })
          }
        })
      })
    },
    handleStart(row) {
      if (row.status !== '0') {
        this.$message({ message: '当前Server不是停止状态,无法启动', type: 'error' })
        return
      }
      this.$confirm('启动Server服务', '确定启动Server服务', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        startNodeServer(row.id).then((res) => {
          if (res.data) {
            this.fetchData()
            this.$message({
              message: '启动成功',
              type: 'success'
            })
          } else {
            this.$message({
              message: '启动Server服务出现异常',
              type: 'error'
            })
          }
        })
      })
    },
    handleStop(row) {
      if (row.status !== '1') {
        this.$message({ message: '当前Server不是启动状态,无法停止', type: 'error' })
        return
      }
      this.$confirm('停止Server服务会导致所有Instance都停止服务', '确定停止Server服务', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        stopNodeServer(row.id).then((res) => {
          if (res.data) {
            this.fetchData()
            this.$message({
              message: '停止成功',
              type: 'success'
            })
          } else {
            this.$message({
              message: '停止Server服务出现异常',
              type: 'error'
            })
          }
        })
      })
    },
    handleLog(row) {
      this.$router.push('nodeServer/log?id=' + row.id)
    },
    handleStartInstance(row) {
      if (row.runningStatus !== '0') {
        this.$message({ message: '当前Instance不是停止状态,无法启动', type: 'error' })
        return
      }
      this.$confirm('启动Instance服务', '确定启动Instance服务', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        startInstance(row.id, this.serverIdTmp).then((res) => {
          if (res.data) {
            this.activeInstances()
            this.$message({
              message: '启动成功, 稍后请刷新列表查看状态',
              type: 'success'
            })
          } else {
            this.$message({
              message: '启动Instance服务出现异常',
              type: 'error'
            })
          }
        })
      })
    },
    handleStopInstance(row) {
      if (row.runningStatus !== '1') {
        this.$message({ message: '当前Instance不是运行状态,无法停止', type: 'error' })
        return
      }
      this.$confirm('集群模式下停止实例其它主机将会抢占执行该实例', '停止 Instance 服务', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        stopInstance(row.id, this.serverIdTmp).then((res) => {
          if (res.data) {
            this.activeInstances()
            this.$message({
              message: '停止成功, 稍后请刷新列表查看状态',
              type: 'success'
            })
          } else {
            this.$message({
              message: '停止Instance服务出现异常',
              type: 'error'
            })
          }
        })
      })
    }
  }
}
</script>


================================================
FILE: admin/admin-ui/src/views/dashboard/index.vue
================================================
<template>
  <div class="dashboard-container">
    <div class="dashboard-text">&nbsp;</div>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
  name: 'Dashboard',
  computed: {
    ...mapGetters([
      'name'
    ])
  },
  mounted() {
    this.$router.push('/canalServer')
  }
}
</script>

<style lang="scss" scoped>
.dashboard {
  &-container {
    margin: 30px;
  }
  &-text {
    font-size: 30px;
    line-height: 46px;
  }
}
</style>


================================================
FILE: admin/admin-ui/src/views/login/index.vue
================================================
<template>
  <div class="login-container">
    <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" auto-complete="on" label-position="left">

      <div class="title-container">
        <h3 class="title">Canal Admin Login</h3>
      </div>

      <el-form-item prop="username">
        <span class="svg-container">
          <svg-icon icon-class="user" />
        </span>
        <el-input
          ref="username"
          v-model="loginForm.username"
          placeholder="Username"
          name="username"
          type="text"
          tabindex="1"
          auto-complete="on"
        />
      </el-form-item>

      <el-form-item prop="password">
        <span class="svg-container">
          <svg-icon icon-class="password" />
        </span>
        <el-input
          :key="passwordType"
          ref="password"
          v-model="loginForm.password"
          :type="passwordType"
          placeholder="Password"
          name="password"
          tabindex="2"
          auto-complete="on"
          @keyup.enter.native="handleLogin"
        />
        <span class="show-pwd" @click="showPwd">
          <svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
        </span>
      </el-form-item>

      <el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">Login</el-button>

      <div class="tips">
        <!-- <span style="margin-right:20px;">username: admin</span>
        <span> password: any</span> -->
      </div>

    </el-form>
  </div>
</template>

<script>
import { validUsername } from '@/utils/validate'

export default {
  name: 'Login',
  data() {
    const validateUsername = (rule, value, callback) => {
      if (!validUsername(value)) {
        callback(new Error('Please enter the correct user name'))
      } else {
        callback()
      }
    }
    const validatePassword = (rule, value, callback) => {
      if (value.length < 5) {
        callback(new Error('The password can not be less than 5 digits'))
      } else {
        callback()
      }
    }
    return {
      loginForm: {
        username: '',
        password: ''
      },
      loginRules: {
        username: [{ required: true, trigger: 'blur', validator: validateUsername }],
        password: [{ required: true, trigger: 'blur', validator: validatePassword }]
      },
      loading: false,
      passwordType: 'password',
      redirect: undefined
    }
  },
  watch: {
    $route: {
      handler: function(route) {
        this.redirect = route.query && route.query.redirect
      },
      immediate: true
    }
  },
  methods: {
    showPwd() {
      if (this.passwordType === 'password') {
        this.passwordType = ''
      } else {
        this.passwordType = 'password'
      }
      this.$nextTick(() => {
        this.$refs.password.focus()
      })
    },
    handleLogin() {
      this.$refs.loginForm.validate(valid => {
        if (valid) {
          this.loading = true
          this.$store.dispatch('user/login', this.loginForm).then(() => {
            this.$router.push({ path: this.redirect || '/' })
            this.loading = false
          }).catch(() => {
            this.loading = false
          })
        } else {
          console.log('error submit!!')
          return false
        }
      })
    }
  }
}
</script>

<style lang="scss">
/* 修复input 背景不协调 和光标变色 */
/* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */

$bg:#283443;
$light_gray:#fff;
$cursor: #fff;

@supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
  .login-container .el-input input {
    color: $cursor;
  }
}

/* reset element-ui css */
.login-container {
  .el-input {
    display: inline-block;
    height: 47px;
    width: 85%;

    input {
      background: transparent;
      border: 0px;
      -webkit-appearance: none;
      border-radius: 0px;
      padding: 12px 5px 12px 15px;
      color: $light_gray;
      height: 47px;
      caret-color: $cursor;

      &:-webkit-autofill {
        box-shadow: 0 0 0px 1000px $bg inset !important;
        -webkit-text-fill-color: $cursor !important;
      }
    }
  }

  .el-form-item {
    border: 1px solid rgba(255, 255, 255, 0.1);
    background: rgba(0, 0, 0, 0.1);
    border-radius: 5px;
    color: #454545;
  }
}
</style>

<style lang="scss" scoped>
$bg:#2d3a4b;
$dark_gray:#889aa4;
$light_gray:#eee;

.login-container {
  min-height: 100%;
  width: 100%;
  background-color: $bg;
  overflow: hidden;

  .login-form {
    position: relative;
    width: 520px;
    max-width: 100%;
    padding: 160px 35px 0;
    margin: 0 auto;
    overflow: hidden;
  }

  .tips {
    font-size: 14px;
    color: #fff;
    margin-bottom: 10px;

    span {
      &:first-of-type {
        margin-right: 16px;
      }
    }
  }

  .svg-container {
    padding: 6px 5px 6px 15px;
    color: $dark_gray;
    vertical-align: middle;
    width: 30px;
    display: inline-block;
  }

  .title-container {
    position: relative;

    .title {
      font-size: 26px;
      color: $light_gray;
      margin: 0px auto 40px auto;
      text-align: center;
      font-weight: bold;
    }
  }

  .show-pwd {
    position: absolute;
    right: 10px;
    top: 7px;
    font-size: 16px;
    color: $dark_gray;
    cursor: pointer;
    user-select: none;
  }
}
</style>


================================================
FILE: admin/admin-ui/src/views/sys/UserInfo.vue
================================================
<template>
  <div class="app-container" style="width: 600px;">
    <el-form ref="form" :rules="rules" :model="form" label-width="120px">
      <el-form-item label="用户名" prop="username">
        <el-input v-model="form.username" style="width: 200px;" />
      </el-form-item>
      <el-form-item label="旧密码" prop="oldPassword">
        <el-input v-model="form.oldPassword" type="password" style="width: 200px;" />
      </el-form-item>
      <el-form-item label="密码" prop="password">
        <el-input v-model="form.password" placeholder="空为不修改密码" type="password" style="width: 200px;" />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="onSubmit">修改</el-button>
        <el-button @click="onCancel">取消</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
import { getInfo, updateUser } from '@/api/user'
import { getToken } from '@/utils/auth'

export default {
  data() {
    return {
      form: {
        username: '',
        oldPassword: '',
        password: null
      },
      rules: {
        username: [{ required: true, message: '用户名能为空', trigger: 'change' }],
        oldPassword: [{ required: true, message: '旧密码不能为空', trigger: 'change' }]
      }
    }
  },
  created() {
    this.fetchUserInfo()
  },
  methods: {
    fetchUserInfo() {
      getInfo(getToken()).then(res => {
        this.form.username = res.data.username
      })
    },
    onSubmit() {
      this.$refs['form'].validate((valid) => {
        if (valid) {
          updateUser(this.form).then(res => {
            if (res.data === 'success') {
              this.form.oldPassword = ''
              this.form.password = null
              this.$nextTick(() => {
                this.$refs['form'].clearValidate()
              })
              this.$message({
                message: '修改用户信息成功',
                type: 'success'
              })
            } else {
              this.$message({
                message: '修改用户信息成功',
                type: 'error'
              })
            }
          })
        }
      })
    },
    onCancel() {
      history.go(-1)
    }
  }
}
</script>

<style scoped>
.line{
  text-align: center;
}
</style>



================================================
FILE: admin/admin-ui/tests/unit/.eslintrc.js
================================================
module.exports = {
  env: {
    jest: true
  }
}


================================================
FILE: admin/admin-ui/tests/unit/components/Breadcrumb.spec.js
================================================
import { mount, createLocalVue } from '@vue/test-utils'
import VueRouter from 'vue-router'
import ElementUI from 'element-ui'
import Breadcrumb from '@/components/Breadcrumb/index.vue'

const localVue = createLocalVue()
localVue.use(VueRouter)
localVue.use(ElementUI)

const routes = [
  {
    path: '/',
    name: 'home',
    children: [{
      path: 'dashboard',
      name: 'dashboard'
    }]
  },
  {
    path: '/menu',
    name: 'menu',
    children: [{
      path: 'menu1',
      name: 'menu1',
      meta: { title: 'menu1' },
      children: [{
        path: 'menu1-1',
        name: 'menu1-1',
        meta: { title: 'menu1-1' }
      },
      {
        path: 'menu1-2',
        name: 'menu1-2',
        redirect: 'noredirect',
        meta: { title: 'menu1-2' },
        children: [{
          path: 'menu1-2-1',
          name: 'menu1-2-1',
          meta: { title: 'menu1-2-1' }
        },
        {
          path: 'menu1-2-2',
          name: 'menu1-2-2'
        }]
      }]
    }]
  }]

const router = new VueRouter({
  routes
})

describe('Breadcrumb.vue', () => {
  const wrapper = mount(Breadcrumb, {
    localVue,
    router
  })
  it('dashboard', () => {
    router.push('/dashboard')
    const len = wrapper.findAll('.el-breadcrumb__inner').length
    expect(len).toBe(1)
  })
  it('normal route', () => {
    router.push('/menu/menu1')
    const len = wrapper.findAll('.el-breadcrumb__inner').length
    expect(len).toBe(2)
  })
  it('nested route', () => {
    router.push('/menu/menu1/menu1-2/menu1-2-1')
    const len = wrapper.findAll('.el-breadcrumb__inner').length
    expect(len).toBe(4)
  })
  it('no meta.title', () => {
    router.push('/menu/menu1/menu1-2/menu1-2-2')
    const len = wrapper.findAll('.el-breadcrumb__inner').length
    expect(len).toBe(3)
  })
  // it('click link', () => {
  //   router.push('/menu/menu1/menu1-2/menu1-2-2')
  //   const breadcrumbArray = wrapper.findAll('.el-breadcrumb__inner')
  //   const second = breadcrumbArray.at(1)
  //   console.log(breadcrumbArray)
  //   const href = second.find('a').attributes().href
  //   expect(href).toBe('#/menu/menu1')
  // })
  // it('noRedirect', () => {
  //   router.push('/menu/menu1/menu1-2/menu1-2-1')
  //   const breadcrumbArray = wrapper.findAll('.el-breadcrumb__inner')
  //   const redirectBreadcrumb = breadcrumbArray.at(2)
  //   expect(redirectBreadcrumb.contains('a')).toBe(false)
  // })
  it('last breadcrumb', () => {
    router.push('/menu/menu1/menu1-2/menu1-2-1')
    const breadcrumbArray = wrapper.findAll('.el-breadcrumb__inner')
    const redirectBreadcrumb = breadcrumbArray.at(3)
    expect(redirectBreadcrumb.contains('a')).toBe(false)
  })
})


================================================
FILE: admin/admin-ui/tests/unit/components/Hamburger.spec.js
================================================
import { shallowMount } from '@vue/test-utils'
import Hamburger from '@/components/Hamburger/index.vue'
describe('Hamburger.vue', () => {
  it('toggle click', () => {
    const wrapper = shallowMount(Hamburger)
    const mockFn = jest.fn()
    wrapper.vm.$on('toggleClick', mockFn)
    wrapper.find('.hamburger').trigger('click')
    expect(mockFn).toBeCalled()
  })
  it('prop isActive', () => {
    const wrapper = shallowMount(Hamburger)
    wrapper.setProps({ isActive: true })
    expect(wrapper.contains('.is-active')).toBe(true)
    wrapper.setProps({ isActive: false })
    expect(wrapper.contains('.is-active')).toBe(false)
  })
})


================================================
FILE: admin/admin-ui/tests/unit/components/SvgIcon.spec.js
================================================
import { shallowMount } from '@vue/test-utils'
import SvgIcon from '@/components/SvgIcon/index.vue'
describe('SvgIcon.vue', () => {
  it('iconClass', () => {
    const wrapper = shallowMount(SvgIcon, {
      propsData: {
        iconClass: 'test'
      }
    })
    expect(wrapper.find('use').attributes().href).toBe('#icon-test')
  })
  it('className', () => {
    const wrapper = shallowMount(SvgIcon, {
      propsData: {
        iconClass: 'test'
      }
    })
    expect(wrapper.classes().length).toBe(1)
    wrapper.setProps({ className: 'test' })
    expect(wrapper.classes().includes('test')).toBe(true)
  })
})


================================================
FILE: admin/admin-ui/tests/unit/utils/formatTime.spec.js
================================================
import { formatTime } from '@/utils/index.js'

describe('Utils:formatTime', () => {
  const d = new Date('2018-07-13 17:54:01') // "2018-07-13 17:54:01"
  const retrofit = 5 * 1000

  it('ten digits timestamp', () => {
    expect(formatTime((d / 1000).toFixed(0))).toBe('7月13日17时54分')
  })
  it('test now', () => {
    expect(formatTime(+new Date() - 1)).toBe('刚刚')
  })
  it('less two minute', () => {
    expect(formatTime(+new Date() - 60 * 2 * 1000 + retrofit)).toBe('2分钟前')
  })
  it('less two hour', () => {
    expect(formatTime(+new Date() - 60 * 60 * 2 * 1000 + retrofit)).toBe('2小时前')
  })
  it('less one day', () => {
    expect(formatTime(+new Date() - 60 * 60 * 24 * 1 * 1000)).toBe('1天前')
  })
  it('more than one day', () => {
    expect(formatTime(d)).toBe('7月13日17时54分')
  })
  it('format', () => {
    expect(formatTime(d, '{y}-{m}-{d} {h}:{i}')).toBe('2018-07-13 17:54')
    expect(formatTime(d, '{y}-{m}-{d}')).toBe('2018-07-13')
    expect(formatTime(d, '{y}/{m}/{d} {h}-{i}')).toBe('2018/07/13 17-54')
  })
})


================================================
FILE: admin/admin-ui/tests/unit/utils/parseTime.spec.js
================================================
import { parseTime } from '@/utils/index.js'

describe('Utils:parseTime', () => {
  const d = new Date('2018-07-13 17:54:01') // "2018-07-13 17:54:01"
  it('timestamp', () => {
    expect(parseTime(d)).toBe('2018-07-13 17:54:01')
  })
  it('ten digits timestamp', () => {
    expect(parseTime((d / 1000).toFixed(0))).toBe('2018-07-13 17:54:01')
  })
  it('new Date', () => {
    expect(parseTime(new Date(d))).toBe('2018-07-13 17:54:01')
  })
  it('format', () => {
    expect(parseTime(d, '{y}-{m}-{d} {h}:{i}')).toBe('2018-07-13 17:54')
    expect(parseTime(d, '{y}-{m}-{d}')).toBe('2018-07-13')
    expect(parseTime(d, '{y}/{m}/{d} {h}-{i}')).toBe('2018/07/13 17-54')
  })
  it('get the day of the week', () => {
    expect(parseTime(d, '{a}')).toBe('五') // 星期五
  })
  it('get the day of the week', () => {
    expect(parseTime(+d + 1000 * 60 * 60 * 24 * 2, '{a}')).toBe('日') // 星期日
  })
  it('empty argument', () => {
    expect(parseTime()).toBeNull()
  })
})


================================================
FILE: admin/admin-ui/tests/unit/utils/validate.spec.js
================================================
import { validUsername, isExternal } from '@/utils/validate.js'

describe('Utils:validate', () => {
  it('validUsername', () => {
    expect(validUsername('admin')).toBe(true)
    expect(validUsername('editor')).toBe(true)
    expect(validUsername('xxxx')).toBe(false)
  })
  it('isExternal', () => {
    expect(isExternal('https://github.com/PanJiaChen/vue-element-admin')).toBe(true)
    expect(isExternal('http://github.com/PanJiaChen/vue-element-admin')).toBe(true)
    expect(isExternal('github.com/PanJiaChen/vue-element-admin')).toBe(false)
    expect(isExternal('/dashboard')).toBe(false)
    expect(isExternal('./dashboard')).toBe(false)
    expect(isExternal('dashboard')).toBe(false)
  })
})


================================================
FILE: admin/admin-ui/vue.config.js
================================================
'use strict'
const path = require('path')
const defaultSettings = require('./src/settings.js')

function resolve(dir) {
  return path.join(__dirname, dir)
}

const name = defaultSettings.title || 'vue Admin Template' // page title

// If your port is set to 80,
// use administrator privileges to execute the command line.
// For example, Mac: sudo npm run
// You can change the port by the following methods:
// port = 9528 npm run dev OR npm run dev --port = 9528
const port = process.env.port || process.env.npm_config_port || 9528 // dev port

// All configuration item explanations can be find in https://cli.vuejs.org/config/
module.exports = {
  /**
   * You will need to set publicPath if you plan to deploy your site under a sub path,
   * for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/,
   * then publicPath should be set to "/bar/".
   * In most cases please use '/' !!!
   * Detail: https://cli.vuejs.org/config/#publicpath
   */
  publicPath: '/',
  outputDir: 'target/dist',
  assetsDir: 'static',
  lintOnSave: process.env.NODE_ENV === 'development',
  productionSourceMap: false,
  devServer: {
    port: port,
    open: true,
    overlay: {
      warnings: false,
      errors: true
    },
    proxy: {
      // change xxx-api/login => mock/login
      // detail: https://cli.vuejs.org/config/#devserver-proxy
      [process.env.VUE_APP_BASE_API]: {
        target: `http://127.0.0.1:${port}/mock`,
        changeOrigin: true,
        pathRewrite: {
          ['^' + process.env.VUE_APP_BASE_API]: ''
        }
      }
    },
    after: require('./mock/mock-server.js')
  },
  configureWebpack: {
    // provide the app's title in webpack's name field, so that
    // it can be accessed in index.html to inject the correct title.
    name: name,
    resolve: {
      alias: {
        '@': resolve('src')
      }
    }
  },
  chainWebpack(config) {
    config.plugins.delete('preload') // TODO: need test
    config.plugins.delete('prefetch') // TODO: need test

    // set svg-sprite-loader
    config.module
      .rule('svg')
      .exclude.add(resolve('src/icons'))
      .end()
    config.module
      .rule('icons')
      .test(/\.svg$/)
      .include.add(resolve('src/icons'))
      .end()
      .use('svg-sprite-loader')
      .loader('svg-sprite-loader')
      .options({
        symbolId: 'icon-[name]'
      })
      .end()

    // set preserveWhitespace
    config.module
      .rule('vue')
      .use('vue-loader')
      .loader('vue-loader')
      .tap(options => {
        options.compilerOptions.preserveWhitespace = true
        return options
      })
      .end()

    config
    // https://webpack.js.org/configuration/devtool/#development
      .when(process.env.NODE_ENV === 'development',
        config => config.devtool('cheap-source-map')
      )

    config
      .when(process.env.NODE_ENV !== 'development',
        config => {
          config
            .plugin('ScriptExtHtmlWebpackPlugin')
            .after('html')
            .use('script-ext-html-webpack-plugin', [{
            // `runtime` must same as runtimeChunk name. default is `runtime`
              inline: /runtime\..*\.js$/
            }])
            .end()
          config
            .optimization.splitChunks({
              chunks: 'all',
              cacheGroups: {
                libs: {
                  name: 'chunk-libs',
                  test: /[\\/]node_modules[\\/]/,
                  priority: 10,
                  chunks: 'initial' // only package third parties that are initially dependent
                },
                elementUI: {
                  name: 'chunk-elementUI', // split elementUI into a single package
                  priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
                  test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
                },
                commons: {
                  name: 'chunk-commons',
                  test: resolve('src/components'), // can customize your rules
                  minChunks: 3, //  minimum common number
                  priority: 5,
                  reuseExistingChunk: true
                }
              }
            })
          config.optimization.runtimeChunk('single')
        }
      )
  }
}


================================================
FILE: admin/admin-web/pom.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>canal.admin</artifactId>
        <groupId>com.alibaba.otter</groupId>
        <version>1.1.9-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>canal.admin-web</artifactId>
    <name>canal admin-web for otter ${project.version}</name>
    <dependencies>
    	<dependency>
			<groupId>com.alibaba.otter</groupId>
			<artifactId>canal.protocol</artifactId>
			<version>${project.version}</version>
			<optional>true</optional>
		</dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <!-- 支持arm64需要mysql 8.0,升级为8.0的新版驱动 -->
            <version>8.0.33</version>
        </dependency>
        <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>caffeine</artifactId>
        </dependency>
        <dependency>
            <groupId>io.ebean</groupId>
            <artifactId>ebean</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
        </dependency>
		<!-- junit -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<scope>test</scope>
		</dependency>
    </dependencies>

    <build>
        <finalName>canal-admin-${project.version}</finalName>
        <plugins>
            <plugin>
                <groupId>io.repaint.maven</groupId>
                <artifactId>tiles-maven-plugin</artifactId>
                <version>2.12</version>
                <extensions>true</extensions>
                <configuration>
                    <tiles>
                        <tile>io.ebean.tile:enhancement:11.41.1</tile>
                    </tiles>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.2.1</version>
                <executions>
                    <execution>
                        <id>assemble</id>
                        <goals>
                            <goal>single</goal>
                        </goals>
                        <phase>package</phase>
                    </execution>
                </executions>
                <configuration>
                    <appendAssemblyId>false</appendAssemblyId>
                    <attach>false</attach>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.0.2</version>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                            <mainClass>com.alibaba.otter.canal.admin.CanalAdminApplication</mainClass>
                        </manifest>
                    </archive>
                    <excludes>
                        <exclude>**/*.properties</exclude>
                        <exclude>**/*.xml</exclude>
                        <exclude>**/*.yml</exclude>
                        <exclude>static/**</exclude>
                        <exclude>public/**</exclude>
                        <exclude>templates/**</exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <profile>
            <id>npm</id>
            <activation>
                <property>
                    <name>env</name>
                    <value>npm</value>
                </property>
            </activation>
            <build>
                <plugins>
                    <plugin>
                        <artifactId>maven-clean-plugin</artifactId>
                        <version>3.0.0</version>
                        <configuration>
                            <filesets>
                                <fileset>
                                    <directory>src/main/resources/public</directory>
                                </fileset>
                            </filesets>
                        </configuration>
                    </plugin>
                    <plugin>
                        <artifactId>maven-resources-plugin</artifactId>
                        <version>3.0.2</version>
                        <executions>
                            <execution>
                                <id>copy Vue.js frontend content</id>
                                <phase>generate-resources</phase>
                                <goals>
                                    <goal>copy-resources</goal>
                                </goals>
                                <configuration>
                                    <outputDirectory>src/main/resources/public</outputDirectory>
                                    <overwrite>true</overwrite>
                                    <resources>
                                        <resource>
                                            <directory>${project.parent.basedir}/admin-ui/target/dist</directory>
                                            <includes>
                                                <include>static/</include>
                                                <include>index.html</include>
                                                <include>avatar.gif</include>
                                                <include>logo.png</include>
                                            </includes>
                                        </resource>
                                    </resources>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>

        <profile>
            <id>dev</id>
            <activation>
                <activeByDefault>true</activeByDefault>
                <property>
                    <name>env</name>
                    <value>!release</value>
                </property>
            </activation>

            <build>
                <plugins>
                    <plugin>
                        <artifactId>maven-assembly-plugin</artifactId>
                        <configuration>
                            <descriptors>
                                <descriptor>${basedir}/src/main/assembly/dev.xml</descriptor>
                            </descriptors>
                            <finalName>canal-admin</finalName>
                            <outputDirectory>${project.build.directory}</outputDirectory>
                        </configuration>
                    </plugin>
                </plugins>
            </build>

        </profile>

        <profile>
            <id>release</id>
            <activation>
                <property>
                    <name>env</name>
                    <value>release</value>
                </property>
            </activation>

            <build>
                <plugins>
                    <plugin>
                        <artifactId>maven-assembly-plugin</artifactId>
                        <configuration>
                            <descriptors>
                                <descriptor>${basedir}/src/main/assembly/release.xml</descriptor>
                            </descriptors>
                            <finalName>canal.admin-${project.version}</finalName>
                            <outputDirectory>${project.basedir}/../../target</outputDirectory>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>

</project>


================================================
FILE: admin/admin-web/src/main/assembly/dev.xml
================================================
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
	<id>dist</id>
	<formats>
		<format>dir</format>
	</formats>
	<includeBaseDirectory>false</includeBaseDirectory>
	<fileSets>
        <fileSet>
            <directory>.</directory>
            <outputDirectory>/</outputDirectory>
            <includes>
                <include>README*</include>
            </includes>
        </fileSet>
        <fileSet>
            <directory>./src/main/bin</directory>
            <outputDirectory>bin</outputDirectory>
            <includes>
                <include>**/*</include>
            </includes>
            <fileMode>0755</fileMode>
        </fileSet>
        <fileSet>
            <directory>./src/main/resources</directory>
            <outputDirectory>/conf</outputDirectory>
            <includes>
                <include>application.yml</include>
                <include>logback.xml</include>
                <include>public/**</include>
                <include>canal_manager.sql</include>
                <include>canal-template.properties</include>
                <include>instance-template.properties</include>
            </includes>
        </fileSet>
        <fileSet>
            <directory>target</directory>
            <outputDirectory>logs</outputDirectory>
            <excludes>
                <exclude>**/*</exclude>
            </excludes>
        </fileSet>
    </fileSets>
    <dependencySets>
        <dependencySet>
            <outputDirectory>lib</outputDirectory>
            <excludes>
                <exclude>junit:junit</exclude>
            </excludes>
        </dependencySet>
    </dependencySets>
</assembly>


================================================
FILE: admin/admin-web/src/main/assembly/release.xml
================================================
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
    <id>dist</id>
    <formats>
        <format>tar.gz</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <fileSets>
        <fileSet>
            <directory>.</directory>
            <outputDirectory>/</outputDirectory>
            <includes>
                <include>README*</include>
            </includes>
        </fileSet>
        <fileSet>
            <directory>./src/main/bin</directory>
            <outputDirectory>bin</outputDirectory>
            <includes>
                <include>**/*</include>
            </includes>
            <fileMode>0755</fileMode>
        </fileSet>
        <fileSet>
            <directory>./src/main/resources</directory>
            <outputDirectory>/conf</outputDirectory>
            <includes>
                <include>application.yml</include>
                <include>logback.xml</include>
                <include>public/**</include>
                <include>canal_manager.sql</include>
                <include>canal-template.properties</include>
                <include>instance-template.properties</include>
            </includes>
        </fileSet>
        <fileSet>
            <directory>target</directory>
            <outputDirectory>logs</outputDirectory>
            <excludes>
                <exclude>**/*</exclude>
            </excludes>
        </fileSet>
    </fileSets>
    <dependencySets>
        <dependencySet>
            <outputDirectory>lib</outputDirectory>
            <excludes>
                <exclude>junit:junit</exclude>
            </excludes>
        </dependencySet>
    </dependencySets>
</assembly>


================================================
FILE: admin/admin-web/src/main/bin/restart.sh
================================================
#!/bin/bash

case $(uname) in
Linux)
  bin_abs_path=$(readlink -f $(dirname $0))
  ;;
*)
  bin_abs_path=$(cd $(dirname $0) ||exit ; pwd)
  ;;
esac

sh "$bin_abs_path"/stop.sh
sh "$bin_abs_path"/startup.sh


================================================
FILE: admin/admin-web/src/main/bin/startup.bat
================================================
@echo off
@if not "%ECHO%" == ""  echo %ECHO%
@if "%OS%" == "Windows_NT"  setlocal

set ENV_PATH=.\
if "%OS%" == "Windows_NT" set ENV_PATH=%~dp0%

set conf_dir=%ENV_PATH%\..\conf

set CLASSPATH=%conf_dir%
set CLASSPATH=%conf_dir%\..\lib\*;%CLASSPATH%

set JAVA_MEM_OPTS= -Xms128m -Xmx512m
set JAVA_OPTS_EXT= -Djava.awt.headless=true -Djava.net.preferIPv4Stack=false -Dapplication.codeset=UTF-8 -Dfile.encoding=UTF-8
set ADAPTER_OPTS= -DappName=canal-admin

set JAVA_OPTS= %JAVA_MEM_OPTS% %JAVA_OPTS_EXT% %ADAPTER_OPTS%

set CMD_STR= java %JAVA_OPTS% -classpath "%CLASSPATH%" com.alibaba.otter.canal.admin.CanalAdminApplication
echo start cmd : %CMD_STR%

java %JAVA_OPTS% -classpath "%CLASSPATH%" com.alibaba.otter.canal.admin.CanalAdminApplication


================================================
FILE: admin/admin-web/src/main/bin/startup.sh
================================================
#!/bin/bash

current_path=`pwd`
case "`uname`" in
    Linux)
		bin_abs_path=$(readlink -f $(dirname $0))
		;;
	*)
		bin_abs_path=`cd $(dirname $0); pwd`
		;;
esac
base=${bin_abs_path}/..
export LANG=en_US.UTF-8
export BASE=$base

if [ -f $base/bin/adapter.pid ] ; then
	echo "found adapter.pid , Please run stop.sh first ,then startup.sh" 2>&2
    exit 1
fi

if [ ! -d $base/logs ] ; then
	mkdir -p $base/logs
fi

## set java path
if [ -z "$JAVA" ] ; then
  JAVA=$(which java)
fi

ALIBABA_JAVA="/usr/alibaba/java/bin/java"
TAOBAO_JAVA="/opt/taobao/java/bin/java"
if [ -z "$JAVA" ]; then
  if [ -f $ALIBABA_JAVA ] ; then
  	JAVA=$ALIBABA_JAVA
  elif [ -f $TAOBAO_JAVA ] ; then
  	JAVA=$TAOBAO_JAVA
  else
  	echo "Cannot find a Java JDK. Please set either set JAVA or put java (>=1.5) in your PATH." 2>&2
    exit 1
  fi
fi

case "$#"
in
0 )
  ;;
2 )
  if [ "$1" = "debug" ]; then
    DEBUG_PORT=$2
    DEBUG_SUSPEND="n"
    JAVA_DEBUG_OPT="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=$DEBUG_PORT,server=y,suspend=$DEBUG_SUSPEND"
  fi
  ;;
* )
  echo "THE PARAMETERS MUST BE TWO OR LESS.PLEASE CHECK AGAIN."
  exit;;
esac

JavaVersion=`$JAVA -version 2>&1 |awk 'NR==1{ gsub(/"/,""); print $3 }' | awk  -F '.' '{print $1}'`
str=`file -L $JAVA | grep 64-bit`

JAVA_OPTS="$JAVA_OPTS -Xss1m -XX:+AggressiveOpts -XX:-UseBiasedLocking -XX:-OmitStackTraceInFastThrow -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$base/logs"
if [ $JavaVersion -ge 11 ] ; then
  #JAVA_OPTS="$JAVA_OPTS -Xlog:gc*:$base_log/gc.log:time "
  JAVA_OPTS="$JAVA_OPTS"
else
  #JAVA_OPTS="$JAVA_OPTS -Xloggc:$base/logs/canal/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime"
  JAVA_OPTS="$JAVA_OPTS -XX:+UseFastAccessorMethods -XX:+PrintAdaptiveSizePolicy -XX:+PrintTenuringDistribution"
fi

if [ -n "$str" ]; then
	if [ $JavaVersion -ge 11 ] ; then
    # For G1
    JAVA_OPTS="-server -Xms2g -Xmx3g -XX:+UseG1GC -XX:MaxGCPauseMillis=250 -XX:+UseGCOverheadLimit -XX:+ExplicitGCInvokesConcurrent $JAVA_OPTS"
  else
	  JAVA_OPTS="-server -Xms2g -Xmx3g -Xmn1g -XX:SurvivorRatio=2 -XX:PermSize=96m -XX:MaxPermSize=256m -XX:MaxTenuringThreshold=15 -XX:+DisableExplicitGC $JAVA_OPTS"
	fi
else
	JAVA_OPTS="-server -Xms1024m -Xmx1024m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:MaxPermSize=128m $JAVA_OPTS"
fi

JAVA_OPTS=" $JAVA_OPTS -Djava.awt.headless=true -Djava.net.preferIPv4Stack=false -Dfile.encoding=UTF-8"
CANAL_OPTS="-DappName=canal-admin"

for i in $base/lib/*;
    do CLASSPATH=$i:"$CLASSPATH";
done

CLASSPATH="$base/conf:$CLASSPATH";

echo "cd to $bin_abs_path for workaround relative path"
cd $bin_abs_path

echo CLASSPATH :$CLASSPATH
$JAVA $JAVA_OPTS $JAVA_DEBUG_OPT $CANAL_OPTS -classpath .:$CLASSPATH com.alibaba.otter.canal.admin.CanalAdminApplication 1>>/dev/null 2>&1 &
echo $! > $base/bin/admin.pid

echo "cd to $current_path for continue"
cd $current_path


================================================
FILE: admin/admin-web/src/main/bin/stop.sh
================================================
#!/bin/bash

cygwin=false;
linux=false;
case "`uname`" in
    CYGWIN*)
        cygwin=true
        ;;
    Linux*)
    	linux=true
    	;;
esac

get_pid() {	
	STR=$1
	PID=$2
    if $cygwin; then
        JAVA_CMD="$JAVA_HOME\bin\java"
        JAVA_CMD=`cygpath --path --unix $JAVA_CMD`
        JAVA_PID=`ps |grep $JAVA_CMD |awk '{print $1}'`
    else
    	if $linux; then
	        if [ ! -z "$PID" ]; then
	        	JAVA_PID=`ps -C java -f --width 1000|grep "$STR"|grep "$PID"|grep -v grep|awk '{print $2}'`
		    else 
		        JAVA_PID=`ps -C java -f --width 1000|grep "$STR"|grep -v grep|awk '{print $2}'`
	        fi
	    else
	    	if [ ! -z "$PID" ]; then
	        	JAVA_PID=`ps aux |grep "$STR"|grep "$PID"|grep -v grep|awk '{print $2}'`
		    else 
		        JAVA_PID=`ps aux |grep "$STR"|grep -v grep|awk '{print $2}'`
	        fi
	    fi
    fi
    echo $JAVA_PID;
}

base=`dirname $0`/..
pidfile=$base/bin/admin.pid
if [ ! -f "$pidfile" ];then
	echo "canal-admin is not running. exists"
	exit
fi

pid=`cat $pidfile`
if [ "$pid" == "" ] ; then
	pid=`get_pid "appName=canal-admin"`
fi

echo -e "`hostname`: stopping canal $pid ... "
kill $pid

LOOPS=0
while (true); 
do 
	gpid=`get_pid "appName=canal-admin" "$pid"`
    if [ "$gpid" == "" ] ; then
    	echo "Oook! cost:$LOOPS"
    	`rm $pidfile`
    	break;
    fi
    let LOOPS=LOOPS+1
    sleep 1
done

================================================
FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/CanalAdminApplication.java
================================================
package com.alibaba.otter.canal.admin;

import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * 启动入口
 *
 * @author rewerma @ 2018-10-20
 * @version 1.0.0
 */
@SpringBootApplication
public class CanalAdminApplication {

    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(CanalAdminApplication.class);
        application.setBannerMode(Banner.Mode.OFF);
        application.run(args);
    }
}


================================================
FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/common/DaemonThreadFactory.java
================================================
package com.alibaba.otter.canal.admin.common;

import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

public class DaemonThreadFactory implements ThreadFactory {

    public static final ThreadFactory daemonThreadFactory = new DaemonThreadFactory();

    public Thread newThread(Runnable r) {
        Thread t = Executors.defaultThreadFactory().newThread(r);
        t.setDaemon(true);
        return t;
    }
}


================================================
FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/common/TemplateConfigLoader.java
================================================
package com.alibaba.otter.canal.admin.common;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TemplateConfigLoader {

    private static final Logger logger              = LoggerFactory.getLogger(TemplateConfigLoader.class);

    public static final String  CONF_DIR            = "conf";
    public static final String  CANAL_CONFIG_TMP    = "canal-template.properties";
    public static final String  INSTANCE_CONFIG_TMP = "instance-template.properties";

    public static String loadCanalConfig() {
        return loadFile(CANAL_CONFIG_TMP);
    }

    public static String loadInstanceConfig() {
        return loadFile(INSTANCE_CONFIG_TMP);
    }

    private static String loadFile(String fileName) {
        File configFile = new File(".." + File.separator + CONF_DIR + File.separator + fileName);
        if (!configFile.exists()) {
            URL url = TemplateConfigLoader.class.getClassLoader().getResource("");
            if (url != null) {
                configFile = new File(url.getPath() + fileName + File.separator);
            }
        }
        if (!configFile.exists()) {
            return null;
        }
        try (InputStream in = new FileInputStream(configFile)) {
            byte[] bytes = new byte[in.available()];
            in.read(bytes);
            return new String(bytes, StandardCharsets.UTF_8);
        } catch (IOException e) {
            logger.error("Read " + fileName + " error", e);
        }

        return null;
    }
}


================================================
FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/common/Threads.java
================================================
package com.alibaba.otter.canal.admin.common;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Threads {

    public static int                   pool            = 60;
    public static final ExecutorService executorService = new ThreadPoolExecutor(pool,
                                                            pool,
                                                            0L,
                                                            TimeUnit.MILLISECONDS,
                                                            new ArrayBlockingQueue<>(pool * 20),
                                                            DaemonThreadFactory.daemonThreadFactory);
}


================================================
FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/common/exception/ServiceException.java
================================================
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.alibaba.otter.canal.admin.common.exception;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

/**
 * Service Logic Exception
 */
@ResponseStatus(value = HttpStatus.SERVICE_UNAVAILABLE)
public class ServiceException extends RuntimeException {

    private static final long serialVersionUID = -663217666968123330L;

    public ServiceException(){
    }

    public ServiceException(String message){
        super(message);
    }

    public ServiceException(String message, Throwable cause){
        super(message, cause);
    }

    public ServiceException(Throwable cause){
        super(cause);
    }

    public ServiceException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace){
        super(message, cause, enableSuppression, writableStackTrace);
    }

}


================================================
FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/config/EbeanConfig.java
========================================
Download .txt
gitextract_xcssslhk/

├── .codecov.yml
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── any-questions-on-canal.md
│   │   ├── bug-report-for-canal.md
│   │   └── feature-request-of-canal.md
│   └── workflows/
│       └── maven.yml
├── .gitignore
├── .mvn/
│   └── wrapper/
│       ├── maven-wrapper.jar
│       └── maven-wrapper.properties
├── .travis.yml
├── LICENSE.txt
├── README.md
├── RELEASE.txt
├── SECURITY.md
├── admin/
│   ├── admin-ui/
│   │   ├── .editorconfig
│   │   ├── .eslintignore
│   │   ├── .eslintrc.js
│   │   ├── .gitignore
│   │   ├── .travis.yml
│   │   ├── LICENSE
│   │   ├── babel.config.js
│   │   ├── build/
│   │   │   └── index.js
│   │   ├── jest.config.js
│   │   ├── mock/
│   │   │   ├── index.js
│   │   │   ├── mock-server.js
│   │   │   ├── table.js
│   │   │   └── user.js
│   │   ├── node/
│   │   │   └── node
│   │   ├── package.json
│   │   ├── pom.xml
│   │   ├── postcss.config.js
│   │   ├── public/
│   │   │   └── index.html
│   │   ├── src/
│   │   │   ├── App.vue
│   │   │   ├── api/
│   │   │   │   ├── canalCluster.js
│   │   │   │   ├── canalConfig.js
│   │   │   │   ├── canalInstance.js
│   │   │   │   ├── nodeServer.js
│   │   │   │   ├── table.js
│   │   │   │   └── user.js
│   │   │   ├── components/
│   │   │   │   ├── Breadcrumb/
│   │   │   │   │   └── index.vue
│   │   │   │   ├── Hamburger/
│   │   │   │   │   └── index.vue
│   │   │   │   ├── Pagination/
│   │   │   │   │   └── index.vue
│   │   │   │   └── SvgIcon/
│   │   │   │       └── index.vue
│   │   │   ├── icons/
│   │   │   │   ├── index.js
│   │   │   │   └── svgo.yml
│   │   │   ├── layout/
│   │   │   │   ├── components/
│   │   │   │   │   ├── AppMain.vue
│   │   │   │   │   ├── Navbar.vue
│   │   │   │   │   ├── Sidebar/
│   │   │   │   │   │   ├── FixiOSBug.js
│   │   │   │   │   │   ├── Item.vue
│   │   │   │   │   │   ├── Link.vue
│   │   │   │   │   │   ├── Logo.vue
│   │   │   │   │   │   ├── SidebarItem.vue
│   │   │   │   │   │   └── index.vue
│   │   │   │   │   └── index.js
│   │   │   │   ├── index.vue
│   │   │   │   └── mixin/
│   │   │   │       └── ResizeHandler.js
│   │   │   ├── main.js
│   │   │   ├── permission.js
│   │   │   ├── router/
│   │   │   │   └── index.js
│   │   │   ├── settings.js
│   │   │   ├── store/
│   │   │   │   ├── getters.js
│   │   │   │   ├── index.js
│   │   │   │   └── modules/
│   │   │   │       ├── app.js
│   │   │   │       ├── settings.js
│   │   │   │       └── user.js
│   │   │   ├── styles/
│   │   │   │   ├── element-ui.scss
│   │   │   │   ├── index.scss
│   │   │   │   ├── mixin.scss
│   │   │   │   ├── sidebar.scss
│   │   │   │   ├── transition.scss
│   │   │   │   └── variables.scss
│   │   │   ├── utils/
│   │   │   │   ├── auth.js
│   │   │   │   ├── get-page-title.js
│   │   │   │   ├── index.js
│   │   │   │   ├── request.js
│   │   │   │   ├── scrollTo.js
│   │   │   │   └── validate.js
│   │   │   └── views/
│   │   │       ├── 404.vue
│   │   │       ├── canalServer/
│   │   │       │   ├── CanalCluster.vue
│   │   │       │   ├── CanalConfig.vue
│   │   │       │   ├── CanalInstance.vue
│   │   │       │   ├── CanalInstanceAdd.vue
│   │   │       │   ├── CanalInstanceLogDetail.vue
│   │   │       │   ├── CanalInstanceUpdate.vue
│   │   │       │   ├── CanalLogDetail.vue
│   │   │       │   └── NodeServer.vue
│   │   │       ├── dashboard/
│   │   │       │   └── index.vue
│   │   │       ├── login/
│   │   │       │   └── index.vue
│   │   │       └── sys/
│   │   │           └── UserInfo.vue
│   │   ├── tests/
│   │   │   └── unit/
│   │   │       ├── .eslintrc.js
│   │   │       ├── components/
│   │   │       │   ├── Breadcrumb.spec.js
│   │   │       │   ├── Hamburger.spec.js
│   │   │       │   └── SvgIcon.spec.js
│   │   │       └── utils/
│   │   │           ├── formatTime.spec.js
│   │   │           ├── parseTime.spec.js
│   │   │           └── validate.spec.js
│   │   └── vue.config.js
│   ├── admin-web/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   ├── assembly/
│   │       │   │   ├── dev.xml
│   │       │   │   └── release.xml
│   │       │   ├── bin/
│   │       │   │   ├── restart.sh
│   │       │   │   ├── startup.bat
│   │       │   │   ├── startup.sh
│   │       │   │   └── stop.sh
│   │       │   ├── java/
│   │       │   │   └── com/
│   │       │   │       └── alibaba/
│   │       │   │           └── otter/
│   │       │   │               └── canal/
│   │       │   │                   └── admin/
│   │       │   │                       ├── CanalAdminApplication.java
│   │       │   │                       ├── common/
│   │       │   │                       │   ├── DaemonThreadFactory.java
│   │       │   │                       │   ├── TemplateConfigLoader.java
│   │       │   │                       │   ├── Threads.java
│   │       │   │                       │   └── exception/
│   │       │   │                       │       └── ServiceException.java
│   │       │   │                       ├── config/
│   │       │   │                       │   ├── EbeanConfig.java
│   │       │   │                       │   ├── SpringContext.java
│   │       │   │                       │   └── WebConfig.java
│   │       │   │                       ├── connector/
│   │       │   │                       │   ├── AdminConnector.java
│   │       │   │                       │   ├── SimpleAdminConnector.java
│   │       │   │                       │   └── SimpleAdminConnectors.java
│   │       │   │                       ├── controller/
│   │       │   │                       │   ├── CanalClusterController.java
│   │       │   │                       │   ├── CanalConfigController.java
│   │       │   │                       │   ├── CanalInstanceController.java
│   │       │   │                       │   ├── NodeServerController.java
│   │       │   │                       │   ├── PollingConfigController.java
│   │       │   │                       │   └── UserController.java
│   │       │   │                       ├── handler/
│   │       │   │                       │   └── CustomExceptionHandler.java
│   │       │   │                       ├── model/
│   │       │   │                       │   ├── BaseModel.java
│   │       │   │                       │   ├── CanalCluster.java
│   │       │   │                       │   ├── CanalConfig.java
│   │       │   │                       │   ├── CanalInstanceConfig.java
│   │       │   │                       │   ├── Model.java
│   │       │   │                       │   ├── NodeServer.java
│   │       │   │                       │   ├── Pager.java
│   │       │   │                       │   └── User.java
│   │       │   │                       └── service/
│   │       │   │                           ├── CanalClusterService.java
│   │       │   │                           ├── CanalConfigService.java
│   │       │   │                           ├── CanalInstanceService.java
│   │       │   │                           ├── NodeServerService.java
│   │       │   │                           ├── PollingConfigService.java
│   │       │   │                           ├── UserService.java
│   │       │   │                           └── impl/
│   │       │   │                               ├── CanalClusterServiceImpl.java
│   │       │   │                               ├── CanalConfigServiceImpl.java
│   │       │   │                               ├── CanalInstanceServiceImpl.java
│   │       │   │                               ├── NodeServerServiceImpl.java
│   │       │   │                               ├── PollingConfigServiceImpl.java
│   │       │   │                               └── UserServiceImpl.java
│   │       │   └── resources/
│   │       │       ├── application.yml
│   │       │       ├── canal-template.properties
│   │       │       ├── canal_manager.sql
│   │       │       ├── instance-template.properties
│   │       │       ├── logback.xml
│   │       │       └── public/
│   │       │           ├── index.html
│   │       │           └── static/
│   │       │               ├── css/
│   │       │               │   ├── app.bb951cb3.css
│   │       │               │   ├── chunk-101fc062.fad9926f.css
│   │       │               │   ├── chunk-14b5f7a4.f3e06673.css
│   │       │               │   ├── chunk-22553be3.f3e06673.css
│   │       │               │   ├── chunk-2301924a.160e7b4a.css
│   │       │               │   ├── chunk-2b9b6c5c.c89f8844.css
│   │       │               │   ├── chunk-37c49cbf.efc21a9c.css
│   │       │               │   ├── chunk-49959c8b.e8e2beee.css
│   │       │               │   ├── chunk-4f09fed2.70ec0b86.css
│   │       │               │   ├── chunk-5afa45f5.a34bb177.css
│   │       │               │   ├── chunk-5b373aad.b966d36b.css
│   │       │               │   ├── chunk-69386cf0.741ff14e.css
│   │       │               │   ├── chunk-7ec889b7.c0585512.css
│   │       │               │   ├── chunk-98f505d0.5280f88f.css
│   │       │               │   ├── chunk-bd1d44ee.1528199a.css
│   │       │               │   ├── chunk-da289616.c89f8844.css
│   │       │               │   ├── chunk-elementUI.18b11d0e.css
│   │       │               │   └── chunk-libs.5cf311f0.css
│   │       │               └── js/
│   │       │                   ├── app.6845b228.js
│   │       │                   ├── app.eee35d99.js
│   │       │                   ├── chunk-0dca2f22.a2bc28b8.js
│   │       │                   ├── chunk-101fc062.372a5ca5.js
│   │       │                   ├── chunk-101fc062.bc898027.js
│   │       │                   ├── chunk-14b5f7a4.013449e9.js
│   │       │                   ├── chunk-22553be3.e6d72de5.js
│   │       │                   ├── chunk-2301924a.1774b851.js
│   │       │                   ├── chunk-2b9b6c5c.cc2181b9.js
│   │       │                   ├── chunk-37c49cbf.64d26540.js
│   │       │                   ├── chunk-37c49cbf.92ebe0ae.js
│   │       │                   ├── chunk-49959c8b.058266cb.js
│   │       │                   ├── chunk-49959c8b.6d226f70.js
│   │       │                   ├── chunk-4f09fed2.d107437b.js
│   │       │                   ├── chunk-4f09fed2.ff28d88d.js
│   │       │                   ├── chunk-55380ff2.430ee174.js
│   │       │                   ├── chunk-55380ff2.681c71c9.js
│   │       │                   ├── chunk-5afa45f5.79ddcc04.js
│   │       │                   ├── chunk-5b373aad.90a2d8e7.js
│   │       │                   ├── chunk-69386cf0.76d77f5c.js
│   │       │                   ├── chunk-69386cf0.bdbe3f0c.js
│   │       │                   ├── chunk-7ec889b7.5f730d9b.js
│   │       │                   ├── chunk-7ec889b7.bd1ca803.js
│   │       │                   ├── chunk-98f505d0.f3096ce7.js
│   │       │                   ├── chunk-bd1d44ee.8c8282cc.js
│   │       │                   ├── chunk-bd1d44ee.8e2c4851.js
│   │       │                   ├── chunk-da289616.7def925e.js
│   │       │                   ├── chunk-elementUI.667f4c87.js
│   │       │                   └── chunk-libs.c04beefc.js
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── alibaba/
│   │                       └── otter/
│   │                           └── canal/
│   │                               └── admin/
│   │                                   └── SimpleAdminConnectorTest.java
│   └── pom.xml
├── charts/
│   ├── README.md
│   ├── canal-admin/
│   │   ├── .helmignore
│   │   ├── Chart.yaml
│   │   ├── templates/
│   │   │   ├── NOTES.txt
│   │   │   ├── _helpers.tpl
│   │   │   ├── deployment.yaml
│   │   │   ├── hpa.yaml
│   │   │   ├── ingress.yaml
│   │   │   ├── secret.yaml
│   │   │   ├── service.yaml
│   │   │   ├── serviceaccount.yaml
│   │   │   └── tests/
│   │   │       └── test-connection.yaml
│   │   └── values.yaml
│   ├── canal-server/
│   │   ├── .helmignore
│   │   ├── Chart.yaml
│   │   ├── templates/
│   │   │   ├── NOTES.txt
│   │   │   ├── _helpers.tpl
│   │   │   ├── hpa.yaml
│   │   │   ├── secret.yaml
│   │   │   ├── service.yaml
│   │   │   ├── serviceaccount.yaml
│   │   │   ├── statefulsets.yaml
│   │   │   └── tests/
│   │   │       └── test-connection.yaml
│   │   └── values.yaml
│   └── tests/
│       ├── admin-values.yaml
│       ├── server-values.yaml
│       └── test.sh
├── client/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── alibaba/
│       │               └── otter/
│       │                   └── canal/
│       │                       └── client/
│       │                           ├── CanalConnector.java
│       │                           ├── CanalConnectors.java
│       │                           ├── CanalMQConnector.java
│       │                           ├── CanalMessageDeserializer.java
│       │                           ├── CanalNodeAccessStrategy.java
│       │                           ├── ConsumerBatchMessage.java
│       │                           ├── impl/
│       │                           │   ├── ClusterCanalConnector.java
│       │                           │   ├── ClusterNodeAccessStrategy.java
│       │                           │   ├── ServerNotFoundException.java
│       │                           │   ├── SimpleCanalConnector.java
│       │                           │   ├── SimpleNodeAccessStrategy.java
│       │                           │   └── running/
│       │                           │       ├── ClientRunningData.java
│       │                           │       ├── ClientRunningListener.java
│       │                           │       └── ClientRunningMonitor.java
│       │                           ├── kafka/
│       │                           │   ├── KafkaCanalConnector.java
│       │                           │   ├── KafkaOffsetCanalConnector.java
│       │                           │   ├── MessageDeserializer.java
│       │                           │   └── protocol/
│       │                           │       ├── KafkaFlatMessage.java
│       │                           │       └── KafkaMessage.java
│       │                           ├── pulsarmq/
│       │                           │   └── PulsarMQCanalConnector.java
│       │                           ├── rabbitmq/
│       │                           │   ├── AliyunCredentialsProvider.java
│       │                           │   └── RabbitMQCanalConnector.java
│       │                           └── rocketmq/
│       │                               └── RocketMQCanalConnector.java
│       └── test/
│           └── java/
│               ├── com/
│               │   └── alibaba/
│               │       └── otter/
│               │           └── canal/
│               │               └── client/
│               │                   └── running/
│               │                       ├── AbstractZkTest.java
│               │                       └── ClientRunningTest.java
│               └── logback.xml
├── client-adapter/
│   ├── README.md
│   ├── clickhouse/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   ├── java/
│   │       │   │   └── com/
│   │       │   │       └── alibaba/
│   │       │   │           └── otter/
│   │       │   │               └── canal/
│   │       │   │                   └── client/
│   │       │   │                       └── adapter/
│   │       │   │                           └── clickhouse/
│   │       │   │                               ├── ClickHouseAdapter.java
│   │       │   │                               ├── config/
│   │       │   │                               │   ├── ConfigLoader.java
│   │       │   │                               │   ├── MappingConfig.java
│   │       │   │                               │   └── MirrorDbConfig.java
│   │       │   │                               ├── monitor/
│   │       │   │                               │   └── ClickHouseConfigMonitor.java
│   │       │   │                               ├── service/
│   │       │   │                               │   ├── ClickHouseBatchSyncService.java
│   │       │   │                               │   ├── ClickHouseEtlService.java
│   │       │   │                               │   └── ClickHouseMirrorDbBatchSyncService.java
│   │       │   │                               └── support/
│   │       │   │                                   ├── BatchExecutor.java
│   │       │   │                                   ├── SingleDml.java
│   │       │   │                                   └── SyncUtil.java
│   │       │   └── resources/
│   │       │       ├── META-INF/
│   │       │       │   └── canal/
│   │       │       │       └── com.alibaba.otter.canal.client.adapter.OuterAdapter
│   │       │       └── clickhouse/
│   │       │           └── mytest_user.yml
│   │       └── test/
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── alibaba/
│   │           │           └── otter/
│   │           │               └── canal/
│   │           │                   └── client/
│   │           │                       └── adapter/
│   │           │                           └── clickhouse/
│   │           │                               ├── ClickHouseBatchSyncServiceTest.java
│   │           │                               ├── ClickHouseBatchSyncThreadSafeTest.java
│   │           │                               ├── TestConstant.java
│   │           │                               └── sync/
│   │           │                                   └── Common.java
│   │           └── resources/
│   │               └── clickhouse/
│   │                   ├── mytest_customer.yml
│   │                   └── mytest_user.yml
│   ├── common/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       └── com/
│   │       │           └── alibaba/
│   │       │               └── otter/
│   │       │                   └── canal/
│   │       │                       └── client/
│   │       │                           └── adapter/
│   │       │                               ├── OuterAdapter.java
│   │       │                               ├── ProxyOuterAdapter.java
│   │       │                               └── support/
│   │       │                                   ├── AbstractEtlService.java
│   │       │                                   ├── AdapterConfig.java
│   │       │                                   ├── CanalClientConfig.java
│   │       │                                   ├── Constant.java
│   │       │                                   ├── DaemonThreadFactory.java
│   │       │                                   ├── DatasourceConfig.java
│   │       │                                   ├── Dml.java
│   │       │                                   ├── EtlResult.java
│   │       │                                   ├── ExtensionLoader.java
│   │       │                                   ├── FileName2KeyMapping.java
│   │       │                                   ├── JdbcTypeUtil.java
│   │       │                                   ├── MappingConfigsLoader.java
│   │       │                                   ├── MessageUtil.java
│   │       │                                   ├── OuterAdapterConfig.java
│   │       │                                   ├── Result.java
│   │       │                                   ├── SPI.java
│   │       │                                   ├── URLClassExtensionLoader.java
│   │       │                                   ├── Util.java
│   │       │                                   └── YamlUtils.java
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── alibaba/
│   │                       └── otter/
│   │                           └── canal/
│   │                               └── client/
│   │                                   └── adapter/
│   │                                       └── support/
│   │                                           ├── JdbcTypeUtilTest.java
│   │                                           ├── UtilTest.java
│   │                                           └── YamlUtilsTest.java
│   ├── es6x/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   ├── java/
│   │       │   │   ├── com/
│   │       │   │   │   └── alibaba/
│   │       │   │   │       └── otter/
│   │       │   │   │           └── canal/
│   │       │   │   │               └── client/
│   │       │   │   │                   └── adapter/
│   │       │   │   │                       └── es6x/
│   │       │   │   │                           ├── ES6xAdapter.java
│   │       │   │   │                           ├── etl/
│   │       │   │   │                           │   └── ESEtlService.java
│   │       │   │   │                           └── support/
│   │       │   │   │                               ├── ES6xTemplate.java
│   │       │   │   │                               └── ESConnection.java
│   │       │   │   └── org/
│   │       │   │       └── elasticsearch/
│   │       │   │           └── client/
│   │       │   │               ├── RequestConvertersExt.java
│   │       │   │               └── RestHighLevelClientExt.java
│   │       │   └── resources/
│   │       │       ├── META-INF/
│   │       │       │   └── canal/
│   │       │       │       └── com.alibaba.otter.canal.client.adapter.OuterAdapter
│   │       │       └── es6/
│   │       │           ├── biz_order.yml
│   │       │           ├── customer.yml
│   │       │           └── mytest_user.yml
│   │       └── test/
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── alibaba/
│   │           │           └── otter/
│   │           │               └── canal/
│   │           │                   └── client/
│   │           │                       └── adapter/
│   │           │                           └── es6x/
│   │           │                               └── test/
│   │           │                                   ├── ConfigLoadTest.java
│   │           │                                   ├── ESTest.java
│   │           │                                   ├── SqlParseTest.java
│   │           │                                   ├── TestConstant.java
│   │           │                                   └── sync/
│   │           │                                       ├── Common.java
│   │           │                                       ├── LabelSyncJoinSub2Test.java
│   │           │                                       ├── LabelSyncJoinSubTest.java
│   │           │                                       ├── RoleSyncJoinOne2Test.java
│   │           │                                       ├── RoleSyncJoinOneTest.java
│   │           │                                       ├── UserSyncJoinOneTest.java
│   │           │                                       ├── UserSyncSingleTest.java
│   │           │                                       ├── db_schema.sql
│   │           │                                       └── es_mapping.json
│   │           └── resources/
│   │               ├── es6/
│   │               │   └── mytest_user_single.yml
│   │               ├── log4j2-test.xml
│   │               └── logback-test.xml
│   ├── es7x/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   ├── java/
│   │       │   │   └── com/
│   │       │   │       └── alibaba/
│   │       │   │           └── otter/
│   │       │   │               └── canal/
│   │       │   │                   └── client/
│   │       │   │                       └── adapter/
│   │       │   │                           └── es7x/
│   │       │   │                               ├── ES7xAdapter.java
│   │       │   │                               ├── etl/
│   │       │   │                               │   └── ESEtlService.java
│   │       │   │                               └── support/
│   │       │   │                                   ├── ES7xTemplate.java
│   │       │   │                                   └── ESConnection.java
│   │       │   └── resources/
│   │       │       ├── META-INF/
│   │       │       │   └── canal/
│   │       │       │       └── com.alibaba.otter.canal.client.adapter.OuterAdapter
│   │       │       └── es7/
│   │       │           ├── biz_order.yml
│   │       │           ├── customer.yml
│   │       │           └── mytest_user.yml
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── alibaba/
│   │                       └── otter/
│   │                           └── canal/
│   │                               └── client/
│   │                                   └── adapter/
│   │                                       └── es7x/
│   │                                           └── test/
│   │                                               ├── ES7xTest.java
│   │                                               ├── ESConnectionTest.java
│   │                                               └── TestConstant.java
│   ├── es8x/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   ├── java/
│   │       │   │   └── com/
│   │       │   │       └── alibaba/
│   │       │   │           └── otter/
│   │       │   │               └── canal/
│   │       │   │                   └── client/
│   │       │   │                       └── adapter/
│   │       │   │                           └── es8x/
│   │       │   │                               ├── ES8xAdapter.java
│   │       │   │                               ├── etl/
│   │       │   │                               │   └── ESEtlService.java
│   │       │   │                               └── support/
│   │       │   │                                   ├── ES8xTemplate.java
│   │       │   │                                   └── ESConnection.java
│   │       │   └── resources/
│   │       │       ├── META-INF/
│   │       │       │   └── canal/
│   │       │       │       └── com.alibaba.otter.canal.client.adapter.OuterAdapter
│   │       │       └── es8/
│   │       │           ├── biz_order.yml
│   │       │           ├── customer.yml
│   │       │           └── mytest_user.yml
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── alibaba/
│   │                       └── otter/
│   │                           └── canal/
│   │                               └── client/
│   │                                   └── adapter/
│   │                                       └── es8x/
│   │                                           └── test/
│   │                                               ├── ESConnectionTest.java
│   │                                               └── TestConstant.java
│   ├── escore/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       └── com/
│   │       │           └── alibaba/
│   │       │               └── otter/
│   │       │                   └── canal/
│   │       │                       └── client/
│   │       │                           └── adapter/
│   │       │                               └── es/
│   │       │                                   └── core/
│   │       │                                       ├── ESAdapter.java
│   │       │                                       ├── config/
│   │       │                                       │   ├── ESSyncConfig.java
│   │       │                                       │   ├── ESSyncConfigLoader.java
│   │       │                                       │   ├── SchemaItem.java
│   │       │                                       │   └── SqlParser.java
│   │       │                                       ├── monitor/
│   │       │                                       │   └── ESConfigMonitor.java
│   │       │                                       ├── service/
│   │       │                                       │   └── ESSyncService.java
│   │       │                                       └── support/
│   │       │                                           ├── ESBulkRequest.java
│   │       │                                           ├── ESSyncUtil.java
│   │       │                                           └── ESTemplate.java
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── alibaba/
│   │                       └── otter/
│   │                           └── canal/
│   │                               └── client/
│   │                                   └── adapter/
│   │                                       └── es/
│   │                                           └── core/
│   │                                               └── support/
│   │                                                   └── ESSyncUtilTest.java
│   ├── hbase/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   ├── java/
│   │       │   │   └── com/
│   │       │   │       └── alibaba/
│   │       │   │           └── otter/
│   │       │   │               └── canal/
│   │       │   │                   └── client/
│   │       │   │                       └── adapter/
│   │       │   │                           └── hbase/
│   │       │   │                               ├── HbaseAdapter.java
│   │       │   │                               ├── config/
│   │       │   │                               │   ├── MappingConfig.java
│   │       │   │                               │   └── MappingConfigLoader.java
│   │       │   │                               ├── monitor/
│   │       │   │                               │   └── HbaseConfigMonitor.java
│   │       │   │                               ├── service/
│   │       │   │                               │   ├── HbaseEtlService.java
│   │       │   │                               │   └── HbaseSyncService.java
│   │       │   │                               └── support/
│   │       │   │                                   ├── HRow.java
│   │       │   │                                   ├── HbaseTemplate.java
│   │       │   │                                   ├── PhType.java
│   │       │   │                                   ├── PhTypeUtil.java
│   │       │   │                                   ├── Type.java
│   │       │   │                                   └── TypeUtil.java
│   │       │   └── resources/
│   │       │       ├── META-INF/
│   │       │       │   └── canal/
│   │       │       │       └── com.alibaba.otter.canal.client.adapter.OuterAdapter
│   │       │       └── hbase/
│   │       │           └── mytest_person2.yml
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── alibaba/
│   │                       └── otter/
│   │                           └── canal/
│   │                               └── client/
│   │                                   └── adapter/
│   │                                       └── hbase/
│   │                                           └── test/
│   │                                               └── HBaseConnectionTest.java
│   ├── kudu/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   ├── java/
│   │       │   │   └── com/
│   │       │   │       └── alibaba/
│   │       │   │           └── otter/
│   │       │   │               └── canal/
│   │       │   │                   └── client/
│   │       │   │                       └── adapter/
│   │       │   │                           └── kudu/
│   │       │   │                               ├── KuduAdapter.java
│   │       │   │                               ├── config/
│   │       │   │                               │   ├── KuduMappingConfig.java
│   │       │   │                               │   └── KuduMappingConfigLoader.java
│   │       │   │                               ├── monitor/
│   │       │   │                               │   └── KuduConfigMonitor.java
│   │       │   │                               ├── service/
│   │       │   │                               │   ├── KuduEtlService.java
│   │       │   │                               │   └── KuduSyncService.java
│   │       │   │                               └── support/
│   │       │   │                                   ├── KuduTemplate.java
│   │       │   │                                   └── SyncUtil.java
│   │       │   └── resources/
│   │       │       ├── META-INF.canal/
│   │       │       │   └── com.alibaba.otter.canal.client.adapter.OuterAdapter
│   │       │       └── kudu/
│   │       │           └── kudutest_user.yml
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── alibaba/
│   │                       └── otter/
│   │                           └── canal/
│   │                               └── client/
│   │                                   └── adapter/
│   │                                       └── kudu/
│   │                                           └── test/
│   │                                               ├── KuduConnectionTest.java
│   │                                               ├── TestConfig.java
│   │                                               ├── TestConstant.java
│   │                                               └── sync/
│   │                                                   ├── Common.java
│   │                                                   └── TestSyncKudu.java
│   ├── launcher/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           ├── assembly/
│   │           │   ├── dev.xml
│   │           │   └── release.xml
│   │           ├── bin/
│   │           │   ├── restart.sh
│   │           │   ├── startup.bat
│   │           │   ├── startup.sh
│   │           │   └── stop.sh
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── alibaba/
│   │           │           └── otter/
│   │           │               └── canal/
│   │           │                   └── adapter/
│   │           │                       └── launcher/
│   │           │                           ├── CanalAdapterApplication.java
│   │           │                           ├── common/
│   │           │                           │   ├── EtlLock.java
│   │           │                           │   ├── Mode.java
│   │           │                           │   └── SyncSwitch.java
│   │           │                           ├── config/
│   │           │                           │   ├── AdapterCanalConfig.java
│   │           │                           │   ├── AdapterConfigHolder.java
│   │           │                           │   ├── BootstrapConfiguration.java
│   │           │                           │   ├── CuratorClient.java
│   │           │                           │   ├── DruidConfig.java
│   │           │                           │   └── SpringContext.java
│   │           │                           ├── loader/
│   │           │                           │   ├── AdapterProcessor.java
│   │           │                           │   ├── CanalAdapterLoader.java
│   │           │                           │   └── CanalAdapterService.java
│   │           │                           ├── monitor/
│   │           │                           │   ├── ApplicationConfigMonitor.java
│   │           │                           │   └── remote/
│   │           │                           │       ├── ConfigItem.java
│   │           │                           │       ├── DbRemoteConfigLoader.java
│   │           │                           │       ├── RemoteAdapterMonitor.java
│   │           │                           │       ├── RemoteAdapterMonitorImpl.java
│   │           │                           │       ├── RemoteConfigLoader.java
│   │           │                           │       └── RemoteConfigLoaderFactory.java
│   │           │                           ├── prometheus/
│   │           │                           │   ├── CanalAdapterExports.java
│   │           │                           │   └── PrometheusService.java
│   │           │                           └── rest/
│   │           │                               └── CommonRest.java
│   │           └── resources/
│   │               ├── META-INF/
│   │               │   └── spring.factories
│   │               ├── application.yml
│   │               ├── bootstrap.yml
│   │               └── logback.xml
│   ├── logger/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── alibaba/
│   │           │           └── otter/
│   │           │               └── canal/
│   │           │                   └── client/
│   │           │                       └── adapter/
│   │           │                           └── logger/
│   │           │                               └── LoggerAdapterExample.java
│   │           └── resources/
│   │               └── META-INF/
│   │                   └── canal/
│   │                       └── com.alibaba.otter.canal.client.adapter.OuterAdapter
│   ├── phoenix/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   ├── java/
│   │       │   │   └── com/
│   │       │   │       └── alibaba/
│   │       │   │           └── otter/
│   │       │   │               └── canal/
│   │       │   │                   └── client/
│   │       │   │                       └── adapter/
│   │       │   │                           └── phoenix/
│   │       │   │                               ├── PhoenixAdapter.java
│   │       │   │                               ├── config/
│   │       │   │                               │   ├── ConfigLoader.java
│   │       │   │                               │   ├── ConfigurationManager.java
│   │       │   │                               │   └── MappingConfig.java
│   │       │   │                               ├── monitor/
│   │       │   │                               │   └── PhoenixConfigMonitor.java
│   │       │   │                               ├── service/
│   │       │   │                               │   ├── PhoenixEtlService.java
│   │       │   │                               │   └── PhoenixSyncService.java
│   │       │   │                               └── support/
│   │       │   │                                   ├── BatchExecutor.java
│   │       │   │                                   ├── PhoenixSupportUtil.java
│   │       │   │                                   ├── SingleDml.java
│   │       │   │                                   ├── SyncUtil.java
│   │       │   │                                   └── TypeUtil.java
│   │       │   └── resources/
│   │       │       ├── META-INF/
│   │       │       │   └── canal/
│   │       │       │       └── com.alibaba.otter.canal.client.adapter.OuterAdapter
│   │       │       ├── hbase-site.xml
│   │       │       └── phoenix/
│   │       │           ├── phoenix_common.properties
│   │       │           └── phoenixtest_user.yml
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── alibaba/
│   │                       └── otter/
│   │                           └── canal/
│   │                               └── client/
│   │                                   └── adapter/
│   │                                       └── phoenix/
│   │                                           └── test/
│   │                                               ├── PhoenixConnectionTest.java
│   │                                               ├── TestConfigLoad.java
│   │                                               ├── TestConstant.java
│   │                                               └── sync/
│   │                                                   ├── Common.java
│   │                                                   └── PhoenixSyncTest.java
│   ├── pom.xml
│   ├── rdb/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   ├── java/
│   │       │   │   └── com/
│   │       │   │       └── alibaba/
│   │       │   │           └── otter/
│   │       │   │               └── canal/
│   │       │   │                   └── client/
│   │       │   │                       └── adapter/
│   │       │   │                           └── rdb/
│   │       │   │                               ├── RdbAdapter.java
│   │       │   │                               ├── config/
│   │       │   │                               │   ├── ConfigLoader.java
│   │       │   │                               │   ├── MappingConfig.java
│   │       │   │                               │   └── MirrorDbConfig.java
│   │       │   │                               ├── monitor/
│   │       │   │                               │   └── RdbConfigMonitor.java
│   │       │   │                               ├── service/
│   │       │   │                               │   ├── RdbEtlService.java
│   │       │   │                               │   ├── RdbMirrorDbSyncService.java
│   │       │   │                               │   └── RdbSyncService.java
│   │       │   │                               └── support/
│   │       │   │                                   ├── BatchExecutor.java
│   │       │   │                                   ├── SingleDml.java
│   │       │   │                                   └── SyncUtil.java
│   │       │   └── resources/
│   │       │       ├── META-INF/
│   │       │       │   └── canal/
│   │       │       │       └── com.alibaba.otter.canal.client.adapter.OuterAdapter
│   │       │       └── rdb/
│   │       │           └── mytest_user.yml
│   │       └── test/
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── alibaba/
│   │           │           └── otter/
│   │           │               └── canal/
│   │           │                   └── client/
│   │           │                       └── adapter/
│   │           │                           └── rdb/
│   │           │                               └── test/
│   │           │                                   ├── ConfigLoadTest.java
│   │           │                                   ├── DBTest.java
│   │           │                                   ├── SqlParserTest.java
│   │           │                                   ├── TestConstant.java
│   │           │                                   └── sync/
│   │           │                                       ├── Common.java
│   │           │                                       └── OracleSyncTest.java
│   │           └── resources/
│   │               ├── log4j2-test.xml
│   │               ├── logback-test.xml
│   │               └── rdb/
│   │                   └── mytest_user.yml
│   └── tablestore/
│       ├── pom.xml
│       └── src/
│           └── main/
│               ├── java/
│               │   └── com/
│               │       └── alibaba/
│               │           └── otter/
│               │               └── canal/
│               │                   └── client/
│               │                       └── adapter/
│               │                           └── tablestore/
│               │                               ├── TablestoreAdapter.java
│               │                               ├── common/
│               │                               │   └── PropertyConstants.java
│               │                               ├── config/
│               │                               │   ├── ConfigLoader.java
│               │                               │   └── MappingConfig.java
│               │                               ├── enums/
│               │                               │   └── TablestoreFieldType.java
│               │                               ├── service/
│               │                               │   ├── TablestoreEtlService.java
│               │                               │   └── TablestoreSyncService.java
│               │                               └── support/
│               │                                   └── SyncUtil.java
│               └── resources/
│                   ├── META-INF/
│                   │   └── canal/
│                   │       └── com.alibaba.otter.canal.client.adapter.OuterAdapter
│                   └── tablestore/
│                       └── test.yml
├── codeformat.xml
├── codetemplates.xml
├── common/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           ├── alibaba/
│       │           │   └── otter/
│       │           │       └── canal/
│       │           │           └── common/
│       │           │               ├── AbstractCanalLifeCycle.java
│       │           │               ├── CanalException.java
│       │           │               ├── CanalLifeCycle.java
│       │           │               ├── alarm/
│       │           │               │   ├── CanalAlarmHandler.java
│       │           │               │   └── LogAlarmHandler.java
│       │           │               ├── utils/
│       │           │               │   ├── AddressUtils.java
│       │           │               │   ├── BooleanMutex.java
│       │           │               │   ├── CanalToStringStyle.java
│       │           │               │   ├── CommonUtils.java
│       │           │               │   ├── ExecutorTemplate.java
│       │           │               │   ├── FileUtils.java
│       │           │               │   ├── JsonUtils.java
│       │           │               │   ├── MQUtil.java
│       │           │               │   ├── NamedThreadFactory.java
│       │           │               │   ├── PropertiesUtils.java
│       │           │               │   └── UriUtils.java
│       │           │               └── zookeeper/
│       │           │                   ├── ByteSerializer.java
│       │           │                   ├── StringSerializer.java
│       │           │                   ├── ZkClientx.java
│       │           │                   ├── ZooKeeperx.java
│       │           │                   ├── ZookeeperPathUtils.java
│       │           │                   └── running/
│       │           │                       ├── ServerRunningData.java
│       │           │                       ├── ServerRunningListener.java
│       │           │                       ├── ServerRunningMonitor.java
│       │           │                       └── ServerRunningMonitors.java
│       │           └── google/
│       │               └── common/
│       │                   └── collect/
│       │                       └── MigrateMap.java
│       └── test/
│           └── java/
│               ├── com/
│               │   └── alibaba/
│               │       └── otter/
│               │           └── canal/
│               │               └── common/
│               │                   ├── AbstractZkTest.java
│               │                   ├── JsonUtilsTest.java
│               │                   ├── ServerRunningTest.java
│               │                   └── utils/
│               │                       └── BooleanMutexTest.java
│               └── logback.xml
├── connector/
│   ├── core/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           └── java/
│   │               └── com/
│   │                   └── alibaba/
│   │                       └── otter/
│   │                           └── canal/
│   │                               └── connector/
│   │                                   └── core/
│   │                                       ├── config/
│   │                                       │   ├── CanalConstants.java
│   │                                       │   └── MQProperties.java
│   │                                       ├── consumer/
│   │                                       │   └── CommonMessage.java
│   │                                       ├── filter/
│   │                                       │   ├── AviaterRegexFilter.java
│   │                                       │   ├── PatternUtils.java
│   │                                       │   └── RegexFunction.java
│   │                                       ├── producer/
│   │                                       │   ├── AbstractMQProducer.java
│   │                                       │   ├── MQDestination.java
│   │                                       │   └── MQMessageUtils.java
│   │                                       ├── spi/
│   │                                       │   ├── CanalMQProducer.java
│   │                                       │   ├── CanalMsgConsumer.java
│   │                                       │   ├── ExtensionLoader.java
│   │                                       │   ├── ProxyCanalMQProducer.java
│   │                                       │   ├── ProxyCanalMsgConsumer.java
│   │                                       │   ├── SPI.java
│   │                                       │   └── URLClassExtensionLoader.java
│   │                                       └── util/
│   │                                           ├── Callback.java
│   │                                           ├── CanalMessageSerializerUtil.java
│   │                                           ├── DateUtil.java
│   │                                           ├── JdbcTypeUtil.java
│   │                                           ├── MessageUtil.java
│   │                                           └── TimeZone.java
│   ├── kafka-connector/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   ├── java/
│   │       │   │   └── com/
│   │       │   │       └── alibaba/
│   │       │   │           └── otter/
│   │       │   │               └── canal/
│   │       │   │                   └── connector/
│   │       │   │                       └── kafka/
│   │       │   │                           ├── config/
│   │       │   │                           │   ├── KafkaConstants.java
│   │       │   │                           │   └── KafkaProducerConfig.java
│   │       │   │                           ├── consumer/
│   │       │   │                           │   ├── CanalKafkaConsumer.java
│   │       │   │                           │   └── KafkaMessageDeserializer.java
│   │       │   │                           └── producer/
│   │       │   │                               ├── CanalKafkaProducer.java
│   │       │   │                               └── KafkaMessageSerializer.java
│   │       │   └── resources/
│   │       │       └── META-INF/
│   │       │           └── canal/
│   │       │               ├── com.alibaba.otter.canal.connector.core.spi.CanalMQProducer
│   │       │               └── com.alibaba.otter.canal.connector.core.spi.CanalMsgConsumer
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── alibaba/
│   │                       └── otter/
│   │                           └── canal/
│   │                               └── connector/
│   │                                   └── kafka/
│   │                                       └── test/
│   │                                           └── CanalKafkaProducerTest.java
│   ├── pom.xml
│   ├── pulsarmq-connector/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   ├── java/
│   │       │   │   └── com/
│   │       │   │       └── alibaba/
│   │       │   │           └── otter/
│   │       │   │               └── canal/
│   │       │   │                   └── connector/
│   │       │   │                       └── pulsarmq/
│   │       │   │                           ├── config/
│   │       │   │                           │   ├── PulsarMQConstants.java
│   │       │   │                           │   └── PulsarMQProducerConfig.java
│   │       │   │                           ├── consumer/
│   │       │   │                           │   └── CanalPulsarMQConsumer.java
│   │       │   │                           └── producer/
│   │       │   │                               └── CanalPulsarMQProducer.java
│   │       │   └── resources/
│   │       │       └── META-INF/
│   │       │           └── canal/
│   │       │               ├── com.alibaba.otter.canal.connector.core.spi.CanalMQProducer
│   │       │               └── com.alibaba.otter.canal.connector.core.spi.CanalMsgConsumer
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── alibaba/
│   │                       └── otter/
│   │                           └── canal/
│   │                               └── connector/
│   │                                   └── pulsarmq/
│   │                                       └── consumer/
│   │                                           └── CanalPulsarMQConsumerTest.java
│   ├── rabbitmq-connector/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── alibaba/
│   │           │           └── otter/
│   │           │               └── canal/
│   │           │                   └── connector/
│   │           │                       └── rabbitmq/
│   │           │                           ├── config/
│   │           │                           │   ├── RabbitMQConstants.java
│   │           │                           │   └── RabbitMQProducerConfig.java
│   │           │                           ├── consumer/
│   │           │                           │   ├── CanalRabbitMQConsumer.java
│   │           │                           │   └── ConsumerBatchMessage.java
│   │           │                           └── producer/
│   │           │                               ├── AliyunCredentialsProvider.java
│   │           │                               └── CanalRabbitMQProducer.java
│   │           └── resources/
│   │               └── META-INF/
│   │                   └── canal/
│   │                       ├── com.alibaba.otter.canal.connector.core.spi.CanalMQProducer
│   │                       └── com.alibaba.otter.canal.connector.core.spi.CanalMsgConsumer
│   ├── rocketmq-connector/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── alibaba/
│   │           │           └── otter/
│   │           │               └── canal/
│   │           │                   └── connector/
│   │           │                       └── rocketmq/
│   │           │                           ├── config/
│   │           │                           │   ├── RocketMQConstants.java
│   │           │                           │   └── RocketMQProducerConfig.java
│   │           │                           ├── consumer/
│   │           │                           │   ├── CanalRocketMQConsumer.java
│   │           │                           │   └── ConsumerBatchMessage.java
│   │           │                           └── producer/
│   │           │                               └── CanalRocketMQProducer.java
│   │           └── resources/
│   │               └── META-INF/
│   │                   └── canal/
│   │                       ├── com.alibaba.otter.canal.connector.core.spi.CanalMQProducer
│   │                       └── com.alibaba.otter.canal.connector.core.spi.CanalMsgConsumer
│   └── tcp-connector/
│       ├── pom.xml
│       └── src/
│           └── main/
│               ├── java/
│               │   └── com/
│               │       └── alibaba/
│               │           └── otter/
│               │               └── canal/
│               │                   └── connector/
│               │                       └── tcp/
│               │                           ├── config/
│               │                           │   └── TCPConstants.java
│               │                           └── consumer/
│               │                               └── CanalTCPConsumer.java
│               └── resources/
│                   └── META-INF/
│                       └── canal/
│                           └── com.alibaba.otter.canal.connector.core.spi.CanalMsgConsumer
├── dbsync/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── taobao/
│       │               └── tddl/
│       │                   └── dbsync/
│       │                       └── binlog/
│       │                           ├── CharsetConversion.java
│       │                           ├── DirectLogFetcher.java
│       │                           ├── FileLogFetcher.java
│       │                           ├── JsonConversion.java
│       │                           ├── JsonDiffConversion.java
│       │                           ├── LogBuffer.java
│       │                           ├── LogContext.java
│       │                           ├── LogDecoder.java
│       │                           ├── LogEvent.java
│       │                           ├── LogFetcher.java
│       │                           ├── LogPosition.java
│       │                           ├── NameCache.java
│       │                           ├── event/
│       │                           │   ├── AppendBlockLogEvent.java
│       │                           │   ├── BeginLoadQueryLogEvent.java
│       │                           │   ├── CreateFileLogEvent.java
│       │                           │   ├── DeleteFileLogEvent.java
│       │                           │   ├── DeleteRowsLogEvent.java
│       │                           │   ├── ExecuteLoadLogEvent.java
│       │                           │   ├── ExecuteLoadQueryLogEvent.java
│       │                           │   ├── FormatDescriptionLogEvent.java
│       │                           │   ├── GtidLogEvent.java
│       │                           │   ├── HeartbeatLogEvent.java
│       │                           │   ├── HeartbeatV2LogEvent.java
│       │                           │   ├── IgnorableLogEvent.java
│       │                           │   ├── IncidentLogEvent.java
│       │                           │   ├── IntvarLogEvent.java
│       │                           │   ├── LoadLogEvent.java
│       │                           │   ├── LogHeader.java
│       │                           │   ├── PreviousGtidsLogEvent.java
│       │                           │   ├── QueryLogEvent.java
│       │                           │   ├── RandLogEvent.java
│       │                           │   ├── RotateLogEvent.java
│       │                           │   ├── RowsLogBuffer.java
│       │                           │   ├── RowsLogEvent.java
│       │                           │   ├── RowsQueryLogEvent.java
│       │                           │   ├── StartLogEventV3.java
│       │                           │   ├── StopLogEvent.java
│       │                           │   ├── TableMapLogEvent.java
│       │                           │   ├── TransactionContextLogEvent.java
│       │                           │   ├── TransactionPayloadLogEvent.java
│       │                           │   ├── UnknownLogEvent.java
│       │                           │   ├── UpdateRowsLogEvent.java
│       │                           │   ├── UserVarLogEvent.java
│       │                           │   ├── ViewChangeEvent.java
│       │                           │   ├── WriteRowsLogEvent.java
│       │                           │   ├── XaPrepareLogEvent.java
│       │                           │   ├── XidLogEvent.java
│       │                           │   └── mariadb/
│       │                           │       ├── AnnotateRowsEvent.java
│       │                           │       ├── BinlogCheckPointLogEvent.java
│       │                           │       ├── DeleteRowsCompressLogEvent.java
│       │                           │       ├── MariaGtidListLogEvent.java
│       │                           │       ├── MariaGtidLogEvent.java
│       │                           │       ├── QueryCompressedLogEvent.java
│       │                           │       ├── StartEncryptionLogEvent.java
│       │                           │       ├── UpdateRowsCompressLogEvent.java
│       │                           │       └── WriteRowsCompressLogEvent.java
│       │                           └── exception/
│       │                               └── TableIdNotFoundException.java
│       └── test/
│           ├── java/
│           │   └── com/
│           │       └── taobao/
│           │           └── tddl/
│           │               └── dbsync/
│           │                   ├── FetcherPerformanceTest.java
│           │                   └── binlog/
│           │                       ├── BaseLogFetcherTest.java
│           │                       ├── DirectLogFetcherTest.java
│           │                       ├── FileLogFetcherTest.java
│           │                       ├── JsonConversion_Json_ValueTest.java
│           │                       ├── JsonDiffConversionTest.java
│           │                       ├── LogEventTest.java
│           │                       └── event/
│           │                           └── LogHeaderTest.java
│           └── resources/
│               ├── binlog/
│               │   └── mysql-bin.000001
│               └── dummy.txt
├── deployer/
│   ├── pom.xml
│   └── src/
│       └── main/
│           ├── assembly/
│           │   ├── dev.xml
│           │   └── release.xml
│           ├── bin/
│           │   ├── restart.sh
│           │   ├── startup.bat
│           │   ├── startup.sh
│           │   └── stop.sh
│           ├── java/
│           │   └── com/
│           │       └── alibaba/
│           │           └── otter/
│           │               └── canal/
│           │                   └── deployer/
│           │                       ├── CanalConstants.java
│           │                       ├── CanalController.java
│           │                       ├── CanalLauncher.java
│           │                       ├── CanalStarter.java
│           │                       ├── InstanceConfig.java
│           │                       ├── admin/
│           │                       │   └── CanalAdminController.java
│           │                       └── monitor/
│           │                           ├── InstanceAction.java
│           │                           ├── InstanceConfigMonitor.java
│           │                           ├── ManagerInstanceConfigMonitor.java
│           │                           └── SpringInstanceConfigMonitor.java
│           └── resources/
│               ├── canal.properties
│               ├── canal_local.properties
│               ├── example/
│               │   └── instance.properties
│               ├── logback.xml
│               ├── metrics/
│               │   └── Canal_instances_tmpl.json
│               └── spring/
│                   ├── base-instance.xml
│                   ├── default-instance.xml
│                   ├── file-instance.xml
│                   ├── group-instance.xml
│                   ├── memory-instance.xml
│                   └── tsdb/
│                       ├── h2-tsdb.xml
│                       ├── mysql-tsdb.xml
│                       ├── sql/
│                       │   └── create_table.sql
│                       └── sql-map/
│                           ├── sqlmap-config.xml
│                           ├── sqlmap_history.xml
│                           └── sqlmap_snapshot.xml
├── docker/
│   ├── Dockerfile
│   ├── Dockerfile_admin
│   ├── base/
│   │   ├── README.md
│   │   ├── amd64/
│   │   │   ├── Dockerfile
│   │   │   ├── Dockerfile_admin
│   │   │   └── yum/
│   │   │       └── CentOS-Base.repo
│   │   └── arm64/
│   │       ├── Dockerfile
│   │       ├── Dockerfile_admin
│   │       └── yum/
│   │           └── CentOS-Base.repo
│   ├── build.sh
│   ├── image/
│   │   ├── admin/
│   │   │   ├── bin/
│   │   │   │   ├── clean_log
│   │   │   │   └── clean_log.sh
│   │   │   └── health.sh
│   │   ├── alidata/
│   │   │   ├── bin/
│   │   │   │   ├── exec_rc_local.sh
│   │   │   │   ├── lark-wait
│   │   │   │   └── main.sh
│   │   │   ├── init/
│   │   │   │   ├── 02init-sshd.sh
│   │   │   │   └── fix-hosts.py
│   │   │   └── lib/
│   │   │       └── proc.sh
│   │   ├── app.sh
│   │   ├── app_admin.sh
│   │   └── canal_manager.sql
│   ├── run.sh
│   └── run_admin.sh
├── driver/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── alibaba/
│       │               └── otter/
│       │                   └── canal/
│       │                       └── parse/
│       │                           └── driver/
│       │                               └── mysql/
│       │                                   ├── MysqlConnector.java
│       │                                   ├── MysqlQueryExecutor.java
│       │                                   ├── MysqlUpdateExecutor.java
│       │                                   ├── packets/
│       │                                   │   ├── Capability.java
│       │                                   │   ├── CommandPacket.java
│       │                                   │   ├── GTIDSet.java
│       │                                   │   ├── HeaderPacket.java
│       │                                   │   ├── IPacket.java
│       │                                   │   ├── MariaGTIDSet.java
│       │                                   │   ├── MariaGtid.java
│       │                                   │   ├── MysqlGTIDSet.java
│       │                                   │   ├── PacketWithHeaderPacket.java
│       │                                   │   ├── UUIDSet.java
│       │                                   │   ├── client/
│       │                                   │   │   ├── AuthSwitchResponsePacket.java
│       │                                   │   │   ├── BinlogDumpCommandPacket.java
│       │                                   │   │   ├── BinlogDumpGTIDCommandPacket.java
│       │                                   │   │   ├── ClientAuthenticationPacket.java
│       │                                   │   │   ├── ClientAuthenticationSHA2Packet.java
│       │                                   │   │   ├── QueryCommandPacket.java
│       │                                   │   │   ├── QuitCommandPacket.java
│       │                                   │   │   ├── RegisterSlaveCommandPacket.java
│       │                                   │   │   ├── SemiAckCommandPacket.java
│       │                                   │   │   └── SslRequestCommandPacket.java
│       │                                   │   └── server/
│       │                                   │       ├── AuthSwitchRequestMoreData.java
│       │                                   │       ├── AuthSwitchRequestPacket.java
│       │                                   │       ├── DataPacket.java
│       │                                   │       ├── EOFPacket.java
│       │                                   │       ├── ErrorPacket.java
│       │                                   │       ├── FieldPacket.java
│       │                                   │       ├── HandshakeInitializationPacket.java
│       │                                   │       ├── OKPacket.java
│       │                                   │       ├── Reply323Packet.java
│       │                                   │       ├── ResultSetHeaderPacket.java
│       │                                   │       ├── ResultSetPacket.java
│       │                                   │       └── RowDataPacket.java
│       │                                   ├── socket/
│       │                                   │   ├── BioSocketChannel.java
│       │                                   │   ├── BioSocketChannelPool.java
│       │                                   │   ├── NettySocketChannel.java
│       │                                   │   ├── NettySocketChannelPool.java
│       │                                   │   ├── SocketChannel.java
│       │                                   │   └── SocketChannelPool.java
│       │                                   ├── ssl/
│       │                                   │   ├── SslInfo.java
│       │                                   │   └── SslMode.java
│       │                                   └── utils/
│       │                                       ├── BinlogDumpCommandBuilder.java
│       │                                       ├── ByteHelper.java
│       │                                       ├── ChannelBufferHelper.java
│       │                                       ├── CharsetUtil.java
│       │                                       ├── GtidUtil.java
│       │                                       ├── LengthCodedStringReader.java
│       │                                       ├── MSC.java
│       │                                       ├── MySQLPasswordEncrypter.java
│       │                                       └── PacketManager.java
│       └── test/
│           └── java/
│               └── com/
│                   └── alibaba/
│                       └── otter/
│                           └── canal/
│                               └── parse/
│                                   └── driver/
│                                       └── mysql/
│                                           ├── CharsetUtilTest.java
│                                           ├── MysqlConnectorTest.java
│                                           ├── MysqlGTIDSetTest.java
│                                           ├── UUIDSetTest.java
│                                           ├── packets/
│                                           │   └── client/
│                                           │       └── RegisterSlaveCommandPacketTest.java
│                                           └── utils/
│                                               ├── ByteHelperTest.java
│                                               └── MySQLPasswordEncrypterTest.java
├── example/
│   ├── pom.xml
│   └── src/
│       └── main/
│           ├── assembly/
│           │   ├── dev.xml
│           │   └── release.xml
│           ├── bin/
│           │   ├── init.sh
│           │   ├── startup.bat
│           │   ├── startup.sh
│           │   └── stop.sh
│           ├── java/
│           │   └── com/
│           │       └── alibaba/
│           │           └── otter/
│           │               └── canal/
│           │                   └── example/
│           │                       ├── AbstractCanalClientTest.java
│           │                       ├── BaseCanalClientTest.java
│           │                       ├── ClusterCanalClientTest.java
│           │                       ├── SimpleCanalClientPermanceTest.java
│           │                       ├── SimpleCanalClientTest.java
│           │                       ├── kafka/
│           │                       │   ├── AbstractKafkaTest.java
│           │                       │   ├── CanalKafkaClientExample.java
│           │                       │   ├── CanalKafkaClientFlatMessageExample.java
│           │                       │   ├── CanalKafkaOffsetClientExample.java
│           │                       │   └── KafkaClientRunningTest.java
│           │                       └── rocketmq/
│           │                           ├── AbstractRocektMQTest.java
│           │                           ├── CanalRocketMQClientExample.java
│           │                           └── CanalRocketMQClientFlatMessageExample.java
│           └── resources/
│               └── logback.xml
├── filter/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── alibaba/
│       │               └── otter/
│       │                   └── canal/
│       │                       └── filter/
│       │                           ├── CanalEventFilter.java
│       │                           ├── PatternUtils.java
│       │                           ├── aviater/
│       │                           │   ├── AviaterELFilter.java
│       │                           │   ├── AviaterRegexFilter.java
│       │                           │   ├── AviaterSimpleFilter.java
│       │                           │   └── RegexFunction.java
│       │                           └── exception/
│       │                               └── CanalFilterException.java
│       └── test/
│           └── java/
│               └── com/
│                   └── alibaba/
│                       └── otter/
│                           └── canal/
│                               └── filter/
│                                   ├── AviaterFilterTest.java
│                                   └── MutliAviaterFilterTest.java
├── instance/
│   ├── core/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           └── java/
│   │               └── com/
│   │                   └── alibaba/
│   │                       └── otter/
│   │                           └── canal/
│   │                               └── instance/
│   │                                   └── core/
│   │                                       ├── AbstractCanalInstance.java
│   │                                       ├── CanalInstance.java
│   │                                       ├── CanalInstanceGenerator.java
│   │                                       └── CanalMQConfig.java
│   ├── manager/
│   │   ├── pom.xml
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       └── com/
│   │       │           └── alibaba/
│   │       │               └── otter/
│   │       │                   └── canal/
│   │       │                       └── instance/
│   │       │                           └── manager/
│   │       │                               ├── CanalConfigClient.java
│   │       │                               ├── CanalInstanceWithManager.java
│   │       │                               ├── ManagerCanalInstanceGenerator.java
│   │       │                               ├── PlainCanalInstanceGenerator.java
│   │       │                               ├── model/
│   │       │                               │   ├── Canal.java
│   │       │                               │   ├── CanalParameter.java
│   │       │                               │   └── CanalStatus.java
│   │       │                               └── plain/
│   │       │                                   ├── HttpHelper.java
│   │       │                                   ├── PlainCanal.java
│   │       │                                   └── PlainCanalConfigClient.java
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── alibaba/
│   │                       └── otter/
│   │                           └── canal/
│   │                               └── instance/
│   │                                   └── manager/
│   │                                       └── PlainCanalConfigClientIntegration.java
│   ├── pom.xml
│   └── spring/
│       ├── pom.xml
│       └── src/
│           ├── main/
│           │   └── java/
│           │       └── com/
│           │           └── alibaba/
│           │               └── otter/
│           │                   └── canal/
│           │                       └── instance/
│           │                           └── spring/
│           │                               ├── CanalInstanceWithSpring.java
│           │                               ├── SpringCanalInstanceGenerator.java
│           │                               └── support/
│           │                                   ├── PropertyPlaceholderConfigurer.java
│           │                                   └── SocketAddressEditor.java
│           └── test/
│               ├── java/
│               │   └── com/
│               │       └── alibaba/
│               │           └── otter/
│               │               └── canal/
│               │                   └── instance/
│               │                       └── spring/
│               │                           └── integrated/
│               │                               ├── DefaultSpringInstanceTest.java
│               │                               ├── GroupSpringInstanceTest.java
│               │                               └── MemorySpringInstanceTest.java
│               └── resources/
│                   ├── canal.properties
│                   ├── retl/
│                   │   └── instance.properties
│                   └── spring/
│                       ├── default-instance.xml
│                       ├── file-instance.xml
│                       ├── group-instance.xml
│                       └── memory-instance.xml
├── meta/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── alibaba/
│       │               └── otter/
│       │                   └── canal/
│       │                       └── meta/
│       │                           ├── CanalMetaManager.java
│       │                           ├── FileMixedMetaManager.java
│       │                           ├── MemoryMetaManager.java
│       │                           ├── MixedMetaManager.java
│       │                           ├── PeriodMixedMetaManager.java
│       │                           ├── ZooKeeperMetaManager.java
│       │                           └── exception/
│       │                               └── CanalMetaManagerException.java
│       └── test/
│           └── java/
│               └── com/
│                   └── alibaba/
│                       └── otter/
│                           └── canal/
│                               └── meta/
│                                   ├── AbstractMetaManagerTest.java
│                                   ├── AbstractZkTest.java
│                                   ├── FileMixedMetaManagerTest.java
│                                   ├── MemoryMetaManagerTest.java
│                                   ├── MixedMetaManagerTest.java
│                                   ├── PeriodMixedMetaManagerTest.java
│                                   └── ZooKeeperMetaManagerTest.java
├── mvnw
├── parse/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── alibaba/
│       │   │           └── otter/
│       │   │               └── canal/
│       │   │                   └── parse/
│       │   │                       ├── CanalEventParser.java
│       │   │                       ├── CanalHASwitchable.java
│       │   │                       ├── exception/
│       │   │                       │   ├── CanalHAException.java
│       │   │                       │   ├── CanalParseException.java
│       │   │                       │   ├── PositionNotFoundException.java
│       │   │                       │   ├── ServerIdNotMatchException.java
│       │   │                       │   └── ServerLogPurgedException.java
│       │   │                       ├── ha/
│       │   │                       │   ├── CanalHAController.java
│       │   │                       │   └── HeartBeatHAController.java
│       │   │                       ├── inbound/
│       │   │                       │   ├── AbstractBinlogParser.java
│       │   │                       │   ├── AbstractEventParser.java
│       │   │                       │   ├── BinlogParser.java
│       │   │                       │   ├── ErosaConnection.java
│       │   │                       │   ├── EventTransactionBuffer.java
│       │   │                       │   ├── HeartBeatCallback.java
│       │   │                       │   ├── MultiStageCoprocessor.java
│       │   │                       │   ├── ParserExceptionHandler.java
│       │   │                       │   ├── SinkFunction.java
│       │   │                       │   ├── TableMeta.java
│       │   │                       │   ├── group/
│       │   │                       │   │   └── GroupEventParser.java
│       │   │                       │   └── mysql/
│       │   │                       │       ├── AbstractMysqlEventParser.java
│       │   │                       │       ├── DbsyncMysqlEventParser.java
│       │   │                       │       ├── LocalBinLogConnection.java
│       │   │                       │       ├── LocalBinlogEventParser.java
│       │   │                       │       ├── MysqlConnection.java
│       │   │                       │       ├── MysqlEventParser.java
│       │   │                       │       ├── MysqlMultiStageCoprocessor.java
│       │   │                       │       ├── SlaveEntryPosition.java
│       │   │                       │       ├── dbsync/
│       │   │                       │       │   ├── DirectLogFetcher.java
│       │   │                       │       │   ├── LogEventConvert.java
│       │   │                       │       │   └── TableMetaCache.java
│       │   │                       │       ├── ddl/
│       │   │                       │       │   ├── DdlResult.java
│       │   │                       │       │   ├── DruidDdlParser.java
│       │   │                       │       │   └── SimpleDdlParser.java
│       │   │                       │       ├── local/
│       │   │                       │       │   ├── BinLogFileQueue.java
│       │   │                       │       │   └── BufferedFileDataInput.java
│       │   │                       │       ├── rds/
│       │   │                       │       │   ├── BinlogDownloadQueue.java
│       │   │                       │       │   ├── HttpHelper.java
│       │   │                       │       │   ├── RdsBinlogEventParserProxy.java
│       │   │                       │       │   ├── RdsBinlogOpenApi.java
│       │   │                       │       │   ├── RdsLocalBinlogEventParser.java
│       │   │                       │       │   ├── data/
│       │   │                       │       │   │   ├── BinlogFile.java
│       │   │                       │       │   │   ├── DescribeBinlogFileResult.java
│       │   │                       │       │   │   ├── RdsBackupPolicy.java
│       │   │                       │       │   │   └── RdsItem.java
│       │   │                       │       │   └── request/
│       │   │                       │       │       ├── AbstractRequest.java
│       │   │                       │       │       ├── DescribeBackupPolicyRequest.java
│       │   │                       │       │       └── DescribeBinlogFilesRequest.java
│       │   │                       │       └── tsdb/
│       │   │                       │           ├── DatabaseTableMeta.java
│       │   │                       │           ├── DefaultTableMetaTSDBFactory.java
│       │   │                       │           ├── MemoryTableMeta.java
│       │   │                       │           ├── TableMetaTSDB.java
│       │   │                       │           ├── TableMetaTSDBBuilder.java
│       │   │                       │           ├── TableMetaTSDBFactory.java
│       │   │                       │           └── dao/
│       │   │                       │               ├── MetaBaseDAO.java
│       │   │                       │               ├── MetaHistoryDAO.java
│       │   │                       │               ├── MetaHistoryDO.java
│       │   │                       │               ├── MetaHistoryMapper.java
│       │   │                       │               ├── MetaSnapshotDAO.java
│       │   │                       │               ├── MetaSnapshotDO.java
│       │   │                       │               └── MetaSnapshotMapper.java
│       │   │                       ├── index/
│       │   │                       │   ├── AbstractLogPositionManager.java
│       │   │                       │   ├── CanalLogPositionManager.java
│       │   │                       │   ├── FailbackLogPositionManager.java
│       │   │                       │   ├── FileMixedLogPositionManager.java
│       │   │                       │   ├── MemoryLogPositionManager.java
│       │   │                       │   ├── MetaLogPositionManager.java
│       │   │                       │   ├── MixedLogPositionManager.java
│       │   │                       │   ├── PeriodMixedLogPositionManager.java
│       │   │                       │   └── ZooKeeperLogPositionManager.java
│       │   │                       └── support/
│       │   │                           ├── AuthenticationInfo.java
│       │   │                           └── HaAuthenticationInfo.java
│       │   └── resources/
│       │       └── ddl/
│       │           ├── derby/
│       │           │   ├── meta_history.sql
│       │           │   └── meta_snapshot.sql
│       │           ├── h2/
│       │           │   ├── meta_history.sql
│       │           │   └── meta_snapshot.sql
│       │           └── mysql/
│       │               ├── meta_history.sql
│       │               └── meta_snapshot.sql
│       └── test/
│           ├── java/
│           │   └── com/
│           │       └── alibaba/
│           │           └── otter/
│           │               └── canal/
│           │                   └── parse/
│           │                       ├── DirectLogFetcherTest.java
│           │                       ├── MysqlBinlogDumpPerformanceTest.java
│           │                       ├── MysqlBinlogEventPerformanceTest.java
│           │                       ├── MysqlBinlogParsePerformanceTest.java
│           │                       ├── helper/
│           │                       │   └── TimeoutChecker.java
│           │                       ├── inbound/
│           │                       │   ├── EventTransactionBufferTest.java
│           │                       │   ├── TableMetaCacheTest.java
│           │                       │   ├── group/
│           │                       │   │   ├── DummyEventStore.java
│           │                       │   │   └── GroupEventPaserTest.java
│           │                       │   └── mysql/
│           │                       │       ├── DruidDdlParserTest.java
│           │                       │       ├── LocalBinlogDumpTest.java
│           │                       │       ├── LocalBinlogEventParserTest.java
│           │                       │       ├── MysqlDumpTest.java
│           │                       │       ├── MysqlEventParserTest.java
│           │                       │       ├── RdsBinlogEventParserProxyTest.java
│           │                       │       ├── RdsBinlogOpenApiTest.java
│           │                       │       ├── RdsLocalBinlogDumpTest.java
│           │                       │       ├── SimpleDdlParserTest.java
│           │                       │       ├── ddl/
│           │                       │       │   └── DdlResultTest.java
│           │                       │       └── tsdb/
│           │                       │           ├── FastsqlSchemaTest.java
│           │                       │           ├── MemoryTableMetaTest.java
│           │                       │           ├── MemoryTableMeta_DDL_Test.java
│           │                       │           ├── MemoryTableMeta_Random_DDL_Test.java
│           │                       │           ├── MetaHistoryDAOTest.java
│           │                       │           ├── MetaSnapshotDAOTest.java
│           │                       │           ├── TableMetaManagerBuilderTest.java
│           │                       │           └── TableMetaManagerTest.java
│           │                       ├── index/
│           │                       │   ├── AbstractLogPositionManagerTest.java
│           │                       │   ├── AbstractZkTest.java
│           │                       │   ├── FileMixedLogPositionManagerTest.java
│           │                       │   ├── MemoryLogPositionManagerTest.java
│           │                       │   ├── MetaLogPositionManagerTest.java
│           │                       │   ├── MixedLogPositionManagerTest.java
│           │                       │   ├── PeriodMixedLogPositionManagerTest.java
│           │                       │   └── ZooKeeperLogPositionManagerTest.java
│           │                       └── stub/
│           │                           └── AbstractCanalEventSinkTest.java
│           └── resources/
│               ├── binlog/
│               │   ├── mysql-bin.000001
│               │   ├── mysql-bin.000002
│               │   └── tsdb/
│               │       ├── mysql-bin.000001
│               │       ├── mysql-bin.000002
│               │       └── mysql-bin.000003
│               ├── ddl/
│               │   ├── alter/
│               │   │   ├── mysql_1.sql
│               │   │   ├── mysql_10.sql
│               │   │   ├── mysql_11.sql
│               │   │   ├── mysql_12.sql
│               │   │   ├── mysql_13.sql
│               │   │   ├── mysql_14.sql
│               │   │   ├── mysql_15.sql
│               │   │   ├── mysql_16.sql
│               │   │   ├── mysql_17.sql
│               │   │   ├── mysql_18.sql
│               │   │   ├── mysql_19.sql
│               │   │   ├── mysql_2.sql
│               │   │   ├── mysql_20.sql
│               │   │   ├── mysql_21.sql
│               │   │   ├── mysql_22.sql
│               │   │   ├── mysql_23.sql
│               │   │   ├── mysql_24.sql
│               │   │   ├── mysql_25.sql
│               │   │   ├── mysql_26.sql
│               │   │   ├── mysql_27.sql
│               │   │   ├── mysql_28.sql
│               │   │   ├── mysql_29.sql
│               │   │   ├── mysql_3.sql
│               │   │   ├── mysql_30.sql
│               │   │   ├── mysql_31.sql
│               │   │   ├── mysql_32.sql
│               │   │   ├── mysql_33.sql
│               │   │   ├── mysql_34.sql
│               │   │   ├── mysql_35.sql
│               │   │   ├── mysql_36.sql
│               │   │   ├── mysql_37.sql
│               │   │   ├── mysql_38.sql
│               │   │   ├── mysql_39.sql
│               │   │   ├── mysql_4.sql
│               │   │   ├── mysql_40.sql
│               │   │   ├── mysql_41.sql
│               │   │   ├── mysql_42.sql
│               │   │   ├── mysql_43.sql
│               │   │   ├── mysql_44.sql
│               │   │   ├── mysql_45.sql
│               │   │   ├── mysql_46.sql
│               │   │   ├── mysql_47.sql
│               │   │   ├── mysql_48.sql
│               │   │   ├── mysql_49.sql
│               │   │   ├── mysql_5.sql
│               │   │   ├── mysql_50.sql
│               │   │   ├── mysql_51.sql
│               │   │   ├── mysql_52.sql
│               │   │   ├── mysql_53.sql
│               │   │   ├── mysql_54.sql
│               │   │   ├── mysql_55.sql
│               │   │   ├── mysql_56.sql
│               │   │   ├── mysql_57.sql
│               │   │   ├── mysql_58.sql
│               │   │   ├── mysql_59.sql
│               │   │   ├── mysql_6.sql
│               │   │   ├── mysql_60.sql
│               │   │   ├── mysql_61.sql
│               │   │   ├── mysql_62.sql
│               │   │   ├── mysql_63.sql
│               │   │   ├── mysql_64.sql
│               │   │   ├── mysql_65.sql
│               │   │   ├── mysql_66.sql
│               │   │   ├── mysql_67.sql
│               │   │   ├── mysql_68.sql
│               │   │   ├── mysql_69.sql
│               │   │   ├── mysql_7.sql
│               │   │   ├── mysql_70.sql
│               │   │   ├── mysql_71.sql
│               │   │   ├── mysql_72.sql
│               │   │   ├── mysql_73.sql
│               │   │   ├── mysql_74.sql
│               │   │   ├── mysql_75.sql
│               │   │   ├── mysql_76.sql
│               │   │   ├── mysql_77.sql
│               │   │   ├── mysql_78.sql
│               │   │   ├── mysql_79.sql
│               │   │   ├── mysql_8.sql
│               │   │   ├── mysql_80.sql
│               │   │   ├── mysql_9.sql
│               │   │   ├── test_1.sql
│               │   │   ├── test_10.sql
│               │   │   ├── test_11.sql
│               │   │   ├── test_12.sql
│               │   │   ├── test_13.sql
│               │   │   ├── test_14.sql
│               │   │   ├── test_15.sql
│               │   │   ├── test_16.sql
│               │   │   ├── test_17.sql
│               │   │   ├── test_18.sql
│               │   │   ├── test_19.sql
│               │   │   ├── test_2.sql
│               │   │   ├── test_20.sql
│               │   │   ├── test_21.sql
│               │   │   ├── test_22.sql
│               │   │   ├── test_23.sql
│               │   │   ├── test_24.sql
│               │   │   ├── test_25.sql
│               │   │   ├── test_26.sql
│               │   │   ├── test_27.sql
│               │   │   ├── test_28.sql
│               │   │   ├── test_29.sql
│               │   │   ├── test_3.sql
│               │   │   ├── test_30.sql
│               │   │   ├── test_31.sql
│               │   │   ├── test_32.sql
│               │   │   ├── test_33.sql
│               │   │   ├── test_34.sql
│               │   │   ├── test_35.sql
│               │   │   ├── test_36.sql
│               │   │   ├── test_37.sql
│               │   │   ├── test_38.sql
│               │   │   ├── test_39.sql
│               │   │   ├── test_4.sql
│               │   │   ├── test_40.sql
│               │   │   ├── test_41.sql
│               │   │   ├── test_42.sql
│               │   │   ├── test_43.sql
│               │   │   ├── test_44.sql
│               │   │   ├── test_45.sql
│               │   │   ├── test_46.sql
│               │   │   ├── test_47.sql
│               │   │   ├── test_48.sql
│               │   │   ├── test_49.sql
│               │   │   ├── test_5.sql
│               │   │   ├── test_50.sql
│               │   │   ├── test_51.sql
│               │   │   ├── test_52.sql
│               │   │   ├── test_53.sql
│               │   │   ├── test_54.sql
│               │   │   ├── test_55.sql
│               │   │   ├── test_56.sql
│               │   │   ├── test_57.sql
│               │   │   ├── test_58.sql
│               │   │   ├── test_59.sql
│               │   │   ├── test_6.sql
│               │   │   ├── test_60.sql
│               │   │   ├── test_61.sql
│               │   │   ├── test_62.sql
│               │   │   ├── test_63.sql
│               │   │   ├── test_64.sql
│               │   │   ├── test_65.sql
│               │   │   ├── test_66.sql
│               │   │   ├── test_67.sql
│               │   │   ├── test_68.sql
│               │   │   ├── test_69.sql
│               │   │   ├── test_7.sql
│               │   │   ├── test_70.sql
│               │   │   ├── test_71.sql
│               │   │   ├── test_72.sql
│               │   │   ├── test_73.sql
│               │   │   ├── test_74.sql
│               │   │   ├── test_75.sql
│               │   │   ├── test_76.sql
│               │   │   ├── test_77.sql
│               │   │   ├── test_78.sql
│               │   │   ├── test_79.sql
│               │   │   ├── test_8.sql
│               │   │   ├── test_80.sql
│               │   │   └── test_9.sql
│               │   ├── create.sql
│               │   ├── ddl_any.sql
│               │   ├── ddl_create_function_index.sql
│               │   ├── ddl_create_if_not_exist.sql
│               │   ├── ddl_test1.sql
│               │   ├── ddl_test2.sql
│               │   ├── ddl_test3.sql
│               │   ├── ddl_test4.sql
│               │   └── table/
│               │       ├── mysql_1.sql
│               │       ├── mysql_10.sql
│               │       ├── mysql_11.sql
│               │       ├── mysql_12.sql
│               │       ├── mysql_13.sql
│               │       ├── mysql_14.sql
│               │       ├── mysql_15.sql
│               │       ├── mysql_16.sql
│               │       ├── mysql_17.sql
│               │       ├── mysql_18.sql
│               │       ├── mysql_19.sql
│               │       ├── mysql_2.sql
│               │       ├── mysql_20.sql
│               │       ├── mysql_21.sql
│               │       ├── mysql_22.sql
│               │       ├── mysql_23.sql
│               │       ├── mysql_24.sql
│               │       ├── mysql_25.sql
│               │       ├── mysql_26.sql
│               │       ├── mysql_27.sql
│               │       ├── mysql_28.sql
│               │       ├── mysql_29.sql
│               │       ├── mysql_3.sql
│               │       ├── mysql_30.sql
│               │       ├── mysql_31.sql
│               │       ├── mysql_32.sql
│               │       ├── mysql_33.sql
│               │       ├── mysql_34.sql
│               │       ├── mysql_35.sql
│               │       ├── mysql_36.sql
│               │       ├── mysql_37.sql
│               │       ├── mysql_38.sql
│               │       ├── mysql_39.sql
│               │       ├── mysql_4.sql
│               │       ├── mysql_5.sql
│               │       ├── mysql_6.sql
│               │       ├── mysql_7.sql
│               │       ├── mysql_8.sql
│               │       ├── mysql_9.sql
│               │       ├── test_1.sql
│               │       ├── test_10.sql
│               │       ├── test_11.sql
│               │       ├── test_12.sql
│               │       ├── test_13.sql
│               │       ├── test_14.sql
│               │       ├── test_15.sql
│               │       ├── test_16.sql
│               │       ├── test_17.sql
│               │       ├── test_18.sql
│               │       ├── test_19.sql
│               │       ├── test_2.sql
│               │       ├── test_20.sql
│               │       ├── test_21.sql
│               │       ├── test_22.sql
│               │       ├── test_23.sql
│               │       ├── test_24.sql
│               │       ├── test_25.sql
│               │       ├── test_26.sql
│               │       ├── test_27.sql
│               │       ├── test_28.sql
│               │       ├── test_29.sql
│               │       ├── test_3.sql
│               │       ├── test_30.sql
│               │       ├── test_31.sql
│               │       ├── test_32.sql
│               │       ├── test_33.sql
│               │       ├── test_34.sql
│               │       ├── test_35.sql
│               │       ├── test_36.sql
│               │       ├── test_37.sql
│               │       ├── test_38.sql
│               │       ├── test_39.sql
│               │       ├── test_4.sql
│               │       ├── test_5.sql
│               │       ├── test_6.sql
│               │       ├── test_7.sql
│               │       ├── test_8.sql
│               │       └── test_9.sql
│               ├── dummy.txt
│               └── tsdb/
│                   ├── derby-tsdb.xml
│                   ├── h2-tsdb.xml
│                   ├── mysql-tsdb.xml
│                   └── sql-map/
│                       ├── sqlmap-config.xml
│                       ├── sqlmap_history.xml
│                       └── sqlmap_snapshot.xml
├── pom.xml
├── prometheus/
│   ├── pom.xml
│   └── src/
│       └── main/
│           ├── java/
│           │   └── com/
│           │       └── alibaba/
│           │           └── otter/
│           │               └── canal/
│           │                   └── prometheus/
│           │                       ├── CanalInstanceExports.java
│           │                       ├── InstanceRegistry.java
│           │                       ├── PrometheusProvider.java
│           │                       ├── PrometheusService.java
│           │                       └── impl/
│           │                           ├── EntryCollector.java
│           │                           ├── MetaCollector.java
│           │                           ├── ParserCollector.java
│           │                           ├── PrometheusCanalEventDownStreamHandler.java
│           │                           ├── PrometheusClientInstanceProfiler.java
│           │                           ├── SinkCollector.java
│           │                           └── StoreCollector.java
│           └── resources/
│               └── META-INF/
│                   └── services/
│                       └── com.alibaba.otter.canal.spi.CanalMetricsProvider
├── protocol/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── alibaba/
│       │               └── otter/
│       │                   └── canal/
│       │                       └── protocol/
│       │                           ├── AdminPacket.java
│       │                           ├── AdminProtocol.proto
│       │                           ├── CanalEntry.java
│       │                           ├── CanalPacket.java
│       │                           ├── CanalProtocol.proto
│       │                           ├── ClientIdentity.java
│       │                           ├── EntryProtocol.proto
│       │                           ├── FlatMessage.java
│       │                           ├── Message.java
│       │                           ├── SecurityUtil.java
│       │                           ├── exception/
│       │                           │   └── CanalClientException.java
│       │                           └── position/
│       │                               ├── EntryPosition.java
│       │                               ├── LogIdentity.java
│       │                               ├── LogPosition.java
│       │                               ├── MetaqPosition.java
│       │                               ├── Position.java
│       │                               ├── PositionRange.java
│       │                               └── TimePosition.java
│       └── test/
│           └── java/
│               └── com/
│                   └── alibaba/
│                       └── otter/
│                           └── canal/
│                               └── protocol/
│                                   ├── ProtocolTest.java
│                                   └── SecurityUtilTest.java
├── server/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── alibaba/
│       │               └── otter/
│       │                   └── canal/
│       │                       ├── admin/
│       │                       │   ├── CanalAdmin.java
│       │                       │   ├── handler/
│       │                       │   │   ├── ClientAuthenticationHandler.java
│       │                       │   │   ├── HandshakeInitializationHandler.java
│       │                       │   │   └── SessionHandler.java
│       │                       │   └── netty/
│       │                       │       ├── AdminNettyUtils.java
│       │                       │       └── CanalAdminWithNetty.java
│       │                       ├── server/
│       │                       │   ├── CanalMQStarter.java
│       │                       │   ├── CanalServer.java
│       │                       │   ├── CanalServerStarter.java
│       │                       │   ├── CanalService.java
│       │                       │   ├── embedded/
│       │                       │   │   └── CanalServerWithEmbedded.java
│       │                       │   ├── exception/
│       │                       │   │   └── CanalServerException.java
│       │                       │   └── netty/
│       │                       │       ├── CanalServerWithNetty.java
│       │                       │       ├── CanalServerWithNettyProfiler.java
│       │                       │       ├── ClientInstanceProfiler.java
│       │                       │       ├── NettyUtils.java
│       │                       │       ├── handler/
│       │                       │       │   ├── ClientAuthenticationHandler.java
│       │                       │       │   ├── FixedHeaderFrameDecoder.java
│       │                       │       │   ├── HandshakeInitializationHandler.java
│       │                       │       │   └── SessionHandler.java
│       │                       │       └── listener/
│       │                       │           └── ChannelFutureAggregator.java
│       │                       └── spi/
│       │                           ├── CanalMetricsProvider.java
│       │                           ├── CanalMetricsService.java
│       │                           └── NopCanalMetricsService.java
│       └── test/
│           └── java/
│               └── com/
│                   └── alibaba/
│                       └── otter/
│                           └── canal/
│                               └── server/
│                                   ├── CanalServerTest.java
│                                   └── embedded/
│                                       ├── BaseCanalServerWithEmbededTest.java
│                                       ├── CanalServerWithEmbedded_FileModeTest.java
│                                       ├── CanalServerWithEmbedded_StandaloneTest.java
│                                       └── CanalServerWithEmbedded_StandbyTest.java
├── sink/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── alibaba/
│       │               └── otter/
│       │                   └── canal/
│       │                       └── sink/
│       │                           ├── AbstractCanalEventDownStreamHandler.java
│       │                           ├── AbstractCanalEventSink.java
│       │                           ├── CanalEventDownStreamHandler.java
│       │                           ├── CanalEventSink.java
│       │                           ├── entry/
│       │                           │   ├── EntryEventSink.java
│       │                           │   ├── HeartBeatEntryEventHandler.java
│       │                           │   └── group/
│       │                           │       ├── GroupBarrier.java
│       │                           │       ├── GroupEventSink.java
│       │                           │       ├── TimelineBarrier.java
│       │                           │       └── TimelineTransactionBarrier.java
│       │                           └── exception/
│       │                               └── CanalSinkException.java
│       └── test/
│           └── java/
│               └── com/
│                   └── alibaba/
│                       └── otter/
│                           └── canal/
│                               └── sink/
│                                   ├── GroupEventSinkTest.java
│                                   └── stub/
│                                       └── DummyEventStore.java
└── store/
    ├── pom.xml
    └── src/
        ├── main/
        │   └── java/
        │       └── com/
        │           └── alibaba/
        │               └── otter/
        │                   └── canal/
        │                       └── store/
        │                           ├── AbstractCanalGroupStore.java
        │                           ├── AbstractCanalStoreScavenge.java
        │                           ├── CanalEventStore.java
        │                           ├── CanalGroupEventStore.java
        │                           ├── CanalStoreConstants.java
        │                           ├── CanalStoreException.java
        │                           ├── CanalStoreScavenge.java
        │                           ├── StoreInfo.java
        │                           ├── helper/
        │                           │   └── CanalEventUtils.java
        │                           ├── memory/
        │                           │   └── MemoryEventStoreWithBuffer.java
        │                           └── model/
        │                               ├── BatchMode.java
        │                               ├── Event.java
        │                               └── Events.java
        └── test/
            └── java/
                └── com/
                    └── alibaba/
                        └── otter/
                            └── canal/
                                └── store/
                                    └── memory/
                                        └── buffer/
                                            ├── MemoryEventStoreBase.java
                                            ├── MemoryEventStoreMemBatchTest.java
                                            ├── MemoryEventStoreMultiThreadTest.java
                                            ├── MemoryEventStorePutAndGetTest.java
                                            └── MemoryEventStoreRollbackAndAckTest.java
Download .txt
Showing preview only (962K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (10888 symbols across 963 files)

FILE: admin/admin-ui/mock/index.js
  function mockXHR (line 15) | function mockXHR() {
  method response (line 58) | response(req, res) {

FILE: admin/admin-ui/mock/mock-server.js
  function registerRoutes (line 8) | function registerRoutes(app) {
  function unregisterRoutes (line 22) | function unregisterRoutes() {

FILE: admin/admin-ui/src/api/canalCluster.js
  function getCanalClusters (line 3) | function getCanalClusters(params) {
  function addCanalCluster (line 11) | function addCanalCluster(data) {
  function canalClusterDetail (line 19) | function canalClusterDetail(id) {
  function updateCanalCluster (line 26) | function updateCanalCluster(data) {
  function deleteCanalCluster (line 34) | function deleteCanalCluster(id) {
  function getClustersAndServers (line 41) | function getClustersAndServers() {

FILE: admin/admin-ui/src/api/canalConfig.js
  function getCanalConfig (line 3) | function getCanalConfig(clusterId, serverId) {
  function updateCanalConfig (line 10) | function updateCanalConfig(data) {
  function getTemplateConfig (line 18) | function getTemplateConfig() {

FILE: admin/admin-ui/src/api/canalInstance.js
  function getCanalInstances (line 3) | function getCanalInstances(params) {
  function canalInstanceDetail (line 11) | function canalInstanceDetail(id) {
  function updateCanalInstance (line 18) | function updateCanalInstance(data) {
  function addCanalInstance (line 26) | function addCanalInstance(data) {
  function deleteCanalInstance (line 34) | function deleteCanalInstance(id) {
  function startInstance (line 41) | function startInstance(id, nodeId) {
  function stopInstance (line 48) | function stopInstance(id, nodeId) {
  function instanceLog (line 55) | function instanceLog(id, nodeId) {
  function instanceStatus (line 62) | function instanceStatus(id, option) {
  function getActiveInstances (line 69) | function getActiveInstances(serverId) {
  function getTemplateInstance (line 76) | function getTemplateInstance() {

FILE: admin/admin-ui/src/api/nodeServer.js
  function getNodeServers (line 3) | function getNodeServers(params) {
  function addNodeServer (line 11) | function addNodeServer(data) {
  function nodeServerDetail (line 19) | function nodeServerDetail(id) {
  function updateNodeServer (line 26) | function updateNodeServer(data) {
  function deleteNodeServer (line 34) | function deleteNodeServer(id) {
  function startNodeServer (line 41) | function startNodeServer(id) {
  function stopNodeServer (line 48) | function stopNodeServer(id) {
  function nodeServerLog (line 55) | function nodeServerLog(id) {

FILE: admin/admin-ui/src/api/table.js
  function getList (line 3) | function getList(params) {

FILE: admin/admin-ui/src/api/user.js
  function login (line 3) | function login(data) {
  function getInfo (line 11) | function getInfo(token) {
  function logout (line 19) | function logout() {
  function updateUser (line 26) | function updateUser(data) {

FILE: admin/admin-ui/src/layout/components/Sidebar/FixiOSBug.js
  method device (line 3) | device() {
  method mounted (line 7) | mounted() {
  method fixBugIniOS (line 13) | fixBugIniOS() {

FILE: admin/admin-ui/src/layout/mixin/ResizeHandler.js
  constant WIDTH (line 4) | const WIDTH = 992 // refer to Bootstrap's responsive design
  method $route (line 8) | $route(route) {
  method beforeMount (line 14) | beforeMount() {
  method beforeDestroy (line 17) | beforeDestroy() {
  method mounted (line 20) | mounted() {
  method $_isMobile (line 30) | $_isMobile() {
  method $_resizeHandler (line 34) | $_resizeHandler() {

FILE: admin/admin-ui/src/router/index.js
  function resetRouter (line 148) | function resetRouter() {

FILE: admin/admin-ui/src/store/modules/app.js
  method toggleSideBar (line 32) | toggleSideBar({ commit }) {
  method closeSideBar (line 35) | closeSideBar({ commit }, { withoutAnimation }) {
  method toggleDevice (line 38) | toggleDevice({ commit }, device) {

FILE: admin/admin-ui/src/store/modules/settings.js
  method changeSetting (line 20) | changeSetting({ commit }, data) {

FILE: admin/admin-ui/src/store/modules/user.js
  method login (line 25) | login({ commit }, userInfo) {
  method getInfo (line 40) | getInfo({ commit, state }) {
  method logout (line 61) | logout({ commit, state }) {
  method resetToken (line 75) | resetToken({ commit }) {

FILE: admin/admin-ui/src/utils/auth.js
  function getToken (line 5) | function getToken() {
  function setToken (line 9) | function setToken(token) {
  function removeToken (line 13) | function removeToken() {

FILE: admin/admin-ui/src/utils/get-page-title.js
  function getPageTitle (line 5) | function getPageTitle(pageTitle) {

FILE: admin/admin-ui/src/utils/index.js
  function parseTime (line 11) | function parseTime(time, cFormat) {
  function formatTime (line 54) | function formatTime(time, option) {
  function param2Obj (line 96) | function param2Obj(url) {

FILE: admin/admin-ui/src/utils/scrollTo.js
  function move (line 16) | function move(amount) {
  function position (line 22) | function position() {
  function scrollTo (line 26) | function scrollTo(to, duration, callback) {

FILE: admin/admin-ui/src/utils/validate.js
  function isExternal (line 9) | function isExternal(path) {
  function validUsername (line 17) | function validUsername(str) {

FILE: admin/admin-ui/vue.config.js
  function resolve (line 5) | function resolve(dir) {
  method chainWebpack (line 62) | chainWebpack(config) {

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/CanalAdminApplication.java
  class CanalAdminApplication (line 13) | @SpringBootApplication
    method main (line 16) | public static void main(String[] args) {

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/common/DaemonThreadFactory.java
  class DaemonThreadFactory (line 6) | public class DaemonThreadFactory implements ThreadFactory {
    method newThread (line 10) | public Thread newThread(Runnable r) {

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/common/TemplateConfigLoader.java
  class TemplateConfigLoader (line 13) | public class TemplateConfigLoader {
    method loadCanalConfig (line 21) | public static String loadCanalConfig() {
    method loadInstanceConfig (line 25) | public static String loadInstanceConfig() {
    method loadFile (line 29) | private static String loadFile(String fileName) {

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/common/Threads.java
  class Threads (line 8) | public class Threads {

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/common/exception/ServiceException.java
  class ServiceException (line 25) | @ResponseStatus(value = HttpStatus.SERVICE_UNAVAILABLE)
    method ServiceException (line 30) | public ServiceException(){
    method ServiceException (line 33) | public ServiceException(String message){
    method ServiceException (line 37) | public ServiceException(String message, Throwable cause){
    method ServiceException (line 41) | public ServiceException(Throwable cause){
    method ServiceException (line 45) | public ServiceException(String message, Throwable cause, boolean enabl...

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/config/EbeanConfig.java
  class EbeanConfig (line 23) | @Configuration
    method ebeanServer (line 26) | @Bean("ebeanServer")

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/config/SpringContext.java
  class SpringContext (line 14) | @Component
    method setApplicationContext (line 22) | public void setApplicationContext(final ApplicationContext context) th...
    method getBean (line 27) | public static Object getBean(final String beanName) {
    method getBean (line 31) | public static Object getBean(final Class<?> clz) {

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/config/WebConfig.java
  class WebConfig (line 28) | @Configuration
    method addInterceptors (line 37) | @Override

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/connector/AdminConnector.java
  type AdminConnector (line 12) | public interface AdminConnector {
    method connect (line 19) | void connect() throws ServiceException;
    method disconnect (line 26) | void disconnect() throws ServiceException;
    method check (line 33) | boolean check();
    method start (line 40) | boolean start();
    method stop (line 47) | boolean stop();
    method restart (line 54) | boolean restart();
    method getRunningInstances (line 61) | String getRunningInstances();
    method checkInstance (line 69) | boolean checkInstance(String destination);
    method startInstance (line 77) | boolean startInstance(String destination);
    method stopInstance (line 85) | boolean stopInstance(String destination);
    method releaseInstance (line 93) | boolean releaseInstance(String destination);
    method restartInstance (line 101) | boolean restartInstance(String destination);
    method listCanalLog (line 108) | String listCanalLog();
    method canalLog (line 115) | String canalLog(int lines);
    method listInstanceLog (line 122) | String listInstanceLog(String destination);
    method instanceLog (line 129) | String instanceLog(String destination, String fileName, int lines);

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/connector/SimpleAdminConnector.java
  class SimpleAdminConnector (line 38) | public class SimpleAdminConnector implements AdminConnector {
    method SimpleAdminConnector (line 53) | public SimpleAdminConnector(String ip, int port, String user, String p...
    method connect (line 59) | @Override
    method disconnect (line 116) | @Override
    method check (line 137) | @Override
    method start (line 142) | @Override
    method stop (line 147) | @Override
    method restart (line 152) | @Override
    method getRunningInstances (line 157) | @Override
    method checkInstance (line 162) | @Override
    method startInstance (line 167) | @Override
    method stopInstance (line 172) | @Override
    method releaseInstance (line 177) | @Override
    method restartInstance (line 182) | @Override
    method listCanalLog (line 187) | @Override
    method canalLog (line 192) | @Override
    method listInstanceLog (line 197) | @Override
    method instanceLog (line 202) | @Override
    method doServerAdmin (line 209) | private String doServerAdmin(String action) {
    method doInstanceAdmin (line 229) | private String doInstanceAdmin(String destination, String action) {
    method doLogAdmin (line 253) | private String doLogAdmin(String type, String action, String destinati...
    method writeWithHeader (line 280) | private void writeWithHeader(byte[] body) throws IOException {
    method readNextPacket (line 284) | private byte[] readNextPacket() throws IOException {
    method writeWithHeader (line 288) | private void writeWithHeader(WritableByteChannel channel, byte[] body)...
    method readNextPacket (line 296) | private byte[] readNextPacket(ReadableByteChannel channel) throws IOEx...
    method read (line 305) | private void read(ReadableByteChannel channel, ByteBuffer buffer) thro...
    method quietlyClose (line 314) | private void quietlyClose(Channel channel) {

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/connector/SimpleAdminConnectors.java
  class SimpleAdminConnectors (line 12) | public class SimpleAdminConnectors {
    method execute (line 16) | public static <R> R execute(String ip, int port, Function<AdminConnect...
    method execute (line 24) | public static <R> R execute(String ip, int port, String user, String p...
    method getDesensitizationPassword (line 40) | private static String getDesensitizationPassword(String password) {

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/controller/CanalClusterController.java
  class CanalClusterController (line 24) | @RestController
    method clusters (line 34) | @GetMapping(value = "/clusters")
    method save (line 39) | @PostMapping(value = "/cluster")
    method detail (line 45) | @GetMapping(value = "/cluster/{id}")
    method update (line 50) | @PutMapping(value = "/cluster")
    method delete (line 56) | @DeleteMapping(value = "/cluster/{id}")
    method clustersAndServers (line 62) | @GetMapping(value = "/clustersAndServers")

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/controller/CanalConfigController.java
  class CanalConfigController (line 22) | @RestController
    method canalConfig (line 35) | @GetMapping(value = "/config/{clusterId}/{serverId}")
    method updateConfig (line 48) | @PutMapping(value = "/config")
    method template (line 54) | @GetMapping(value = "/config/template")

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/controller/CanalInstanceController.java
  class CanalInstanceController (line 29) | @RestController
    method list (line 43) | @GetMapping(value = "/instances")
    method save (line 56) | @PostMapping(value = "/instance")
    method config (line 69) | @GetMapping(value = "/instance")
    method detail (line 81) | @GetMapping(value = "/instance/{id}")
    method update (line 93) | @PutMapping(value = "/instance")
    method delete (line 106) | @DeleteMapping(value = "/instance/{id}")
    method start (line 119) | @PutMapping(value = "/instance/start/{id}/{nodeId}")
    method stop (line 132) | @PutMapping(value = "/instance/stop/{id}/{nodeId}")
    method instanceStart (line 145) | @PutMapping(value = "/instance/status/{id}")
    method instanceLog (line 158) | @GetMapping(value = "/instance/log/{id}/{nodeId}")
    method activeInstances (line 171) | @GetMapping(value = "/active/instances/{serverId}")
    method template (line 176) | @GetMapping(value = "/instance/template")

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/controller/NodeServerController.java
  class NodeServerController (line 25) | @RestController
    method nodeServers (line 39) | @GetMapping(value = "/nodeServers")
    method save (line 52) | @PostMapping(value = "/nodeServer")
    method detail (line 65) | @GetMapping(value = "/nodeServer/{id}")
    method update (line 77) | @PutMapping(value = "/nodeServer")
    method delete (line 90) | @DeleteMapping(value = "/nodeServer/{id}")
    method status (line 104) | @GetMapping(value = "/nodeServer/status")
    method start (line 116) | @PutMapping(value = "/nodeServer/start/{id}")
    method log (line 128) | @GetMapping(value = "/nodeServer/log/{id}")
    method stop (line 140) | @PutMapping(value = "/nodeServer/stop/{id}")

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/controller/PollingConfigController.java
  class PollingConfigController (line 23) | @RestController
    method canalConfigPoll (line 41) | @GetMapping(value = "/server_polling")
    method instanceConfigPoll (line 63) | @GetMapping(value = "/instance_polling/{destination}")
    method instancesPoll (line 78) | @GetMapping(value = "/instances_polling")
    method auth (line 90) | private boolean auth(String user, String passwd) {

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/controller/UserController.java
  class UserController (line 32) | @RestController
    method login (line 51) | @PostMapping(value = "/login")
    method info (line 75) | @GetMapping(value = "/info")
    method update (line 96) | @PutMapping(value = "")
    method logout (line 111) | @PostMapping(value = "/logout")

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/handler/CustomExceptionHandler.java
  class CustomExceptionHandler (line 20) | @ControllerAdvice(annotations = ResponseBody.class)
    method commonExceptionHandle (line 31) | @ResponseBody

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/model/BaseModel.java
  class BaseModel (line 9) | public class BaseModel<T> {
    method getCode (line 15) | public Integer getCode() {
    method setCode (line 19) | public void setCode(Integer code) {
    method getMessage (line 23) | public String getMessage() {
    method setMessage (line 27) | public void setMessage(String message) {
    method getData (line 31) | public T getData() {
    method setData (line 35) | public void setData(T data) {
    method getInstance (line 39) | public static <T> BaseModel<T> getInstance(T data) {

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/model/CanalCluster.java
  class CanalCluster (line 18) | @Entity
    class CanalClusterFinder (line 24) | public static class CanalClusterFinder extends Finder<Long, CanalClust...
      method CanalClusterFinder (line 29) | public CanalClusterFinder(){
    method getId (line 42) | public Long getId() {
    method setId (line 46) | public void setId(Long id) {
    method getName (line 50) | public String getName() {
    method setName (line 54) | public void setName(String name) {
    method getZkHosts (line 58) | public String getZkHosts() {
    method setZkHosts (line 62) | public void setZkHosts(String zkHosts) {
    method getModifiedTime (line 66) | public Date getModifiedTime() {
    method setModifiedTime (line 70) | public void setModifiedTime(Date modifiedTime) {

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/model/CanalConfig.java
  class CanalConfig (line 17) | @Entity
    class CanalConfigFinder (line 22) | public static class CanalConfigFinder extends Finder<Long, CanalConfig> {
      method CanalConfigFinder (line 27) | public CanalConfigFinder(){
    method init (line 44) | public void init() {
    method getId (line 48) | public Long getId() {
    method setId (line 52) | public void setId(Long id) {
    method getClusterId (line 56) | public Long getClusterId() {
    method setClusterId (line 60) | public void setClusterId(Long clusterId) {
    method getServerId (line 64) | public Long getServerId() {
    method setServerId (line 68) | public void setServerId(Long serverId) {
    method getName (line 72) | public String getName() {
    method setName (line 76) | public void setName(String name) {
    method getContent (line 80) | public String getContent() {
    method setContent (line 84) | public void setContent(String content) {
    method getContentMd5 (line 88) | public String getContentMd5() {
    method setContentMd5 (line 92) | public void setContentMd5(String contentMd5) {
    method getModifiedTime (line 96) | public Date getModifiedTime() {
    method setModifiedTime (line 100) | public void setModifiedTime(Date modifiedTime) {
    method getStatus (line 104) | public String getStatus() {
    method setStatus (line 108) | public void setStatus(String status) {

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/model/CanalInstanceConfig.java
  class CanalInstanceConfig (line 22) | @Entity
    class CanalInstanceConfigFinder (line 27) | public static class CanalInstanceConfigFinder extends Finder<Long, Can...
      method CanalInstanceConfigFinder (line 32) | public CanalInstanceConfigFinder(){
    method init (line 62) | public void init() {
    method getId (line 66) | public Long getId() {
    method setId (line 70) | public void setId(Long id) {
    method getClusterId (line 74) | public Long getClusterId() {
    method setClusterId (line 78) | public void setClusterId(Long clusterId) {
    method getCanalCluster (line 82) | public CanalCluster getCanalCluster() {
    method setCanalCluster (line 86) | public void setCanalCluster(CanalCluster canalCluster) {
    method getServerId (line 90) | public Long getServerId() {
    method setServerId (line 94) | public void setServerId(Long serverId) {
    method getNodeServer (line 98) | public NodeServer getNodeServer() {
    method setNodeServer (line 102) | public void setNodeServer(NodeServer nodeServer) {
    method getName (line 106) | public String getName() {
    method setName (line 110) | public void setName(String name) {
    method getContent (line 114) | public String getContent() {
    method setContent (line 118) | public void setContent(String content) {
    method getContentMd5 (line 122) | public String getContentMd5() {
    method setContentMd5 (line 126) | public void setContentMd5(String contentMd5) {
    method getStatus (line 130) | public String getStatus() {
    method setStatus (line 134) | public void setStatus(String status) {
    method getModifiedTime (line 138) | public Date getModifiedTime() {
    method setModifiedTime (line 142) | public void setModifiedTime(Date modifiedTime) {
    method getClusterServerId (line 146) | public String getClusterServerId() {
    method setClusterServerId (line 150) | public void setClusterServerId(String clusterServerId) {
    method getRunningStatus (line 154) | public String getRunningStatus() {
    method setRunningStatus (line 158) | public void setRunningStatus(String runningStatus) {

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/model/Model.java
  class Model (line 17) | @MappedSuperclass
    method init (line 20) | public void init() {
    method save (line 23) | public void save() {
    method insert (line 28) | public void insert() {
    method saveOrUpdate (line 33) | public void saveOrUpdate() {
    method update (line 48) | public void update(String... propertiesNames) {

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/model/NodeServer.java
  class NodeServer (line 22) | @Entity
    class NodeServerFinder (line 28) | public static class NodeServerFinder extends Finder<Long, NodeServer> {
      method NodeServerFinder (line 33) | public NodeServerFinder(){
    method init (line 55) | public void init() {
    method getId (line 59) | public Long getId() {
    method setId (line 63) | public void setId(Long id) {
    method getCanalCluster (line 67) | public CanalCluster getCanalCluster() {
    method setCanalCluster (line 71) | public void setCanalCluster(CanalCluster canalCluster) {
    method getClusterId (line 75) | public Long getClusterId() {
    method setClusterId (line 79) | public void setClusterId(Long clusterId) {
    method getName (line 83) | public String getName() {
    method setName (line 87) | public void setName(String name) {
    method getIp (line 91) | public String getIp() {
    method setIp (line 95) | public void setIp(String ip) {
    method getAdminPort (line 99) | public Integer getAdminPort() {
    method setAdminPort (line 103) | public void setAdminPort(Integer adminPort) {
    method getMetricPort (line 107) | public Integer getMetricPort() {
    method setMetricPort (line 111) | public void setMetricPort(Integer metricPort) {
    method getTcpPort (line 115) | public Integer getTcpPort() {
    method setTcpPort (line 119) | public void setTcpPort(Integer tcpPort) {
    method getStatus (line 123) | public String getStatus() {
    method setStatus (line 127) | public void setStatus(String status) {
    method getModifiedTime (line 131) | public Date getModifiedTime() {
    method setModifiedTime (line 135) | public void setModifiedTime(Date modifiedTime) {

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/model/Pager.java
  class Pager (line 7) | public class Pager<T> implements Serializable {
    method Pager (line 17) | public Pager(){
    method Pager (line 21) | public Pager(Integer page, Integer size){
    method Pager (line 26) | public Pager(Long count, List<T> items){
    method toString (line 31) | public String toString() {
    method getCount (line 35) | public Long getCount() {
    method setCount (line 39) | public void setCount(Long count) {
    method getItems (line 43) | public List<T> getItems() {
    method setItems (line 47) | public void setItems(List<T> items) {
    method getPage (line 51) | public Integer getPage() {
    method setPage (line 58) | public void setPage(Integer page) {
    method getSize (line 62) | public Integer getSize() {
    method setSize (line 69) | public void setSize(Integer size) {
    method getOffset (line 73) | public Long getOffset() {
    method setOffset (line 78) | public void setOffset(Long offset) {

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/model/User.java
  class User (line 16) | @Entity
    class UserFinder (line 22) | public static class UserFinder extends Finder<Long, User> {
      method UserFinder (line 27) | public UserFinder(){
    method getId (line 47) | public Long getId() {
    method setId (line 51) | public void setId(Long id) {
    method getUsername (line 55) | public String getUsername() {
    method setUsername (line 59) | public void setUsername(String username) {
    method getPassword (line 63) | public String getPassword() {
    method setPassword (line 67) | public void setPassword(String password) {
    method getRoles (line 71) | public String getRoles() {
    method setRoles (line 75) | public void setRoles(String roles) {
    method getIntroduction (line 79) | public String getIntroduction() {
    method setIntroduction (line 83) | public void setIntroduction(String introduction) {
    method getAvatar (line 87) | public String getAvatar() {
    method setAvatar (line 91) | public void setAvatar(String avatar) {
    method getName (line 95) | public String getName() {
    method setName (line 99) | public void setName(String name) {
    method getCreationDate (line 103) | public Date getCreationDate() {
    method setCreationDate (line 107) | public void setCreationDate(Date creationDate) {
    method getOldPassword (line 111) | public String getOldPassword() {
    method setOldPassword (line 115) | public void setOldPassword(String oldPassword) {

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/CanalClusterService.java
  type CanalClusterService (line 7) | public interface CanalClusterService {
    method save (line 9) | void save(CanalCluster canalCluster);
    method detail (line 11) | CanalCluster detail(Long id);
    method update (line 13) | void update(CanalCluster canalCluster);
    method delete (line 15) | void delete(Long id);
    method findList (line 17) | List<CanalCluster> findList(CanalCluster canalCluster);

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/CanalConfigService.java
  type CanalConfigService (line 5) | public interface CanalConfigService {
    method getCanalConfig (line 7) | CanalConfig getCanalConfig(Long clusterId, Long serverId);
    method getCanalConfigSummary (line 9) | CanalConfig getCanalConfigSummary();
    method getAdapterConfig (line 11) | CanalConfig getAdapterConfig();
    method updateContent (line 13) | void updateContent(CanalConfig canalConfig);

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/CanalInstanceService.java
  type CanalInstanceService (line 15) | public interface CanalInstanceService {
    method findList (line 17) | Pager<CanalInstanceConfig> findList(CanalInstanceConfig canalInstanceC...
    method save (line 19) | void save(CanalInstanceConfig canalInstanceConfig);
    method detail (line 21) | CanalInstanceConfig detail(Long id);
    method updateContent (line 23) | void updateContent(CanalInstanceConfig canalInstanceConfig);
    method delete (line 25) | void delete(Long id);
    method remoteInstanceLog (line 27) | Map<String, String> remoteInstanceLog(Long id, Long nodeId);
    method remoteOperation (line 29) | boolean remoteOperation(Long id, Long nodeId, String option);
    method instanceOperation (line 31) | boolean instanceOperation(Long id, String option);
    method findActiveInstanceByServerId (line 33) | List<CanalInstanceConfig> findActiveInstanceByServerId(Long serverId);

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/NodeServerService.java
  type NodeServerService (line 8) | public interface NodeServerService {
    method save (line 10) | void save(NodeServer nodeServer);
    method detail (line 12) | NodeServer detail(Long id);
    method update (line 14) | void update(NodeServer nodeServer);
    method delete (line 16) | void delete(Long id);
    method findAll (line 18) | List<NodeServer> findAll(NodeServer nodeServer);
    method findList (line 20) | Pager<NodeServer> findList(NodeServer nodeServer, Pager<NodeServer> pa...
    method remoteNodeStatus (line 22) | int remoteNodeStatus(String ip, Integer port);
    method remoteCanalLog (line 24) | String remoteCanalLog(Long id);
    method remoteOperation (line 26) | boolean remoteOperation(Long id, String option);

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/PollingConfigService.java
  type PollingConfigService (line 6) | public interface PollingConfigService {
    method autoRegister (line 8) | public boolean autoRegister(String ip, Integer adminPort, String clust...
    method getChangedConfig (line 10) | CanalConfig getChangedConfig(String ip, Integer port, String md5);
    method getInstancesConfig (line 12) | CanalInstanceConfig getInstancesConfig(String ip, Integer port, String...
    method getInstanceConfig (line 14) | CanalInstanceConfig getInstanceConfig(String destination, String md5);

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/UserService.java
  type UserService (line 5) | public interface UserService {
    method find4Login (line 7) | User find4Login(String username, String password);
    method update (line 9) | void update(User user);

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/impl/CanalClusterServiceImpl.java
  class CanalClusterServiceImpl (line 15) | @Service
    method save (line 18) | public void save(CanalCluster canalCluster) {
    method detail (line 22) | public CanalCluster detail(Long id) {
    method update (line 26) | public void update(CanalCluster canalCluster) {
    method delete (line 30) | public void delete(Long id) {
    method findList (line 49) | public List<CanalCluster> findList(CanalCluster canalCluster) {

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/impl/CanalConfigServiceImpl.java
  class CanalConfigServiceImpl (line 26) | @Service
    method getCanalConfig (line 34) | public CanalConfig getCanalConfig(Long clusterId, Long serverId) {
    method getCanalConfigSummary (line 61) | public CanalConfig getCanalConfigSummary() {
    method getAdapterConfig (line 70) | public CanalConfig getAdapterConfig() {
    method updateContent (line 90) | public void updateContent(CanalConfig canalConfig) {
    method loadDefaultConf (line 108) | private String loadDefaultConf(String confFileName) {

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/impl/CanalInstanceServiceImpl.java
  class CanalInstanceServiceImpl (line 37) | @Service
    method findList (line 40) | public Pager<CanalInstanceConfig> findList(CanalInstanceConfig canalIn...
    method findActiveInstanceByServerId (line 129) | public List<CanalInstanceConfig> findActiveInstanceByServerId(Long ser...
    method save (line 173) | public void save(CanalInstanceConfig canalInstanceConfig) {
    method detail (line 195) | public CanalInstanceConfig detail(Long id) {
    method updateContent (line 207) | public void updateContent(CanalInstanceConfig canalInstanceConfig) {
    method delete (line 231) | public void delete(Long id) {
    method remoteInstanceLog (line 238) | public Map<String, String> remoteInstanceLog(Long id, Long nodeId) {
    method remoteOperation (line 259) | public boolean remoteOperation(Long id, Long nodeId, String option) {
    method instanceOperation (line 306) | public boolean instanceOperation(Long id, String option) {

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/impl/NodeServerServiceImpl.java
  class NodeServerServiceImpl (line 34) | @Service
    method save (line 37) | public void save(NodeServer nodeServer) {
    method detail (line 63) | public NodeServer detail(Long id) {
    method update (line 67) | public void update(NodeServer nodeServer) {
    method delete (line 81) | public void delete(Long id) {
    method getBaseQuery (line 100) | private Query<NodeServer> getBaseQuery(NodeServer nodeServer) {
    method findAll (line 123) | public List<NodeServer> findAll(NodeServer nodeServer) {
    method findList (line 129) | public Pager<NodeServer> findList(NodeServer nodeServer, Pager<NodeSer...
    method remoteNodeStatus (line 170) | public int remoteNodeStatus(String ip, Integer port) {
    method remoteCanalLog (line 175) | public String remoteCanalLog(Long id) {
    method remoteOperation (line 185) | public boolean remoteOperation(Long id, String option) {

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/impl/PollingConfigServiceImpl.java
  class PollingConfigServiceImpl (line 23) | @Service
    method autoRegister (line 32) | public boolean autoRegister(String ip, Integer adminPort, String clust...
    method getChangedConfig (line 55) | public CanalConfig getChangedConfig(String ip, Integer port, String md...
    method getInstancesConfig (line 76) | public CanalInstanceConfig getInstancesConfig(String ip, Integer port,...
    method getInstanceConfig (line 115) | public CanalInstanceConfig getInstanceConfig(String destination, Strin...

FILE: admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/impl/UserServiceImpl.java
  class UserServiceImpl (line 19) | @Service
    method find4Login (line 26) | public User find4Login(String username, String password) {
    method update (line 47) | public void update(User user) {

FILE: admin/admin-web/src/main/resources/canal_manager.sql
  type `canal_adapter_config` (line 12) | CREATE TABLE `canal_adapter_config` (
  type `canal_cluster` (line 26) | CREATE TABLE `canal_cluster` (
  type `canal_config` (line 38) | CREATE TABLE `canal_config` (
  type `canal_instance_config` (line 55) | CREATE TABLE `canal_instance_config` (
  type `canal_node_server` (line 72) | CREATE TABLE `canal_node_server` (
  type `canal_user` (line 89) | CREATE TABLE `canal_user` (

FILE: admin/admin-web/src/main/resources/public/static/js/app.6845b228.js
  function i (line 1) | function i(e){var t=r(e);return n(t)}
  function r (line 1) | function r(e){var t=a[e];if(!(t+1)){var n=new Error("Cannot find module ...
  function j (line 1) | function j(e){return e?"".concat(e," - ").concat(T):"".concat(T)}
  function o (line 1) | function o(){return i.a.get(r)}
  function c (line 1) | function c(e){return i.a.set(r,e,{maxAge:0})}
  function s (line 1) | function s(){return i.a.remove(r)}
  function a (line 1) | function a(e){return/^(https?:|mailto:|tel:)/.test(e)}
  function i (line 1) | function i(e){var t=["admin","editor"];return t.indexOf(e.trim())>=0}
  function t (line 1) | function t(){return e.apply(this,arguments)}
  function Be (line 1) | function Be(){var e=He();Me.matcher=e.matcher}
  function i (line 1) | function i(e){return Object(a["a"])({url:"/user/login",method:"post",dat...
  function r (line 1) | function r(e){return Object(a["a"])({url:"/user/info",method:"get",param...
  function o (line 1) | function o(){return Object(a["a"])({url:"/user/logout",method:"post"})}
  function c (line 1) | function c(e){return Object(a["a"])({url:"/user",method:"put",data:e})}

FILE: admin/admin-web/src/main/resources/public/static/js/app.eee35d99.js
  function i (line 1) | function i(e){var t=r(e);return n(t)}
  function r (line 1) | function r(e){var t=a[e];if(!(t+1)){var n=new Error("Cannot find module ...
  function j (line 1) | function j(e){return e?"".concat(e," - ").concat(T):"".concat(T)}
  function o (line 1) | function o(){return i.a.get(r)}
  function c (line 1) | function c(e){return i.a.set(r,e,{maxAge:0})}
  function s (line 1) | function s(){return i.a.remove(r)}
  function a (line 1) | function a(e){return/^(https?:|mailto:|tel:)/.test(e)}
  function i (line 1) | function i(e){var t=["admin","editor"];return t.indexOf(e.trim())>=0}
  function t (line 1) | function t(){return e.apply(this,arguments)}
  function Be (line 1) | function Be(){var e=He();Me.matcher=e.matcher}
  function i (line 1) | function i(e){return Object(a["a"])({url:"/user/login",method:"post",dat...
  function r (line 1) | function r(e){return Object(a["a"])({url:"/user/info",method:"get",param...
  function o (line 1) | function o(){return Object(a["a"])({url:"/user/logout",method:"post"})}
  function c (line 1) | function c(e){return Object(a["a"])({url:"/user",method:"put",data:e})}

FILE: admin/admin-web/src/main/resources/public/static/js/chunk-0dca2f22.a2bc28b8.js
  function s (line 1) | function s(e){var r=t;e&&(t[e]||(t[e]={}),r=t[e]),r.define&&r.define.pac...
  function a (line 1) | function a(e){return(e.global?"g":"")+(e.ignoreCase?"i":"")+(e.multiline...
  function s (line 1) | function s(e,t,n){if(Array.prototype.indexOf)return e.indexOf(t,n);for(v...
  function r (line 1) | function r(){}
  function e (line 1) | function e(e){var t=new Array(e+2);return t[0]=t[1]=0,t}
  function y (line 1) | function y(e){try{return Object.defineProperty(e,"sentinel",{}),"sentine...
  function D (line 1) | function D(e){return e=+e,e!==e?e=0:0!==e&&e!==1/0&&e!==-1/0&&(e=(e>0||-...
  function i (line 1) | function i(e){n&&n(e),r&&r(e),t.removeListener(document,"mousemove",n,!0...
  function d (line 1) | function d(e){if(0!==t.getButton(e)?c=0:e.detail>1?(c++,c>4&&(c=1)):c=1,...
  function h (line 1) | function h(e){c=2,l&&clearTimeout(l),l=setTimeout(function(){l=null},n[c...
  function l (line 1) | function l(e,t,n){var l=s(t);if(!i.isMac&&o){if(t.getModifierState&&(t.g...
  function c (line 1) | function c(){o=Object.create(null)}
  function w (line 1) | function w(e){if(!f){if(f=!0,T)t=0,r=e?0:n.value.length-1;else var t=4,r...
  function x (line 1) | function x(){f||(n.value=d,i.isWebKit&&y.schedule())}
  function P (line 1) | function P(){clearTimeout(D),D=setTimeout(function(){g&&(n.style.cssText...
  function k (line 1) | function k(e){if(!p){if(p=!0,E)var t=0,r=e?0:n.value.length-1;else t=e?2...
  function y (line 1) | function y(){p||(n.value=u,i.isWebKit&&v.schedule())}
  function I (line 1) | function I(){clearTimeout($),$=setTimeout(function(){m&&(n.style.cssText...
  function a (line 1) | function a(e){e.$clickSelection=null;var t=e.editor;t.setDefaultHandler(...
  function s (line 1) | function s(e,t,n,r){return Math.sqrt(Math.pow(n-e,2)+Math.pow(r-t,2))}
  function l (line 1) | function l(e,t){if(e.start.row==e.end.row)var n=2*t.column-e.start.colum...
  function i (line 1) | function i(e){this.isOpen=!1,this.$element=null,this.$parentNode=e}
  function s (line 1) | function s(e){var t,n,i,a=e.editor,s=a.renderer.$gutterLayer,c=new l(a.c...
  function l (line 1) | function l(e){a.call(this,e)}
  function c (line 1) | function c(e){var t=e.editor,n=r.createElement("img");n.src="data:image/...
  function u (line 1) | function u(e,t,n,r){return Math.sqrt(Math.pow(n-e,2)+Math.pow(r-t,2))}
  function a (line 1) | function a(e){"undefined"!=typeof console&&console.warn&&console.warn.ap...
  function s (line 1) | function s(e,t){var n=new Error(e);n.data=t,"object"==typeof console&&co...
  function c (line 1) | function c(i){if(s&&s.document){l.packaged=i||e.packaged||r.packaged||s....
  function u (line 1) | function u(e){return e.replace(/-(.)/g,function(e,t){return t.toUpperCas...
  function r (line 1) | function r(e){e.on("click",function(t){var n=t.getDocumentPosition(),r=e...
  function B (line 1) | function B(e,t,n,u){var d=r?c:l,h=null,p=null,m=null,f=0,g=null,k=null,w...
  function D (line 1) | function D(e,t,n){if(!(i<e))if(1!=e||r!=d||a){var o,s,l,c,u=n.length,h=0...
  function M (line 1) | function M(e,t,n,i){var l,c,u,d,R=t[i];switch(R){case h:case p:o=!1;case...
  function O (line 1) | function O(e){var t=e.charCodeAt(0),n=t>>8;return 0==n?t>191?h:R[t]:5==n...
  function i (line 1) | function i(o){var a=r[o];a.processed=!0;for(var s=0;s<a.length;s++){var ...
  function r (line 1) | function r(e){var n=/\w{4}/g;for(var r in e)t.packages[r]=e[r].replace(n...
  function y (line 1) | function y(e){for(var t=n;t<=r;t++)e(i.getLine(t),t)}
  function e (line 1) | function e(e,t,n){var r=n?e.column<=t.column:e.column<t.column;return e....
  function t (line 1) | function t(t,n,r){var i="insert"==t.action,o=(i?1:-1)*(t.end.row-t.start...
  function i (line 1) | function i(e,t){this.foldData=e,Array.isArray(t)?this.folds=t:t=this.fol...
  function a (line 1) | function a(e,t){e.row-=t.row,0==e.row&&(e.column-=t.column)}
  function s (line 1) | function s(e,t){a(e.start,t),a(e.end,t)}
  function l (line 1) | function l(e,t){0==e.row&&(e.column+=t.column),e.row+=t.row}
  function c (line 1) | function c(e,t){l(e.start,t),l(e.end,t)}
  function s (line 1) | function s(){this.getFoldAt=function(e,t,n){var r=this.getFoldLine(e);if...
  function o (line 1) | function o(){this.findMatchingBracket=function(e,t){if(0==e.column)retur...
  function r (line 1) | function r(e){return t?"insert"!==e.action:"insert"===e.action}
  function g (line 1) | function g(e){return!(e<4352)&&(e>=4352&&e<=4447||e>=4515&&e<=4519||e>=4...
  function b (line 1) | function b(){var t=0;if(0===g)return t;if(p)for(var n=0;n<e.length;n++){...
  function v (line 1) | function v(t){var n=e.slice(c,t),r=n.length;n.join("").replace(/12/g,fun...
  function s (line 1) | function s(e,t){function n(e){return/\w/.test(e)||t.regExp?"\\b":""}retu...
  function a (line 1) | function a(e,t){this.platform=t||(i.isMac?"mac":"win"),this.commands={},...
  function s (line 1) | function s(e,t){a.call(this,e,t),this.$singleCommand=!1}
  function e (line 1) | function e(e){return"object"==typeof e&&e.bindKey&&e.bindKey.position||(...
  function a (line 1) | function a(e,t){return{win:e,mac:t}}
  function e (line 1) | function e(e){return{action:e.action,start:e.start,end:e.end,lines:1==e....
  function t (line 1) | function t(e){return{action:e.action,start:e.start,end:e.end,lines:e.lin...
  function n (line 1) | function n(e,t){for(var n=new Array(e.length),r=0;r<e.length;r++){for(va...
  function e (line 1) | function e(e,t,n,r){return(e?1:0)|(t?2:0)|(n?4:0)|(r?8:0)}
  function i (line 1) | function i(e,t,n){var i=0,o=0;while(o+e[i].value.length<t)if(o+=e[i].val...
  function a (line 1) | function a(r){if(n.$themeId!=e)return t&&t();if(!r||!r.cssClass)throw ne...
  function s (line 1) | function s(e,t){var n=t.src;i.qualifyURL(e);try{return new Blob([n],{typ...
  function l (line 1) | function l(e,t){var n=s(e,t),r=window.URL||window.webkitURL,i=r.createOb...
  function o (line 1) | function o(e,t){return e.row==t.row&&e.column==t.column}
  function a (line 1) | function a(e){var t=e.domEvent,n=t.altKey,a=t.shiftKey,s=t.ctrlKey,l=e.g...
  function h (line 1) | function h(e,t,n){return d.$options.wrap=!0,d.$options.needle=t,d.$optio...
  function f (line 1) | function f(e,t){return e.row==t.row&&e.column==t.column}
  function g (line 1) | function g(e){e.$multiselectOnSessionChange||(e.$onAddRange=e.$onAddRang...
  function b (line 1) | function b(e){var t=e.textInput.getElement(),n=!1;function r(t){n&&(e.re...
  function s (line 1) | function s(e){return l.stringRepeat(" ",e)}
  function c (line 1) | function c(e){return e[2]?s(n)+e[2]+s(r-e[2].length+i)+e[4].replace(/^([...
  function u (line 1) | function u(e){return e[2]?s(n+r-e[2].length)+e[2]+s(i," ")+e[4].replace(...
  function d (line 1) | function d(e){return e[2]?s(n)+e[2]+s(i)+e[4].replace(/^([=:])\s+/,"$1 "...
  function i (line 1) | function i(e){this.session=e,this.session.widgetManager=this,this.sessio...
  function a (line 1) | function a(e,t,n){var r=0,i=e.length-1;while(r<=i){var o=r+i>>1,a=n(t,e[...
  function s (line 1) | function s(e,t,n){var r=e.getAnnotations().sort(o.comparePoints);if(r.le...
  function e (line 1) | function e(e,t,n){return e=e.substr(1),/^\d+$/.test(e)&&!n.inFormatStrin...
  function t (line 1) | function t(e){return"(?:[^\\\\"+e+"]|\\\\.)"}
  function a (line 1) | function a(t){var n=e.indexOf(t,r+1);-1!=n&&(r=n)}
  function c (line 1) | function c(e){for(var t=[],n=0;n<e.length;n++){var r=e[n];if("object"==t...
  function a (line 1) | function a(e){return e&&!/^\^?\(.*\)\$?$|^\\b$/.test(e)&&(e="(?:"+e+")")...
  function s (line 1) | function s(e,t,n){return e=a(e),t=a(t),n?(e=t+e,e&&"$"!=e[e.length-1]&&(...
  function l (line 1) | function l(e){e.scope||(e.scope=t||"_"),t=e.scope,n[t]||(n[t]=[],r[t]={}...
  function i (line 1) | function i(e){var i=r[e.scope||t];if(i&&i[e.name]){delete i[e.name];var ...
  function o (line 1) | function o(e,t){var n=e.getTextRange(r.fromPoints({row:0,column:0},t));r...
  function a (line 1) | function a(e,t){var n=o(e,t),r=e.getValue().split(i),a=Object.create(nul...
  function e (line 1) | function e(e,t,n){return e=e.substr(1),/^\d+$/.test(e)&&!n.inFormatStrin...
  function t (line 1) | function t(e){return"(?:[^\\\\"+e+"]|\\\\.)"}
  function a (line 1) | function a(t){var n=e.indexOf(t,r+1);-1!=n&&(r=n)}
  function c (line 1) | function c(e){for(var t=[],n=0;n<e.length;n++){var r=e[n];if("object"==t...
  function a (line 1) | function a(e){return e&&!/^\^?\(.*\)\$?$|^\\b$/.test(e)&&(e="(?:"+e+")")...
  function s (line 1) | function s(e,t,n){return e=a(e),t=a(t),n?(e=t+e,e&&"$"!=e[e.length-1]&&(...
  function l (line 1) | function l(e){e.scope||(e.scope=t||"_"),t=e.scope,n[t]||(n[t]=[],r[t]={}...
  function i (line 1) | function i(e){var i=r[e.scope||t];if(i&&i[e.name]){delete i[e.name];var ...
  function c (line 1) | function c(){}
  function l (line 1) | function l(){var e=a.replace("\\d","\\d\\-"),t={onMatch:function(e,t,n){...
  function c (line 1) | function c(e){return[{token:"comment",regex:/\/\*/,next:[i.getTagRule(),...
  function l (line 1) | function l(){var e=a.replace("\\d","\\d\\-"),t={onMatch:function(e,t,n){...
  function c (line 1) | function c(e){return[{token:"comment",regex:/\/\*/,next:[i.getTagRule(),...
  function a (line 1) | function a(e,t){return e.type.lastIndexOf(t+".xml")>-1}
  function c (line 1) | function c(e,t){return e.type.lastIndexOf(t+".xml")>-1}
  function c (line 1) | function c(e,t){return e.type.lastIndexOf(t+".xml")>-1}
  function u (line 1) | function u(e,t){var n=new r(e,t.row,t.column),i=n.getCurrentToken();whil...
  function d (line 1) | function d(e,t){var n=new r(e,t.row,t.column),i=n.getCurrentToken();whil...

FILE: admin/admin-web/src/main/resources/public/static/js/chunk-14b5f7a4.013449e9.js
  function o (line 1) | function o(t){document.documentElement.scrollTop=t,document.body.parentN...
  function l (line 1) | function l(){return document.documentElement.scrollTop||document.body.pa...
  function s (line 1) | function s(t,e,n){var r=l(),a=t-r,s=20,c=0;e="undefined"===typeof e?500:...
  function a (line 1) | function a(t){return Object(r["a"])({url:"/nodeServers",method:"get",par...
  function i (line 1) | function i(t){return Object(r["a"])({url:"/nodeServer",method:"post",dat...
  function o (line 1) | function o(t){return Object(r["a"])({url:"/nodeServer",method:"put",data...
  function l (line 1) | function l(t){return Object(r["a"])({url:"/nodeServer/"+t,method:"delete...
  function s (line 1) | function s(t){return Object(r["a"])({url:"/nodeServer/start/"+t,method:"...
  function c (line 1) | function c(t){return Object(r["a"])({url:"/nodeServer/stop/"+t,method:"p...
  function u (line 1) | function u(t){return Object(r["a"])({url:"/nodeServer/log/"+t,method:"ge...
  function a (line 1) | function a(t){return Object(r["a"])({url:"/canal/clusters",method:"get",...
  function i (line 1) | function i(t){return Object(r["a"])({url:"/canal/cluster",method:"post",...
  function o (line 1) | function o(t){return Object(r["a"])({url:"/canal/cluster",method:"put",d...
  function l (line 1) | function l(t){return Object(r["a"])({url:"/canal/cluster/"+t,method:"del...
  function s (line 1) | function s(){return Object(r["a"])({url:"/canal/clustersAndServers",meth...
  function a (line 1) | function a(t){return Object(r["a"])({url:"/canal/instances",method:"get"...
  function i (line 1) | function i(t){return Object(r["a"])({url:"/canal/instance/"+t,method:"ge...
  function o (line 1) | function o(t){return Object(r["a"])({url:"/canal/instance",method:"put",...
  function l (line 1) | function l(t){return Object(r["a"])({url:"/canal/instance",method:"post"...
  function s (line 1) | function s(t){return Object(r["a"])({url:"/canal/instance/"+t,method:"de...
  function c (line 1) | function c(t,e){return Object(r["a"])({url:"/canal/instance/start/"+t+"/...
  function u (line 1) | function u(t,e){return Object(r["a"])({url:"/canal/instance/stop/"+t+"/"...
  function d (line 1) | function d(t,e){return Object(r["a"])({url:"/canal/instance/log/"+t+"/"+...
  function f (line 1) | function f(t,e){return Object(r["a"])({url:"/canal/instance/status/"+t+"...
  function p (line 1) | function p(t){return Object(r["a"])({url:"/canal/active/instances/"+t,me...

FILE: admin/admin-web/src/main/resources/public/static/js/chunk-22553be3.e6d72de5.js
  function o (line 1) | function o(t){document.documentElement.scrollTop=t,document.body.parentN...
  function c (line 1) | function c(){return document.documentElement.scrollTop||document.body.pa...
  function u (line 1) | function u(t,e,n){var a=c(),r=t-a,u=20,s=0;e="undefined"===typeof e?500:...
  function r (line 1) | function r(t){return Object(a["a"])({url:"/canal/clusters",method:"get",...
  function i (line 1) | function i(t){return Object(a["a"])({url:"/canal/cluster",method:"post",...
  function o (line 1) | function o(t){return Object(a["a"])({url:"/canal/cluster",method:"put",d...
  function c (line 1) | function c(t){return Object(a["a"])({url:"/canal/cluster/"+t,method:"del...
  function u (line 1) | function u(){return Object(a["a"])({url:"/canal/clustersAndServers",meth...
  function r (line 1) | function r(t){return Object(a["a"])({url:"/canal/instances",method:"get"...
  function i (line 1) | function i(t){return Object(a["a"])({url:"/canal/instance/"+t,method:"ge...
  function o (line 1) | function o(t){return Object(a["a"])({url:"/canal/instance",method:"put",...
  function c (line 1) | function c(t){return Object(a["a"])({url:"/canal/instance",method:"post"...
  function u (line 1) | function u(t){return Object(a["a"])({url:"/canal/instance/"+t,method:"de...
  function s (line 1) | function s(t,e){return Object(a["a"])({url:"/canal/instance/start/"+t+"/...
  function l (line 1) | function l(t,e){return Object(a["a"])({url:"/canal/instance/stop/"+t+"/"...
  function d (line 1) | function d(t,e){return Object(a["a"])({url:"/canal/instance/log/"+t+"/"+...
  function f (line 1) | function f(t,e){return Object(a["a"])({url:"/canal/instance/status/"+t+"...
  function p (line 1) | function p(t){return Object(a["a"])({url:"/canal/active/instances/"+t,me...

FILE: admin/admin-web/src/main/resources/public/static/js/chunk-2301924a.1774b851.js
  function a (line 1) | function a(t){return Object(r["a"])({url:"/canal/clusters",method:"get",...
  function c (line 1) | function c(t){return Object(r["a"])({url:"/canal/cluster",method:"post",...
  function o (line 1) | function o(t){return Object(r["a"])({url:"/canal/cluster",method:"put",d...
  function u (line 1) | function u(t){return Object(r["a"])({url:"/canal/cluster/"+t,method:"del...
  function i (line 1) | function i(){return Object(r["a"])({url:"/canal/clustersAndServers",meth...
  function a (line 1) | function a(t){return Object(r["a"])({url:"/canal/instances",method:"get"...
  function c (line 1) | function c(t){return Object(r["a"])({url:"/canal/instance/"+t,method:"ge...
  function o (line 1) | function o(t){return Object(r["a"])({url:"/canal/instance",method:"put",...
  function u (line 1) | function u(t){return Object(r["a"])({url:"/canal/instance",method:"post"...
  function i (line 1) | function i(t){return Object(r["a"])({url:"/canal/instance/"+t,method:"de...
  function s (line 1) | function s(t,e){return Object(r["a"])({url:"/canal/instance/start/"+t+"/...
  function l (line 1) | function l(t,e){return Object(r["a"])({url:"/canal/instance/stop/"+t+"/"...
  function f (line 1) | function f(t,e){return Object(r["a"])({url:"/canal/instance/log/"+t+"/"+...
  function d (line 1) | function d(t,e){return Object(r["a"])({url:"/canal/instance/status/"+t+"...
  function m (line 1) | function m(t){return Object(r["a"])({url:"/canal/active/instances/"+t,me...

FILE: admin/admin-web/src/main/resources/public/static/js/chunk-2b9b6c5c.cc2181b9.js
  function o (line 1) | function o(t){document.documentElement.scrollTop=t,document.body.parentN...
  function c (line 1) | function c(){return document.documentElement.scrollTop||document.body.pa...
  function u (line 1) | function u(t,e,n){var a=c(),r=t-a,u=20,s=0;e="undefined"===typeof e?500:...
  function r (line 1) | function r(t){return Object(a["a"])({url:"/canal/clusters",method:"get",...
  function i (line 1) | function i(t){return Object(a["a"])({url:"/canal/cluster",method:"post",...
  function o (line 1) | function o(t){return Object(a["a"])({url:"/canal/cluster",method:"put",d...
  function c (line 1) | function c(t){return Object(a["a"])({url:"/canal/cluster/"+t,method:"del...
  function u (line 1) | function u(){return Object(a["a"])({url:"/canal/clustersAndServers",meth...
  function r (line 1) | function r(t){return Object(a["a"])({url:"/canal/instances",method:"get"...
  function i (line 1) | function i(t){return Object(a["a"])({url:"/canal/instance/"+t,method:"ge...
  function o (line 1) | function o(t){return Object(a["a"])({url:"/canal/instance",method:"put",...
  function c (line 1) | function c(t){return Object(a["a"])({url:"/canal/instance",method:"post"...
  function u (line 1) | function u(t){return Object(a["a"])({url:"/canal/instance/"+t,method:"de...
  function s (line 1) | function s(t,e){return Object(a["a"])({url:"/canal/instance/start/"+t+"/...
  function l (line 1) | function l(t,e){return Object(a["a"])({url:"/canal/instance/stop/"+t+"/"...
  function d (line 1) | function d(t,e){return Object(a["a"])({url:"/canal/instance/log/"+t+"/"+...
  function f (line 1) | function f(t,e){return Object(a["a"])({url:"/canal/instance/status/"+t+"...
  function p (line 1) | function p(t){return Object(a["a"])({url:"/canal/active/instances/"+t,me...
  function m (line 1) | function m(){return Object(a["a"])({url:"/canal/instance/template",metho...

FILE: admin/admin-web/src/main/resources/public/static/js/chunk-4f09fed2.d107437b.js
  function o (line 1) | function o(t){return Object(r["a"])({url:"/nodeServers",method:"get",par...
  function c (line 1) | function c(t){return Object(r["a"])({url:"/nodeServer",method:"post",dat...
  function u (line 1) | function u(t){return Object(r["a"])({url:"/nodeServer",method:"put",data...
  function a (line 1) | function a(t){return Object(r["a"])({url:"/nodeServer/"+t,method:"delete...
  function d (line 1) | function d(t){return Object(r["a"])({url:"/nodeServer/start/"+t,method:"...
  function i (line 1) | function i(t){return Object(r["a"])({url:"/nodeServer/stop/"+t,method:"p...
  function f (line 1) | function f(t){return Object(r["a"])({url:"/nodeServer/log/"+t,method:"ge...

FILE: admin/admin-web/src/main/resources/public/static/js/chunk-4f09fed2.ff28d88d.js
  function o (line 1) | function o(t){return Object(r["a"])({url:"/nodeServers",method:"get",par...
  function c (line 1) | function c(t){return Object(r["a"])({url:"/nodeServer",method:"post",dat...
  function u (line 1) | function u(t){return Object(r["a"])({url:"/nodeServer",method:"put",data...
  function a (line 1) | function a(t){return Object(r["a"])({url:"/nodeServer/"+t,method:"delete...
  function d (line 1) | function d(t){return Object(r["a"])({url:"/nodeServer/start/"+t,method:"...
  function i (line 1) | function i(t){return Object(r["a"])({url:"/nodeServer/stop/"+t,method:"p...
  function f (line 1) | function f(t){return Object(r["a"])({url:"/nodeServer/log/"+t,method:"ge...

FILE: admin/admin-web/src/main/resources/public/static/js/chunk-55380ff2.430ee174.js
  function i (line 1) | function i(t){return Object(a["a"])({url:"/canal/clusters",method:"get",...
  function r (line 1) | function r(t){return Object(a["a"])({url:"/canal/cluster",method:"post",...
  function l (line 1) | function l(t){return Object(a["a"])({url:"/canal/cluster",method:"put",d...
  function s (line 1) | function s(t){return Object(a["a"])({url:"/canal/cluster/"+t,method:"del...
  function o (line 1) | function o(){return Object(a["a"])({url:"/canal/clustersAndServers",meth...

FILE: admin/admin-web/src/main/resources/public/static/js/chunk-55380ff2.681c71c9.js
  function i (line 1) | function i(t){return Object(a["a"])({url:"/canal/clusters",method:"get",...
  function r (line 1) | function r(t){return Object(a["a"])({url:"/canal/cluster",method:"post",...
  function l (line 1) | function l(t){return Object(a["a"])({url:"/canal/cluster",method:"put",d...
  function s (line 1) | function s(t){return Object(a["a"])({url:"/canal/cluster/"+t,method:"del...
  function o (line 1) | function o(){return Object(a["a"])({url:"/canal/clustersAndServers",meth...

FILE: admin/admin-web/src/main/resources/public/static/js/chunk-5afa45f5.79ddcc04.js
  function c (line 1) | function c(t,e){return Object(a["a"])({url:"/canal/config/"+t+"/"+e,meth...
  function i (line 1) | function i(t){return Object(a["a"])({url:"/canal/config",method:"put",da...
  function s (line 1) | function s(){return Object(a["a"])({url:"/canal/config/template",method:...

FILE: admin/admin-web/src/main/resources/public/static/js/chunk-5b373aad.90a2d8e7.js
  function a (line 1) | function a(t){return Object(r["a"])({url:"/canal/clusters",method:"get",...
  function c (line 1) | function c(t){return Object(r["a"])({url:"/canal/cluster",method:"post",...
  function o (line 1) | function o(t){return Object(r["a"])({url:"/canal/cluster",method:"put",d...
  function u (line 1) | function u(t){return Object(r["a"])({url:"/canal/cluster/"+t,method:"del...
  function i (line 1) | function i(){return Object(r["a"])({url:"/canal/clustersAndServers",meth...
  function a (line 1) | function a(t){return Object(r["a"])({url:"/canal/instances",method:"get"...
  function c (line 1) | function c(t){return Object(r["a"])({url:"/canal/instance/"+t,method:"ge...
  function o (line 1) | function o(t){return Object(r["a"])({url:"/canal/instance",method:"put",...
  function u (line 1) | function u(t){return Object(r["a"])({url:"/canal/instance",method:"post"...
  function i (line 1) | function i(t){return Object(r["a"])({url:"/canal/instance/"+t,method:"de...
  function s (line 1) | function s(t,e){return Object(r["a"])({url:"/canal/instance/start/"+t+"/...
  function l (line 1) | function l(t,e){return Object(r["a"])({url:"/canal/instance/stop/"+t+"/"...
  function f (line 1) | function f(t,e){return Object(r["a"])({url:"/canal/instance/log/"+t+"/"+...
  function d (line 1) | function d(t,e){return Object(r["a"])({url:"/canal/instance/status/"+t+"...
  function m (line 1) | function m(t){return Object(r["a"])({url:"/canal/active/instances/"+t,me...
  function p (line 1) | function p(){return Object(r["a"])({url:"/canal/instance/template",metho...

FILE: admin/admin-web/src/main/resources/public/static/js/chunk-7ec889b7.5f730d9b.js
  function r (line 1) | function r(t){return Object(c["a"])({url:"/canal/instances",method:"get"...
  function a (line 1) | function a(t){return Object(c["a"])({url:"/canal/instance/"+t,method:"ge...
  function o (line 1) | function o(t){return Object(c["a"])({url:"/canal/instance",method:"put",...
  function u (line 1) | function u(t){return Object(c["a"])({url:"/canal/instance",method:"post"...
  function i (line 1) | function i(t){return Object(c["a"])({url:"/canal/instance/"+t,method:"de...
  function f (line 1) | function f(t,n){return Object(c["a"])({url:"/canal/instance/start/"+t+"/...
  function s (line 1) | function s(t,n){return Object(c["a"])({url:"/canal/instance/stop/"+t+"/"...
  function d (line 1) | function d(t,n){return Object(c["a"])({url:"/canal/instance/log/"+t+"/"+...
  function l (line 1) | function l(t,n){return Object(c["a"])({url:"/canal/instance/status/"+t+"...
  function h (line 1) | function h(t){return Object(c["a"])({url:"/canal/active/instances/"+t,me...

FILE: admin/admin-web/src/main/resources/public/static/js/chunk-7ec889b7.bd1ca803.js
  function r (line 1) | function r(t){return Object(c["a"])({url:"/canal/instances",method:"get"...
  function a (line 1) | function a(t){return Object(c["a"])({url:"/canal/instance/"+t,method:"ge...
  function o (line 1) | function o(t){return Object(c["a"])({url:"/canal/instance",method:"put",...
  function u (line 1) | function u(t){return Object(c["a"])({url:"/canal/instance",method:"post"...
  function i (line 1) | function i(t){return Object(c["a"])({url:"/canal/instance/"+t,method:"de...
  function f (line 1) | function f(t,n){return Object(c["a"])({url:"/canal/instance/start/"+t+"/...
  function s (line 1) | function s(t,n){return Object(c["a"])({url:"/canal/instance/stop/"+t+"/"...
  function d (line 1) | function d(t,n){return Object(c["a"])({url:"/canal/instance/log/"+t+"/"+...
  function l (line 1) | function l(t,n){return Object(c["a"])({url:"/canal/instance/status/"+t+"...
  function m (line 1) | function m(t){return Object(c["a"])({url:"/canal/active/instances/"+t,me...
  function h (line 1) | function h(){return Object(c["a"])({url:"/canal/instance/template",metho...

FILE: admin/admin-web/src/main/resources/public/static/js/chunk-98f505d0.f3096ce7.js
  function i (line 1) | function i(t,e){return Object(a["a"])({url:"/canal/config/"+t+"/"+e,meth...
  function c (line 1) | function c(t){return Object(a["a"])({url:"/canal/config",method:"put",da...

FILE: admin/admin-web/src/main/resources/public/static/js/chunk-bd1d44ee.8c8282cc.js
  function o (line 1) | function o(t){return Object(r["a"])({url:"/canal/clusters",method:"get",...
  function c (line 1) | function c(t){return Object(r["a"])({url:"/canal/cluster",method:"post",...
  function a (line 1) | function a(t){return Object(r["a"])({url:"/canal/cluster",method:"put",d...
  function u (line 1) | function u(t){return Object(r["a"])({url:"/canal/cluster/"+t,method:"del...
  function i (line 1) | function i(){return Object(r["a"])({url:"/canal/clustersAndServers",meth...
  function o (line 1) | function o(t){return Object(r["a"])({url:"/canal/instances",method:"get"...
  function c (line 1) | function c(t){return Object(r["a"])({url:"/canal/instance/"+t,method:"ge...
  function a (line 1) | function a(t){return Object(r["a"])({url:"/canal/instance",method:"put",...
  function u (line 1) | function u(t){return Object(r["a"])({url:"/canal/instance",method:"post"...
  function i (line 1) | function i(t){return Object(r["a"])({url:"/canal/instance/"+t,method:"de...
  function l (line 1) | function l(t,n){return Object(r["a"])({url:"/canal/instance/start/"+t+"/...
  function s (line 1) | function s(t,n){return Object(r["a"])({url:"/canal/instance/stop/"+t+"/"...
  function d (line 1) | function d(t,n){return Object(r["a"])({url:"/canal/instance/log/"+t+"/"+...
  function f (line 1) | function f(t,n){return Object(r["a"])({url:"/canal/instance/status/"+t+"...
  function m (line 1) | function m(t){return Object(r["a"])({url:"/canal/active/instances/"+t,me...

FILE: admin/admin-web/src/main/resources/public/static/js/chunk-bd1d44ee.8e2c4851.js
  function c (line 1) | function c(t){return Object(r["a"])({url:"/canal/clusters",method:"get",...
  function o (line 1) | function o(t){return Object(r["a"])({url:"/canal/cluster",method:"post",...
  function a (line 1) | function a(t){return Object(r["a"])({url:"/canal/cluster",method:"put",d...
  function u (line 1) | function u(t){return Object(r["a"])({url:"/canal/cluster/"+t,method:"del...
  function i (line 1) | function i(){return Object(r["a"])({url:"/canal/clustersAndServers",meth...
  function c (line 1) | function c(t){return Object(r["a"])({url:"/canal/instances",method:"get"...
  function o (line 1) | function o(t){return Object(r["a"])({url:"/canal/instance/"+t,method:"ge...
  function a (line 1) | function a(t){return Object(r["a"])({url:"/canal/instance",method:"put",...
  function u (line 1) | function u(t){return Object(r["a"])({url:"/canal/instance",method:"post"...
  function i (line 1) | function i(t){return Object(r["a"])({url:"/canal/instance/"+t,method:"de...
  function l (line 1) | function l(t,n){return Object(r["a"])({url:"/canal/instance/start/"+t+"/...
  function s (line 1) | function s(t,n){return Object(r["a"])({url:"/canal/instance/stop/"+t+"/"...
  function d (line 1) | function d(t,n){return Object(r["a"])({url:"/canal/instance/log/"+t+"/"+...
  function f (line 1) | function f(t,n){return Object(r["a"])({url:"/canal/instance/status/"+t+"...
  function m (line 1) | function m(t){return Object(r["a"])({url:"/canal/active/instances/"+t,me...
  function b (line 1) | function b(){return Object(r["a"])({url:"/canal/instance/template",metho...

FILE: admin/admin-web/src/main/resources/public/static/js/chunk-da289616.7def925e.js
  function o (line 1) | function o(t){document.documentElement.scrollTop=t,document.body.parentN...
  function l (line 1) | function l(){return document.documentElement.scrollTop||document.body.pa...
  function s (line 1) | function s(t,e,n){var r=l(),a=t-r,s=20,c=0;e="undefined"===typeof e?500:...
  function a (line 1) | function a(t){return Object(r["a"])({url:"/nodeServers",method:"get",par...
  function i (line 1) | function i(t){return Object(r["a"])({url:"/nodeServer",method:"post",dat...
  function o (line 1) | function o(t){return Object(r["a"])({url:"/nodeServer",method:"put",data...
  function l (line 1) | function l(t){return Object(r["a"])({url:"/nodeServer/"+t,method:"delete...
  function s (line 1) | function s(t){return Object(r["a"])({url:"/nodeServer/start/"+t,method:"...
  function c (line 1) | function c(t){return Object(r["a"])({url:"/nodeServer/stop/"+t,method:"p...
  function u (line 1) | function u(t){return Object(r["a"])({url:"/nodeServer/log/"+t,method:"ge...
  function a (line 1) | function a(t){return Object(r["a"])({url:"/canal/clusters",method:"get",...
  function i (line 1) | function i(t){return Object(r["a"])({url:"/canal/cluster",method:"post",...
  function o (line 1) | function o(t){return Object(r["a"])({url:"/canal/cluster",method:"put",d...
  function l (line 1) | function l(t){return Object(r["a"])({url:"/canal/cluster/"+t,method:"del...
  function s (line 1) | function s(){return Object(r["a"])({url:"/canal/clustersAndServers",meth...
  function a (line 1) | function a(t){return Object(r["a"])({url:"/canal/instances",method:"get"...
  function i (line 1) | function i(t){return Object(r["a"])({url:"/canal/instance/"+t,method:"ge...
  function o (line 1) | function o(t){return Object(r["a"])({url:"/canal/instance",method:"put",...
  function l (line 1) | function l(t){return Object(r["a"])({url:"/canal/instance",method:"post"...
  function s (line 1) | function s(t){return Object(r["a"])({url:"/canal/instance/"+t,method:"de...
  function c (line 1) | function c(t,e){return Object(r["a"])({url:"/canal/instance/start/"+t+"/...
  function u (line 1) | function u(t,e){return Object(r["a"])({url:"/canal/instance/stop/"+t+"/"...
  function d (line 1) | function d(t,e){return Object(r["a"])({url:"/canal/instance/log/"+t+"/"+...
  function f (line 1) | function f(t,e){return Object(r["a"])({url:"/canal/instance/status/"+t+"...
  function p (line 1) | function p(t){return Object(r["a"])({url:"/canal/active/instances/"+t,me...
  function m (line 1) | function m(){return Object(r["a"])({url:"/canal/instance/template",metho...

FILE: admin/admin-web/src/main/resources/public/static/js/chunk-elementUI.667f4c87.js
  function i (line 1) | function i(n){if(t[n])return t[n].exports;var s=t[n]={i:n,l:!1,exports:{...
  function u (line 1) | function u(e){var t=e.move,i=e.size,n=e.bar,s={},r="translate"+n.axis+"(...
  function i (line 1) | function i(n){if(t[n])return t[n].exports;var s=t[n]={i:n,l:!1,exports:{...
  function r (line 1) | function r(e){return e&&e.__esModule?e:{default:e}}
  function o (line 1) | function o(e,t){if(!s.default.prototype.$isServer)if(t){var i=[],n=t.off...
  function r (line 1) | function r(e){return e&&e.__esModule?e:{default:e}}
  function o (line 1) | function o(e){return e&&e.__esModule?e:{default:e}}
  function h (line 1) | function h(e,t,i){return function(){var n=arguments.length>0&&void 0!==a...
  function r (line 1) | function r(e){return null!==e&&"object"===("undefined"===typeof e?"undef...
  function h (line 1) | function h(e){return e&&e.__esModule?e:{default:e}}
  function o (line 1) | function o(e){return e&&e.__esModule?e:{default:e}}
  function i (line 1) | function i(n){if(t[n])return t[n].exports;var s=t[n]={i:n,l:!1,exports:{...
  function n (line 1) | function n(e,t,i,n,s,r,o,a){var l,u="function"===typeof e?e.options:e;if...
  function d (line 1) | function d(e){return e&&e.__esModule?e:{default:e}}
  function s (line 1) | function s(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a ...
  function e (line 1) | function e(){s(this,e)}
  function o (line 1) | function o(e){return e&&e.__esModule?e:{default:e}}
  function m (line 1) | function m(e,t){if(!e||!t)return!1;if(-1!==t.indexOf(" "))throw new Erro...
  function v (line 1) | function v(e,t){if(e){for(var i=e.className,n=(t||"").split(" "),s=0,r=n...
  function g (line 1) | function g(e,t){if(e&&t){for(var i=t.split(" "),n=" "+e.className+" ",s=...
  function b (line 1) | function b(e,t,i){if(e&&t)if("object"===("undefined"===typeof t?"undefin...
  function i (line 1) | function i(n){if(t[n])return t[n].exports;var s=t[n]={i:n,l:!1,exports:{...
  function a (line 1) | function a(e,t,i,n,s,r,o,a){var l,u="function"===typeof e?e.options:e;if...
  function Ct (line 1) | function Ct(e){var t=window.getComputedStyle(e),i=t.getPropertyValue("bo...
  function wt (line 1) | function wt(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments...
  function as (line 1) | function as(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a...
  function e (line 1) | function e(t){for(var i in as(this,e),this.observers=[],this.table=null,...
  function cr (line 1) | function cr(e,t,i,n){for(var s=t;s<i;s++)e[s]=n}
  function ql (line 1) | function ql(){}
  function e (line 1) | function e(e,t){for(var i=0;i<t.length;i++){var n=t[i];n.enumerable=n.en...
  function Du (line 1) | function Du(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a...
  function e (line 1) | function e(t){for(var i in Du(this,e),this.id=Iu++,this.text=null,this.c...
  function Fu (line 1) | function Fu(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a...
  function e (line 1) | function e(t){var i=this;for(var n in Fu(this,e),this.currentNode=null,t...
  function bh (line 1) | function bh(e,t,i){var n=void 0;n=i.response?""+(i.response.error||i.res...
  function yh (line 1) | function yh(e){var t=e.responseText||e.response;if(!t)return t;try{retur...
  function _h (line 1) | function _h(e){if("undefined"!==typeof XMLHttpRequest){var t=new XMLHttp...
  function Mh (line 1) | function Mh(){}
  function op (line 1) | function op(e){var t=e.move,i=e.size,n=e.bar,s={},r="translate"+n.axis+"...
  function Xp (line 1) | function Xp(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a...
  function e (line 1) | function e(t){for(var i in Xp(this,e),this._hue=0,this._saturation=100,t...
  function i (line 1) | function i(e,i,n){this._reference=e.jquery?e[0]:e,this.state={};var s="u...
  function n (line 1) | function n(t){var i=t.style.display,n=t.style.visibility;t.style.display...
  function s (line 1) | function s(e){var t={left:"right",right:"left",bottom:"top",top:"bottom"...
  function r (line 1) | function r(e){var t=Object.assign({},e);return t.right=t.left+t.width,t....
  function o (line 1) | function o(e,t){var i,n=0;for(i in e){if(e[i]===t)return n;n++}return null}
  function a (line 1) | function a(t,i){var n=e.getComputedStyle(t,null);return n[i]}
  function l (line 1) | function l(t){var i=t.offsetParent;return i!==e.document.body&&i?i:e.doc...
  function u (line 1) | function u(t){var i=t.parentNode;return i?i===e.document?e.document.body...
  function c (line 1) | function c(t){return t!==e.document.body&&("fixed"===a(t,"position")||(t...
  function h (line 1) | function h(e,t){function i(e){return""!==e&&!isNaN(parseFloat(e))&&isFin...
  function d (line 1) | function d(e){var t={};return e&&"[object Function]"===t.toString.call(e)}
  function p (line 1) | function p(e){var t={width:e.offsetWidth,height:e.offsetHeight,left:e.of...
  function f (line 1) | function f(e){var t=e.getBoundingClientRect(),i=-1!=navigator.userAgent....
  function m (line 1) | function m(e,t,i){var n=f(e),s=f(t);if(i){var r=u(t);s.top+=r.scrollTop,...
  function v (line 1) | function v(t){for(var i=["","ms","webkit","moz","o"],n=0;n<i.length;n++)...
  function a (line 1) | function a(e,t){t.forEach(function(t){e.classList.add(t)})}
  function l (line 1) | function l(e,t){t.forEach(function(t){e.setAttribute(t.split(":")[0],t.s...
  function o (line 1) | function o(e){return e&&e.__esModule?e:{default:e}}
  function i (line 1) | function i(n){if(t[n])return t[n].exports;var s=t[n]={i:n,l:!1,exports:{...
  function n (line 1) | function n(e,t,i,n,s,r,o,a){var l,u="function"===typeof e?e.options:e;if...
  function r (line 1) | function r(e){return e&&e.__esModule?e:{default:e}}
  function a (line 1) | function a(){}
  function l (line 1) | function l(e,t){return o.call(e,t)}
  function u (line 1) | function u(e,t){for(var i in t)e[i]=t[i];return e}
  function c (line 1) | function c(e){for(var t={},i=0;i<e.length;i++)e[i]&&u(t,e[i]);return t}
  function h (line 1) | function h(e,t,i){var n=e;t=t.replace(/\[(\w+)\]/g,".$1"),t=t.replace(/^...
  function i (line 1) | function i(n){if(t[n])return t[n].exports;var s=t[n]={i:n,l:!1,exports:{...
  function n (line 1) | function n(e,t,i,n,s,r,o,a){var l,u="function"===typeof e?e.options:e;if...
  function i (line 1) | function i(n){if(t[n])return t[n].exports;var s=t[n]={i:n,l:!1,exports:{...
  function n (line 1) | function n(e,t,i,n,s,r,o,a){var l,u="function"===typeof e?e.options:e;if...
  function t (line 1) | function t(e){for(var t=arguments.length,i=Array(t>1?t-1:0),o=1;o<t;o++)...
  function i (line 1) | function i(n){if(t[n])return t[n].exports;var s=t[n]={i:n,l:!1,exports:{...
  function n (line 1) | function n(e,t,i,n,s,r,o,a){var l,u="function"===typeof e?e.options:e;if...
  function n (line 1) | function n(e,t,i){this.$children.forEach(function(s){var r=s.$options.co...
  function n (line 1) | function n(e){return void 0!==e&&null!==e}
  function s (line 1) | function s(e){var t=/([(\uAC00-\uD7AF)|(\u3130-\u318F)])+/gi;return t.te...
  function d (line 1) | function d(e,t){for(var i=[],n=0,s=e.length;n<s;n++)i.push(e[n].substr(0...
  function p (line 1) | function p(e){return function(t,i,n){var s=n[e].indexOf(i.charAt(0).toUp...
  function f (line 1) | function f(e,t){e=String(e),t=t||2;while(e.length<t)e="0"+e;return e}
  function i (line 1) | function i(n){if(t[n])return t[n].exports;var s=t[n]={i:n,l:!1,exports:{...
  function n (line 1) | function n(e,t,i,n,s,r,o,a){var l,u="function"===typeof e?e.options:e;if...
  function i (line 1) | function i(n){if(t[n])return t[n].exports;var s=t[n]={i:n,l:!1,exports:{...
  function n (line 1) | function n(e,t,i,n,s,r,o,a){var l,u="function"===typeof e?e.options:e;if...
  function r (line 1) | function r(e){return e&&e.__esModule?e:{default:e}}
  function i (line 1) | function i(n){if(t[n])return t[n].exports;var s=t[n]={i:n,l:!1,exports:{...
  function n (line 1) | function n(e,t,i,n,s,r,o,a){var l,u="function"===typeof e?e.options:e;if...
  function o (line 1) | function o(e){return e&&e.__esModule?e:{default:e}}
  function i (line 1) | function i(n){if(t[n])return t[n].exports;var s=t[n]={i:n,l:!1,exports:{...
  function n (line 1) | function n(e,t,i,n,s,r,o,a){var l,u="function"===typeof e?e.options:e;if...
  function i (line 1) | function i(n){if(t[n])return t[n].exports;var s=t[n]={i:n,l:!1,exports:{...
  function n (line 1) | function n(e,t,i,n,s,r,o,a){var l,u="function"===typeof e?e.options:e;if...
  function d (line 1) | function d(e){var t=window.getComputedStyle(e),i=t.getPropertyValue("box...
  function p (line 1) | function p(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[...

FILE: admin/admin-web/src/main/resources/public/static/js/chunk-libs.c04beefc.js
  function s (line 8) | function s(t){this.defaults=t,this.interceptors={request:new i,response:...
  function c (line 8) | function c(t){return t&&t.__esModule?t:{default:t}}
  function t (line 8) | function t(t,e){return e={exports:{}},t(e,e.exports),e.exports}
  function t (line 8) | function t(t){var e=t&&"object"===typeof t;return e&&"[object RegExp]"!=...
  function e (line 8) | function e(t){return Array.isArray(t)?[]:{}}
  function n (line 8) | function n(n,r){var o=r&&!0===r.clone;return o&&t(n)?i(e(n),n,r):n}
  function r (line 8) | function r(e,r,o){var a=e.slice();return r.forEach(function(r,s){"undefi...
  function o (line 8) | function o(e,r,o){var a={};return t(e)&&Object.keys(e).forEach(function(...
  function i (line 8) | function i(t,e,i){var a=Array.isArray(e),s=i||{arrayMerge:r},c=s.arrayMe...
  function r (line 8) | function r(t){return t=t||Object.create(null),{on:function(e,n){(t[e]||(...
  function e (line 8) | function e(){t.apply(this,arguments)}
  function k (line 8) | function k(t,e){var n=b(t).reduce(function(t,n){if(!n.attributes)return ...
  function M (line 8) | function M(t){return t.replace($,function(t){return"%"+t[0].charCodeAt(0...
  function P (line 8) | function P(t,e,n){return b(t).forEach(function(t){var r=t.getAttribute(T...
  function e (line 8) | function e(e){var o=this;void 0===e&&(e={}),t.call(this,n(g,e));var i=r(...
  function a (line 12) | function a(t,e){!r.isUndefined(t)&&r.isUndefined(t["Content-Type"])&&(t[...
  function s (line 12) | function s(){var t;return"undefined"!==typeof XMLHttpRequest?t=n("b50d")...
  function r (line 12) | function r(t,e,n,r,o,i,a,s){var c,u="function"===typeof t?t.options:t;if...
  function r (line 18) | function r(t){return void 0===t||null===t}
  function o (line 18) | function o(t){return void 0!==t&&null!==t}
  function i (line 18) | function i(t){return!0===t}
  function a (line 18) | function a(t){return!1===t}
  function s (line 18) | function s(t){return"string"===typeof t||"number"===typeof t||"symbol"==...
  function c (line 18) | function c(t){return null!==t&&"object"===typeof t}
  function f (line 18) | function f(t){return"[object Object]"===u.call(t)}
  function l (line 18) | function l(t){return"[object RegExp]"===u.call(t)}
  function p (line 18) | function p(t){var e=parseFloat(String(t));return e>=0&&Math.floor(e)===e...
  function d (line 18) | function d(t){return o(t)&&"function"===typeof t.then&&"function"===type...
  function h (line 18) | function h(t){return null==t?"":Array.isArray(t)||f(t)&&t.toString===u?J...
  function v (line 18) | function v(t){var e=parseFloat(t);return isNaN(e)?t:e}
  function y (line 18) | function y(t,e){for(var n=Object.create(null),r=t.split(","),o=0;o<r.len...
  function g (line 18) | function g(t,e){if(t.length){var n=t.indexOf(e);if(n>-1)return t.splice(...
  function _ (line 18) | function _(t,e){return b.call(t,e)}
  function w (line 18) | function w(t){var e=Object.create(null);return function(n){var r=e[n];re...
  function C (line 18) | function C(t,e){function n(n){var r=arguments.length;return r?r>1?t.appl...
  function k (line 18) | function k(t,e){return t.bind(e)}
  function T (line 18) | function T(t,e){e=e||0;var n=t.length-e,r=new Array(n);while(n--)r[n]=t[...
  function $ (line 18) | function $(t,e){for(var n in e)t[n]=e[n];return t}
  function M (line 18) | function M(t){for(var e={},n=0;n<t.length;n++)t[n]&&$(e,t[n]);return e}
  function P (line 18) | function P(t,e,n){}
  function N (line 18) | function N(t,e){if(t===e)return!0;var n=c(t),r=c(e);if(!n||!r)return!n&&...
  function F (line 18) | function F(t,e){for(var n=0;n<t.length;n++)if(N(t[n],e))return n;return-1}
  function I (line 18) | function I(t){var e=!1;return function(){e||(e=!0,t.apply(this,arguments...
  function H (line 18) | function H(t){var e=(t+"").charCodeAt(0);return 36===e||95===e}
  function z (line 18) | function z(t,e,n,r){Object.defineProperty(t,e,{value:n,enumerable:!!r,wr...
  function W (line 18) | function W(t){if(!G.test(t)){var e=t.split(".");return function(t){for(v...
  function ft (line 18) | function ft(t){return"function"===typeof t&&/native code/.test(t.toStrin...
  function t (line 18) | function t(){this.set=Object.create(null)}
  function mt (line 18) | function mt(t){yt.push(t),vt.target=t}
  function gt (line 18) | function gt(){yt.pop(),vt.target=yt[yt.length-1]}
  function xt (line 18) | function xt(t){return new bt(void 0,void 0,void 0,String(t))}
  function Ot (line 18) | function Ot(t){var e=new bt(t.tag,t.data,t.children&&t.children.slice(),...
  function jt (line 18) | function jt(t){kt=t}
  function $t (line 18) | function $t(t,e){t.__proto__=e}
  function Mt (line 18) | function Mt(t,e,n){for(var r=0,o=n.length;r<o;r++){var i=n[r];z(t,i,e[i])}}
  function Pt (line 18) | function Pt(t,e){var n;if(c(t)&&!(t instanceof bt))return _(t,"__ob__")&...
  function Lt (line 18) | function Lt(t,e,n,r,o){var i=new vt,a=Object.getOwnPropertyDescriptor(t,...
  function Rt (line 18) | function Rt(t,e,n){if(Array.isArray(t)&&p(e))return t.length=Math.max(t....
  function Nt (line 18) | function Nt(t,e){if(Array.isArray(t)&&p(e))t.splice(e,1);else{var n=t.__...
  function Ft (line 18) | function Ft(t){for(var e=void 0,n=0,r=t.length;n<r;n++)e=t[n],e&&e.__ob_...
  function Dt (line 18) | function Dt(t,e){if(!e)return t;for(var n,r,o,i=pt?Reflect.ownKeys(e):Ob...
  function qt (line 18) | function qt(t,e,n){return n?function(){var r="function"===typeof e?e.cal...
  function Ut (line 18) | function Ut(t,e){var n=e?t?t.concat(e):Array.isArray(e)?e:[e]:t;return n...
  function Bt (line 18) | function Bt(t){for(var e=[],n=0;n<t.length;n++)-1===e.indexOf(t[n])&&e.p...
  function Vt (line 18) | function Vt(t,e,n,r){var o=Object.create(t||null);return e?$(o,e):o}
  function zt (line 18) | function zt(t,e){var n=t.props;if(n){var r,o,i,a={};if(Array.isArray(n))...
  function Gt (line 18) | function Gt(t,e){var n=t.inject;if(n){var r=t.inject={};if(Array.isArray...
  function Wt (line 18) | function Wt(t){var e=t.directives;if(e)for(var n in e){var r=e[n];"funct...
  function Kt (line 18) | function Kt(t,e,n){if("function"===typeof e&&(e=e.options),zt(e,n),Gt(e,...
  function Xt (line 18) | function Xt(t,e,n,r){if("string"===typeof n){var o=t[e];if(_(o,n))return...
  function Jt (line 18) | function Jt(t,e,n,r){var o=e[t],i=!_(n,t),a=n[t],s=te(Boolean,o.type);if...
  function Yt (line 18) | function Yt(t,e,n){if(_(e,"default")){var r=e.default;return t&&t.$optio...
  function Zt (line 18) | function Zt(t){var e=t&&t.toString().match(/^\s*function (\w+)/);return ...
  function Qt (line 18) | function Qt(t,e){return Zt(t)===Zt(e)}
  function te (line 18) | function te(t,e){if(!Array.isArray(e))return Qt(e,t)?0:-1;for(var n=0,r=...
  function ee (line 18) | function ee(t,e,n){mt();try{if(e){var r=e;while(r=r.$parent){var o=r.$op...
  function ne (line 18) | function ne(t,e,n,r,o){var i;try{i=n?t.apply(e,n):t.call(e),i&&!i._isVue...
  function re (line 18) | function re(t,e,n){if(B.errorHandler)try{return B.errorHandler.call(null...
  function oe (line 18) | function oe(t,e,n){if(!J&&!Y||"undefined"===typeof console)throw t;conso...
  function ue (line 18) | function ue(){ce=!1;var t=se.slice(0);se.length=0;for(var e=0;e<t.length...
  function he (line 18) | function he(t,e){var n;if(se.push(function(){if(t)try{t.call(e)}catch(Oa...
  function ye (line 18) | function ye(t){me(t,ve),ve.clear()}
  function me (line 18) | function me(t,e){var n,r,o=Array.isArray(t);if(!(!o&&!c(t)||Object.isFro...
  function be (line 18) | function be(t,e){function n(){var t=arguments,r=n.fns;if(!Array.isArray(...
  function _e (line 18) | function _e(t,e,n,o,a,s){var c,u,f,l;for(c in t)u=t[c],f=e[c],l=ge(c),r(...
  function we (line 18) | function we(t,e,n){var a;t instanceof bt&&(t=t.data.hook||(t.data.hook={...
  function xe (line 18) | function xe(t,e,n){var i=e.options.props;if(!r(i)){var a={},s=t.attrs,c=...
  function Oe (line 18) | function Oe(t,e,n,r,i){if(o(e)){if(_(e,n))return t[n]=e[n],i||delete e[n...
  function Ee (line 18) | function Ee(t){for(var e=0;e<t.length;e++)if(Array.isArray(t[e]))return ...
  function Se (line 18) | function Se(t){return s(t)?[xt(t)]:Array.isArray(t)?Ce(t):void 0}
  function Ae (line 18) | function Ae(t){return o(t)&&o(t.text)&&a(t.isComment)}
  function Ce (line 18) | function Ce(t,e){var n,a,c,u,f=[];for(n=0;n<t.length;n++)a=t[n],r(a)||"b...
  function ke (line 18) | function ke(t){var e=t.$options.provide;e&&(t._provided="function"===typ...
  function je (line 18) | function je(t){var e=Te(t.$options.inject,t);e&&(jt(!1),Object.keys(e).f...
  function Te (line 18) | function Te(t,e){if(t){for(var n=Object.create(null),r=pt?Reflect.ownKey...
  function $e (line 18) | function $e(t,e){if(!t||!t.length)return{};for(var n={},r=0,o=t.length;r...
  function Me (line 18) | function Me(t){return t.isComment&&!t.asyncFactory||" "===t.text}
  function Pe (line 18) | function Pe(t,e,r){var o,i=Object.keys(e).length>0,a=t?!!t.$stable:!i,s=...
  function Le (line 18) | function Le(t,e,n){var r=function(){var t=arguments.length?n.apply(null,...
  function Re (line 18) | function Re(t,e){return function(){return t[e]}}
  function Ne (line 18) | function Ne(t,e){var n,r,i,a,s;if(Array.isArray(t)||"string"===typeof t)...
  function Fe (line 18) | function Fe(t,e,n,r){var o,i=this.$scopedSlots[t];i?(n=n||{},r&&(n=$($({...
  function Ie (line 18) | function Ie(t){return Xt(this.$options,"filters",t,!0)||R}
  function De (line 18) | function De(t,e){return Array.isArray(t)?-1===t.indexOf(e):t!==e}
  function qe (line 18) | function qe(t,e,n,r,o){var i=B.keyCodes[e]||n;return o&&r&&!B.keyCodes[e...
  function Ue (line 18) | function Ue(t,e,n,r,o){if(n)if(c(n)){var i;Array.isArray(n)&&(n=M(n));va...
  function Be (line 18) | function Be(t,e){var n=this._staticTrees||(this._staticTrees=[]),r=n[t];...
  function Ve (line 18) | function Ve(t,e,n){return He(t,"__once__"+e+(n?"_"+n:""),!0),t}
  function He (line 18) | function He(t,e,n){if(Array.isArray(t))for(var r=0;r<t.length;r++)t[r]&&...
  function ze (line 18) | function ze(t,e,n){t.isStatic=!0,t.key=e,t.isOnce=n}
  function Ge (line 18) | function Ge(t,e){if(e)if(f(e)){var n=t.on=t.on?$({},t.on):{};for(var r i...
  function We (line 18) | function We(t,e,n,r){e=e||{$stable:!n};for(var o=0;o<t.length;o++){var i...
  function Ke (line 18) | function Ke(t,e){for(var n=0;n<e.length;n+=2){var r=e[n];"string"===type...
  function Xe (line 18) | function Xe(t,e){return"string"===typeof t?e+t:t}
  function Je (line 18) | function Je(t){t._o=Ve,t._n=v,t._s=h,t._l=Ne,t._t=Fe,t._q=N,t._i=F,t._m=...
  function Ye (line 18) | function Ye(t,e,r,o,a){var s,c=this,u=a.options;_(o,"_uid")?(s=Object.cr...
  function Ze (line 18) | function Ze(t,e,r,i,a){var s=t.options,c={},u=s.props;if(o(u))for(var f ...
  function Qe (line 18) | function Qe(t,e,n,r,o){var i=Ot(t);return i.fnContext=n,i.fnOptions=r,e....
  function tn (line 18) | function tn(t,e){for(var n in e)t[O(n)]=e[n]}
  function rn (line 18) | function rn(t,e,n,a,s){if(!r(t)){var u=n.$options._base;if(c(t)&&(t=u.ex...
  function on (line 18) | function on(t,e){var n={_isComponent:!0,_parentVnode:t,parent:e},r=t.dat...
  function an (line 18) | function an(t){for(var e=t.hook||(t.hook={}),n=0;n<nn.length;n++){var r=...
  function sn (line 18) | function sn(t,e){var n=function(n,r){t(n,r),e(n,r)};return n._merged=!0,n}
  function cn (line 18) | function cn(t,e){var n=t.model&&t.model.prop||"value",r=t.model&&t.model...
  function ln (line 18) | function ln(t,e,n,r,o,a){return(Array.isArray(n)||s(n))&&(o=r,r=n,n=void...
  function pn (line 18) | function pn(t,e,n,r,i){if(o(n)&&o(n.__ob__))return wt();if(o(n)&&o(n.is)...
  function dn (line 18) | function dn(t,e,n){if(t.ns=e,"foreignObject"===t.tag&&(e=void 0,n=!0),o(...
  function hn (line 18) | function hn(t){c(t.style)&&ye(t.style),c(t.class)&&ye(t.class)}
  function vn (line 18) | function vn(t){t._vnode=null,t._staticTrees=null;var e=t.$options,r=t.$v...
  function gn (line 18) | function gn(t){Je(t.prototype),t.prototype.$nextTick=function(t){return ...
  function bn (line 18) | function bn(t,e){return(t.__esModule||pt&&"Module"===t[Symbol.toStringTa...
  function _n (line 18) | function _n(t,e,n,r,o){var i=wt();return i.asyncFactory=t,i.asyncMeta={d...
  function wn (line 18) | function wn(t,e){if(i(t.error)&&o(t.errorComp))return t.errorComp;if(o(t...
  function xn (line 18) | function xn(t){return t.isComment&&t.asyncFactory}
  function On (line 18) | function On(t){if(Array.isArray(t))for(var e=0;e<t.length;e++){var n=t[e...
  function En (line 18) | function En(t){t._events=Object.create(null),t._hasHookEvent=!1;var e=t....
  function Sn (line 18) | function Sn(t,e){yn.$on(t,e)}
  function An (line 18) | function An(t,e){yn.$off(t,e)}
  function Cn (line 18) | function Cn(t,e){var n=yn;return function r(){var o=e.apply(null,argumen...
  function kn (line 18) | function kn(t,e,n){yn=t,_e(e,n||{},Sn,An,Cn,t),yn=void 0}
  function jn (line 18) | function jn(t){var e=/^hook:/;t.prototype.$on=function(t,n){var r=this;i...
  function $n (line 18) | function $n(t){var e=Tn;return Tn=t,function(){Tn=e}}
  function Mn (line 18) | function Mn(t){var e=t.$options,n=e.parent;if(n&&!e.abstract){while(n.$o...
  function Pn (line 18) | function Pn(t){t.prototype._update=function(t,e){var n=this,r=n.$el,o=n....
  function Ln (line 18) | function Ln(t,e,n){var r;return t.$el=e,t.$options.render||(t.$options.r...
  function Rn (line 18) | function Rn(t,e,r,o,i){var a=o.data.scopedSlots,s=t.$scopedSlots,c=!!(a&...
  function Nn (line 18) | function Nn(t){while(t&&(t=t.$parent))if(t._inactive)return!0;return!1}
  function Fn (line 18) | function Fn(t,e){if(e){if(t._directInactive=!1,Nn(t))return}else if(t._d...
  function In (line 18) | function In(t,e){if((!e||(t._directInactive=!0,!Nn(t)))&&!t._inactive){t...
  function Dn (line 18) | function Dn(t,e){mt();var n=t.$options[e],r=e+" hook";if(n)for(var o=0,i...
  function Gn (line 18) | function Gn(){zn=qn.length=Un.length=0,Bn={},Vn=Hn=!1}
  function Jn (line 18) | function Jn(){var t,e;for(Wn=Kn(),Hn=!0,qn.sort(function(t,e){return t.i...
  function Yn (line 18) | function Yn(t){var e=t.length;while(e--){var n=t[e],r=n.vm;r._watcher===...
  function Zn (line 18) | function Zn(t){t._inactive=!1,Un.push(t)}
  function Qn (line 18) | function Qn(t){for(var e=0;e<t.length;e++)t[e]._inactive=!0,Fn(t[e],!0)}
  function tr (line 18) | function tr(t){var e=t.id;if(null==Bn[e]){if(Bn[e]=!0,Hn){var n=qn.lengt...
  function or (line 18) | function or(t,e,n){rr.get=function(){return this[e][n]},rr.set=function(...
  function ir (line 18) | function ir(t){t._watchers=[];var e=t.$options;e.props&&ar(t,e.props),e....
  function ar (line 18) | function ar(t,e){var n=t.$options.propsData||{},r=t._props={},o=t.$optio...
  function sr (line 18) | function sr(t){var e=t.$options.data;e=t._data="function"===typeof e?cr(...
  function cr (line 18) | function cr(t,e){mt();try{return t.call(e,e)}catch(Oa){return ee(Oa,e,"d...
  function fr (line 18) | function fr(t,e){var n=t._computedWatchers=Object.create(null),r=ct();fo...
  function lr (line 18) | function lr(t,e,n){var r=!ct();"function"===typeof n?(rr.get=r?pr(e):dr(...
  function pr (line 18) | function pr(t){return function(){var e=this._computedWatchers&&this._com...
  function dr (line 18) | function dr(t){return function(){return t.call(this,this)}}
  function hr (line 18) | function hr(t,e){t.$options.props;for(var n in e)t[n]="function"!==typeo...
  function vr (line 18) | function vr(t,e){for(var n in e){var r=e[n];if(Array.isArray(r))for(var ...
  function yr (line 18) | function yr(t,e,n,r){return f(n)&&(r=n,n=n.handler),"string"===typeof n&...
  function mr (line 18) | function mr(t){var e={get:function(){return this._data}},n={get:function...
  function br (line 18) | function br(t){t.prototype._init=function(t){var e=this;e._uid=gr++,e._i...
  function _r (line 18) | function _r(t,e){var n=t.$options=Object.create(t.constructor.options),r...
  function wr (line 18) | function wr(t){var e=t.options;if(t.super){var n=wr(t.super),r=t.superOp...
  function xr (line 18) | function xr(t){var e,n=t.options,r=t.sealedOptions;for(var o in n)n[o]!=...
  function Or (line 18) | function Or(t){this._init(t)}
  function Er (line 18) | function Er(t){t.use=function(t){var e=this._installedPlugins||(this._in...
  function Sr (line 18) | function Sr(t){t.mixin=function(t){return this.options=Kt(this.options,t...
  function Ar (line 18) | function Ar(t){t.cid=0;var e=1;t.extend=function(t){t=t||{};var n=this,r...
  function Cr (line 18) | function Cr(t){var e=t.options.props;for(var n in e)or(t.prototype,"_pro...
  function kr (line 18) | function kr(t){var e=t.options.computed;for(var n in e)lr(t.prototype,n,...
  function jr (line 18) | function jr(t){q.forEach(function(e){t[e]=function(t,n){return n?("compo...
  function Tr (line 18) | function Tr(t){return t&&(t.Ctor.options.name||t.tag)}
  function $r (line 18) | function $r(t,e){return Array.isArray(t)?t.indexOf(e)>-1:"string"===type...
  function Mr (line 18) | function Mr(t,e){var n=t.cache,r=t.keys,o=t._vnode;for(var i in n){var a...
  function Pr (line 18) | function Pr(t,e,n,r){var o=t[e];!o||r&&o.tag===r.tag||o.componentInstanc...
  function Fr (line 18) | function Fr(t){var e={get:function(){return B}};Object.defineProperty(t,...
  function Xr (line 18) | function Xr(t){var e=t.data,n=t,r=t;while(o(r.componentInstance))r=r.com...
  function Jr (line 18) | function Jr(t,e){return{staticClass:Zr(t.staticClass,e.staticClass),clas...
  function Yr (line 18) | function Yr(t,e){return o(t)||o(e)?Zr(t,Qr(e)):""}
  function Zr (line 18) | function Zr(t,e){return t?e?t+" "+e:t:e||""}
  function Qr (line 18) | function Qr(t){return Array.isArray(t)?to(t):c(t)?eo(t):"string"===typeo...
  function to (line 18) | function to(t){for(var e,n="",r=0,i=t.length;r<i;r++)o(e=Qr(t[r]))&&""!=...
  function eo (line 18) | function eo(t){var e="";for(var n in t)t[n]&&(e&&(e+=" "),e+=n);return e}
  function ao (line 18) | function ao(t){return oo(t)?"svg":"math"===t?"math":void 0}
  function co (line 18) | function co(t){if(!J)return!0;if(io(t))return!1;if(t=t.toLowerCase(),nul...
  function fo (line 18) | function fo(t){if("string"===typeof t){var e=document.querySelector(t);r...
  function lo (line 18) | function lo(t,e){var n=document.createElement(t);return"select"!==t?n:(e...
  function po (line 18) | function po(t,e){return document.createElementNS(no[t],e)}
  function ho (line 18) | function ho(t){return document.createTextNode(t)}
  function vo (line 18) | function vo(t){return document.createComment(t)}
  function yo (line 18) | function yo(t,e,n){t.insertBefore(e,n)}
  function mo (line 18) | function mo(t,e){t.removeChild(e)}
  function go (line 18) | function go(t,e){t.appendChild(e)}
  function bo (line 18) | function bo(t){return t.parentNode}
  function _o (line 18) | function _o(t){return t.nextSibling}
  function wo (line 18) | function wo(t){return t.tagName}
  function xo (line 18) | function xo(t,e){t.textContent=e}
  function Oo (line 18) | function Oo(t,e){t.setAttribute(e,"")}
  function Ao (line 18) | function Ao(t,e){var n=t.data.ref;if(o(n)){var r=t.context,i=t.component...
  function jo (line 18) | function jo(t,e){return t.key===e.key&&(t.tag===e.tag&&t.isComment===e.i...
  function To (line 18) | function To(t,e){if("input"!==t.tag)return!0;var n,r=o(n=t.data)&&o(n=n....
  function $o (line 18) | function $o(t,e,n){var r,i,a={};for(r=e;r<=n;++r)i=t[r].key,o(i)&&(a[i]=...
  function Mo (line 18) | function Mo(t){var e,n,a={},c=t.modules,u=t.nodeOps;for(e=0;e<ko.length;...
  function Lo (line 18) | function Lo(t,e){(t.data.directives||e.data.directives)&&Ro(t,e)}
  function Ro (line 18) | function Ro(t,e){var n,r,o,i=t===Co,a=e===Co,s=Fo(t.data.directives,t.co...
  function Fo (line 18) | function Fo(t,e){var n,r,o=Object.create(null);if(!t)return o;for(n=0;n<...
  function Io (line 18) | function Io(t){return t.rawName||t.name+"."+Object.keys(t.modifiers||{})...
  function Do (line 18) | function Do(t,e,n,r,o){var i=t.def&&t.def[e];if(i)try{i(n.elm,t,n,r,o)}c...
  function Uo (line 18) | function Uo(t,e){var n=e.componentOptions;if((!o(n)||!1!==n.Ctor.options...
  function Bo (line 18) | function Bo(t,e,n){t.tagName.indexOf("-")>-1?Vo(t,e,n):Hr(e)?Kr(n)?t.rem...
  function Vo (line 18) | function Vo(t,e,n){if(Kr(n))t.removeAttribute(e);else{if(tt&&!et&&"TEXTA...
  function zo (line 18) | function zo(t,e){var n=e.elm,i=e.data,a=t.data;if(!(r(i.staticClass)&&r(...
  function Jo (line 18) | function Jo(t){if(o(t[Ko])){var e=tt?"change":"input";t[e]=[].concat(t[K...
  function Yo (line 18) | function Yo(t,e,n){var r=Go;return function o(){var i=e.apply(null,argum...
  function Qo (line 18) | function Qo(t,e,n,r){if(Zo){var o=Wn,i=e;e=i._wrapper=function(t){if(t.t...
  function ti (line 18) | function ti(t,e,n,r){(r||Go).removeEventListener(t,e._wrapper||e,n)}
  function ei (line 18) | function ei(t,e){if(!r(t.data.on)||!r(e.data.on)){var n=e.data.on||{},o=...
  function oi (line 18) | function oi(t,e){if(!r(t.data.domProps)||!r(e.data.domProps)){var n,i,a=...
  function ii (line 18) | function ii(t,e){return!t.composing&&("OPTION"===t.tagName||ai(t,e)||si(...
  function ai (line 18) | function ai(t,e){var n=!0;try{n=document.activeElement!==t}catch(Oa){}re...
  function si (line 18) | function si(t,e){var n=t.value,r=t._vModifiers;if(o(r)){if(r.number)retu...
  function fi (line 18) | function fi(t){var e=li(t.style);return t.staticStyle?$(t.staticStyle,e):e}
  function li (line 18) | function li(t){return Array.isArray(t)?M(t):"string"===typeof t?ui(t):t}
  function pi (line 18) | function pi(t,e){var n,r={};if(e){var o=t;while(o.componentInstance)o=o....
  function bi (line 18) | function bi(t,e){var n=e.data,i=t.data;if(!(r(n.staticStyle)&&r(n.style)...
  function xi (line 18) | function xi(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.s...
  function Oi (line 18) | function Oi(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.s...
  function Ei (line 18) | function Ei(t){if(t){if("object"===typeof t){var e={};return!1!==t.css&&...
  function Li (line 18) | function Li(t){Pi(function(){Pi(t)})}
  function Ri (line 18) | function Ri(t,e){var n=t._transitionClasses||(t._transitionClasses=[]);n...
  function Ni (line 18) | function Ni(t,e){t._transitionClasses&&g(t._transitionClasses,e),Oi(t,e)}
  function Fi (line 18) | function Fi(t,e,n){var r=Di(t,e),o=r.type,i=r.timeout,a=r.propCount;if(!...
  function Di (line 18) | function Di(t,e){var n,r=window.getComputedStyle(t),o=(r[ji+"Delay"]||""...
  function qi (line 18) | function qi(t,e){while(t.length<e.length)t=t.concat(t);return Math.max.a...
  function Ui (line 18) | function Ui(t){return 1e3*Number(t.slice(0,-1).replace(",","."))}
  function Bi (line 18) | function Bi(t,e){var n=t.elm;o(n._leaveCb)&&(n._leaveCb.cancelled=!0,n._...
  function Vi (line 18) | function Vi(t,e){var n=t.elm;o(n._enterCb)&&(n._enterCb.cancelled=!0,n._...
  function Hi (line 18) | function Hi(t){return"number"===typeof t&&!isNaN(t)}
  function zi (line 18) | function zi(t){if(r(t))return!1;var e=t.fns;return o(e)?zi(Array.isArray...
  function Gi (line 18) | function Gi(t,e){!0!==e.data.show&&Bi(e)}
  function Zi (line 18) | function Zi(t,e,n){Qi(t,e,n),(tt||nt)&&setTimeout(function(){Qi(t,e,n)},0)}
  function Qi (line 18) | function Qi(t,e,n){var r=e.value,o=t.multiple;if(!o||Array.isArray(r)){f...
  function ta (line 18) | function ta(t,e){return e.every(function(e){return!N(e,t)})}
  function ea (line 18) | function ea(t){return"_value"in t?t._value:t.value}
  function na (line 18) | function na(t){t.target.composing=!0}
  function ra (line 18) | function ra(t){t.target.composing&&(t.target.composing=!1,oa(t.target,"i...
  function oa (line 18) | function oa(t,e){var n=document.createEvent("HTMLEvents");n.initEvent(e,...
  function ia (line 18) | function ia(t){return!t.componentInstance||t.data&&t.data.transition?t:i...
  function ua (line 18) | function ua(t){var e=t&&t.componentOptions;return e&&e.Ctor.options.abst...
  function fa (line 18) | function fa(t){var e={},n=t.$options;for(var r in n.propsData)e[r]=t[r];...
  function la (line 18) | function la(t,e){if(/\d-keep-alive$/.test(e.tag))return t("keep-alive",{...
  function pa (line 18) | function pa(t){while(t=t.parent)if(t.data.transition)return!0}
  function da (line 18) | function da(t,e){return e.key===t.key&&e.tag===t.tag}
  function ba (line 18) | function ba(t){t.elm._moveCb&&t.elm._moveCb(),t.elm._enterCb&&t.elm._ent...
  function _a (line 18) | function _a(t){t.data.newPos=t.elm.getBoundingClientRect()}
  function wa (line 18) | function wa(t){var e=t.data.pos,n=t.data.newPos,r=e.left-n.left,o=e.top-...
  function r (line 24) | function r(t){var e=Number(t.version.split(".")[0]);if(e>=2)t.mixin({bef...
  function i (line 24) | function i(t){o&&(t._devtoolHook=o,o.emit("vuex:init",t),o.on("vuex:trav...
  function a (line 24) | function a(t,e){Object.keys(t).forEach(function(n){return e(t[n],n)})}
  function s (line 24) | function s(t){return null!==t&&"object"===typeof t}
  function c (line 24) | function c(t){return t&&"function"===typeof t.then}
  function p (line 24) | function p(t,e,n){if(e.update(n),n.modules)for(var r in n.modules){if(!e...
  function y (line 24) | function y(t,e){return e.indexOf(t)<0&&e.push(t),function(){var n=e.inde...
  function m (line 24) | function m(t,e){t._actions=Object.create(null),t._mutations=Object.creat...
  function g (line 24) | function g(t,e,n){var r=t._vm;t.getters={};var o=t._wrappedGetters,i={};...
  function b (line 24) | function b(t,e,n,r,o){var i=!n.length,a=t._modules.getNamespace(n);if(r....
  function _ (line 24) | function _(t,e,n){var r=""===e,o={dispatch:r?t.dispatch:function(n,r,o){...
  function w (line 24) | function w(t,e){var n={},r=e.length;return Object.keys(t.getters).forEac...
  function x (line 24) | function x(t,e,n,r){var o=t._mutations[e]||(t._mutations[e]=[]);o.push(f...
  function O (line 24) | function O(t,e,n,r){var o=t._actions[e]||(t._actions[e]=[]);o.push(funct...
  function E (line 24) | function E(t,e,n,r){t._wrappedGetters[e]||(t._wrappedGetters[e]=function...
  function S (line 24) | function S(t){t._vm.$watch(function(){return this._data.$$state},functio...
  function A (line 24) | function A(t,e){return e.length?e.reduce(function(t,e){return t[e]},t):t}
  function C (line 24) | function C(t,e,n){return s(t)&&t.type&&(n=e,e=t,t=t.type),{type:t,payloa...
  function k (line 24) | function k(t){d&&t===d||(d=t,r(d))}
  function L (line 24) | function L(t){return Array.isArray(t)?t.map(function(t){return{key:t,val...
  function R (line 24) | function R(t){return function(e,n){return"string"!==typeof e?(n=e,e=""):...
  function N (line 24) | function N(t,e,n){var r=t._modulesNamespaceMap[n];return r}
  function o (line 24) | function o(t){return encodeURIComponent(t).replace(/%40/gi,"@").replace(...
  function n (line 26) | function n(t,e,n){return t<e?e:t>n?n:t}
  function r (line 26) | function r(t){return 100*(-1+t)}
  function o (line 26) | function o(t,n,o){var i;return i="translate3d"===e.positionUsing?{transf...
  function e (line 26) | function e(){var n=t.shift();n&&n(e)}
  function n (line 26) | function n(t){return t.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,fun...
  function r (line 26) | function r(e){var n=document.body.style;if(e in n)return e;var r,o=t.len...
  function o (line 26) | function o(t){return t=n(t),e[t]||(e[t]=r(t))}
  function i (line 26) | function i(t,e,n){e=o(e),t.style[e]=n}
  function s (line 26) | function s(t,e){var n="string"==typeof t?t:f(t);return n.indexOf(" "+e+"...
  function c (line 26) | function c(t,e){var n=f(t),r=n+e;s(n,e)||(t.className=r.substring(1))}
  function u (line 26) | function u(t,e){var n,r=f(t);s(t,e)&&(n=r.replace(" "+e+" "," "),t.class...
  function f (line 26) | function f(t){return(" "+(t.className||"")+" ").replace(/\s+/gi," ")}
  function l (line 26) | function l(t){t&&t.parentNode&&t.parentNode.removeChild(t)}
  function o (line 26) | function o(t){var r=t;return e&&(n.setAttribute("href",r),r=n.href),n.se...
  function i (line 26) | function i(t,e,n,r,i,a,s){try{var c=t[a](s),u=c.value}catch(f){return vo...
  function a (line 26) | function a(t){return function(){var e=this,n=arguments;return new o.a(fu...
  function o (line 26) | function o(t){return!!t&&"object"===typeof t}
  function i (line 26) | function i(t){var e=Object.prototype.toString.call(t);return"[object Reg...
  function c (line 26) | function c(t){return t.$$typeof===s}
  function u (line 26) | function u(t){return Array.isArray(t)?[]:{}}
  function f (line 26) | function f(t,e){var n=e&&!0===e.clone;return n&&r(t)?d(u(t),t,e):t}
  function l (line 26) | function l(t,e,n){var o=t.slice();return e.forEach(function(e,i){"undefi...
  function p (line 26) | function p(t,e,n){var o={};return r(t)&&Object.keys(t).forEach(function(...
  function d (line 26) | function d(t,e,n){var r=Array.isArray(e),o=Array.isArray(t),i=n||{arrayM...
  function i (line 26) | function i(t){return t&&t.__esModule?t:{default:t}}
  function u (line 26) | function u(t){t.cancelToken&&t.cancelToken.throwIfRequested()}
  function a (line 26) | function a(){var a=this,s=Number(new Date)-i,c=arguments;function u(){i=...
  function o (line 26) | function o(t){var e,n;this.promise=new t(function(t,r){if(void 0!==e||vo...
  function t (line 26) | function t(t,e){var n=-1;return t.some(function(t,r){return t[0]===e&&(n...
  function e (line 26) | function e(){this.__entries__=[]}
  function s (line 26) | function s(t,e){var n=!1,r=!1,o=0;function s(){n&&(n=!1,t()),r&&u()}func...
  function t (line 26) | function t(){this.connected_=!1,this.mutationEventsAdded_=!1,this.mutati...
  function v (line 26) | function v(t){return parseFloat(t)||0}
  function y (line 26) | function y(t){for(var e=[],n=1;n<arguments.length;n++)e[n-1]=arguments[n...
  function m (line 26) | function m(t){for(var e=["top","right","bottom","left"],n={},r=0,o=e;r<o...
  function g (line 26) | function g(t){var e=t.getBBox();return E(0,0,e.width,e.height)}
  function b (line 26) | function b(t){var e=t.clientWidth,n=t.clientHeight;if(!e&&!n)return h;va...
  function w (line 26) | function w(t){return t===d(t).document.documentElement}
  function x (line 26) | function x(t){return r?_(t)?g(t):b(t):h}
  function O (line 26) | function O(t){var e=t.x,n=t.y,r=t.width,o=t.height,i="undefined"!==typeo...
  function E (line 26) | function E(t,e,n,r){return{x:t,y:e,width:n,height:r}}
  function t (line 26) | function t(t){this.broadcastWidth=0,this.broadcastHeight=0,this.contentR...
  function t (line 26) | function t(t,e){var n=O(e);p(this,{target:t,contentRect:n})}
  function t (line 26) | function t(t,e,r){if(this.activeObservations_=[],this.observations_=new ...
  function t (line 26) | function t(e){if(!(this instanceof t))throw new TypeError("Cannot call a...
  function r (line 26) | function r(t){this.message=t}
  function i (line 41) | function i(t,e){if(!o.canUseDOM||e&&!("addEventListener"in document))ret...
  function r (line 46) | function r(t,e){0}
  function o (line 46) | function o(t){return Object.prototype.toString.call(t).indexOf("Error")>-1}
  function i (line 46) | function i(t,e){for(var n in e)t[n]=e[n];return t}
  function s (line 46) | function s(t,e){switch(typeof e){case"undefined":return;case"object":ret...
  function d (line 46) | function d(t,e,n){void 0===e&&(e={});var r,o=n||h;try{r=o(t||"")}catch(a...
  function h (line 46) | function h(t){var e={};return t=t.trim().replace(/^(\?|#|&)/,""),t?(t.sp...
  function v (line 46) | function v(t){var e=t?Object.keys(t).map(function(e){var n=t[e];if(void ...
  function m (line 46) | function m(t,e,n,r){var o=r&&r.options.stringifyQuery,i=e.query||{};try{...
  function g (line 46) | function g(t){if(Array.isArray(t))return t.map(g);if(t&&"object"===typeo...
  function _ (line 46) | function _(t){var e=[];while(t)e.unshift(t),t=t.parent;return e}
  function w (line 46) | function w(t,e){var n=t.path,r=t.query;void 0===r&&(r={});var o=t.hash;v...
  function x (line 46) | function x(t,e){return e===b?t===e:!!e&&(t.path&&e.path?t.path.replace(y...
  function O (line 46) | function O(t,e){if(void 0===t&&(t={}),void 0===e&&(e={}),!t||!e)return t...
  function E (line 46) | function E(t,e){return 0===t.path.replace(y,"/").indexOf(e.path.replace(...
  function S (line 46) | function S(t,e){for(var n in e)if(!(n in t))return!1;return!0}
  function T (line 46) | function T(t){if(!(t.metaKey||t.altKey||t.ctrlKey||t.shiftKey)&&!t.defau...
  function $ (line 46) | function $(t){if(t)for(var e,n=0;n<t.length;n++){if(e=t[n],"a"===e.tag)r...
  function M (line 46) | function M(t){if(!M.installed||A!==t){M.installed=!0,A=t;var e=function(...
  function L (line 46) | function L(t,e,n){var r=t.charAt(0);if("/"===r)return t;if("?"===r||"#"=...
  function R (line 46) | function R(t){var e="",n="",r=t.indexOf("#");r>=0&&(e=t.slice(r),t=t.sli...
  function N (line 46) | function N(t){return t.replace(/\/\//g,"/")}
  function H (line 46) | function H(t,e){var n,r=[],o=0,i=0,a="",s=e&&e.delimiter||"/";while(null...
  function z (line 46) | function z(t,e){return K(H(t,e))}
  function G (line 46) | function G(t){return encodeURI(t).replace(/[\/?#]/g,function(t){return"%...
  function W (line 46) | function W(t){return encodeURI(t).replace(/[?#]/g,function(t){return"%"+...
  function K (line 46) | function K(t){for(var e=new Array(t.length),n=0;n<t.length;n++)"object"=...
  function X (line 46) | function X(t){return t.replace(/([.+*?=^!:${}()[\]|\/\\])/g,"\\$1")}
  function J (line 46) | function J(t){return t.replace(/([=!:$\/()])/g,"\\$1")}
  function Y (line 46) | function Y(t,e){return t.keys=e,t}
  function Z (line 46) | function Z(t){return t.sensitive?"":"i"}
  function Q (line 46) | function Q(t,e){var n=t.source.match(/\((?!\?)/g);if(n)for(var r=0;r<n.l...
  function tt (line 46) | function tt(t,e,n){for(var r=[],o=0;o<t.length;o++)r.push(rt(t[o],e,n).s...
  function et (line 46) | function et(t,e,n){return nt(H(t,n),e,n)}
  function nt (line 46) | function nt(t,e,n){F(e)||(n=e||n,e=[]),n=n||{};for(var r=n.strict,o=!1!=...
  function rt (line 46) | function rt(t,e,n){return F(e)||(n=e||n,e=[]),n=n||{},t instanceof RegEx...
  function it (line 46) | function it(t,e,n){e=e||{};try{var r=ot[t]||(ot[t]=I.compile(t));return ...
  function at (line 46) | function at(t,e,n,r){var o=e||[],i=n||Object.create(null),a=r||Object.cr...
  function st (line 46) | function st(t,e,n,r,o,i){var a=r.path,s=r.name;var c=r.pathToRegexpOptio...
  function ct (line 46) | function ct(t,e){var n=I(t,[],e);return n}
  function ut (line 46) | function ut(t,e,n){return n||(t=t.replace(/\/$/,"")),"/"===t[0]?t:null==...
  function ft (line 46) | function ft(t,e,n,r){var o="string"===typeof t?{path:t}:t;if(o._normaliz...
  function lt (line 46) | function lt(t,e){var n=at(t),r=n.pathList,o=n.pathMap,i=n.nameMap;functi...
  function pt (line 46) | function pt(t,e,n){var r=e.match(t);if(!r)return!1;if(!n)return!0;for(va...
  function dt (line 46) | function dt(t,e){return L(t,e.parent?e.parent.path:"/",!0)}
  function vt (line 46) | function vt(){window.history.replaceState({key:jt()},"",window.location....
  function yt (line 46) | function yt(t,e,n,r){if(t.app){var o=t.options.scrollBehavior;o&&t.app.$...
  function mt (line 46) | function mt(){var t=jt();t&&(ht[t]={x:window.pageXOffset,y:window.pageYO...
  function gt (line 46) | function gt(){var t=jt();if(t)return ht[t]}
  function bt (line 46) | function bt(t,e){var n=document.documentElement,r=n.getBoundingClientRec...
  function _t (line 46) | function _t(t){return Ot(t.x)||Ot(t.y)}
  function wt (line 46) | function wt(t){return{x:Ot(t.x)?t.x:window.pageXOffset,y:Ot(t.y)?t.y:win...
  function xt (line 46) | function xt(t){return{x:Ot(t.x)?t.x:0,y:Ot(t.y)?t.y:0}}
  function Ot (line 46) | function Ot(t){return"number"===typeof t}
  function Et (line 46) | function Et(t,e){var n="object"===typeof t;if(n&&"string"===typeof t.sel...
  function kt (line 46) | function kt(){return At.now().toFixed(3)}
  function jt (line 46) | function jt(){return Ct}
  function Tt (line 46) | function Tt(t){Ct=t}
  function $t (line 46) | function $t(t,e){mt();var n=window.history;try{e?n.replaceState({key:Ct}...
  function Mt (line 46) | function Mt(t){$t(t,!0)}
  function Pt (line 46) | function Pt(t,e,n){var r=function(o){o>=t.length?n():t[o]?e(t[o],functio...
  function Lt (line 46) | function Lt(t){return function(e,n,r){var i=!1,a=0,s=null;Rt(t,function(...
  function Rt (line 46) | function Rt(t,e){return Nt(t.map(function(t){return Object.keys(t.compon...
  function Nt (line 46) | function Nt(t){return Array.prototype.concat.apply([],t)}
  function It (line 46) | function It(t){return t.__esModule||Ft&&"Module"===t[Symbol.toStringTag]}
  function Dt (line 46) | function Dt(t){var e=!1;return function(){var n=[],r=arguments.length;wh...
  function Ut (line 46) | function Ut(t){if(!t)if(P){var e=document.querySelector("base");t=e&&e.g...
  function Bt (line 46) | function Bt(t,e){var n,r=Math.max(t.length,e.length);for(n=0;n<r;n++)if(...
  function Vt (line 46) | function Vt(t,e,n,r){var o=Rt(t,function(t,r,o,i){var a=Ht(t,e);if(a)ret...
  function Ht (line 46) | function Ht(t,e){return"function"!==typeof t&&(t=A.extend(t)),t.options[e]}
  function zt (line 46) | function zt(t){return Vt(t,"beforeRouteLeave",Wt,!0)}
  function Gt (line 46) | function Gt(t){return Vt(t,"beforeRouteUpdate",Wt)}
  function Wt (line 46) | function Wt(t,e){if(e)return function(){return t.apply(e,arguments)}}
  function Kt (line 46) | function Kt(t,e,n){return Vt(t,"beforeRouteEnter",function(t,r,o,i){retu...
  function Xt (line 46) | function Xt(t,e,n,r,o){return function(i,a,s){return t(i,a,function(t){s...
  function Jt (line 46) | function Jt(t,e,n,r){e[n]&&!e[n]._isBeingDestroyed?t(e[n]):r()&&setTimeo...
  function e (line 46) | function e(e,n){var r=this;t.call(this,e,n);var o=e.options.scrollBehavi...
  function Zt (line 46) | function Zt(t){var e=decodeURI(window.location.pathname);return t&&0===e...
  function e (line 46) | function e(e,n,r){t.call(this,e,n),r&&te(this.base)||ee()}
  function te (line 46) | function te(t){var e=Zt(t);if(!/^\/#/.test(e))return window.location.rep...
  function ee (line 46) | function ee(){var t=ne();return"/"===t.charAt(0)||(ie("/"+t),!1)}
  function ne (line 46) | function ne(){var t=window.location.href,e=t.indexOf("#");if(e<0)return"...
  function re (line 46) | function re(t){var e=window.location.href,n=e.indexOf("#"),r=n>=0?e.slic...
  function oe (line 46) | function oe(t){St?$t(re(t)):window.location.hash=t}
  function ie (line 46) | function ie(t){St?Mt(re(t)):window.location.replace(re(t))}
  function e (line 46) | function e(e,n){t.call(this,e,n),this.stack=[],this.index=-1}
  function ue (line 46) | function ue(t,e){return t.push(e),function(){var n=t.indexOf(e);n>-1&&t....
  function fe (line 46) | function fe(t,e,n){var r="hash"===n?"#"+e:e;return t?N(t+"/"+r):r}
  function o (line 46) | function o(t){if("function"!==typeof t)throw new TypeError("executor mus...
  function g (line 46) | function g(){if(!m){m=!0;var t=navigator.userAgent,e=/(?:MSIE.(\d+\.\d+)...
  function r (line 46) | function r(t,e){return function(){t&&t.apply(this,arguments),e&&e.apply(...
  function r (line 46) | function r(r,o){return s.type="throw",s.arg=t,e.next=r,o&&(e.method="nex...
  function _ (line 46) | function _(t,e,n,r){var o=e&&e.prototype instanceof x?e:x,i=Object.creat...
  function w (line 46) | function w(t,e,n){try{return{type:"normal",arg:t.call(e,n)}}catch(r){ret...
  function x (line 46) | function x(){}
  function O (line 46) | function O(){}
  function E (line 46) | function E(){}
  function S (line 46) | function S(t){["next","throw","return"].forEach(function(e){t[e]=functio...
  function A (line 46) | function A(t){function e(n,r,i,a){var s=w(t[n],t,r);if("throw"!==s.type)...
  function C (line 46) | function C(t,e,n){var r=l;return function(o,i){if(r===d)throw new Error(...
  function k (line 46) | function k(t,e){var r=t.iterator[e.method];if(r===n){if(e.delegate=null,...
  function j (line 46) | function j(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.f...
  function T (line 46) | function T(t){var e=t.completion||{};e.type="normal",delete e.arg,t.comp...
  function $ (line 46) | function $(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(j,this),this.r...
  function M (line 46) | function M(t){if(t){var e=t[a];if(e)return e.call(t);if("function"===typ...
  function P (line 46) | function P(){return{value:n,done:!0}}
  function u (line 46) | function u(){for(var t=arguments.length,e=Array(t),n=0;n<t;n++)e[n]=argu...
  function f (line 46) | function f(t){return"string"===t||"url"===t||"hex"===t||"email"===t||"pa...
  function l (line 46) | function l(t,e){return void 0===t||null===t||(!("array"!==e||!Array.isAr...
  function p (line 46) | function p(t,e,n){var r=[],o=0,i=t.length;function a(t){r.push.apply(r,t...
  function d (line 46) | function d(t,e,n){var r=0,o=t.length;function i(a){if(a&&a.length)n(a);e...
  function h (line 46) | function h(t){var e=[];return Object.keys(t).forEach(function(n){e.push....
  function v (line 46) | function v(t,e,n,r){if(e.first){var o=h(t);return d(o,n,r)}var i=e.first...
  function y (line 46) | function y(t){return function(e){return e&&e.message?(e.field=e.field||t...
  function m (line 46) | function m(t,e){if(e)for(var n in e)if(e.hasOwnProperty(n)){var r=e[n];"...
  function g (line 46) | function g(t,e,n,r,o,i){!t.required||n.hasOwnProperty(t.field)&&!l(e,i||...
  function _ (line 46) | function _(t,e,n,r,o){(/^\s+$/.test(e)||""===e)&&r.push(u(o.messages.whi...
  function E (line 46) | function E(t,e,n,r,o){if(t.required&&void 0===e)b(t,e,n,r,o);else{var i=...
  function A (line 46) | function A(t,e,n,r,o){var i="number"===typeof t.len,a="number"===typeof ...
  function j (line 46) | function j(t,e,n,r,o){t[k]=Array.isArray(t[k])?t[k]:[],-1===t[k].indexOf...
  function $ (line 46) | function $(t,e,n,r,o){if(t.pattern)if(t.pattern instanceof RegExp)t.patt...
  function L (line 46) | function L(t,e,n,r,o){var i=[],a=t.required||!t.required&&r.hasOwnProper...
  function N (line 46) | function N(t,e,n,r,o){var i=[],a=t.required||!t.required&&r.hasOwnProper...
  function I (line 46) | function I(t,e,n,r,o){var i=[],a=t.required||!t.required&&r.hasOwnProper...
  function q (line 46) | function q(t,e,n,r,o){var i=[],a=t.required||!t.required&&r.hasOwnProper...
  function B (line 46) | function B(t,e,n,r,o){var i=[],a=t.required||!t.required&&r.hasOwnProper...
  function H (line 46) | function H(t,e,n,r,o){var i=[],a=t.required||!t.required&&r.hasOwnProper...
  function G (line 46) | function G(t,e,n,r,o){var i=[],a=t.required||!t.required&&r.hasOwnProper...
  function K (line 46) | function K(t,e,n,r,o){var i=[],a=t.required||!t.required&&r.hasOwnProper...
  function J (line 46) | function J(t,e,n,r,o){var i=[],a=t.required||!t.required&&r.hasOwnProper...
  function Q (line 46) | function Q(t,e,n,r,o){var i=[],a=t.required||!t.required&&r.hasOwnProper...
  function et (line 46) | function et(t,e,n,r,o){var i=[],a=t.required||!t.required&&r.hasOwnPrope...
  function rt (line 46) | function rt(t,e,n,r,o){var i=[],a=t.required||!t.required&&r.hasOwnPrope...
  function it (line 46) | function it(t,e,n,r,o){var i=[],s=Array.isArray(e)?"array":"undefined"==...
  function st (line 46) | function st(t,e,n,r,o){var i=t.type,a=[],s=t.required||!t.required&&r.ha...
  function ft (line 46) | function ft(){return{default:"Validation error on field %s",required:"%s...
  function pt (line 46) | function pt(t){this.rules=null,this._messages=lt,this.define(t)}
  function i (line 46) | function i(t,e){return o()({},e,{fullField:n.fullField+"."+t})}
  function f (line 46) | function f(){var a=arguments.length>0&&void 0!==arguments[0]?arguments[0...
  function _ (line 46) | function _(t){var e=void 0,n=void 0,r=[],o={};function i(t){Array.isArra...
  function o (line 46) | function o(t){var e,n;this.promise=new t(function(t,r){if(void 0!==e||vo...
  function t (line 53) | function t(){for(var t=0,e={};t<arguments.length;t++){var n=arguments[t]...
  function e (line 53) | function e(n){function r(e,o,i){var a;if("undefined"!==typeof document){...
  function i (line 53) | function i(t,e){var i,a=[],s=0,f=0,l="",p=e&&e.delimiter||n,d=e&&e.delim...
  function a (line 53) | function a(t,e){return s(i(t,e))}
  function s (line 53) | function s(t){for(var e=new Array(t.length),n=0;n<t.length;n++)"object"=...
  function c (line 53) | function c(t){return t.replace(/([.+*?=^!:${}()[\]|\/\\])/g,"\\$1")}
  function u (line 53) | function u(t){return t.replace(/([=!:$\/()])/g,"\\$1")}
  function f (line 53) | function f(t){return t&&t.sensitive?"":"i"}
  function l (line 53) | function l(t,e){if(!e)return t;var n=t.source.match(/\((?!\?)/g);if(n)fo...
  function p (line 53) | function p(t,e,n){for(var r=[],o=0;o<t.length;o++)r.push(v(t[o],e,n).sou...
  function d (line 53) | function d(t,e,n){return h(i(t,n),e,n)}
  function h (line 53) | function h(t,e,o){o=o||{};for(var i=o.strict,a=!1!==o.start,s=!1!==o.end...
  function v (line 53) | function v(t,e,n){return t instanceof RegExp?l(t,e):Array.isArray(t)?p(t...
  function a (line 53) | function a(t){return"[object Array]"===i.call(t)}
  function s (line 53) | function s(t){return"[object ArrayBuffer]"===i.call(t)}
  function c (line 53) | function c(t){return"undefined"!==typeof FormData&&t instanceof FormData}
  function u (line 53) | function u(t){var e;return e="undefined"!==typeof ArrayBuffer&&ArrayBuff...
  function f (line 53) | function f(t){return"string"===typeof t}
  function l (line 53) | function l(t){return"number"===typeof t}
  function p (line 53) | function p(t){return"undefined"===typeof t}
  function d (line 53) | function d(t){return null!==t&&"object"===typeof t}
  function h (line 53) | function h(t){return"[object Date]"===i.call(t)}
  function v (line 53) | function v(t){return"[object File]"===i.call(t)}
  function y (line 53) | function y(t){return"[object Blob]"===i.call(t)}
  function m (line 53) | function m(t){return"[object Function]"===i.call(t)}
  function g (line 53) | function g(t){return d(t)&&m(t.pipe)}
  function b (line 53) | function b(t){return"undefined"!==typeof URLSearchParams&&t instanceof U...
  function _ (line 53) | function _(t){return t.replace(/^\s*/,"").replace(/\s*$/,"")}
  function w (line 53) | function w(){return("undefined"===typeof navigator||"ReactNative"!==navi...
  function x (line 53) | function x(t,e){if(null!==t&&"undefined"!==typeof t)if("object"!==typeof...
  function O (line 53) | function O(){var t={};function e(e,n){"object"===typeof t[n]&&"object"==...
  function E (line 53) | function E(t,e,n){return x(e,function(e,o){t[o]=n&&"function"===typeof e...
  function s (line 53) | function s(t){var e=new i(t),n=o(i.prototype.request,e);return r.extend(...
  function c (line 53) | function c(t){var e=0,n=0,r=0,o=0;return"detail"in t&&(n=t.detail),"whee...
  function v (line 53) | function v(t,e,n){return e in t?o()(t,e,{value:n,enumerable:!0,configura...
  function y (line 53) | function y(t,e){var n=h()(t);return p.a&&n.push.apply(n,p()(t)),e&&(n=n....
  function m (line 53) | function m(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[...
  function n (line 53) | function n(t,e){for(var n=0,r=t.length-1;r>=0;r--){var o=t[r];"."===o?t....
  function r (line 53) | function r(t){"string"!==typeof t&&(t+="");var e,n=0,r=-1,o=!0;for(e=t.l...
  function o (line 53) | function o(t,e){if(t.filter)return t.filter(e);for(var n=[],r=0;r<t.leng...
  function r (line 53) | function r(t){for(var e=0;e<t.length;e++)if(""!==t[e])break;for(var n=t....
  function r (line 53) | function r(t,e){return e={exports:{}},t(e,e.exports),e.exports}
  function t (line 53) | function t(t){var e=t&&"object"===typeof t;return e&&"[object RegExp]"!=...
  function e (line 53) | function e(t){return Array.isArray(t)?[]:{}}
  function n (line 53) | function n(n,r){var o=r&&!0===r.clone;return o&&t(n)?i(e(n),n,r):n}
  function r (line 53) | function r(e,r,o){var a=e.slice();return r.forEach(function(r,s){"undefi...
  function o (line 53) | function o(e,r,o){var a={};return t(e)&&Object.keys(e).forEach(function(...
  function i (line 53) | function i(t,e,i){var a=Array.isArray(e),s=i||{arrayMerge:r},c=s.arrayMe...
  function e (line 53) | function e(){t.apply(this,arguments)}
  function o (line 53) | function o(){this.handlers=[]}

FILE: admin/admin-web/src/test/java/com/alibaba/otter/canal/admin/SimpleAdminConnectorTest.java
  class SimpleAdminConnectorTest (line 8) | @Ignore
    method testSimple (line 11) | @Test

FILE: client-adapter/clickhouse/src/main/java/com/alibaba/otter/canal/client/adapter/clickhouse/ClickHouseAdapter.java
  class ClickHouseAdapter (line 34) | @SPI
    method getClickHouseMapping (line 62) | public Map<String, MappingConfig> getClickHouseMapping() {
    method init (line 66) | @Override
    method sync (line 143) | @Override
    method destroy (line 162) | @Override
    method etl (line 185) | @Override
    method count (line 228) | @Override
    method getDestination (line 269) | @Override
    method addSyncConfigToCache (line 278) | private void addSyncConfigToCache(String configName, MappingConfig map...
    method addConfig (line 300) | public boolean addConfig(String fileName, MappingConfig config) {
    method updateConfig (line 311) | public void updateConfig(String fileName, MappingConfig config) {
    method deleteConfig (line 321) | public void deleteConfig(String fileName) {
    method match (line 331) | private boolean match(MappingConfig config) {

FILE: client-adapter/clickhouse/src/main/java/com/alibaba/otter/canal/client/adapter/clickhouse/config/ConfigLoader.java
  class ConfigLoader (line 21) | public class ConfigLoader {
    method load (line 30) | public static Map<String, MappingConfig> load(Properties envProperties) {

FILE: client-adapter/clickhouse/src/main/java/com/alibaba/otter/canal/client/adapter/clickhouse/config/MappingConfig.java
  class MappingConfig (line 18) | public class MappingConfig implements AdapterConfig {
    method getDataSourceKey (line 32) | public String getDataSourceKey() {
    method setDataSourceKey (line 36) | public void setDataSourceKey(String dataSourceKey) {
    method getGroupId (line 40) | public String getGroupId() {
    method setGroupId (line 44) | public void setGroupId(String groupId) {
    method getOuterAdapterKey (line 48) | public String getOuterAdapterKey() {
    method setOuterAdapterKey (line 52) | public void setOuterAdapterKey(String outerAdapterKey) {
    method getConcurrent (line 56) | public boolean getConcurrent() {
    method setConcurrent (line 60) | public void setConcurrent(boolean concurrent) {
    method getDbMapping (line 64) | public DbMapping getDbMapping() {
    method setDbMapping (line 68) | public void setDbMapping(DbMapping dbMapping) {
    method getDestination (line 72) | public String getDestination() {
    method setDestination (line 76) | public void setDestination(String destination) {
    method getMapping (line 80) | public AdapterMapping getMapping() {
    method validate (line 84) | public void validate() {
    class DbMapping (line 96) | public static class DbMapping implements AdapterMapping {
      method getMirrorDb (line 116) | public boolean getMirrorDb() {
      method setMirrorDb (line 120) | public void setMirrorDb(boolean mirrorDb) {
      method getDatabase (line 124) | public String getDatabase() {
      method setDatabase (line 128) | public void setDatabase(String database) {
      method getTable (line 132) | public String getTable() {
      method setTable (line 136) | public void setTable(String table) {
      method getTargetPk (line 140) | public Map<String, String> getTargetPk() {
      method setTargetPk (line 144) | public void setTargetPk(Map<String, String> targetPk) {
      method getMapAll (line 148) | public Boolean getMapAll() {
      method setMapAll (line 152) | public void setMapAll(Boolean mapAll) {
      method getTargetDb (line 156) | public String getTargetDb() {
      method setTargetDb (line 160) | public void setTargetDb(String targetDb) {
      method getTargetTable (line 164) | public String getTargetTable() {
      method setTargetTable (line 168) | public void setTargetTable(String targetTable) {
      method getTargetColumns (line 172) | public Map<String, String> getTargetColumns() {
      method setTargetColumns (line 183) | public void setTargetColumns(Map<String, String> targetColumns) {
      method isCaseInsensitive (line 187) | public boolean isCaseInsensitive() {
      method setCaseInsensitive (line 191) | public void setCaseInsensitive(boolean caseInsensitive) {
      method getEtlCondition (line 195) | public String getEtlCondition() {
      method setEtlCondition (line 199) | public void setEtlCondition(String etlCondition) {
      method getReadBatch (line 203) | public int getReadBatch() {
      method setReadBatch (line 207) | public void setReadBatch(int readBatch) {
      method getCommitBatch (line 211) | public int getCommitBatch() {
      method setCommitBatch (line 215) | public void setCommitBatch(int commitBatch) {
      method getAllMapColumns (line 219) | public Map<String, String> getAllMapColumns() {
      method setAllMapColumns (line 223) | public void setAllMapColumns(Map<String, String> allMapColumns) {

FILE: client-adapter/clickhouse/src/main/java/com/alibaba/otter/canal/client/adapter/clickhouse/config/MirrorDbConfig.java
  class MirrorDbConfig (line 13) | public class MirrorDbConfig {
    method create (line 19) | public static MirrorDbConfig create(String fileName, MappingConfig map...
    method MirrorDbConfig (line 23) | public MirrorDbConfig(String fileName, MappingConfig mappingConfig){
    method getFileName (line 28) | public String getFileName() {
    method setFileName (line 32) | public void setFileName(String fileName) {
    method getMappingConfig (line 36) | public MappingConfig getMappingConfig() {
    method setMappingConfig (line 40) | public void setMappingConfig(MappingConfig mappingConfig) {
    method getTableConfig (line 44) | public Map<String, MappingConfig> getTableConfig() {
    method setTableConfig (line 48) | public void setTableConfig(Map<String, MappingConfig> tableConfig) {

FILE: client-adapter/clickhouse/src/main/java/com/alibaba/otter/canal/client/adapter/clickhouse/monitor/ClickHouseConfigMonitor.java
  class ClickHouseConfigMonitor (line 26) | public class ClickHouseConfigMonitor {
    method init (line 40) | public void init(String key, ClickHouseAdapter clickHouseAdapter, Prop...
    method destroy (line 58) | public void destroy() {
    class FileListener (line 66) | private class FileListener extends FileAlterationListenerAdaptor {
      method onFileCreate (line 68) | @Override
      method onFileChange (line 89) | @Override
      method onFileDelete (line 116) | @Override

FILE: client-adapter/clickhouse/src/main/java/com/alibaba/otter/canal/client/adapter/clickhouse/service/ClickHouseBatchSyncService.java
  class ClickHouseBatchSyncService (line 35) | public class ClickHouseBatchSyncService {
    method getColumnsTypeCache (line 58) | public Map<String, Map<String, Integer>> getColumnsTypeCache() {
    method ClickHouseBatchSyncService (line 62) | public ClickHouseBatchSyncService(DruidDataSource dataSource, Integer ...
    method ClickHouseBatchSyncService (line 66) | @SuppressWarnings("unchecked")
    method scheduleBatchSync (line 103) | private void scheduleBatchSync() {
    method sync (line 140) | public void sync(List<Dml> dmls, Function<Dml, Boolean> function) {
    method sync (line 157) | public void sync(Map<String, Map<String, MappingConfig>> mappingConfig...
    method distributeDml (line 195) | private void distributeDml(MappingConfig config, Dml dml) {
    method appendDmlBufferPartition (line 228) | public void appendDmlBufferPartition(MappingConfig config, Dml dml) {
    method syncToClickHouse (line 253) | private void syncToClickHouse(MappingConfig config, int index) {
    method insert (line 283) | private void insert(BatchExecutor batchExecutor, MappingConfig config,...
    method update (line 365) | private void update(BatchExecutor batchExecutor, MappingConfig config,...
    method delete (line 426) | private void delete(BatchExecutor batchExecutor, MappingConfig config,...
    method truncate (line 452) | private void truncate(BatchExecutor batchExecutor, MappingConfig confi...
    method getTargetColumnType (line 469) | private Map<String, Integer> getTargetColumnType(Connection conn, Mapp...
    method appendCondition (line 506) | private void appendCondition(MappingConfig.DbMapping dbMapping, String...
    method appendCondition (line 511) | private void appendCondition(MappingConfig.DbMapping dbMapping, String...
    method mappingHash (line 544) | private int mappingHash(MappingConfig.DbMapping dbMapping) {
    method close (line 550) | public void close() {

FILE: client-adapter/clickhouse/src/main/java/com/alibaba/otter/canal/client/adapter/clickhouse/service/ClickHouseEtlService.java
  class ClickHouseEtlService (line 26) | public class ClickHouseEtlService extends AbstractEtlService {
    method ClickHouseEtlService (line 31) | public ClickHouseEtlService(DataSource targetDS, MappingConfig config){
    method importData (line 40) | public EtlResult importData(List<String> params) {
    method executeSqlImport (line 50) | protected boolean executeSqlImport(DataSource srcDS, String sql, List<...
    method appendCondition (line 182) | private static void appendCondition(DbMapping dbMapping, StringBuilder...

FILE: client-adapter/clickhouse/src/main/java/com/alibaba/otter/canal/client/adapter/clickhouse/service/ClickHouseMirrorDbBatchSyncService.java
  class ClickHouseMirrorDbBatchSyncService (line 30) | public class ClickHouseMirrorDbBatchSyncService {
    method ClickHouseMirrorDbBatchSyncService (line 40) | public ClickHouseMirrorDbBatchSyncService(Map<String, MirrorDbConfig> ...
    method sync (line 59) | public void sync(List<Dml> dmls) {
    method syncDml (line 104) | private void syncDml(List<Dml> dmlList) {
    method initMappingConfig (line 131) | private void initMappingConfig(String key, MappingConfig baseConfigMap...
    method executeDdl (line 162) | private void executeDdl(MirrorDbConfig mirrorDbConfig, Dml ddl) {

FILE: client-adapter/clickhouse/src/main/java/com/alibaba/otter/canal/client/adapter/clickhouse/support/BatchExecutor.java
  class BatchExecutor (line 23) | public class BatchExecutor implements Closeable {
    method BatchExecutor (line 31) | public BatchExecutor(DataSource dataSource){
    method getConn (line 35) | public Connection getConn() {
    method setValue (line 47) | public static void setValue(List<Map<String, ?>> values, int type, Obj...
    method execute (line 54) | public void execute(String sql, List<Map<String, ?>> values) throws SQ...
    method batchExecute (line 68) | public void batchExecute(String sql, List<List<Map<String, ?>>> batchV...
    method commit (line 85) | public void commit() throws SQLException {
    method rollback (line 93) | public void rollback() throws SQLException {
    method close (line 101) | @Override

FILE: client-adapter/clickhouse/src/main/java/com/alibaba/otter/canal/client/adapter/clickhouse/support/SingleDml.java
  class SingleDml (line 11) | public class SingleDml {
    method getDestination (line 20) | public String getDestination() {
    method setDestination (line 24) | public void setDestination(String destination) {
    method getDatabase (line 28) | public String getDatabase() {
    method setDatabase (line 32) | public void setDatabase(String database) {
    method getTable (line 36) | public String getTable() {
    method setTable (line 40) | public void setTable(String table) {
    method getType (line 44) | public String getType() {
    method setType (line 48) | public void setType(String type) {
    method getData (line 52) | public Map<String, Object> getData() {
    method setData (line 56) | public void setData(Map<String, Object> data) {
    method getOld (line 60) | public Map<String, Object> getOld() {
    method setOld (line 64) | public void setOld(Map<String, Object> old) {
    method dml2SingleDmls (line 68) | public static List<SingleDml> dml2SingleDmls(Dml dml, boolean caseInse...
    method dml2SingleDmls (line 103) | public static List<SingleDml> dml2SingleDmls(Dml dml) {
    method toCaseInsensitiveMap (line 107) | private static <V> LinkedCaseInsensitiveMap<V> toCaseInsensitiveMap(Ma...

FILE: client-adapter/clickhouse/src/main/java/com/alibaba/otter/canal/client/adapter/clickhouse/support/SyncUtil.java
  class SyncUtil (line 20) | public class SyncUtil {
    method getColumnsMap (line 24) | public static Map<String, String> getColumnsMap(MappingConfig.DbMappin...
    method getColumnsMap (line 28) | public static Map<String, String> getColumnsMap(MappingConfig.DbMappin...
    method setPStmt (line 65) | public static void setPStmt(int type, PreparedStatement pstmt, Object ...
    method getDbTableName (line 261) | public static String getDbTableName(MappingConfig.DbMapping dbMapping,...
    method getSourceDbTableName (line 271) | public static String getSourceDbTableName(MappingConfig.DbMapping dbMa...
    method getBacktickByDbType (line 288) | public static String getBacktickByDbType(String dbTypeName) {

FILE: client-adapter/clickhouse/src/test/java/com/alibaba/otter/canal/client/adapter/clickhouse/ClickHouseBatchSyncServiceTest.java
  class ClickHouseBatchSyncServiceTest (line 12) | @Ignore
    method init (line 17) | @Before
    method insert (line 22) | @Test
    method update (line 44) | @Test
    method delete (line 67) | @Test
    method truncate (line 85) | @Test

FILE: client-adapter/clickhouse/src/test/java/com/alibaba/otter/canal/client/adapter/clickhouse/ClickHouseBatchSyncThreadSafeTest.java
  class ClickHouseBatchSyncThreadSafeTest (line 26) | @Ignore
    method init (line 37) | @Before
    method test01 (line 44) | @Test

FILE: client-adapter/clickhouse/src/test/java/com/alibaba/otter/canal/client/adapter/clickhouse/TestConstant.java
  class TestConstant (line 7) | public class TestConstant {

FILE: client-adapter/clickhouse/src/test/java/com/alibaba/otter/canal/client/adapter/clickhouse/sync/Common.java
  class Common (line 21) | public class Common {
    method init (line 23) | public static ClickHouseAdapter init() {
    method setLogLevel (line 46) | public static void setLogLevel(Level logLevel) {

FILE: client-adapter/common/src/main/java/com/alibaba/otter/canal/client/adapter/OuterAdapter.java
  type OuterAdapter (line 18) | @SPI("logger")
    method init (line 27) | void init(OuterAdapterConfig configuration, Properties envProperties);
    method sync (line 34) | void sync(List<Dml> dmls);
    method destroy (line 39) | void destroy();
    method etl (line 47) | default EtlResult etl(String task, List<String> params) {
    method count (line 57) | default Map<String, Object> count(String task) {
    method getDestination (line 67) | default String getDestination(String task) {

FILE: client-adapter/common/src/main/java/com/alibaba/otter/canal/client/adapter/ProxyOuterAdapter.java
  class ProxyOuterAdapter (line 10) | public class ProxyOuterAdapter implements OuterAdapter {
    method ProxyOuterAdapter (line 14) | public ProxyOuterAdapter(OuterAdapter outerAdapter) {
    method changeCL (line 18) | private ClassLoader changeCL() {
    method revertCL (line 24) | private void revertCL(ClassLoader cl) {
    method init (line 28) | @Override
    method sync (line 38) | @Override
    method destroy (line 48) | @Override
    method etl (line 58) | @Override
    method count (line 68) | @Override
    method getDestination (line 78) | @Override

FILE: client-adapter/common/src/main/java/com/alibaba/otter/canal/client/adapter/support/AbstractEtlService.java
  class AbstractEtlService (line 17) | public abstract class AbstractEtlService {
    method AbstractEtlService (line 25) | public AbstractEtlService(String type, AdapterConfig config){
    method importData (line 30) | protected EtlResult importData(String sql, List<String> params) {
    method executeSqlImport (line 122) | protected abstract boolean executeSqlImport(DataSource ds, String sql,...

FILE: client-adapter/common/src/main/java/com/alibaba/otter/canal/client/adapter/support/AdapterConfig.java
  type AdapterConfig (line 3) | public interface AdapterConfig {
    method getDataSourceKey (line 4) | String getDataSourceKey();
    method getMapping (line 6) | AdapterMapping getMapping();
    type AdapterMapping (line 8) | interface AdapterMapping {
      method getEtlCondition (line 9) | String getEtlCondition();

FILE: client-adapter/common/src/main/java/com/alibaba/otter/canal/client/adapter/support/CanalClientConfig.java
  class CanalClientConfig (line 14) | public class CanalClientConfig {
    method getCanalServerHost (line 59) | public String getCanalServerHost() {
    method setCanalServerHost (line 63) | public void setCanalServerHost(String canalServerHost) {
    method getZookeeperHosts (line 67) | public String getZookeeperHosts() {
    method setZookeeperHosts (line 71) | public void setZookeeperHosts(String zookeeperHosts) {
    method getMqServers (line 75) | public String getMqServers() {
    method setMqServers (line 79) | public void setMqServers(String mqServers) {
    method getFlatMessage (line 83) | public Boolean getFlatMessage() {
    method setFlatMessage (line 87) | public void setFlatMessage(Boolean flatMessage) {
    method getBatchSize (line 91) | public Integer getBatchSize() {
    method setBatchSize (line 95) | public void setBatchSize(Integer batchSize) {
    method getRetries (line 99) | public Integer getRetries() {
    method getSyncBatchSize (line 103) | public Integer getSyncBatchSize() {
    method setSyncBatchSize (line 107) | public void setSyncBatchSize(Integer syncBatchSize) {
    method setRetries (line 111) | public void setRetries(Integer retries) {
    method getTimeout (line 115) | public Long getTimeout() {
    method setTimeout (line 119) | public void setTimeout(Long timeout) {
    method getMode (line 123) | public String getMode() {
    method setMode (line 127) | public void setMode(String mode) {
    method getAccessKey (line 131) | public String getAccessKey() {
    method setAccessKey (line 135) | public void setAccessKey(String accessKey) {
    method getSecretKey (line 139) | public String getSecretKey() {
    method setSecretKey (line 143) | public void setSecretKey(String secretKey) {
    method getUsername (line 147) | public String getUsername() {
    method setUsername (line 151) | public void setUsername(String username) {
    method getPassword (line 155) | public String getPassword() {
    method setPassword (line 159) | public void setPassword(String password) {
    method getVhost (line 163) | public String getVhost() {
    method setVhost (line 167) | public void setVhost(String vhost) {
    method getConsumerProperties (line 171) | public Properties getConsumerProperties() {
    method setConsumerProperties (line 175) | public void setConsumerProperties(Properties consumerProperties) {
    method getResourceOwnerId (line 179) | public Long getResourceOwnerId() {
    method setResourceOwnerId (line 183) | public void setResourceOwnerId(Long resourceOwnerId) {
    method getCanalAdapters (line 187) | public List<CanalAdapter> getCanalAdapters() {
    method setCanalAdapters (line 191) | public void setCanalAdapters(List<CanalAdapter> canalAdapters) {
    method isEnableMessageTrace (line 195) | public boolean isEnableMessageTrace() {
    method setEnableMessageTrace (line 199) | public void setEnableMessageTrace(boolean enableMessageTrace) {
    method getAccessChannel (line 203) | public String getAccessChannel() {
    method setAccessChannel (line 207) | public void setAccessChannel(String accessChannel) {
    method getCustomizedTraceTopic (line 211) | public String getCustomizedTraceTopic() {
    method setCustomizedTraceTopic (line 215) | public void setCustomizedTraceTopic(String customizedTraceTopic) {
    method getNamespace (line 219) | public String getNamespace() {
    method setNamespace (line 223) | public void setNamespace(String namespace) {
    method getTerminateOnException (line 227) | public Boolean getTerminateOnException() {
    method setTerminateOnException (line 231) | public void setTerminateOnException(Boolean terminateOnException) {
    class CanalAdapter (line 235) | public static class CanalAdapter {
      method getInstance (line 241) | public String getInstance() {
      method setInstance (line 245) | public void setInstance(String instance) {
      method getGroups (line 251) | public List<Group> getGroups() {
      method setGroups (line 255) | public void setGroups(List<Group> groups) {
    class Group (line 260) | public static class Group {
      method getGroupId (line 267) | public String getGroupId() {
      method setGroupId (line 271) | public void setGroupId(String groupId) {
      method getOuterAdapters (line 275) | public List<OuterAdapterConfig> getOuterAdapters() {
      method setOuterAdapters (line 279) | public void setOuterAdapters(List<OuterAdapterConfig> outerAdapters) {
      method getOuterAdaptersMap (line 283) | public Map<String, OuterAdapterConfig> getOuterAdaptersMap() {
      method setOuterAdaptersMap (line 287) | public void setOuterAdaptersMap(Map<String, OuterAdapterConfig> oute...

FILE: client-adapter/common/src/main/java/com/alibaba/otter/canal/client/adapter/support/Constant.java
  class Constant (line 3) | public class Constant {

FILE: client-adapter/common/src/main/java/com/alibaba/otter/canal/client/adapter/support/DaemonThreadFactory.java
  class DaemonThreadFactory (line 6) | public class DaemonThreadFactory implements ThreadFactory {
    method newThread (line 10) | public Thread newThread(Runnable r) {

FILE: client-adapter/common/src/main/java/com/alibaba/otter/canal/client/adapter/support/DatasourceConfig.java
  class DatasourceConfig (line 14) | public class DatasourceConfig {
    method getDriver (line 26) | public String getDriver() {
    method setDriver (line 30) | public void setDriver(String driver) {
    method getUrl (line 34) | public String getUrl() {
    method setUrl (line 38) | public void setUrl(String url) {
    method getDatabase (line 42) | public String getDatabase() {
    method setDatabase (line 46) | public void setDatabase(String database) {
    method getType (line 50) | public String getType() {
    method setType (line 54) | public void setType(String type) {
    method getUsername (line 58) | public String getUsername() {
    method setUsername (line 62) | public void setUsername(String username) {
    method getPassword (line 66) | public String getPassword() {
    method setPassword (line 70) | public void setPassword(String password) {
    method getMaxActive (line 74) | public Integer getMaxActive() {
    method setMaxActive (line 78) | public void setMaxActive(Integer maxActive) {

FILE: client-adapter/common/src/main/java/com/alibaba/otter/canal/client/adapter/support/Dml.java
  class Dml (line 13) | public class Dml implements Serializable {
    method getDestination (line 32) | public String getDestination() {
    method setDestination (line 36) | public void setDestination(String destination) {
    method getGroupId (line 40) | public String getGroupId() {
    method setGroupId (line 44) | public void setGroupId(String groupId) {
    method getDatabase (line 48) | public String getDatabase() {
    method setDatabase (line 52) | public void setDatabase(String database) {
    method getTable (line 56) | public String getTable() {
    method setTable (line 60) | public void setTable(String table) {
    method getPkNames (line 64) | public List<String> getPkNames() {
    method setPkNames (line 68) | public void setPkNames(List<String> pkNames) {
    method getIsDdl (line 72) | public Boolean getIsDdl() {
    method setIsDdl (line 76) | public void setIsDdl(Boolean isDdl) {
    method getType (line 80) | public String getType() {
    method setType (line 84) | public void setType(String type) {
    method getTs (line 88) | public Long getTs() {
    method setTs (line 92) | public void setTs(Long ts) {
    method getSql (line 96) | public String getSql() {
    method setSql (line 100) | public void setSql(String sql) {
    method getData (line 104) | public List<Map<String, Object>> getData() {
    method setData (line 108) | public void setData(List<Map<String, Object>> data) {
    method getOld (line 112) | public List<Map<String, Object>> getOld() {
    method setOld (line 116) | public void setOld(List<Map<String, Object>> old) {
    method getEs (line 120) | public Long getEs() {
    method setEs (line 124) | public void setEs(Long es) {
    method clear (line 128) | public void clear() {
    method toString (line 139) | @Override

FILE: client-adapter/common/src/main/java/com/alibaba/otter/canal/client/adapter/support/EtlResult.java
  class EtlResult (line 11) | public class EtlResult implements Serializable {
    method getSucceeded (line 21) | public boolean getSucceeded() {
    method setSucceeded (line 25) | public void setSucceeded(boolean succeeded) {
    method getResultMessage (line 29) | public String getResultMessage() {
    method setResultMessage (line 33) | public void setResultMessage(String resultMessage) {
    method getErrorMessage (line 37) | public String getErrorMessage() {
    method setErrorMessage (line 41) | public void setErrorMessage(String errorMessage) {

FILE: client-adapter/common/src/main/java/com/alibaba/otter/canal/client/adapter/support/ExtensionLoader.java
  class ExtensionLoader (line 30) | public class ExtensionLoader<T> {
    method withExtensionAnnotation (line 64) | private static <T> boolean withExtensionAnnotation(Class<T> type) {
    method getExtensionLoader (line 68) | public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
    method getExtensionLoader (line 72) | @SuppressWarnings("unchecked")
    method ExtensionLoader (line 91) | private ExtensionLoader(Class<?> type, String classLoaderPolicy){
    method getExtension (line 102) | @SuppressWarnings("unchecked")
    method getExtension (line 126) | @SuppressWarnings("unchecked")
    method getDefaultExtension (line 154) | public T getDefaultExtension() {
    method createExtension (line 162) | @SuppressWarnings("unchecked")
    method createExtension (line 183) | @SuppressWarnings("unchecked")
    method getExtensionClasses (line 204) | private Map<String, Class<?>> getExtensionClasses() {
    method getJarDirectoryPath (line 219) | private String getJarDirectoryPath() {
    method loadExtensionClasses (line 249) | private Map<String, Class<?>> loadExtensionClasses() {
    method loadFile (line 308) | private void loadFile(Map<String, Class<?>> extensionClasses, String d...
    method findClassLoader (line 399) | @SuppressWarnings("unused")
    method toString (line 404) | @Override
    class Holder (line 409) | private static class Holder<T> {
      method set (line 413) | private void set(T value) {
      method get (line 417) | private T get() {

FILE: client-adapter/common/src/main/java/com/alibaba/otter/canal/client/adapter/support/FileName2KeyMapping.java
  class FileName2KeyMapping (line 9) | public class FileName2KeyMapping {
    method register (line 13) | public static void register(String type, String fileName, String key) {
    method unregister (line 17) | public static void unregister(String type, String fileName) {
    method getKey (line 21) | public static String getKey(String type, String fileName) {
    method join (line 25) | private static String join(String type, String fileName) {

FILE: client-adapter/common/src/main/java/com/alibaba/otter/canal/client/adapter/support/JdbcTypeUtil.java
  class JdbcTypeUtil (line 21) | public class JdbcTypeUtil {
    method getRSData (line 25) | public static Object getRSData(ResultSet rs, String columnName, int jd...
    method jdbcType2javaType (line 33) | public static Class<?> jdbcType2javaType(int jdbcType) {
    method isText (line 74) | private static boolean isText(String columnType) {
    method typeConvert (line 79) | public static Object typeConvert(String tableName ,String columnName, ...

FILE: client-adapter/common/src/main/java/com/alibaba/otter/canal/client/adapter/support/MappingConfigsLoader.java
  class MappingConfigsLoader (line 12) | public class MappingConfigsLoader {
    method loadConfigs (line 14) | public static Map<String, String> loadConfigs(String name) {
    method loadConfig (line 47) | public static String loadConfig(String name) {

FILE: client-adapter/common/src/main/java/com/alibaba/otter/canal/client/adapter/support/MessageUtil.java
  class MessageUtil (line 15) | public class MessageUtil {
    method parse4Dml (line 17) | public static List<Dml> parse4Dml(String destination, String groupId, ...
    method flatMessage2Dml (line 134) | public static List<Dml> flatMessage2Dml(String destination, String gro...
    method flatMessage2Dml (line 149) | public static Dml flatMessage2Dml(String destination, String groupId, ...
    method changeRows (line 178) | private static List<Map<String, Object>> changeRows(String table, List...

FILE: client-adapter/common/src/main/java/com/alibaba/otter/canal/client/adapter/support/OuterAdapterConfig.java
  class OuterAdapterConfig (line 11) | public class OuterAdapterConfig {
    method getName (line 23) | public String getName() {
    method setName (line 27) | public void setName(String name) {
    method getKey (line 31) | public String getKey() {
    method setKey (line 35) | public void setKey(String key) {
    method getHosts (line 39) | public String getHosts() {
    method setHosts (line 43) | public void setHosts(String hosts) {
    method getProperties (line 47) | public Map<String, String> getProperties() {
    method setProperties (line 51) | public void setProperties(Map<String, String> properties) {
    method getZkHosts (line 55) | public String getZkHosts() {
    method setZkHosts (line 59) | public void setZkHosts(String zkHosts) {

FILE: client-adapter/common/src/main/java/com/alibaba/otter/canal/client/adapter/support/Result.java
  class Result (line 12) | public class Result implements Serializable {
    method createSuccess (line 20) | public static Result createSuccess(String message) {
    method getCode (line 26) | public Integer getCode() {
    method setCode (line 30) | public void setCode(Integer code) {
    method getData (line 34) | public Object getData() {
    method setData (line 38) | public void setData(Object data) {
    method getMessage (line 42) | public String getMessage() {
    method setMessage (line 46) | public void setMessage(String message) {
    method getSysTime (line 50) | public Date getSysTime() {
    method setSysTime (line 54) | public void setSysTime(Date sysTime) {

FILE: client-adapter/common/src/main/java/com/alibaba/otter/canal/client/adapter/support/URLClassExtensionLoader.java
  class URLClassExtensionLoader (line 9) | public class URLClassExtensionLoader extends URLClassLoader {
    method URLClassExtensionLoader (line 11) | public URLClassExtensionLoader(URL[] urls){
    method loadClass (line 15) | @Override
    method getResources (line 46) | @Override
    class CompoundEnumeration (line 58) | private static class CompoundEnumeration<E> implements Enumeration<E> {
      method CompoundEnumeration (line 63) | public CompoundEnumeration(Enumeration<E>[] enums){
      method next (line 67) | private boolean next() {
      method hasMoreElements (line 79) | public boolean hasMoreElements() {
      method nextElement (line 83) | public E nextElement() {

FILE: client-adapter/common/src/main/java/com/alibaba/otter/canal/client/adapter/support/Util.java
  class Util (line 30) | public class Util {
    method sqlRS (line 39) | public static Object sqlRS(DataSource ds, String sql, Function<ResultS...
    method sqlRS (line 62) | public static Object sqlRS(DataSource ds, String sql, List<Object> val...
    method sqlRS (line 95) | public static void sqlRS(Connection conn, String sql, Consumer<ResultS...
    method getConfDirPath (line 103) | public static File getConfDirPath() {
    method getConfDirPath (line 107) | public static File getConfDirPath(String subConf) {
    method cleanColumn (line 130) | public static String cleanColumn(String column) {
    method newFixedThreadPool (line 149) | public static ThreadPoolExecutor newFixedThreadPool(int nThreads, long...
    method newSingleThreadExecutor (line 166) | public static ThreadPoolExecutor newSingleThreadExecutor(long keepAliv...
    method newFixedDaemonThreadPool (line 183) | public static ThreadPoolExecutor newFixedDaemonThreadPool(int nThreads...
    method newSingleDaemonThreadExecutor (line 201) | public static ThreadPoolExecutor newSingleDaemonThreadExecutor(long ke...
    method parseDate (line 245) | public static Date parseDate(String datetimeStr) {
    method load (line 266) | @Override
    method parseDate2 (line 272) | public static Date parseDate2(String datetimeStr) {
    method isAccuracyOverSecond (line 353) | public static boolean isAccuracyOverSecond(String timeStr) {
    method isAccuracyOverMillisecond (line 367) | public static boolean isAccuracyOverMillisecond(String datetimeStr) {
    method parseISOLocalDateTime (line 384) | public static LocalDateTime parseISOLocalDateTime(String datetimeStr) {

FILE: client-adapter/common/src/main/java/com/alibaba/otter/canal/client/adapter/support/YamlUtils.java
  class YamlUtils (line 25) | public class YamlUtils {
    method resourceYmlToObj (line 27) | public static <T> T resourceYmlToObj(String resource, String prefix, C...
    method ymlToObj (line 49) | public static <T> T ymlToObj(String content, Class<T> clazz) {
    method ymlToObj (line 53) | public static <T> T ymlToObj(String prefix, String content, Class<T> c...
    method ymlToObj (line 57) | public static <T> T ymlToObj(String prefix, String content, Class<T> c...
    method ymlToObj (line 61) | public static <T> T ymlToObj(String prefix, String content, Class<T> c...

FILE: client-adapter/common/src/test/java/com/alibaba/otter/canal/client/adapter/support/JdbcTypeUtilTest.java
  class JdbcTypeUtilTest (line 11) | @RunWith(PowerMockRunner.class)
    method typeConvertInputNotNullNotNullNotNullNegativeNotNullOutput3 (line 20) | @Test
    method typeConvertInputNotNullNotNullNotNullNegativeNotNullOutputPositive (line 39) | @Test
    method typeConvertInputNotNullNotNullNotNullNegativeNotNullOutputPositive2 (line 58) | @Test
    method typeConvertInputNotNullNotNullNotNullPositiveNotNullOutputFalse (line 77) | @Test
    method typeConvertInputNotNullNotNullNotNullPositiveNotNullOutputNotNull (line 96) | @Test
    method typeConvertInputNotNullNotNullNotNullPositiveNotNullOutputPositive (line 115) | @Test
    method typeConvertInputNotNullNotNullNotNullPositiveNotNullOutputTrue (line 134) | @Test
    method typeConvertInputNotNullNotNullNotNullPositiveNotNullOutputZero2 (line 153) | @Test
    method typeConvertInputNotNullNotNullNotNullPositiveNotNullOutputZero3 (line 172) | @Test

FILE: client-adapter/common/src/test/java/com/alibaba/otter/canal/client/adapter/support/UtilTest.java
  class UtilTest (line 23) | @RunWith(PowerMockRunner.class)
    method cleanColumnInputNotNullOutputNotNull (line 33) | @Test
    method cleanColumnInputNullOutputNull (line 47) | @Test
    method parseDate2InputNotNullOutputNull (line 61) | @PrepareForTest(StringUtils.class)
    method parseDate2InputNotNullOutputNull2 (line 84) | @PrepareForTest(StringUtils.class)
    method parseDateInputNotNullOutputNull (line 107) | @PrepareForTest(StringUtils.class)

FILE: client-adapter/common/src/test/java/com/alibaba/otter/canal/client/adapter/support/YamlUtilsTest.java
  class YamlUtilsTest (line 11) | public class YamlUtilsTest {
    method testLoadConfigToYml (line 15) | @Test
    class MappingConfig (line 49) | private static class MappingConfig {
      method getDataSourceKey (line 62) | public String getDataSourceKey() {
      method setDataSourceKey (line 66) | public void setDataSourceKey(String dataSourceKey) {
      method getDestination (line 70) | public String getDestination() {
      method setDestination (line 74) | public void setDestination(String destination) {
      method getGroupId (line 78) | public String getGroupId() {
      method setGroupId (line 82) | public void setGroupId(String groupId) {
      method getOuterAdapterKey (line 86) | public String getOuterAdapterKey() {
      method setOuterAdapterKey (line 90) | public void setOuterAdapterKey(String outerAdapterKey) {
      method isConcurrent (line 94) | public boolean isConcurrent() {
      method setConcurrent (line 98) | public void setConcurrent(boolean concurrent) {
      method getDbMapping (line 102) | public DbMapping getDbMapping() {
      method setDbMapping (line 106) | public void setDbMapping(DbMapping dbMapping) {
    class DbMapping (line 111) | private static class DbMapping {
      method isMirrorDb (line 133) | public boolean isMirrorDb() {
      method setMirrorDb (line 137) | public void setMirrorDb(boolean mirrorDb) {
      method getDatabase (line 141) | public String getDatabase() {
      method setDatabase (line 145) | public void setDatabase(String database) {
      method getTable (line 149) | public String getTable() {
      method setTable (line 153) | public void setTable(String table) {
      method getTargetPk (line 157) | public Map<String, String> getTargetPk() {
      method setTargetPk (line 161) | public void setTargetPk(Map<String, String> targetPk) {
      method isMapAll (line 165) | public boolean isMapAll() {
      method setMapAll (line 169) | public void setMapAll(boolean mapAll) {
      method getTargetDb (line 173) | public String getTargetDb() {
      method setTargetDb (line 177) | public void setTargetDb(String targetDb) {
      method getTargetTable (line 181) | public String getTargetTable() {
      method setTargetTable (line 185) | public void setTargetTable(String targetTable) {
      method getTargetColumns (line 189) | public Map<String, String> getTargetColumns() {
      method setTargetColumns (line 193) | public void setTargetColumns(Map<String, String> targetColumns) {
      method isCaseInsensitive (line 197) | public boolean isCaseInsensitive() {
      method setCaseInsensitive (line 201) | public void setCaseInsensitive(boolean caseInsensitive) {
      method getEtlCondition (line 205) | public String getEtlCondition() {
      method setEtlCondition (line 209) | public void setEtlCondition(String etlCondition) {
      method getReadBatch (line 213) | public int getReadBatch() {
      method setReadBatch (line 217) | public void setReadBatch(int readBatch) {
      method getCommitBatch (line 221) | public int getCommitBatch() {
      method setCommitBatch (line 225) | public void setCommitBatch(int commitBatch) {
      method getAllMapColumns (line 229) | public Map<String, String> getAllMapColumns() {
      method setAllMapColumns (line 233) | public void setAllMapColumns(Map<String, String> allMapColumns) {
      method getId (line 237) | public String getId() {
      method setId (line 241) | public void setId(String id) {

FILE: client-adapter/es6x/src/main/java/com/alibaba/otter/canal/client/adapter/es6x/ES6xAdapter.java
  class ES6xAdapter (line 28) | @SPI("es6")
    method getEsConnection (line 33) | public ESConnection getEsConnection() {
    method init (line 37) | @Override
    method count (line 58) | @Override
    method etl (line 72) | @Override
    method destroy (line 117) | @Override

FILE: client-adapter/es6x/src/main/java/com/alibaba/otter/canal/client/adapter/es6x/etl/ESEtlService.java
  class ESEtlService (line 39) | public class ESEtlService extends AbstractEtlService {
    method ESEtlService (line 45) | public ESEtlService(ESConnection esConnection, ESSyncConfig config){
    method importData (line 52) | public EtlResult importData(List<String> params) {
    method executeSqlImport (line 59) | protected boolean executeSqlImport(DataSource ds, String sql, List<Obj...

FILE: client-adapter/es6x/src/main/java/com/alibaba/otter/canal/client/adapter/es6x/support/ES6xTemplate.java
  class ES6xTemplate (line 40) | public class ES6xTemplate implements ESTemplate {
    method ES6xTemplate (line 54) | public ES6xTemplate(ESConnection esConnection){
    method getBulk (line 59) | public ESBulkRequest getBulk() {
    method resetBulkRequestBuilder (line 63) | public void resetBulkRequestBuilder() {
    method insert (line 67) | @Override
    method update (line 104) | @Override
    method updateByQuery (line 112) | @Override
    method delete (line 151) | @Override
    method commit (line 173) | @Override
    method getValFromRS (line 184) | @Override
    method getESDataFromRS (line 206) | @Override
    method getIdValFromRS (line 231) | @Override
    method getESDataFromRS (line 247) | @Override
    method getValFromData (line 274) | @Override
    method getESDataFromDmlData (line 293) | @Override
    method getESDataFromDmlData (line 318) | @Override
    method commitBulk (line 349) | private void commitBulk() {
    method append4Update (line 355) | private void append4Update(ESMapping mapping, Object pkVal, Map<String...
    method getEsType (line 395) | @SuppressWarnings("unchecked")
    method putRelationDataFromRS (line 426) | private void putRelationDataFromRS(ESMapping mapping, SchemaItem schem...
    method putRelationData (line 455) | private void putRelationData(ESMapping mapping, SchemaItem schemaItem,...

FILE: client-adapter/es6x/src/main/java/com/alibaba/otter/canal/client/adapter/es6x/support/ESConnection.java
  class ESConnection (line 57) | public class ESConnection {
    type ESClientMode (line 61) | public enum ESClientMode {
    method ESConnection (line 71) | public ESConnection(String[] hosts, Map<String, String> properties, ES...
    method close (line 98) | public void close() {
    method getMapping (line 110) | public MappingMetaData getMapping(String index, String type) {
    class ES6xIndexRequest (line 164) | public class ES6xIndexRequest implements ESBulkRequest.ESIndexRequest {
      method ES6xIndexRequest (line 170) | public ES6xIndexRequest(String index, String type, String id){
      method setSource (line 178) | public ES6xIndexRequest setSource(Map<String, ?> source) {
      method setRouting (line 187) | public ES6xIndexRequest setRouting(String routing) {
      method getIndexRequestBuilder (line 196) | public IndexRequestBuilder getIndexRequestBuilder() {
      method setIndexRequestBuilder (line 200) | public void setIndexRequestBuilder(IndexRequestBuilder indexRequestB...
      method getIndexRequest (line 204) | public IndexRequest getIndexRequest() {
      method setIndexRequest (line 208) | public void setIndexRequest(IndexRequest indexRequest) {
    class ES6xUpdateRequest (line 213) | public class ES6xUpdateRequest implements ESBulkRequest.ESUpdateRequest {
      method ES6xUpdateRequest (line 219) | public ES6xUpdateRequest(String index, String type, String id){
      method setDoc (line 227) | public ES6xUpdateRequest setDoc(Map source) {
      method setDocAsUpsert (line 236) | public ES6xUpdateRequest setDocAsUpsert(boolean shouldUpsertDoc) {
      method setRouting (line 245) | public ES6xUpdateRequest setRouting(String routing) {
      method getUpdateRequestBuilder (line 254) | public UpdateRequestBuilder getUpdateRequestBuilder() {
      method setUpdateRequestBuilder (line 258) | public void setUpdateRequestBuilder(UpdateRequestBuilder updateReque...
      method getUpdateRequest (line 262) | public UpdateRequest getUpdateRequest() {
      method setUpdateRequest (line 266) | public void setUpdateRequest(UpdateRequest updateRequest) {
    class ES6xDeleteRequest (line 271) | public class ES6xDeleteRequest implements ESBulkRequest.ESDeleteRequest {
      method ES6xDeleteRequest (line 277) | public ES6xDeleteRequest(String index, String type, String id){
      method getDeleteRequestBuilder (line 285) | public DeleteRequestBuilder getDeleteRequestBuilder() {
      method setDeleteRequestBuilder (line 289) | public void setDeleteRequestBuilder(DeleteRequestBuilder deleteReque...
      method getDeleteRequest (line 293) | public DeleteRequest getDeleteRequest() {
      method setDeleteRequest (line 297) | public void setDeleteRequest(DeleteRequest deleteRequest) {
    class ESSearchRequest (line 302) | public class ESSearchRequest {
      method ESSearchRequest (line 310) | public ESSearchRequest(String index, String... types){
      method setQuery (line 319) | public ESSearchRequest setQuery(QueryBuilder queryBuilder) {
      method size (line 328) | public ESSearchRequest size(int size) {
      method getResponse (line 337) | public SearchResponse getResponse() {
      method getSearchRequestBuilder (line 350) | public SearchRequestBuilder getSearchRequestBuilder() {
      method setSearchRequestBuilder (line 354) | public void setSearchRequestBuilder(SearchRequestBuilder searchReque...
      method getSearchRequest (line 358) | public SearchRequest getSearchRequest() {
      method setSearchRequest (line 362) | public void setSearchRequest(SearchRequest searchRequest) {
    class ES6xBulkRequest (line 367) | public class ES6xBulkRequest implements ESBulkRequest {
      method ES6xBulkRequest (line 373) | public ES6xBulkRequest(){
      method resetBulk (line 381) | public void resetBulk() {
      method add (line 389) | public ES6xBulkRequest add(ESIndexRequest esIndexRequest) {
      method add (line 399) | public ES6xBulkRequest add(ESUpdateRequest esUpdateRequest) {
      method add (line 409) | public ES6xBulkRequest add(ESDeleteRequest esDeleteRequest) {
      method numberOfActions (line 419) | public int numberOfActions() {
      method bulk (line 427) | @SuppressWarnings("deprecation")
      method getBulkRequestBuilder (line 442) | public BulkRequestBuilder getBulkRequestBuilder() {
      method setBulkRequestBuilder (line 446) | public void setBulkRequestBuilder(BulkRequestBuilder bulkRequestBuil...
      method getBulkRequest (line 450) | public BulkRequest getBulkRequest() {
      method setBulkRequest (line 454) | public void setBulkRequest(BulkRequest bulkRequest) {
    class ES6xBulkResponse (line 459) | public static class ES6xBulkResponse implements ESBulkRequest.ESBulkRe...
      method ES6xBulkResponse (line 463) | public ES6xBulkResponse(BulkResponse bulkResponse){
      method hasFailures (line 467) | @Override
      method processFailBulkResponse (line 472) | @Override
    method getMode (line 489) | public ESClientMode getMode() {
    method setMode (line 493) | public void setMode(ESClientMode mode) {
    method getTransportClient (line 497) | public TransportClient getTransportClient() {
    method setTransportClient (line 501) | public void setTransportClient(TransportClient transportClient) {
    method getRestHighLevelClient (line 505) | public RestHighLevelClient getRestHighLevelClient() {
    method setRestHighLevelClient (line 509) | public void setRestHighLevelClient(RestHighLevelClient restHighLevelCl...
    method createHttpHost (line 513) | private HttpHost createHttpHost(String uriStr) {

FILE: client-adapter/es6x/src/main/java/org/elasticsearch/client/RequestConvertersExt.java
  class RequestConvertersExt (line 15) | public class RequestConvertersExt {
    method getMappings (line 24) | static Request getMappings(GetMappingsRequest getMappingsRequest) thro...

FILE: client-adapter/es6x/src/main/java/org/elasticsearch/client/RestHighLevelClientExt.java
  class RestHighLevelClientExt (line 16) | public class RestHighLevelClientExt {
    method getMapping (line 18) | public static GetMappingsResponse getMapping(RestHighLevelClient restH...

FILE: client-adapter/es6x/src/test/java/com/alibaba/otter/canal/client/adapter/es6x/test/ConfigLoadTest.java
  class ConfigLoadTest (line 14) | @Ignore
    method before (line 17) | @Before
    method testLoad (line 24) | @Test

FILE: client-adapter/es6x/src/test/java/com/alibaba/otter/canal/client/adapter/es6x/test/ESTest.java
  class ESTest (line 24) | @Ignore
    method init (line 29) | @Before
    method test01 (line 43) | @Test
    method test02 (line 55) | @Test
    method test03 (line 74) | @Test
    method test04 (line 90) | @Test
    method commit (line 97) | private void commit(BulkRequestBuilder bulkRequestBuilder) {
    method after (line 116) | @After

FILE: client-adapter/es6x/src/test/java/com/alibaba/otter/canal/client/adapter/es6x/test/SqlParseTest.java
  class SqlParseTest (line 14) | public class SqlParseTest {
    method parseTest (line 16) | @Test

FILE: client-adapter/es6x/src/test/java/com/alibaba/otter/canal/client/adapter/es6x/test/TestConstant.java
  class TestConstant (line 7) | public class TestConstant {

FILE: client-adapter/es6x/src/test/java/com/alibaba/otter/canal/client/adapter/es6x/test/sync/Common.java
  class Common (line 17) | public class Common {
    method init (line 19) | public static ES6xAdapter init() {
    method sqlExe (line 34) | public static void sqlExe(DataSource dataSource, String sql) {

FILE: client-adapter/es6x/src/test/java/com/alibaba/otter/canal/client/adapter/es6x/test/sync/LabelSyncJoinSub2Test.java
  class LabelSyncJoinSub2Test (line 22) | @Ignore
    method init (line 27) | @Before
    method test01 (line 36) | @Test
    method test02 (line 73) | @Test
    method test03 (line 114) | @Test

FILE: client-adapter/es6x/src/test/java/com/alibaba/otter/canal/client/adapter/es6x/test/sync/LabelSyncJoinSubTest.java
  class LabelSyncJoinSubTest (line 22) | @Ignore
    method init (line 27) | @Before
    method test01 (line 36) | @Test
    method test02 (line 73) | @Test
    method test03 (line 114) | @Test

FILE: client-adapter/es6x/src/test/java/com/alibaba/otter/canal/client/adapter/es6x/test/sync/RoleSyncJoinOne2Test.java
  class RoleSyncJoinOne2Test (line 22) | @Ignore
    method init (line 27) | @Before
    method test01 (line 36) | @Test
    method test02 (line 71) | @Test

FILE: client-adapter/es6x/src/test/java/com/alibaba/otter/canal/client/adapter/es6x/test/sync/RoleSyncJoinOneTest.java
  class RoleSyncJoinOneTest (line 22) | @Ignore
    method init (line 27) | @Before
    method test01 (line 36) | @Test
    method test02 (line 72) | @Test
    method test03 (line 112) | @Test
    method test04 (line 181) | @Test

FILE: client-adapter/es6x/src/test/java/com/alibaba/otter/canal/client/adapter/es6x/test/sync/UserSyncJoinOneTest.java
  class UserSyncJoinOneTest (line 22) | @Ignore
    method init (line 27) | @Before
    method test01 (line 36) | @Test
    method test02 (line 73) | @Test

FILE: client-adapter/es6x/src/test/java/com/alibaba/otter/canal/client/adapter/es6x/test/sync/UserSyncSingleTest.java
  class UserSyncSingleTest (line 19) | @Ignore
    method init (line 24) | @Before
    method test01 (line 33) | @Test
    method test02 (line 66) | @Test
    method test03 (line 102) | @Test

FILE: client-adapter/es6x/src/test/java/com/alibaba/otter/canal/client/adapter/es6x/test/sync/db_schema.sql
  type `label` (line 5) | CREATE TABLE `label` (
  type `role` (line 16) | CREATE TABLE `role` (
  type `user` (line 26) | CREATE TABLE `user` (

FILE: client-adapter/es7x/src/main/java/com/alibaba/otter/canal/client/adapter/es7x/ES7xAdapter.java
  class ES7xAdapter (line 28) | @SPI("es7")
    method getEsConnection (line 33) | public ESConnection getEsConnection() {
    method init (line 37) | @Override
    method count (line 58) | @Override
    method etl (line 71) | @Override
    method destroy (line 116) | @Override

FILE: client-adapter/es7x/src/main/java/com/alibaba/otter/canal/client/adapter/es7x/etl/ESEtlService.java
  class ESEtlService (line 39) | public class ESEtlService extends AbstractEtlService {
    method ESEtlService (line 45) | public ESEtlService(ESConnection esConnection, ESSyncConfig config){
    method importData (line 52) | public EtlResult importData(List<String> params) {
    method executeSqlImport (line 59) | protected boolean executeSqlImport(DataSource ds, String sql, List<Obj...

FILE: client-adapter/es7x/src/main/java/com/alibaba/otter/canal/client/adapter/es7x/support/ES7xTemplate.java
  class ES7xTemplate (line 36) | public class ES7xTemplate implements ESTemplate {
    method ES7xTemplate (line 47) | public ES7xTemplate(ESConnection esConnection){
    method getBulk (line 52) | public ESBulkRequest getBulk() {
    method resetBulkRequestBuilder (line 56) | public void resetBulkRequestBuilder() {
    method insert (line 60) | @Override
    method update (line 96) | @Override
    method updateByQuery (line 104) | @Override
    method delete (line 143) | @Override
    method commit (line 164) | @Override
    method getValFromRS (line 175) | @Override
    method getESDataFromRS (line 197) | @Override
    method getIdValFromRS (line 222) | @Override
    method getESDataFromRS (line 238) | @Override
    method getValFromData (line 265) | @Override
    method getESDataFromDmlData (line 283) | @Override
    method getESDataFromDmlData (line 308) | @Override
    method commitBulk (line 343) | private void commitBulk() {
    method append4Update (line 349) | private void append4Update(ESMapping mapping, Object pkVal, Map<String...
    method getEsType (line 387) | @SuppressWarnings("unchecked")
    method putRelationDataFromRS (line 418) | private void putRelationDataFromRS(ESMapping mapping, SchemaItem schem...
    method putRelationData (line 447) | private void putRelationData(ESMapping mapping, SchemaItem schemaItem,...

FILE: client-adapter/es7x/src/main/java/com/alibaba/otter/canal/client/adapter/es7x/support/ESConnection.java
  class ESConnection (line 55) | public class ESConnection {
    method ESConnection (line 63) | public ESConnection(String[] hosts, Map<String, String> properties, ES...
    method close (line 91) | public void close() {
    method getMapping (line 103) | public MappingMetaData getMapping(String index) {
    method getMode (line 152) | public ESClientMode getMode() {
    method setMode (line 156) | public void setMode(ESClientMode mode) {
    method getTransportClient (line 160) | public TransportClient getTransportClient() {
    method setTransportClient (line 164) | public void setTransportClient(TransportClient transportClient) {
    method getRestHighLevelClient (line 168) | public RestHighLevelClient getRestHighLevelClient() {
    method setRestHighLevelClient (line 172) | public void setRestHighLevelClient(RestHighLevelClient restHighLevelCl...
    method createHttpHost (line 176) | private HttpHost createHttpHost(String uriStr) {
    type ESClientMode (line 190) | public enum ESClientMode {
    class ES7xBulkResponse (line 194) | public static class ES7xBulkResponse implements ESBulkRequest.ESBulkRe...
      method ES7xBulkResponse (line 198) | public ES7xBulkResponse(BulkResponse bulkResponse){
      method hasFailures (line 202) | @Override
      method processFailBulkResponse (line 207) | @Override
    class ES7xIndexRequest (line 223) | public class ES7xIndexRequest implements ESBulkRequest.ESIndexRequest {
      method ES7xIndexRequest (line 229) | public ES7xIndexRequest(String index, String id){
      method setSource (line 240) | public ES7xIndexRequest setSource(Map<String, ?> source) {
      method setRouting (line 249) | public ES7xIndexRequest setRouting(String routing) {
      method getIndexRequestBuilder (line 258) | public IndexRequestBuilder getIndexRequestBuilder() {
      method setIndexRequestBuilder (line 262) | public void setIndexRequestBuilder(IndexRequestBuilder indexRequestB...
      method getIndexRequest (line 266) | public IndexRequest getIndexRequest() {
      method setIndexRequest (line 270) | public void setIndexRequest(IndexRequest indexRequest) {
    class ES7xUpdateRequest (line 275) | public class ES7xUpdateRequest implements ESBulkRequest.ESUpdateRequest {
      method ES7xUpdateRequest (line 281) | public ES7xUpdateRequest(String index, String id){
      method setDoc (line 291) | public ES7xUpdateRequest setDoc(Map source) {
      method setDocAsUpsert (line 300) | public ES7xUpdateRequest setDocAsUpsert(boolean shouldUpsertDoc) {
      method setRouting (line 309) | public ES7xUpdateRequest setRouting(String routing) {
      method getUpdateRequestBuilder (line 318) | public UpdateRequestBuilder getUpdateRequestBuilder() {
      method setUpdateRequestBuilder (line 322) | public void setUpdateRequestBuilder(UpdateRequestBuilder updateReque...
      method getUpdateRequest (line 326) | public UpdateRequest getUpdateRequest() {
      method setUpdateRequest (line 330) | public void setUpdateRequest(UpdateRequest updateRequest) {
    class ES7xDeleteRequest (line 335) | public class ES7xDeleteRequest implements ESBulkRequest.ESDeleteRequest {
      method ES7xDeleteRequest (line 341) | public ES7xDeleteRequest(String index, String id){
      method getDeleteRequestBuilder (line 351) | public DeleteRequestBuilder getDeleteRequestBuilder() {
      method setDeleteRequestBuilder (line 355) | public void setDeleteRequestBuilder(DeleteRequestBuilder deleteReque...
      method getDeleteRequest (line 359) | public DeleteRequest getDeleteRequest() {
      method setDeleteRequest (line 363) | public void setDeleteRequest(DeleteRequest deleteRequest) {
    class ESSearchRequest (line 368) | public class ESSearchRequest {
      method ESSearchRequest (line 376) | public ESSearchRequest(String index){
      method setQuery (line 385) | public ESSearchRequest setQuery(QueryBuilder queryBuilder) {
      method size (line 394) | public ESSearchRequest size(int size) {
      method getResponse (line 403) | public SearchResponse getResponse() {
      method getSearchRequestBuilder (line 416) | public SearchRequestBuilder getSearchRequestBuilder() {
      method setSearchRequestBuilder (line 420) | public void setSearchRequestBuilder(SearchRequestBuilder searchReque...
      method getSearchRequest (line 424) | public SearchRequest getSearchRequest() {
      method setSearchRequest (line 428) | public void setSearchRequest(SearchRequest searchRequest) {
    class ES7xBulkRequest (line 433) | public class ES7xBulkRequest implements ESBulkRequest {
      method ES7xBulkRequest (line 439) | public ES7xBulkRequest(){
      method resetBulk (line 447) | public void resetBulk() {
      method add (line 455) | public ES7xBulkRequest add(ESIndexRequest esIndexRequest) {
      method add (line 465) | public ES7xBulkRequest add(ESUpdateRequest esUpdateRequest) {
      method add (line 475) | public ES7xBulkRequest add(ESDeleteRequest esDeleteRequest) {
      method numberOfActions (line 485) | public int numberOfActions() {
      method bulk (line 493) | public ESBulkResponse bulk() {
      method getBulkRequestBuilder (line 507) | public BulkRequestBuilder getBulkRequestBuilder() {
      method setBulkRequestBuilder (line 511) | public void setBulkRequestBuilder(BulkRequestBuilder bulkRequestBuil...
      method getBulkRequest (line 515) | public BulkRequest getBulkRequest() {
      method setBulkRequest (line 519) | public void setBulkRequest(BulkRequest bulkRequest) {

FILE: client-adapter/es7x/src/test/java/com/alibaba/otter/canal/client/adapter/es7x/test/ES7xTest.java
  class ES7xTest (line 24) | @Ignore
    method init (line 30) | @Before
    method test01 (line 44) | @Test
    method test02 (line 55) | @Test
    method test03 (line 75) | @Test
    method test04 (line 91) | @Test
    method commit (line 98) | private void commit(BulkRequestBuilder bulkRequestBuilder) {
    method after (line 117) | @After

FILE: client-adapter/es7x/src/test/java/com/alibaba/otter/canal/client/adapter/es7x/test/ESConnectionTest.java
  class ESConnectionTest (line 15) | @Ignore
    method init (line 20) | @Before
    method test01 (line 28) | @Test

FILE: client-adapter/es7x/src/test/java/com/alibaba/otter/canal/client/adapter/es7x/test/TestConstant.java
  class TestConstant (line 7) | public class TestConstant {

FILE: client-adapter/es8x/src/main/java/com/alibaba/otter/canal/client/adapter/es8x/ES8xAdapter.java
  class ES8xAdapter (line 28) | @SPI("es8")
    method getEsConnection (line 33) | public ESConnection getEsConnection() {
    method init (line 37) | @Override
    method count (line 54) | @Override
    method etl (line 67) | @Override
    method destroy (line 112) | @Override

FILE: client-adapter/es8x/src/main/java/com/alibaba/otter/canal/client/adapter/es8x/etl/ESEtlService.java
  class ESEtlService (line 39) | public class ESEtlService extends AbstractEtlService {
    method ESEtlService (line 45) | public ESEtlService(ESConnection esConnection, ESSyncConfig config){
    method importData (line 52) | public EtlResult importData(List<String> params) {
    method executeSqlImport (line 59) | protected boolean executeSqlImport(DataSource ds, String sql, List<Obj...

FILE: client-adapter/es8x/src/main/java/com/alibaba/otter/canal/client/adapter/es8x/support/ES8xTemplate.java
  class ES8xTemplate (line 36) | public class ES8xTemplate implements ESTemplate {
    method ES8xTemplate (line 47) | public ES8xTemplate(ESConnection esConnection){
    method getBulk (line 52) | public ESBulkRequest getBulk() {
    method resetBulkRequestBuilder (line 56) | public void resetBulkRequestBuilder() {
    method insert (line 60) | @Override
    method update (line 96) | @Override
    method updateByQuery (line 104) | @Override
    method delete (line 143) | @Override
    method commit (line 164) | @Override
    method getValFromRS (line 175) | @Override
    method getESDataFromRS (line 197) | @Override
    method getIdValFromRS (line 222) | @Override
    method getESDataFromRS (line 238) | @Override
    method getValFromData (line 265) | @Override
    method getESDataFromDmlData (line 283) | @Override
    method getESDataFromDmlData (line 308) | @Override
    method commitBulk (line 339) | private void commitBulk() {
    method append4Update (line 345) | private void append4Update(ESMapping mapping, Object pkVal, Map<String...
    method getEsType (line 383) | @SuppressWarnings("unchecked")
    method putRelationDataFromRS (line 414) | private void putRelationDataFromRS(ESMapping mapping, SchemaItem schem...
    method putRelationData (line 443) | private void putRelationData(ESMapping mapping, SchemaItem schemaItem,...

FILE: client-adapter/es8x/src/main/java/com/alibaba/otter/canal/client/adapter/es8x/support/ESConnection.java
  class ESConnection (line 58) | public class ESConnection {
    method ESConnection (line 64) | public ESConnection(String[] hosts, Map<String, String> properties) th...
    method connectEsWithCa (line 73) | private void connectEsWithCa(String[] hosts, Map<String, String> prope...
    method connectEsWithoutCa (line 105) | private void connectEsWithoutCa(String[] hosts, Map<String, String> pr...
    method close (line 121) | public void close() {
    method getMapping (line 129) | public MappingMetadata getMapping(String index) {
    method getRestHighLevelClient (line 161) | public RestHighLevelClient getRestHighLevelClient() {
    method setRestHighLevelClient (line 165) | public void setRestHighLevelClient(RestHighLevelClient restHighLevelCl...
    method createHttpHost (line 169) | private HttpHost createHttpHost(String uriStr) {
    class ES8xBulkResponse (line 183) | public static class ES8xBulkResponse implements ESBulkRequest.ESBulkRe...
      method ES8xBulkResponse (line 187) | public ES8xBulkResponse(BulkResponse bulkResponse){
      method hasFailures (line 191) | @Override
      method processFailBulkResponse (line 196) | @Override
    class ES8xIndexRequest (line 212) | public class ES8xIndexRequest implements ESBulkRequest.ESIndexRequest {
      method ES8xIndexRequest (line 218) | public ES8xIndexRequest(String index, String id){
      method setSource (line 224) | public ES8xIndexRequest setSource(Map<String, ?> source) {
      method setRouting (line 231) | public ES8xIndexRequest setRouting(String routing) {
      method getIndexRequestBuilder (line 238) | public IndexRequestBuilder getIndexRequestBuilder() {
      method setIndexRequestBuilder (line 242) | public void setIndexRequestBuilder(IndexRequestBuilder indexRequestB...
      method getIndexRequest (line 246) | public IndexRequest getIndexRequest() {
      method setIndexRequest (line 250) | public void setIndexRequest(IndexRequest indexRequest) {
    class ES8xUpdateRequest (line 255) | public class ES8xUpdateRequest implements ESBulkRequest.ESUpdateRequest {
      method ES8xUpdateRequest (line 261) | public ES8xUpdateRequest(String index, String id){
      method setDoc (line 266) | public ES8xUpdateRequest setDoc(Map source) {
      method setDocAsUpsert (line 273) | public ES8xUpdateRequest setDocAsUpsert(boolean shouldUpsertDoc) {
      method setRouting (line 280) | public ES8xUpdateRequest setRouting(String routing) {
      method getUpdateRequestBuilder (line 287) | public UpdateRequestBuilder getUpdateRequestBuilder() {
      method setUpdateRequestBuilder (line 291) | public void setUpdateRequestBuilder(UpdateRequestBuilder updateReque...
      method getUpdateRequest (line 295) | public UpdateRequest getUpdateRequest() {
      method setUpdateRequest (line 299) | public void setUpdateRequest(UpdateRequest updateRequest) {
    class ES8xDeleteRequest (line 304) | public class ES8xDeleteRequest implements ESBulkRequest.ESDeleteRequest {
      method ES8xDeleteRequest (line 310) | public ES8xDeleteRequest(String index, String id){
      method getDeleteRequestBuilder (line 316) | public DeleteRequestBuilder getDeleteRequestBuilder() {
      method setDeleteRequestBuilder (line 320) | public void setDeleteRequestBuilder(DeleteRequestBuilder deleteReque...
      method getDeleteRequest (line 324) | public DeleteRequest getDeleteRequest() {
      method setDeleteRequest (line 328) | public void setDeleteRequest(DeleteRequest deleteRequest) {
    class ESSearchRequest (line 333) | public class ESSearchRequest {
      method ESSearchRequest (line 341) | public ESSearchRequest(String index){
      method setQuery (line 348) | public ESSearchRequest setQuery(QueryBuilder queryBuilder) {
      method size (line 355) | public ESSearchRequest size(int size) {
      method getResponse (line 362) | public SearchResponse getResponse() {
      method getSearchRequestBuilder (line 373) | public SearchRequestBuilder getSearchRequestBuilder() {
      method setSearchRequestBuilder (line 377) | public void setSearchRequestBuilder(SearchRequestBuilder searchReque...
      method getSearchRequest (line 381) | public SearchRequest getSearchRequest() {
      method setSearchRequest (line 385) | public void setSearchRequest(SearchRequest searchRequest) {
    class ES8xBulkRequest (line 390) | public class ES8xBulkRequest implements ESBulkRequest {
      method ES8xBulkRequest (line 396) | public ES8xBulkRequest(){
      method resetBulk (line 400) | public void resetBulk() {
      method add (line 406) | public ES8xBulkRequest add(ESIndexRequest esIndexRequest) {
      method add (line 414) | public ES8xBulkRequest add(ESUpdateRequest esUpdateRequest) {
      method add (line 422) | public ES8xBulkRequest add(ESDeleteRequest esDeleteRequest) {
      method numberOfActions (line 430) | public int numberOfActions() {
      method bulk (line 434) | public ESBulkResponse bulk() {
      method getBulkRequestBuilder (line 444) | public BulkRequestBuilder getBulkRequestBuilder() {
      method setBulkRequestBuilder (line 448) | public void setBulkRequestBuilder(BulkRequestBuilder bulkRequestBuil...
      method getBulkRequest (line 452) | public BulkRequest getBulkRequest() {
      method setBulkRequest (line 456) | public void setBulkRequest(BulkRequest bulkRequest) {

FILE: client-adapter/es8x/src/test/java/com/alibaba/otter/canal/client/adapter/es8x/test/ESConnectionTest.java
  class ESConnectionTest (line 14) | @Ignore
    method init (line 19) | @Before
    method test01 (line 27) | @Test

FILE: client-adapter/es8x/src/test/java/com/alibaba/otter/canal/client/adapter/es8x/test/TestConstant.java
  class TestConstant (line 7) | public class TestConstant {

FILE: client-adapter/escore/src/main/java/com/alibaba/otter/canal/client/adapter/es/core/ESAdapter.java
  class ESAdapter (line 29) | public abstract class ESAdapter implements OuterAdapter {
    method getEsSyncService (line 44) | public ESSyncService getEsSyncService() {
    method getEsSyncConfig (line 48) | public Map<String, ESSyncConfig> getEsSyncConfig() {
    method getDbTableEsSyncConfig (line 52) | public Map<String, Map<String, ESSyncConfig>> getDbTableEsSyncConfig() {
    method init (line 56) | @Override
    method sync (line 76) | @Override
    method sync (line 90) | private void sync(Dml dml) {
    method etl (line 108) | @Override
    method count (line 111) | @Override
    method destroy (line 114) | @Override
    method getDestination (line 121) | @Override
    method addSyncConfigToCache (line 130) | private void addSyncConfigToCache(String configName, ESSyncConfig conf...
    method addConfig (line 164) | public boolean addConfig(String fileName, ESSyncConfig config) {
    method updateConfig (line 174) | public void updateConfig(String fileName, ESSyncConfig config) {
    method deleteConfig (line 183) | public void deleteConfig(String fileName) {
    method match (line 193) | private boolean match(ESSyncConfig config) {

FILE: client-adapter/escore/src/main/java/com/alibaba/otter/canal/client/adapter/es/core/config/ESSyncConfig.java
  class ESSyncConfig (line 17) | public class ESSyncConfig implements AdapterConfig {
    method validate (line 31) | public void validate() {
    method getDataSourceKey (line 46) | public String getDataSourceKey() {
    method setDataSourceKey (line 50) | public void setDataSourceKey(String dataSourceKey) {
    method getOuterAdapterKey (line 54) | public String getOuterAdapterKey() {
    method setOuterAdapterKey (line 58) | public void setOuterAdapterKey(String outerAdapterKey) {
    method getGroupId (line 62) | public String getGroupId() {
    method setGroupId (line 66) | public void setGroupId(String groupId) {
    method getDestination (line 70) | public String getDestination() {
    method setDestination (line 74) | public void setDestination(String destination) {
    method getEsMapping (line 78) | public ESMapping getEsMapping() {
    method setEsMapping (line 82) | public void setEsMapping(ESMapping esMapping) {
    method getMapping (line 86) | public ESMapping getMapping() {
    method getEsVersion (line 90) | public String getEsVersion() {
    method setEsVersion (line 94) | public void setEsVersion(String esVersion) {
    class ESMapping (line 98) | public static class ESMapping implements AdapterMapping {
      method getIndex (line 123) | public String getIndex() {
      method setIndex (line 127) | public void setIndex(String index) {
      method getType (line 131) | public String getType() {
      method setType (line 135) | public void setType(String type) {
      method getId (line 139) | public String getId() {
      method setId (line 143) | public void setId(String id) {
      method isUpsert (line 147) | public boolean isUpsert() {
      method setUpsert (line 151) | public void setUpsert(boolean upsert) {
      method getPk (line 155) | public String getPk() {
      method setPk (line 159) | public void setPk(String pk) {
      method getObjFields (line 163) | public Map<String, String> getObjFields() {
      method setObjFields (line 167) | public void setObjFields(Map<String, String> objFields) {
      method getSkips (line 171) | public List<String> getSkips() {
      method setSkips (line 175) | public void setSkips(List<String> skips) {
      method getRelations (line 179) | public Map<String, RelationMapping> getRelations() {
      method setRelations (line 183) | public void setRelations(Map<String, RelationMapping> relations) {
      method getSql (line 187) | public String getSql() {
      method setSql (line 191) | public void setSql(String sql) {
      method getCommitBatch (line 195) | public int getCommitBatch() {
      method setCommitBatch (line 199) | public void setCommitBatch(int commitBatch) {
      method getEtlCondition (line 203) | public String getEtlCondition() {
      method setEtlCondition (line 207) | public void setEtlCondition(String etlCondition) {
      method getSyncInterval (line 211) | public Long getSyncInterval() {
      method setSyncInterval (line 215) | public void setSyncInterval(Long syncInterval) {
      method isSyncByTimestamp (line 219) | public boolean isSyncByTimestamp() {
      method setSyncByTimestamp (line 223) | public void setSyncByTimestamp(boolean syncByTimestamp) {
      method getSchemaItem (line 227) | public SchemaItem getSchemaItem() {
      method setSchemaItem (line 231) | public void setSchemaItem(SchemaItem schemaItem) {
    class RelationMapping (line 236) | public static class RelationMapping {
      method getName (line 241) | public String getName() {
      method setName (line 245) | public void setName(String name) {
      method getParent (line 249) | public String getParent() {
      method setParent (line 253) | public void setParent(String parent) {

FILE: client-adapter/escore/src/main/java/com/alibaba/otter/canal/client/adapter/es/core/config/ESSyncConfigLoader.java
  class ESSyncConfigLoader (line 19) | public class ESSyncConfigLoader {
    method load (line 23) | public static synchronized Map<String, ESSyncConfig> load(Properties e...

FILE: client-adapter/escore/src/main/java/com/alibaba/otter/canal/client/adapter/es/core/config/SchemaItem.java
  class SchemaItem (line 15) | public class SchemaItem {
    method init (line 25) | public void init() {
    method getAliasTableItems (line 35) | public Map<String, TableItem> getAliasTableItems() {
    method setAliasTableItems (line 39) | public void setAliasTableItems(Map<String, TableItem> aliasTableItems) {
    method getSql (line 43) | public String getSql() {
    method setSql (line 47) | public void setSql(String sql) {
    method getSelectFields (line 51) | public Map<String, FieldItem> getSelectFields() {
    method setSelectFields (line 55) | public void setSelectFields(Map<String, FieldItem> selectFields) {
    method toSql (line 59) | public String toSql() {
    method getTableItemAliases (line 64) | public Map<String, List<TableItem>> getTableItemAliases() {
    method getColumnFields (line 80) | public Map<String, List<FieldItem>> getColumnFields() {
    method isAllFieldsSimple (line 111) | public boolean isAllFieldsSimple() {
    method getMainTable (
Condensed preview — 1316 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (8,270K chars).
[
  {
    "path": ".codecov.yml",
    "chars": 95,
    "preview": "coverage:\n  status:\n    # pull-requests only\n    patch:\n      default:\n        threshold: 0.1%\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/any-questions-on-canal.md",
    "chars": 166,
    "preview": "---\nname: Any Questions on Canal\nabout: Ask whatever you want to know or confusion about Canal\n\n---\n\n## Question\n<!-- Yo"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report-for-canal.md",
    "chars": 598,
    "preview": "---\nname: Bug Report for Canal\nabout: Create a report to help us improve\n\n---\n\n- [ ] I have searched the [issues](https:"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-request-of-canal.md",
    "chars": 469,
    "preview": "---\nname: Feature Request of Canal\nabout: Suggest an idea for this project\n\n---\n\n## Why you need it?\n<!-- Is your featur"
  },
  {
    "path": ".github/workflows/maven.yml",
    "chars": 1515,
    "preview": "# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow executi"
  },
  {
    "path": ".gitignore",
    "chars": 376,
    "preview": ".svn/\ntarget/\ntest-output/\n*.class\n.classpath\n.project\n.settings/\ntmp\ntemp\nlogs/\n*.log\nantx.properties\notter.properties\n"
  },
  {
    "path": ".mvn/wrapper/maven-wrapper.properties",
    "chars": 110,
    "preview": "distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.0/apache-maven-3.5.0-bin.zip\n"
  },
  {
    "path": ".travis.yml",
    "chars": 492,
    "preview": "language: java\nsudo: false # faster builds\n\njdk:\n  - oraclejdk12\n  - openjdk11\n  - oraclejdk11\n  - openjdk8\n\ncache:\n  di"
  },
  {
    "path": "LICENSE.txt",
    "chars": 11560,
    "preview": "\r\n                                 Apache License\r\n                           Version 2.0, January 2004\r\n               "
  },
  {
    "path": "README.md",
    "chars": 6001,
    "preview": "[![build status](https://travis-ci.com/alibaba/canal.svg?branch=master)](https://travis-ci.com/alibaba/canal)\n[![codecov"
  },
  {
    "path": "RELEASE.txt",
    "chars": 120,
    "preview": "release link : https://alibaba.github.com/canal/release.html\n\ndownload link : https://github.com/alibaba/canal/releases\n"
  },
  {
    "path": "SECURITY.md",
    "chars": 4179,
    "preview": "# 漏洞奖励计划 \n## 报告\n如果您认为自己在本程序中发现了任何安全(技术)漏洞,欢迎您通过 https://security.alibaba.com 向我们提交漏洞报告。\n如果您报告任何安全漏洞,请注意您可能包含以下信息(合格报告):\n"
  },
  {
    "path": "admin/admin-ui/.editorconfig",
    "chars": 243,
    "preview": "# http://editorconfig.org\nroot = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\nend_of_line = lf\ninsert_"
  },
  {
    "path": "admin/admin-ui/.eslintignore",
    "chars": 34,
    "preview": "build/*.js\nsrc/assets\npublic\ndist\n"
  },
  {
    "path": "admin/admin-ui/.eslintrc.js",
    "chars": 5120,
    "preview": "module.exports = {\n  root: true,\n  parserOptions: {\n    parser: 'babel-eslint',\n    sourceType: 'module'\n  },\n  env: {\n "
  },
  {
    "path": "admin/admin-ui/.gitignore",
    "chars": 198,
    "preview": ".DS_Store\nnode_modules/\ndist/\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npackage-lock.json\ntests/**/coverage/\ntarget"
  },
  {
    "path": "admin/admin-ui/.travis.yml",
    "chars": 81,
    "preview": "language: node_js\nnode_js: 10\nscript: npm run test\nnotifications:\n  email: false\n"
  },
  {
    "path": "admin/admin-ui/LICENSE",
    "chars": 1075,
    "preview": "MIT License\n\nCopyright (c) 2017-present PanJiaChen\n\nPermission is hereby granted, free of charge, to any person obtainin"
  },
  {
    "path": "admin/admin-ui/babel.config.js",
    "chars": 53,
    "preview": "module.exports = {\n  presets: [\n    '@vue/app'\n  ]\n}\n"
  },
  {
    "path": "admin/admin-ui/build/index.js",
    "chars": 899,
    "preview": "const { run } = require('runjs')\nconst chalk = require('chalk')\nconst config = require('../vue.config.js')\nconst rawArgv"
  },
  {
    "path": "admin/admin-ui/jest.config.js",
    "chars": 766,
    "preview": "module.exports = {\n  moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],\n  transform: {\n    '^.+\\\\.vue$': 'vue-jest',\n  "
  },
  {
    "path": "admin/admin-ui/mock/index.js",
    "chars": 1697,
    "preview": "import Mock from 'mockjs'\nimport { param2Obj } from '../src/utils'\n\nimport user from './user'\nimport table from './table"
  },
  {
    "path": "admin/admin-ui/mock/mock-server.js",
    "chars": 1842,
    "preview": "const chokidar = require('chokidar')\nconst bodyParser = require('body-parser')\nconst chalk = require('chalk')\nconst path"
  },
  {
    "path": "admin/admin-ui/mock/table.js",
    "chars": 519,
    "preview": "import Mock from 'mockjs'\n\nconst data = Mock.mock({\n  'items|30': [{\n    id: '@id',\n    title: '@sentence(10, 20)',\n    "
  },
  {
    "path": "admin/admin-ui/mock/user.js",
    "chars": 1493,
    "preview": "\nconst tokens = {\n  admin: {\n    token: 'admin-token'\n  },\n  editor: {\n    token: 'editor-token'\n  }\n}\n\nconst users = {\n"
  },
  {
    "path": "admin/admin-ui/package.json",
    "chars": 1909,
    "preview": "{\n  \"name\": \"canal-admin-ui\",\n  \"version\": \"1.1.4\",\n  \"description\": \"A canal-admin ui with Element UI & axios & iconfon"
  },
  {
    "path": "admin/admin-ui/pom.xml",
    "chars": 2594,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2"
  },
  {
    "path": "admin/admin-ui/postcss.config.js",
    "chars": 197,
    "preview": "// https://github.com/michael-ciniawsky/postcss-load-config\n\nmodule.exports = {\n  'plugins': {\n    // to edit target bro"
  },
  {
    "path": "admin/admin-ui/public/index.html",
    "chars": 620,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrom"
  },
  {
    "path": "admin/admin-ui/src/App.vue",
    "chars": 122,
    "preview": "<template>\n  <div id=\"app\">\n    <router-view />\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'App'\n}\n</script"
  },
  {
    "path": "admin/admin-ui/src/api/canalCluster.js",
    "chars": 788,
    "preview": "import request from '@/utils/request'\n\nexport function getCanalClusters(params) {\n  return request({\n    url: '/canal/cl"
  },
  {
    "path": "admin/admin-ui/src/api/canalConfig.js",
    "chars": 434,
    "preview": "import request from '@/utils/request'\n\nexport function getCanalConfig(clusterId, serverId) {\n  return request({\n    url:"
  },
  {
    "path": "admin/admin-ui/src/api/canalInstance.js",
    "chars": 1514,
    "preview": "import request from '@/utils/request'\n\nexport function getCanalInstances(params) {\n  return request({\n    url: '/canal/i"
  },
  {
    "path": "admin/admin-ui/src/api/nodeServer.js",
    "chars": 989,
    "preview": "import request from '@/utils/request'\n\nexport function getNodeServers(params) {\n  return request({\n    url: '/nodeServer"
  },
  {
    "path": "admin/admin-ui/src/api/table.js",
    "chars": 153,
    "preview": "import request from '@/utils/request'\n\nexport function getList(params) {\n  return request({\n    url: '/table/list',\n    "
  },
  {
    "path": "admin/admin-ui/src/api/user.js",
    "chars": 478,
    "preview": "import request from '@/utils/request'\n\nexport function login(data) {\n  return request({\n    url: '/user/login',\n    meth"
  },
  {
    "path": "admin/admin-ui/src/components/Breadcrumb/index.vue",
    "chars": 2006,
    "preview": "<template>\n  <el-breadcrumb class=\"app-breadcrumb\" separator=\"/\">\n    <transition-group name=\"breadcrumb\">\n      <el-bre"
  },
  {
    "path": "admin/admin-ui/src/components/Hamburger/index.vue",
    "chars": 1156,
    "preview": "<template>\n  <div style=\"padding: 0 15px;\" @click=\"toggleClick\">\n    <svg\n      :class=\"{'is-active':isActive}\"\n      cl"
  },
  {
    "path": "admin/admin-ui/src/components/Pagination/index.vue",
    "chars": 1881,
    "preview": "<template>\n  <div :class=\"{'hidden':hidden}\" class=\"pagination-container\">\n    <el-pagination\n      :background=\"backgro"
  },
  {
    "path": "admin/admin-ui/src/components/SvgIcon/index.vue",
    "chars": 1312,
    "preview": "<template>\n  <div v-if=\"isExternal\" :style=\"styleExternalIcon\" class=\"svg-external-icon svg-icon\" v-on=\"$listeners\" />\n "
  },
  {
    "path": "admin/admin-ui/src/icons/index.js",
    "chars": 288,
    "preview": "import Vue from 'vue'\nimport SvgIcon from '@/components/SvgIcon'// svg component\n\n// register globally\nVue.component('sv"
  },
  {
    "path": "admin/admin-ui/src/icons/svgo.yml",
    "chars": 248,
    "preview": "# replace default config\n\n# multipass: true\n# full: true\n\nplugins:\n\n  # - name\n  #\n  # or:\n  # - name: false\n  # - name:"
  },
  {
    "path": "admin/admin-ui/src/layout/components/AppMain.vue",
    "chars": 637,
    "preview": "<template>\n  <section class=\"app-main\">\n    <transition name=\"fade-transform\" mode=\"out-in\">\n      <router-view :key=\"ke"
  },
  {
    "path": "admin/admin-ui/src/layout/components/Navbar.vue",
    "chars": 3015,
    "preview": "<template>\n  <div class=\"navbar\">\n    <hamburger :is-active=\"sidebar.opened\" class=\"hamburger-container\" @toggleClick=\"t"
  },
  {
    "path": "admin/admin-ui/src/layout/components/Sidebar/FixiOSBug.js",
    "chars": 633,
    "preview": "export default {\n  computed: {\n    device() {\n      return this.$store.state.app.device\n    }\n  },\n  mounted() {\n    // "
  },
  {
    "path": "admin/admin-ui/src/layout/components/Sidebar/Item.vue",
    "chars": 468,
    "preview": "<script>\nexport default {\n  name: 'MenuItem',\n  functional: true,\n  props: {\n    icon: {\n      type: String,\n      defau"
  },
  {
    "path": "admin/admin-ui/src/layout/components/Sidebar/Link.vue",
    "chars": 567,
    "preview": "\n<template>\n  <!-- eslint-disable vue/require-component-is -->\n  <component v-bind=\"linkProps(to)\">\n    <slot />\n  </com"
  },
  {
    "path": "admin/admin-ui/src/layout/components/Sidebar/Logo.vue",
    "chars": 1675,
    "preview": "<template>\n  <div class=\"sidebar-logo-container\" :class=\"{'collapse':collapse}\">\n    <transition name=\"sidebarLogoFade\">"
  },
  {
    "path": "admin/admin-ui/src/layout/components/Sidebar/SidebarItem.vue",
    "chars": 2674,
    "preview": "<template>\n  <div v-if=\"!item.hidden\" class=\"menu-wrapper\">\n    <template v-if=\"hasOneShowingChild(item.children,item) &"
  },
  {
    "path": "admin/admin-ui/src/layout/components/Sidebar/index.vue",
    "chars": 1416,
    "preview": "<template>\n  <div :class=\"{'has-logo':showLogo}\">\n    <logo v-if=\"showLogo\" :collapse=\"isCollapse\" />\n    <el-scrollbar "
  },
  {
    "path": "admin/admin-ui/src/layout/components/index.js",
    "chars": 139,
    "preview": "export { default as Navbar } from './Navbar'\nexport { default as Sidebar } from './Sidebar'\nexport { default as AppMain "
  },
  {
    "path": "admin/admin-ui/src/layout/index.vue",
    "chars": 1892,
    "preview": "<template>\n  <div :class=\"classObj\" class=\"app-wrapper\">\n    <div v-if=\"device==='mobile'&&sidebar.opened\" class=\"drawer"
  },
  {
    "path": "admin/admin-ui/src/layout/mixin/ResizeHandler.js",
    "chars": 1235,
    "preview": "import store from '@/store'\n\nconst { body } = document\nconst WIDTH = 992 // refer to Bootstrap's responsive design\n\nexpo"
  },
  {
    "path": "admin/admin-ui/src/main.js",
    "chars": 958,
    "preview": "import Vue from 'vue'\n\nimport 'normalize.css/normalize.css' // A modern alternative to CSS resets\n\nimport ElementUI from"
  },
  {
    "path": "admin/admin-ui/src/permission.js",
    "chars": 1729,
    "preview": "import router from './router'\nimport store from './store'\nimport { Message } from 'element-ui'\nimport NProgress from 'np"
  },
  {
    "path": "admin/admin-ui/src/router/index.js",
    "chars": 4488,
    "preview": "import Vue from 'vue'\nimport Router from 'vue-router'\n\nVue.use(Router)\n\n/* Layout */\nimport Layout from '@/layout'\n\n/**\n"
  },
  {
    "path": "admin/admin-ui/src/settings.js",
    "chars": 273,
    "preview": "module.exports = {\n\n  title: 'Canal Admin',\n\n  /**\n   * @type {boolean} true | false\n   * @description Whether fix the h"
  },
  {
    "path": "admin/admin-ui/src/store/getters.js",
    "chars": 226,
    "preview": "const getters = {\n  sidebar: state => state.app.sidebar,\n  device: state => state.app.device,\n  token: state => state.us"
  },
  {
    "path": "admin/admin-ui/src/store/index.js",
    "chars": 318,
    "preview": "import Vue from 'vue'\nimport Vuex from 'vuex'\nimport getters from './getters'\nimport app from './modules/app'\nimport set"
  },
  {
    "path": "admin/admin-ui/src/store/modules/app.js",
    "chars": 1056,
    "preview": "import Cookies from 'js-cookie'\n\nconst state = {\n  sidebar: {\n    opened: Cookies.get('sidebarStatus') ? !!+Cookies.get("
  },
  {
    "path": "admin/admin-ui/src/store/modules/settings.js",
    "chars": 524,
    "preview": "import defaultSettings from '@/settings'\n\nconst { showSettings, fixedHeader, sidebarLogo } = defaultSettings\n\nconst stat"
  },
  {
    "path": "admin/admin-ui/src/store/modules/user.js",
    "chars": 1857,
    "preview": "import { login, logout, getInfo } from '@/api/user'\nimport { getToken, setToken, removeToken } from '@/utils/auth'\nimpor"
  },
  {
    "path": "admin/admin-ui/src/styles/element-ui.scss",
    "chars": 597,
    "preview": "// cover some element-ui styles\n\n.el-breadcrumb__inner,\n.el-breadcrumb__inner a {\n  font-weight: 400 !important;\n}\n\n.el-"
  },
  {
    "path": "admin/admin-ui/src/styles/index.scss",
    "chars": 1059,
    "preview": "@import './variables.scss';\n@import './mixin.scss';\n@import './transition.scss';\n@import './element-ui.scss';\n@import '."
  },
  {
    "path": "admin/admin-ui/src/styles/mixin.scss",
    "chars": 384,
    "preview": "@mixin clearfix {\n  &:after {\n    content: \"\";\n    display: table;\n    clear: both;\n  }\n}\n\n@mixin scrollBar {\n  &::-webk"
  },
  {
    "path": "admin/admin-ui/src/styles/sidebar.scss",
    "chars": 3701,
    "preview": "#app {\n\n  .main-container {\n    min-height: 100%;\n    transition: margin-left .28s;\n    margin-left: $sideBarWidth;\n    "
  },
  {
    "path": "admin/admin-ui/src/styles/transition.scss",
    "chars": 714,
    "preview": "// global transition css\n\n/* fade */\n.fade-enter-active,\n.fade-leave-active {\n  transition: opacity 0.28s;\n}\n\n.fade-ente"
  },
  {
    "path": "admin/admin-ui/src/styles/variables.scss",
    "chars": 616,
    "preview": "// sidebar\n$menuText:#bfcbd9;\n$menuActiveText:#409EFF;\n$subMenuActiveText:#f4f4f5; //https://github.com/ElemeFE/element/"
  },
  {
    "path": "admin/admin-ui/src/utils/auth.js",
    "chars": 292,
    "preview": "import Cookies from 'js-cookie'\n\nconst TokenKey = 'canal_admin_token'\n\nexport function getToken() {\n  return Cookies.get"
  },
  {
    "path": "admin/admin-ui/src/utils/get-page-title.js",
    "chars": 235,
    "preview": "import defaultSettings from '@/settings'\n\nconst title = defaultSettings.title || 'Vue Admin Template'\n\nexport default fu"
  },
  {
    "path": "admin/admin-ui/src/utils/index.js",
    "chars": 2324,
    "preview": "/**\n * Created by PanJiaChen on 16/11/18.\n */\n\n/**\n * Parse the time to string\n * @param {(Object|string|number)} time\n "
  },
  {
    "path": "admin/admin-ui/src/utils/request.js",
    "chars": 2344,
    "preview": "import axios from 'axios'\nimport { MessageBox, Message } from 'element-ui'\nimport store from '@/store'\nimport { getToken"
  },
  {
    "path": "admin/admin-ui/src/utils/scrollTo.js",
    "chars": 1592,
    "preview": "Math.easeInOutQuad = function(t, b, c, d) {\n  t /= d / 2\n  if (t < 1) {\n    return c / 2 * t * t + b\n  }\n  t--\n  return "
  },
  {
    "path": "admin/admin-ui/src/utils/validate.js",
    "chars": 361,
    "preview": "/**\n * Created by PanJiaChen on 16/11/18.\n */\n\n/**\n * @param {string} path\n * @returns {Boolean}\n */\nexport function isE"
  },
  {
    "path": "admin/admin-ui/src/views/404.vue",
    "chars": 5227,
    "preview": "<template>\n  <div class=\"wscn-http404-container\">\n    <div class=\"wscn-http404\">\n      <div class=\"pic-404\">\n        <im"
  },
  {
    "path": "admin/admin-ui/src/views/canalServer/CanalCluster.vue",
    "chars": 6203,
    "preview": "<template>\n  <div class=\"app-container\">\n    <div class=\"filter-container\">\n      <!-- <el-input v-model=\"listQuery.name"
  },
  {
    "path": "admin/admin-ui/src/views/canalServer/CanalConfig.vue",
    "chars": 3067,
    "preview": "<template>\n  <div>\n    <el-form ref=\"form\" :model=\"form\">\n      <div style=\"padding-left: 10px;padding-top: 20px;\">\n    "
  },
  {
    "path": "admin/admin-ui/src/views/canalServer/CanalInstance.vue",
    "chars": 7397,
    "preview": "<template>\n  <div class=\"app-container\">\n    <div class=\"filter-container\">\n      <el-input v-model=\"listQuery.name\" pla"
  },
  {
    "path": "admin/admin-ui/src/views/canalServer/CanalInstanceAdd.vue",
    "chars": 3192,
    "preview": "<template>\n  <div>\n    <el-form ref=\"form\" :model=\"form\">\n      <div class=\"filter-container\" style=\"padding-left: 10px;"
  },
  {
    "path": "admin/admin-ui/src/views/canalServer/CanalInstanceLogDetail.vue",
    "chars": 1109,
    "preview": "<template>\n  <div>\n    <el-form ref=\"form\" :model=\"form\">\n      <div style=\"padding-left: 10px;padding-right: 10px;paddi"
  },
  {
    "path": "admin/admin-ui/src/views/canalServer/CanalInstanceUpdate.vue",
    "chars": 2922,
    "preview": "<template>\n  <div>\n    <el-form ref=\"form\" :model=\"form\">\n      <div style=\"padding-left: 10px;padding-top: 20px;\">\n    "
  },
  {
    "path": "admin/admin-ui/src/views/canalServer/CanalLogDetail.vue",
    "chars": 992,
    "preview": "<template>\n  <div>\n    <el-form ref=\"form\" :model=\"form\">\n      <div style=\"padding-left: 10px;padding-right: 10px;paddi"
  },
  {
    "path": "admin/admin-ui/src/views/canalServer/NodeServer.vue",
    "chars": 15492,
    "preview": "<template>\n  <div class=\"app-container\">\n    <div class=\"filter-container\">\n      <!--<el-input v-model=\"listQuery.name\""
  },
  {
    "path": "admin/admin-ui/src/views/dashboard/index.vue",
    "chars": 472,
    "preview": "<template>\n  <div class=\"dashboard-container\">\n    <div class=\"dashboard-text\">&nbsp;</div>\n  </div>\n</template>\n\n<scrip"
  },
  {
    "path": "admin/admin-ui/src/views/login/index.vue",
    "chars": 5369,
    "preview": "<template>\n  <div class=\"login-container\">\n    <el-form ref=\"loginForm\" :model=\"loginForm\" :rules=\"loginRules\" class=\"lo"
  },
  {
    "path": "admin/admin-ui/src/views/sys/UserInfo.vue",
    "chars": 2197,
    "preview": "<template>\n  <div class=\"app-container\" style=\"width: 600px;\">\n    <el-form ref=\"form\" :rules=\"rules\" :model=\"form\" labe"
  },
  {
    "path": "admin/admin-ui/tests/unit/.eslintrc.js",
    "chars": 49,
    "preview": "module.exports = {\n  env: {\n    jest: true\n  }\n}\n"
  },
  {
    "path": "admin/admin-ui/tests/unit/components/Breadcrumb.spec.js",
    "chars": 2677,
    "preview": "import { mount, createLocalVue } from '@vue/test-utils'\nimport VueRouter from 'vue-router'\nimport ElementUI from 'elemen"
  },
  {
    "path": "admin/admin-ui/tests/unit/components/Hamburger.spec.js",
    "chars": 641,
    "preview": "import { shallowMount } from '@vue/test-utils'\nimport Hamburger from '@/components/Hamburger/index.vue'\ndescribe('Hambur"
  },
  {
    "path": "admin/admin-ui/tests/unit/components/SvgIcon.spec.js",
    "chars": 621,
    "preview": "import { shallowMount } from '@vue/test-utils'\nimport SvgIcon from '@/components/SvgIcon/index.vue'\ndescribe('SvgIcon.vu"
  },
  {
    "path": "admin/admin-ui/tests/unit/utils/formatTime.spec.js",
    "chars": 1032,
    "preview": "import { formatTime } from '@/utils/index.js'\n\ndescribe('Utils:formatTime', () => {\n  const d = new Date('2018-07-13 17:"
  },
  {
    "path": "admin/admin-ui/tests/unit/utils/parseTime.spec.js",
    "chars": 965,
    "preview": "import { parseTime } from '@/utils/index.js'\n\ndescribe('Utils:parseTime', () => {\n  const d = new Date('2018-07-13 17:54"
  },
  {
    "path": "admin/admin-ui/tests/unit/utils/validate.spec.js",
    "chars": 703,
    "preview": "import { validUsername, isExternal } from '@/utils/validate.js'\n\ndescribe('Utils:validate', () => {\n  it('validUsername'"
  },
  {
    "path": "admin/admin-ui/vue.config.js",
    "chars": 4344,
    "preview": "'use strict'\nconst path = require('path')\nconst defaultSettings = require('./src/settings.js')\n\nfunction resolve(dir) {\n"
  },
  {
    "path": "admin/admin-web/pom.xml",
    "chars": 8820,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2"
  },
  {
    "path": "admin/admin-web/src/main/assembly/dev.xml",
    "chars": 1878,
    "preview": "<assembly xmlns=\"http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0\" xmlns:xsi=\"http://www.w3.org/2001"
  },
  {
    "path": "admin/admin-web/src/main/assembly/release.xml",
    "chars": 1921,
    "preview": "<assembly xmlns=\"http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0\"\n          xmlns:xsi=\"http://www.w"
  },
  {
    "path": "admin/admin-web/src/main/bin/restart.sh",
    "chars": 205,
    "preview": "#!/bin/bash\n\ncase $(uname) in\nLinux)\n  bin_abs_path=$(readlink -f $(dirname $0))\n  ;;\n*)\n  bin_abs_path=$(cd $(dirname $"
  },
  {
    "path": "admin/admin-web/src/main/bin/startup.bat",
    "chars": 749,
    "preview": "@echo off\n@if not \"%ECHO%\" == \"\"  echo %ECHO%\n@if \"%OS%\" == \"Windows_NT\"  setlocal\n\nset ENV_PATH=.\\\nif \"%OS%\" == \"Window"
  },
  {
    "path": "admin/admin-web/src/main/bin/startup.sh",
    "chars": 2906,
    "preview": "#!/bin/bash\n\ncurrent_path=`pwd`\ncase \"`uname`\" in\n    Linux)\n\t\tbin_abs_path=$(readlink -f $(dirname $0))\n\t\t;;\n\t*)\n\t\tbin_"
  },
  {
    "path": "admin/admin-web/src/main/bin/stop.sh",
    "chars": 1362,
    "preview": "#!/bin/bash\n\ncygwin=false;\nlinux=false;\ncase \"`uname`\" in\n    CYGWIN*)\n        cygwin=true\n        ;;\n    Linux*)\n    \tl"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/CanalAdminApplication.java",
    "chars": 559,
    "preview": "package com.alibaba.otter.canal.admin;\n\nimport org.springframework.boot.Banner;\nimport org.springframework.boot.SpringAp"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/common/DaemonThreadFactory.java",
    "chars": 440,
    "preview": "package com.alibaba.otter.canal.admin.common;\n\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.Thread"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/common/TemplateConfigLoader.java",
    "chars": 1672,
    "preview": "package com.alibaba.otter.canal.admin.common;\n\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.IOExc"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/common/Threads.java",
    "chars": 814,
    "preview": "package com.alibaba.otter.canal.admin.common;\n\nimport java.util.concurrent.ArrayBlockingQueue;\nimport java.util.concurre"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/common/exception/ServiceException.java",
    "chars": 1673,
    "preview": "/*\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements.  See the NOT"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/config/EbeanConfig.java",
    "chars": 1293,
    "preview": "package com.alibaba.otter.canal.admin.config;\n\nimport io.ebean.EbeanServer;\nimport io.ebean.EbeanServerFactory;\nimport i"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/config/SpringContext.java",
    "chars": 905,
    "preview": "package com.alibaba.otter.canal.admin.config;\n\nimport org.springframework.beans.BeansException;\nimport org.springframewo"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/config/WebConfig.java",
    "chars": 4717,
    "preview": "package com.alibaba.otter.canal.admin.config;\n\nimport java.io.PrintWriter;\n\nimport javax.servlet.http.HttpServletRequest"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/connector/AdminConnector.java",
    "chars": 2204,
    "preview": "package com.alibaba.otter.canal.admin.connector;\n\nimport com.alibaba.otter.canal.admin.common.exception.ServiceException"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/connector/SimpleAdminConnector.java",
    "chars": 11426,
    "preview": "package com.alibaba.otter.canal.admin.connector;\n\nimport java.io.IOException;\nimport java.net.InetSocketAddress;\nimport "
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/connector/SimpleAdminConnectors.java",
    "chars": 1790,
    "preview": "package com.alibaba.otter.canal.admin.connector;\n\nimport java.util.function.Function;\n\nimport org.assertj.core.util.Stri"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/controller/CanalClusterController.java",
    "chars": 3759,
    "preview": "package com.alibaba.otter.canal.admin.controller;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.spring"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/controller/CanalConfigController.java",
    "chars": 1937,
    "preview": "package com.alibaba.otter.canal.admin.controller;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/controller/CanalInstanceController.java",
    "chars": 5867,
    "preview": "package com.alibaba.otter.canal.admin.controller;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport org.springframew"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/controller/NodeServerController.java",
    "chars": 4249,
    "preview": "package com.alibaba.otter.canal.admin.controller;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/controller/PollingConfigController.java",
    "chars": 4473,
    "preview": "package com.alibaba.otter.canal.admin.controller;\n\nimport java.security.NoSuchAlgorithmException;\n\nimport org.apache.com"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/controller/UserController.java",
    "chars": 3851,
    "preview": "package com.alibaba.otter.canal.admin.controller;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.UUID"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/handler/CustomExceptionHandler.java",
    "chars": 1320,
    "preview": "package com.alibaba.otter.canal.admin.handler;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.spri"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/model/BaseModel.java",
    "chars": 820,
    "preview": "package com.alibaba.otter.canal.admin.model;\n\n/**\n * 基础Model\n *\n * @author rewerma 2019-07-13 下午05:12:16\n * @version 1.0"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/model/CanalCluster.java",
    "chars": 1430,
    "preview": "package com.alibaba.otter.canal.admin.model;\n\nimport io.ebean.Finder;\nimport io.ebean.annotation.WhenModified;\n\nimport j"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/model/CanalConfig.java",
    "chars": 2163,
    "preview": "package com.alibaba.otter.canal.admin.model;\n\nimport io.ebean.Finder;\nimport io.ebean.annotation.WhenModified;\n\nimport j"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/model/CanalInstanceConfig.java",
    "chars": 3705,
    "preview": "package com.alibaba.otter.canal.admin.model;\n\nimport io.ebean.Finder;\nimport io.ebean.annotation.WhenModified;\n\nimport j"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/model/Model.java",
    "chars": 2164,
    "preview": "package com.alibaba.otter.canal.admin.model;\n\nimport io.ebean.Ebean;\nimport io.ebean.EbeanServer;\n\nimport javax.persiste"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/model/NodeServer.java",
    "chars": 2932,
    "preview": "package com.alibaba.otter.canal.admin.model;\n\nimport io.ebean.Finder;\nimport io.ebean.annotation.WhenModified;\n\nimport j"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/model/Pager.java",
    "chars": 1747,
    "preview": "package com.alibaba.otter.canal.admin.model;\n\nimport java.io.Serializable;\nimport java.util.ArrayList;\nimport java.util."
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/model/User.java",
    "chars": 2290,
    "preview": "package com.alibaba.otter.canal.admin.model;\n\nimport io.ebean.Finder;\nimport io.ebean.annotation.WhenCreated;\n\nimport ja"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/CanalClusterService.java",
    "chars": 382,
    "preview": "package com.alibaba.otter.canal.admin.service;\n\nimport java.util.List;\n\nimport com.alibaba.otter.canal.admin.model.Canal"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/CanalConfigService.java",
    "chars": 338,
    "preview": "package com.alibaba.otter.canal.admin.service;\n\nimport com.alibaba.otter.canal.admin.model.CanalConfig;\n\npublic interfac"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/CanalInstanceService.java",
    "chars": 915,
    "preview": "package com.alibaba.otter.canal.admin.service;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport com.alibaba.otter.c"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/NodeServerService.java",
    "chars": 635,
    "preview": "package com.alibaba.otter.canal.admin.service;\n\nimport java.util.List;\n\nimport com.alibaba.otter.canal.admin.model.NodeS"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/PollingConfigService.java",
    "chars": 534,
    "preview": "package com.alibaba.otter.canal.admin.service;\n\nimport com.alibaba.otter.canal.admin.model.CanalConfig;\nimport com.aliba"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/UserService.java",
    "chars": 216,
    "preview": "package com.alibaba.otter.canal.admin.service;\n\nimport com.alibaba.otter.canal.admin.model.User;\n\npublic interface UserS"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/impl/CanalClusterServiceImpl.java",
    "chars": 1680,
    "preview": "package com.alibaba.otter.canal.admin.service.impl;\n\nimport io.ebean.Query;\n\nimport java.util.List;\n\nimport org.springfr"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/impl/CanalConfigServiceImpl.java",
    "chars": 4317,
    "preview": "package com.alibaba.otter.canal.admin.service.impl;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/impl/CanalInstanceServiceImpl.java",
    "chars": 13003,
    "preview": "package com.alibaba.otter.canal.admin.service.impl;\n\nimport io.ebean.Query;\n\nimport java.security.NoSuchAlgorithmExcepti"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/impl/NodeServerServiceImpl.java",
    "chars": 6999,
    "preview": "package com.alibaba.otter.canal.admin.service.impl;\n\nimport io.ebean.Query;\n\nimport java.security.NoSuchAlgorithmExcepti"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/impl/PollingConfigServiceImpl.java",
    "chars": 5311,
    "preview": "package com.alibaba.otter.canal.admin.service.impl;\n\nimport java.security.NoSuchAlgorithmException;\nimport java.util.Lis"
  },
  {
    "path": "admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/impl/UserServiceImpl.java",
    "chars": 2578,
    "preview": "package com.alibaba.otter.canal.admin.service.impl;\n\nimport java.security.NoSuchAlgorithmException;\n\nimport org.apache.c"
  },
  {
    "path": "admin/admin-web/src/main/resources/application.yml",
    "chars": 479,
    "preview": "server:\n  port: 8089\nspring:\n  jackson:\n    date-format: yyyy-MM-dd HH:mm:ss\n    time-zone: GMT+8\n\nspring.datasource:\n  "
  },
  {
    "path": "admin/admin-web/src/main/resources/canal-template.properties",
    "chars": 6737,
    "preview": "#################################################\n######### \t\tcommon argument\t\t#############\n###########################"
  },
  {
    "path": "admin/admin-web/src/main/resources/canal_manager.sql",
    "chars": 3908,
    "preview": "CREATE DATABASE /*!32312 IF NOT EXISTS*/ `canal_manager` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_bin */;\n\nUSE `"
  },
  {
    "path": "admin/admin-web/src/main/resources/instance-template.properties",
    "chars": 2036,
    "preview": "#################################################\n## mysql serverId , v1.0.26+ will autoGen\n# canal.instance.mysql.slave"
  },
  {
    "path": "admin/admin-web/src/main/resources/logback.xml",
    "chars": 1568,
    "preview": "<configuration scan=\"true\" scanPeriod=\" 5 seconds\">\n\t<jmxConfigurator />\n\t<appender name=\"STDOUT\" class=\"ch.qos.logback."
  },
  {
    "path": "admin/admin-web/src/main/resources/public/index.html",
    "chars": 4818,
    "preview": "<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content=\"IE=edge,chrome=1\"><meta name=vi"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/css/app.bb951cb3.css",
    "chars": 9517,
    "preview": ".fade-enter-active,.fade-leave-active{-webkit-transition:opacity .28s;transition:opacity .28s}.fade-enter,.fade-leave-ac"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/css/chunk-101fc062.fad9926f.css",
    "chars": 1633,
    "preview": "@supports (-webkit-mask:none) and (not (cater-color:#fff)){.login-container .el-input input{color:#fff}}.login-container"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/css/chunk-14b5f7a4.f3e06673.css",
    "chars": 132,
    "preview": ".pagination-container[data-v-cebf2f0c]{background:#fff;padding:32px 16px}.pagination-container.hidden[data-v-cebf2f0c]{d"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/css/chunk-22553be3.f3e06673.css",
    "chars": 132,
    "preview": ".pagination-container[data-v-cebf2f0c]{background:#fff;padding:32px 16px}.pagination-container.hidden[data-v-cebf2f0c]{d"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/css/chunk-2301924a.160e7b4a.css",
    "chars": 41,
    "preview": ".line[data-v-28f0cd0f]{text-align:center}"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/css/chunk-2b9b6c5c.c89f8844.css",
    "chars": 132,
    "preview": ".pagination-container[data-v-38ef71f0]{background:#fff;padding:32px 16px}.pagination-container.hidden[data-v-38ef71f0]{d"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/css/chunk-37c49cbf.efc21a9c.css",
    "chars": 115,
    "preview": ".dashboard-container[data-v-42037c2b]{margin:30px}.dashboard-text[data-v-42037c2b]{font-size:30px;line-height:46px}"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/css/chunk-49959c8b.e8e2beee.css",
    "chars": 4748,
    "preview": ".wscn-http404-container[data-v-c095f994]{-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);position:"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/css/chunk-4f09fed2.70ec0b86.css",
    "chars": 41,
    "preview": ".line[data-v-64c3fae5]{text-align:center}"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/css/chunk-5afa45f5.a34bb177.css",
    "chars": 41,
    "preview": ".line[data-v-2e6a6604]{text-align:center}"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/css/chunk-5b373aad.b966d36b.css",
    "chars": 41,
    "preview": ".line[data-v-e884438a]{text-align:center}"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/css/chunk-69386cf0.741ff14e.css",
    "chars": 41,
    "preview": ".line[data-v-756ebb70]{text-align:center}"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/css/chunk-7ec889b7.c0585512.css",
    "chars": 41,
    "preview": ".line[data-v-0b80198c]{text-align:center}"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/css/chunk-98f505d0.5280f88f.css",
    "chars": 41,
    "preview": ".line[data-v-35af5ff9]{text-align:center}"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/css/chunk-bd1d44ee.1528199a.css",
    "chars": 41,
    "preview": ".line[data-v-5c332416]{text-align:center}"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/css/chunk-da289616.c89f8844.css",
    "chars": 132,
    "preview": ".pagination-container[data-v-38ef71f0]{background:#fff;padding:32px 16px}.pagination-container.hidden[data-v-38ef71f0]{d"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/css/chunk-elementUI.18b11d0e.css",
    "chars": 202729,
    "preview": ".el-pagination--small .arrow.disabled,.el-table--hidden,.el-table .hidden-columns,.el-table td.is-hidden>*,.el-table th."
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/css/chunk-libs.5cf311f0.css",
    "chars": 3568,
    "preview": "/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-ms-text-size-adjust:1"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/app.6845b228.js",
    "chars": 37105,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"app\"],{0:function(e,t,n){e.exports=n(\"56d7\")},\"028b\":functio"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/app.eee35d99.js",
    "chars": 37105,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"app\"],{0:function(e,t,n){e.exports=n(\"56d7\")},\"028b\":functio"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-0dca2f22.a2bc28b8.js",
    "chars": 1192794,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-0dca2f22\"],{\"0329\":function(e,t){ace.define(\"ace/mode/"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-101fc062.372a5ca5.js",
    "chars": 3138,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-101fc062\"],{2017:function(e,t,s){\"use strict\";var n=s("
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-101fc062.bc898027.js",
    "chars": 3138,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-101fc062\"],{2017:function(e,t,s){\"use strict\";var n=s("
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-14b5f7a4.013449e9.js",
    "chars": 21474,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-14b5f7a4\"],{\"11e9\":function(t,e,n){var r=n(\"52a7\"),a=n"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-22553be3.e6d72de5.js",
    "chars": 13258,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-22553be3\"],{\"11e9\":function(t,e,n){var a=n(\"52a7\"),r=n"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-2301924a.1774b851.js",
    "chars": 4415,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-2301924a\"],{\"10df\":function(t,e,n){},1248:function(t,e"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-2b9b6c5c.cc2181b9.js",
    "chars": 13372,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-2b9b6c5c\"],{\"11e9\":function(t,e,n){var a=n(\"52a7\"),r=n"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-37c49cbf.64d26540.js",
    "chars": 703,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-37c49cbf\"],{3671:function(t,e,n){\"use strict\";var a=n("
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-37c49cbf.92ebe0ae.js",
    "chars": 703,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-37c49cbf\"],{3671:function(t,e,n){\"use strict\";var a=n("
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-49959c8b.058266cb.js",
    "chars": 1891,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-49959c8b\"],{\"26fc\":function(t,s,a){t.exports=a.p+\"stat"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-49959c8b.6d226f70.js",
    "chars": 1891,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-49959c8b\"],{\"26fc\":function(t,s,a){t.exports=a.p+\"stat"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-4f09fed2.d107437b.js",
    "chars": 2044,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-4f09fed2\"],{\"68d6\":function(t,e,n){\"use strict\";var r="
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-4f09fed2.ff28d88d.js",
    "chars": 2044,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-4f09fed2\"],{\"68d6\":function(t,e,n){\"use strict\";var r="
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-55380ff2.430ee174.js",
    "chars": 5773,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-55380ff2\"],{d631:function(t,e,n){\"use strict\";n.d(e,\"c"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-55380ff2.681c71c9.js",
    "chars": 5773,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-55380ff2\"],{d631:function(t,e,n){\"use strict\";n.d(e,\"c"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-5afa45f5.79ddcc04.js",
    "chars": 2618,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-5afa45f5\"],{\"0984\":function(t,e,n){},\"0f47\":function(t"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-5b373aad.90a2d8e7.js",
    "chars": 4744,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-5b373aad\"],{1248:function(t,e,n){\"use strict\";n.r(e);v"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-69386cf0.76d77f5c.js",
    "chars": 2223,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-69386cf0\"],{2829:function(e,t,s){},\"646d\":function(e,t"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-69386cf0.bdbe3f0c.js",
    "chars": 2223,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-69386cf0\"],{2829:function(e,t,s){},\"646d\":function(e,t"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-7ec889b7.5f730d9b.js",
    "chars": 2551,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-7ec889b7\"],{\"11ec\":function(t,n,e){},\"7f19\":function(t"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-7ec889b7.bd1ca803.js",
    "chars": 2665,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-7ec889b7\"],{\"11ec\":function(t,n,e){},\"7f19\":function(t"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-98f505d0.f3096ce7.js",
    "chars": 2362,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-98f505d0\"],{\"4e8a\":function(t,e,n){\"use strict\";var o="
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-bd1d44ee.8c8282cc.js",
    "chars": 4331,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-bd1d44ee\"],{\"878d\":function(t,n,e){},b0a2:function(t,n"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-bd1d44ee.8e2c4851.js",
    "chars": 4445,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-bd1d44ee\"],{\"878d\":function(t,n,e){},b0a2:function(t,n"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-da289616.7def925e.js",
    "chars": 21588,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-da289616\"],{\"11e9\":function(t,e,n){var r=n(\"52a7\"),a=n"
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-elementUI.667f4c87.js",
    "chars": 566110,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-elementUI\"],{\"0fae\":function(e,t,i){},\"12f2\":function("
  },
  {
    "path": "admin/admin-web/src/main/resources/public/static/js/chunk-libs.c04beefc.js",
    "chars": 219081,
    "preview": "(window[\"webpackJsonp\"]=window[\"webpackJsonp\"]||[]).push([[\"chunk-libs\"],{\"014b\":function(t,e,n){\"use strict\";var r=n(\"e"
  },
  {
    "path": "admin/admin-web/src/test/java/com/alibaba/otter/canal/admin/SimpleAdminConnectorTest.java",
    "chars": 2147,
    "preview": "package com.alibaba.otter.canal.admin;\n\nimport org.junit.Ignore;\nimport org.junit.Test;\n\nimport com.alibaba.otter.canal."
  },
  {
    "path": "admin/pom.xml",
    "chars": 2869,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2"
  },
  {
    "path": "charts/README.md",
    "chars": 4176,
    "preview": "# helm charts 使用说明\n\n包含`canal-admin`和`canal-server`两个chart,基本配置保存在k8s的`secret`里,`canal.properties`和`instance.properties`保"
  },
  {
    "path": "charts/canal-admin/.helmignore",
    "chars": 349,
    "preview": "# Patterns to ignore when building packages.\n# This supports shell glob matching, relative path matching, and\n# negation"
  },
  {
    "path": "charts/canal-admin/Chart.yaml",
    "chars": 1155,
    "preview": "apiVersion: v2\nname: canal-admin\ndescription: A Helm chart for Kubernetes\n\n# A chart can be either an 'application' or a"
  },
  {
    "path": "charts/canal-admin/templates/NOTES.txt",
    "chars": 1760,
    "preview": "1. Get the application URL by running these commands:\n{{- if .Values.ingress.enabled }}\n{{- range $host := .Values.ingre"
  },
  {
    "path": "charts/canal-admin/templates/_helpers.tpl",
    "chars": 1822,
    "preview": "{{/*\nExpand the name of the chart.\n*/}}\n{{- define \"canal-admin.name\" -}}\n{{- default .Chart.Name .Values.nameOverride |"
  },
  {
    "path": "charts/canal-admin/templates/deployment.yaml",
    "chars": 2460,
    "preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: {{ include \"canal-admin.fullname\" . }}\n  labels:\n    {{- include "
  }
]

// ... and 1116 more files (download for full content)

About this extraction

This page contains the full source code of the alibaba/canal GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1316 files (41.6 MB), approximately 2.1M tokens, and a symbol index with 10888 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!