{"diffoscope-json-version": 1, "source1": "/input1", "source2": "/input2", "unified_diff": null, "details": [{"source1": "zipinfo {}", "source2": "zipinfo {}", "unified_diff": "@@ -1,8 +1,8 @@\n-Zip file size: 34350 bytes, number of entries: 36\n+Zip file size: 34477 bytes, number of entries: 36\n -rw-r--r--  2.0 unx       64 b- defN 20-Apr-01 08:04 META-INF/MANIFEST.MF\n drwxr-xr-x  2.0 unx        0 b- stor 20-Apr-01 08:04 META-INF/\n drwxr-xr-x  2.0 unx        0 b- stor 20-Apr-01 08:04 org/\n drwxr-xr-x  2.0 unx        0 b- stor 20-Apr-01 08:04 org/apache/\n drwxr-xr-x  2.0 unx        0 b- stor 20-Apr-01 08:04 org/apache/dubbo/\n drwxr-xr-x  2.0 unx        0 b- stor 20-Apr-01 08:04 org/apache/dubbo/remoting/\n drwxr-xr-x  2.0 unx        0 b- stor 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/\n@@ -13,26 +13,26 @@\n drwxr-xr-x  2.0 unx        0 b- stor 20-Apr-01 08:04 META-INF/dubbo/internal/\n drwxr-xr-x  2.0 unx        0 b- stor 20-Apr-01 08:04 META-INF/maven/\n drwxr-xr-x  2.0 unx        0 b- stor 20-Apr-01 08:04 META-INF/maven/org.apache.dubbo/\n drwxr-xr-x  2.0 unx        0 b- stor 20-Apr-01 08:04 META-INF/maven/org.apache.dubbo/dubbo-remoting-etcd3/\n -rw-r--r--  2.0 unx    10117 b- defN 20-Apr-01 08:04 META-INF/DEPENDENCIES\n -rw-r--r--  2.0 unx    11358 b- defN 20-Apr-01 08:04 META-INF/LICENSE\n -rw-r--r--  2.0 unx      177 b- defN 20-Apr-01 08:04 META-INF/NOTICE\n--rw-r--r--  2.0 unx     1578 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/AbstractRetryPolicy.java\n+-rw-r--r--  2.0 unx     1623 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/AbstractRetryPolicy.java\n -rw-r--r--  2.0 unx      988 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/ChildListener.java\n--rw-r--r--  2.0 unx     1737 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/Constants.java\n--rw-r--r--  2.0 unx     6379 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/EtcdClient.java\n--rw-r--r--  2.0 unx     1975 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/EtcdTransporter.java\n--rw-r--r--  2.0 unx     1243 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/RetryPolicy.java\n+-rw-r--r--  2.0 unx     1792 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/Constants.java\n+-rw-r--r--  2.0 unx     6570 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/EtcdClient.java\n+-rw-r--r--  2.0 unx     2022 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/EtcdTransporter.java\n+-rw-r--r--  2.0 unx     1274 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/RetryPolicy.java\n -rw-r--r--  2.0 unx      996 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/StateListener.java\n--rw-r--r--  2.0 unx     1132 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/jetcd/ConnectionStateListener.java\n--rw-r--r--  2.0 unx    16648 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/jetcd/JEtcdClient.java\n--rw-r--r--  2.0 unx    28360 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/jetcd/JEtcdClientWrapper.java\n--rw-r--r--  2.0 unx     1152 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/jetcd/JEtcdTransporter.java\n--rw-r--r--  2.0 unx     3433 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/jetcd/RetryLoops.java\n+-rw-r--r--  2.0 unx     1162 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/jetcd/ConnectionStateListener.java\n+-rw-r--r--  2.0 unx    17121 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/jetcd/JEtcdClient.java\n+-rw-r--r--  2.0 unx    29112 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/jetcd/JEtcdClientWrapper.java\n+-rw-r--r--  2.0 unx     1182 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/jetcd/JEtcdTransporter.java\n+-rw-r--r--  2.0 unx     3532 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/jetcd/RetryLoops.java\n -rw-r--r--  2.0 unx     1386 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/jetcd/RetryNTimes.java\n--rw-r--r--  2.0 unx     2923 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/option/OptionUtil.java\n--rw-r--r--  2.0 unx     7250 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/support/AbstractEtcdClient.java\n+-rw-r--r--  2.0 unx     3001 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/option/OptionUtil.java\n+-rw-r--r--  2.0 unx     7444 b- defN 20-Apr-01 08:04 org/apache/dubbo/remoting/etcd/support/AbstractEtcdClient.java\n -rw-r--r--  2.0 unx       59 b- defN 20-Apr-01 08:04 META-INF/dubbo/internal/org.apache.dubbo.remoting.etcd.EtcdTransporter\n--rw-r--r--  2.0 unx     3689 b- defN 20-Apr-01 08:04 META-INF/maven/org.apache.dubbo/dubbo-remoting-etcd3/pom.xml\n+-rw-r--r--  2.0 unx     3585 b- defN 20-Apr-01 08:04 META-INF/maven/org.apache.dubbo/dubbo-remoting-etcd3/pom.xml\n -rw-r--r--  2.0 unx       75 b- defN 20-Apr-01 08:04 META-INF/maven/org.apache.dubbo/dubbo-remoting-etcd3/pom.properties\n-36 files, 102719 bytes uncompressed, 28756 bytes compressed:  72.0%\n+36 files, 104640 bytes uncompressed, 28883 bytes compressed:  72.4%\n"}, {"source1": "zipdetails --redact --scan --utc {}", "source2": "zipdetails --redact --scan --utc {}", "unified_diff": "@@ -335,1486 +335,1486 @@\n 1BA5 Extract Zip Spec      14 (20) '2.0'\n 1BA6 Extract OS            00 (0) 'MS-DOS'\n 1BA7 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n 1BA9 Compression Method    0008 (8) 'Deflated'\n 1BAB Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-1BAF CRC                   36F8F065 (922284133)\n-1BB3 Compressed Size       000002DB (731)\n-1BB7 Uncompressed Size     0000062A (1578)\n+1BAF CRC                   2526A8CF (623290575)\n+1BB3 Compressed Size       000002E1 (737)\n+1BB7 Uncompressed Size     00000657 (1623)\n 1BBB Filename Length       0037 (55)\n 1BBD Extra Length          0000 (0)\n 1BBF Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n # WARNING: Offset 0x1BBF: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n 1BF6 PAYLOAD\n \n-1ED1 LOCAL HEADER #20      04034B50 (67324752)\n-1ED5 Extract Zip Spec      14 (20) '2.0'\n-1ED6 Extract OS            00 (0) 'MS-DOS'\n-1ED7 General Purpose Flag  0800 (2048)\n+1ED7 LOCAL HEADER #20      04034B50 (67324752)\n+1EDB Extract Zip Spec      14 (20) '2.0'\n+1EDC Extract OS            00 (0) 'MS-DOS'\n+1EDD General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-1ED9 Compression Method    0008 (8) 'Deflated'\n-1EDB Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-1EDF CRC                   CD8B51D1 (3448459729)\n-1EE3 Compressed Size       00000232 (562)\n-1EE7 Uncompressed Size     000003DC (988)\n-1EEB Filename Length       0031 (49)\n-1EED Extra Length          0000 (0)\n-1EEF Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+1EDF Compression Method    0008 (8) 'Deflated'\n+1EE1 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+1EE5 CRC                   CD8B51D1 (3448459729)\n+1EE9 Compressed Size       00000232 (562)\n+1EED Uncompressed Size     000003DC (988)\n+1EF1 Filename Length       0031 (49)\n+1EF3 Extra Length          0000 (0)\n+1EF5 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x1EEF: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x1EF5: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-1F20 PAYLOAD\n+1F26 PAYLOAD\n \n-2152 LOCAL HEADER #21      04034B50 (67324752)\n-2156 Extract Zip Spec      14 (20) '2.0'\n-2157 Extract OS            00 (0) 'MS-DOS'\n-2158 General Purpose Flag  0800 (2048)\n+2158 LOCAL HEADER #21      04034B50 (67324752)\n+215C Extract Zip Spec      14 (20) '2.0'\n+215D Extract OS            00 (0) 'MS-DOS'\n+215E General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-215A Compression Method    0008 (8) 'Deflated'\n-215C Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-2160 CRC                   123318DF (305338591)\n-2164 Compressed Size       0000032F (815)\n-2168 Uncompressed Size     000006C9 (1737)\n-216C Filename Length       002D (45)\n-216E Extra Length          0000 (0)\n-2170 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+2160 Compression Method    0008 (8) 'Deflated'\n+2162 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+2166 CRC                   322BAD20 (841723168)\n+216A Compressed Size       00000333 (819)\n+216E Uncompressed Size     00000700 (1792)\n+2172 Filename Length       002D (45)\n+2174 Extra Length          0000 (0)\n+2176 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x2170: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x2176: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-219D PAYLOAD\n+21A3 PAYLOAD\n \n-24CC LOCAL HEADER #22      04034B50 (67324752)\n-24D0 Extract Zip Spec      14 (20) '2.0'\n-24D1 Extract OS            00 (0) 'MS-DOS'\n-24D2 General Purpose Flag  0800 (2048)\n+24D6 LOCAL HEADER #22      04034B50 (67324752)\n+24DA Extract Zip Spec      14 (20) '2.0'\n+24DB Extract OS            00 (0) 'MS-DOS'\n+24DC General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-24D4 Compression Method    0008 (8) 'Deflated'\n-24D6 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-24DA CRC                   6B994ABC (1805208252)\n-24DE Compressed Size       00000650 (1616)\n-24E2 Uncompressed Size     000018EB (6379)\n-24E6 Filename Length       002E (46)\n-24E8 Extra Length          0000 (0)\n-24EA Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+24DE Compression Method    0008 (8) 'Deflated'\n+24E0 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+24E4 CRC                   9A56CC71 (2589379697)\n+24E8 Compressed Size       0000065D (1629)\n+24EC Uncompressed Size     000019AA (6570)\n+24F0 Filename Length       002E (46)\n+24F2 Extra Length          0000 (0)\n+24F4 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x24EA: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x24F4: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-2518 PAYLOAD\n+2522 PAYLOAD\n \n-2B68 LOCAL HEADER #23      04034B50 (67324752)\n-2B6C Extract Zip Spec      14 (20) '2.0'\n-2B6D Extract OS            00 (0) 'MS-DOS'\n-2B6E General Purpose Flag  0800 (2048)\n+2B7F LOCAL HEADER #23      04034B50 (67324752)\n+2B83 Extract Zip Spec      14 (20) '2.0'\n+2B84 Extract OS            00 (0) 'MS-DOS'\n+2B85 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-2B70 Compression Method    0008 (8) 'Deflated'\n-2B72 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-2B76 CRC                   387B0FF7 (947589111)\n-2B7A Compressed Size       0000027C (636)\n-2B7E Uncompressed Size     000007B7 (1975)\n-2B82 Filename Length       0033 (51)\n-2B84 Extra Length          0000 (0)\n-2B86 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+2B87 Compression Method    0008 (8) 'Deflated'\n+2B89 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+2B8D CRC                   BBB4B4AC (3149182124)\n+2B91 Compressed Size       00000285 (645)\n+2B95 Uncompressed Size     000007E6 (2022)\n+2B99 Filename Length       0033 (51)\n+2B9B Extra Length          0000 (0)\n+2B9D Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x2B86: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x2B9D: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-2BB9 PAYLOAD\n+2BD0 PAYLOAD\n \n-2E35 LOCAL HEADER #24      04034B50 (67324752)\n-2E39 Extract Zip Spec      14 (20) '2.0'\n-2E3A Extract OS            00 (0) 'MS-DOS'\n-2E3B General Purpose Flag  0800 (2048)\n+2E55 LOCAL HEADER #24      04034B50 (67324752)\n+2E59 Extract Zip Spec      14 (20) '2.0'\n+2E5A Extract OS            00 (0) 'MS-DOS'\n+2E5B General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-2E3D Compression Method    0008 (8) 'Deflated'\n-2E3F Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-2E43 CRC                   0F6205B4 (258082228)\n-2E47 Compressed Size       00000295 (661)\n-2E4B Uncompressed Size     000004DB (1243)\n-2E4F Filename Length       002F (47)\n-2E51 Extra Length          0000 (0)\n-2E53 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+2E5D Compression Method    0008 (8) 'Deflated'\n+2E5F Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+2E63 CRC                   302E6CD8 (808348888)\n+2E67 Compressed Size       0000029D (669)\n+2E6B Uncompressed Size     000004FA (1274)\n+2E6F Filename Length       002F (47)\n+2E71 Extra Length          0000 (0)\n+2E73 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x2E53: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x2E73: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-2E82 PAYLOAD\n+2EA2 PAYLOAD\n \n-3117 LOCAL HEADER #25      04034B50 (67324752)\n-311B Extract Zip Spec      14 (20) '2.0'\n-311C Extract OS            00 (0) 'MS-DOS'\n-311D General Purpose Flag  0800 (2048)\n+313F LOCAL HEADER #25      04034B50 (67324752)\n+3143 Extract Zip Spec      14 (20) '2.0'\n+3144 Extract OS            00 (0) 'MS-DOS'\n+3145 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-311F Compression Method    0008 (8) 'Deflated'\n-3121 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-3125 CRC                   6ADC9301 (1792840449)\n-3129 Compressed Size       0000022E (558)\n-312D Uncompressed Size     000003E4 (996)\n-3131 Filename Length       0031 (49)\n-3133 Extra Length          0000 (0)\n-3135 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+3147 Compression Method    0008 (8) 'Deflated'\n+3149 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+314D CRC                   6ADC9301 (1792840449)\n+3151 Compressed Size       0000022E (558)\n+3155 Uncompressed Size     000003E4 (996)\n+3159 Filename Length       0031 (49)\n+315B Extra Length          0000 (0)\n+315D Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x3135: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x315D: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-3166 PAYLOAD\n+318E PAYLOAD\n \n-3394 LOCAL HEADER #26      04034B50 (67324752)\n-3398 Extract Zip Spec      14 (20) '2.0'\n-3399 Extract OS            00 (0) 'MS-DOS'\n-339A General Purpose Flag  0800 (2048)\n+33BC LOCAL HEADER #26      04034B50 (67324752)\n+33C0 Extract Zip Spec      14 (20) '2.0'\n+33C1 Extract OS            00 (0) 'MS-DOS'\n+33C2 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-339C Compression Method    0008 (8) 'Deflated'\n-339E Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-33A2 CRC                   3F422686 (1061299846)\n-33A6 Compressed Size       00000266 (614)\n-33AA Uncompressed Size     0000046C (1132)\n-33AE Filename Length       0041 (65)\n-33B0 Extra Length          0000 (0)\n-33B2 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+33C4 Compression Method    0008 (8) 'Deflated'\n+33C6 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+33CA CRC                   F69577E7 (4136990695)\n+33CE Compressed Size       0000026D (621)\n+33D2 Uncompressed Size     0000048A (1162)\n+33D6 Filename Length       0041 (65)\n+33D8 Extra Length          0000 (0)\n+33DA Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x33B2: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x33DA: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-33F3 PAYLOAD\n+341B PAYLOAD\n \n-3659 LOCAL HEADER #27      04034B50 (67324752)\n-365D Extract Zip Spec      14 (20) '2.0'\n-365E Extract OS            00 (0) 'MS-DOS'\n-365F General Purpose Flag  0800 (2048)\n+3688 LOCAL HEADER #27      04034B50 (67324752)\n+368C Extract Zip Spec      14 (20) '2.0'\n+368D Extract OS            00 (0) 'MS-DOS'\n+368E General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-3661 Compression Method    0008 (8) 'Deflated'\n-3663 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-3667 CRC                   A75036DE (2807051998)\n-366B Compressed Size       00000F72 (3954)\n-366F Uncompressed Size     00004108 (16648)\n-3673 Filename Length       0035 (53)\n-3675 Extra Length          0000 (0)\n-3677 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+3690 Compression Method    0008 (8) 'Deflated'\n+3692 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+3696 CRC                   93092688 (2466850440)\n+369A Compressed Size       00000F85 (3973)\n+369E Uncompressed Size     000042E1 (17121)\n+36A2 Filename Length       0035 (53)\n+36A4 Extra Length          0000 (0)\n+36A6 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x3677: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x36A6: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-36AC PAYLOAD\n+36DB PAYLOAD\n \n-461E LOCAL HEADER #28      04034B50 (67324752)\n-4622 Extract Zip Spec      14 (20) '2.0'\n-4623 Extract OS            00 (0) 'MS-DOS'\n-4624 General Purpose Flag  0800 (2048)\n+4660 LOCAL HEADER #28      04034B50 (67324752)\n+4664 Extract Zip Spec      14 (20) '2.0'\n+4665 Extract OS            00 (0) 'MS-DOS'\n+4666 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-4626 Compression Method    0008 (8) 'Deflated'\n-4628 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-462C CRC                   F1F2D150 (4059222352)\n-4630 Compressed Size       00001721 (5921)\n-4634 Uncompressed Size     00006EC8 (28360)\n-4638 Filename Length       003C (60)\n-463A Extra Length          0000 (0)\n-463C Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+4668 Compression Method    0008 (8) 'Deflated'\n+466A Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+466E CRC                   29CC663D (701261373)\n+4672 Compressed Size       0000173E (5950)\n+4676 Uncompressed Size     000071B8 (29112)\n+467A Filename Length       003C (60)\n+467C Extra Length          0000 (0)\n+467E Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x463C: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x467E: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-4678 PAYLOAD\n+46BA PAYLOAD\n \n-5D99 LOCAL HEADER #29      04034B50 (67324752)\n-5D9D Extract Zip Spec      14 (20) '2.0'\n-5D9E Extract OS            00 (0) 'MS-DOS'\n-5D9F General Purpose Flag  0800 (2048)\n+5DF8 LOCAL HEADER #29      04034B50 (67324752)\n+5DFC Extract Zip Spec      14 (20) '2.0'\n+5DFD Extract OS            00 (0) 'MS-DOS'\n+5DFE General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-5DA1 Compression Method    0008 (8) 'Deflated'\n-5DA3 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-5DA7 CRC                   F823DAB1 (4163099313)\n-5DAB Compressed Size       00000253 (595)\n-5DAF Uncompressed Size     00000480 (1152)\n-5DB3 Filename Length       003A (58)\n-5DB5 Extra Length          0000 (0)\n-5DB7 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+5E00 Compression Method    0008 (8) 'Deflated'\n+5E02 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+5E06 CRC                   11BF3CA1 (297745569)\n+5E0A Compressed Size       00000258 (600)\n+5E0E Uncompressed Size     0000049E (1182)\n+5E12 Filename Length       003A (58)\n+5E14 Extra Length          0000 (0)\n+5E16 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x5DB7: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x5E16: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-5DF1 PAYLOAD\n+5E50 PAYLOAD\n \n-6044 LOCAL HEADER #30      04034B50 (67324752)\n-6048 Extract Zip Spec      14 (20) '2.0'\n-6049 Extract OS            00 (0) 'MS-DOS'\n-604A General Purpose Flag  0800 (2048)\n+60A8 LOCAL HEADER #30      04034B50 (67324752)\n+60AC Extract Zip Spec      14 (20) '2.0'\n+60AD Extract OS            00 (0) 'MS-DOS'\n+60AE General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-604C Compression Method    0008 (8) 'Deflated'\n-604E Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-6052 CRC                   0B4932D9 (189346521)\n-6056 Compressed Size       00000430 (1072)\n-605A Uncompressed Size     00000D69 (3433)\n-605E Filename Length       0034 (52)\n-6060 Extra Length          0000 (0)\n-6062 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+60B0 Compression Method    0008 (8) 'Deflated'\n+60B2 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+60B6 CRC                   8B7AC527 (2340078887)\n+60BA Compressed Size       00000439 (1081)\n+60BE Uncompressed Size     00000DCC (3532)\n+60C2 Filename Length       0034 (52)\n+60C4 Extra Length          0000 (0)\n+60C6 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x6062: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x60C6: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-6096 PAYLOAD\n+60FA PAYLOAD\n \n-64C6 LOCAL HEADER #31      04034B50 (67324752)\n-64CA Extract Zip Spec      14 (20) '2.0'\n-64CB Extract OS            00 (0) 'MS-DOS'\n-64CC General Purpose Flag  0800 (2048)\n+6533 LOCAL HEADER #31      04034B50 (67324752)\n+6537 Extract Zip Spec      14 (20) '2.0'\n+6538 Extract OS            00 (0) 'MS-DOS'\n+6539 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-64CE Compression Method    0008 (8) 'Deflated'\n-64D0 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-64D4 CRC                   117709A7 (293013927)\n-64D8 Compressed Size       000002BF (703)\n-64DC Uncompressed Size     0000056A (1386)\n-64E0 Filename Length       0035 (53)\n-64E2 Extra Length          0000 (0)\n-64E4 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+653B Compression Method    0008 (8) 'Deflated'\n+653D Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+6541 CRC                   117709A7 (293013927)\n+6545 Compressed Size       000002BF (703)\n+6549 Uncompressed Size     0000056A (1386)\n+654D Filename Length       0035 (53)\n+654F Extra Length          0000 (0)\n+6551 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x64E4: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x6551: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-6519 PAYLOAD\n+6586 PAYLOAD\n \n-67D8 LOCAL HEADER #32      04034B50 (67324752)\n-67DC Extract Zip Spec      14 (20) '2.0'\n-67DD Extract OS            00 (0) 'MS-DOS'\n-67DE General Purpose Flag  0800 (2048)\n+6845 LOCAL HEADER #32      04034B50 (67324752)\n+6849 Extract Zip Spec      14 (20) '2.0'\n+684A Extract OS            00 (0) 'MS-DOS'\n+684B General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-67E0 Compression Method    0008 (8) 'Deflated'\n-67E2 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-67E6 CRC                   35D495FB (903124475)\n-67EA Compressed Size       000004DC (1244)\n-67EE Uncompressed Size     00000B6B (2923)\n-67F2 Filename Length       0035 (53)\n-67F4 Extra Length          0000 (0)\n-67F6 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+684D Compression Method    0008 (8) 'Deflated'\n+684F Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+6853 CRC                   A1B16DDC (2712759772)\n+6857 Compressed Size       000004E7 (1255)\n+685B Uncompressed Size     00000BB9 (3001)\n+685F Filename Length       0035 (53)\n+6861 Extra Length          0000 (0)\n+6863 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x67F6: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x6863: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-682B PAYLOAD\n+6898 PAYLOAD\n \n-6D07 LOCAL HEADER #33      04034B50 (67324752)\n-6D0B Extract Zip Spec      14 (20) '2.0'\n-6D0C Extract OS            00 (0) 'MS-DOS'\n-6D0D General Purpose Flag  0800 (2048)\n+6D7F LOCAL HEADER #33      04034B50 (67324752)\n+6D83 Extract Zip Spec      14 (20) '2.0'\n+6D84 Extract OS            00 (0) 'MS-DOS'\n+6D85 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-6D0F Compression Method    0008 (8) 'Deflated'\n-6D11 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-6D15 CRC                   2FB39AE6 (800299750)\n-6D19 Compressed Size       000006C0 (1728)\n-6D1D Uncompressed Size     00001C52 (7250)\n-6D21 Filename Length       003E (62)\n-6D23 Extra Length          0000 (0)\n-6D25 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+6D87 Compression Method    0008 (8) 'Deflated'\n+6D89 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+6D8D CRC                   43B8CAA4 (1136183972)\n+6D91 Compressed Size       000006CC (1740)\n+6D95 Uncompressed Size     00001D14 (7444)\n+6D99 Filename Length       003E (62)\n+6D9B Extra Length          0000 (0)\n+6D9D Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x6D25: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x6D9D: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-6D63 PAYLOAD\n+6DDB PAYLOAD\n \n-7423 LOCAL HEADER #34      04034B50 (67324752)\n-7427 Extract Zip Spec      14 (20) '2.0'\n-7428 Extract OS            00 (0) 'MS-DOS'\n-7429 General Purpose Flag  0800 (2048)\n+74A7 LOCAL HEADER #34      04034B50 (67324752)\n+74AB Extract Zip Spec      14 (20) '2.0'\n+74AC Extract OS            00 (0) 'MS-DOS'\n+74AD General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-742B Compression Method    0008 (8) 'Deflated'\n-742D Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-7431 CRC                   91BA560C (2444908044)\n-7435 Compressed Size       00000036 (54)\n-7439 Uncompressed Size     0000003B (59)\n-743D Filename Length       0046 (70)\n-743F Extra Length          0000 (0)\n-7441 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+74AF Compression Method    0008 (8) 'Deflated'\n+74B1 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+74B5 CRC                   91BA560C (2444908044)\n+74B9 Compressed Size       00000036 (54)\n+74BD Uncompressed Size     0000003B (59)\n+74C1 Filename Length       0046 (70)\n+74C3 Extra Length          0000 (0)\n+74C5 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x7441: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x74C5: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-7487 PAYLOAD               XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n+750B PAYLOAD               XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n \n-74BD LOCAL HEADER #35      04034B50 (67324752)\n-74C1 Extract Zip Spec      14 (20) '2.0'\n-74C2 Extract OS            00 (0) 'MS-DOS'\n-74C3 General Purpose Flag  0800 (2048)\n+7541 LOCAL HEADER #35      04034B50 (67324752)\n+7545 Extract Zip Spec      14 (20) '2.0'\n+7546 Extract OS            00 (0) 'MS-DOS'\n+7547 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-74C5 Compression Method    0008 (8) 'Deflated'\n-74C7 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-74CB CRC                   FACEEC94 (4207864980)\n-74CF Compressed Size       00000455 (1109)\n-74D3 Uncompressed Size     00000E69 (3689)\n-74D7 Filename Length       003C (60)\n-74D9 Extra Length          0000 (0)\n-74DB Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+7549 Compression Method    0008 (8) 'Deflated'\n+754B Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+754F CRC                   DB79C8F6 (3682191606)\n+7553 Compressed Size       00000450 (1104)\n+7557 Uncompressed Size     00000E01 (3585)\n+755B Filename Length       003C (60)\n+755D Extra Length          0000 (0)\n+755F Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x74DB: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x755F: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-7517 PAYLOAD\n+759B PAYLOAD\n \n-796C LOCAL HEADER #36      04034B50 (67324752)\n-7970 Extract Zip Spec      14 (20) '2.0'\n-7971 Extract OS            00 (0) 'MS-DOS'\n-7972 General Purpose Flag  0800 (2048)\n+79EB LOCAL HEADER #36      04034B50 (67324752)\n+79EF Extract Zip Spec      14 (20) '2.0'\n+79F0 Extract OS            00 (0) 'MS-DOS'\n+79F1 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-7974 Compression Method    0008 (8) 'Deflated'\n-7976 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-797A CRC                   D4B7125F (3568767583)\n-797E Compressed Size       00000049 (73)\n-7982 Uncompressed Size     0000004B (75)\n-7986 Filename Length       0043 (67)\n-7988 Extra Length          0000 (0)\n-798A Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+79F3 Compression Method    0008 (8) 'Deflated'\n+79F5 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+79F9 CRC                   D4B7125F (3568767583)\n+79FD Compressed Size       00000049 (73)\n+7A01 Uncompressed Size     0000004B (75)\n+7A05 Filename Length       0043 (67)\n+7A07 Extra Length          0000 (0)\n+7A09 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x798A: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7A09: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-79CD PAYLOAD               XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n+7A4C PAYLOAD               XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n \n-7A16 CENTRAL HEADER #1     02014B50 (33639248)\n-7A1A Created Zip Spec      14 (20) '2.0'\n-7A1B Created OS            03 (3) 'Unix'\n-7A1C Extract Zip Spec      14 (20) '2.0'\n-7A1D Extract OS            00 (0) 'MS-DOS'\n-7A1E General Purpose Flag  0800 (2048)\n+7A95 CENTRAL HEADER #1     02014B50 (33639248)\n+7A99 Created Zip Spec      14 (20) '2.0'\n+7A9A Created OS            03 (3) 'Unix'\n+7A9B Extract Zip Spec      14 (20) '2.0'\n+7A9C Extract OS            00 (0) 'MS-DOS'\n+7A9D General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-7A20 Compression Method    0008 (8) 'Deflated'\n-7A22 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-7A26 CRC                   A689EB18 (2794056472)\n-7A2A Compressed Size       00000042 (66)\n-7A2E Uncompressed Size     00000040 (64)\n-7A32 Filename Length       0014 (20)\n-7A34 Extra Length          0000 (0)\n-7A36 Comment Length        0000 (0)\n-7A38 Disk Start            0000 (0)\n-7A3A Int File Attributes   0000 (0)\n+7A9F Compression Method    0008 (8) 'Deflated'\n+7AA1 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+7AA5 CRC                   A689EB18 (2794056472)\n+7AA9 Compressed Size       00000042 (66)\n+7AAD Uncompressed Size     00000040 (64)\n+7AB1 Filename Length       0014 (20)\n+7AB3 Extra Length          0000 (0)\n+7AB5 Comment Length        0000 (0)\n+7AB7 Disk Start            0000 (0)\n+7AB9 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-7A3C Ext File Attributes   81A40000 (2175008768)\n+7ABB Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-7A40 Local Header Offset   00000000 (0)\n-7A44 Filename              'XXXXXXXXXXXXXXXXXXXX'\n+7ABF Local Header Offset   00000000 (0)\n+7AC3 Filename              'XXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x7A44: Filename 'XXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7AC3: Filename 'XXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-7A58 CENTRAL HEADER #2     02014B50 (33639248)\n-7A5C Created Zip Spec      14 (20) '2.0'\n-7A5D Created OS            03 (3) 'Unix'\n-7A5E Extract Zip Spec      0A (10) '1.0'\n-7A5F Extract OS            00 (0) 'MS-DOS'\n-7A60 General Purpose Flag  0800 (2048)\n+7AD7 CENTRAL HEADER #2     02014B50 (33639248)\n+7ADB Created Zip Spec      14 (20) '2.0'\n+7ADC Created OS            03 (3) 'Unix'\n+7ADD Extract Zip Spec      0A (10) '1.0'\n+7ADE Extract OS            00 (0) 'MS-DOS'\n+7ADF General Purpose Flag  0800 (2048)\n      [Bit 11]              1 'Language Encoding'\n-7A62 Compression Method    0000 (0) 'Stored'\n-7A64 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-7A68 CRC                   00000000 (0)\n-7A6C Compressed Size       00000000 (0)\n-7A70 Uncompressed Size     00000000 (0)\n-7A74 Filename Length       0009 (9)\n-7A76 Extra Length          0000 (0)\n-7A78 Comment Length        0000 (0)\n-7A7A Disk Start            0000 (0)\n-7A7C Int File Attributes   0000 (0)\n+7AE1 Compression Method    0000 (0) 'Stored'\n+7AE3 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+7AE7 CRC                   00000000 (0)\n+7AEB Compressed Size       00000000 (0)\n+7AEF Uncompressed Size     00000000 (0)\n+7AF3 Filename Length       0009 (9)\n+7AF5 Extra Length          0000 (0)\n+7AF7 Comment Length        0000 (0)\n+7AF9 Disk Start            0000 (0)\n+7AFB Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-7A7E Ext File Attributes   41ED0010 (1106051088)\n+7AFD Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-7A82 Local Header Offset   00000074 (116)\n-7A86 Filename              'XXXXXXXXX'\n+7B01 Local Header Offset   00000074 (116)\n+7B05 Filename              'XXXXXXXXX'\n #\n-# WARNING: Offset 0x7A86: Filename 'XXXXXXXXX'\n+# WARNING: Offset 0x7B05: Filename 'XXXXXXXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0x7A86: Directory 'XXXXXXXXX' must end in a '/'\n+# ERROR: Offset 0x7B05: Directory 'XXXXXXXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0x7A5E: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXX'\n+# WARNING: Offset 0x7ADD: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXX'\n #\n \n-7A8F CENTRAL HEADER #3     02014B50 (33639248)\n-7A93 Created Zip Spec      14 (20) '2.0'\n-7A94 Created OS            03 (3) 'Unix'\n-7A95 Extract Zip Spec      0A (10) '1.0'\n-7A96 Extract OS            00 (0) 'MS-DOS'\n-7A97 General Purpose Flag  0800 (2048)\n-     [Bit 11]              1 'Language Encoding'\n-7A99 Compression Method    0000 (0) 'Stored'\n-7A9B Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-7A9F CRC                   00000000 (0)\n-7AA3 Compressed Size       00000000 (0)\n-7AA7 Uncompressed Size     00000000 (0)\n-7AAB Filename Length       0004 (4)\n-7AAD Extra Length          0000 (0)\n-7AAF Comment Length        0000 (0)\n-7AB1 Disk Start            0000 (0)\n-7AB3 Int File Attributes   0000 (0)\n+7B0E CENTRAL HEADER #3     02014B50 (33639248)\n+7B12 Created Zip Spec      14 (20) '2.0'\n+7B13 Created OS            03 (3) 'Unix'\n+7B14 Extract Zip Spec      0A (10) '1.0'\n+7B15 Extract OS            00 (0) 'MS-DOS'\n+7B16 General Purpose Flag  0800 (2048)\n+     [Bit 11]              1 'Language Encoding'\n+7B18 Compression Method    0000 (0) 'Stored'\n+7B1A Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+7B1E CRC                   00000000 (0)\n+7B22 Compressed Size       00000000 (0)\n+7B26 Uncompressed Size     00000000 (0)\n+7B2A Filename Length       0004 (4)\n+7B2C Extra Length          0000 (0)\n+7B2E Comment Length        0000 (0)\n+7B30 Disk Start            0000 (0)\n+7B32 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-7AB5 Ext File Attributes   41ED0010 (1106051088)\n+7B34 Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-7AB9 Local Header Offset   0000009B (155)\n-7ABD Filename              'XXXX'\n+7B38 Local Header Offset   0000009B (155)\n+7B3C Filename              'XXXX'\n #\n-# WARNING: Offset 0x7ABD: Filename 'XXXX'\n+# WARNING: Offset 0x7B3C: Filename 'XXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0x7ABD: Directory 'XXXX' must end in a '/'\n+# ERROR: Offset 0x7B3C: Directory 'XXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0x7A95: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXX'\n+# WARNING: Offset 0x7B14: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXX'\n #\n \n-7AC1 CENTRAL HEADER #4     02014B50 (33639248)\n-7AC5 Created Zip Spec      14 (20) '2.0'\n-7AC6 Created OS            03 (3) 'Unix'\n-7AC7 Extract Zip Spec      0A (10) '1.0'\n-7AC8 Extract OS            00 (0) 'MS-DOS'\n-7AC9 General Purpose Flag  0800 (2048)\n-     [Bit 11]              1 'Language Encoding'\n-7ACB Compression Method    0000 (0) 'Stored'\n-7ACD Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-7AD1 CRC                   00000000 (0)\n-7AD5 Compressed Size       00000000 (0)\n-7AD9 Uncompressed Size     00000000 (0)\n-7ADD Filename Length       000B (11)\n-7ADF Extra Length          0000 (0)\n-7AE1 Comment Length        0000 (0)\n-7AE3 Disk Start            0000 (0)\n-7AE5 Int File Attributes   0000 (0)\n+7B40 CENTRAL HEADER #4     02014B50 (33639248)\n+7B44 Created Zip Spec      14 (20) '2.0'\n+7B45 Created OS            03 (3) 'Unix'\n+7B46 Extract Zip Spec      0A (10) '1.0'\n+7B47 Extract OS            00 (0) 'MS-DOS'\n+7B48 General Purpose Flag  0800 (2048)\n+     [Bit 11]              1 'Language Encoding'\n+7B4A Compression Method    0000 (0) 'Stored'\n+7B4C Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+7B50 CRC                   00000000 (0)\n+7B54 Compressed Size       00000000 (0)\n+7B58 Uncompressed Size     00000000 (0)\n+7B5C Filename Length       000B (11)\n+7B5E Extra Length          0000 (0)\n+7B60 Comment Length        0000 (0)\n+7B62 Disk Start            0000 (0)\n+7B64 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-7AE7 Ext File Attributes   41ED0010 (1106051088)\n+7B66 Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-7AEB Local Header Offset   000000BD (189)\n-7AEF Filename              'XXXXXXXXXXX'\n+7B6A Local Header Offset   000000BD (189)\n+7B6E Filename              'XXXXXXXXXXX'\n #\n-# WARNING: Offset 0x7AEF: Filename 'XXXXXXXXXXX'\n+# WARNING: Offset 0x7B6E: Filename 'XXXXXXXXXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0x7AEF: Directory 'XXXXXXXXXXX' must end in a '/'\n+# ERROR: Offset 0x7B6E: Directory 'XXXXXXXXXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0x7AC7: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXX'\n+# WARNING: Offset 0x7B46: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXX'\n #\n \n-7AFA CENTRAL HEADER #5     02014B50 (33639248)\n-7AFE Created Zip Spec      14 (20) '2.0'\n-7AFF Created OS            03 (3) 'Unix'\n-7B00 Extract Zip Spec      0A (10) '1.0'\n-7B01 Extract OS            00 (0) 'MS-DOS'\n-7B02 General Purpose Flag  0800 (2048)\n-     [Bit 11]              1 'Language Encoding'\n-7B04 Compression Method    0000 (0) 'Stored'\n-7B06 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-7B0A CRC                   00000000 (0)\n-7B0E Compressed Size       00000000 (0)\n-7B12 Uncompressed Size     00000000 (0)\n-7B16 Filename Length       0011 (17)\n-7B18 Extra Length          0000 (0)\n-7B1A Comment Length        0000 (0)\n-7B1C Disk Start            0000 (0)\n-7B1E Int File Attributes   0000 (0)\n+7B79 CENTRAL HEADER #5     02014B50 (33639248)\n+7B7D Created Zip Spec      14 (20) '2.0'\n+7B7E Created OS            03 (3) 'Unix'\n+7B7F Extract Zip Spec      0A (10) '1.0'\n+7B80 Extract OS            00 (0) 'MS-DOS'\n+7B81 General Purpose Flag  0800 (2048)\n+     [Bit 11]              1 'Language Encoding'\n+7B83 Compression Method    0000 (0) 'Stored'\n+7B85 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+7B89 CRC                   00000000 (0)\n+7B8D Compressed Size       00000000 (0)\n+7B91 Uncompressed Size     00000000 (0)\n+7B95 Filename Length       0011 (17)\n+7B97 Extra Length          0000 (0)\n+7B99 Comment Length        0000 (0)\n+7B9B Disk Start            0000 (0)\n+7B9D Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-7B20 Ext File Attributes   41ED0010 (1106051088)\n+7B9F Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-7B24 Local Header Offset   000000E6 (230)\n-7B28 Filename              'XXXXXXXXXXXXXXXXX'\n+7BA3 Local Header Offset   000000E6 (230)\n+7BA7 Filename              'XXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x7B28: Filename 'XXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7BA7: Filename 'XXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0x7B28: Directory 'XXXXXXXXXXXXXXXXX' must end in a '/'\n+# ERROR: Offset 0x7BA7: Directory 'XXXXXXXXXXXXXXXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0x7B00: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7B7F: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXX'\n #\n \n-7B39 CENTRAL HEADER #6     02014B50 (33639248)\n-7B3D Created Zip Spec      14 (20) '2.0'\n-7B3E Created OS            03 (3) 'Unix'\n-7B3F Extract Zip Spec      0A (10) '1.0'\n-7B40 Extract OS            00 (0) 'MS-DOS'\n-7B41 General Purpose Flag  0800 (2048)\n-     [Bit 11]              1 'Language Encoding'\n-7B43 Compression Method    0000 (0) 'Stored'\n-7B45 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-7B49 CRC                   00000000 (0)\n-7B4D Compressed Size       00000000 (0)\n-7B51 Uncompressed Size     00000000 (0)\n-7B55 Filename Length       001A (26)\n-7B57 Extra Length          0000 (0)\n-7B59 Comment Length        0000 (0)\n-7B5B Disk Start            0000 (0)\n-7B5D Int File Attributes   0000 (0)\n+7BB8 CENTRAL HEADER #6     02014B50 (33639248)\n+7BBC Created Zip Spec      14 (20) '2.0'\n+7BBD Created OS            03 (3) 'Unix'\n+7BBE Extract Zip Spec      0A (10) '1.0'\n+7BBF Extract OS            00 (0) 'MS-DOS'\n+7BC0 General Purpose Flag  0800 (2048)\n+     [Bit 11]              1 'Language Encoding'\n+7BC2 Compression Method    0000 (0) 'Stored'\n+7BC4 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+7BC8 CRC                   00000000 (0)\n+7BCC Compressed Size       00000000 (0)\n+7BD0 Uncompressed Size     00000000 (0)\n+7BD4 Filename Length       001A (26)\n+7BD6 Extra Length          0000 (0)\n+7BD8 Comment Length        0000 (0)\n+7BDA Disk Start            0000 (0)\n+7BDC Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-7B5F Ext File Attributes   41ED0010 (1106051088)\n+7BDE Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-7B63 Local Header Offset   00000115 (277)\n-7B67 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXX'\n+7BE2 Local Header Offset   00000115 (277)\n+7BE6 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x7B67: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7BE6: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0x7B67: Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n+# ERROR: Offset 0x7BE6: Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0x7B3F: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7BBE: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n \n-7B81 CENTRAL HEADER #7     02014B50 (33639248)\n-7B85 Created Zip Spec      14 (20) '2.0'\n-7B86 Created OS            03 (3) 'Unix'\n-7B87 Extract Zip Spec      0A (10) '1.0'\n-7B88 Extract OS            00 (0) 'MS-DOS'\n-7B89 General Purpose Flag  0800 (2048)\n-     [Bit 11]              1 'Language Encoding'\n-7B8B Compression Method    0000 (0) 'Stored'\n-7B8D Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-7B91 CRC                   00000000 (0)\n-7B95 Compressed Size       00000000 (0)\n-7B99 Uncompressed Size     00000000 (0)\n-7B9D Filename Length       001F (31)\n-7B9F Extra Length          0000 (0)\n-7BA1 Comment Length        0000 (0)\n-7BA3 Disk Start            0000 (0)\n-7BA5 Int File Attributes   0000 (0)\n+7C00 CENTRAL HEADER #7     02014B50 (33639248)\n+7C04 Created Zip Spec      14 (20) '2.0'\n+7C05 Created OS            03 (3) 'Unix'\n+7C06 Extract Zip Spec      0A (10) '1.0'\n+7C07 Extract OS            00 (0) 'MS-DOS'\n+7C08 General Purpose Flag  0800 (2048)\n+     [Bit 11]              1 'Language Encoding'\n+7C0A Compression Method    0000 (0) 'Stored'\n+7C0C Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+7C10 CRC                   00000000 (0)\n+7C14 Compressed Size       00000000 (0)\n+7C18 Uncompressed Size     00000000 (0)\n+7C1C Filename Length       001F (31)\n+7C1E Extra Length          0000 (0)\n+7C20 Comment Length        0000 (0)\n+7C22 Disk Start            0000 (0)\n+7C24 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-7BA7 Ext File Attributes   41ED0010 (1106051088)\n+7C26 Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-7BAB Local Header Offset   0000014D (333)\n-7BAF Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+7C2A Local Header Offset   0000014D (333)\n+7C2E Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x7BAF: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7C2E: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0x7BAF: Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n+# ERROR: Offset 0x7C2E: Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0x7B87: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7C06: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n \n-7BCE CENTRAL HEADER #8     02014B50 (33639248)\n-7BD2 Created Zip Spec      14 (20) '2.0'\n-7BD3 Created OS            03 (3) 'Unix'\n-7BD4 Extract Zip Spec      0A (10) '1.0'\n-7BD5 Extract OS            00 (0) 'MS-DOS'\n-7BD6 General Purpose Flag  0800 (2048)\n-     [Bit 11]              1 'Language Encoding'\n-7BD8 Compression Method    0000 (0) 'Stored'\n-7BDA Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-7BDE CRC                   00000000 (0)\n-7BE2 Compressed Size       00000000 (0)\n-7BE6 Uncompressed Size     00000000 (0)\n-7BEA Filename Length       0025 (37)\n-7BEC Extra Length          0000 (0)\n-7BEE Comment Length        0000 (0)\n-7BF0 Disk Start            0000 (0)\n-7BF2 Int File Attributes   0000 (0)\n+7C4D CENTRAL HEADER #8     02014B50 (33639248)\n+7C51 Created Zip Spec      14 (20) '2.0'\n+7C52 Created OS            03 (3) 'Unix'\n+7C53 Extract Zip Spec      0A (10) '1.0'\n+7C54 Extract OS            00 (0) 'MS-DOS'\n+7C55 General Purpose Flag  0800 (2048)\n+     [Bit 11]              1 'Language Encoding'\n+7C57 Compression Method    0000 (0) 'Stored'\n+7C59 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+7C5D CRC                   00000000 (0)\n+7C61 Compressed Size       00000000 (0)\n+7C65 Uncompressed Size     00000000 (0)\n+7C69 Filename Length       0025 (37)\n+7C6B Extra Length          0000 (0)\n+7C6D Comment Length        0000 (0)\n+7C6F Disk Start            0000 (0)\n+7C71 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-7BF4 Ext File Attributes   41ED0010 (1106051088)\n+7C73 Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-7BF8 Local Header Offset   0000018A (394)\n-7BFC Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+7C77 Local Header Offset   0000018A (394)\n+7C7B Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x7BFC: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7C7B: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0x7BFC: Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n+# ERROR: Offset 0x7C7B: Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0x7BD4: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7C53: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n \n-7C21 CENTRAL HEADER #9     02014B50 (33639248)\n-7C25 Created Zip Spec      14 (20) '2.0'\n-7C26 Created OS            03 (3) 'Unix'\n-7C27 Extract Zip Spec      0A (10) '1.0'\n-7C28 Extract OS            00 (0) 'MS-DOS'\n-7C29 General Purpose Flag  0800 (2048)\n-     [Bit 11]              1 'Language Encoding'\n-7C2B Compression Method    0000 (0) 'Stored'\n-7C2D Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-7C31 CRC                   00000000 (0)\n-7C35 Compressed Size       00000000 (0)\n-7C39 Uncompressed Size     00000000 (0)\n-7C3D Filename Length       0026 (38)\n-7C3F Extra Length          0000 (0)\n-7C41 Comment Length        0000 (0)\n-7C43 Disk Start            0000 (0)\n-7C45 Int File Attributes   0000 (0)\n+7CA0 CENTRAL HEADER #9     02014B50 (33639248)\n+7CA4 Created Zip Spec      14 (20) '2.0'\n+7CA5 Created OS            03 (3) 'Unix'\n+7CA6 Extract Zip Spec      0A (10) '1.0'\n+7CA7 Extract OS            00 (0) 'MS-DOS'\n+7CA8 General Purpose Flag  0800 (2048)\n+     [Bit 11]              1 'Language Encoding'\n+7CAA Compression Method    0000 (0) 'Stored'\n+7CAC Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+7CB0 CRC                   00000000 (0)\n+7CB4 Compressed Size       00000000 (0)\n+7CB8 Uncompressed Size     00000000 (0)\n+7CBC Filename Length       0026 (38)\n+7CBE Extra Length          0000 (0)\n+7CC0 Comment Length        0000 (0)\n+7CC2 Disk Start            0000 (0)\n+7CC4 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-7C47 Ext File Attributes   41ED0010 (1106051088)\n+7CC6 Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-7C4B Local Header Offset   000001CD (461)\n-7C4F Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+7CCA Local Header Offset   000001CD (461)\n+7CCE Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x7C4F: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7CCE: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0x7C4F: Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n+# ERROR: Offset 0x7CCE: Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0x7C27: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7CA6: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n \n-7C75 CENTRAL HEADER #10    02014B50 (33639248)\n-7C79 Created Zip Spec      14 (20) '2.0'\n-7C7A Created OS            03 (3) 'Unix'\n-7C7B Extract Zip Spec      0A (10) '1.0'\n-7C7C Extract OS            00 (0) 'MS-DOS'\n-7C7D General Purpose Flag  0800 (2048)\n-     [Bit 11]              1 'Language Encoding'\n-7C7F Compression Method    0000 (0) 'Stored'\n-7C81 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-7C85 CRC                   00000000 (0)\n-7C89 Compressed Size       00000000 (0)\n-7C8D Uncompressed Size     00000000 (0)\n-7C91 Filename Length       0027 (39)\n-7C93 Extra Length          0000 (0)\n-7C95 Comment Length        0000 (0)\n-7C97 Disk Start            0000 (0)\n-7C99 Int File Attributes   0000 (0)\n+7CF4 CENTRAL HEADER #10    02014B50 (33639248)\n+7CF8 Created Zip Spec      14 (20) '2.0'\n+7CF9 Created OS            03 (3) 'Unix'\n+7CFA Extract Zip Spec      0A (10) '1.0'\n+7CFB Extract OS            00 (0) 'MS-DOS'\n+7CFC General Purpose Flag  0800 (2048)\n+     [Bit 11]              1 'Language Encoding'\n+7CFE Compression Method    0000 (0) 'Stored'\n+7D00 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+7D04 CRC                   00000000 (0)\n+7D08 Compressed Size       00000000 (0)\n+7D0C Uncompressed Size     00000000 (0)\n+7D10 Filename Length       0027 (39)\n+7D12 Extra Length          0000 (0)\n+7D14 Comment Length        0000 (0)\n+7D16 Disk Start            0000 (0)\n+7D18 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-7C9B Ext File Attributes   41ED0010 (1106051088)\n+7D1A Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-7C9F Local Header Offset   00000211 (529)\n-7CA3 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+7D1E Local Header Offset   00000211 (529)\n+7D22 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x7CA3: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7D22: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0x7CA3: Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n+# ERROR: Offset 0x7D22: Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0x7C7B: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7CFA: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n \n-7CCA CENTRAL HEADER #11    02014B50 (33639248)\n-7CCE Created Zip Spec      14 (20) '2.0'\n-7CCF Created OS            03 (3) 'Unix'\n-7CD0 Extract Zip Spec      0A (10) '1.0'\n-7CD1 Extract OS            00 (0) 'MS-DOS'\n-7CD2 General Purpose Flag  0800 (2048)\n-     [Bit 11]              1 'Language Encoding'\n-7CD4 Compression Method    0000 (0) 'Stored'\n-7CD6 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-7CDA CRC                   00000000 (0)\n-7CDE Compressed Size       00000000 (0)\n-7CE2 Uncompressed Size     00000000 (0)\n-7CE6 Filename Length       000F (15)\n-7CE8 Extra Length          0000 (0)\n-7CEA Comment Length        0000 (0)\n-7CEC Disk Start            0000 (0)\n-7CEE Int File Attributes   0000 (0)\n+7D49 CENTRAL HEADER #11    02014B50 (33639248)\n+7D4D Created Zip Spec      14 (20) '2.0'\n+7D4E Created OS            03 (3) 'Unix'\n+7D4F Extract Zip Spec      0A (10) '1.0'\n+7D50 Extract OS            00 (0) 'MS-DOS'\n+7D51 General Purpose Flag  0800 (2048)\n+     [Bit 11]              1 'Language Encoding'\n+7D53 Compression Method    0000 (0) 'Stored'\n+7D55 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+7D59 CRC                   00000000 (0)\n+7D5D Compressed Size       00000000 (0)\n+7D61 Uncompressed Size     00000000 (0)\n+7D65 Filename Length       000F (15)\n+7D67 Extra Length          0000 (0)\n+7D69 Comment Length        0000 (0)\n+7D6B Disk Start            0000 (0)\n+7D6D Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-7CF0 Ext File Attributes   41ED0010 (1106051088)\n+7D6F Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-7CF4 Local Header Offset   00000256 (598)\n-7CF8 Filename              'XXXXXXXXXXXXXXX'\n+7D73 Local Header Offset   00000256 (598)\n+7D77 Filename              'XXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x7CF8: Filename 'XXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7D77: Filename 'XXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0x7CF8: Directory 'XXXXXXXXXXXXXXX' must end in a '/'\n+# ERROR: Offset 0x7D77: Directory 'XXXXXXXXXXXXXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0x7CD0: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7D4F: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXX'\n #\n \n-7D07 CENTRAL HEADER #12    02014B50 (33639248)\n-7D0B Created Zip Spec      14 (20) '2.0'\n-7D0C Created OS            03 (3) 'Unix'\n-7D0D Extract Zip Spec      0A (10) '1.0'\n-7D0E Extract OS            00 (0) 'MS-DOS'\n-7D0F General Purpose Flag  0800 (2048)\n-     [Bit 11]              1 'Language Encoding'\n-7D11 Compression Method    0000 (0) 'Stored'\n-7D13 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-7D17 CRC                   00000000 (0)\n-7D1B Compressed Size       00000000 (0)\n-7D1F Uncompressed Size     00000000 (0)\n-7D23 Filename Length       0018 (24)\n-7D25 Extra Length          0000 (0)\n-7D27 Comment Length        0000 (0)\n-7D29 Disk Start            0000 (0)\n-7D2B Int File Attributes   0000 (0)\n+7D86 CENTRAL HEADER #12    02014B50 (33639248)\n+7D8A Created Zip Spec      14 (20) '2.0'\n+7D8B Created OS            03 (3) 'Unix'\n+7D8C Extract Zip Spec      0A (10) '1.0'\n+7D8D Extract OS            00 (0) 'MS-DOS'\n+7D8E General Purpose Flag  0800 (2048)\n+     [Bit 11]              1 'Language Encoding'\n+7D90 Compression Method    0000 (0) 'Stored'\n+7D92 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+7D96 CRC                   00000000 (0)\n+7D9A Compressed Size       00000000 (0)\n+7D9E Uncompressed Size     00000000 (0)\n+7DA2 Filename Length       0018 (24)\n+7DA4 Extra Length          0000 (0)\n+7DA6 Comment Length        0000 (0)\n+7DA8 Disk Start            0000 (0)\n+7DAA Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-7D2D Ext File Attributes   41ED0010 (1106051088)\n+7DAC Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-7D31 Local Header Offset   00000283 (643)\n-7D35 Filename              'XXXXXXXXXXXXXXXXXXXXXXXX'\n+7DB0 Local Header Offset   00000283 (643)\n+7DB4 Filename              'XXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x7D35: Filename 'XXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7DB4: Filename 'XXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0x7D35: Directory 'XXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n+# ERROR: Offset 0x7DB4: Directory 'XXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0x7D0D: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7D8C: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXX'\n #\n \n-7D4D CENTRAL HEADER #13    02014B50 (33639248)\n-7D51 Created Zip Spec      14 (20) '2.0'\n-7D52 Created OS            03 (3) 'Unix'\n-7D53 Extract Zip Spec      0A (10) '1.0'\n-7D54 Extract OS            00 (0) 'MS-DOS'\n-7D55 General Purpose Flag  0800 (2048)\n-     [Bit 11]              1 'Language Encoding'\n-7D57 Compression Method    0000 (0) 'Stored'\n-7D59 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-7D5D CRC                   00000000 (0)\n-7D61 Compressed Size       00000000 (0)\n-7D65 Uncompressed Size     00000000 (0)\n-7D69 Filename Length       000F (15)\n-7D6B Extra Length          0000 (0)\n-7D6D Comment Length        0000 (0)\n-7D6F Disk Start            0000 (0)\n-7D71 Int File Attributes   0000 (0)\n+7DCC CENTRAL HEADER #13    02014B50 (33639248)\n+7DD0 Created Zip Spec      14 (20) '2.0'\n+7DD1 Created OS            03 (3) 'Unix'\n+7DD2 Extract Zip Spec      0A (10) '1.0'\n+7DD3 Extract OS            00 (0) 'MS-DOS'\n+7DD4 General Purpose Flag  0800 (2048)\n+     [Bit 11]              1 'Language Encoding'\n+7DD6 Compression Method    0000 (0) 'Stored'\n+7DD8 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+7DDC CRC                   00000000 (0)\n+7DE0 Compressed Size       00000000 (0)\n+7DE4 Uncompressed Size     00000000 (0)\n+7DE8 Filename Length       000F (15)\n+7DEA Extra Length          0000 (0)\n+7DEC Comment Length        0000 (0)\n+7DEE Disk Start            0000 (0)\n+7DF0 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-7D73 Ext File Attributes   41ED0010 (1106051088)\n+7DF2 Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-7D77 Local Header Offset   000002B9 (697)\n-7D7B Filename              'XXXXXXXXXXXXXXX'\n+7DF6 Local Header Offset   000002B9 (697)\n+7DFA Filename              'XXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x7D7B: Filename 'XXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7DFA: Filename 'XXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0x7D7B: Directory 'XXXXXXXXXXXXXXX' must end in a '/'\n+# ERROR: Offset 0x7DFA: Directory 'XXXXXXXXXXXXXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0x7D53: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7DD2: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXX'\n #\n \n-7D8A CENTRAL HEADER #14    02014B50 (33639248)\n-7D8E Created Zip Spec      14 (20) '2.0'\n-7D8F Created OS            03 (3) 'Unix'\n-7D90 Extract Zip Spec      0A (10) '1.0'\n-7D91 Extract OS            00 (0) 'MS-DOS'\n-7D92 General Purpose Flag  0800 (2048)\n-     [Bit 11]              1 'Language Encoding'\n-7D94 Compression Method    0000 (0) 'Stored'\n-7D96 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-7D9A CRC                   00000000 (0)\n-7D9E Compressed Size       00000000 (0)\n-7DA2 Uncompressed Size     00000000 (0)\n-7DA6 Filename Length       0020 (32)\n-7DA8 Extra Length          0000 (0)\n-7DAA Comment Length        0000 (0)\n-7DAC Disk Start            0000 (0)\n-7DAE Int File Attributes   0000 (0)\n+7E09 CENTRAL HEADER #14    02014B50 (33639248)\n+7E0D Created Zip Spec      14 (20) '2.0'\n+7E0E Created OS            03 (3) 'Unix'\n+7E0F Extract Zip Spec      0A (10) '1.0'\n+7E10 Extract OS            00 (0) 'MS-DOS'\n+7E11 General Purpose Flag  0800 (2048)\n+     [Bit 11]              1 'Language Encoding'\n+7E13 Compression Method    0000 (0) 'Stored'\n+7E15 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+7E19 CRC                   00000000 (0)\n+7E1D Compressed Size       00000000 (0)\n+7E21 Uncompressed Size     00000000 (0)\n+7E25 Filename Length       0020 (32)\n+7E27 Extra Length          0000 (0)\n+7E29 Comment Length        0000 (0)\n+7E2B Disk Start            0000 (0)\n+7E2D Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-7DB0 Ext File Attributes   41ED0010 (1106051088)\n+7E2F Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-7DB4 Local Header Offset   000002E6 (742)\n-7DB8 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+7E33 Local Header Offset   000002E6 (742)\n+7E37 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x7DB8: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7E37: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0x7DB8: Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n+# ERROR: Offset 0x7E37: Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0x7D90: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7E0F: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n \n-7DD8 CENTRAL HEADER #15    02014B50 (33639248)\n-7DDC Created Zip Spec      14 (20) '2.0'\n-7DDD Created OS            03 (3) 'Unix'\n-7DDE Extract Zip Spec      0A (10) '1.0'\n-7DDF Extract OS            00 (0) 'MS-DOS'\n-7DE0 General Purpose Flag  0800 (2048)\n-     [Bit 11]              1 'Language Encoding'\n-7DE2 Compression Method    0000 (0) 'Stored'\n-7DE4 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-7DE8 CRC                   00000000 (0)\n-7DEC Compressed Size       00000000 (0)\n-7DF0 Uncompressed Size     00000000 (0)\n-7DF4 Filename Length       0035 (53)\n-7DF6 Extra Length          0000 (0)\n-7DF8 Comment Length        0000 (0)\n-7DFA Disk Start            0000 (0)\n-7DFC Int File Attributes   0000 (0)\n+7E57 CENTRAL HEADER #15    02014B50 (33639248)\n+7E5B Created Zip Spec      14 (20) '2.0'\n+7E5C Created OS            03 (3) 'Unix'\n+7E5D Extract Zip Spec      0A (10) '1.0'\n+7E5E Extract OS            00 (0) 'MS-DOS'\n+7E5F General Purpose Flag  0800 (2048)\n+     [Bit 11]              1 'Language Encoding'\n+7E61 Compression Method    0000 (0) 'Stored'\n+7E63 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+7E67 CRC                   00000000 (0)\n+7E6B Compressed Size       00000000 (0)\n+7E6F Uncompressed Size     00000000 (0)\n+7E73 Filename Length       0035 (53)\n+7E75 Extra Length          0000 (0)\n+7E77 Comment Length        0000 (0)\n+7E79 Disk Start            0000 (0)\n+7E7B Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-7DFE Ext File Attributes   41ED0010 (1106051088)\n+7E7D Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-7E02 Local Header Offset   00000324 (804)\n-7E06 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+7E81 Local Header Offset   00000324 (804)\n+7E85 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x7E06: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7E85: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0x7E06: Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n+# ERROR: Offset 0x7E85: Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0x7DDE: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7E5D: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n \n-7E3B CENTRAL HEADER #16    02014B50 (33639248)\n-7E3F Created Zip Spec      14 (20) '2.0'\n-7E40 Created OS            03 (3) 'Unix'\n-7E41 Extract Zip Spec      14 (20) '2.0'\n-7E42 Extract OS            00 (0) 'MS-DOS'\n-7E43 General Purpose Flag  0800 (2048)\n+7EBA CENTRAL HEADER #16    02014B50 (33639248)\n+7EBE Created Zip Spec      14 (20) '2.0'\n+7EBF Created OS            03 (3) 'Unix'\n+7EC0 Extract Zip Spec      14 (20) '2.0'\n+7EC1 Extract OS            00 (0) 'MS-DOS'\n+7EC2 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-7E45 Compression Method    0008 (8) 'Deflated'\n-7E47 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-7E4B CRC                   1A3FB9F4 (440383988)\n-7E4F Compressed Size       000007AE (1966)\n-7E53 Uncompressed Size     00002785 (10117)\n-7E57 Filename Length       0015 (21)\n-7E59 Extra Length          0000 (0)\n-7E5B Comment Length        0000 (0)\n-7E5D Disk Start            0000 (0)\n-7E5F Int File Attributes   0000 (0)\n+7EC4 Compression Method    0008 (8) 'Deflated'\n+7EC6 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+7ECA CRC                   1A3FB9F4 (440383988)\n+7ECE Compressed Size       000007AE (1966)\n+7ED2 Uncompressed Size     00002785 (10117)\n+7ED6 Filename Length       0015 (21)\n+7ED8 Extra Length          0000 (0)\n+7EDA Comment Length        0000 (0)\n+7EDC Disk Start            0000 (0)\n+7EDE Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-7E61 Ext File Attributes   81A40000 (2175008768)\n+7EE0 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-7E65 Local Header Offset   00000377 (887)\n-7E69 Filename              'XXXXXXXXXXXXXXXXXXXXX'\n+7EE4 Local Header Offset   00000377 (887)\n+7EE8 Filename              'XXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x7E69: Filename 'XXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7EE8: Filename 'XXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-7E7E CENTRAL HEADER #17    02014B50 (33639248)\n-7E82 Created Zip Spec      14 (20) '2.0'\n-7E83 Created OS            03 (3) 'Unix'\n-7E84 Extract Zip Spec      14 (20) '2.0'\n-7E85 Extract OS            00 (0) 'MS-DOS'\n-7E86 General Purpose Flag  0800 (2048)\n+7EFD CENTRAL HEADER #17    02014B50 (33639248)\n+7F01 Created Zip Spec      14 (20) '2.0'\n+7F02 Created OS            03 (3) 'Unix'\n+7F03 Extract Zip Spec      14 (20) '2.0'\n+7F04 Extract OS            00 (0) 'MS-DOS'\n+7F05 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-7E88 Compression Method    0008 (8) 'Deflated'\n-7E8A Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-7E8E CRC                   86E2B4B4 (2263004340)\n-7E92 Compressed Size       00000F6D (3949)\n-7E96 Uncompressed Size     00002C5E (11358)\n-7E9A Filename Length       0010 (16)\n-7E9C Extra Length          0000 (0)\n-7E9E Comment Length        0000 (0)\n-7EA0 Disk Start            0000 (0)\n-7EA2 Int File Attributes   0000 (0)\n+7F07 Compression Method    0008 (8) 'Deflated'\n+7F09 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+7F0D CRC                   86E2B4B4 (2263004340)\n+7F11 Compressed Size       00000F6D (3949)\n+7F15 Uncompressed Size     00002C5E (11358)\n+7F19 Filename Length       0010 (16)\n+7F1B Extra Length          0000 (0)\n+7F1D Comment Length        0000 (0)\n+7F1F Disk Start            0000 (0)\n+7F21 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-7EA4 Ext File Attributes   81A40000 (2175008768)\n+7F23 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-7EA8 Local Header Offset   00000B58 (2904)\n-7EAC Filename              'XXXXXXXXXXXXXXXX'\n+7F27 Local Header Offset   00000B58 (2904)\n+7F2B Filename              'XXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x7EAC: Filename 'XXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7F2B: Filename 'XXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-7EBC CENTRAL HEADER #18    02014B50 (33639248)\n-7EC0 Created Zip Spec      14 (20) '2.0'\n-7EC1 Created OS            03 (3) 'Unix'\n-7EC2 Extract Zip Spec      14 (20) '2.0'\n-7EC3 Extract OS            00 (0) 'MS-DOS'\n-7EC4 General Purpose Flag  0800 (2048)\n+7F3B CENTRAL HEADER #18    02014B50 (33639248)\n+7F3F Created Zip Spec      14 (20) '2.0'\n+7F40 Created OS            03 (3) 'Unix'\n+7F41 Extract Zip Spec      14 (20) '2.0'\n+7F42 Extract OS            00 (0) 'MS-DOS'\n+7F43 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-7EC6 Compression Method    0008 (8) 'Deflated'\n-7EC8 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-7ECC CRC                   B2802DB1 (2994744753)\n-7ED0 Compressed Size       00000081 (129)\n-7ED4 Uncompressed Size     000000B1 (177)\n-7ED8 Filename Length       000F (15)\n-7EDA Extra Length          0000 (0)\n-7EDC Comment Length        0000 (0)\n-7EDE Disk Start            0000 (0)\n-7EE0 Int File Attributes   0000 (0)\n+7F45 Compression Method    0008 (8) 'Deflated'\n+7F47 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+7F4B CRC                   B2802DB1 (2994744753)\n+7F4F Compressed Size       00000081 (129)\n+7F53 Uncompressed Size     000000B1 (177)\n+7F57 Filename Length       000F (15)\n+7F59 Extra Length          0000 (0)\n+7F5B Comment Length        0000 (0)\n+7F5D Disk Start            0000 (0)\n+7F5F Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-7EE2 Ext File Attributes   81A40000 (2175008768)\n+7F61 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-7EE6 Local Header Offset   00001AF3 (6899)\n-7EEA Filename              'XXXXXXXXXXXXXXX'\n+7F65 Local Header Offset   00001AF3 (6899)\n+7F69 Filename              'XXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x7EEA: Filename 'XXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7F69: Filename 'XXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-7EF9 CENTRAL HEADER #19    02014B50 (33639248)\n-7EFD Created Zip Spec      14 (20) '2.0'\n-7EFE Created OS            03 (3) 'Unix'\n-7EFF Extract Zip Spec      14 (20) '2.0'\n-7F00 Extract OS            00 (0) 'MS-DOS'\n-7F01 General Purpose Flag  0800 (2048)\n+7F78 CENTRAL HEADER #19    02014B50 (33639248)\n+7F7C Created Zip Spec      14 (20) '2.0'\n+7F7D Created OS            03 (3) 'Unix'\n+7F7E Extract Zip Spec      14 (20) '2.0'\n+7F7F Extract OS            00 (0) 'MS-DOS'\n+7F80 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-7F03 Compression Method    0008 (8) 'Deflated'\n-7F05 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-7F09 CRC                   36F8F065 (922284133)\n-7F0D Compressed Size       000002DB (731)\n-7F11 Uncompressed Size     0000062A (1578)\n-7F15 Filename Length       0037 (55)\n-7F17 Extra Length          0000 (0)\n-7F19 Comment Length        0000 (0)\n-7F1B Disk Start            0000 (0)\n-7F1D Int File Attributes   0000 (0)\n+7F82 Compression Method    0008 (8) 'Deflated'\n+7F84 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+7F88 CRC                   2526A8CF (623290575)\n+7F8C Compressed Size       000002E1 (737)\n+7F90 Uncompressed Size     00000657 (1623)\n+7F94 Filename Length       0037 (55)\n+7F96 Extra Length          0000 (0)\n+7F98 Comment Length        0000 (0)\n+7F9A Disk Start            0000 (0)\n+7F9C Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-7F1F Ext File Attributes   81A40000 (2175008768)\n+7F9E Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-7F23 Local Header Offset   00001BA1 (7073)\n-7F27 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+7FA2 Local Header Offset   00001BA1 (7073)\n+7FA6 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x7F27: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7FA6: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-7F5E CENTRAL HEADER #20    02014B50 (33639248)\n-7F62 Created Zip Spec      14 (20) '2.0'\n-7F63 Created OS            03 (3) 'Unix'\n-7F64 Extract Zip Spec      14 (20) '2.0'\n-7F65 Extract OS            00 (0) 'MS-DOS'\n-7F66 General Purpose Flag  0800 (2048)\n+7FDD CENTRAL HEADER #20    02014B50 (33639248)\n+7FE1 Created Zip Spec      14 (20) '2.0'\n+7FE2 Created OS            03 (3) 'Unix'\n+7FE3 Extract Zip Spec      14 (20) '2.0'\n+7FE4 Extract OS            00 (0) 'MS-DOS'\n+7FE5 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-7F68 Compression Method    0008 (8) 'Deflated'\n-7F6A Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-7F6E CRC                   CD8B51D1 (3448459729)\n-7F72 Compressed Size       00000232 (562)\n-7F76 Uncompressed Size     000003DC (988)\n-7F7A Filename Length       0031 (49)\n-7F7C Extra Length          0000 (0)\n-7F7E Comment Length        0000 (0)\n-7F80 Disk Start            0000 (0)\n-7F82 Int File Attributes   0000 (0)\n+7FE7 Compression Method    0008 (8) 'Deflated'\n+7FE9 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+7FED CRC                   CD8B51D1 (3448459729)\n+7FF1 Compressed Size       00000232 (562)\n+7FF5 Uncompressed Size     000003DC (988)\n+7FF9 Filename Length       0031 (49)\n+7FFB Extra Length          0000 (0)\n+7FFD Comment Length        0000 (0)\n+7FFF Disk Start            0000 (0)\n+8001 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-7F84 Ext File Attributes   81A40000 (2175008768)\n+8003 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-7F88 Local Header Offset   00001ED1 (7889)\n-7F8C Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+8007 Local Header Offset   00001ED7 (7895)\n+800B Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x7F8C: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x800B: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-7FBD CENTRAL HEADER #21    02014B50 (33639248)\n-7FC1 Created Zip Spec      14 (20) '2.0'\n-7FC2 Created OS            03 (3) 'Unix'\n-7FC3 Extract Zip Spec      14 (20) '2.0'\n-7FC4 Extract OS            00 (0) 'MS-DOS'\n-7FC5 General Purpose Flag  0800 (2048)\n+803C CENTRAL HEADER #21    02014B50 (33639248)\n+8040 Created Zip Spec      14 (20) '2.0'\n+8041 Created OS            03 (3) 'Unix'\n+8042 Extract Zip Spec      14 (20) '2.0'\n+8043 Extract OS            00 (0) 'MS-DOS'\n+8044 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-7FC7 Compression Method    0008 (8) 'Deflated'\n-7FC9 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-7FCD CRC                   123318DF (305338591)\n-7FD1 Compressed Size       0000032F (815)\n-7FD5 Uncompressed Size     000006C9 (1737)\n-7FD9 Filename Length       002D (45)\n-7FDB Extra Length          0000 (0)\n-7FDD Comment Length        0000 (0)\n-7FDF Disk Start            0000 (0)\n-7FE1 Int File Attributes   0000 (0)\n+8046 Compression Method    0008 (8) 'Deflated'\n+8048 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+804C CRC                   322BAD20 (841723168)\n+8050 Compressed Size       00000333 (819)\n+8054 Uncompressed Size     00000700 (1792)\n+8058 Filename Length       002D (45)\n+805A Extra Length          0000 (0)\n+805C Comment Length        0000 (0)\n+805E Disk Start            0000 (0)\n+8060 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-7FE3 Ext File Attributes   81A40000 (2175008768)\n+8062 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-7FE7 Local Header Offset   00002152 (8530)\n-7FEB Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+8066 Local Header Offset   00002158 (8536)\n+806A Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x7FEB: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x806A: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-8018 CENTRAL HEADER #22    02014B50 (33639248)\n-801C Created Zip Spec      14 (20) '2.0'\n-801D Created OS            03 (3) 'Unix'\n-801E Extract Zip Spec      14 (20) '2.0'\n-801F Extract OS            00 (0) 'MS-DOS'\n-8020 General Purpose Flag  0800 (2048)\n+8097 CENTRAL HEADER #22    02014B50 (33639248)\n+809B Created Zip Spec      14 (20) '2.0'\n+809C Created OS            03 (3) 'Unix'\n+809D Extract Zip Spec      14 (20) '2.0'\n+809E Extract OS            00 (0) 'MS-DOS'\n+809F General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-8022 Compression Method    0008 (8) 'Deflated'\n-8024 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-8028 CRC                   6B994ABC (1805208252)\n-802C Compressed Size       00000650 (1616)\n-8030 Uncompressed Size     000018EB (6379)\n-8034 Filename Length       002E (46)\n-8036 Extra Length          0000 (0)\n-8038 Comment Length        0000 (0)\n-803A Disk Start            0000 (0)\n-803C Int File Attributes   0000 (0)\n+80A1 Compression Method    0008 (8) 'Deflated'\n+80A3 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+80A7 CRC                   9A56CC71 (2589379697)\n+80AB Compressed Size       0000065D (1629)\n+80AF Uncompressed Size     000019AA (6570)\n+80B3 Filename Length       002E (46)\n+80B5 Extra Length          0000 (0)\n+80B7 Comment Length        0000 (0)\n+80B9 Disk Start            0000 (0)\n+80BB Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-803E Ext File Attributes   81A40000 (2175008768)\n+80BD Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-8042 Local Header Offset   000024CC (9420)\n-8046 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+80C1 Local Header Offset   000024D6 (9430)\n+80C5 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x8046: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x80C5: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-8074 CENTRAL HEADER #23    02014B50 (33639248)\n-8078 Created Zip Spec      14 (20) '2.0'\n-8079 Created OS            03 (3) 'Unix'\n-807A Extract Zip Spec      14 (20) '2.0'\n-807B Extract OS            00 (0) 'MS-DOS'\n-807C General Purpose Flag  0800 (2048)\n+80F3 CENTRAL HEADER #23    02014B50 (33639248)\n+80F7 Created Zip Spec      14 (20) '2.0'\n+80F8 Created OS            03 (3) 'Unix'\n+80F9 Extract Zip Spec      14 (20) '2.0'\n+80FA Extract OS            00 (0) 'MS-DOS'\n+80FB General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-807E Compression Method    0008 (8) 'Deflated'\n-8080 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-8084 CRC                   387B0FF7 (947589111)\n-8088 Compressed Size       0000027C (636)\n-808C Uncompressed Size     000007B7 (1975)\n-8090 Filename Length       0033 (51)\n-8092 Extra Length          0000 (0)\n-8094 Comment Length        0000 (0)\n-8096 Disk Start            0000 (0)\n-8098 Int File Attributes   0000 (0)\n+80FD Compression Method    0008 (8) 'Deflated'\n+80FF Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+8103 CRC                   BBB4B4AC (3149182124)\n+8107 Compressed Size       00000285 (645)\n+810B Uncompressed Size     000007E6 (2022)\n+810F Filename Length       0033 (51)\n+8111 Extra Length          0000 (0)\n+8113 Comment Length        0000 (0)\n+8115 Disk Start            0000 (0)\n+8117 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-809A Ext File Attributes   81A40000 (2175008768)\n+8119 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-809E Local Header Offset   00002B68 (11112)\n-80A2 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+811D Local Header Offset   00002B7F (11135)\n+8121 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x80A2: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x8121: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-80D5 CENTRAL HEADER #24    02014B50 (33639248)\n-80D9 Created Zip Spec      14 (20) '2.0'\n-80DA Created OS            03 (3) 'Unix'\n-80DB Extract Zip Spec      14 (20) '2.0'\n-80DC Extract OS            00 (0) 'MS-DOS'\n-80DD General Purpose Flag  0800 (2048)\n+8154 CENTRAL HEADER #24    02014B50 (33639248)\n+8158 Created Zip Spec      14 (20) '2.0'\n+8159 Created OS            03 (3) 'Unix'\n+815A Extract Zip Spec      14 (20) '2.0'\n+815B Extract OS            00 (0) 'MS-DOS'\n+815C General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-80DF Compression Method    0008 (8) 'Deflated'\n-80E1 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-80E5 CRC                   0F6205B4 (258082228)\n-80E9 Compressed Size       00000295 (661)\n-80ED Uncompressed Size     000004DB (1243)\n-80F1 Filename Length       002F (47)\n-80F3 Extra Length          0000 (0)\n-80F5 Comment Length        0000 (0)\n-80F7 Disk Start            0000 (0)\n-80F9 Int File Attributes   0000 (0)\n+815E Compression Method    0008 (8) 'Deflated'\n+8160 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+8164 CRC                   302E6CD8 (808348888)\n+8168 Compressed Size       0000029D (669)\n+816C Uncompressed Size     000004FA (1274)\n+8170 Filename Length       002F (47)\n+8172 Extra Length          0000 (0)\n+8174 Comment Length        0000 (0)\n+8176 Disk Start            0000 (0)\n+8178 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-80FB Ext File Attributes   81A40000 (2175008768)\n+817A Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-80FF Local Header Offset   00002E35 (11829)\n-8103 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+817E Local Header Offset   00002E55 (11861)\n+8182 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x8103: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x8182: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-8132 CENTRAL HEADER #25    02014B50 (33639248)\n-8136 Created Zip Spec      14 (20) '2.0'\n-8137 Created OS            03 (3) 'Unix'\n-8138 Extract Zip Spec      14 (20) '2.0'\n-8139 Extract OS            00 (0) 'MS-DOS'\n-813A General Purpose Flag  0800 (2048)\n+81B1 CENTRAL HEADER #25    02014B50 (33639248)\n+81B5 Created Zip Spec      14 (20) '2.0'\n+81B6 Created OS            03 (3) 'Unix'\n+81B7 Extract Zip Spec      14 (20) '2.0'\n+81B8 Extract OS            00 (0) 'MS-DOS'\n+81B9 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-813C Compression Method    0008 (8) 'Deflated'\n-813E Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-8142 CRC                   6ADC9301 (1792840449)\n-8146 Compressed Size       0000022E (558)\n-814A Uncompressed Size     000003E4 (996)\n-814E Filename Length       0031 (49)\n-8150 Extra Length          0000 (0)\n-8152 Comment Length        0000 (0)\n-8154 Disk Start            0000 (0)\n-8156 Int File Attributes   0000 (0)\n+81BB Compression Method    0008 (8) 'Deflated'\n+81BD Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+81C1 CRC                   6ADC9301 (1792840449)\n+81C5 Compressed Size       0000022E (558)\n+81C9 Uncompressed Size     000003E4 (996)\n+81CD Filename Length       0031 (49)\n+81CF Extra Length          0000 (0)\n+81D1 Comment Length        0000 (0)\n+81D3 Disk Start            0000 (0)\n+81D5 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-8158 Ext File Attributes   81A40000 (2175008768)\n+81D7 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-815C Local Header Offset   00003117 (12567)\n-8160 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+81DB Local Header Offset   0000313F (12607)\n+81DF Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x8160: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x81DF: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-8191 CENTRAL HEADER #26    02014B50 (33639248)\n-8195 Created Zip Spec      14 (20) '2.0'\n-8196 Created OS            03 (3) 'Unix'\n-8197 Extract Zip Spec      14 (20) '2.0'\n-8198 Extract OS            00 (0) 'MS-DOS'\n-8199 General Purpose Flag  0800 (2048)\n+8210 CENTRAL HEADER #26    02014B50 (33639248)\n+8214 Created Zip Spec      14 (20) '2.0'\n+8215 Created OS            03 (3) 'Unix'\n+8216 Extract Zip Spec      14 (20) '2.0'\n+8217 Extract OS            00 (0) 'MS-DOS'\n+8218 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-819B Compression Method    0008 (8) 'Deflated'\n-819D Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-81A1 CRC                   3F422686 (1061299846)\n-81A5 Compressed Size       00000266 (614)\n-81A9 Uncompressed Size     0000046C (1132)\n-81AD Filename Length       0041 (65)\n-81AF Extra Length          0000 (0)\n-81B1 Comment Length        0000 (0)\n-81B3 Disk Start            0000 (0)\n-81B5 Int File Attributes   0000 (0)\n+821A Compression Method    0008 (8) 'Deflated'\n+821C Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+8220 CRC                   F69577E7 (4136990695)\n+8224 Compressed Size       0000026D (621)\n+8228 Uncompressed Size     0000048A (1162)\n+822C Filename Length       0041 (65)\n+822E Extra Length          0000 (0)\n+8230 Comment Length        0000 (0)\n+8232 Disk Start            0000 (0)\n+8234 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-81B7 Ext File Attributes   81A40000 (2175008768)\n+8236 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-81BB Local Header Offset   00003394 (13204)\n-81BF Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+823A Local Header Offset   000033BC (13244)\n+823E Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x81BF: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x823E: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-8200 CENTRAL HEADER #27    02014B50 (33639248)\n-8204 Created Zip Spec      14 (20) '2.0'\n-8205 Created OS            03 (3) 'Unix'\n-8206 Extract Zip Spec      14 (20) '2.0'\n-8207 Extract OS            00 (0) 'MS-DOS'\n-8208 General Purpose Flag  0800 (2048)\n+827F CENTRAL HEADER #27    02014B50 (33639248)\n+8283 Created Zip Spec      14 (20) '2.0'\n+8284 Created OS            03 (3) 'Unix'\n+8285 Extract Zip Spec      14 (20) '2.0'\n+8286 Extract OS            00 (0) 'MS-DOS'\n+8287 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-820A Compression Method    0008 (8) 'Deflated'\n-820C Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-8210 CRC                   A75036DE (2807051998)\n-8214 Compressed Size       00000F72 (3954)\n-8218 Uncompressed Size     00004108 (16648)\n-821C Filename Length       0035 (53)\n-821E Extra Length          0000 (0)\n-8220 Comment Length        0000 (0)\n-8222 Disk Start            0000 (0)\n-8224 Int File Attributes   0000 (0)\n+8289 Compression Method    0008 (8) 'Deflated'\n+828B Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+828F CRC                   93092688 (2466850440)\n+8293 Compressed Size       00000F85 (3973)\n+8297 Uncompressed Size     000042E1 (17121)\n+829B Filename Length       0035 (53)\n+829D Extra Length          0000 (0)\n+829F Comment Length        0000 (0)\n+82A1 Disk Start            0000 (0)\n+82A3 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-8226 Ext File Attributes   81A40000 (2175008768)\n+82A5 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-822A Local Header Offset   00003659 (13913)\n-822E Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+82A9 Local Header Offset   00003688 (13960)\n+82AD Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x822E: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x82AD: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-8263 CENTRAL HEADER #28    02014B50 (33639248)\n-8267 Created Zip Spec      14 (20) '2.0'\n-8268 Created OS            03 (3) 'Unix'\n-8269 Extract Zip Spec      14 (20) '2.0'\n-826A Extract OS            00 (0) 'MS-DOS'\n-826B General Purpose Flag  0800 (2048)\n+82E2 CENTRAL HEADER #28    02014B50 (33639248)\n+82E6 Created Zip Spec      14 (20) '2.0'\n+82E7 Created OS            03 (3) 'Unix'\n+82E8 Extract Zip Spec      14 (20) '2.0'\n+82E9 Extract OS            00 (0) 'MS-DOS'\n+82EA General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-826D Compression Method    0008 (8) 'Deflated'\n-826F Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-8273 CRC                   F1F2D150 (4059222352)\n-8277 Compressed Size       00001721 (5921)\n-827B Uncompressed Size     00006EC8 (28360)\n-827F Filename Length       003C (60)\n-8281 Extra Length          0000 (0)\n-8283 Comment Length        0000 (0)\n-8285 Disk Start            0000 (0)\n-8287 Int File Attributes   0000 (0)\n+82EC Compression Method    0008 (8) 'Deflated'\n+82EE Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+82F2 CRC                   29CC663D (701261373)\n+82F6 Compressed Size       0000173E (5950)\n+82FA Uncompressed Size     000071B8 (29112)\n+82FE Filename Length       003C (60)\n+8300 Extra Length          0000 (0)\n+8302 Comment Length        0000 (0)\n+8304 Disk Start            0000 (0)\n+8306 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-8289 Ext File Attributes   81A40000 (2175008768)\n+8308 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-828D Local Header Offset   0000461E (17950)\n-8291 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+830C Local Header Offset   00004660 (18016)\n+8310 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x8291: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x8310: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-82CD CENTRAL HEADER #29    02014B50 (33639248)\n-82D1 Created Zip Spec      14 (20) '2.0'\n-82D2 Created OS            03 (3) 'Unix'\n-82D3 Extract Zip Spec      14 (20) '2.0'\n-82D4 Extract OS            00 (0) 'MS-DOS'\n-82D5 General Purpose Flag  0800 (2048)\n+834C CENTRAL HEADER #29    02014B50 (33639248)\n+8350 Created Zip Spec      14 (20) '2.0'\n+8351 Created OS            03 (3) 'Unix'\n+8352 Extract Zip Spec      14 (20) '2.0'\n+8353 Extract OS            00 (0) 'MS-DOS'\n+8354 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-82D7 Compression Method    0008 (8) 'Deflated'\n-82D9 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-82DD CRC                   F823DAB1 (4163099313)\n-82E1 Compressed Size       00000253 (595)\n-82E5 Uncompressed Size     00000480 (1152)\n-82E9 Filename Length       003A (58)\n-82EB Extra Length          0000 (0)\n-82ED Comment Length        0000 (0)\n-82EF Disk Start            0000 (0)\n-82F1 Int File Attributes   0000 (0)\n+8356 Compression Method    0008 (8) 'Deflated'\n+8358 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+835C CRC                   11BF3CA1 (297745569)\n+8360 Compressed Size       00000258 (600)\n+8364 Uncompressed Size     0000049E (1182)\n+8368 Filename Length       003A (58)\n+836A Extra Length          0000 (0)\n+836C Comment Length        0000 (0)\n+836E Disk Start            0000 (0)\n+8370 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-82F3 Ext File Attributes   81A40000 (2175008768)\n+8372 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-82F7 Local Header Offset   00005D99 (23961)\n-82FB Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+8376 Local Header Offset   00005DF8 (24056)\n+837A Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x82FB: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x837A: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-8335 CENTRAL HEADER #30    02014B50 (33639248)\n-8339 Created Zip Spec      14 (20) '2.0'\n-833A Created OS            03 (3) 'Unix'\n-833B Extract Zip Spec      14 (20) '2.0'\n-833C Extract OS            00 (0) 'MS-DOS'\n-833D General Purpose Flag  0800 (2048)\n+83B4 CENTRAL HEADER #30    02014B50 (33639248)\n+83B8 Created Zip Spec      14 (20) '2.0'\n+83B9 Created OS            03 (3) 'Unix'\n+83BA Extract Zip Spec      14 (20) '2.0'\n+83BB Extract OS            00 (0) 'MS-DOS'\n+83BC General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-833F Compression Method    0008 (8) 'Deflated'\n-8341 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-8345 CRC                   0B4932D9 (189346521)\n-8349 Compressed Size       00000430 (1072)\n-834D Uncompressed Size     00000D69 (3433)\n-8351 Filename Length       0034 (52)\n-8353 Extra Length          0000 (0)\n-8355 Comment Length        0000 (0)\n-8357 Disk Start            0000 (0)\n-8359 Int File Attributes   0000 (0)\n+83BE Compression Method    0008 (8) 'Deflated'\n+83C0 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+83C4 CRC                   8B7AC527 (2340078887)\n+83C8 Compressed Size       00000439 (1081)\n+83CC Uncompressed Size     00000DCC (3532)\n+83D0 Filename Length       0034 (52)\n+83D2 Extra Length          0000 (0)\n+83D4 Comment Length        0000 (0)\n+83D6 Disk Start            0000 (0)\n+83D8 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-835B Ext File Attributes   81A40000 (2175008768)\n+83DA Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-835F Local Header Offset   00006044 (24644)\n-8363 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+83DE Local Header Offset   000060A8 (24744)\n+83E2 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x8363: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x83E2: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-8397 CENTRAL HEADER #31    02014B50 (33639248)\n-839B Created Zip Spec      14 (20) '2.0'\n-839C Created OS            03 (3) 'Unix'\n-839D Extract Zip Spec      14 (20) '2.0'\n-839E Extract OS            00 (0) 'MS-DOS'\n-839F General Purpose Flag  0800 (2048)\n+8416 CENTRAL HEADER #31    02014B50 (33639248)\n+841A Created Zip Spec      14 (20) '2.0'\n+841B Created OS            03 (3) 'Unix'\n+841C Extract Zip Spec      14 (20) '2.0'\n+841D Extract OS            00 (0) 'MS-DOS'\n+841E General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-83A1 Compression Method    0008 (8) 'Deflated'\n-83A3 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-83A7 CRC                   117709A7 (293013927)\n-83AB Compressed Size       000002BF (703)\n-83AF Uncompressed Size     0000056A (1386)\n-83B3 Filename Length       0035 (53)\n-83B5 Extra Length          0000 (0)\n-83B7 Comment Length        0000 (0)\n-83B9 Disk Start            0000 (0)\n-83BB Int File Attributes   0000 (0)\n+8420 Compression Method    0008 (8) 'Deflated'\n+8422 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+8426 CRC                   117709A7 (293013927)\n+842A Compressed Size       000002BF (703)\n+842E Uncompressed Size     0000056A (1386)\n+8432 Filename Length       0035 (53)\n+8434 Extra Length          0000 (0)\n+8436 Comment Length        0000 (0)\n+8438 Disk Start            0000 (0)\n+843A Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-83BD Ext File Attributes   81A40000 (2175008768)\n+843C Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-83C1 Local Header Offset   000064C6 (25798)\n-83C5 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+8440 Local Header Offset   00006533 (25907)\n+8444 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x83C5: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x8444: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-83FA CENTRAL HEADER #32    02014B50 (33639248)\n-83FE Created Zip Spec      14 (20) '2.0'\n-83FF Created OS            03 (3) 'Unix'\n-8400 Extract Zip Spec      14 (20) '2.0'\n-8401 Extract OS            00 (0) 'MS-DOS'\n-8402 General Purpose Flag  0800 (2048)\n+8479 CENTRAL HEADER #32    02014B50 (33639248)\n+847D Created Zip Spec      14 (20) '2.0'\n+847E Created OS            03 (3) 'Unix'\n+847F Extract Zip Spec      14 (20) '2.0'\n+8480 Extract OS            00 (0) 'MS-DOS'\n+8481 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-8404 Compression Method    0008 (8) 'Deflated'\n-8406 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-840A CRC                   35D495FB (903124475)\n-840E Compressed Size       000004DC (1244)\n-8412 Uncompressed Size     00000B6B (2923)\n-8416 Filename Length       0035 (53)\n-8418 Extra Length          0000 (0)\n-841A Comment Length        0000 (0)\n-841C Disk Start            0000 (0)\n-841E Int File Attributes   0000 (0)\n+8483 Compression Method    0008 (8) 'Deflated'\n+8485 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+8489 CRC                   A1B16DDC (2712759772)\n+848D Compressed Size       000004E7 (1255)\n+8491 Uncompressed Size     00000BB9 (3001)\n+8495 Filename Length       0035 (53)\n+8497 Extra Length          0000 (0)\n+8499 Comment Length        0000 (0)\n+849B Disk Start            0000 (0)\n+849D Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-8420 Ext File Attributes   81A40000 (2175008768)\n+849F Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-8424 Local Header Offset   000067D8 (26584)\n-8428 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+84A3 Local Header Offset   00006845 (26693)\n+84A7 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x8428: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x84A7: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-845D CENTRAL HEADER #33    02014B50 (33639248)\n-8461 Created Zip Spec      14 (20) '2.0'\n-8462 Created OS            03 (3) 'Unix'\n-8463 Extract Zip Spec      14 (20) '2.0'\n-8464 Extract OS            00 (0) 'MS-DOS'\n-8465 General Purpose Flag  0800 (2048)\n+84DC CENTRAL HEADER #33    02014B50 (33639248)\n+84E0 Created Zip Spec      14 (20) '2.0'\n+84E1 Created OS            03 (3) 'Unix'\n+84E2 Extract Zip Spec      14 (20) '2.0'\n+84E3 Extract OS            00 (0) 'MS-DOS'\n+84E4 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-8467 Compression Method    0008 (8) 'Deflated'\n-8469 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-846D CRC                   2FB39AE6 (800299750)\n-8471 Compressed Size       000006C0 (1728)\n-8475 Uncompressed Size     00001C52 (7250)\n-8479 Filename Length       003E (62)\n-847B Extra Length          0000 (0)\n-847D Comment Length        0000 (0)\n-847F Disk Start            0000 (0)\n-8481 Int File Attributes   0000 (0)\n+84E6 Compression Method    0008 (8) 'Deflated'\n+84E8 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+84EC CRC                   43B8CAA4 (1136183972)\n+84F0 Compressed Size       000006CC (1740)\n+84F4 Uncompressed Size     00001D14 (7444)\n+84F8 Filename Length       003E (62)\n+84FA Extra Length          0000 (0)\n+84FC Comment Length        0000 (0)\n+84FE Disk Start            0000 (0)\n+8500 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-8483 Ext File Attributes   81A40000 (2175008768)\n+8502 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-8487 Local Header Offset   00006D07 (27911)\n-848B Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+8506 Local Header Offset   00006D7F (28031)\n+850A Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x848B: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x850A: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-84C9 CENTRAL HEADER #34    02014B50 (33639248)\n-84CD Created Zip Spec      14 (20) '2.0'\n-84CE Created OS            03 (3) 'Unix'\n-84CF Extract Zip Spec      14 (20) '2.0'\n-84D0 Extract OS            00 (0) 'MS-DOS'\n-84D1 General Purpose Flag  0800 (2048)\n+8548 CENTRAL HEADER #34    02014B50 (33639248)\n+854C Created Zip Spec      14 (20) '2.0'\n+854D Created OS            03 (3) 'Unix'\n+854E Extract Zip Spec      14 (20) '2.0'\n+854F Extract OS            00 (0) 'MS-DOS'\n+8550 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-84D3 Compression Method    0008 (8) 'Deflated'\n-84D5 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-84D9 CRC                   91BA560C (2444908044)\n-84DD Compressed Size       00000036 (54)\n-84E1 Uncompressed Size     0000003B (59)\n-84E5 Filename Length       0046 (70)\n-84E7 Extra Length          0000 (0)\n-84E9 Comment Length        0000 (0)\n-84EB Disk Start            0000 (0)\n-84ED Int File Attributes   0000 (0)\n+8552 Compression Method    0008 (8) 'Deflated'\n+8554 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+8558 CRC                   91BA560C (2444908044)\n+855C Compressed Size       00000036 (54)\n+8560 Uncompressed Size     0000003B (59)\n+8564 Filename Length       0046 (70)\n+8566 Extra Length          0000 (0)\n+8568 Comment Length        0000 (0)\n+856A Disk Start            0000 (0)\n+856C Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-84EF Ext File Attributes   81A40000 (2175008768)\n+856E Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-84F3 Local Header Offset   00007423 (29731)\n-84F7 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+8572 Local Header Offset   000074A7 (29863)\n+8576 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x84F7: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x8576: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-853D CENTRAL HEADER #35    02014B50 (33639248)\n-8541 Created Zip Spec      14 (20) '2.0'\n-8542 Created OS            03 (3) 'Unix'\n-8543 Extract Zip Spec      14 (20) '2.0'\n-8544 Extract OS            00 (0) 'MS-DOS'\n-8545 General Purpose Flag  0800 (2048)\n+85BC CENTRAL HEADER #35    02014B50 (33639248)\n+85C0 Created Zip Spec      14 (20) '2.0'\n+85C1 Created OS            03 (3) 'Unix'\n+85C2 Extract Zip Spec      14 (20) '2.0'\n+85C3 Extract OS            00 (0) 'MS-DOS'\n+85C4 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-8547 Compression Method    0008 (8) 'Deflated'\n-8549 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-854D CRC                   FACEEC94 (4207864980)\n-8551 Compressed Size       00000455 (1109)\n-8555 Uncompressed Size     00000E69 (3689)\n-8559 Filename Length       003C (60)\n-855B Extra Length          0000 (0)\n-855D Comment Length        0000 (0)\n-855F Disk Start            0000 (0)\n-8561 Int File Attributes   0000 (0)\n+85C6 Compression Method    0008 (8) 'Deflated'\n+85C8 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+85CC CRC                   DB79C8F6 (3682191606)\n+85D0 Compressed Size       00000450 (1104)\n+85D4 Uncompressed Size     00000E01 (3585)\n+85D8 Filename Length       003C (60)\n+85DA Extra Length          0000 (0)\n+85DC Comment Length        0000 (0)\n+85DE Disk Start            0000 (0)\n+85E0 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-8563 Ext File Attributes   81A40000 (2175008768)\n+85E2 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-8567 Local Header Offset   000074BD (29885)\n-856B Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+85E6 Local Header Offset   00007541 (30017)\n+85EA Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x856B: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x85EA: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-85A7 CENTRAL HEADER #36    02014B50 (33639248)\n-85AB Created Zip Spec      14 (20) '2.0'\n-85AC Created OS            03 (3) 'Unix'\n-85AD Extract Zip Spec      14 (20) '2.0'\n-85AE Extract OS            00 (0) 'MS-DOS'\n-85AF General Purpose Flag  0800 (2048)\n+8626 CENTRAL HEADER #36    02014B50 (33639248)\n+862A Created Zip Spec      14 (20) '2.0'\n+862B Created OS            03 (3) 'Unix'\n+862C Extract Zip Spec      14 (20) '2.0'\n+862D Extract OS            00 (0) 'MS-DOS'\n+862E General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-85B1 Compression Method    0008 (8) 'Deflated'\n-85B3 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-85B7 CRC                   D4B7125F (3568767583)\n-85BB Compressed Size       00000049 (73)\n-85BF Uncompressed Size     0000004B (75)\n-85C3 Filename Length       0043 (67)\n-85C5 Extra Length          0000 (0)\n-85C7 Comment Length        0000 (0)\n-85C9 Disk Start            0000 (0)\n-85CB Int File Attributes   0000 (0)\n+8630 Compression Method    0008 (8) 'Deflated'\n+8632 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+8636 CRC                   D4B7125F (3568767583)\n+863A Compressed Size       00000049 (73)\n+863E Uncompressed Size     0000004B (75)\n+8642 Filename Length       0043 (67)\n+8644 Extra Length          0000 (0)\n+8646 Comment Length        0000 (0)\n+8648 Disk Start            0000 (0)\n+864A Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-85CD Ext File Attributes   81A40000 (2175008768)\n+864C Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-85D1 Local Header Offset   0000796C (31084)\n-85D5 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+8650 Local Header Offset   000079EB (31211)\n+8654 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x85D5: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x8654: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-8618 END CENTRAL HEADER    06054B50 (101010256)\n-861C Number of this disk   0000 (0)\n-861E Central Dir Disk no   0000 (0)\n-8620 Entries in this disk  0024 (36)\n-8622 Total Entries         0024 (36)\n-8624 Size of Central Dir   00000C02 (3074)\n-8628 Offset to Central Dir 00007A16 (31254)\n-862C Comment Length        0000 (0)\n+8697 END CENTRAL HEADER    06054B50 (101010256)\n+869B Number of this disk   0000 (0)\n+869D Central Dir Disk no   0000 (0)\n+869F Entries in this disk  0024 (36)\n+86A1 Total Entries         0024 (36)\n+86A3 Size of Central Dir   00000C02 (3074)\n+86A7 Offset to Central Dir 00007A95 (31381)\n+86AB Comment Length        0000 (0)\n #\n # Error Count: 14\n # Warning Count: 86\n #\n # Done\n"}, {"source1": "org/apache/dubbo/remoting/etcd/AbstractRetryPolicy.java", "source2": "org/apache/dubbo/remoting/etcd/AbstractRetryPolicy.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,45 +1,45 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-package org.apache.dubbo.remoting.etcd;\n-\n-public abstract class AbstractRetryPolicy implements RetryPolicy {\n-\n-    private final int maxRetried;\n-\n-    protected AbstractRetryPolicy(int maxRetried) {\n-        this.maxRetried = maxRetried;\n-    }\n-\n-    @Override\n-    public boolean shouldRetry(int retried, long elapsed, boolean sleep) {\n-        if (retried < maxRetried) {\n-            try {\n-                if (sleep) {\n-                    Thread.sleep(getSleepTime(retried, elapsed));\n-                }\n-            } catch (InterruptedException e) {\n-                Thread.currentThread().interrupt();\n-                return false;\n-            }\n-            return true;\n-        }\n-        return false;\n-    }\n-\n-    protected abstract long getSleepTime(int retried, long elapsed);\n-\n-}\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+package org.apache.dubbo.remoting.etcd;\r\n+\r\n+public abstract class AbstractRetryPolicy implements RetryPolicy {\r\n+\r\n+    private final int maxRetried;\r\n+\r\n+    protected AbstractRetryPolicy(int maxRetried) {\r\n+        this.maxRetried = maxRetried;\r\n+    }\r\n+\r\n+    @Override\r\n+    public boolean shouldRetry(int retried, long elapsed, boolean sleep) {\r\n+        if (retried < maxRetried) {\r\n+            try {\r\n+                if (sleep) {\r\n+                    Thread.sleep(getSleepTime(retried, elapsed));\r\n+                }\r\n+            } catch (InterruptedException e) {\r\n+                Thread.currentThread().interrupt();\r\n+                return false;\r\n+            }\r\n+            return true;\r\n+        }\r\n+        return false;\r\n+    }\r\n+\r\n+    protected abstract long getSleepTime(int retried, long elapsed);\r\n+\r\n+}\r\n"}, {"source1": "org/apache/dubbo/remoting/etcd/Constants.java", "source2": "org/apache/dubbo/remoting/etcd/Constants.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,55 +1,55 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-package org.apache.dubbo.remoting.etcd;\n-\n-import static org.apache.dubbo.remoting.Constants.DEFAULT_IO_THREADS;\n-\n-public interface Constants {\n-    String ETCD3_NOTIFY_MAXTHREADS_KEYS = \"etcd3.notify.maxthreads\";\n-\n-    int DEFAULT_ETCD3_NOTIFY_THREADS = DEFAULT_IO_THREADS;\n-\n-    String DEFAULT_ETCD3_NOTIFY_QUEUES_KEY = \"etcd3.notify.queues\";\n-\n-    int DEFAULT_GRPC_QUEUES = 300_0000;\n-\n-    String RETRY_PERIOD_KEY = \"retry.period\";\n-\n-    int DEFAULT_RETRY_PERIOD = 5 * 1000;\n-\n-    int DEFAULT_SESSION_TIMEOUT = 60 * 1000;\n-\n-    String HTTP_SUBFIX_KEY = \"://\";\n-\n-    String HTTP_KEY = \"http://\";\n-\n-    int DEFAULT_KEEPALIVE_TIMEOUT = DEFAULT_SESSION_TIMEOUT / 2;\n-\n-    String SESSION_TIMEOUT_KEY = \"session\";\n-\n-    int DEFAULT_RECONNECT_PERIOD = 3 * 1000;\n-\n-    String ROUTERS_CATEGORY = \"routers\";\n-\n-    String PROVIDERS_CATEGORY = \"providers\";\n-\n-    String CONSUMERS_CATEGORY = \"consumers\";\n-\n-    String CONFIGURATORS_CATEGORY = \"configurators\";\n-}\n-\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+\r\n+package org.apache.dubbo.remoting.etcd;\r\n+\r\n+import static org.apache.dubbo.remoting.Constants.DEFAULT_IO_THREADS;\r\n+\r\n+public interface Constants {\r\n+    String ETCD3_NOTIFY_MAXTHREADS_KEYS = \"etcd3.notify.maxthreads\";\r\n+\r\n+    int DEFAULT_ETCD3_NOTIFY_THREADS = DEFAULT_IO_THREADS;\r\n+\r\n+    String DEFAULT_ETCD3_NOTIFY_QUEUES_KEY = \"etcd3.notify.queues\";\r\n+\r\n+    int DEFAULT_GRPC_QUEUES = 300_0000;\r\n+\r\n+    String RETRY_PERIOD_KEY = \"retry.period\";\r\n+\r\n+    int DEFAULT_RETRY_PERIOD = 5 * 1000;\r\n+\r\n+    int DEFAULT_SESSION_TIMEOUT = 60 * 1000;\r\n+\r\n+    String HTTP_SUBFIX_KEY = \"://\";\r\n+\r\n+    String HTTP_KEY = \"http://\";\r\n+\r\n+    int DEFAULT_KEEPALIVE_TIMEOUT = DEFAULT_SESSION_TIMEOUT / 2;\r\n+\r\n+    String SESSION_TIMEOUT_KEY = \"session\";\r\n+\r\n+    int DEFAULT_RECONNECT_PERIOD = 3 * 1000;\r\n+\r\n+    String ROUTERS_CATEGORY = \"routers\";\r\n+\r\n+    String PROVIDERS_CATEGORY = \"providers\";\r\n+\r\n+    String CONSUMERS_CATEGORY = \"consumers\";\r\n+\r\n+    String CONFIGURATORS_CATEGORY = \"configurators\";\r\n+}\r\n+\r\n"}, {"source1": "org/apache/dubbo/remoting/etcd/EtcdClient.java", "source2": "org/apache/dubbo/remoting/etcd/EtcdClient.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,191 +1,191 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-package org.apache.dubbo.remoting.etcd;\n-\n-import org.apache.dubbo.common.URL;\n-\n-import java.util.List;\n-import java.util.concurrent.CancellationException;\n-import java.util.concurrent.ExecutionException;\n-import java.util.concurrent.TimeUnit;\n-import java.util.concurrent.TimeoutException;\n-\n-public interface EtcdClient {\n-\n-    /**\n-     * save the specified path to the etcd registry.\n-     *\n-     * @param path the path to be saved\n-     */\n-    void create(String path);\n-\n-    /**\n-     * save the specified path to the etcd registry.\n-     * if node disconnect from etcd, it will be deleted\n-     * automatically by etcd when session timeout.\n-     *\n-     * @param path the path to be saved\n-     * @return the lease of current path.\n-     */\n-    long createEphemeral(String path);\n-\n-    /**\n-     * remove the specified  from etcd registry.\n-     *\n-     * @param path the path to be removed\n-     */\n-    void delete(String path);\n-\n-    /**\n-     * find direct children directory, excluding path self,\n-     * Never return null.\n-     *\n-     * @param path the path to be found direct children.\n-     * @return direct children directory, contains zero element\n-     * list if children directory not exists.\n-     */\n-    List<String> getChildren(String path);\n-\n-    /**\n-     * register children listener for specified path.\n-     *\n-     * @param path     the path to be watched when children is added, delete or update.\n-     * @param listener when children is changed , listener will be triggered.\n-     * @return direct children directory, contains zero element\n-     * list if children directory not exists.\n-     */\n-    List<String> addChildListener(String path, ChildListener listener);\n-\n-    /**\n-     * find watcher of the children listener for specified path.\n-     *\n-     * @param path     the path to be watched when children is added, delete or update.\n-     * @param listener when children is changed , listener will be triggered.\n-     * @return watcher if find else null\n-     */\n-    <T> T getChildListener(String path, ChildListener listener);\n-\n-    /**\n-     * unregister children lister for specified path.\n-     *\n-     * @param path     the path to be unwatched .\n-     * @param listener when children is changed , lister will be triggered.\n-     */\n-    void removeChildListener(String path, ChildListener listener);\n-\n-    /**\n-     * support connection notify if connection state was changed.\n-     *\n-     * @param listener if state changed, listener will be triggered.\n-     */\n-    void addStateListener(StateListener listener);\n-\n-    /**\n-     * remove connection notify if connection state was changed.\n-     *\n-     * @param listener remove already registered listener, if listener\n-     *                 not exists nothing happened.\n-     */\n-    void removeStateListener(StateListener listener);\n-\n-    /**\n-     * test if current client is active.\n-     *\n-     * @return true if connection is active else false.\n-     */\n-    boolean isConnected();\n-\n-    /**\n-     * close current client and release all resourses.\n-     */\n-    void close();\n-\n-    URL getUrl();\n-\n-    /***\n-     * create new lease from specified second ,it should be waiting if failed.<p>\n-     *\n-     * @param second lease time (support second only).\n-     * @return lease id from etcd\n-     */\n-    long createLease(long second);\n-\n-    /***\n-     * create new lease from specified ttl second before waiting specified timeout.<p>\n-     *\n-     * @param ttl lease time (support second only).\n-     * @param timeout the maximum time to wait\n-     * @param unit the time unit of the timeout argument\n-     * @throws CancellationException if this future was cancelled\n-     * @throws ExecutionException if this future completed exceptionally\n-     * @throws InterruptedException if the current thread was interrupted\n-     * while waiting\n-     * @throws TimeoutException if the wait timed out\n-     * @return lease id from etcd\n-     */\n-    long createLease(long ttl, long timeout, TimeUnit unit)\n-            throws InterruptedException, ExecutionException, TimeoutException;\n-\n-    /**\n-     * revoke specified lease, any associated path will removed automatically.\n-     *\n-     * @param lease to be removed lease\n-     */\n-    void revokeLease(long lease);\n-\n-\n-    /**\n-     * Get the value of the specified key.\n-     * @param key the specified key\n-     * @return null if the value is not found\n-     */\n-    String getKVValue(String key);\n-\n-    /**\n-     * Put the key value pair to etcd\n-     * @param key the specified key\n-     * @param value the paired value\n-     * @return true if put success\n-     */\n-    boolean put(String key, String value);\n-\n-    /**\n-     * Put the key value pair to etcd (Ephemeral)\n-     * @param key the specified key\n-     * @param value the paired value\n-     * @return true if put success\n-     */\n-    boolean putEphemeral(String key, String value);\n-\n-}\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+\r\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+package org.apache.dubbo.remoting.etcd;\r\n+\r\n+import org.apache.dubbo.common.URL;\r\n+\r\n+import java.util.List;\r\n+import java.util.concurrent.CancellationException;\r\n+import java.util.concurrent.ExecutionException;\r\n+import java.util.concurrent.TimeUnit;\r\n+import java.util.concurrent.TimeoutException;\r\n+\r\n+public interface EtcdClient {\r\n+\r\n+    /**\r\n+     * save the specified path to the etcd registry.\r\n+     *\r\n+     * @param path the path to be saved\r\n+     */\r\n+    void create(String path);\r\n+\r\n+    /**\r\n+     * save the specified path to the etcd registry.\r\n+     * if node disconnect from etcd, it will be deleted\r\n+     * automatically by etcd when session timeout.\r\n+     *\r\n+     * @param path the path to be saved\r\n+     * @return the lease of current path.\r\n+     */\r\n+    long createEphemeral(String path);\r\n+\r\n+    /**\r\n+     * remove the specified  from etcd registry.\r\n+     *\r\n+     * @param path the path to be removed\r\n+     */\r\n+    void delete(String path);\r\n+\r\n+    /**\r\n+     * find direct children directory, excluding path self,\r\n+     * Never return null.\r\n+     *\r\n+     * @param path the path to be found direct children.\r\n+     * @return direct children directory, contains zero element\r\n+     * list if children directory not exists.\r\n+     */\r\n+    List<String> getChildren(String path);\r\n+\r\n+    /**\r\n+     * register children listener for specified path.\r\n+     *\r\n+     * @param path     the path to be watched when children is added, delete or update.\r\n+     * @param listener when children is changed , listener will be triggered.\r\n+     * @return direct children directory, contains zero element\r\n+     * list if children directory not exists.\r\n+     */\r\n+    List<String> addChildListener(String path, ChildListener listener);\r\n+\r\n+    /**\r\n+     * find watcher of the children listener for specified path.\r\n+     *\r\n+     * @param path     the path to be watched when children is added, delete or update.\r\n+     * @param listener when children is changed , listener will be triggered.\r\n+     * @return watcher if find else null\r\n+     */\r\n+    <T> T getChildListener(String path, ChildListener listener);\r\n+\r\n+    /**\r\n+     * unregister children lister for specified path.\r\n+     *\r\n+     * @param path     the path to be unwatched .\r\n+     * @param listener when children is changed , lister will be triggered.\r\n+     */\r\n+    void removeChildListener(String path, ChildListener listener);\r\n+\r\n+    /**\r\n+     * support connection notify if connection state was changed.\r\n+     *\r\n+     * @param listener if state changed, listener will be triggered.\r\n+     */\r\n+    void addStateListener(StateListener listener);\r\n+\r\n+    /**\r\n+     * remove connection notify if connection state was changed.\r\n+     *\r\n+     * @param listener remove already registered listener, if listener\r\n+     *                 not exists nothing happened.\r\n+     */\r\n+    void removeStateListener(StateListener listener);\r\n+\r\n+    /**\r\n+     * test if current client is active.\r\n+     *\r\n+     * @return true if connection is active else false.\r\n+     */\r\n+    boolean isConnected();\r\n+\r\n+    /**\r\n+     * close current client and release all resourses.\r\n+     */\r\n+    void close();\r\n+\r\n+    URL getUrl();\r\n+\r\n+    /***\r\n+     * create new lease from specified second ,it should be waiting if failed.<p>\r\n+     *\r\n+     * @param second lease time (support second only).\r\n+     * @return lease id from etcd\r\n+     */\r\n+    long createLease(long second);\r\n+\r\n+    /***\r\n+     * create new lease from specified ttl second before waiting specified timeout.<p>\r\n+     *\r\n+     * @param ttl lease time (support second only).\r\n+     * @param timeout the maximum time to wait\r\n+     * @param unit the time unit of the timeout argument\r\n+     * @throws CancellationException if this future was cancelled\r\n+     * @throws ExecutionException if this future completed exceptionally\r\n+     * @throws InterruptedException if the current thread was interrupted\r\n+     * while waiting\r\n+     * @throws TimeoutException if the wait timed out\r\n+     * @return lease id from etcd\r\n+     */\r\n+    long createLease(long ttl, long timeout, TimeUnit unit)\r\n+            throws InterruptedException, ExecutionException, TimeoutException;\r\n+\r\n+    /**\r\n+     * revoke specified lease, any associated path will removed automatically.\r\n+     *\r\n+     * @param lease to be removed lease\r\n+     */\r\n+    void revokeLease(long lease);\r\n+\r\n+\r\n+    /**\r\n+     * Get the value of the specified key.\r\n+     * @param key the specified key\r\n+     * @return null if the value is not found\r\n+     */\r\n+    String getKVValue(String key);\r\n+\r\n+    /**\r\n+     * Put the key value pair to etcd\r\n+     * @param key the specified key\r\n+     * @param value the paired value\r\n+     * @return true if put success\r\n+     */\r\n+    boolean put(String key, String value);\r\n+\r\n+    /**\r\n+     * Put the key value pair to etcd (Ephemeral)\r\n+     * @param key the specified key\r\n+     * @param value the paired value\r\n+     * @return true if put success\r\n+     */\r\n+    boolean putEphemeral(String key, String value);\r\n+\r\n+}\r\n"}, {"source1": "org/apache/dubbo/remoting/etcd/EtcdTransporter.java", "source2": "org/apache/dubbo/remoting/etcd/EtcdTransporter.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,47 +1,47 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-package org.apache.dubbo.remoting.etcd;\n-\n-import org.apache.dubbo.common.URL;\n-import org.apache.dubbo.common.extension.Adaptive;\n-import org.apache.dubbo.common.extension.SPI;\n-import org.apache.dubbo.remoting.Constants;\n-\n-@SPI(\"jetcd\")\n-public interface EtcdTransporter {\n-\n-    @Adaptive({Constants.CLIENT_KEY, Constants.TRANSPORTER_KEY})\n-    EtcdClient connect(URL url);\n-\n-}\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+\r\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+package org.apache.dubbo.remoting.etcd;\r\n+\r\n+import org.apache.dubbo.common.URL;\r\n+import org.apache.dubbo.common.extension.Adaptive;\r\n+import org.apache.dubbo.common.extension.SPI;\r\n+import org.apache.dubbo.remoting.Constants;\r\n+\r\n+@SPI(\"jetcd\")\r\n+public interface EtcdTransporter {\r\n+\r\n+    @Adaptive({Constants.CLIENT_KEY, Constants.TRANSPORTER_KEY})\r\n+    EtcdClient connect(URL url);\r\n+\r\n+}\r\n"}, {"source1": "org/apache/dubbo/remoting/etcd/RetryPolicy.java", "source2": "org/apache/dubbo/remoting/etcd/RetryPolicy.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,31 +1,31 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-package org.apache.dubbo.remoting.etcd;\n-\n-public interface RetryPolicy {\n-\n-    /**\n-     * Whether retry is supported when operation fails.\n-     *\n-     * @param retried the number of times retried so far\n-     * @param elapsed the elapsed time in millisecond since the operation was attempted\n-     * @param sleep   should be sleep\n-     * @return true should be retry\n-     */\n-    boolean shouldRetry(int retried, long elapsed, boolean sleep);\n-\n-}\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+package org.apache.dubbo.remoting.etcd;\r\n+\r\n+public interface RetryPolicy {\r\n+\r\n+    /**\r\n+     * Whether retry is supported when operation fails.\r\n+     *\r\n+     * @param retried the number of times retried so far\r\n+     * @param elapsed the elapsed time in millisecond since the operation was attempted\r\n+     * @param sleep   should be sleep\r\n+     * @return true should be retry\r\n+     */\r\n+    boolean shouldRetry(int retried, long elapsed, boolean sleep);\r\n+\r\n+}\r\n"}, {"source1": "org/apache/dubbo/remoting/etcd/jetcd/ConnectionStateListener.java", "source2": "org/apache/dubbo/remoting/etcd/jetcd/ConnectionStateListener.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,31 +1,31 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-package org.apache.dubbo.remoting.etcd.jetcd;\n-\n-import io.etcd.jetcd.Client;\n-\n-public interface ConnectionStateListener {\n-\n-    /**\n-     * Called when there is a state change in the connection\n-     *\n-     * @param client   the client\n-     * @param newState the new state\n-     */\n-    void stateChanged(Client client, int newState);\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+\r\n+package org.apache.dubbo.remoting.etcd.jetcd;\r\n+\r\n+import io.etcd.jetcd.Client;\r\n+\r\n+public interface ConnectionStateListener {\r\n+\r\n+    /**\r\n+     * Called when there is a state change in the connection\r\n+     *\r\n+     * @param client   the client\r\n+     * @param newState the new state\r\n+     */\r\n+    void stateChanged(Client client, int newState);\r\n }\n"}, {"source1": "org/apache/dubbo/remoting/etcd/jetcd/JEtcdClient.java", "source2": "org/apache/dubbo/remoting/etcd/jetcd/JEtcdClient.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,473 +1,473 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-package org.apache.dubbo.remoting.etcd.jetcd;\n-\n-import org.apache.dubbo.common.URL;\n-import org.apache.dubbo.common.logger.Logger;\n-import org.apache.dubbo.common.logger.LoggerFactory;\n-import org.apache.dubbo.common.utils.ExecutorUtil;\n-import org.apache.dubbo.common.utils.NamedThreadFactory;\n-import org.apache.dubbo.remoting.etcd.ChildListener;\n-import org.apache.dubbo.remoting.etcd.StateListener;\n-import org.apache.dubbo.remoting.etcd.option.OptionUtil;\n-import org.apache.dubbo.remoting.etcd.support.AbstractEtcdClient;\n-\n-import com.google.protobuf.ByteString;\n-import io.etcd.jetcd.ByteSequence;\n-import io.etcd.jetcd.api.Event;\n-import io.etcd.jetcd.api.KeyValue;\n-import io.etcd.jetcd.api.WatchCancelRequest;\n-import io.etcd.jetcd.api.WatchCreateRequest;\n-import io.etcd.jetcd.api.WatchGrpc;\n-import io.etcd.jetcd.api.WatchRequest;\n-import io.etcd.jetcd.api.WatchResponse;\n-import io.etcd.jetcd.common.exception.ClosedClientException;\n-import io.grpc.ManagedChannel;\n-import io.grpc.Status;\n-import io.grpc.stub.StreamObserver;\n-import io.netty.util.internal.ConcurrentSet;\n-\n-import java.util.ArrayList;\n-import java.util.Collections;\n-import java.util.Iterator;\n-import java.util.List;\n-import java.util.Random;\n-import java.util.Set;\n-import java.util.concurrent.ExecutionException;\n-import java.util.concurrent.ExecutorService;\n-import java.util.concurrent.Executors;\n-import java.util.concurrent.LinkedBlockingQueue;\n-import java.util.concurrent.ScheduledExecutorService;\n-import java.util.concurrent.ThreadPoolExecutor;\n-import java.util.concurrent.TimeUnit;\n-import java.util.concurrent.TimeoutException;\n-import java.util.concurrent.locks.ReentrantLock;\n-\n-import static java.util.stream.Collectors.toList;\n-import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR;\n-import static org.apache.dubbo.remoting.etcd.Constants.DEFAULT_ETCD3_NOTIFY_QUEUES_KEY;\n-import static org.apache.dubbo.remoting.etcd.Constants.DEFAULT_ETCD3_NOTIFY_THREADS;\n-import static org.apache.dubbo.remoting.etcd.Constants.DEFAULT_GRPC_QUEUES;\n-import static org.apache.dubbo.remoting.etcd.Constants.DEFAULT_RETRY_PERIOD;\n-import static org.apache.dubbo.remoting.etcd.Constants.DEFAULT_SESSION_TIMEOUT;\n-import static org.apache.dubbo.remoting.etcd.Constants.ETCD3_NOTIFY_MAXTHREADS_KEYS;\n-import static org.apache.dubbo.remoting.etcd.Constants.RETRY_PERIOD_KEY;\n-import static org.apache.dubbo.remoting.etcd.jetcd.JEtcdClientWrapper.UTF_8;\n-\n-/**\n- * etcd3 client.\n- */\n-public class JEtcdClient extends AbstractEtcdClient<JEtcdClient.EtcdWatcher> {\n-\n-    private JEtcdClientWrapper clientWrapper;\n-    private ScheduledExecutorService reconnectSchedule;\n-\n-    private ExecutorService notifyExecutor;\n-\n-    private int delayPeriod;\n-    private Logger logger = LoggerFactory.getLogger(JEtcdClient.class);\n-\n-    public JEtcdClient(URL url) {\n-        super(url);\n-        try {\n-            clientWrapper = new JEtcdClientWrapper(url);\n-            clientWrapper.setConnectionStateListener((client, state) -> {\n-                if (state == StateListener.CONNECTED) {\n-                    JEtcdClient.this.stateChanged(StateListener.CONNECTED);\n-                } else if (state == StateListener.DISCONNECTED) {\n-                    JEtcdClient.this.stateChanged(StateListener.DISCONNECTED);\n-                }\n-            });\n-            delayPeriod = getUrl().getParameter(RETRY_PERIOD_KEY, DEFAULT_RETRY_PERIOD);\n-            reconnectSchedule = Executors.newScheduledThreadPool(1,\n-                    new NamedThreadFactory(\"etcd3-watch-auto-reconnect\"));\n-\n-            notifyExecutor = new ThreadPoolExecutor(\n-                    1\n-                    , url.getParameter(ETCD3_NOTIFY_MAXTHREADS_KEYS, DEFAULT_ETCD3_NOTIFY_THREADS)\n-                    , DEFAULT_SESSION_TIMEOUT\n-                    , TimeUnit.MILLISECONDS\n-                    , new LinkedBlockingQueue<Runnable>(url.getParameter(DEFAULT_ETCD3_NOTIFY_QUEUES_KEY, DEFAULT_GRPC_QUEUES * 3))\n-                    , new NamedThreadFactory(\"etcd3-notify\", true));\n-\n-            clientWrapper.start();\n-        } catch (Exception e) {\n-            throw new IllegalStateException(e.getMessage(), e);\n-        }\n-    }\n-\n-    @Override\n-    public void doCreatePersistent(String path) {\n-        clientWrapper.createPersistent(path);\n-    }\n-\n-    @Override\n-    public long doCreateEphemeral(String path) {\n-        return clientWrapper.createEphemeral(path);\n-    }\n-\n-    @Override\n-    public boolean checkExists(String path) {\n-        return clientWrapper.checkExists(path);\n-    }\n-\n-    @Override\n-    public EtcdWatcher createChildWatcherListener(String path, ChildListener listener) {\n-        return new EtcdWatcher(listener);\n-    }\n-\n-    @Override\n-    public List<String> addChildWatcherListener(String path, EtcdWatcher etcdWatcher) {\n-        return etcdWatcher.forPath(path);\n-    }\n-\n-    @Override\n-    public void removeChildWatcherListener(String path, EtcdWatcher etcdWatcher) {\n-        etcdWatcher.unwatch();\n-    }\n-\n-    @Override\n-    public List<String> getChildren(String path) {\n-        return clientWrapper.getChildren(path);\n-    }\n-\n-    @Override\n-    public boolean isConnected() {\n-        return clientWrapper.isConnected();\n-    }\n-\n-    @Override\n-    public long createLease(long second) {\n-        return clientWrapper.createLease(second);\n-    }\n-\n-    @Override\n-    public long createLease(long ttl, long timeout, TimeUnit unit)\n-            throws InterruptedException, ExecutionException, TimeoutException {\n-        return clientWrapper.createLease(ttl, timeout, unit);\n-    }\n-\n-    @Override\n-    public void delete(String path) {\n-        clientWrapper.delete(path);\n-    }\n-\n-    @Override\n-    public void revokeLease(long lease) {\n-        clientWrapper.revokeLease(lease);\n-    }\n-\n-    @Override\n-    public void doClose() {\n-        try {\n-            if (notifyExecutor != null) {\n-                ExecutorUtil.shutdownNow(notifyExecutor, 100);\n-            }\n-        } catch (Exception e) {\n-            logger.warn(e.getMessage(), e);\n-        }\n-\n-        try {\n-            if (reconnectSchedule != null) {\n-                ExecutorUtil.shutdownNow(reconnectSchedule, 100);\n-            }\n-        } catch (Exception e) {\n-            logger.warn(e.getMessage(), e);\n-        } finally {\n-            clientWrapper.doClose();\n-        }\n-    }\n-\n-    @Override\n-    public String getKVValue(String key) {\n-        return clientWrapper.getKVValue(key);\n-    }\n-\n-    @Override\n-    public boolean put(String key, String value) {\n-        return clientWrapper.put(key, value);\n-    }\n-\n-    @Override\n-    public boolean putEphemeral(String key, String value) {\n-        return clientWrapper.putEphemeral(key, value);\n-    }\n-\n-    public ManagedChannel getChannel() {\n-        return clientWrapper.getChannel();\n-    }\n-\n-    public class EtcdWatcher implements StreamObserver<WatchResponse> {\n-\n-        protected WatchGrpc.WatchStub watchStub;\n-        protected StreamObserver<WatchRequest> watchRequest;\n-        protected long watchId;\n-        protected String path;\n-        protected Throwable throwable;\n-        protected volatile Set<String> urls = new ConcurrentSet<>();\n-        private ChildListener listener;\n-\n-        protected ReentrantLock lock = new ReentrantLock(true);\n-\n-        public EtcdWatcher(ChildListener listener) {\n-            this.listener = listener;\n-        }\n-\n-        @Override\n-        public void onNext(WatchResponse response) {\n-\n-            // prevents grpc on sending watchResponse to a closed watch client.\n-            if (!isConnected()) {\n-                return;\n-            }\n-\n-            watchId = response.getWatchId();\n-\n-            if (listener != null) {\n-                int modified = 0;\n-                String service = null;\n-                Iterator<Event> iterator = response.getEventsList().iterator();\n-                while (iterator.hasNext()) {\n-                    Event event = iterator.next();\n-                    switch (event.getType()) {\n-                        case PUT: {\n-                            if (((service = find(event)) != null)\n-                                    && safeUpdate(service, true)) {\n-                                modified++;\n-                            }\n-                            break;\n-                        }\n-                        case DELETE: {\n-                            if (((service = find(event)) != null)\n-                                    && safeUpdate(service, false)) {\n-                                modified++;\n-                            }\n-                            break;\n-                        }\n-                        default:\n-                            break;\n-                    }\n-                }\n-                if (modified > 0) {\n-                    notifyExecutor.execute(() -> listener.childChanged(path, new ArrayList<>(urls)));\n-                }\n-\n-            }\n-        }\n-\n-        @Override\n-        public void onError(Throwable e) {\n-            tryReconnect(e);\n-        }\n-\n-        public void unwatch() {\n-\n-            // prevents grpc on sending watchResponse to a closed watch client.\n-            if (!isConnected()) {\n-                return;\n-            }\n-\n-            try {\n-                /**\n-                 * issue : https://github.com/apache/dubbo/issues/4115\n-                 *\n-                 * When the network is reconnected, the listener is empty\n-                 * and the data cannot be received.\n-                 */\n-                // this.listener = null;\n-\n-                if (watchRequest != null) {\n-                    WatchCancelRequest watchCancelRequest =\n-                            WatchCancelRequest.newBuilder().setWatchId(watchId).build();\n-                    WatchRequest cancelRequest = WatchRequest.newBuilder()\n-                            .setCancelRequest(watchCancelRequest).build();\n-                    this.watchRequest.onNext(cancelRequest);\n-                }\n-            } catch (Exception ignored) {\n-                logger.warn(\"Failed to cancel watch for path '\" + path + \"'\", ignored);\n-            }\n-        }\n-\n-        public List<String> forPath(String path) {\n-\n-            if (!isConnected()) {\n-                throw new ClosedClientException(\"watch client has been closed, path '\" + path + \"'\");\n-            }\n-            if (this.path != null) {\n-                unwatch();\n-            }\n-\n-            this.path = path;\n-\n-            lock.lock();\n-            try {\n-\n-                this.watchStub = WatchGrpc.newStub(clientWrapper.getChannel());\n-                this.watchRequest = watchStub.watch(this);\n-                this.watchRequest.onNext(nextRequest());\n-\n-                List<String> children = clientWrapper.getChildren(path);\n-                /**\n-                 * caching the current service\n-                 */\n-                if (!children.isEmpty()) {\n-                    this.urls.addAll(filterChildren(children));\n-                }\n-\n-                return new ArrayList<>(urls);\n-            } finally {\n-                lock.unlock();\n-            }\n-        }\n-\n-        private boolean safeUpdate(String service, boolean add) {\n-            lock.lock();\n-            try {\n-                /**\n-                 * If the collection already contains the specified service, do nothing\n-                 */\n-                return add ? this.urls.add(service) : this.urls.remove(service);\n-            } finally {\n-                lock.unlock();\n-            }\n-        }\n-\n-        private String find(Event event) {\n-            KeyValue keyValue = event.getKv();\n-            String key = keyValue.getKey().toStringUtf8();\n-\n-            int len = path.length(), index = len, count = 0;\n-            if (key.length() >= index) {\n-                for (; (index = key.indexOf(PATH_SEPARATOR, index)) != -1; ++index) {\n-                    if (count++ > 1) {\n-                        break;\n-                    }\n-                }\n-            }\n-\n-            /**\n-             * if children changed , we should refresh invokers\n-             */\n-            if (count == 1) {\n-                /**\n-                 * remove prefix\n-                 */\n-                return key.substring(len + 1);\n-            }\n-\n-            return null;\n-        }\n-\n-        private List<String> filterChildren(List<String> children) {\n-            if (children == null) {\n-                return Collections.emptyList();\n-            }\n-            if (children.size() <= 0) {\n-                return children;\n-            }\n-            final int len = path.length();\n-            return children.stream().parallel()\n-                    .filter(child -> {\n-                        int index = len, count = 0;\n-                        if (child.length() > len) {\n-                            for (; (index = child.indexOf(PATH_SEPARATOR, index)) != -1; ++index) {\n-                                if (count++ > 1) {\n-                                    break;\n-                                }\n-                            }\n-                        }\n-                        return count == 1;\n-                    })\n-                    .map(child -> child.substring(len + 1))\n-                    .collect(toList());\n-        }\n-\n-        /**\n-         * create new watching request for current path.\n-         */\n-        protected WatchRequest nextRequest() {\n-\n-            WatchCreateRequest.Builder builder = WatchCreateRequest.newBuilder()\n-                    .setKey(ByteString.copyFromUtf8(path))\n-                    .setRangeEnd(ByteString.copyFrom(\n-                            OptionUtil.prefixEndOf(ByteSequence.from(path, UTF_8)).getBytes()))\n-                    .setProgressNotify(true);\n-\n-            return WatchRequest.newBuilder().setCreateRequest(builder).build();\n-        }\n-\n-        public void tryReconnect(Throwable e) {\n-\n-            this.throwable = e;\n-\n-            logger.error(\"watcher client has error occurred, current path '\" + path + \"'\", e);\n-\n-            // prevents grpc on sending error to a closed watch client.\n-            if (!isConnected()) {\n-                return;\n-            }\n-\n-\n-            Status status = Status.fromThrowable(e);\n-            // system may be recover later, current connect won't be lost\n-            if (OptionUtil.isHaltError(status) || OptionUtil.isNoLeaderError(status)) {\n-                reconnectSchedule.schedule(this::reconnect, new Random().nextInt(delayPeriod), TimeUnit.MILLISECONDS);\n-                return;\n-            }\n-            // reconnect with a delay; avoiding immediate retry on a long connection downtime.\n-            reconnectSchedule.schedule(this::reconnect, new Random().nextInt(delayPeriod), TimeUnit.MILLISECONDS);\n-        }\n-\n-        protected synchronized void reconnect() {\n-            this.closeWatchRequest();\n-            this.recreateWatchRequest();\n-        }\n-\n-        protected void recreateWatchRequest() {\n-            if (watchRequest == null) {\n-                this.watchStub = WatchGrpc.newStub(clientWrapper.getChannel());\n-                this.watchRequest = watchStub.watch(this);\n-            }\n-            this.watchRequest.onNext(nextRequest());\n-            this.throwable = null;\n-            logger.warn(\"watch client retried connect for path '\" + path + \"', connection status : \" + isConnected());\n-        }\n-\n-        protected void closeWatchRequest() {\n-            if (this.watchRequest == null) {\n-                return;\n-            }\n-\n-            try {\n-                WatchCancelRequest watchCancelRequest =\n-                        WatchCancelRequest.newBuilder().setWatchId(watchId).build();\n-                WatchRequest cancelRequest = WatchRequest.newBuilder()\n-                        .setCancelRequest(watchCancelRequest).build();\n-                watchRequest.onNext(cancelRequest);\n-            } finally {\n-                this.watchRequest.onCompleted();\n-                this.watchRequest = null;\n-            }\n-        }\n-\n-        @Override\n-        public void onCompleted() {\n-            // do not touch this method, if you want terminate this stream.\n-        }\n-    }\n-}\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+\r\n+package org.apache.dubbo.remoting.etcd.jetcd;\r\n+\r\n+import org.apache.dubbo.common.URL;\r\n+import org.apache.dubbo.common.logger.Logger;\r\n+import org.apache.dubbo.common.logger.LoggerFactory;\r\n+import org.apache.dubbo.common.utils.ExecutorUtil;\r\n+import org.apache.dubbo.common.utils.NamedThreadFactory;\r\n+import org.apache.dubbo.remoting.etcd.ChildListener;\r\n+import org.apache.dubbo.remoting.etcd.StateListener;\r\n+import org.apache.dubbo.remoting.etcd.option.OptionUtil;\r\n+import org.apache.dubbo.remoting.etcd.support.AbstractEtcdClient;\r\n+\r\n+import com.google.protobuf.ByteString;\r\n+import io.etcd.jetcd.ByteSequence;\r\n+import io.etcd.jetcd.api.Event;\r\n+import io.etcd.jetcd.api.KeyValue;\r\n+import io.etcd.jetcd.api.WatchCancelRequest;\r\n+import io.etcd.jetcd.api.WatchCreateRequest;\r\n+import io.etcd.jetcd.api.WatchGrpc;\r\n+import io.etcd.jetcd.api.WatchRequest;\r\n+import io.etcd.jetcd.api.WatchResponse;\r\n+import io.etcd.jetcd.common.exception.ClosedClientException;\r\n+import io.grpc.ManagedChannel;\r\n+import io.grpc.Status;\r\n+import io.grpc.stub.StreamObserver;\r\n+import io.netty.util.internal.ConcurrentSet;\r\n+\r\n+import java.util.ArrayList;\r\n+import java.util.Collections;\r\n+import java.util.Iterator;\r\n+import java.util.List;\r\n+import java.util.Random;\r\n+import java.util.Set;\r\n+import java.util.concurrent.ExecutionException;\r\n+import java.util.concurrent.ExecutorService;\r\n+import java.util.concurrent.Executors;\r\n+import java.util.concurrent.LinkedBlockingQueue;\r\n+import java.util.concurrent.ScheduledExecutorService;\r\n+import java.util.concurrent.ThreadPoolExecutor;\r\n+import java.util.concurrent.TimeUnit;\r\n+import java.util.concurrent.TimeoutException;\r\n+import java.util.concurrent.locks.ReentrantLock;\r\n+\r\n+import static java.util.stream.Collectors.toList;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR;\r\n+import static org.apache.dubbo.remoting.etcd.Constants.DEFAULT_ETCD3_NOTIFY_QUEUES_KEY;\r\n+import static org.apache.dubbo.remoting.etcd.Constants.DEFAULT_ETCD3_NOTIFY_THREADS;\r\n+import static org.apache.dubbo.remoting.etcd.Constants.DEFAULT_GRPC_QUEUES;\r\n+import static org.apache.dubbo.remoting.etcd.Constants.DEFAULT_RETRY_PERIOD;\r\n+import static org.apache.dubbo.remoting.etcd.Constants.DEFAULT_SESSION_TIMEOUT;\r\n+import static org.apache.dubbo.remoting.etcd.Constants.ETCD3_NOTIFY_MAXTHREADS_KEYS;\r\n+import static org.apache.dubbo.remoting.etcd.Constants.RETRY_PERIOD_KEY;\r\n+import static org.apache.dubbo.remoting.etcd.jetcd.JEtcdClientWrapper.UTF_8;\r\n+\r\n+/**\r\n+ * etcd3 client.\r\n+ */\r\n+public class JEtcdClient extends AbstractEtcdClient<JEtcdClient.EtcdWatcher> {\r\n+\r\n+    private JEtcdClientWrapper clientWrapper;\r\n+    private ScheduledExecutorService reconnectSchedule;\r\n+\r\n+    private ExecutorService notifyExecutor;\r\n+\r\n+    private int delayPeriod;\r\n+    private Logger logger = LoggerFactory.getLogger(JEtcdClient.class);\r\n+\r\n+    public JEtcdClient(URL url) {\r\n+        super(url);\r\n+        try {\r\n+            clientWrapper = new JEtcdClientWrapper(url);\r\n+            clientWrapper.setConnectionStateListener((client, state) -> {\r\n+                if (state == StateListener.CONNECTED) {\r\n+                    JEtcdClient.this.stateChanged(StateListener.CONNECTED);\r\n+                } else if (state == StateListener.DISCONNECTED) {\r\n+                    JEtcdClient.this.stateChanged(StateListener.DISCONNECTED);\r\n+                }\r\n+            });\r\n+            delayPeriod = getUrl().getParameter(RETRY_PERIOD_KEY, DEFAULT_RETRY_PERIOD);\r\n+            reconnectSchedule = Executors.newScheduledThreadPool(1,\r\n+                    new NamedThreadFactory(\"etcd3-watch-auto-reconnect\"));\r\n+\r\n+            notifyExecutor = new ThreadPoolExecutor(\r\n+                    1\r\n+                    , url.getParameter(ETCD3_NOTIFY_MAXTHREADS_KEYS, DEFAULT_ETCD3_NOTIFY_THREADS)\r\n+                    , DEFAULT_SESSION_TIMEOUT\r\n+                    , TimeUnit.MILLISECONDS\r\n+                    , new LinkedBlockingQueue<Runnable>(url.getParameter(DEFAULT_ETCD3_NOTIFY_QUEUES_KEY, DEFAULT_GRPC_QUEUES * 3))\r\n+                    , new NamedThreadFactory(\"etcd3-notify\", true));\r\n+\r\n+            clientWrapper.start();\r\n+        } catch (Exception e) {\r\n+            throw new IllegalStateException(e.getMessage(), e);\r\n+        }\r\n+    }\r\n+\r\n+    @Override\r\n+    public void doCreatePersistent(String path) {\r\n+        clientWrapper.createPersistent(path);\r\n+    }\r\n+\r\n+    @Override\r\n+    public long doCreateEphemeral(String path) {\r\n+        return clientWrapper.createEphemeral(path);\r\n+    }\r\n+\r\n+    @Override\r\n+    public boolean checkExists(String path) {\r\n+        return clientWrapper.checkExists(path);\r\n+    }\r\n+\r\n+    @Override\r\n+    public EtcdWatcher createChildWatcherListener(String path, ChildListener listener) {\r\n+        return new EtcdWatcher(listener);\r\n+    }\r\n+\r\n+    @Override\r\n+    public List<String> addChildWatcherListener(String path, EtcdWatcher etcdWatcher) {\r\n+        return etcdWatcher.forPath(path);\r\n+    }\r\n+\r\n+    @Override\r\n+    public void removeChildWatcherListener(String path, EtcdWatcher etcdWatcher) {\r\n+        etcdWatcher.unwatch();\r\n+    }\r\n+\r\n+    @Override\r\n+    public List<String> getChildren(String path) {\r\n+        return clientWrapper.getChildren(path);\r\n+    }\r\n+\r\n+    @Override\r\n+    public boolean isConnected() {\r\n+        return clientWrapper.isConnected();\r\n+    }\r\n+\r\n+    @Override\r\n+    public long createLease(long second) {\r\n+        return clientWrapper.createLease(second);\r\n+    }\r\n+\r\n+    @Override\r\n+    public long createLease(long ttl, long timeout, TimeUnit unit)\r\n+            throws InterruptedException, ExecutionException, TimeoutException {\r\n+        return clientWrapper.createLease(ttl, timeout, unit);\r\n+    }\r\n+\r\n+    @Override\r\n+    public void delete(String path) {\r\n+        clientWrapper.delete(path);\r\n+    }\r\n+\r\n+    @Override\r\n+    public void revokeLease(long lease) {\r\n+        clientWrapper.revokeLease(lease);\r\n+    }\r\n+\r\n+    @Override\r\n+    public void doClose() {\r\n+        try {\r\n+            if (notifyExecutor != null) {\r\n+                ExecutorUtil.shutdownNow(notifyExecutor, 100);\r\n+            }\r\n+        } catch (Exception e) {\r\n+            logger.warn(e.getMessage(), e);\r\n+        }\r\n+\r\n+        try {\r\n+            if (reconnectSchedule != null) {\r\n+                ExecutorUtil.shutdownNow(reconnectSchedule, 100);\r\n+            }\r\n+        } catch (Exception e) {\r\n+            logger.warn(e.getMessage(), e);\r\n+        } finally {\r\n+            clientWrapper.doClose();\r\n+        }\r\n+    }\r\n+\r\n+    @Override\r\n+    public String getKVValue(String key) {\r\n+        return clientWrapper.getKVValue(key);\r\n+    }\r\n+\r\n+    @Override\r\n+    public boolean put(String key, String value) {\r\n+        return clientWrapper.put(key, value);\r\n+    }\r\n+\r\n+    @Override\r\n+    public boolean putEphemeral(String key, String value) {\r\n+        return clientWrapper.putEphemeral(key, value);\r\n+    }\r\n+\r\n+    public ManagedChannel getChannel() {\r\n+        return clientWrapper.getChannel();\r\n+    }\r\n+\r\n+    public class EtcdWatcher implements StreamObserver<WatchResponse> {\r\n+\r\n+        protected WatchGrpc.WatchStub watchStub;\r\n+        protected StreamObserver<WatchRequest> watchRequest;\r\n+        protected long watchId;\r\n+        protected String path;\r\n+        protected Throwable throwable;\r\n+        protected volatile Set<String> urls = new ConcurrentSet<>();\r\n+        private ChildListener listener;\r\n+\r\n+        protected ReentrantLock lock = new ReentrantLock(true);\r\n+\r\n+        public EtcdWatcher(ChildListener listener) {\r\n+            this.listener = listener;\r\n+        }\r\n+\r\n+        @Override\r\n+        public void onNext(WatchResponse response) {\r\n+\r\n+            // prevents grpc on sending watchResponse to a closed watch client.\r\n+            if (!isConnected()) {\r\n+                return;\r\n+            }\r\n+\r\n+            watchId = response.getWatchId();\r\n+\r\n+            if (listener != null) {\r\n+                int modified = 0;\r\n+                String service = null;\r\n+                Iterator<Event> iterator = response.getEventsList().iterator();\r\n+                while (iterator.hasNext()) {\r\n+                    Event event = iterator.next();\r\n+                    switch (event.getType()) {\r\n+                        case PUT: {\r\n+                            if (((service = find(event)) != null)\r\n+                                    && safeUpdate(service, true)) {\r\n+                                modified++;\r\n+                            }\r\n+                            break;\r\n+                        }\r\n+                        case DELETE: {\r\n+                            if (((service = find(event)) != null)\r\n+                                    && safeUpdate(service, false)) {\r\n+                                modified++;\r\n+                            }\r\n+                            break;\r\n+                        }\r\n+                        default:\r\n+                            break;\r\n+                    }\r\n+                }\r\n+                if (modified > 0) {\r\n+                    notifyExecutor.execute(() -> listener.childChanged(path, new ArrayList<>(urls)));\r\n+                }\r\n+\r\n+            }\r\n+        }\r\n+\r\n+        @Override\r\n+        public void onError(Throwable e) {\r\n+            tryReconnect(e);\r\n+        }\r\n+\r\n+        public void unwatch() {\r\n+\r\n+            // prevents grpc on sending watchResponse to a closed watch client.\r\n+            if (!isConnected()) {\r\n+                return;\r\n+            }\r\n+\r\n+            try {\r\n+                /**\r\n+                 * issue : https://github.com/apache/dubbo/issues/4115\r\n+                 *\r\n+                 * When the network is reconnected, the listener is empty\r\n+                 * and the data cannot be received.\r\n+                 */\r\n+                // this.listener = null;\r\n+\r\n+                if (watchRequest != null) {\r\n+                    WatchCancelRequest watchCancelRequest =\r\n+                            WatchCancelRequest.newBuilder().setWatchId(watchId).build();\r\n+                    WatchRequest cancelRequest = WatchRequest.newBuilder()\r\n+                            .setCancelRequest(watchCancelRequest).build();\r\n+                    this.watchRequest.onNext(cancelRequest);\r\n+                }\r\n+            } catch (Exception ignored) {\r\n+                logger.warn(\"Failed to cancel watch for path '\" + path + \"'\", ignored);\r\n+            }\r\n+        }\r\n+\r\n+        public List<String> forPath(String path) {\r\n+\r\n+            if (!isConnected()) {\r\n+                throw new ClosedClientException(\"watch client has been closed, path '\" + path + \"'\");\r\n+            }\r\n+            if (this.path != null) {\r\n+                unwatch();\r\n+            }\r\n+\r\n+            this.path = path;\r\n+\r\n+            lock.lock();\r\n+            try {\r\n+\r\n+                this.watchStub = WatchGrpc.newStub(clientWrapper.getChannel());\r\n+                this.watchRequest = watchStub.watch(this);\r\n+                this.watchRequest.onNext(nextRequest());\r\n+\r\n+                List<String> children = clientWrapper.getChildren(path);\r\n+                /**\r\n+                 * caching the current service\r\n+                 */\r\n+                if (!children.isEmpty()) {\r\n+                    this.urls.addAll(filterChildren(children));\r\n+                }\r\n+\r\n+                return new ArrayList<>(urls);\r\n+            } finally {\r\n+                lock.unlock();\r\n+            }\r\n+        }\r\n+\r\n+        private boolean safeUpdate(String service, boolean add) {\r\n+            lock.lock();\r\n+            try {\r\n+                /**\r\n+                 * If the collection already contains the specified service, do nothing\r\n+                 */\r\n+                return add ? this.urls.add(service) : this.urls.remove(service);\r\n+            } finally {\r\n+                lock.unlock();\r\n+            }\r\n+        }\r\n+\r\n+        private String find(Event event) {\r\n+            KeyValue keyValue = event.getKv();\r\n+            String key = keyValue.getKey().toStringUtf8();\r\n+\r\n+            int len = path.length(), index = len, count = 0;\r\n+            if (key.length() >= index) {\r\n+                for (; (index = key.indexOf(PATH_SEPARATOR, index)) != -1; ++index) {\r\n+                    if (count++ > 1) {\r\n+                        break;\r\n+                    }\r\n+                }\r\n+            }\r\n+\r\n+            /**\r\n+             * if children changed , we should refresh invokers\r\n+             */\r\n+            if (count == 1) {\r\n+                /**\r\n+                 * remove prefix\r\n+                 */\r\n+                return key.substring(len + 1);\r\n+            }\r\n+\r\n+            return null;\r\n+        }\r\n+\r\n+        private List<String> filterChildren(List<String> children) {\r\n+            if (children == null) {\r\n+                return Collections.emptyList();\r\n+            }\r\n+            if (children.size() <= 0) {\r\n+                return children;\r\n+            }\r\n+            final int len = path.length();\r\n+            return children.stream().parallel()\r\n+                    .filter(child -> {\r\n+                        int index = len, count = 0;\r\n+                        if (child.length() > len) {\r\n+                            for (; (index = child.indexOf(PATH_SEPARATOR, index)) != -1; ++index) {\r\n+                                if (count++ > 1) {\r\n+                                    break;\r\n+                                }\r\n+                            }\r\n+                        }\r\n+                        return count == 1;\r\n+                    })\r\n+                    .map(child -> child.substring(len + 1))\r\n+                    .collect(toList());\r\n+        }\r\n+\r\n+        /**\r\n+         * create new watching request for current path.\r\n+         */\r\n+        protected WatchRequest nextRequest() {\r\n+\r\n+            WatchCreateRequest.Builder builder = WatchCreateRequest.newBuilder()\r\n+                    .setKey(ByteString.copyFromUtf8(path))\r\n+                    .setRangeEnd(ByteString.copyFrom(\r\n+                            OptionUtil.prefixEndOf(ByteSequence.from(path, UTF_8)).getBytes()))\r\n+                    .setProgressNotify(true);\r\n+\r\n+            return WatchRequest.newBuilder().setCreateRequest(builder).build();\r\n+        }\r\n+\r\n+        public void tryReconnect(Throwable e) {\r\n+\r\n+            this.throwable = e;\r\n+\r\n+            logger.error(\"watcher client has error occurred, current path '\" + path + \"'\", e);\r\n+\r\n+            // prevents grpc on sending error to a closed watch client.\r\n+            if (!isConnected()) {\r\n+                return;\r\n+            }\r\n+\r\n+\r\n+            Status status = Status.fromThrowable(e);\r\n+            // system may be recover later, current connect won't be lost\r\n+            if (OptionUtil.isHaltError(status) || OptionUtil.isNoLeaderError(status)) {\r\n+                reconnectSchedule.schedule(this::reconnect, new Random().nextInt(delayPeriod), TimeUnit.MILLISECONDS);\r\n+                return;\r\n+            }\r\n+            // reconnect with a delay; avoiding immediate retry on a long connection downtime.\r\n+            reconnectSchedule.schedule(this::reconnect, new Random().nextInt(delayPeriod), TimeUnit.MILLISECONDS);\r\n+        }\r\n+\r\n+        protected synchronized void reconnect() {\r\n+            this.closeWatchRequest();\r\n+            this.recreateWatchRequest();\r\n+        }\r\n+\r\n+        protected void recreateWatchRequest() {\r\n+            if (watchRequest == null) {\r\n+                this.watchStub = WatchGrpc.newStub(clientWrapper.getChannel());\r\n+                this.watchRequest = watchStub.watch(this);\r\n+            }\r\n+            this.watchRequest.onNext(nextRequest());\r\n+            this.throwable = null;\r\n+            logger.warn(\"watch client retried connect for path '\" + path + \"', connection status : \" + isConnected());\r\n+        }\r\n+\r\n+        protected void closeWatchRequest() {\r\n+            if (this.watchRequest == null) {\r\n+                return;\r\n+            }\r\n+\r\n+            try {\r\n+                WatchCancelRequest watchCancelRequest =\r\n+                        WatchCancelRequest.newBuilder().setWatchId(watchId).build();\r\n+                WatchRequest cancelRequest = WatchRequest.newBuilder()\r\n+                        .setCancelRequest(watchCancelRequest).build();\r\n+                watchRequest.onNext(cancelRequest);\r\n+            } finally {\r\n+                this.watchRequest.onCompleted();\r\n+                this.watchRequest = null;\r\n+            }\r\n+        }\r\n+\r\n+        @Override\r\n+        public void onCompleted() {\r\n+            // do not touch this method, if you want terminate this stream.\r\n+        }\r\n+    }\r\n+}\r\n"}, {"source1": "org/apache/dubbo/remoting/etcd/jetcd/JEtcdClientWrapper.java", "source2": "org/apache/dubbo/remoting/etcd/jetcd/JEtcdClientWrapper.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,752 +1,752 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-package org.apache.dubbo.remoting.etcd.jetcd;\n-\n-import org.apache.dubbo.common.URL;\n-import org.apache.dubbo.common.logger.Logger;\n-import org.apache.dubbo.common.logger.LoggerFactory;\n-import org.apache.dubbo.common.utils.ConcurrentHashSet;\n-import org.apache.dubbo.common.utils.NamedThreadFactory;\n-import org.apache.dubbo.common.utils.ReflectUtils;\n-import org.apache.dubbo.common.utils.StringUtils;\n-import org.apache.dubbo.remoting.etcd.RetryPolicy;\n-import org.apache.dubbo.remoting.etcd.StateListener;\n-\n-import io.etcd.jetcd.ByteSequence;\n-import io.etcd.jetcd.Client;\n-import io.etcd.jetcd.ClientBuilder;\n-import io.etcd.jetcd.KeyValue;\n-import io.etcd.jetcd.common.exception.ErrorCode;\n-import io.etcd.jetcd.common.exception.EtcdException;\n-import io.etcd.jetcd.kv.GetResponse;\n-import io.etcd.jetcd.kv.PutResponse;\n-import io.etcd.jetcd.lease.LeaseKeepAliveResponse;\n-import io.etcd.jetcd.options.GetOption;\n-import io.etcd.jetcd.options.PutOption;\n-import io.etcd.jetcd.support.CloseableClient;\n-import io.etcd.jetcd.support.Observers;\n-import io.grpc.ConnectivityState;\n-import io.grpc.ManagedChannel;\n-import io.grpc.Status;\n-import io.grpc.stub.StreamObserver;\n-\n-import java.lang.reflect.Field;\n-import java.lang.reflect.Method;\n-import java.nio.charset.Charset;\n-import java.nio.charset.StandardCharsets;\n-import java.util.Arrays;\n-import java.util.Collections;\n-import java.util.HashSet;\n-import java.util.List;\n-import java.util.Set;\n-import java.util.concurrent.Callable;\n-import java.util.concurrent.CompletableFuture;\n-import java.util.concurrent.ExecutionException;\n-import java.util.concurrent.Executors;\n-import java.util.concurrent.ScheduledExecutorService;\n-import java.util.concurrent.ScheduledFuture;\n-import java.util.concurrent.TimeUnit;\n-import java.util.concurrent.TimeoutException;\n-import java.util.concurrent.atomic.AtomicReference;\n-import java.util.function.Consumer;\n-\n-import static java.util.stream.Collectors.toList;\n-import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR;\n-import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR;\n-import static org.apache.dubbo.remoting.etcd.Constants.DEFAULT_KEEPALIVE_TIMEOUT;\n-import static org.apache.dubbo.remoting.etcd.Constants.DEFAULT_RECONNECT_PERIOD;\n-import static org.apache.dubbo.remoting.etcd.Constants.DEFAULT_RETRY_PERIOD;\n-import static org.apache.dubbo.remoting.etcd.Constants.HTTP_KEY;\n-import static org.apache.dubbo.remoting.etcd.Constants.HTTP_SUBFIX_KEY;\n-import static org.apache.dubbo.remoting.etcd.Constants.RETRY_PERIOD_KEY;\n-import static org.apache.dubbo.remoting.etcd.Constants.SESSION_TIMEOUT_KEY;\n-\n-public class JEtcdClientWrapper {\n-\n-    private Logger logger = LoggerFactory.getLogger(JEtcdClientWrapper.class);\n-\n-    private final URL url;\n-    private volatile Client client;\n-    private volatile boolean started = false;\n-    private volatile boolean connectState = false;\n-    private ScheduledFuture future;\n-    private ScheduledExecutorService reconnectNotify;\n-    private AtomicReference<ManagedChannel> channel;\n-\n-    private ConnectionStateListener connectionStateListener;\n-\n-    private long expirePeriod;\n-\n-    private CompletableFuture<Client> completableFuture;\n-\n-    private RetryPolicy retryPolicy;\n-\n-    private RuntimeException failed;\n-\n-    private final ScheduledFuture<?> retryFuture;\n-    private final ScheduledExecutorService retryExecutor = Executors.newScheduledThreadPool(1,\n-            new NamedThreadFactory(\"Etcd3RegistryKeepAliveFailedRetryTimer\", true));\n-\n-    private final Set<String> failedRegistered = new ConcurrentHashSet<String>();\n-\n-    private final Set<String> registeredPaths = new ConcurrentHashSet<>();\n-    private volatile CloseableClient keepAlive = null;\n-\n-    /**\n-     * Support temporary nodes to reuse the same lease\n-     */\n-    private volatile long globalLeaseId;\n-\n-    private volatile boolean cancelKeepAlive = false;\n-\n-    public static final Charset UTF_8 = StandardCharsets.UTF_8;\n-\n-    public JEtcdClientWrapper(URL url) {\n-        this.url = url;\n-        this.expirePeriod = url.getParameter(SESSION_TIMEOUT_KEY, DEFAULT_KEEPALIVE_TIMEOUT) / 1000;\n-        if (expirePeriod <= 0) {\n-            this.expirePeriod = DEFAULT_KEEPALIVE_TIMEOUT / 1000;\n-        }\n-        this.channel = new AtomicReference<>();\n-        this.completableFuture = CompletableFuture.supplyAsync(() -> prepareClient(url));\n-        this.reconnectNotify = Executors.newScheduledThreadPool(1,\n-                new NamedThreadFactory(\"reconnectNotify\", true));\n-        this.retryPolicy = new RetryNTimes(1, 1000, TimeUnit.MILLISECONDS);\n-\n-        this.failed = new IllegalStateException(\"Etcd3 registry is not connected yet, url:\" + url);\n-        int retryPeriod = url.getParameter(RETRY_PERIOD_KEY, DEFAULT_RETRY_PERIOD);\n-\n-        this.retryFuture = retryExecutor.scheduleWithFixedDelay(() -> {\n-            try {\n-                retry();\n-            } catch (Throwable t) {\n-                logger.error(\"Unexpected error occur at failed retry, cause: \" + t.getMessage(), t);\n-            }\n-        }, retryPeriod, retryPeriod, TimeUnit.MILLISECONDS);\n-    }\n-\n-    private Client prepareClient(URL url) {\n-\n-        int maxInboundSize = DEFAULT_INBOUND_SIZE;\n-        if (StringUtils.isNotEmpty(System.getProperty(GRPC_MAX_INBOUND_SIZE_KEY))) {\n-            maxInboundSize = Integer.valueOf(System.getProperty(GRPC_MAX_INBOUND_SIZE_KEY));\n-        }\n-\n-        // TODO, uses default pick-first round robin.\n-        ClientBuilder clientBuilder = Client.builder()\n-                .endpoints(endPoints(url.getBackupAddress()))\n-                .maxInboundMessageSize(maxInboundSize);\n-\n-        return clientBuilder.build();\n-    }\n-\n-    public Client getClient() {\n-        return client;\n-    }\n-\n-    /**\n-     * try to get current connected channel.\n-     *\n-     * @return connected channel.\n-     */\n-    public ManagedChannel getChannel() {\n-        if (channel.get() == null || (channel.get().isShutdown() || channel.get().isTerminated())) {\n-            channel.set(newChannel(client));\n-        }\n-        return channel.get();\n-    }\n-\n-    /**\n-     * find direct children directory, excluding path self,\n-     * Never return null.\n-     *\n-     * @param path the path to be found direct children.\n-     * @return direct children directory, contains zero element\n-     * list if children directory not exists.\n-     */\n-    public List<String> getChildren(String path) {\n-        try {\n-            return RetryLoops.invokeWithRetry(\n-                    () -> {\n-                        requiredNotNull(client, failed);\n-                        int len = path.length();\n-                        return client.getKVClient()\n-                                .get(ByteSequence.from(path, UTF_8),\n-                                        GetOption.newBuilder().withPrefix(ByteSequence.from(path, UTF_8)).build())\n-                                .get(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS)\n-                                .getKvs().stream().parallel()\n-                                .filter(pair -> {\n-                                    String key = pair.getKey().toString(UTF_8);\n-                                    int index = len, count = 0;\n-                                    if (key.length() > len) {\n-                                        for (; (index = key.indexOf(PATH_SEPARATOR, index)) != -1; ++index) {\n-                                            if (count++ > 1) {\n-                                                break;\n-                                            }\n-                                        }\n-                                    }\n-                                    return count == 1;\n-                                })\n-                                .map(pair -> pair.getKey().toString(UTF_8))\n-                                .collect(toList());\n-                    }, retryPolicy);\n-        } catch (Exception e) {\n-            throw new IllegalStateException(e.getMessage(), e);\n-        }\n-    }\n-\n-    public boolean isConnected() {\n-        return ConnectivityState.READY == (getChannel().getState(false))\n-                || ConnectivityState.IDLE == (getChannel().getState(false));\n-    }\n-\n-    public long createLease(long second) {\n-        try {\n-            return RetryLoops.invokeWithRetry(\n-                    () -> {\n-                        requiredNotNull(client, failed);\n-                        return client.getLeaseClient()\n-                                .grant(second)\n-                                .get(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS)\n-                                .getID();\n-                    }, retryPolicy);\n-        } catch (Exception e) {\n-            throw new IllegalStateException(e.getMessage(), e);\n-        }\n-    }\n-\n-    public void revokeLease(long lease) {\n-        try {\n-            RetryLoops.invokeWithRetry(\n-                    (Callable<Void>) () -> {\n-                        requiredNotNull(client, failed);\n-                        client.getLeaseClient()\n-                                .revoke(lease)\n-                                .get(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS);\n-                        return null;\n-                    }, retryPolicy);\n-        } catch (Exception e) {\n-            throw new IllegalStateException(e.getMessage(), e);\n-        }\n-    }\n-\n-    public long createLease(long ttl, long timeout, TimeUnit unit)\n-            throws InterruptedException, ExecutionException, TimeoutException {\n-\n-        if (timeout <= 0) {\n-            return createLease(ttl);\n-        }\n-\n-        requiredNotNull(client, failed);\n-        return client.getLeaseClient()\n-                .grant(ttl)\n-                .get(timeout, unit).getID();\n-    }\n-\n-\n-    /**\n-     * try to check if path exists.\n-     */\n-    public boolean checkExists(String path) {\n-        try {\n-            return RetryLoops.invokeWithRetry(\n-                    () -> {\n-                        requiredNotNull(client, failed);\n-                        return client.getKVClient()\n-                                .get(ByteSequence.from(path, UTF_8), GetOption.newBuilder().withCountOnly(true).build())\n-                                .get(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS)\n-                                .getCount() > 0;\n-                    }, retryPolicy);\n-        } catch (Exception e) {\n-            throw new IllegalStateException(e.getMessage(), e);\n-        }\n-    }\n-\n-    /**\n-     * only internal use only, maybe change in the future\n-     */\n-    protected Long find(String path) {\n-        try {\n-            return RetryLoops.invokeWithRetry(\n-                    () -> {\n-                        requiredNotNull(client, failed);\n-                        return client.getKVClient()\n-                                .get(ByteSequence.from(path, UTF_8))\n-                                .get(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS)\n-                                .getKvs().stream()\n-                                .mapToLong(keyValue -> Long.valueOf(keyValue.getValue().toString(UTF_8)))\n-                                .findFirst().getAsLong();\n-                    }, retryPolicy);\n-        } catch (Exception e) {\n-            throw new IllegalStateException(e.getMessage(), e);\n-        }\n-    }\n-\n-    public void createPersistent(String path) {\n-        try {\n-            RetryLoops.invokeWithRetry(\n-                    (Callable<Void>) () -> {\n-                        requiredNotNull(client, failed);\n-                        client.getKVClient()\n-                                .put(ByteSequence.from(path, UTF_8),\n-                                        ByteSequence.from(String.valueOf(path.hashCode()), UTF_8))\n-                                .get(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS);\n-                        return null;\n-                    }, retryPolicy);\n-        } catch (Exception e) {\n-            throw new IllegalStateException(e.getMessage(), e);\n-        }\n-    }\n-\n-    /**\n-     * create new ephemeral path save to etcd .\n-     * if node disconnect from etcd, it will be deleted\n-     * automatically by etcd when session timeout.\n-     *\n-     * @param path the path to be saved\n-     * @return the lease of current path.\n-     */\n-    public long createEphemeral(String path) {\n-        try {\n-            return RetryLoops.invokeWithRetry(\n-                    () -> {\n-                        requiredNotNull(client, failed);\n-\n-                        registeredPaths.add(path);\n-                        keepAlive();\n-                        final long leaseId = globalLeaseId;\n-                        client.getKVClient()\n-                                .put(ByteSequence.from(path, UTF_8)\n-                                        , ByteSequence.from(String.valueOf(leaseId), UTF_8)\n-                                        , PutOption.newBuilder().withLeaseId(leaseId).build())\n-                                .get(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS);\n-                        return leaseId;\n-                    }, retryPolicy);\n-        } catch (Exception e) {\n-            throw new IllegalStateException(e.getMessage(), e);\n-        }\n-    }\n-\n-    // easy for mock\n-    public void keepAlive(long lease) {\n-        this.keepAlive(lease, null);\n-    }\n-\n-    @SuppressWarnings(\"unchecked\")\n-    private <T> void keepAlive(long lease, Consumer<T> onFailed) {\n-        final StreamObserver<LeaseKeepAliveResponse> observer = new Observers.Builder()\n-                .onError((e) -> {\n-                    if (e instanceof EtcdException) {\n-                        EtcdException error = (EtcdException) e;\n-                        /**\n-                         * ttl has expired\n-                         */\n-                        if (error.getErrorCode() == ErrorCode.NOT_FOUND) {\n-                            keepAlive0(onFailed);\n-                        }\n-                    }\n-                }).onCompleted(() -> {\n-                    /**\n-                     * deadline reached.\n-                     */\n-                    keepAlive0(onFailed);\n-                }).build();\n-\n-        /**\n-         * If there is already a keepalive, cancel first\n-         */\n-        cancelKeepAlive();\n-\n-        /**\n-         * create and set new keepAlive to globalKeepAliveRef\n-         */\n-        this.keepAlive = client.getLeaseClient().keepAlive(lease, observer);\n-    }\n-\n-    private void keepAlive() throws Exception {\n-        if (keepAlive == null) {\n-            synchronized (this) {\n-                if (keepAlive == null) {\n-                    this.globalLeaseId = client.getLeaseClient()\n-                            .grant(expirePeriod)\n-                            .get(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS)\n-                            .getID();\n-                    /**\n-                     * If the keepAlive expires, the registration will be re-attempted\n-                     */\n-                    keepAlive(globalLeaseId, (NULL) -> recovery());\n-                }\n-            }\n-        }\n-    }\n-\n-    private <T> void keepAlive0(Consumer<T> onFailed) {\n-        if (onFailed != null) {\n-\n-            /**\n-             * The following two scenarios will cause the keep-alive failure\uff1a\n-             *\n-             * 1. Service is offline\n-             * 2. Local deadline check expired\n-             *\n-             * The multiplex lease cannot update the local deadline,\n-             * causing the extreme scene service to be dropped.\n-             *\n-             */\n-            long leaseId = globalLeaseId;\n-            try {\n-                if (logger.isWarnEnabled()) {\n-                    logger.warn(\"Failed to keep alive for global lease '\" + leaseId + \"', waiting for retry again.\");\n-                }\n-                onFailed.accept(null);\n-            } catch (Exception ignored) {\n-                logger.warn(\"Failed to recover from global lease expired or lease deadline exceeded. lease '\" + leaseId + \"'\", ignored);\n-            }\n-        }\n-    }\n-\n-    private void recovery() {\n-\n-        try {\n-            /**\n-             * The client is processing reconnection\n-             */\n-            if (cancelKeepAlive) {\n-                return;\n-            }\n-\n-            cancelKeepAlive();\n-\n-            Set<String> ephemeralPaths = new HashSet<String>(registeredPaths);\n-            if (!ephemeralPaths.isEmpty()) {\n-                for (String path : ephemeralPaths) {\n-                    try {\n-\n-                        /**\n-                         * The client is processing reconnection,\n-                         * cancel remaining service registration\n-                         */\n-                        if (cancelKeepAlive) {\n-                            return;\n-                        }\n-\n-                        createEphemeral(path);\n-                        failedRegistered.remove(path);\n-                    } catch (Exception e) {\n-\n-                        /**\n-                         * waiting for retry again\n-                         */\n-                        failedRegistered.add(path);\n-\n-                        Status status = Status.fromThrowable(e);\n-                        if (status.getCode() == Status.Code.NOT_FOUND) {\n-                            cancelKeepAlive();\n-                        }\n-                    }\n-                }\n-            }\n-        } catch (Throwable t) {\n-            logger.warn(\"Unexpected error, failed to recover from global lease expired or deadline exceeded.\", t);\n-        }\n-    }\n-\n-    public void delete(String path) {\n-        try {\n-            RetryLoops.invokeWithRetry(\n-                    (Callable<Void>) () -> {\n-                        requiredNotNull(client, failed);\n-                        client.getKVClient()\n-                                .delete(ByteSequence.from(path, UTF_8))\n-                                .get(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS);\n-                        registeredPaths.remove(path);\n-                        return null;\n-                    }, retryPolicy);\n-        } catch (Exception e) {\n-            throw new IllegalStateException(e.getMessage(), e);\n-        } finally {\n-            /**\n-             * Cancel retry\n-             */\n-            failedRegistered.remove(path);\n-        }\n-    }\n-\n-    public String[] endPoints(String backupAddress) {\n-        String[] endpoints = backupAddress.split(COMMA_SEPARATOR);\n-        List<String> addresses = Arrays.stream(endpoints)\n-                .map(address -> address.contains(HTTP_SUBFIX_KEY)\n-                        ? address\n-                        : HTTP_KEY + address)\n-                .collect(toList());\n-        Collections.shuffle(addresses);\n-        return addresses.toArray(new String[0]);\n-    }\n-\n-    /**\n-     * because jetcd's connection change callback not supported yet, we must\n-     * loop to test if connect or disconnect event happened or not. It will be changed\n-     * in the future if we found better choice.\n-     */\n-    public void start() {\n-        if (!started) {\n-            try {\n-                this.client = completableFuture.get(expirePeriod, TimeUnit.SECONDS);\n-                this.connectState = isConnected();\n-                this.started = true;\n-            } catch (Throwable t) {\n-                logger.error(\"Timeout! etcd3 server can not be connected in : \" + expirePeriod + \" seconds! url: \" + url, t);\n-\n-                completableFuture.whenComplete((c, e) -> {\n-                    this.client = c;\n-                    if (e != null) {\n-                        logger.error(\"Got an exception when trying to create etcd3 instance, can not connect to etcd3 server, url: \" + url, e);\n-                    }\n-                });\n-\n-            }\n-\n-            try {\n-                this.future = reconnectNotify.scheduleWithFixedDelay(() -> {\n-                    boolean connected = isConnected();\n-                    if (connectState != connected) {\n-                        int notifyState = connected ? StateListener.CONNECTED : StateListener.DISCONNECTED;\n-                        if (connectionStateListener != null) {\n-                            try {\n-                                if (connected) {\n-                                    clearKeepAlive();\n-                                }\n-                                connectionStateListener.stateChanged(getClient(), notifyState);\n-                            } finally {\n-                                cancelKeepAlive = false;\n-                            }\n-                        }\n-                        connectState = connected;\n-                    }\n-                }, DEFAULT_RECONNECT_PERIOD, DEFAULT_RECONNECT_PERIOD, TimeUnit.MILLISECONDS);\n-            } catch (Throwable t) {\n-                logger.error(\"monitor reconnect status failed.\", t);\n-            }\n-        }\n-    }\n-\n-    private void cancelKeepAlive() {\n-        try {\n-            if (keepAlive != null) {\n-                keepAlive.close();\n-            }\n-        } finally {\n-            // help for gc\n-            keepAlive = null;\n-        }\n-    }\n-\n-    private void clearKeepAlive() {\n-        cancelKeepAlive = true;\n-        failedRegistered.clear();\n-        cancelKeepAlive();\n-    }\n-\n-    protected void doClose() {\n-\n-        try {\n-            cancelKeepAlive = true;\n-            if (globalLeaseId != 0) {\n-                revokeLease(this.globalLeaseId);\n-            }\n-        } catch (Exception e) {\n-            logger.warn(\"revoke global lease '\" + globalLeaseId + \"' failed, registry: \" + url, e);\n-        }\n-\n-        try {\n-            if (started && future != null) {\n-                started = false;\n-                future.cancel(true);\n-                reconnectNotify.shutdownNow();\n-            }\n-        } catch (Exception e) {\n-            logger.warn(\"stop reconnect Notify failed, registry: \" + url, e);\n-        }\n-\n-        try {\n-            retryFuture.cancel(true);\n-            retryExecutor.shutdownNow();\n-        } catch (Throwable t) {\n-            logger.warn(t.getMessage(), t);\n-        }\n-\n-        if (getClient() != null) {\n-            getClient().close();\n-        }\n-    }\n-\n-    /**\n-     * try get client's shared channel, because all fields is private on jetcd,\n-     * we must using it by reflect, in the future, jetcd may provider better tools.\n-     *\n-     * @param client get channel from current client\n-     * @return current connection channel\n-     */\n-    private ManagedChannel newChannel(Client client) {\n-        try {\n-            Field connectionField = client.getClass().getDeclaredField(\"connectionManager\");\n-            ReflectUtils.makeAccessible(connectionField);\n-            Object connection = connectionField.get(client);\n-            Method channel = connection.getClass().getDeclaredMethod(\"getChannel\");\n-            ReflectUtils.makeAccessible(channel);\n-            return (ManagedChannel) channel.invoke(connection);\n-        } catch (Exception e) {\n-            throw new RuntimeException(\"Failed to obtain connection channel from \" + url.getBackupAddress(), e);\n-        }\n-    }\n-\n-    public ConnectionStateListener getConnectionStateListener() {\n-        return connectionStateListener;\n-    }\n-\n-    public void setConnectionStateListener(ConnectionStateListener connectionStateListener) {\n-        this.connectionStateListener = connectionStateListener;\n-    }\n-\n-    public static void requiredNotNull(Object obj, RuntimeException exception) {\n-        if (obj == null) {\n-            throw exception;\n-        }\n-    }\n-\n-    public String getKVValue(String key) {\n-        if (null == key) {\n-            return null;\n-        }\n-\n-        CompletableFuture<GetResponse> responseFuture = this.client.getKVClient().get(ByteSequence.from(key, UTF_8));\n-\n-        try {\n-            List<KeyValue> result = responseFuture.get(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS).getKvs();\n-            if (!result.isEmpty()) {\n-                return result.get(0).getValue().toString(UTF_8);\n-            }\n-        } catch (Exception e) {\n-            // ignore\n-        }\n-\n-        return null;\n-    }\n-\n-\n-    public boolean put(String key, String value) {\n-        if (key == null || value == null) {\n-            return false;\n-        }\n-        CompletableFuture<PutResponse> putFuture =\n-                this.client.getKVClient().put(ByteSequence.from(key, UTF_8), ByteSequence.from(value, UTF_8));\n-        try {\n-            putFuture.get(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS);\n-            return true;\n-        } catch (Exception e) {\n-            // ignore\n-        }\n-        return false;\n-    }\n-\n-    public boolean putEphemeral(final String key, String value) {\n-        try {\n-            return RetryLoops.invokeWithRetry(\n-                    () -> {\n-                        requiredNotNull(client, failed);\n-                        // recovery an retry\n-                        keepAlive();\n-                        final long leaseId = globalLeaseId;\n-                        client.getKVClient()\n-                                .put(ByteSequence.from(key, UTF_8)\n-                                        , ByteSequence.from(String.valueOf(value), UTF_8)\n-                                        , PutOption.newBuilder().withLeaseId(leaseId).build())\n-                                .get(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS);\n-                        return true;\n-                    }, retryPolicy);\n-        } catch (Exception e) {\n-            throw new IllegalStateException(e.getMessage(), e);\n-        }\n-    }\n-\n-    private void retry() {\n-        if (!failedRegistered.isEmpty()) {\n-            Set<String> failed = new HashSet<String>(failedRegistered);\n-            if (!failed.isEmpty()) {\n-\n-                if (cancelKeepAlive) {\n-                    return;\n-                }\n-\n-                if (logger.isWarnEnabled()) {\n-                    logger.warn(\"Retry failed register(keep alive) for path '\" + failed\n-                            + \"', path size: \" + failed.size());\n-                }\n-                try {\n-                    for (String path : failed) {\n-                        try {\n-\n-                            /**\n-                             * Is it currently reconnecting ?\n-                             */\n-                            if (cancelKeepAlive) {\n-                                return;\n-                            }\n-\n-                            createEphemeral(path);\n-                            failedRegistered.remove(path);\n-                        } catch (Throwable e) {\n-\n-                            failedRegistered.add(path);\n-\n-                            Status status = Status.fromThrowable(e);\n-                            if (status.getCode() == Status.Code.NOT_FOUND) {\n-                                cancelKeepAlive();\n-                            }\n-\n-                            logger.warn(\"Failed to retry register(keep alive) for path '\" + path + \"', waiting for again, cause: \" + e.getMessage(), e);\n-                        }\n-                    }\n-                } catch (Throwable t) {\n-                    logger.warn(\"Failed to retry register(keep alive) for path '\" + failed + \"', waiting for again, cause: \" + t.getMessage(), t);\n-                }\n-            }\n-        }\n-    }\n-\n-    /**\n-     * default request timeout\n-     */\n-    public static final long DEFAULT_REQUEST_TIMEOUT = obtainRequestTimeout();\n-\n-    public static final int DEFAULT_INBOUND_SIZE = 100 * 1024 * 1024;\n-\n-    public static final String GRPC_MAX_INBOUND_SIZE_KEY = \"grpc.max.inbound.size\";\n-\n-    public static final String ETCD_REQUEST_TIMEOUT_KEY = \"etcd.request.timeout\";\n-\n-    private static int obtainRequestTimeout() {\n-        if (StringUtils.isNotEmpty(System.getProperty(ETCD_REQUEST_TIMEOUT_KEY))) {\n-            return Integer.valueOf(System.getProperty(ETCD_REQUEST_TIMEOUT_KEY));\n-        }\n-        /**\n-         * 10 seconds.\n-         */\n-        return 10 * 1000;\n-    }\n-}\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+\r\n+package org.apache.dubbo.remoting.etcd.jetcd;\r\n+\r\n+import org.apache.dubbo.common.URL;\r\n+import org.apache.dubbo.common.logger.Logger;\r\n+import org.apache.dubbo.common.logger.LoggerFactory;\r\n+import org.apache.dubbo.common.utils.ConcurrentHashSet;\r\n+import org.apache.dubbo.common.utils.NamedThreadFactory;\r\n+import org.apache.dubbo.common.utils.ReflectUtils;\r\n+import org.apache.dubbo.common.utils.StringUtils;\r\n+import org.apache.dubbo.remoting.etcd.RetryPolicy;\r\n+import org.apache.dubbo.remoting.etcd.StateListener;\r\n+\r\n+import io.etcd.jetcd.ByteSequence;\r\n+import io.etcd.jetcd.Client;\r\n+import io.etcd.jetcd.ClientBuilder;\r\n+import io.etcd.jetcd.KeyValue;\r\n+import io.etcd.jetcd.common.exception.ErrorCode;\r\n+import io.etcd.jetcd.common.exception.EtcdException;\r\n+import io.etcd.jetcd.kv.GetResponse;\r\n+import io.etcd.jetcd.kv.PutResponse;\r\n+import io.etcd.jetcd.lease.LeaseKeepAliveResponse;\r\n+import io.etcd.jetcd.options.GetOption;\r\n+import io.etcd.jetcd.options.PutOption;\r\n+import io.etcd.jetcd.support.CloseableClient;\r\n+import io.etcd.jetcd.support.Observers;\r\n+import io.grpc.ConnectivityState;\r\n+import io.grpc.ManagedChannel;\r\n+import io.grpc.Status;\r\n+import io.grpc.stub.StreamObserver;\r\n+\r\n+import java.lang.reflect.Field;\r\n+import java.lang.reflect.Method;\r\n+import java.nio.charset.Charset;\r\n+import java.nio.charset.StandardCharsets;\r\n+import java.util.Arrays;\r\n+import java.util.Collections;\r\n+import java.util.HashSet;\r\n+import java.util.List;\r\n+import java.util.Set;\r\n+import java.util.concurrent.Callable;\r\n+import java.util.concurrent.CompletableFuture;\r\n+import java.util.concurrent.ExecutionException;\r\n+import java.util.concurrent.Executors;\r\n+import java.util.concurrent.ScheduledExecutorService;\r\n+import java.util.concurrent.ScheduledFuture;\r\n+import java.util.concurrent.TimeUnit;\r\n+import java.util.concurrent.TimeoutException;\r\n+import java.util.concurrent.atomic.AtomicReference;\r\n+import java.util.function.Consumer;\r\n+\r\n+import static java.util.stream.Collectors.toList;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR;\r\n+import static org.apache.dubbo.remoting.etcd.Constants.DEFAULT_KEEPALIVE_TIMEOUT;\r\n+import static org.apache.dubbo.remoting.etcd.Constants.DEFAULT_RECONNECT_PERIOD;\r\n+import static org.apache.dubbo.remoting.etcd.Constants.DEFAULT_RETRY_PERIOD;\r\n+import static org.apache.dubbo.remoting.etcd.Constants.HTTP_KEY;\r\n+import static org.apache.dubbo.remoting.etcd.Constants.HTTP_SUBFIX_KEY;\r\n+import static org.apache.dubbo.remoting.etcd.Constants.RETRY_PERIOD_KEY;\r\n+import static org.apache.dubbo.remoting.etcd.Constants.SESSION_TIMEOUT_KEY;\r\n+\r\n+public class JEtcdClientWrapper {\r\n+\r\n+    private Logger logger = LoggerFactory.getLogger(JEtcdClientWrapper.class);\r\n+\r\n+    private final URL url;\r\n+    private volatile Client client;\r\n+    private volatile boolean started = false;\r\n+    private volatile boolean connectState = false;\r\n+    private ScheduledFuture future;\r\n+    private ScheduledExecutorService reconnectNotify;\r\n+    private AtomicReference<ManagedChannel> channel;\r\n+\r\n+    private ConnectionStateListener connectionStateListener;\r\n+\r\n+    private long expirePeriod;\r\n+\r\n+    private CompletableFuture<Client> completableFuture;\r\n+\r\n+    private RetryPolicy retryPolicy;\r\n+\r\n+    private RuntimeException failed;\r\n+\r\n+    private final ScheduledFuture<?> retryFuture;\r\n+    private final ScheduledExecutorService retryExecutor = Executors.newScheduledThreadPool(1,\r\n+            new NamedThreadFactory(\"Etcd3RegistryKeepAliveFailedRetryTimer\", true));\r\n+\r\n+    private final Set<String> failedRegistered = new ConcurrentHashSet<String>();\r\n+\r\n+    private final Set<String> registeredPaths = new ConcurrentHashSet<>();\r\n+    private volatile CloseableClient keepAlive = null;\r\n+\r\n+    /**\r\n+     * Support temporary nodes to reuse the same lease\r\n+     */\r\n+    private volatile long globalLeaseId;\r\n+\r\n+    private volatile boolean cancelKeepAlive = false;\r\n+\r\n+    public static final Charset UTF_8 = StandardCharsets.UTF_8;\r\n+\r\n+    public JEtcdClientWrapper(URL url) {\r\n+        this.url = url;\r\n+        this.expirePeriod = url.getParameter(SESSION_TIMEOUT_KEY, DEFAULT_KEEPALIVE_TIMEOUT) / 1000;\r\n+        if (expirePeriod <= 0) {\r\n+            this.expirePeriod = DEFAULT_KEEPALIVE_TIMEOUT / 1000;\r\n+        }\r\n+        this.channel = new AtomicReference<>();\r\n+        this.completableFuture = CompletableFuture.supplyAsync(() -> prepareClient(url));\r\n+        this.reconnectNotify = Executors.newScheduledThreadPool(1,\r\n+                new NamedThreadFactory(\"reconnectNotify\", true));\r\n+        this.retryPolicy = new RetryNTimes(1, 1000, TimeUnit.MILLISECONDS);\r\n+\r\n+        this.failed = new IllegalStateException(\"Etcd3 registry is not connected yet, url:\" + url);\r\n+        int retryPeriod = url.getParameter(RETRY_PERIOD_KEY, DEFAULT_RETRY_PERIOD);\r\n+\r\n+        this.retryFuture = retryExecutor.scheduleWithFixedDelay(() -> {\r\n+            try {\r\n+                retry();\r\n+            } catch (Throwable t) {\r\n+                logger.error(\"Unexpected error occur at failed retry, cause: \" + t.getMessage(), t);\r\n+            }\r\n+        }, retryPeriod, retryPeriod, TimeUnit.MILLISECONDS);\r\n+    }\r\n+\r\n+    private Client prepareClient(URL url) {\r\n+\r\n+        int maxInboundSize = DEFAULT_INBOUND_SIZE;\r\n+        if (StringUtils.isNotEmpty(System.getProperty(GRPC_MAX_INBOUND_SIZE_KEY))) {\r\n+            maxInboundSize = Integer.valueOf(System.getProperty(GRPC_MAX_INBOUND_SIZE_KEY));\r\n+        }\r\n+\r\n+        // TODO, uses default pick-first round robin.\r\n+        ClientBuilder clientBuilder = Client.builder()\r\n+                .endpoints(endPoints(url.getBackupAddress()))\r\n+                .maxInboundMessageSize(maxInboundSize);\r\n+\r\n+        return clientBuilder.build();\r\n+    }\r\n+\r\n+    public Client getClient() {\r\n+        return client;\r\n+    }\r\n+\r\n+    /**\r\n+     * try to get current connected channel.\r\n+     *\r\n+     * @return connected channel.\r\n+     */\r\n+    public ManagedChannel getChannel() {\r\n+        if (channel.get() == null || (channel.get().isShutdown() || channel.get().isTerminated())) {\r\n+            channel.set(newChannel(client));\r\n+        }\r\n+        return channel.get();\r\n+    }\r\n+\r\n+    /**\r\n+     * find direct children directory, excluding path self,\r\n+     * Never return null.\r\n+     *\r\n+     * @param path the path to be found direct children.\r\n+     * @return direct children directory, contains zero element\r\n+     * list if children directory not exists.\r\n+     */\r\n+    public List<String> getChildren(String path) {\r\n+        try {\r\n+            return RetryLoops.invokeWithRetry(\r\n+                    () -> {\r\n+                        requiredNotNull(client, failed);\r\n+                        int len = path.length();\r\n+                        return client.getKVClient()\r\n+                                .get(ByteSequence.from(path, UTF_8),\r\n+                                        GetOption.newBuilder().withPrefix(ByteSequence.from(path, UTF_8)).build())\r\n+                                .get(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS)\r\n+                                .getKvs().stream().parallel()\r\n+                                .filter(pair -> {\r\n+                                    String key = pair.getKey().toString(UTF_8);\r\n+                                    int index = len, count = 0;\r\n+                                    if (key.length() > len) {\r\n+                                        for (; (index = key.indexOf(PATH_SEPARATOR, index)) != -1; ++index) {\r\n+                                            if (count++ > 1) {\r\n+                                                break;\r\n+                                            }\r\n+                                        }\r\n+                                    }\r\n+                                    return count == 1;\r\n+                                })\r\n+                                .map(pair -> pair.getKey().toString(UTF_8))\r\n+                                .collect(toList());\r\n+                    }, retryPolicy);\r\n+        } catch (Exception e) {\r\n+            throw new IllegalStateException(e.getMessage(), e);\r\n+        }\r\n+    }\r\n+\r\n+    public boolean isConnected() {\r\n+        return ConnectivityState.READY == (getChannel().getState(false))\r\n+                || ConnectivityState.IDLE == (getChannel().getState(false));\r\n+    }\r\n+\r\n+    public long createLease(long second) {\r\n+        try {\r\n+            return RetryLoops.invokeWithRetry(\r\n+                    () -> {\r\n+                        requiredNotNull(client, failed);\r\n+                        return client.getLeaseClient()\r\n+                                .grant(second)\r\n+                                .get(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS)\r\n+                                .getID();\r\n+                    }, retryPolicy);\r\n+        } catch (Exception e) {\r\n+            throw new IllegalStateException(e.getMessage(), e);\r\n+        }\r\n+    }\r\n+\r\n+    public void revokeLease(long lease) {\r\n+        try {\r\n+            RetryLoops.invokeWithRetry(\r\n+                    (Callable<Void>) () -> {\r\n+                        requiredNotNull(client, failed);\r\n+                        client.getLeaseClient()\r\n+                                .revoke(lease)\r\n+                                .get(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS);\r\n+                        return null;\r\n+                    }, retryPolicy);\r\n+        } catch (Exception e) {\r\n+            throw new IllegalStateException(e.getMessage(), e);\r\n+        }\r\n+    }\r\n+\r\n+    public long createLease(long ttl, long timeout, TimeUnit unit)\r\n+            throws InterruptedException, ExecutionException, TimeoutException {\r\n+\r\n+        if (timeout <= 0) {\r\n+            return createLease(ttl);\r\n+        }\r\n+\r\n+        requiredNotNull(client, failed);\r\n+        return client.getLeaseClient()\r\n+                .grant(ttl)\r\n+                .get(timeout, unit).getID();\r\n+    }\r\n+\r\n+\r\n+    /**\r\n+     * try to check if path exists.\r\n+     */\r\n+    public boolean checkExists(String path) {\r\n+        try {\r\n+            return RetryLoops.invokeWithRetry(\r\n+                    () -> {\r\n+                        requiredNotNull(client, failed);\r\n+                        return client.getKVClient()\r\n+                                .get(ByteSequence.from(path, UTF_8), GetOption.newBuilder().withCountOnly(true).build())\r\n+                                .get(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS)\r\n+                                .getCount() > 0;\r\n+                    }, retryPolicy);\r\n+        } catch (Exception e) {\r\n+            throw new IllegalStateException(e.getMessage(), e);\r\n+        }\r\n+    }\r\n+\r\n+    /**\r\n+     * only internal use only, maybe change in the future\r\n+     */\r\n+    protected Long find(String path) {\r\n+        try {\r\n+            return RetryLoops.invokeWithRetry(\r\n+                    () -> {\r\n+                        requiredNotNull(client, failed);\r\n+                        return client.getKVClient()\r\n+                                .get(ByteSequence.from(path, UTF_8))\r\n+                                .get(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS)\r\n+                                .getKvs().stream()\r\n+                                .mapToLong(keyValue -> Long.valueOf(keyValue.getValue().toString(UTF_8)))\r\n+                                .findFirst().getAsLong();\r\n+                    }, retryPolicy);\r\n+        } catch (Exception e) {\r\n+            throw new IllegalStateException(e.getMessage(), e);\r\n+        }\r\n+    }\r\n+\r\n+    public void createPersistent(String path) {\r\n+        try {\r\n+            RetryLoops.invokeWithRetry(\r\n+                    (Callable<Void>) () -> {\r\n+                        requiredNotNull(client, failed);\r\n+                        client.getKVClient()\r\n+                                .put(ByteSequence.from(path, UTF_8),\r\n+                                        ByteSequence.from(String.valueOf(path.hashCode()), UTF_8))\r\n+                                .get(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS);\r\n+                        return null;\r\n+                    }, retryPolicy);\r\n+        } catch (Exception e) {\r\n+            throw new IllegalStateException(e.getMessage(), e);\r\n+        }\r\n+    }\r\n+\r\n+    /**\r\n+     * create new ephemeral path save to etcd .\r\n+     * if node disconnect from etcd, it will be deleted\r\n+     * automatically by etcd when session timeout.\r\n+     *\r\n+     * @param path the path to be saved\r\n+     * @return the lease of current path.\r\n+     */\r\n+    public long createEphemeral(String path) {\r\n+        try {\r\n+            return RetryLoops.invokeWithRetry(\r\n+                    () -> {\r\n+                        requiredNotNull(client, failed);\r\n+\r\n+                        registeredPaths.add(path);\r\n+                        keepAlive();\r\n+                        final long leaseId = globalLeaseId;\r\n+                        client.getKVClient()\r\n+                                .put(ByteSequence.from(path, UTF_8)\r\n+                                        , ByteSequence.from(String.valueOf(leaseId), UTF_8)\r\n+                                        , PutOption.newBuilder().withLeaseId(leaseId).build())\r\n+                                .get(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS);\r\n+                        return leaseId;\r\n+                    }, retryPolicy);\r\n+        } catch (Exception e) {\r\n+            throw new IllegalStateException(e.getMessage(), e);\r\n+        }\r\n+    }\r\n+\r\n+    // easy for mock\r\n+    public void keepAlive(long lease) {\r\n+        this.keepAlive(lease, null);\r\n+    }\r\n+\r\n+    @SuppressWarnings(\"unchecked\")\r\n+    private <T> void keepAlive(long lease, Consumer<T> onFailed) {\r\n+        final StreamObserver<LeaseKeepAliveResponse> observer = new Observers.Builder()\r\n+                .onError((e) -> {\r\n+                    if (e instanceof EtcdException) {\r\n+                        EtcdException error = (EtcdException) e;\r\n+                        /**\r\n+                         * ttl has expired\r\n+                         */\r\n+                        if (error.getErrorCode() == ErrorCode.NOT_FOUND) {\r\n+                            keepAlive0(onFailed);\r\n+                        }\r\n+                    }\r\n+                }).onCompleted(() -> {\r\n+                    /**\r\n+                     * deadline reached.\r\n+                     */\r\n+                    keepAlive0(onFailed);\r\n+                }).build();\r\n+\r\n+        /**\r\n+         * If there is already a keepalive, cancel first\r\n+         */\r\n+        cancelKeepAlive();\r\n+\r\n+        /**\r\n+         * create and set new keepAlive to globalKeepAliveRef\r\n+         */\r\n+        this.keepAlive = client.getLeaseClient().keepAlive(lease, observer);\r\n+    }\r\n+\r\n+    private void keepAlive() throws Exception {\r\n+        if (keepAlive == null) {\r\n+            synchronized (this) {\r\n+                if (keepAlive == null) {\r\n+                    this.globalLeaseId = client.getLeaseClient()\r\n+                            .grant(expirePeriod)\r\n+                            .get(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS)\r\n+                            .getID();\r\n+                    /**\r\n+                     * If the keepAlive expires, the registration will be re-attempted\r\n+                     */\r\n+                    keepAlive(globalLeaseId, (NULL) -> recovery());\r\n+                }\r\n+            }\r\n+        }\r\n+    }\r\n+\r\n+    private <T> void keepAlive0(Consumer<T> onFailed) {\r\n+        if (onFailed != null) {\r\n+\r\n+            /**\r\n+             * The following two scenarios will cause the keep-alive failure\uff1a\r\n+             *\r\n+             * 1. Service is offline\r\n+             * 2. Local deadline check expired\r\n+             *\r\n+             * The multiplex lease cannot update the local deadline,\r\n+             * causing the extreme scene service to be dropped.\r\n+             *\r\n+             */\r\n+            long leaseId = globalLeaseId;\r\n+            try {\r\n+                if (logger.isWarnEnabled()) {\r\n+                    logger.warn(\"Failed to keep alive for global lease '\" + leaseId + \"', waiting for retry again.\");\r\n+                }\r\n+                onFailed.accept(null);\r\n+            } catch (Exception ignored) {\r\n+                logger.warn(\"Failed to recover from global lease expired or lease deadline exceeded. lease '\" + leaseId + \"'\", ignored);\r\n+            }\r\n+        }\r\n+    }\r\n+\r\n+    private void recovery() {\r\n+\r\n+        try {\r\n+            /**\r\n+             * The client is processing reconnection\r\n+             */\r\n+            if (cancelKeepAlive) {\r\n+                return;\r\n+            }\r\n+\r\n+            cancelKeepAlive();\r\n+\r\n+            Set<String> ephemeralPaths = new HashSet<String>(registeredPaths);\r\n+            if (!ephemeralPaths.isEmpty()) {\r\n+                for (String path : ephemeralPaths) {\r\n+                    try {\r\n+\r\n+                        /**\r\n+                         * The client is processing reconnection,\r\n+                         * cancel remaining service registration\r\n+                         */\r\n+                        if (cancelKeepAlive) {\r\n+                            return;\r\n+                        }\r\n+\r\n+                        createEphemeral(path);\r\n+                        failedRegistered.remove(path);\r\n+                    } catch (Exception e) {\r\n+\r\n+                        /**\r\n+                         * waiting for retry again\r\n+                         */\r\n+                        failedRegistered.add(path);\r\n+\r\n+                        Status status = Status.fromThrowable(e);\r\n+                        if (status.getCode() == Status.Code.NOT_FOUND) {\r\n+                            cancelKeepAlive();\r\n+                        }\r\n+                    }\r\n+                }\r\n+            }\r\n+        } catch (Throwable t) {\r\n+            logger.warn(\"Unexpected error, failed to recover from global lease expired or deadline exceeded.\", t);\r\n+        }\r\n+    }\r\n+\r\n+    public void delete(String path) {\r\n+        try {\r\n+            RetryLoops.invokeWithRetry(\r\n+                    (Callable<Void>) () -> {\r\n+                        requiredNotNull(client, failed);\r\n+                        client.getKVClient()\r\n+                                .delete(ByteSequence.from(path, UTF_8))\r\n+                                .get(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS);\r\n+                        registeredPaths.remove(path);\r\n+                        return null;\r\n+                    }, retryPolicy);\r\n+        } catch (Exception e) {\r\n+            throw new IllegalStateException(e.getMessage(), e);\r\n+        } finally {\r\n+            /**\r\n+             * Cancel retry\r\n+             */\r\n+            failedRegistered.remove(path);\r\n+        }\r\n+    }\r\n+\r\n+    public String[] endPoints(String backupAddress) {\r\n+        String[] endpoints = backupAddress.split(COMMA_SEPARATOR);\r\n+        List<String> addresses = Arrays.stream(endpoints)\r\n+                .map(address -> address.contains(HTTP_SUBFIX_KEY)\r\n+                        ? address\r\n+                        : HTTP_KEY + address)\r\n+                .collect(toList());\r\n+        Collections.shuffle(addresses);\r\n+        return addresses.toArray(new String[0]);\r\n+    }\r\n+\r\n+    /**\r\n+     * because jetcd's connection change callback not supported yet, we must\r\n+     * loop to test if connect or disconnect event happened or not. It will be changed\r\n+     * in the future if we found better choice.\r\n+     */\r\n+    public void start() {\r\n+        if (!started) {\r\n+            try {\r\n+                this.client = completableFuture.get(expirePeriod, TimeUnit.SECONDS);\r\n+                this.connectState = isConnected();\r\n+                this.started = true;\r\n+            } catch (Throwable t) {\r\n+                logger.error(\"Timeout! etcd3 server can not be connected in : \" + expirePeriod + \" seconds! url: \" + url, t);\r\n+\r\n+                completableFuture.whenComplete((c, e) -> {\r\n+                    this.client = c;\r\n+                    if (e != null) {\r\n+                        logger.error(\"Got an exception when trying to create etcd3 instance, can not connect to etcd3 server, url: \" + url, e);\r\n+                    }\r\n+                });\r\n+\r\n+            }\r\n+\r\n+            try {\r\n+                this.future = reconnectNotify.scheduleWithFixedDelay(() -> {\r\n+                    boolean connected = isConnected();\r\n+                    if (connectState != connected) {\r\n+                        int notifyState = connected ? StateListener.CONNECTED : StateListener.DISCONNECTED;\r\n+                        if (connectionStateListener != null) {\r\n+                            try {\r\n+                                if (connected) {\r\n+                                    clearKeepAlive();\r\n+                                }\r\n+                                connectionStateListener.stateChanged(getClient(), notifyState);\r\n+                            } finally {\r\n+                                cancelKeepAlive = false;\r\n+                            }\r\n+                        }\r\n+                        connectState = connected;\r\n+                    }\r\n+                }, DEFAULT_RECONNECT_PERIOD, DEFAULT_RECONNECT_PERIOD, TimeUnit.MILLISECONDS);\r\n+            } catch (Throwable t) {\r\n+                logger.error(\"monitor reconnect status failed.\", t);\r\n+            }\r\n+        }\r\n+    }\r\n+\r\n+    private void cancelKeepAlive() {\r\n+        try {\r\n+            if (keepAlive != null) {\r\n+                keepAlive.close();\r\n+            }\r\n+        } finally {\r\n+            // help for gc\r\n+            keepAlive = null;\r\n+        }\r\n+    }\r\n+\r\n+    private void clearKeepAlive() {\r\n+        cancelKeepAlive = true;\r\n+        failedRegistered.clear();\r\n+        cancelKeepAlive();\r\n+    }\r\n+\r\n+    protected void doClose() {\r\n+\r\n+        try {\r\n+            cancelKeepAlive = true;\r\n+            if (globalLeaseId != 0) {\r\n+                revokeLease(this.globalLeaseId);\r\n+            }\r\n+        } catch (Exception e) {\r\n+            logger.warn(\"revoke global lease '\" + globalLeaseId + \"' failed, registry: \" + url, e);\r\n+        }\r\n+\r\n+        try {\r\n+            if (started && future != null) {\r\n+                started = false;\r\n+                future.cancel(true);\r\n+                reconnectNotify.shutdownNow();\r\n+            }\r\n+        } catch (Exception e) {\r\n+            logger.warn(\"stop reconnect Notify failed, registry: \" + url, e);\r\n+        }\r\n+\r\n+        try {\r\n+            retryFuture.cancel(true);\r\n+            retryExecutor.shutdownNow();\r\n+        } catch (Throwable t) {\r\n+            logger.warn(t.getMessage(), t);\r\n+        }\r\n+\r\n+        if (getClient() != null) {\r\n+            getClient().close();\r\n+        }\r\n+    }\r\n+\r\n+    /**\r\n+     * try get client's shared channel, because all fields is private on jetcd,\r\n+     * we must using it by reflect, in the future, jetcd may provider better tools.\r\n+     *\r\n+     * @param client get channel from current client\r\n+     * @return current connection channel\r\n+     */\r\n+    private ManagedChannel newChannel(Client client) {\r\n+        try {\r\n+            Field connectionField = client.getClass().getDeclaredField(\"connectionManager\");\r\n+            ReflectUtils.makeAccessible(connectionField);\r\n+            Object connection = connectionField.get(client);\r\n+            Method channel = connection.getClass().getDeclaredMethod(\"getChannel\");\r\n+            ReflectUtils.makeAccessible(channel);\r\n+            return (ManagedChannel) channel.invoke(connection);\r\n+        } catch (Exception e) {\r\n+            throw new RuntimeException(\"Failed to obtain connection channel from \" + url.getBackupAddress(), e);\r\n+        }\r\n+    }\r\n+\r\n+    public ConnectionStateListener getConnectionStateListener() {\r\n+        return connectionStateListener;\r\n+    }\r\n+\r\n+    public void setConnectionStateListener(ConnectionStateListener connectionStateListener) {\r\n+        this.connectionStateListener = connectionStateListener;\r\n+    }\r\n+\r\n+    public static void requiredNotNull(Object obj, RuntimeException exception) {\r\n+        if (obj == null) {\r\n+            throw exception;\r\n+        }\r\n+    }\r\n+\r\n+    public String getKVValue(String key) {\r\n+        if (null == key) {\r\n+            return null;\r\n+        }\r\n+\r\n+        CompletableFuture<GetResponse> responseFuture = this.client.getKVClient().get(ByteSequence.from(key, UTF_8));\r\n+\r\n+        try {\r\n+            List<KeyValue> result = responseFuture.get(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS).getKvs();\r\n+            if (!result.isEmpty()) {\r\n+                return result.get(0).getValue().toString(UTF_8);\r\n+            }\r\n+        } catch (Exception e) {\r\n+            // ignore\r\n+        }\r\n+\r\n+        return null;\r\n+    }\r\n+\r\n+\r\n+    public boolean put(String key, String value) {\r\n+        if (key == null || value == null) {\r\n+            return false;\r\n+        }\r\n+        CompletableFuture<PutResponse> putFuture =\r\n+                this.client.getKVClient().put(ByteSequence.from(key, UTF_8), ByteSequence.from(value, UTF_8));\r\n+        try {\r\n+            putFuture.get(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS);\r\n+            return true;\r\n+        } catch (Exception e) {\r\n+            // ignore\r\n+        }\r\n+        return false;\r\n+    }\r\n+\r\n+    public boolean putEphemeral(final String key, String value) {\r\n+        try {\r\n+            return RetryLoops.invokeWithRetry(\r\n+                    () -> {\r\n+                        requiredNotNull(client, failed);\r\n+                        // recovery an retry\r\n+                        keepAlive();\r\n+                        final long leaseId = globalLeaseId;\r\n+                        client.getKVClient()\r\n+                                .put(ByteSequence.from(key, UTF_8)\r\n+                                        , ByteSequence.from(String.valueOf(value), UTF_8)\r\n+                                        , PutOption.newBuilder().withLeaseId(leaseId).build())\r\n+                                .get(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS);\r\n+                        return true;\r\n+                    }, retryPolicy);\r\n+        } catch (Exception e) {\r\n+            throw new IllegalStateException(e.getMessage(), e);\r\n+        }\r\n+    }\r\n+\r\n+    private void retry() {\r\n+        if (!failedRegistered.isEmpty()) {\r\n+            Set<String> failed = new HashSet<String>(failedRegistered);\r\n+            if (!failed.isEmpty()) {\r\n+\r\n+                if (cancelKeepAlive) {\r\n+                    return;\r\n+                }\r\n+\r\n+                if (logger.isWarnEnabled()) {\r\n+                    logger.warn(\"Retry failed register(keep alive) for path '\" + failed\r\n+                            + \"', path size: \" + failed.size());\r\n+                }\r\n+                try {\r\n+                    for (String path : failed) {\r\n+                        try {\r\n+\r\n+                            /**\r\n+                             * Is it currently reconnecting ?\r\n+                             */\r\n+                            if (cancelKeepAlive) {\r\n+                                return;\r\n+                            }\r\n+\r\n+                            createEphemeral(path);\r\n+                            failedRegistered.remove(path);\r\n+                        } catch (Throwable e) {\r\n+\r\n+                            failedRegistered.add(path);\r\n+\r\n+                            Status status = Status.fromThrowable(e);\r\n+                            if (status.getCode() == Status.Code.NOT_FOUND) {\r\n+                                cancelKeepAlive();\r\n+                            }\r\n+\r\n+                            logger.warn(\"Failed to retry register(keep alive) for path '\" + path + \"', waiting for again, cause: \" + e.getMessage(), e);\r\n+                        }\r\n+                    }\r\n+                } catch (Throwable t) {\r\n+                    logger.warn(\"Failed to retry register(keep alive) for path '\" + failed + \"', waiting for again, cause: \" + t.getMessage(), t);\r\n+                }\r\n+            }\r\n+        }\r\n+    }\r\n+\r\n+    /**\r\n+     * default request timeout\r\n+     */\r\n+    public static final long DEFAULT_REQUEST_TIMEOUT = obtainRequestTimeout();\r\n+\r\n+    public static final int DEFAULT_INBOUND_SIZE = 100 * 1024 * 1024;\r\n+\r\n+    public static final String GRPC_MAX_INBOUND_SIZE_KEY = \"grpc.max.inbound.size\";\r\n+\r\n+    public static final String ETCD_REQUEST_TIMEOUT_KEY = \"etcd.request.timeout\";\r\n+\r\n+    private static int obtainRequestTimeout() {\r\n+        if (StringUtils.isNotEmpty(System.getProperty(ETCD_REQUEST_TIMEOUT_KEY))) {\r\n+            return Integer.valueOf(System.getProperty(ETCD_REQUEST_TIMEOUT_KEY));\r\n+        }\r\n+        /**\r\n+         * 10 seconds.\r\n+         */\r\n+        return 10 * 1000;\r\n+    }\r\n+}\r\n"}, {"source1": "org/apache/dubbo/remoting/etcd/jetcd/JEtcdTransporter.java", "source2": "org/apache/dubbo/remoting/etcd/jetcd/JEtcdTransporter.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,30 +1,30 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-package org.apache.dubbo.remoting.etcd.jetcd;\n-\n-import org.apache.dubbo.common.URL;\n-import org.apache.dubbo.remoting.etcd.EtcdClient;\n-import org.apache.dubbo.remoting.etcd.EtcdTransporter;\n-\n-public class JEtcdTransporter implements EtcdTransporter {\n-\n-    @Override\n-    public EtcdClient connect(URL url) {\n-        return new JEtcdClient(url);\n-    }\n-\n-}\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+package org.apache.dubbo.remoting.etcd.jetcd;\r\n+\r\n+import org.apache.dubbo.common.URL;\r\n+import org.apache.dubbo.remoting.etcd.EtcdClient;\r\n+import org.apache.dubbo.remoting.etcd.EtcdTransporter;\r\n+\r\n+public class JEtcdTransporter implements EtcdTransporter {\r\n+\r\n+    @Override\r\n+    public EtcdClient connect(URL url) {\r\n+        return new JEtcdClient(url);\r\n+    }\r\n+\r\n+}\r\n"}, {"source1": "org/apache/dubbo/remoting/etcd/jetcd/RetryLoops.java", "source2": "org/apache/dubbo/remoting/etcd/jetcd/RetryLoops.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,99 +1,99 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-package org.apache.dubbo.remoting.etcd.jetcd;\n-\n-import io.grpc.Status;\n-import org.apache.dubbo.common.logger.Logger;\n-import org.apache.dubbo.common.logger.LoggerFactory;\n-import org.apache.dubbo.remoting.etcd.RetryPolicy;\n-import org.apache.dubbo.remoting.etcd.option.OptionUtil;\n-\n-import java.util.concurrent.Callable;\n-\n-public class RetryLoops {\n-\n-    private final long startTimeMs = System.currentTimeMillis();\n-    private boolean isDone = false;\n-    private int retriedCount = 0;\n-    private Logger logger = LoggerFactory.getLogger(RetryLoops.class);\n-\n-    public static <R> R invokeWithRetry(Callable<R> task, RetryPolicy retryPolicy) throws Exception {\n-        R result = null;\n-        RetryLoops retryLoop = new RetryLoops();\n-        while (retryLoop.shouldContinue()) {\n-            try {\n-                result = task.call();\n-                retryLoop.complete();\n-            } catch (Exception e) {\n-                retryLoop.fireException(e, retryPolicy);\n-            }\n-        }\n-        return result;\n-    }\n-\n-    public void fireException(Exception e, RetryPolicy retryPolicy) throws Exception {\n-\n-        if (e instanceof InterruptedException) {\n-            Thread.currentThread().interrupt();\n-        }\n-\n-        boolean rethrow = true;\n-        if (isRetryException(e)\n-                && retryPolicy.shouldRetry(retriedCount++, System.currentTimeMillis() - startTimeMs, true)) {\n-            rethrow = false;\n-        }\n-\n-        if (rethrow) {\n-            throw e;\n-        }\n-    }\n-\n-    private boolean isRetryException(Throwable e) {\n-        Status status = Status.fromThrowable(e);\n-        if (OptionUtil.isRecoverable(status)) {\n-            return true;\n-        }\n-\n-        return false;\n-    }\n-\n-    public boolean shouldContinue() {\n-        return !isDone;\n-    }\n-\n-    public void complete() {\n-        isDone = true;\n-    }\n-\n-}\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+\r\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+package org.apache.dubbo.remoting.etcd.jetcd;\r\n+\r\n+import io.grpc.Status;\r\n+import org.apache.dubbo.common.logger.Logger;\r\n+import org.apache.dubbo.common.logger.LoggerFactory;\r\n+import org.apache.dubbo.remoting.etcd.RetryPolicy;\r\n+import org.apache.dubbo.remoting.etcd.option.OptionUtil;\r\n+\r\n+import java.util.concurrent.Callable;\r\n+\r\n+public class RetryLoops {\r\n+\r\n+    private final long startTimeMs = System.currentTimeMillis();\r\n+    private boolean isDone = false;\r\n+    private int retriedCount = 0;\r\n+    private Logger logger = LoggerFactory.getLogger(RetryLoops.class);\r\n+\r\n+    public static <R> R invokeWithRetry(Callable<R> task, RetryPolicy retryPolicy) throws Exception {\r\n+        R result = null;\r\n+        RetryLoops retryLoop = new RetryLoops();\r\n+        while (retryLoop.shouldContinue()) {\r\n+            try {\r\n+                result = task.call();\r\n+                retryLoop.complete();\r\n+            } catch (Exception e) {\r\n+                retryLoop.fireException(e, retryPolicy);\r\n+            }\r\n+        }\r\n+        return result;\r\n+    }\r\n+\r\n+    public void fireException(Exception e, RetryPolicy retryPolicy) throws Exception {\r\n+\r\n+        if (e instanceof InterruptedException) {\r\n+            Thread.currentThread().interrupt();\r\n+        }\r\n+\r\n+        boolean rethrow = true;\r\n+        if (isRetryException(e)\r\n+                && retryPolicy.shouldRetry(retriedCount++, System.currentTimeMillis() - startTimeMs, true)) {\r\n+            rethrow = false;\r\n+        }\r\n+\r\n+        if (rethrow) {\r\n+            throw e;\r\n+        }\r\n+    }\r\n+\r\n+    private boolean isRetryException(Throwable e) {\r\n+        Status status = Status.fromThrowable(e);\r\n+        if (OptionUtil.isRecoverable(status)) {\r\n+            return true;\r\n+        }\r\n+\r\n+        return false;\r\n+    }\r\n+\r\n+    public boolean shouldContinue() {\r\n+        return !isDone;\r\n+    }\r\n+\r\n+    public void complete() {\r\n+        isDone = true;\r\n+    }\r\n+\r\n+}\r\n"}, {"source1": "org/apache/dubbo/remoting/etcd/option/OptionUtil.java", "source2": "org/apache/dubbo/remoting/etcd/option/OptionUtil.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,78 +1,78 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-package org.apache.dubbo.remoting.etcd.option;\n-\n-import io.etcd.jetcd.ByteSequence;\n-import io.grpc.Status;\n-import io.netty.handler.codec.http2.Http2Exception;\n-\n-import java.util.Arrays;\n-\n-public class OptionUtil {\n-\n-    public static final byte[] NO_PREFIX_END = {0};\n-\n-    public static final ByteSequence prefixEndOf(ByteSequence prefix) {\n-        byte[] endKey = prefix.getBytes().clone();\n-        for (int i = endKey.length - 1; i >= 0; i--) {\n-            if (endKey[i] < 0xff) {\n-                endKey[i] = (byte) (endKey[i] + 1);\n-                return ByteSequence.from(Arrays.copyOf(endKey, i + 1));\n-            }\n-        }\n-\n-        return ByteSequence.from(NO_PREFIX_END);\n-    }\n-\n-    public static boolean isRecoverable(Status status) {\n-        return isHaltError(status)\n-                || isNoLeaderError(status)\n-                // ephemeral is expired\n-                || status.getCode() == Status.Code.NOT_FOUND;\n-    }\n-\n-    public static boolean isHaltError(Status status) {\n-        // Unavailable codes mean the system will be right back.\n-        // (e.g., can't connect, lost leader)\n-        // Treat Internal codes as if something failed, leaving the\n-        // system in an inconsistent state, but retrying could make progress.\n-        // (e.g., failed in middle of send, corrupted frame)\n-        return status.getCode() != Status.Code.UNAVAILABLE && status.getCode() != Status.Code.INTERNAL;\n-    }\n-\n-    public static boolean isNoLeaderError(Status status) {\n-        return status.getCode() == Status.Code.UNAVAILABLE\n-                && \"etcdserver: no leader\".equals(status.getDescription());\n-    }\n-\n-    public static boolean isProtocolError(Throwable e) {\n-        if (e == null) {\n-            return false;\n-        }\n-        Throwable cause = e.getCause();\n-        while (cause != null) {\n-            if (cause instanceof Http2Exception) {\n-                Http2Exception t = (Http2Exception) cause;\n-                if (\"PROTOCOL_ERROR\".equals(t.error().name())) {\n-                    return true;\n-                }\n-            }\n-            cause = cause.getCause();\n-        }\n-        return false;\n-    }\n-}\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+package org.apache.dubbo.remoting.etcd.option;\r\n+\r\n+import io.etcd.jetcd.ByteSequence;\r\n+import io.grpc.Status;\r\n+import io.netty.handler.codec.http2.Http2Exception;\r\n+\r\n+import java.util.Arrays;\r\n+\r\n+public class OptionUtil {\r\n+\r\n+    public static final byte[] NO_PREFIX_END = {0};\r\n+\r\n+    public static final ByteSequence prefixEndOf(ByteSequence prefix) {\r\n+        byte[] endKey = prefix.getBytes().clone();\r\n+        for (int i = endKey.length - 1; i >= 0; i--) {\r\n+            if (endKey[i] < 0xff) {\r\n+                endKey[i] = (byte) (endKey[i] + 1);\r\n+                return ByteSequence.from(Arrays.copyOf(endKey, i + 1));\r\n+            }\r\n+        }\r\n+\r\n+        return ByteSequence.from(NO_PREFIX_END);\r\n+    }\r\n+\r\n+    public static boolean isRecoverable(Status status) {\r\n+        return isHaltError(status)\r\n+                || isNoLeaderError(status)\r\n+                // ephemeral is expired\r\n+                || status.getCode() == Status.Code.NOT_FOUND;\r\n+    }\r\n+\r\n+    public static boolean isHaltError(Status status) {\r\n+        // Unavailable codes mean the system will be right back.\r\n+        // (e.g., can't connect, lost leader)\r\n+        // Treat Internal codes as if something failed, leaving the\r\n+        // system in an inconsistent state, but retrying could make progress.\r\n+        // (e.g., failed in middle of send, corrupted frame)\r\n+        return status.getCode() != Status.Code.UNAVAILABLE && status.getCode() != Status.Code.INTERNAL;\r\n+    }\r\n+\r\n+    public static boolean isNoLeaderError(Status status) {\r\n+        return status.getCode() == Status.Code.UNAVAILABLE\r\n+                && \"etcdserver: no leader\".equals(status.getDescription());\r\n+    }\r\n+\r\n+    public static boolean isProtocolError(Throwable e) {\r\n+        if (e == null) {\r\n+            return false;\r\n+        }\r\n+        Throwable cause = e.getCause();\r\n+        while (cause != null) {\r\n+            if (cause instanceof Http2Exception) {\r\n+                Http2Exception t = (Http2Exception) cause;\r\n+                if (\"PROTOCOL_ERROR\".equals(t.error().name())) {\r\n+                    return true;\r\n+                }\r\n+            }\r\n+            cause = cause.getCause();\r\n+        }\r\n+        return false;\r\n+    }\r\n+}\r\n"}, {"source1": "org/apache/dubbo/remoting/etcd/support/AbstractEtcdClient.java", "source2": "org/apache/dubbo/remoting/etcd/support/AbstractEtcdClient.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,194 +1,194 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-package org.apache.dubbo.remoting.etcd.support;\n-\n-import org.apache.dubbo.common.URL;\n-import org.apache.dubbo.common.logger.Logger;\n-import org.apache.dubbo.common.logger.LoggerFactory;\n-import org.apache.dubbo.common.utils.ConcurrentHashSet;\n-import org.apache.dubbo.common.utils.StringUtils;\n-import org.apache.dubbo.remoting.etcd.ChildListener;\n-import org.apache.dubbo.remoting.etcd.EtcdClient;\n-import org.apache.dubbo.remoting.etcd.StateListener;\n-\n-import java.util.Arrays;\n-import java.util.List;\n-import java.util.Set;\n-import java.util.concurrent.ConcurrentHashMap;\n-import java.util.concurrent.ConcurrentMap;\n-\n-import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR;\n-import static org.apache.dubbo.remoting.etcd.Constants.CONFIGURATORS_CATEGORY;\n-import static org.apache.dubbo.remoting.etcd.Constants.CONSUMERS_CATEGORY;\n-import static org.apache.dubbo.remoting.etcd.Constants.PROVIDERS_CATEGORY;\n-import static org.apache.dubbo.remoting.etcd.Constants.ROUTERS_CATEGORY;\n-\n-public abstract class AbstractEtcdClient<WatcherListener> implements EtcdClient {\n-\n-    protected static final Logger logger = LoggerFactory.getLogger(AbstractEtcdClient.class);\n-\n-    private final URL url;\n-\n-    private final Set<StateListener> stateListeners = new ConcurrentHashSet<>();\n-\n-    private final ConcurrentMap<String, ConcurrentMap<ChildListener, WatcherListener>> childListeners = new ConcurrentHashMap<>();\n-    private final List<String> categories = Arrays.asList(PROVIDERS_CATEGORY, CONSUMERS_CATEGORY, ROUTERS_CATEGORY,\n-            CONFIGURATORS_CATEGORY);\n-    private volatile boolean closed = false;\n-\n-    public AbstractEtcdClient(URL url) {\n-        this.url = url;\n-    }\n-\n-    @Override\n-    public URL getUrl() {\n-        return url;\n-    }\n-\n-    @Override\n-    public void create(String path) {\n-        String fixedPath = fixNamespace(path);\n-        createParentIfAbsent(fixedPath);\n-        doCreatePersistent(fixedPath);\n-    }\n-\n-    @Override\n-    public long createEphemeral(String path) {\n-        String fixedPath = fixNamespace(path);\n-        createParentIfAbsent(fixedPath);\n-        return doCreateEphemeral(path);\n-    }\n-\n-    @Override\n-    public void addStateListener(StateListener listener) {\n-        stateListeners.add(listener);\n-    }\n-\n-    @Override\n-    public void removeStateListener(StateListener listener) {\n-        stateListeners.remove(listener);\n-    }\n-\n-    public Set<StateListener> getSessionListeners() {\n-        return stateListeners;\n-    }\n-\n-    @Override\n-    public List<String> addChildListener(String path, final ChildListener listener) {\n-        ConcurrentMap<ChildListener, WatcherListener> listeners = childListeners.computeIfAbsent(path, k -> new ConcurrentHashMap<>());\n-        WatcherListener targetListener = listeners.computeIfAbsent(listener, k -> createChildWatcherListener(path, k));\n-        return addChildWatcherListener(path, targetListener);\n-    }\n-\n-    @Override\n-    public WatcherListener getChildListener(String path, ChildListener listener) {\n-        ConcurrentMap<ChildListener, WatcherListener> listeners = childListeners.get(path);\n-        if (listeners == null) {\n-            return null;\n-        }\n-        return listeners.computeIfAbsent(listener, k -> createChildWatcherListener(path, k));\n-    }\n-\n-    @Override\n-    public void removeChildListener(String path, ChildListener listener) {\n-        ConcurrentMap<ChildListener, WatcherListener> listeners = childListeners.get(path);\n-        if (listeners != null) {\n-            WatcherListener targetListener = listeners.remove(listener);\n-            if (targetListener != null) {\n-                removeChildWatcherListener(path, targetListener);\n-            }\n-        }\n-    }\n-\n-    protected void stateChanged(int state) {\n-        for (StateListener sessionListener : getSessionListeners()) {\n-            sessionListener.stateChanged(state);\n-        }\n-    }\n-\n-    protected String fixNamespace(String path) {\n-        if (StringUtils.isEmpty(path)) {\n-            throw new IllegalArgumentException(\"path is required, actual null or ''\");\n-        }\n-        return (path.charAt(0) != '/') ? (PATH_SEPARATOR + path) : path;\n-    }\n-\n-    protected void createParentIfAbsent(String fixedPath) {\n-        int i = fixedPath.lastIndexOf('/');\n-        if (i > 0) {\n-            String parentPath = fixedPath.substring(0, i);\n-            if (categories.stream().anyMatch(c -> fixedPath.endsWith(c))) {\n-                if (!checkExists(parentPath)) {\n-                    this.doCreatePersistent(parentPath);\n-                }\n-            } else if (categories.stream().anyMatch(c -> parentPath.endsWith(c))) {\n-                String grandfather = parentPath.substring(0, parentPath.lastIndexOf('/'));\n-                if (!checkExists(grandfather)) {\n-                    this.doCreatePersistent(grandfather);\n-                }\n-            }\n-        }\n-    }\n-\n-    @Override\n-    public void close() {\n-        if (closed) {\n-            return;\n-        }\n-        closed = true;\n-        try {\n-            doClose();\n-        } catch (Throwable t) {\n-            logger.warn(t.getMessage(), t);\n-        }\n-    }\n-\n-    public abstract void doClose();\n-\n-    public abstract void doCreatePersistent(String path);\n-\n-    public abstract long doCreateEphemeral(String path);\n-\n-    @Override\n-    public abstract void delete(String path);\n-\n-    public abstract boolean checkExists(String path);\n-\n-    public abstract WatcherListener createChildWatcherListener(String path, ChildListener listener);\n-\n-    public abstract List<String> addChildWatcherListener(String path, WatcherListener listener);\n-\n-    public abstract void removeChildWatcherListener(String path, WatcherListener listener);\n-\n-}\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+\r\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+package org.apache.dubbo.remoting.etcd.support;\r\n+\r\n+import org.apache.dubbo.common.URL;\r\n+import org.apache.dubbo.common.logger.Logger;\r\n+import org.apache.dubbo.common.logger.LoggerFactory;\r\n+import org.apache.dubbo.common.utils.ConcurrentHashSet;\r\n+import org.apache.dubbo.common.utils.StringUtils;\r\n+import org.apache.dubbo.remoting.etcd.ChildListener;\r\n+import org.apache.dubbo.remoting.etcd.EtcdClient;\r\n+import org.apache.dubbo.remoting.etcd.StateListener;\r\n+\r\n+import java.util.Arrays;\r\n+import java.util.List;\r\n+import java.util.Set;\r\n+import java.util.concurrent.ConcurrentHashMap;\r\n+import java.util.concurrent.ConcurrentMap;\r\n+\r\n+import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR;\r\n+import static org.apache.dubbo.remoting.etcd.Constants.CONFIGURATORS_CATEGORY;\r\n+import static org.apache.dubbo.remoting.etcd.Constants.CONSUMERS_CATEGORY;\r\n+import static org.apache.dubbo.remoting.etcd.Constants.PROVIDERS_CATEGORY;\r\n+import static org.apache.dubbo.remoting.etcd.Constants.ROUTERS_CATEGORY;\r\n+\r\n+public abstract class AbstractEtcdClient<WatcherListener> implements EtcdClient {\r\n+\r\n+    protected static final Logger logger = LoggerFactory.getLogger(AbstractEtcdClient.class);\r\n+\r\n+    private final URL url;\r\n+\r\n+    private final Set<StateListener> stateListeners = new ConcurrentHashSet<>();\r\n+\r\n+    private final ConcurrentMap<String, ConcurrentMap<ChildListener, WatcherListener>> childListeners = new ConcurrentHashMap<>();\r\n+    private final List<String> categories = Arrays.asList(PROVIDERS_CATEGORY, CONSUMERS_CATEGORY, ROUTERS_CATEGORY,\r\n+            CONFIGURATORS_CATEGORY);\r\n+    private volatile boolean closed = false;\r\n+\r\n+    public AbstractEtcdClient(URL url) {\r\n+        this.url = url;\r\n+    }\r\n+\r\n+    @Override\r\n+    public URL getUrl() {\r\n+        return url;\r\n+    }\r\n+\r\n+    @Override\r\n+    public void create(String path) {\r\n+        String fixedPath = fixNamespace(path);\r\n+        createParentIfAbsent(fixedPath);\r\n+        doCreatePersistent(fixedPath);\r\n+    }\r\n+\r\n+    @Override\r\n+    public long createEphemeral(String path) {\r\n+        String fixedPath = fixNamespace(path);\r\n+        createParentIfAbsent(fixedPath);\r\n+        return doCreateEphemeral(path);\r\n+    }\r\n+\r\n+    @Override\r\n+    public void addStateListener(StateListener listener) {\r\n+        stateListeners.add(listener);\r\n+    }\r\n+\r\n+    @Override\r\n+    public void removeStateListener(StateListener listener) {\r\n+        stateListeners.remove(listener);\r\n+    }\r\n+\r\n+    public Set<StateListener> getSessionListeners() {\r\n+        return stateListeners;\r\n+    }\r\n+\r\n+    @Override\r\n+    public List<String> addChildListener(String path, final ChildListener listener) {\r\n+        ConcurrentMap<ChildListener, WatcherListener> listeners = childListeners.computeIfAbsent(path, k -> new ConcurrentHashMap<>());\r\n+        WatcherListener targetListener = listeners.computeIfAbsent(listener, k -> createChildWatcherListener(path, k));\r\n+        return addChildWatcherListener(path, targetListener);\r\n+    }\r\n+\r\n+    @Override\r\n+    public WatcherListener getChildListener(String path, ChildListener listener) {\r\n+        ConcurrentMap<ChildListener, WatcherListener> listeners = childListeners.get(path);\r\n+        if (listeners == null) {\r\n+            return null;\r\n+        }\r\n+        return listeners.computeIfAbsent(listener, k -> createChildWatcherListener(path, k));\r\n+    }\r\n+\r\n+    @Override\r\n+    public void removeChildListener(String path, ChildListener listener) {\r\n+        ConcurrentMap<ChildListener, WatcherListener> listeners = childListeners.get(path);\r\n+        if (listeners != null) {\r\n+            WatcherListener targetListener = listeners.remove(listener);\r\n+            if (targetListener != null) {\r\n+                removeChildWatcherListener(path, targetListener);\r\n+            }\r\n+        }\r\n+    }\r\n+\r\n+    protected void stateChanged(int state) {\r\n+        for (StateListener sessionListener : getSessionListeners()) {\r\n+            sessionListener.stateChanged(state);\r\n+        }\r\n+    }\r\n+\r\n+    protected String fixNamespace(String path) {\r\n+        if (StringUtils.isEmpty(path)) {\r\n+            throw new IllegalArgumentException(\"path is required, actual null or ''\");\r\n+        }\r\n+        return (path.charAt(0) != '/') ? (PATH_SEPARATOR + path) : path;\r\n+    }\r\n+\r\n+    protected void createParentIfAbsent(String fixedPath) {\r\n+        int i = fixedPath.lastIndexOf('/');\r\n+        if (i > 0) {\r\n+            String parentPath = fixedPath.substring(0, i);\r\n+            if (categories.stream().anyMatch(c -> fixedPath.endsWith(c))) {\r\n+                if (!checkExists(parentPath)) {\r\n+                    this.doCreatePersistent(parentPath);\r\n+                }\r\n+            } else if (categories.stream().anyMatch(c -> parentPath.endsWith(c))) {\r\n+                String grandfather = parentPath.substring(0, parentPath.lastIndexOf('/'));\r\n+                if (!checkExists(grandfather)) {\r\n+                    this.doCreatePersistent(grandfather);\r\n+                }\r\n+            }\r\n+        }\r\n+    }\r\n+\r\n+    @Override\r\n+    public void close() {\r\n+        if (closed) {\r\n+            return;\r\n+        }\r\n+        closed = true;\r\n+        try {\r\n+            doClose();\r\n+        } catch (Throwable t) {\r\n+            logger.warn(t.getMessage(), t);\r\n+        }\r\n+    }\r\n+\r\n+    public abstract void doClose();\r\n+\r\n+    public abstract void doCreatePersistent(String path);\r\n+\r\n+    public abstract long doCreateEphemeral(String path);\r\n+\r\n+    @Override\r\n+    public abstract void delete(String path);\r\n+\r\n+    public abstract boolean checkExists(String path);\r\n+\r\n+    public abstract WatcherListener createChildWatcherListener(String path, ChildListener listener);\r\n+\r\n+    public abstract List<String> addChildWatcherListener(String path, WatcherListener listener);\r\n+\r\n+    public abstract void removeChildWatcherListener(String path, WatcherListener listener);\r\n+\r\n+}\r\n"}, {"source1": "META-INF/maven/org.apache.dubbo/dubbo-remoting-etcd3/pom.xml", "source2": "META-INF/maven/org.apache.dubbo/dubbo-remoting-etcd3/pom.xml", "comments": ["Format-specific differences are supported for XML files but no file-specific differences were detected; falling back to a binary diff. file(1) reports: XML 1.0 document, ASCII text, with CRLF line terminators"], "has_internal_linenos": true, "unified_diff": "@@ -1,231 +1,225 @@\n 00000000: 3c3f 786d 6c20 7665 7273 696f 6e3d 2231  <?xml version=\"1\n 00000010: 2e30 2220 656e 636f 6469 6e67 3d22 5554  .0\" encoding=\"UT\n-00000020: 462d 3822 3f3e 0d0a 3c21 2d2d 0d0a 2020  F-8\"?>..<!--..  \n-00000030: 7e20 4c69 6365 6e73 6564 2074 6f20 7468  ~ Licensed to th\n-00000040: 6520 4170 6163 6865 2053 6f66 7477 6172  e Apache Softwar\n-00000050: 6520 466f 756e 6461 7469 6f6e 2028 4153  e Foundation (AS\n-00000060: 4629 2075 6e64 6572 206f 6e65 206f 7220  F) under one or \n-00000070: 6d6f 7265 0d0a 2020 7e20 636f 6e74 7269  more..  ~ contri\n-00000080: 6275 746f 7220 6c69 6365 6e73 6520 6167  butor license ag\n-00000090: 7265 656d 656e 7473 2e20 2053 6565 2074  reements.  See t\n-000000a0: 6865 204e 4f54 4943 4520 6669 6c65 2064  he NOTICE file d\n-000000b0: 6973 7472 6962 7574 6564 2077 6974 680d  istributed with.\n-000000c0: 0a20 207e 2074 6869 7320 776f 726b 2066  .  ~ this work f\n-000000d0: 6f72 2061 6464 6974 696f 6e61 6c20 696e  or additional in\n-000000e0: 666f 726d 6174 696f 6e20 7265 6761 7264  formation regard\n-000000f0: 696e 6720 636f 7079 7269 6768 7420 6f77  ing copyright ow\n-00000100: 6e65 7273 6869 702e 0d0a 2020 7e20 5468  nership...  ~ Th\n-00000110: 6520 4153 4620 6c69 6365 6e73 6573 2074  e ASF licenses t\n-00000120: 6869 7320 6669 6c65 2074 6f20 596f 7520  his file to You \n-00000130: 756e 6465 7220 7468 6520 4170 6163 6865  under the Apache\n-00000140: 204c 6963 656e 7365 2c20 5665 7273 696f   License, Versio\n-00000150: 6e20 322e 300d 0a20 207e 2028 7468 6520  n 2.0..  ~ (the \n-00000160: 224c 6963 656e 7365 2229 3b20 796f 7520  \"License\"); you \n-00000170: 6d61 7920 6e6f 7420 7573 6520 7468 6973  may not use this\n-00000180: 2066 696c 6520 6578 6365 7074 2069 6e20   file except in \n-00000190: 636f 6d70 6c69 616e 6365 2077 6974 680d  compliance with.\n-000001a0: 0a20 207e 2074 6865 204c 6963 656e 7365  .  ~ the License\n-000001b0: 2e20 2059 6f75 206d 6179 206f 6274 6169  .  You may obtai\n-000001c0: 6e20 6120 636f 7079 206f 6620 7468 6520  n a copy of the \n-000001d0: 4c69 6365 6e73 6520 6174 0d0a 2020 7e0d  License at..  ~.\n-000001e0: 0a20 207e 2020 2020 2068 7474 703a 2f2f  .  ~     http://\n-000001f0: 7777 772e 6170 6163 6865 2e6f 7267 2f6c  www.apache.org/l\n-00000200: 6963 656e 7365 732f 4c49 4345 4e53 452d  icenses/LICENSE-\n-00000210: 322e 300d 0a20 207e 0d0a 2020 7e20 556e  2.0..  ~..  ~ Un\n-00000220: 6c65 7373 2072 6571 7569 7265 6420 6279  less required by\n-00000230: 2061 7070 6c69 6361 626c 6520 6c61 7720   applicable law \n-00000240: 6f72 2061 6772 6565 6420 746f 2069 6e20  or agreed to in \n-00000250: 7772 6974 696e 672c 2073 6f66 7477 6172  writing, softwar\n-00000260: 650d 0a20 207e 2064 6973 7472 6962 7574  e..  ~ distribut\n-00000270: 6564 2075 6e64 6572 2074 6865 204c 6963  ed under the Lic\n-00000280: 656e 7365 2069 7320 6469 7374 7269 6275  ense is distribu\n-00000290: 7465 6420 6f6e 2061 6e20 2241 5320 4953  ted on an \"AS IS\n-000002a0: 2220 4241 5349 532c 0d0a 2020 7e20 5749  \" BASIS,..  ~ WI\n-000002b0: 5448 4f55 5420 5741 5252 414e 5449 4553  THOUT WARRANTIES\n-000002c0: 204f 5220 434f 4e44 4954 494f 4e53 204f   OR CONDITIONS O\n-000002d0: 4620 414e 5920 4b49 4e44 2c20 6569 7468  F ANY KIND, eith\n-000002e0: 6572 2065 7870 7265 7373 206f 7220 696d  er express or im\n-000002f0: 706c 6965 642e 0d0a 2020 7e20 5365 6520  plied...  ~ See \n-00000300: 7468 6520 4c69 6365 6e73 6520 666f 7220  the License for \n-00000310: 7468 6520 7370 6563 6966 6963 206c 616e  the specific lan\n-00000320: 6775 6167 6520 676f 7665 726e 696e 6720  guage governing \n-00000330: 7065 726d 6973 7369 6f6e 7320 616e 640d  permissions and.\n-00000340: 0a20 207e 206c 696d 6974 6174 696f 6e73  .  ~ limitations\n-00000350: 2075 6e64 6572 2074 6865 204c 6963 656e   under the Licen\n-00000360: 7365 2e0d 0a20 202d 2d3e 0d0a 3c70 726f  se...  -->..<pro\n-00000370: 6a65 6374 2078 7369 3a73 6368 656d 614c  ject xsi:schemaL\n-00000380: 6f63 6174 696f 6e3d 2268 7474 703a 2f2f  ocation=\"http://\n-00000390: 6d61 7665 6e2e 6170 6163 6865 2e6f 7267  maven.apache.org\n-000003a0: 2f50 4f4d 2f34 2e30 2e30 2068 7474 7073  /POM/4.0.0 https\n-000003b0: 3a2f 2f6d 6176 656e 2e61 7061 6368 652e  ://maven.apache.\n-000003c0: 6f72 672f 7873 642f 6d61 7665 6e2d 342e  org/xsd/maven-4.\n-000003d0: 302e 302e 7873 6422 2078 6d6c 6e73 3d22  0.0.xsd\" xmlns=\"\n-000003e0: 6874 7470 3a2f 2f6d 6176 656e 2e61 7061  http://maven.apa\n-000003f0: 6368 652e 6f72 672f 504f 4d2f 342e 302e  che.org/POM/4.0.\n-00000400: 3022 0d0a 2020 2020 786d 6c6e 733a 7873  0\"..    xmlns:xs\n-00000410: 693d 2268 7474 703a 2f2f 7777 772e 7733  i=\"http://www.w3\n-00000420: 2e6f 7267 2f32 3030 312f 584d 4c53 6368  .org/2001/XMLSch\n-00000430: 656d 612d 696e 7374 616e 6365 223e 0d0a  ema-instance\">..\n-00000440: 2020 3c6d 6f64 656c 5665 7273 696f 6e3e    <modelVersion>\n-00000450: 342e 302e 303c 2f6d 6f64 656c 5665 7273  4.0.0</modelVers\n-00000460: 696f 6e3e 0d0a 2020 3c70 6172 656e 743e  ion>..  <parent>\n-00000470: 0d0a 2020 2020 3c67 726f 7570 4964 3e6f  ..    <groupId>o\n-00000480: 7267 2e61 7061 6368 652e 6475 6262 6f3c  rg.apache.dubbo<\n-00000490: 2f67 726f 7570 4964 3e0d 0a20 2020 203c  /groupId>..    <\n-000004a0: 6172 7469 6661 6374 4964 3e64 7562 626f  artifactId>dubbo\n-000004b0: 2d72 656d 6f74 696e 673c 2f61 7274 6966  -remoting</artif\n-000004c0: 6163 7449 643e 0d0a 2020 2020 3c76 6572  actId>..    <ver\n-000004d0: 7369 6f6e 3e32 2e37 2e31 303c 2f76 6572  sion>2.7.10</ver\n-000004e0: 7369 6f6e 3e0d 0a20 203c 2f70 6172 656e  sion>..  </paren\n-000004f0: 743e 0d0a 2020 3c67 726f 7570 4964 3e6f  t>..  <groupId>o\n-00000500: 7267 2e61 7061 6368 652e 6475 6262 6f3c  rg.apache.dubbo<\n-00000510: 2f67 726f 7570 4964 3e0d 0a20 203c 6172  /groupId>..  <ar\n-00000520: 7469 6661 6374 4964 3e64 7562 626f 2d72  tifactId>dubbo-r\n-00000530: 656d 6f74 696e 672d 6574 6364 333c 2f61  emoting-etcd3</a\n-00000540: 7274 6966 6163 7449 643e 0d0a 2020 3c76  rtifactId>..  <v\n-00000550: 6572 7369 6f6e 3e32 2e37 2e31 303c 2f76  ersion>2.7.10</v\n-00000560: 6572 7369 6f6e 3e0d 0a20 203c 6e61 6d65  ersion>..  <name\n-00000570: 3e24 7b70 726f 6a65 6374 2e61 7274 6966  >${project.artif\n-00000580: 6163 7449 647d 3c2f 6e61 6d65 3e0d 0a20  actId}</name>.. \n-00000590: 203c 6465 7363 7269 7074 696f 6e3e 5468   <description>Th\n-000005a0: 6520 6574 6364 3320 7265 6d6f 7469 6e67  e etcd3 remoting\n-000005b0: 206d 6f64 756c 6520 6f66 2044 7562 626f   module of Dubbo\n-000005c0: 2070 726f 6a65 6374 3c2f 6465 7363 7269   project</descri\n-000005d0: 7074 696f 6e3e 0d0a 2020 3c6c 6963 656e  ption>..  <licen\n-000005e0: 7365 733e 0d0a 2020 2020 3c6c 6963 656e  ses>..    <licen\n-000005f0: 7365 3e0d 0a20 2020 2020 203c 6e61 6d65  se>..      <name\n-00000600: 3e41 7061 6368 6520 4c69 6365 6e73 652c  >Apache License,\n-00000610: 2056 6572 7369 6f6e 2032 2e30 3c2f 6e61   Version 2.0</na\n-00000620: 6d65 3e0d 0a20 2020 2020 203c 7572 6c3e  me>..      <url>\n-00000630: 6874 7470 3a2f 2f77 7777 2e61 7061 6368  http://www.apach\n-00000640: 652e 6f72 672f 6c69 6365 6e73 6573 2f4c  e.org/licenses/L\n-00000650: 4943 454e 5345 2d32 2e30 3c2f 7572 6c3e  ICENSE-2.0</url>\n-00000660: 0d0a 2020 2020 2020 3c64 6973 7472 6962  ..      <distrib\n-00000670: 7574 696f 6e3e 7265 706f 3c2f 6469 7374  ution>repo</dist\n-00000680: 7269 6275 7469 6f6e 3e0d 0a20 2020 203c  ribution>..    <\n-00000690: 2f6c 6963 656e 7365 3e0d 0a20 203c 2f6c  /license>..  </l\n-000006a0: 6963 656e 7365 733e 0d0a 2020 3c70 726f  icenses>..  <pro\n-000006b0: 7065 7274 6965 733e 0d0a 2020 2020 3c73  perties>..    <s\n-000006c0: 6b69 7049 6e74 6567 7261 7469 6f6e 5465  kipIntegrationTe\n-000006d0: 7374 733e 7472 7565 3c2f 736b 6970 496e  sts>true</skipIn\n-000006e0: 7465 6772 6174 696f 6e54 6573 7473 3e0d  tegrationTests>.\n-000006f0: 0a20 2020 203c 736b 6970 5f6d 6176 656e  .    <skip_maven\n-00000700: 5f64 6570 6c6f 793e 6661 6c73 653c 2f73  _deploy>false</s\n-00000710: 6b69 705f 6d61 7665 6e5f 6465 706c 6f79  kip_maven_deploy\n-00000720: 3e0d 0a20 2020 203c 6173 7365 7274 6a2e  >..    <assertj.\n-00000730: 7665 7273 696f 6e3e 332e 3133 2e32 3c2f  version>3.13.2</\n-00000740: 6173 7365 7274 6a2e 7665 7273 696f 6e3e  assertj.version>\n-00000750: 0d0a 2020 3c2f 7072 6f70 6572 7469 6573  ..  </properties\n-00000760: 3e0d 0a20 203c 6465 7065 6e64 656e 6369  >..  <dependenci\n-00000770: 6573 3e0d 0a20 2020 203c 6465 7065 6e64  es>..    <depend\n-00000780: 656e 6379 3e0d 0a20 2020 2020 203c 6772  ency>..      <gr\n-00000790: 6f75 7049 643e 6f72 672e 6170 6163 6865  oupId>org.apache\n-000007a0: 2e64 7562 626f 3c2f 6772 6f75 7049 643e  .dubbo</groupId>\n-000007b0: 0d0a 2020 2020 2020 3c61 7274 6966 6163  ..      <artifac\n-000007c0: 7449 643e 6475 6262 6f2d 7265 6d6f 7469  tId>dubbo-remoti\n-000007d0: 6e67 2d61 7069 3c2f 6172 7469 6661 6374  ng-api</artifact\n-000007e0: 4964 3e0d 0a20 2020 2020 203c 7665 7273  Id>..      <vers\n-000007f0: 696f 6e3e 247b 7072 6f6a 6563 742e 7061  ion>${project.pa\n-00000800: 7265 6e74 2e76 6572 7369 6f6e 7d3c 2f76  rent.version}</v\n-00000810: 6572 7369 6f6e 3e0d 0a20 2020 203c 2f64  ersion>..    </d\n-00000820: 6570 656e 6465 6e63 793e 0d0a 2020 2020  ependency>..    \n-00000830: 3c64 6570 656e 6465 6e63 793e 0d0a 2020  <dependency>..  \n-00000840: 2020 2020 3c67 726f 7570 4964 3e6f 7267      <groupId>org\n-00000850: 2e61 7061 6368 652e 6475 6262 6f3c 2f67  .apache.dubbo</g\n-00000860: 726f 7570 4964 3e0d 0a20 2020 2020 203c  roupId>..      <\n-00000870: 6172 7469 6661 6374 4964 3e64 7562 626f  artifactId>dubbo\n-00000880: 2d63 6f6d 6d6f 6e3c 2f61 7274 6966 6163  -common</artifac\n-00000890: 7449 643e 0d0a 2020 2020 2020 3c76 6572  tId>..      <ver\n-000008a0: 7369 6f6e 3e24 7b70 726f 6a65 6374 2e70  sion>${project.p\n-000008b0: 6172 656e 742e 7665 7273 696f 6e7d 3c2f  arent.version}</\n-000008c0: 7665 7273 696f 6e3e 0d0a 2020 2020 3c2f  version>..    </\n-000008d0: 6465 7065 6e64 656e 6379 3e0d 0a20 2020  dependency>..   \n-000008e0: 203c 6465 7065 6e64 656e 6379 3e0d 0a20   <dependency>.. \n-000008f0: 2020 2020 203c 6772 6f75 7049 643e 696f       <groupId>io\n-00000900: 2e65 7463 643c 2f67 726f 7570 4964 3e0d  .etcd</groupId>.\n-00000910: 0a20 2020 2020 203c 6172 7469 6661 6374  .      <artifact\n-00000920: 4964 3e6a 6574 6364 2d63 6f72 653c 2f61  Id>jetcd-core</a\n-00000930: 7274 6966 6163 7449 643e 0d0a 2020 2020  rtifactId>..    \n-00000940: 3c2f 6465 7065 6e64 656e 6379 3e0d 0a20  </dependency>.. \n-00000950: 2020 203c 6465 7065 6e64 656e 6379 3e0d     <dependency>.\n-00000960: 0a20 2020 2020 203c 6772 6f75 7049 643e  .      <groupId>\n-00000970: 696f 2e67 7270 633c 2f67 726f 7570 4964  io.grpc</groupId\n-00000980: 3e0d 0a20 2020 2020 203c 6172 7469 6661  >..      <artifa\n-00000990: 6374 4964 3e67 7270 632d 636f 7265 3c2f  ctId>grpc-core</\n-000009a0: 6172 7469 6661 6374 4964 3e0d 0a20 2020  artifactId>..   \n-000009b0: 203c 2f64 6570 656e 6465 6e63 793e 0d0a   </dependency>..\n-000009c0: 2020 2020 3c64 6570 656e 6465 6e63 793e      <dependency>\n-000009d0: 0d0a 2020 2020 2020 3c67 726f 7570 4964  ..      <groupId\n-000009e0: 3e69 6f2e 6772 7063 3c2f 6772 6f75 7049  >io.grpc</groupI\n-000009f0: 643e 0d0a 2020 2020 2020 3c61 7274 6966  d>..      <artif\n-00000a00: 6163 7449 643e 6772 7063 2d6e 6574 7479  actId>grpc-netty\n-00000a10: 3c2f 6172 7469 6661 6374 4964 3e0d 0a20  </artifactId>.. \n-00000a20: 2020 203c 2f64 6570 656e 6465 6e63 793e     </dependency>\n-00000a30: 0d0a 2020 2020 3c64 6570 656e 6465 6e63  ..    <dependenc\n-00000a40: 793e 0d0a 2020 2020 2020 3c67 726f 7570  y>..      <group\n-00000a50: 4964 3e69 6f2e 6772 7063 3c2f 6772 6f75  Id>io.grpc</grou\n-00000a60: 7049 643e 0d0a 2020 2020 2020 3c61 7274  pId>..      <art\n-00000a70: 6966 6163 7449 643e 6772 7063 2d70 726f  ifactId>grpc-pro\n-00000a80: 746f 6275 663c 2f61 7274 6966 6163 7449  tobuf</artifactI\n-00000a90: 643e 0d0a 2020 2020 3c2f 6465 7065 6e64  d>..    </depend\n-00000aa0: 656e 6379 3e0d 0a20 2020 203c 6465 7065  ency>..    <depe\n-00000ab0: 6e64 656e 6379 3e0d 0a20 2020 2020 203c  ndency>..      <\n-00000ac0: 6772 6f75 7049 643e 696f 2e67 7270 633c  groupId>io.grpc<\n-00000ad0: 2f67 726f 7570 4964 3e0d 0a20 2020 2020  /groupId>..     \n-00000ae0: 203c 6172 7469 6661 6374 4964 3e67 7270   <artifactId>grp\n-00000af0: 632d 7374 7562 3c2f 6172 7469 6661 6374  c-stub</artifact\n-00000b00: 4964 3e0d 0a20 2020 203c 2f64 6570 656e  Id>..    </depen\n-00000b10: 6465 6e63 793e 0d0a 2020 2020 3c64 6570  dency>..    <dep\n-00000b20: 656e 6465 6e63 793e 0d0a 2020 2020 2020  endency>..      \n-00000b30: 3c67 726f 7570 4964 3e69 6f2e 6772 7063  <groupId>io.grpc\n-00000b40: 3c2f 6772 6f75 7049 643e 0d0a 2020 2020  </groupId>..    \n-00000b50: 2020 3c61 7274 6966 6163 7449 643e 6772    <artifactId>gr\n-00000b60: 7063 2d67 7270 636c 623c 2f61 7274 6966  pc-grpclb</artif\n-00000b70: 6163 7449 643e 0d0a 2020 2020 3c2f 6465  actId>..    </de\n-00000b80: 7065 6e64 656e 6379 3e0d 0a20 2020 203c  pendency>..    <\n-00000b90: 6465 7065 6e64 656e 6379 3e0d 0a20 2020  dependency>..   \n-00000ba0: 2020 203c 6772 6f75 7049 643e 696f 2e65     <groupId>io.e\n-00000bb0: 7463 643c 2f67 726f 7570 4964 3e0d 0a20  tcd</groupId>.. \n-00000bc0: 2020 2020 203c 6172 7469 6661 6374 4964       <artifactId\n-00000bd0: 3e6a 6574 6364 2d6c 6175 6e63 6865 723c  >jetcd-launcher<\n-00000be0: 2f61 7274 6966 6163 7449 643e 0d0a 2020  /artifactId>..  \n-00000bf0: 2020 2020 3c73 636f 7065 3e74 6573 743c      <scope>test<\n-00000c00: 2f73 636f 7065 3e0d 0a20 2020 203c 2f64  /scope>..    </d\n-00000c10: 6570 656e 6465 6e63 793e 0d0a 2020 2020  ependency>..    \n-00000c20: 3c64 6570 656e 6465 6e63 793e 0d0a 2020  <dependency>..  \n-00000c30: 2020 2020 3c67 726f 7570 4964 3e69 6f2e      <groupId>io.\n-00000c40: 6e65 7474 793c 2f67 726f 7570 4964 3e0d  netty</groupId>.\n-00000c50: 0a20 2020 2020 203c 6172 7469 6661 6374  .      <artifact\n-00000c60: 4964 3e6e 6574 7479 2d61 6c6c 3c2f 6172  Id>netty-all</ar\n-00000c70: 7469 6661 6374 4964 3e0d 0a20 2020 203c  tifactId>..    <\n-00000c80: 2f64 6570 656e 6465 6e63 793e 0d0a 2020  /dependency>..  \n-00000c90: 2020 3c64 6570 656e 6465 6e63 793e 0d0a    <dependency>..\n-00000ca0: 2020 2020 2020 3c67 726f 7570 4964 3e6f        <groupId>o\n-00000cb0: 7267 2e61 7373 6572 746a 3c2f 6772 6f75  rg.assertj</grou\n-00000cc0: 7049 643e 0d0a 2020 2020 2020 3c61 7274  pId>..      <art\n-00000cd0: 6966 6163 7449 643e 6173 7365 7274 6a2d  ifactId>assertj-\n-00000ce0: 636f 7265 3c2f 6172 7469 6661 6374 4964  core</artifactId\n-00000cf0: 3e0d 0a20 2020 2020 203c 7665 7273 696f  >..      <versio\n-00000d00: 6e3e 247b 6173 7365 7274 6a2e 7665 7273  n>${assertj.vers\n-00000d10: 696f 6e7d 3c2f 7665 7273 696f 6e3e 0d0a  ion}</version>..\n-00000d20: 2020 2020 2020 3c73 636f 7065 3e74 6573        <scope>tes\n-00000d30: 743c 2f73 636f 7065 3e0d 0a20 2020 203c  t</scope>..    <\n-00000d40: 2f64 6570 656e 6465 6e63 793e 0d0a 2020  /dependency>..  \n-00000d50: 3c2f 6465 7065 6e64 656e 6369 6573 3e0d  </dependencies>.\n-00000d60: 0a20 203c 6275 696c 643e 0d0a 2020 2020  .  <build>..    \n-00000d70: 3c70 6c75 6769 6e73 3e0d 0a20 2020 2020  <plugins>..     \n-00000d80: 203c 706c 7567 696e 3e0d 0a20 2020 2020   <plugin>..     \n-00000d90: 2020 203c 6172 7469 6661 6374 4964 3e6d     <artifactId>m\n-00000da0: 6176 656e 2d73 7572 6566 6972 652d 706c  aven-surefire-pl\n-00000db0: 7567 696e 3c2f 6172 7469 6661 6374 4964  ugin</artifactId\n-00000dc0: 3e0d 0a20 2020 2020 2020 203c 636f 6e66  >..        <conf\n-00000dd0: 6967 7572 6174 696f 6e3e 0d0a 2020 2020  iguration>..    \n-00000de0: 2020 2020 2020 3c73 6b69 7054 6573 7473        <skipTests\n-00000df0: 3e24 7b73 6b69 7049 6e74 6567 7261 7469  >${skipIntegrati\n-00000e00: 6f6e 5465 7374 737d 3c2f 736b 6970 5465  onTests}</skipTe\n-00000e10: 7374 733e 0d0a 2020 2020 2020 2020 3c2f  sts>..        </\n-00000e20: 636f 6e66 6967 7572 6174 696f 6e3e 0d0a  configuration>..\n-00000e30: 2020 2020 2020 3c2f 706c 7567 696e 3e0d        </plugin>.\n-00000e40: 0a20 2020 203c 2f70 6c75 6769 6e73 3e0d  .    </plugins>.\n-00000e50: 0a20 203c 2f62 7569 6c64 3e0d 0a3c 2f70  .  </build>..</p\n-00000e60: 726f 6a65 6374 3e0d 0a                   roject>..\n+00000020: 462d 3822 3f3e 0a3c 212d 2d0a 2020 7e20  F-8\"?>.<!--.  ~ \n+00000030: 4c69 6365 6e73 6564 2074 6f20 7468 6520  Licensed to the \n+00000040: 4170 6163 6865 2053 6f66 7477 6172 6520  Apache Software \n+00000050: 466f 756e 6461 7469 6f6e 2028 4153 4629  Foundation (ASF)\n+00000060: 2075 6e64 6572 206f 6e65 206f 7220 6d6f   under one or mo\n+00000070: 7265 0a20 207e 2063 6f6e 7472 6962 7574  re.  ~ contribut\n+00000080: 6f72 206c 6963 656e 7365 2061 6772 6565  or license agree\n+00000090: 6d65 6e74 732e 2020 5365 6520 7468 6520  ments.  See the \n+000000a0: 4e4f 5449 4345 2066 696c 6520 6469 7374  NOTICE file dist\n+000000b0: 7269 6275 7465 6420 7769 7468 0a20 207e  ributed with.  ~\n+000000c0: 2074 6869 7320 776f 726b 2066 6f72 2061   this work for a\n+000000d0: 6464 6974 696f 6e61 6c20 696e 666f 726d  dditional inform\n+000000e0: 6174 696f 6e20 7265 6761 7264 696e 6720  ation regarding \n+000000f0: 636f 7079 7269 6768 7420 6f77 6e65 7273  copyright owners\n+00000100: 6869 702e 0a20 207e 2054 6865 2041 5346  hip..  ~ The ASF\n+00000110: 206c 6963 656e 7365 7320 7468 6973 2066   licenses this f\n+00000120: 696c 6520 746f 2059 6f75 2075 6e64 6572  ile to You under\n+00000130: 2074 6865 2041 7061 6368 6520 4c69 6365   the Apache Lice\n+00000140: 6e73 652c 2056 6572 7369 6f6e 2032 2e30  nse, Version 2.0\n+00000150: 0a20 207e 2028 7468 6520 224c 6963 656e  .  ~ (the \"Licen\n+00000160: 7365 2229 3b20 796f 7520 6d61 7920 6e6f  se\"); you may no\n+00000170: 7420 7573 6520 7468 6973 2066 696c 6520  t use this file \n+00000180: 6578 6365 7074 2069 6e20 636f 6d70 6c69  except in compli\n+00000190: 616e 6365 2077 6974 680a 2020 7e20 7468  ance with.  ~ th\n+000001a0: 6520 4c69 6365 6e73 652e 2020 596f 7520  e License.  You \n+000001b0: 6d61 7920 6f62 7461 696e 2061 2063 6f70  may obtain a cop\n+000001c0: 7920 6f66 2074 6865 204c 6963 656e 7365  y of the License\n+000001d0: 2061 740a 2020 7e0a 2020 7e20 2020 2020   at.  ~.  ~     \n+000001e0: 6874 7470 3a2f 2f77 7777 2e61 7061 6368  http://www.apach\n+000001f0: 652e 6f72 672f 6c69 6365 6e73 6573 2f4c  e.org/licenses/L\n+00000200: 4943 454e 5345 2d32 2e30 0a20 207e 0a20  ICENSE-2.0.  ~. \n+00000210: 207e 2055 6e6c 6573 7320 7265 7175 6972   ~ Unless requir\n+00000220: 6564 2062 7920 6170 706c 6963 6162 6c65  ed by applicable\n+00000230: 206c 6177 206f 7220 6167 7265 6564 2074   law or agreed t\n+00000240: 6f20 696e 2077 7269 7469 6e67 2c20 736f  o in writing, so\n+00000250: 6674 7761 7265 0a20 207e 2064 6973 7472  ftware.  ~ distr\n+00000260: 6962 7574 6564 2075 6e64 6572 2074 6865  ibuted under the\n+00000270: 204c 6963 656e 7365 2069 7320 6469 7374   License is dist\n+00000280: 7269 6275 7465 6420 6f6e 2061 6e20 2241  ributed on an \"A\n+00000290: 5320 4953 2220 4241 5349 532c 0a20 207e  S IS\" BASIS,.  ~\n+000002a0: 2057 4954 484f 5554 2057 4152 5241 4e54   WITHOUT WARRANT\n+000002b0: 4945 5320 4f52 2043 4f4e 4449 5449 4f4e  IES OR CONDITION\n+000002c0: 5320 4f46 2041 4e59 204b 494e 442c 2065  S OF ANY KIND, e\n+000002d0: 6974 6865 7220 6578 7072 6573 7320 6f72  ither express or\n+000002e0: 2069 6d70 6c69 6564 2e0a 2020 7e20 5365   implied..  ~ Se\n+000002f0: 6520 7468 6520 4c69 6365 6e73 6520 666f  e the License fo\n+00000300: 7220 7468 6520 7370 6563 6966 6963 206c  r the specific l\n+00000310: 616e 6775 6167 6520 676f 7665 726e 696e  anguage governin\n+00000320: 6720 7065 726d 6973 7369 6f6e 7320 616e  g permissions an\n+00000330: 640a 2020 7e20 6c69 6d69 7461 7469 6f6e  d.  ~ limitation\n+00000340: 7320 756e 6465 7220 7468 6520 4c69 6365  s under the Lice\n+00000350: 6e73 652e 0a20 202d 2d3e 0a3c 7072 6f6a  nse..  -->.<proj\n+00000360: 6563 7420 7873 693a 7363 6865 6d61 4c6f  ect xsi:schemaLo\n+00000370: 6361 7469 6f6e 3d22 6874 7470 3a2f 2f6d  cation=\"http://m\n+00000380: 6176 656e 2e61 7061 6368 652e 6f72 672f  aven.apache.org/\n+00000390: 504f 4d2f 342e 302e 3020 6874 7470 733a  POM/4.0.0 https:\n+000003a0: 2f2f 6d61 7665 6e2e 6170 6163 6865 2e6f  //maven.apache.o\n+000003b0: 7267 2f78 7364 2f6d 6176 656e 2d34 2e30  rg/xsd/maven-4.0\n+000003c0: 2e30 2e78 7364 2220 786d 6c6e 733d 2268  .0.xsd\" xmlns=\"h\n+000003d0: 7474 703a 2f2f 6d61 7665 6e2e 6170 6163  ttp://maven.apac\n+000003e0: 6865 2e6f 7267 2f50 4f4d 2f34 2e30 2e30  he.org/POM/4.0.0\n+000003f0: 220a 2020 2020 786d 6c6e 733a 7873 693d  \".    xmlns:xsi=\n+00000400: 2268 7474 703a 2f2f 7777 772e 7733 2e6f  \"http://www.w3.o\n+00000410: 7267 2f32 3030 312f 584d 4c53 6368 656d  rg/2001/XMLSchem\n+00000420: 612d 696e 7374 616e 6365 223e 0a20 203c  a-instance\">.  <\n+00000430: 6d6f 6465 6c56 6572 7369 6f6e 3e34 2e30  modelVersion>4.0\n+00000440: 2e30 3c2f 6d6f 6465 6c56 6572 7369 6f6e  .0</modelVersion\n+00000450: 3e0a 2020 3c70 6172 656e 743e 0a20 2020  >.  <parent>.   \n+00000460: 203c 6772 6f75 7049 643e 6f72 672e 6170   <groupId>org.ap\n+00000470: 6163 6865 2e64 7562 626f 3c2f 6772 6f75  ache.dubbo</grou\n+00000480: 7049 643e 0a20 2020 203c 6172 7469 6661  pId>.    <artifa\n+00000490: 6374 4964 3e64 7562 626f 2d72 656d 6f74  ctId>dubbo-remot\n+000004a0: 696e 673c 2f61 7274 6966 6163 7449 643e  ing</artifactId>\n+000004b0: 0a20 2020 203c 7665 7273 696f 6e3e 322e  .    <version>2.\n+000004c0: 372e 3130 3c2f 7665 7273 696f 6e3e 0a20  7.10</version>. \n+000004d0: 203c 2f70 6172 656e 743e 0a20 203c 6772   </parent>.  <gr\n+000004e0: 6f75 7049 643e 6f72 672e 6170 6163 6865  oupId>org.apache\n+000004f0: 2e64 7562 626f 3c2f 6772 6f75 7049 643e  .dubbo</groupId>\n+00000500: 0a20 203c 6172 7469 6661 6374 4964 3e64  .  <artifactId>d\n+00000510: 7562 626f 2d72 656d 6f74 696e 672d 6574  ubbo-remoting-et\n+00000520: 6364 333c 2f61 7274 6966 6163 7449 643e  cd3</artifactId>\n+00000530: 0a20 203c 7665 7273 696f 6e3e 322e 372e  .  <version>2.7.\n+00000540: 3130 3c2f 7665 7273 696f 6e3e 0a20 203c  10</version>.  <\n+00000550: 6e61 6d65 3e24 7b70 726f 6a65 6374 2e61  name>${project.a\n+00000560: 7274 6966 6163 7449 647d 3c2f 6e61 6d65  rtifactId}</name\n+00000570: 3e0a 2020 3c64 6573 6372 6970 7469 6f6e  >.  <description\n+00000580: 3e54 6865 2065 7463 6433 2072 656d 6f74  >The etcd3 remot\n+00000590: 696e 6720 6d6f 6475 6c65 206f 6620 4475  ing module of Du\n+000005a0: 6262 6f20 7072 6f6a 6563 743c 2f64 6573  bbo project</des\n+000005b0: 6372 6970 7469 6f6e 3e0a 2020 3c6c 6963  cription>.  <lic\n+000005c0: 656e 7365 733e 0a20 2020 203c 6c69 6365  enses>.    <lice\n+000005d0: 6e73 653e 0a20 2020 2020 203c 6e61 6d65  nse>.      <name\n+000005e0: 3e41 7061 6368 6520 4c69 6365 6e73 652c  >Apache License,\n+000005f0: 2056 6572 7369 6f6e 2032 2e30 3c2f 6e61   Version 2.0</na\n+00000600: 6d65 3e0a 2020 2020 2020 3c75 726c 3e68  me>.      <url>h\n+00000610: 7474 703a 2f2f 7777 772e 6170 6163 6865  ttp://www.apache\n+00000620: 2e6f 7267 2f6c 6963 656e 7365 732f 4c49  .org/licenses/LI\n+00000630: 4345 4e53 452d 322e 303c 2f75 726c 3e0a  CENSE-2.0</url>.\n+00000640: 2020 2020 2020 3c64 6973 7472 6962 7574        <distribut\n+00000650: 696f 6e3e 7265 706f 3c2f 6469 7374 7269  ion>repo</distri\n+00000660: 6275 7469 6f6e 3e0a 2020 2020 3c2f 6c69  bution>.    </li\n+00000670: 6365 6e73 653e 0a20 203c 2f6c 6963 656e  cense>.  </licen\n+00000680: 7365 733e 0a20 203c 7072 6f70 6572 7469  ses>.  <properti\n+00000690: 6573 3e0a 2020 2020 3c73 6b69 7049 6e74  es>.    <skipInt\n+000006a0: 6567 7261 7469 6f6e 5465 7374 733e 7472  egrationTests>tr\n+000006b0: 7565 3c2f 736b 6970 496e 7465 6772 6174  ue</skipIntegrat\n+000006c0: 696f 6e54 6573 7473 3e0a 2020 2020 3c73  ionTests>.    <s\n+000006d0: 6b69 705f 6d61 7665 6e5f 6465 706c 6f79  kip_maven_deploy\n+000006e0: 3e66 616c 7365 3c2f 736b 6970 5f6d 6176  >false</skip_mav\n+000006f0: 656e 5f64 6570 6c6f 793e 0a20 2020 203c  en_deploy>.    <\n+00000700: 6173 7365 7274 6a2e 7665 7273 696f 6e3e  assertj.version>\n+00000710: 332e 3133 2e32 3c2f 6173 7365 7274 6a2e  3.13.2</assertj.\n+00000720: 7665 7273 696f 6e3e 0a20 203c 2f70 726f  version>.  </pro\n+00000730: 7065 7274 6965 733e 0a20 203c 6465 7065  perties>.  <depe\n+00000740: 6e64 656e 6369 6573 3e0a 2020 2020 3c64  ndencies>.    <d\n+00000750: 6570 656e 6465 6e63 793e 0a20 2020 2020  ependency>.     \n+00000760: 203c 6772 6f75 7049 643e 6f72 672e 6170   <groupId>org.ap\n+00000770: 6163 6865 2e64 7562 626f 3c2f 6772 6f75  ache.dubbo</grou\n+00000780: 7049 643e 0a20 2020 2020 203c 6172 7469  pId>.      <arti\n+00000790: 6661 6374 4964 3e64 7562 626f 2d72 656d  factId>dubbo-rem\n+000007a0: 6f74 696e 672d 6170 693c 2f61 7274 6966  oting-api</artif\n+000007b0: 6163 7449 643e 0a20 2020 2020 203c 7665  actId>.      <ve\n+000007c0: 7273 696f 6e3e 247b 7072 6f6a 6563 742e  rsion>${project.\n+000007d0: 7061 7265 6e74 2e76 6572 7369 6f6e 7d3c  parent.version}<\n+000007e0: 2f76 6572 7369 6f6e 3e0a 2020 2020 3c2f  /version>.    </\n+000007f0: 6465 7065 6e64 656e 6379 3e0a 2020 2020  dependency>.    \n+00000800: 3c64 6570 656e 6465 6e63 793e 0a20 2020  <dependency>.   \n+00000810: 2020 203c 6772 6f75 7049 643e 6f72 672e     <groupId>org.\n+00000820: 6170 6163 6865 2e64 7562 626f 3c2f 6772  apache.dubbo</gr\n+00000830: 6f75 7049 643e 0a20 2020 2020 203c 6172  oupId>.      <ar\n+00000840: 7469 6661 6374 4964 3e64 7562 626f 2d63  tifactId>dubbo-c\n+00000850: 6f6d 6d6f 6e3c 2f61 7274 6966 6163 7449  ommon</artifactI\n+00000860: 643e 0a20 2020 2020 203c 7665 7273 696f  d>.      <versio\n+00000870: 6e3e 247b 7072 6f6a 6563 742e 7061 7265  n>${project.pare\n+00000880: 6e74 2e76 6572 7369 6f6e 7d3c 2f76 6572  nt.version}</ver\n+00000890: 7369 6f6e 3e0a 2020 2020 3c2f 6465 7065  sion>.    </depe\n+000008a0: 6e64 656e 6379 3e0a 2020 2020 3c64 6570  ndency>.    <dep\n+000008b0: 656e 6465 6e63 793e 0a20 2020 2020 203c  endency>.      <\n+000008c0: 6772 6f75 7049 643e 696f 2e65 7463 643c  groupId>io.etcd<\n+000008d0: 2f67 726f 7570 4964 3e0a 2020 2020 2020  /groupId>.      \n+000008e0: 3c61 7274 6966 6163 7449 643e 6a65 7463  <artifactId>jetc\n+000008f0: 642d 636f 7265 3c2f 6172 7469 6661 6374  d-core</artifact\n+00000900: 4964 3e0a 2020 2020 3c2f 6465 7065 6e64  Id>.    </depend\n+00000910: 656e 6379 3e0a 2020 2020 3c64 6570 656e  ency>.    <depen\n+00000920: 6465 6e63 793e 0a20 2020 2020 203c 6772  dency>.      <gr\n+00000930: 6f75 7049 643e 696f 2e67 7270 633c 2f67  oupId>io.grpc</g\n+00000940: 726f 7570 4964 3e0a 2020 2020 2020 3c61  roupId>.      <a\n+00000950: 7274 6966 6163 7449 643e 6772 7063 2d63  rtifactId>grpc-c\n+00000960: 6f72 653c 2f61 7274 6966 6163 7449 643e  ore</artifactId>\n+00000970: 0a20 2020 203c 2f64 6570 656e 6465 6e63  .    </dependenc\n+00000980: 793e 0a20 2020 203c 6465 7065 6e64 656e  y>.    <dependen\n+00000990: 6379 3e0a 2020 2020 2020 3c67 726f 7570  cy>.      <group\n+000009a0: 4964 3e69 6f2e 6772 7063 3c2f 6772 6f75  Id>io.grpc</grou\n+000009b0: 7049 643e 0a20 2020 2020 203c 6172 7469  pId>.      <arti\n+000009c0: 6661 6374 4964 3e67 7270 632d 6e65 7474  factId>grpc-nett\n+000009d0: 793c 2f61 7274 6966 6163 7449 643e 0a20  y</artifactId>. \n+000009e0: 2020 203c 2f64 6570 656e 6465 6e63 793e     </dependency>\n+000009f0: 0a20 2020 203c 6465 7065 6e64 656e 6379  .    <dependency\n+00000a00: 3e0a 2020 2020 2020 3c67 726f 7570 4964  >.      <groupId\n+00000a10: 3e69 6f2e 6772 7063 3c2f 6772 6f75 7049  >io.grpc</groupI\n+00000a20: 643e 0a20 2020 2020 203c 6172 7469 6661  d>.      <artifa\n+00000a30: 6374 4964 3e67 7270 632d 7072 6f74 6f62  ctId>grpc-protob\n+00000a40: 7566 3c2f 6172 7469 6661 6374 4964 3e0a  uf</artifactId>.\n+00000a50: 2020 2020 3c2f 6465 7065 6e64 656e 6379      </dependency\n+00000a60: 3e0a 2020 2020 3c64 6570 656e 6465 6e63  >.    <dependenc\n+00000a70: 793e 0a20 2020 2020 203c 6772 6f75 7049  y>.      <groupI\n+00000a80: 643e 696f 2e67 7270 633c 2f67 726f 7570  d>io.grpc</group\n+00000a90: 4964 3e0a 2020 2020 2020 3c61 7274 6966  Id>.      <artif\n+00000aa0: 6163 7449 643e 6772 7063 2d73 7475 623c  actId>grpc-stub<\n+00000ab0: 2f61 7274 6966 6163 7449 643e 0a20 2020  /artifactId>.   \n+00000ac0: 203c 2f64 6570 656e 6465 6e63 793e 0a20   </dependency>. \n+00000ad0: 2020 203c 6465 7065 6e64 656e 6379 3e0a     <dependency>.\n+00000ae0: 2020 2020 2020 3c67 726f 7570 4964 3e69        <groupId>i\n+00000af0: 6f2e 6772 7063 3c2f 6772 6f75 7049 643e  o.grpc</groupId>\n+00000b00: 0a20 2020 2020 203c 6172 7469 6661 6374  .      <artifact\n+00000b10: 4964 3e67 7270 632d 6772 7063 6c62 3c2f  Id>grpc-grpclb</\n+00000b20: 6172 7469 6661 6374 4964 3e0a 2020 2020  artifactId>.    \n+00000b30: 3c2f 6465 7065 6e64 656e 6379 3e0a 2020  </dependency>.  \n+00000b40: 2020 3c64 6570 656e 6465 6e63 793e 0a20    <dependency>. \n+00000b50: 2020 2020 203c 6772 6f75 7049 643e 696f       <groupId>io\n+00000b60: 2e65 7463 643c 2f67 726f 7570 4964 3e0a  .etcd</groupId>.\n+00000b70: 2020 2020 2020 3c61 7274 6966 6163 7449        <artifactI\n+00000b80: 643e 6a65 7463 642d 6c61 756e 6368 6572  d>jetcd-launcher\n+00000b90: 3c2f 6172 7469 6661 6374 4964 3e0a 2020  </artifactId>.  \n+00000ba0: 2020 2020 3c73 636f 7065 3e74 6573 743c      <scope>test<\n+00000bb0: 2f73 636f 7065 3e0a 2020 2020 3c2f 6465  /scope>.    </de\n+00000bc0: 7065 6e64 656e 6379 3e0a 2020 2020 3c64  pendency>.    <d\n+00000bd0: 6570 656e 6465 6e63 793e 0a20 2020 2020  ependency>.     \n+00000be0: 203c 6772 6f75 7049 643e 696f 2e6e 6574   <groupId>io.net\n+00000bf0: 7479 3c2f 6772 6f75 7049 643e 0a20 2020  ty</groupId>.   \n+00000c00: 2020 203c 6172 7469 6661 6374 4964 3e6e     <artifactId>n\n+00000c10: 6574 7479 2d61 6c6c 3c2f 6172 7469 6661  etty-all</artifa\n+00000c20: 6374 4964 3e0a 2020 2020 3c2f 6465 7065  ctId>.    </depe\n+00000c30: 6e64 656e 6379 3e0a 2020 2020 3c64 6570  ndency>.    <dep\n+00000c40: 656e 6465 6e63 793e 0a20 2020 2020 203c  endency>.      <\n+00000c50: 6772 6f75 7049 643e 6f72 672e 6173 7365  groupId>org.asse\n+00000c60: 7274 6a3c 2f67 726f 7570 4964 3e0a 2020  rtj</groupId>.  \n+00000c70: 2020 2020 3c61 7274 6966 6163 7449 643e      <artifactId>\n+00000c80: 6173 7365 7274 6a2d 636f 7265 3c2f 6172  assertj-core</ar\n+00000c90: 7469 6661 6374 4964 3e0a 2020 2020 2020  tifactId>.      \n+00000ca0: 3c76 6572 7369 6f6e 3e24 7b61 7373 6572  <version>${asser\n+00000cb0: 746a 2e76 6572 7369 6f6e 7d3c 2f76 6572  tj.version}</ver\n+00000cc0: 7369 6f6e 3e0a 2020 2020 2020 3c73 636f  sion>.      <sco\n+00000cd0: 7065 3e74 6573 743c 2f73 636f 7065 3e0a  pe>test</scope>.\n+00000ce0: 2020 2020 3c2f 6465 7065 6e64 656e 6379      </dependency\n+00000cf0: 3e0a 2020 3c2f 6465 7065 6e64 656e 6369  >.  </dependenci\n+00000d00: 6573 3e0a 2020 3c62 7569 6c64 3e0a 2020  es>.  <build>.  \n+00000d10: 2020 3c70 6c75 6769 6e73 3e0a 2020 2020    <plugins>.    \n+00000d20: 2020 3c70 6c75 6769 6e3e 0a20 2020 2020    <plugin>.     \n+00000d30: 2020 203c 6172 7469 6661 6374 4964 3e6d     <artifactId>m\n+00000d40: 6176 656e 2d73 7572 6566 6972 652d 706c  aven-surefire-pl\n+00000d50: 7567 696e 3c2f 6172 7469 6661 6374 4964  ugin</artifactId\n+00000d60: 3e0a 2020 2020 2020 2020 3c63 6f6e 6669  >.        <confi\n+00000d70: 6775 7261 7469 6f6e 3e0a 2020 2020 2020  guration>.      \n+00000d80: 2020 2020 3c73 6b69 7054 6573 7473 3e24      <skipTests>$\n+00000d90: 7b73 6b69 7049 6e74 6567 7261 7469 6f6e  {skipIntegration\n+00000da0: 5465 7374 737d 3c2f 736b 6970 5465 7374  Tests}</skipTest\n+00000db0: 733e 0a20 2020 2020 2020 203c 2f63 6f6e  s>.        </con\n+00000dc0: 6669 6775 7261 7469 6f6e 3e0a 2020 2020  figuration>.    \n+00000dd0: 2020 3c2f 706c 7567 696e 3e0a 2020 2020    </plugin>.    \n+00000de0: 3c2f 706c 7567 696e 733e 0a20 203c 2f62  </plugins>.  </b\n+00000df0: 7569 6c64 3e0a 3c2f 7072 6f6a 6563 743e  uild>.</project>\n+00000e00: 0a                                       .\n"}]}
