no message
This commit is contained in:
parent
8c688c52ef
commit
68344c354a
78
Jenkinsfile
vendored
Normal file
78
Jenkinsfile
vendored
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pipeline {
|
||||||
|
agent {
|
||||||
|
label 'Hadoop'
|
||||||
|
}
|
||||||
|
|
||||||
|
options {
|
||||||
|
disableConcurrentBuilds()
|
||||||
|
buildDiscarder(logRotator(daysToKeepStr: '14'))
|
||||||
|
timeout(time: 2, unit: 'HOURS')
|
||||||
|
timestamps()
|
||||||
|
}
|
||||||
|
|
||||||
|
triggers {
|
||||||
|
cron('@daily')
|
||||||
|
}
|
||||||
|
|
||||||
|
stages {
|
||||||
|
stage('Prepare') {
|
||||||
|
matrix {
|
||||||
|
agent any
|
||||||
|
axes {
|
||||||
|
axis {
|
||||||
|
name 'JAVA_VERSION'
|
||||||
|
values 'jdk_1.8_latest', 'jdk_11_latest'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tools {
|
||||||
|
maven "maven_latest"
|
||||||
|
jdk "${JAVA_VERSION}"
|
||||||
|
}
|
||||||
|
|
||||||
|
stages {
|
||||||
|
stage('BuildAndTest') {
|
||||||
|
steps {
|
||||||
|
sh "git clean -fxd"
|
||||||
|
sh "mvn verify spotbugs:check checkstyle:check -Pfull-build -Dsurefire-forkcount=4"
|
||||||
|
}
|
||||||
|
post {
|
||||||
|
always {
|
||||||
|
junit '**/target/surefire-reports/TEST-*.xml'
|
||||||
|
archiveArtifacts '**/target/*.jar'
|
||||||
|
}
|
||||||
|
// Jenkins pipeline jobs fill slaves on PRs without this :(
|
||||||
|
cleanup() {
|
||||||
|
script {
|
||||||
|
sh label: 'Cleanup workspace', script: '''
|
||||||
|
# See HADOOP-13951
|
||||||
|
chmod -R u+rxw "${WORKSPACE}"
|
||||||
|
'''
|
||||||
|
deleteDir()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
63
Jenkinsfile-PreCommit
Normal file
63
Jenkinsfile-PreCommit
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pipeline {
|
||||||
|
agent {
|
||||||
|
label 'Hadoop'
|
||||||
|
}
|
||||||
|
|
||||||
|
options {
|
||||||
|
disableConcurrentBuilds()
|
||||||
|
buildDiscarder(logRotator(daysToKeepStr: '14'))
|
||||||
|
timeout(time: 2, unit: 'HOURS')
|
||||||
|
timestamps()
|
||||||
|
}
|
||||||
|
|
||||||
|
tools {
|
||||||
|
maven "maven_latest"
|
||||||
|
jdk "jdk_1.8_latest"
|
||||||
|
}
|
||||||
|
|
||||||
|
stages {
|
||||||
|
stage('BuildAndTest') {
|
||||||
|
steps {
|
||||||
|
git 'https://github.com/apache/zookeeper'
|
||||||
|
sh "git clean -fxd"
|
||||||
|
sh "mvn verify spotbugs:check checkstyle:check -Pfull-build -Dsurefire-forkcount=4"
|
||||||
|
}
|
||||||
|
post {
|
||||||
|
always {
|
||||||
|
junit '**/target/surefire-reports/TEST-*.xml'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
// Jenkins pipeline jobs fill slaves on PRs without this :(
|
||||||
|
cleanup() {
|
||||||
|
script {
|
||||||
|
sh label: 'Cleanup workspace', script: '''
|
||||||
|
# See HADOOP-13951
|
||||||
|
chmod -R u+rxw "${WORKSPACE}"
|
||||||
|
'''
|
||||||
|
deleteDir()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
61
Jenkinsfile-owasp
Normal file
61
Jenkinsfile-owasp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pipeline {
|
||||||
|
agent {
|
||||||
|
label 'Hadoop'
|
||||||
|
}
|
||||||
|
|
||||||
|
options {
|
||||||
|
buildDiscarder(logRotator(daysToKeepStr: '14'))
|
||||||
|
timeout(time: 2, unit: 'HOURS')
|
||||||
|
timestamps()
|
||||||
|
}
|
||||||
|
|
||||||
|
tools {
|
||||||
|
maven "maven_latest"
|
||||||
|
jdk "jdk_1.8_latest"
|
||||||
|
}
|
||||||
|
|
||||||
|
stages {
|
||||||
|
stage('BuildAndTest') {
|
||||||
|
steps {
|
||||||
|
sh "git clean -fxd"
|
||||||
|
sh "mvn clean package -DskipTests dependency-check:check"
|
||||||
|
}
|
||||||
|
post {
|
||||||
|
always {
|
||||||
|
archiveArtifacts '**/target/dependency-check-*'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
// Jenkins pipeline jobs fill slaves on PRs without this :(
|
||||||
|
cleanup() {
|
||||||
|
script {
|
||||||
|
sh label: 'Cleanup workspace', script: '''
|
||||||
|
# See HADOOP-13951
|
||||||
|
chmod -R u+rxw "${WORKSPACE}"
|
||||||
|
'''
|
||||||
|
deleteDir()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
202
LICENSE.txt
Normal file
202
LICENSE.txt
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
11
NOTICE.txt
Normal file
11
NOTICE.txt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
Apache ZooKeeper
|
||||||
|
Copyright 2009-2021 The Apache Software Foundation
|
||||||
|
|
||||||
|
This product includes software developed at
|
||||||
|
The Apache Software Foundation (http://www.apache.org/).
|
||||||
|
|
||||||
|
This product includes software components originally
|
||||||
|
developed for Airlift (https://github.com/airlift/airlift),
|
||||||
|
licensed under the Apache 2.0 license. The licensing terms
|
||||||
|
for Airlift code can be found at:
|
||||||
|
https://github.com/airlift/airlift/blob/master/LICENSE
|
76
README_packaging.md
Normal file
76
README_packaging.md
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
# README file for Packaging Notes
|
||||||
|
|
||||||
|
The ZooKeeper project publishes releases as tarballs. For ZooKeeper packages
|
||||||
|
specific to your OS (such as rpm and deb), consider using Apache Bigtop:
|
||||||
|
|
||||||
|
http://bigtop.apache.org/
|
||||||
|
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- you need maven to build the java code
|
||||||
|
- gcc, cppunit, openssl and python-setuptools are required to build C and python bindings. (only needed when using `-Pfull-build`)
|
||||||
|
|
||||||
|
On RHEL machine:
|
||||||
|
|
||||||
|
```
|
||||||
|
yum install cppunit
|
||||||
|
yum install python-setuptools
|
||||||
|
yum install openssl openssl-devel
|
||||||
|
```
|
||||||
|
|
||||||
|
On Ubuntu (in case of 16.4+):
|
||||||
|
|
||||||
|
```
|
||||||
|
apt-get install libcppunit-dev
|
||||||
|
apt-get install python-setuptools python2.7-dev
|
||||||
|
apt-get install openssl libssl-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Package build command (using maven)
|
||||||
|
|
||||||
|
Commands to clean everything and build the tarball package without executing the tests: `mvn clean install -DskipTests`
|
||||||
|
|
||||||
|
|
||||||
|
`zookeeper-assembly/target/apache-zookeeper-<version>-bin.tar.gz` tarball file structure layout:
|
||||||
|
|
||||||
|
- `/bin` - User executables
|
||||||
|
- `/conf` - Configuration files
|
||||||
|
- `/lib` - ZooKeeper JAR files and all the required java library dependencies
|
||||||
|
- `/docs` - Documents
|
||||||
|
|
||||||
|
Beside the binary tarball, you can find the whole original source project packaged into:
|
||||||
|
`zookeeper-assembly/target/apache-zookeeper-<version>.tar.gz`
|
||||||
|
|
||||||
|
|
||||||
|
### Building the C client (using maven)
|
||||||
|
|
||||||
|
To also build the C client, you need to activate the `full-build` profile:
|
||||||
|
|
||||||
|
```
|
||||||
|
mvn clean -Pfull-build
|
||||||
|
mvn install -Pfull-build -DskipTests
|
||||||
|
```
|
||||||
|
|
||||||
|
Optional parameters you might consider when using maven:
|
||||||
|
- `-Pfull-build` - activates the full-build profile, causing the C client to be built
|
||||||
|
- `-DskipTests` - this parameter will skip both java and C++ unit test execution during the build
|
||||||
|
- `-Pc-test-coverage` - activates the test coverage calculation during the execution of C client tests
|
||||||
|
- `-Dc-client-openssl` - specify ssl support and openssl library location. Default value: `yes`, resulting in
|
||||||
|
the autodetection of the openssl library. If the openssl library will not be detected,
|
||||||
|
then a warning will be shown and the C client will be compiled without SSL support.
|
||||||
|
Use `-Dc-client-openssl=no` to explicitly disable SSL feature in C client. Or use
|
||||||
|
`-Dc-client-openssl=/path/to/openssl/` if you want to use a non-default / specific
|
||||||
|
openssl library location.
|
||||||
|
|
||||||
|
Please note: if you don't provide the `-Pfull-build` parameter, then the C client will not be built, the C client tests
|
||||||
|
will not be executed and the previous C client builds will no be cleaned up (e.g. with simply using `mvn clean`).
|
||||||
|
|
||||||
|
The compiled C client can be found here:
|
||||||
|
- `zookeeper-client/zookeeper-client-c/target/c/bin` - User executable
|
||||||
|
- `zookeeper-client/zookeeper-client-c/target/c/lib` - Native libraries
|
||||||
|
- `zookeeper-client/zookeeper-client-c/target/c/include/zookeeper` - Native library headers
|
||||||
|
|
||||||
|
The same folders gets archived to the `zookeeper-assembly/target/apache-zookeeper-<version>-lib.tar.gz` file, assuming
|
||||||
|
you activated the `full-build` maven profile.
|
6
bin/README.txt
Normal file
6
bin/README.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
This directory contain scripts that allow easy access (classpath in particular)
|
||||||
|
to the ZooKeeper server and command line client.
|
||||||
|
|
||||||
|
Files ending in .sh are unix and cygwin compatible
|
||||||
|
|
||||||
|
Files ending in .cmd are msdos/windows compatible
|
53
bin/zkCleanup.sh
Normal file
53
bin/zkCleanup.sh
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
# contributor license agreements. See the NOTICE file distributed with
|
||||||
|
# this work for additional information regarding copyright ownership.
|
||||||
|
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
# (the "License"); you may not use this file except in compliance with
|
||||||
|
# the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
#
|
||||||
|
# This script cleans up old transaction logs and snapshots
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# If this scripted is run out of /usr/bin or some other system bin directory
|
||||||
|
# it should be linked to and not copied. Things like java jar files are found
|
||||||
|
# relative to the canonical path of this script.
|
||||||
|
#
|
||||||
|
|
||||||
|
# use POSIX interface, symlink is followed automatically
|
||||||
|
ZOOBIN="${BASH_SOURCE-$0}"
|
||||||
|
ZOOBIN="$(dirname "${ZOOBIN}")"
|
||||||
|
ZOOBINDIR="$(cd "${ZOOBIN}"; pwd)"
|
||||||
|
|
||||||
|
if [ -e "$ZOOBIN/../libexec/zkEnv.sh" ]; then
|
||||||
|
. "$ZOOBINDIR"/../libexec/zkEnv.sh
|
||||||
|
else
|
||||||
|
. "$ZOOBINDIR"/zkEnv.sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
ZOODATADIR="$(grep "^[[:space:]]*dataDir=" "$ZOOCFG" | sed -e 's/.*=//')"
|
||||||
|
ZOODATALOGDIR="$(grep "^[[:space:]]*dataLogDir=" "$ZOOCFG" | sed -e 's/.*=//')"
|
||||||
|
|
||||||
|
ZOO_LOG_FILE=zookeeper-$USER-cleanup-$HOSTNAME.log
|
||||||
|
|
||||||
|
if [ "x$ZOODATALOGDIR" = "x" ]
|
||||||
|
then
|
||||||
|
"$JAVA" "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" "-Dzookeeper.log.file=${ZOO_LOG_FILE}" \
|
||||||
|
-cp "$CLASSPATH" $JVMFLAGS \
|
||||||
|
org.apache.zookeeper.server.PurgeTxnLog "$ZOODATADIR" $*
|
||||||
|
else
|
||||||
|
"$JAVA" "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" "-Dzookeeper.log.file=${ZOO_LOG_FILE}" \
|
||||||
|
-cp "$CLASSPATH" $JVMFLAGS \
|
||||||
|
org.apache.zookeeper.server.PurgeTxnLog "$ZOODATALOGDIR" "$ZOODATADIR" $*
|
||||||
|
fi
|
26
bin/zkCli.cmd
Normal file
26
bin/zkCli.cmd
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
@echo off
|
||||||
|
REM Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
REM contributor license agreements. See the NOTICE file distributed with
|
||||||
|
REM this work for additional information regarding copyright ownership.
|
||||||
|
REM The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
REM (the "License"); you may not use this file except in compliance with
|
||||||
|
REM the License. You may obtain a copy of the License at
|
||||||
|
REM
|
||||||
|
REM http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
REM
|
||||||
|
REM Unless required by applicable law or agreed to in writing, software
|
||||||
|
REM distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
REM See the License for the specific language governing permissions and
|
||||||
|
REM limitations under the License.
|
||||||
|
|
||||||
|
setlocal
|
||||||
|
call "%~dp0zkEnv.cmd"
|
||||||
|
|
||||||
|
set ZOO_LOG_FILE=zookeeper-%USERNAME%-cli-%COMPUTERNAME%.log
|
||||||
|
|
||||||
|
set ZOOMAIN=org.apache.zookeeper.ZooKeeperMain
|
||||||
|
call %JAVA% "-Dzookeeper.log.dir=%ZOO_LOG_DIR%" "-Dzookeeper.root.logger=%ZOO_LOG4J_PROP%" "-Dzookeeper.log.file=%ZOO_LOG_FILE%" -cp "%CLASSPATH%" %ZOOMAIN% %*
|
||||||
|
|
||||||
|
endlocal
|
||||||
|
|
43
bin/zkCli.sh
Normal file
43
bin/zkCli.sh
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
# contributor license agreements. See the NOTICE file distributed with
|
||||||
|
# this work for additional information regarding copyright ownership.
|
||||||
|
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
# (the "License"); you may not use this file except in compliance with
|
||||||
|
# the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
#
|
||||||
|
# This script cleans up old transaction logs and snapshots
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# If this scripted is run out of /usr/bin or some other system bin directory
|
||||||
|
# it should be linked to and not copied. Things like java jar files are found
|
||||||
|
# relative to the canonical path of this script.
|
||||||
|
#
|
||||||
|
|
||||||
|
# use POSIX interface, symlink is followed automatically
|
||||||
|
ZOOBIN="${BASH_SOURCE-$0}"
|
||||||
|
ZOOBIN="$(dirname "${ZOOBIN}")"
|
||||||
|
ZOOBINDIR="$(cd "${ZOOBIN}"; pwd)"
|
||||||
|
|
||||||
|
if [ -e "$ZOOBIN/../libexec/zkEnv.sh" ]; then
|
||||||
|
. "$ZOOBINDIR"/../libexec/zkEnv.sh
|
||||||
|
else
|
||||||
|
. "$ZOOBINDIR"/zkEnv.sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
ZOO_LOG_FILE=zookeeper-$USER-cli-$HOSTNAME.log
|
||||||
|
|
||||||
|
"$JAVA" "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" "-Dzookeeper.log.file=${ZOO_LOG_FILE}" \
|
||||||
|
-cp "$CLASSPATH" $CLIENT_JVMFLAGS $JVMFLAGS \
|
||||||
|
org.apache.zookeeper.ZooKeeperMain "$@"
|
54
bin/zkEnv.cmd
Normal file
54
bin/zkEnv.cmd
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
@echo off
|
||||||
|
REM Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
REM contributor license agreements. See the NOTICE file distributed with
|
||||||
|
REM this work for additional information regarding copyright ownership.
|
||||||
|
REM The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
REM (the "License"); you may not use this file except in compliance with
|
||||||
|
REM the License. You may obtain a copy of the License at
|
||||||
|
REM
|
||||||
|
REM http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
REM
|
||||||
|
REM Unless required by applicable law or agreed to in writing, software
|
||||||
|
REM distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
REM See the License for the specific language governing permissions and
|
||||||
|
REM limitations under the License.
|
||||||
|
|
||||||
|
set ZOOCFGDIR=%~dp0%..\conf
|
||||||
|
set ZOO_LOG_DIR=%~dp0%..\logs
|
||||||
|
set ZOO_LOG4J_PROP=INFO,CONSOLE
|
||||||
|
|
||||||
|
REM for sanity sake assume Java 1.6
|
||||||
|
REM see: http://java.sun.com/javase/6/docs/technotes/tools/windows/java.html
|
||||||
|
|
||||||
|
REM add the zoocfg dir to classpath
|
||||||
|
set CLASSPATH=%ZOOCFGDIR%
|
||||||
|
|
||||||
|
REM make it work in the release
|
||||||
|
SET CLASSPATH=%~dp0..\*;%~dp0..\lib\*;%CLASSPATH%
|
||||||
|
|
||||||
|
REM make it work for developers
|
||||||
|
SET CLASSPATH=%~dp0..\build\classes;%~dp0..\build\lib\*;%CLASSPATH%
|
||||||
|
|
||||||
|
set ZOOCFG=%ZOOCFGDIR%\zoo.cfg
|
||||||
|
|
||||||
|
@REM setup java environment variables
|
||||||
|
|
||||||
|
if not defined JAVA_HOME (
|
||||||
|
echo Error: JAVA_HOME is not set.
|
||||||
|
goto :eof
|
||||||
|
)
|
||||||
|
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
|
||||||
|
if not exist "%JAVA_HOME%"\bin\java.exe (
|
||||||
|
echo Error: JAVA_HOME is incorrectly set: %JAVA_HOME%
|
||||||
|
echo Expected to find java.exe here: %JAVA_HOME%\bin\java.exe
|
||||||
|
goto :eof
|
||||||
|
)
|
||||||
|
|
||||||
|
REM strip off trailing \ from JAVA_HOME or java does not start
|
||||||
|
if "%JAVA_HOME:~-1%" EQU "\" set "JAVA_HOME=%JAVA_HOME:~0,-1%"
|
||||||
|
|
||||||
|
set JAVA="%JAVA_HOME%"\bin\java
|
||||||
|
|
148
bin/zkEnv.sh
Normal file
148
bin/zkEnv.sh
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
# contributor license agreements. See the NOTICE file distributed with
|
||||||
|
# this work for additional information regarding copyright ownership.
|
||||||
|
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
# (the "License"); you may not use this file except in compliance with
|
||||||
|
# the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
# This script should be sourced into other zookeeper
|
||||||
|
# scripts to setup the env variables
|
||||||
|
|
||||||
|
# We use ZOOCFGDIR if defined,
|
||||||
|
# otherwise we use /etc/zookeeper
|
||||||
|
# or the conf directory that is
|
||||||
|
# a sibling of this script's directory.
|
||||||
|
# Or you can specify the ZOOCFGDIR using the
|
||||||
|
# '--config' option in the command line.
|
||||||
|
|
||||||
|
ZOOBINDIR="${ZOOBINDIR:-/usr/bin}"
|
||||||
|
ZOOKEEPER_PREFIX="${ZOOBINDIR}/.."
|
||||||
|
|
||||||
|
#check to see if the conf dir is given as an optional argument
|
||||||
|
if [ $# -gt 1 ]
|
||||||
|
then
|
||||||
|
if [ "--config" = "$1" ]
|
||||||
|
then
|
||||||
|
shift
|
||||||
|
confdir=$1
|
||||||
|
shift
|
||||||
|
ZOOCFGDIR=$confdir
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "x$ZOOCFGDIR" = "x" ]
|
||||||
|
then
|
||||||
|
if [ -e "${ZOOKEEPER_PREFIX}/conf" ]; then
|
||||||
|
ZOOCFGDIR="$ZOOBINDIR/../conf"
|
||||||
|
else
|
||||||
|
ZOOCFGDIR="$ZOOBINDIR/../etc/zookeeper"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "${ZOOCFGDIR}/zookeeper-env.sh" ]; then
|
||||||
|
. "${ZOOCFGDIR}/zookeeper-env.sh"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "x$ZOOCFG" = "x" ]
|
||||||
|
then
|
||||||
|
ZOOCFG="zoo.cfg"
|
||||||
|
fi
|
||||||
|
|
||||||
|
ZOOCFG="$ZOOCFGDIR/$ZOOCFG"
|
||||||
|
|
||||||
|
if [ -f "$ZOOCFGDIR/java.env" ]
|
||||||
|
then
|
||||||
|
. "$ZOOCFGDIR/java.env"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "x${ZOO_LOG_DIR}" = "x" ]
|
||||||
|
then
|
||||||
|
ZOO_LOG_DIR="$ZOOKEEPER_PREFIX/logs"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "x${ZOO_LOG4J_PROP}" = "x" ]
|
||||||
|
then
|
||||||
|
ZOO_LOG4J_PROP="INFO,CONSOLE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$JAVA_HOME" ]] && [[ -x "$JAVA_HOME/bin/java" ]]; then
|
||||||
|
JAVA="$JAVA_HOME/bin/java"
|
||||||
|
elif type -p java; then
|
||||||
|
JAVA=java
|
||||||
|
else
|
||||||
|
echo "Error: JAVA_HOME is not set and java could not be found in PATH." 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#add the zoocfg dir to classpath
|
||||||
|
CLASSPATH="$ZOOCFGDIR:$CLASSPATH"
|
||||||
|
|
||||||
|
for i in "$ZOOBINDIR"/../zookeeper-server/src/main/resources/lib/*.jar
|
||||||
|
do
|
||||||
|
CLASSPATH="$i:$CLASSPATH"
|
||||||
|
done
|
||||||
|
|
||||||
|
#make it work in the binary package
|
||||||
|
#(use array for LIBPATH to account for spaces within wildcard expansion)
|
||||||
|
if ls "${ZOOKEEPER_PREFIX}"/share/zookeeper/zookeeper-*.jar > /dev/null 2>&1; then
|
||||||
|
LIBPATH=("${ZOOKEEPER_PREFIX}"/share/zookeeper/*.jar)
|
||||||
|
else
|
||||||
|
#release tarball format
|
||||||
|
for i in "$ZOOBINDIR"/../zookeeper-*.jar
|
||||||
|
do
|
||||||
|
CLASSPATH="$i:$CLASSPATH"
|
||||||
|
done
|
||||||
|
LIBPATH=("${ZOOBINDIR}"/../lib/*.jar)
|
||||||
|
fi
|
||||||
|
|
||||||
|
for i in "${LIBPATH[@]}"
|
||||||
|
do
|
||||||
|
CLASSPATH="$i:$CLASSPATH"
|
||||||
|
done
|
||||||
|
|
||||||
|
#make it work for developers
|
||||||
|
for d in "$ZOOBINDIR"/../build/lib/*.jar
|
||||||
|
do
|
||||||
|
CLASSPATH="$d:$CLASSPATH"
|
||||||
|
done
|
||||||
|
|
||||||
|
for d in "$ZOOBINDIR"/../zookeeper-server/target/lib/*.jar
|
||||||
|
do
|
||||||
|
CLASSPATH="$d:$CLASSPATH"
|
||||||
|
done
|
||||||
|
|
||||||
|
#make it work for developers
|
||||||
|
CLASSPATH="$ZOOBINDIR/../build/classes:$CLASSPATH"
|
||||||
|
|
||||||
|
#make it work for developers
|
||||||
|
CLASSPATH="$ZOOBINDIR/../zookeeper-server/target/classes:$CLASSPATH"
|
||||||
|
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN*|MINGW*) cygwin=true ;;
|
||||||
|
*) cygwin=false ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if $cygwin
|
||||||
|
then
|
||||||
|
CLASSPATH=`cygpath -wp "$CLASSPATH"`
|
||||||
|
fi
|
||||||
|
|
||||||
|
#echo "CLASSPATH=$CLASSPATH"
|
||||||
|
|
||||||
|
# default heap for zookeeper server
|
||||||
|
ZK_SERVER_HEAP="${ZK_SERVER_HEAP:-1000}"
|
||||||
|
export SERVER_JVMFLAGS="-Xmx${ZK_SERVER_HEAP}m $SERVER_JVMFLAGS"
|
||||||
|
|
||||||
|
# default heap for zookeeper client
|
||||||
|
ZK_CLIENT_HEAP="${ZK_CLIENT_HEAP:-256}"
|
||||||
|
export CLIENT_JVMFLAGS="-Xmx${ZK_CLIENT_HEAP}m $CLIENT_JVMFLAGS"
|
141
bin/zkServer-initialize.sh
Normal file
141
bin/zkServer-initialize.sh
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
# contributor license agreements. See the NOTICE file distributed with
|
||||||
|
# this work for additional information regarding copyright ownership.
|
||||||
|
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
# (the "License"); you may not use this file except in compliance with
|
||||||
|
# the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
#
|
||||||
|
# If this scripted is run out of /usr/bin or some other system bin directory
|
||||||
|
# it should be linked to and not copied. Things like java jar files are found
|
||||||
|
# relative to the canonical path of this script.
|
||||||
|
#
|
||||||
|
|
||||||
|
# use POSIX interface, symlink is followed automatically
|
||||||
|
ZOOBIN="${BASH_SOURCE-$0}"
|
||||||
|
ZOOBIN="$(dirname "${ZOOBIN}")"
|
||||||
|
ZOOBINDIR="$(cd "${ZOOBIN}"; pwd)"
|
||||||
|
|
||||||
|
if [ -e "$ZOOBIN/../libexec/zkEnv.sh" ]; then
|
||||||
|
. "$ZOOBINDIR"/../libexec/zkEnv.sh
|
||||||
|
else
|
||||||
|
. "$ZOOBINDIR"/zkEnv.sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
# the configfile will be properly formatted as long as the
|
||||||
|
# configfile path is less then 40 chars, otw the line will look a
|
||||||
|
# bit weird, but otherwise it's fine
|
||||||
|
printf "usage: $0 <parameters>
|
||||||
|
Optional parameters:
|
||||||
|
-h Display this message
|
||||||
|
--help Display this message
|
||||||
|
--configfile=%-40s ZooKeeper config file
|
||||||
|
--myid=# Set the myid to be used, if any (1-255)
|
||||||
|
--force Force creation of the data/txnlog dirs
|
||||||
|
" "$ZOOCFG"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ $? != 0 ] ; then
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
initialize() {
|
||||||
|
if [ ! -e "$ZOOCFG" ]; then
|
||||||
|
echo "Unable to find config file at $ZOOCFG"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
ZOO_DATADIR="$(grep "^[[:space:]]*dataDir" "$ZOOCFG" | sed -e 's/.*=//')"
|
||||||
|
ZOO_DATALOGDIR="$(grep "^[[:space:]]*dataLogDir" "$ZOOCFG" | sed -e 's/.*=//')"
|
||||||
|
|
||||||
|
if [ -z "$ZOO_DATADIR" ]; then
|
||||||
|
echo "Unable to determine dataDir from $ZOOCFG"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $FORCE ]; then
|
||||||
|
echo "Force enabled, data/txnlog directories will be re-initialized"
|
||||||
|
else
|
||||||
|
# we create if version-2 exists (ie real data), not the
|
||||||
|
# parent. See comments in following section for more insight
|
||||||
|
if [ -d "$ZOO_DATADIR/version-2" ]; then
|
||||||
|
echo "ZooKeeper data directory already exists at $ZOO_DATADIR (or use --force to force re-initialization)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$ZOO_DATALOGDIR" ] && [ -d "$ZOO_DATALOGDIR/version-2" ]; then
|
||||||
|
echo "ZooKeeper txnlog directory already exists at $ZOO_DATALOGDIR (or use --force to force re-initialization)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# remove the child files that we're (not) interested in, not the
|
||||||
|
# parent. this allows for parent to be installed separately, and
|
||||||
|
# permissions to be set based on overarching requirements. by
|
||||||
|
# default we'll use the permissions of the user running this
|
||||||
|
# script for the files contained by the parent. note also by using
|
||||||
|
# -p the parent(s) will be created if it doesn't already exist
|
||||||
|
rm -rf "$ZOO_DATADIR/myid" 2>/dev/null >/dev/null
|
||||||
|
rm -rf "$ZOO_DATADIR/version-2" 2>/dev/null >/dev/null
|
||||||
|
mkdir -p "$ZOO_DATADIR/version-2"
|
||||||
|
|
||||||
|
if [ -n "$ZOO_DATALOGDIR" ]; then
|
||||||
|
rm -rf "$ZOO_DATALOGDIR/myid" 2>/dev/null >/dev/null
|
||||||
|
rm -rf "$ZOO_DATALOGDIR/version-2" 2>/dev/null >/dev/null
|
||||||
|
mkdir -p "$ZOO_DATALOGDIR/version-2"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $MYID ]; then
|
||||||
|
echo "Using myid of $MYID"
|
||||||
|
echo $MYID > "$ZOO_DATADIR/myid"
|
||||||
|
else
|
||||||
|
echo "No myid provided, be sure to specify it in $ZOO_DATADIR/myid if using non-standalone"
|
||||||
|
fi
|
||||||
|
|
||||||
|
touch "$ZOO_DATADIR/initialize"
|
||||||
|
}
|
||||||
|
|
||||||
|
while [ ! -z "$1" ]; do
|
||||||
|
case "$1" in
|
||||||
|
--configfile)
|
||||||
|
ZOOCFG=$2; shift 2
|
||||||
|
;;
|
||||||
|
--configfile=?*)
|
||||||
|
ZOOCFG=${1#*=}; shift 1
|
||||||
|
;;
|
||||||
|
--myid)
|
||||||
|
MYID=$2; shift 2
|
||||||
|
;;
|
||||||
|
--myid=?*)
|
||||||
|
MYID=${1#*=}; shift 1
|
||||||
|
;;
|
||||||
|
--force)
|
||||||
|
FORCE=1; shift 1
|
||||||
|
;;
|
||||||
|
-h)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
--help)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1"
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
initialize
|
26
bin/zkServer.cmd
Normal file
26
bin/zkServer.cmd
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
@echo off
|
||||||
|
REM Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
REM contributor license agreements. See the NOTICE file distributed with
|
||||||
|
REM this work for additional information regarding copyright ownership.
|
||||||
|
REM The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
REM (the "License"); you may not use this file except in compliance with
|
||||||
|
REM the License. You may obtain a copy of the License at
|
||||||
|
REM
|
||||||
|
REM http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
REM
|
||||||
|
REM Unless required by applicable law or agreed to in writing, software
|
||||||
|
REM distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
REM See the License for the specific language governing permissions and
|
||||||
|
REM limitations under the License.
|
||||||
|
|
||||||
|
setlocal
|
||||||
|
call "%~dp0zkEnv.cmd"
|
||||||
|
|
||||||
|
set ZOOMAIN=org.apache.zookeeper.server.quorum.QuorumPeerMain
|
||||||
|
set ZOO_LOG_FILE=zookeeper-%USERNAME%-server-%COMPUTERNAME%.log
|
||||||
|
|
||||||
|
echo on
|
||||||
|
call %JAVA% "-Dzookeeper.log.dir=%ZOO_LOG_DIR%" "-Dzookeeper.root.logger=%ZOO_LOG4J_PROP%" "-Dzookeeper.log.file=%ZOO_LOG_FILE%" "-XX:+HeapDumpOnOutOfMemoryError" "-XX:OnOutOfMemoryError=cmd /c taskkill /pid %%%%p /t /f" -cp "%CLASSPATH%" %ZOOMAIN% "%ZOOCFG%" %*
|
||||||
|
|
||||||
|
endlocal
|
325
bin/zkServer.sh
Normal file
325
bin/zkServer.sh
Normal file
@ -0,0 +1,325 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
# contributor license agreements. See the NOTICE file distributed with
|
||||||
|
# this work for additional information regarding copyright ownership.
|
||||||
|
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
# (the "License"); you may not use this file except in compliance with
|
||||||
|
# the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
#
|
||||||
|
# If this scripted is run out of /usr/bin or some other system bin directory
|
||||||
|
# it should be linked to and not copied. Things like java jar files are found
|
||||||
|
# relative to the canonical path of this script.
|
||||||
|
#
|
||||||
|
|
||||||
|
# TODO_MA 马中华 注释: 如果一个大数据技术组件的底层源码实现是 java
|
||||||
|
# TODO_MA 马中华 注释: 那么 shell 命令的规范,就一定是先准备各种参数,然后通过 java 命令启动一个 JVM 执行某个类的 main()
|
||||||
|
|
||||||
|
|
||||||
|
# use POSIX interface, symlink is followed automatically
|
||||||
|
ZOOBIN="${BASH_SOURCE-$0}"
|
||||||
|
ZOOBIN="$(dirname "${ZOOBIN}")"
|
||||||
|
ZOOBINDIR="$(cd "${ZOOBIN}"; pwd)"
|
||||||
|
|
||||||
|
if [ -e "$ZOOBIN/../libexec/zkEnv.sh" ]; then
|
||||||
|
. "$ZOOBINDIR"/../libexec/zkEnv.sh
|
||||||
|
else
|
||||||
|
. "$ZOOBINDIR"/zkEnv.sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
# See the following page for extensive details on setting
|
||||||
|
# up the JVM to accept JMX remote management:
|
||||||
|
# http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html
|
||||||
|
# by default we allow local JMX connections
|
||||||
|
if [ "x$JMXLOCALONLY" = "x" ]
|
||||||
|
then
|
||||||
|
JMXLOCALONLY=false
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "x$JMXDISABLE" = "x" ] || [ "$JMXDISABLE" = 'false' ]
|
||||||
|
then
|
||||||
|
echo "ZooKeeper JMX enabled by default" >&2
|
||||||
|
if [ "x$JMXPORT" = "x" ]
|
||||||
|
then
|
||||||
|
# for some reason these two options are necessary on jdk6 on Ubuntu
|
||||||
|
# accord to the docs they are not necessary, but otw jconsole cannot
|
||||||
|
# do a local attach
|
||||||
|
ZOOMAIN="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=$JMXLOCALONLY org.apache.zookeeper.server.quorum.QuorumPeerMain"
|
||||||
|
else
|
||||||
|
if [ "x$JMXAUTH" = "x" ]
|
||||||
|
then
|
||||||
|
JMXAUTH=false
|
||||||
|
fi
|
||||||
|
if [ "x$JMXSSL" = "x" ]
|
||||||
|
then
|
||||||
|
JMXSSL=false
|
||||||
|
fi
|
||||||
|
if [ "x$JMXLOG4J" = "x" ]
|
||||||
|
then
|
||||||
|
JMXLOG4J=true
|
||||||
|
fi
|
||||||
|
echo "ZooKeeper remote JMX Port set to $JMXPORT" >&2
|
||||||
|
echo "ZooKeeper remote JMX authenticate set to $JMXAUTH" >&2
|
||||||
|
echo "ZooKeeper remote JMX ssl set to $JMXSSL" >&2
|
||||||
|
echo "ZooKeeper remote JMX log4j set to $JMXLOG4J" >&2
|
||||||
|
ZOOMAIN="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=$JMXPORT -Dcom.sun.management.jmxremote.authenticate=$JMXAUTH -Dcom.sun.management.jmxremote.ssl=$JMXSSL -Dzookeeper.jmx.log4j.disable=$JMXLOG4J org.apache.zookeeper.server.quorum.QuorumPeerMain"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "JMX disabled by user request" >&2
|
||||||
|
# TODO_MA 马中华 注释: 运行主类
|
||||||
|
# TODO_MA 马中华 注释:ZK JVM 进程的名称: QuorumPeerMain
|
||||||
|
# TODO_MA 马中华 注释:QuorumPeer + Main ==> 这个类的作用,就是启动 QuorumPeer
|
||||||
|
# TODO_MA 马中华 注释:QuorumPeer 代表了一台服务器的全部功能实现!
|
||||||
|
ZOOMAIN="org.apache.zookeeper.server.quorum.QuorumPeerMain"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "x$SERVER_JVMFLAGS" != "x" ]
|
||||||
|
then
|
||||||
|
JVMFLAGS="$SERVER_JVMFLAGS $JVMFLAGS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "x$2" != "x" ]
|
||||||
|
then
|
||||||
|
ZOOCFG="$ZOOCFGDIR/$2"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# if we give a more complicated path to the config, don't screw around in $ZOOCFGDIR
|
||||||
|
if [ "x$(dirname "$ZOOCFG")" != "x$ZOOCFGDIR" ]
|
||||||
|
then
|
||||||
|
ZOOCFG="$2"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if $cygwin
|
||||||
|
then
|
||||||
|
ZOOCFG=`cygpath -wp "$ZOOCFG"`
|
||||||
|
# cygwin has a "kill" in the shell itself, gets confused
|
||||||
|
KILL=/bin/kill
|
||||||
|
else
|
||||||
|
KILL=kill
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Using config: $ZOOCFG" >&2
|
||||||
|
|
||||||
|
case "$OSTYPE" in
|
||||||
|
*solaris*)
|
||||||
|
GREP=/usr/xpg4/bin/grep
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
GREP=grep
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
ZOO_DATADIR="$($GREP "^[[:space:]]*dataDir" "$ZOOCFG" | sed -e 's/.*=//')"
|
||||||
|
ZOO_DATADIR="$(echo -e "${ZOO_DATADIR}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
|
||||||
|
ZOO_DATALOGDIR="$($GREP "^[[:space:]]*dataLogDir" "$ZOOCFG" | sed -e 's/.*=//')"
|
||||||
|
|
||||||
|
# iff autocreate is turned off and the datadirs don't exist fail
|
||||||
|
# immediately as we can't create the PID file, etc..., anyway.
|
||||||
|
if [ -n "$ZOO_DATADIR_AUTOCREATE_DISABLE" ]; then
|
||||||
|
if [ ! -d "$ZOO_DATADIR/version-2" ]; then
|
||||||
|
echo "ZooKeeper data directory is missing at $ZOO_DATADIR fix the path or run initialize"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$ZOO_DATALOGDIR" ] && [ ! -d "$ZOO_DATALOGDIR/version-2" ]; then
|
||||||
|
echo "ZooKeeper txnlog directory is missing at $ZOO_DATALOGDIR fix the path or run initialize"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
ZOO_DATADIR_AUTOCREATE="-Dzookeeper.datadir.autocreate=false"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$ZOOPIDFILE" ]; then
|
||||||
|
if [ ! -d "$ZOO_DATADIR" ]; then
|
||||||
|
mkdir -p "$ZOO_DATADIR"
|
||||||
|
fi
|
||||||
|
ZOOPIDFILE="$ZOO_DATADIR/zookeeper_server.pid"
|
||||||
|
else
|
||||||
|
# ensure it exists, otw stop will fail
|
||||||
|
mkdir -p "$(dirname "$ZOOPIDFILE")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -w "$ZOO_LOG_DIR" ] ; then
|
||||||
|
mkdir -p "$ZOO_LOG_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
ZOO_LOG_FILE=zookeeper-$USER-server-$HOSTNAME.log
|
||||||
|
_ZOO_DAEMON_OUT="$ZOO_LOG_DIR/zookeeper-$USER-server-$HOSTNAME.out"
|
||||||
|
|
||||||
|
# TODO_MA 马中华 注释: zkServer.sh start
|
||||||
|
# TODO_MA 马中华 注释: $1 = start
|
||||||
|
case $1 in
|
||||||
|
start)
|
||||||
|
echo -n "Starting zookeeper ... "
|
||||||
|
if [ -f "$ZOOPIDFILE" ]; then
|
||||||
|
if kill -0 `cat "$ZOOPIDFILE"` > /dev/null 2>&1; then
|
||||||
|
echo $command already running as process `cat "$ZOOPIDFILE"`.
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# TODO_MA 马中华 注释: 核心的启动命令4
|
||||||
|
# TODO_MA 马中华 注释: $JAVA = $JAVA_HOME/bin/java
|
||||||
|
# TODO_MA 马中华 注释: $ZOOMAIN = 核心java类 = QuorumPeerMain
|
||||||
|
# TODO_MA 马中华 注释: "$ZOOCFG" = zoo.cfg 的路径 = $ZOOKEEPER_HOME/conf/zoo.cfg
|
||||||
|
nohup "$JAVA" $ZOO_DATADIR_AUTOCREATE "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" \
|
||||||
|
"-Dzookeeper.log.file=${ZOO_LOG_FILE}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \
|
||||||
|
-XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError='kill -9 %p' \
|
||||||
|
-cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG" > "$_ZOO_DAEMON_OUT" 2>&1 < /dev/null &
|
||||||
|
if [ $? -eq 0 ]
|
||||||
|
then
|
||||||
|
case "$OSTYPE" in
|
||||||
|
*solaris*)
|
||||||
|
/bin/echo "${!}\\c" > "$ZOOPIDFILE"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
/bin/echo -n $! > "$ZOOPIDFILE"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
if [ $? -eq 0 ];
|
||||||
|
then
|
||||||
|
sleep 1
|
||||||
|
pid=$(cat "${ZOOPIDFILE}")
|
||||||
|
if ps -p "${pid}" > /dev/null 2>&1; then
|
||||||
|
echo STARTED
|
||||||
|
else
|
||||||
|
echo FAILED TO START
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo FAILED TO WRITE PID
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo SERVER DID NOT START
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
start-foreground)
|
||||||
|
ZOO_CMD=(exec "$JAVA")
|
||||||
|
if [ "${ZOO_NOEXEC}" != "" ]; then
|
||||||
|
ZOO_CMD=("$JAVA")
|
||||||
|
fi
|
||||||
|
"${ZOO_CMD[@]}" $ZOO_DATADIR_AUTOCREATE "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" \
|
||||||
|
"-Dzookeeper.log.file=${ZOO_LOG_FILE}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \
|
||||||
|
-XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError='kill -9 %p' \
|
||||||
|
-cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG"
|
||||||
|
;;
|
||||||
|
print-cmd)
|
||||||
|
echo "\"$JAVA\" $ZOO_DATADIR_AUTOCREATE -Dzookeeper.log.dir=\"${ZOO_LOG_DIR}\" \
|
||||||
|
-Dzookeeper.log.file=\"${ZOO_LOG_FILE}\" -Dzookeeper.root.logger=\"${ZOO_LOG4J_PROP}\" \
|
||||||
|
-XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError='kill -9 %p' \
|
||||||
|
-cp \"$CLASSPATH\" $JVMFLAGS $ZOOMAIN \"$ZOOCFG\" > \"$_ZOO_DAEMON_OUT\" 2>&1 < /dev/null"
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
echo -n "Stopping zookeeper ... "
|
||||||
|
if [ ! -f "$ZOOPIDFILE" ]
|
||||||
|
then
|
||||||
|
echo "no zookeeper to stop (could not find file $ZOOPIDFILE)"
|
||||||
|
else
|
||||||
|
$KILL $(cat "$ZOOPIDFILE")
|
||||||
|
rm "$ZOOPIDFILE"
|
||||||
|
sleep 1
|
||||||
|
echo STOPPED
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
version)
|
||||||
|
ZOOMAIN=org.apache.zookeeper.version.VersionInfoMain
|
||||||
|
$JAVA -cp "$CLASSPATH" $ZOOMAIN 2> /dev/null
|
||||||
|
;;
|
||||||
|
restart)
|
||||||
|
shift
|
||||||
|
"$0" stop ${@}
|
||||||
|
sleep 3
|
||||||
|
"$0" start ${@}
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
# -q is necessary on some versions of linux where nc returns too quickly, and no stat result is output
|
||||||
|
isSSL="false"
|
||||||
|
clientPortAddress=`$GREP "^[[:space:]]*clientPortAddress[^[:alpha:]]" "$ZOOCFG" | sed -e 's/.*=//'`
|
||||||
|
if ! [ $clientPortAddress ]
|
||||||
|
then
|
||||||
|
clientPortAddress="localhost"
|
||||||
|
fi
|
||||||
|
clientPort=`$GREP "^[[:space:]]*clientPort[^[:alpha:]]" "$ZOOCFG" | sed -e 's/.*=//'`
|
||||||
|
if ! [[ "$clientPort" =~ ^[0-9]+$ ]]
|
||||||
|
then
|
||||||
|
dataDir=`$GREP "^[[:space:]]*dataDir" "$ZOOCFG" | sed -e 's/.*=//'`
|
||||||
|
myid=`cat "$dataDir/myid" 2> /dev/null`
|
||||||
|
if ! [[ "$myid" =~ ^[0-9]+$ ]] ; then
|
||||||
|
echo "myid could not be determined, will not able to locate clientPort in the server configs."
|
||||||
|
else
|
||||||
|
clientPortAndAddress=`$GREP "^[[:space:]]*server.$myid=.*;.*" "$ZOOCFG" | sed -e 's/.*=//' | sed -e 's/.*;//'`
|
||||||
|
if [ ! "$clientPortAndAddress" ] ; then
|
||||||
|
echo "Client port not found in static config file. Looking in dynamic config file."
|
||||||
|
dynamicConfigFile=`$GREP "^[[:space:]]*dynamicConfigFile" "$ZOOCFG" | sed -e 's/.*=//'`
|
||||||
|
clientPortAndAddress=`$GREP "^[[:space:]]*server.$myid=.*;.*" "$dynamicConfigFile" | sed -e 's/.*=//' | sed -e 's/.*;//'`
|
||||||
|
fi
|
||||||
|
if [ ! "$clientPortAndAddress" ] ; then
|
||||||
|
echo "Client port not found in the server configs"
|
||||||
|
else
|
||||||
|
if [[ "$clientPortAndAddress" =~ ^.*:[0-9]+ ]] ; then
|
||||||
|
if [[ "$clientPortAndAddress" =~ \[.*\]:[0-9]+ ]] ; then
|
||||||
|
# Extracts address from address:port for example extracts 127::1 from "[127::1]:2181"
|
||||||
|
clientPortAddress=`echo "$clientPortAndAddress" | sed -e 's|\[||' | sed -e 's|\]:.*||'`
|
||||||
|
else
|
||||||
|
clientPortAddress=`echo "$clientPortAndAddress" | sed -e 's/:.*//'`
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
clientPort=`echo "$clientPortAndAddress" | sed -e 's/.*://'`
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ ! "$clientPort" ] ; then
|
||||||
|
echo "Client port not found. Looking for secureClientPort in the static config."
|
||||||
|
secureClientPort=`$GREP "^[[:space:]]*secureClientPort[^[:alpha:]]" "$ZOOCFG" | sed -e 's/.*=//'`
|
||||||
|
if [ "$secureClientPort" ] ; then
|
||||||
|
isSSL="true"
|
||||||
|
clientPort=$secureClientPort
|
||||||
|
clientPortAddress=`$GREP "^[[:space:]]*secureClientPortAddress[^[:alpha:]]" "$ZOOCFG" | sed -e 's/.*=//'`
|
||||||
|
if ! [ $clientPortAddress ]
|
||||||
|
then
|
||||||
|
clientPortAddress="localhost"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Unable to find either secure or unsecure client port in any configs. Terminating."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "Client port found: $clientPort. Client address: $clientPortAddress. Client SSL: $isSSL."
|
||||||
|
STAT=`"$JAVA" "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" "-Dzookeeper.log.file=${ZOO_LOG_FILE}" \
|
||||||
|
-cp "$CLASSPATH" $CLIENT_JVMFLAGS $JVMFLAGS org.apache.zookeeper.client.FourLetterWordMain \
|
||||||
|
$clientPortAddress $clientPort srvr $isSSL 2> /dev/null \
|
||||||
|
| $GREP Mode`
|
||||||
|
if [ "x$STAT" = "x" ]
|
||||||
|
then
|
||||||
|
if [ "$isSSL" = "true" ] ; then
|
||||||
|
echo " "
|
||||||
|
echo "Note: We used secureClientPort ($secureClientPort) to establish connection, but we failed. The 'status'"
|
||||||
|
echo " command establishes a client connection to the server to execute diagnostic commands. Please make sure you"
|
||||||
|
echo " provided all the Client SSL connection related parameters in the CLIENT_JVMFLAGS environment variable! E.g.:"
|
||||||
|
echo " CLIENT_JVMFLAGS=\"-Dzookeeper.clientCnxnSocket=org.apache.zookeeper.ClientCnxnSocketNetty"
|
||||||
|
echo " -Dzookeeper.ssl.trustStore.location=/tmp/clienttrust.jks -Dzookeeper.ssl.trustStore.password=password"
|
||||||
|
echo " -Dzookeeper.ssl.keyStore.location=/tmp/client.jks -Dzookeeper.ssl.keyStore.password=password"
|
||||||
|
echo " -Dzookeeper.client.secure=true\" ./zkServer.sh status"
|
||||||
|
echo " "
|
||||||
|
fi
|
||||||
|
echo "Error contacting service. It is probably not running."
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo $STAT
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 [--config <conf-dir>] {start|start-foreground|stop|version|restart|status|print-cmd}" >&2
|
||||||
|
|
||||||
|
esac
|
24
bin/zkSnapShotToolkit.cmd
Normal file
24
bin/zkSnapShotToolkit.cmd
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
@echo off
|
||||||
|
REM Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
REM contributor license agreements. See the NOTICE file distributed with
|
||||||
|
REM this work for additional information regarding copyright ownership.
|
||||||
|
REM The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
REM (the "License"); you may not use this file except in compliance with
|
||||||
|
REM the License. You may obtain a copy of the License at
|
||||||
|
REM
|
||||||
|
REM http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
REM
|
||||||
|
REM Unless required by applicable law or agreed to in writing, software
|
||||||
|
REM distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
REM See the License for the specific language governing permissions and
|
||||||
|
REM limitations under the License.
|
||||||
|
|
||||||
|
setlocal
|
||||||
|
call "%~dp0zkEnv.cmd"
|
||||||
|
|
||||||
|
set ZOOMAIN=org.apache.zookeeper.server.SnapshotFormatter
|
||||||
|
call %JAVA% -cp "%CLASSPATH%" %ZOOMAIN% %*
|
||||||
|
|
||||||
|
endlocal
|
||||||
|
|
38
bin/zkSnapShotToolkit.sh
Normal file
38
bin/zkSnapShotToolkit.sh
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
# contributor license agreements. See the NOTICE file distributed with
|
||||||
|
# this work for additional information regarding copyright ownership.
|
||||||
|
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
# (the "License"); you may not use this file except in compliance with
|
||||||
|
# the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
#
|
||||||
|
# If this scripted is run out of /usr/bin or some other system bin directory
|
||||||
|
# it should be linked to and not copied. Things like java jar files are found
|
||||||
|
# relative to the canonical path of this script.
|
||||||
|
#
|
||||||
|
|
||||||
|
# use POSIX interface, symlink is followed automatically
|
||||||
|
ZOOBIN="${BASH_SOURCE-$0}"
|
||||||
|
ZOOBIN="$(dirname "${ZOOBIN}")"
|
||||||
|
ZOOBINDIR="$(cd "${ZOOBIN}"; pwd)"
|
||||||
|
|
||||||
|
if [ -e "$ZOOBIN/../libexec/zkEnv.sh" ]; then
|
||||||
|
. "$ZOOBINDIR"/../libexec/zkEnv.sh
|
||||||
|
else
|
||||||
|
. "$ZOOBINDIR"/zkEnv.sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
"$JAVA" -cp "$CLASSPATH" $JVMFLAGS \
|
||||||
|
org.apache.zookeeper.server.SnapshotFormatter "$@"
|
||||||
|
|
||||||
|
|
24
bin/zkTxnLogToolkit.cmd
Normal file
24
bin/zkTxnLogToolkit.cmd
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
@echo off
|
||||||
|
REM Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
REM contributor license agreements. See the NOTICE file distributed with
|
||||||
|
REM this work for additional information regarding copyright ownership.
|
||||||
|
REM The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
REM (the "License"); you may not use this file except in compliance with
|
||||||
|
REM the License. You may obtain a copy of the License at
|
||||||
|
REM
|
||||||
|
REM http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
REM
|
||||||
|
REM Unless required by applicable law or agreed to in writing, software
|
||||||
|
REM distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
REM See the License for the specific language governing permissions and
|
||||||
|
REM limitations under the License.
|
||||||
|
|
||||||
|
setlocal
|
||||||
|
call "%~dp0zkEnv.cmd"
|
||||||
|
|
||||||
|
set ZOOMAIN=org.apache.zookeeper.server.persistence.TxnLogToolkit
|
||||||
|
call %JAVA% -cp "%CLASSPATH%" %ZOOMAIN% %*
|
||||||
|
|
||||||
|
endlocal
|
||||||
|
|
38
bin/zkTxnLogToolkit.sh
Normal file
38
bin/zkTxnLogToolkit.sh
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
# contributor license agreements. See the NOTICE file distributed with
|
||||||
|
# this work for additional information regarding copyright ownership.
|
||||||
|
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
# (the "License"); you may not use this file except in compliance with
|
||||||
|
# the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
#
|
||||||
|
# If this scripted is run out of /usr/bin or some other system bin directory
|
||||||
|
# it should be linked to and not copied. Things like java jar files are found
|
||||||
|
# relative to the canonical path of this script.
|
||||||
|
#
|
||||||
|
|
||||||
|
# use POSIX interface, symlink is followed automatically
|
||||||
|
ZOOBIN="${BASH_SOURCE-$0}"
|
||||||
|
ZOOBIN="$(dirname "${ZOOBIN}")"
|
||||||
|
ZOOBINDIR="$(cd "${ZOOBIN}"; pwd)"
|
||||||
|
|
||||||
|
if [ -e "$ZOOBIN/../libexec/zkEnv.sh" ]; then
|
||||||
|
. "$ZOOBINDIR"/../libexec/zkEnv.sh
|
||||||
|
else
|
||||||
|
. "$ZOOBINDIR"/zkEnv.sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
"$JAVA" -cp "$CLASSPATH" $JVMFLAGS \
|
||||||
|
org.apache.zookeeper.server.persistence.TxnLogToolkit "$@"
|
||||||
|
|
||||||
|
|
63
checkstyle-simple.xml
Normal file
63
checkstyle-simple.xml
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
<!DOCTYPE module PUBLIC
|
||||||
|
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
|
||||||
|
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
|
||||||
|
|
||||||
|
<!-- This is a checkstyle configuration file. For descriptions of
|
||||||
|
what the following rules do, please see the checkstyle configuration
|
||||||
|
page at http://checkstyle.sourceforge.net/config.html -->
|
||||||
|
|
||||||
|
<module name="Checker">
|
||||||
|
|
||||||
|
<!-- Prevent *Tests.java as tools may not pick them up -->
|
||||||
|
<module name="RegexpOnFilename">
|
||||||
|
<property name="fileNamePattern" value=".*Tests\.java$" />
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="SuppressionFilter">
|
||||||
|
<property name="file" value="${checkstyle.suppressions.file}" default="suppressions.xml" />
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<!-- All Java AST specific tests live under TreeWalker module. -->
|
||||||
|
<module name="TreeWalker">
|
||||||
|
|
||||||
|
<!-- Allow use of comment to suppress javadocstyle -->
|
||||||
|
<module name="SuppressionCommentFilter">
|
||||||
|
<property name="offCommentFormat" value="CHECKSTYLE.OFF\: ([\w\|]+)"/>
|
||||||
|
<property name="onCommentFormat" value="CHECKSTYLE.ON\: ([\w\|]+)"/>
|
||||||
|
<property name="checkFormat" value="$1"/>
|
||||||
|
</module>
|
||||||
|
<module name="TodoComment">
|
||||||
|
<!-- Checks that disallowed strings are not used in comments. -->
|
||||||
|
<property name="format" value="(@author)" />
|
||||||
|
</module>
|
||||||
|
|
||||||
|
|
||||||
|
<module name="PackageName">
|
||||||
|
<!-- Validates identifiers for package names against the
|
||||||
|
supplied expression. -->
|
||||||
|
<!-- Here the default checkstyle rule restricts package name parts to
|
||||||
|
seven characters, this is not in line with common practice at Google.
|
||||||
|
-->
|
||||||
|
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]{1,})*$"/>
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
</module>
|
||||||
|
</module>
|
436
checkstyle-strict.xml
Normal file
436
checkstyle-strict.xml
Normal file
@ -0,0 +1,436 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
<!DOCTYPE module PUBLIC
|
||||||
|
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
|
||||||
|
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
|
||||||
|
|
||||||
|
<!-- This is a checkstyle configuration file. For descriptions of
|
||||||
|
what the following rules do, please see the checkstyle configuration
|
||||||
|
page at http://checkstyle.sourceforge.net/config.html -->
|
||||||
|
|
||||||
|
<module name="Checker">
|
||||||
|
|
||||||
|
<module name="FileTabCharacter">
|
||||||
|
<!-- Checks that there are no tab characters in the file. -->
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="RegexpSingleline">
|
||||||
|
<!-- Checks that TODOs don't have stuff in parenthesis, e.g., username. -->
|
||||||
|
<property name="format" value="((//.*)|(\*.*))TODO\(" />
|
||||||
|
<property name="message" value="TODO comments must not include usernames." />
|
||||||
|
<property name="severity" value="error" />
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="RegexpSingleline">
|
||||||
|
<property name="format" value="\s+$"/>
|
||||||
|
<property name="message" value="Trailing whitespace"/>
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="RegexpSingleline">
|
||||||
|
<property name="format" value="Throwables.propagate\("/>
|
||||||
|
<property name="message" value="Throwables.propagate is deprecated"/>
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<!-- Prevent *Tests.java as tools may not pick them up -->
|
||||||
|
<module name="RegexpOnFilename">
|
||||||
|
<property name="fileNamePattern" value=".*Tests\.java$" />
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="SuppressionFilter">
|
||||||
|
<property name="file" value="${checkstyle.suppressions.file}" default="suppressions.xml" />
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<!-- All Java AST specific tests live under TreeWalker module. -->
|
||||||
|
<module name="TreeWalker">
|
||||||
|
|
||||||
|
<!-- Allow use of comment to suppress javadocstyle -->
|
||||||
|
<module name="SuppressionCommentFilter">
|
||||||
|
<property name="offCommentFormat" value="CHECKSTYLE.OFF\: ([\w\|]+)"/>
|
||||||
|
<property name="onCommentFormat" value="CHECKSTYLE.ON\: ([\w\|]+)"/>
|
||||||
|
<property name="checkFormat" value="$1"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="TodoComment">
|
||||||
|
<!-- Checks that disallowed strings are not used in comments. -->
|
||||||
|
<property name="format" value="(FIXME)|(XXX)|(@author)" />
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
IMPORT CHECKS
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
<module name="RedundantImport">
|
||||||
|
<!-- Checks for redundant import statements. -->
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
<message key="import.redundancy"
|
||||||
|
value="Redundant import {0}."/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="ImportOrder">
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
<!-- This ensures that static imports go first. -->
|
||||||
|
<property name="option" value="top"/>
|
||||||
|
<property name="sortStaticImportsAlphabetically" value="true"/>
|
||||||
|
<property name="tokens" value="STATIC_IMPORT, IMPORT"/>
|
||||||
|
<message key="import.ordering"
|
||||||
|
value="Import {0} appears after other imports that it should precede"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="AvoidStarImport">
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="IllegalImport">
|
||||||
|
<property name="illegalPkgs" value="autovalue.shaded, avro.shaded, bk-shade, com.google.api.client.repackaged, com.google.appengine.repackaged, io.netty.util.internal"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="RedundantModifier">
|
||||||
|
<!-- Checks for redundant modifiers on various symbol definitions.
|
||||||
|
See: http://checkstyle.sourceforge.net/config_modifier.html#RedundantModifier
|
||||||
|
-->
|
||||||
|
<property name="tokens" value="METHOD_DEF, VARIABLE_DEF, ANNOTATION_FIELD_DEF, INTERFACE_DEF, CLASS_DEF, ENUM_DEF"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
IllegalImport cannot blacklist classes, and c.g.api.client.util is used for some shaded
|
||||||
|
code and some useful code. So we need to fall back to Regexp.
|
||||||
|
-->
|
||||||
|
<module name="RegexpSinglelineJava">
|
||||||
|
<property name="format" value="com\.google\.api\.client\.util\.(ByteStreams|Charsets|Collections2|Joiner|Lists|Maps|Objects|Preconditions|Sets|Strings|Throwables)"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Require static importing from Preconditions.
|
||||||
|
-->
|
||||||
|
<module name="RegexpSinglelineJava">
|
||||||
|
<property name="format" value="^import com.google.common.base.Preconditions;$"/>
|
||||||
|
<property name="message" value="Static import functions from Guava Preconditions"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="UnusedImports">
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
<property name="processJavadoc" value="true"/>
|
||||||
|
<message key="import.unused"
|
||||||
|
value="Unused import: {0}."/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
JAVADOC CHECKS
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- Checks for Javadoc comments. -->
|
||||||
|
<!-- See http://checkstyle.sf.net/config_javadoc.html -->
|
||||||
|
<module name="JavadocMethod">
|
||||||
|
<property name="scope" value="protected"/>
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
<property name="allowMissingJavadoc" value="true"/>
|
||||||
|
<property name="allowMissingParamTags" value="true"/>
|
||||||
|
<property name="allowMissingReturnTag" value="true"/>
|
||||||
|
<property name="allowMissingThrowsTags" value="true"/>
|
||||||
|
<property name="allowThrowsTagsForSubclasses" value="true"/>
|
||||||
|
<property name="allowUndeclaredRTE" value="true"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<!-- Check that paragraph tags are used correctly in Javadoc. -->
|
||||||
|
<module name="JavadocParagraph"/>
|
||||||
|
|
||||||
|
<module name="JavadocType">
|
||||||
|
<property name="scope" value="protected"/>
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
<property name="allowMissingParamTags" value="true"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="JavadocStyle">
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
<property name="checkHtml" value="true"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
NAMING CHECKS
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- Item 38 - Adhere to generally accepted naming conventions -->
|
||||||
|
|
||||||
|
<module name="PackageName">
|
||||||
|
<!-- Validates identifiers for package names against the
|
||||||
|
supplied expression. -->
|
||||||
|
<!-- Here the default checkstyle rule restricts package name parts to
|
||||||
|
seven characters, this is not in line with common practice at Google.
|
||||||
|
-->
|
||||||
|
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]{1,})*$"/>
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="TypeNameCheck">
|
||||||
|
<!-- Validates static, final fields against the
|
||||||
|
expression "^[A-Z][a-zA-Z0-9]*$". -->
|
||||||
|
<metadata name="altname" value="TypeName"/>
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="ConstantNameCheck">
|
||||||
|
<!-- Validates non-private, static, final fields against the supplied
|
||||||
|
public/package final fields "^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$". -->
|
||||||
|
<metadata name="altname" value="ConstantName"/>
|
||||||
|
<property name="applyToPublic" value="true"/>
|
||||||
|
<property name="applyToProtected" value="true"/>
|
||||||
|
<property name="applyToPackage" value="true"/>
|
||||||
|
<property name="applyToPrivate" value="false"/>
|
||||||
|
<property name="format" value="^([A-Z][A-Za-z0-9_]*|FLAG_.*)$"/>
|
||||||
|
<message key="name.invalidPattern"
|
||||||
|
value="Variable ''{0}'' should be in ALL_CAPS (if it is a constant) or be private (otherwise)."/>
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="StaticVariableNameCheck">
|
||||||
|
<!-- Validates static, non-final fields against the supplied
|
||||||
|
expression "^[a-z][a-zA-Z0-9]*_?$". -->
|
||||||
|
<metadata name="altname" value="StaticVariableName"/>
|
||||||
|
<property name="applyToPublic" value="true"/>
|
||||||
|
<property name="applyToProtected" value="true"/>
|
||||||
|
<property name="applyToPackage" value="true"/>
|
||||||
|
<property name="applyToPrivate" value="true"/>
|
||||||
|
<property name="format" value="^[a-z][a-zA-Z0-9]*_?$"/>
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="MemberNameCheck">
|
||||||
|
<!-- Validates non-static members against the supplied expression. -->
|
||||||
|
<metadata name="altname" value="MemberName"/>
|
||||||
|
<property name="applyToPublic" value="true"/>
|
||||||
|
<property name="applyToProtected" value="true"/>
|
||||||
|
<property name="applyToPackage" value="true"/>
|
||||||
|
<property name="applyToPrivate" value="true"/>
|
||||||
|
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="MethodNameCheck">
|
||||||
|
<!-- Validates identifiers for method names. -->
|
||||||
|
<metadata name="altname" value="MethodName"/>
|
||||||
|
<property name="format" value="(^[a-z][a-zA-Z0-9]*(_[a-zA-Z0-9]+)*$|Void)"/>
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="ParameterName">
|
||||||
|
<!-- Validates identifiers for method parameters against the
|
||||||
|
expression "^[a-z][a-zA-Z0-9]*$". -->
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="LocalFinalVariableName">
|
||||||
|
<!-- Validates identifiers for local final variables against the
|
||||||
|
expression "^[a-z][a-zA-Z0-9]*$". -->
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="LocalVariableName">
|
||||||
|
<!-- Validates identifiers for local variables against the
|
||||||
|
expression "^[a-z][a-zA-Z0-9]*$". -->
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<!-- Type parameters must be either one of the four blessed letters
|
||||||
|
T, K, V, W, X or else be capital-case terminated with a T,
|
||||||
|
such as MyGenericParameterT -->
|
||||||
|
<module name="ClassTypeParameterName">
|
||||||
|
<property name="format" value="^(((T|K|V|W|X|R)[0-9]*)|([A-Z][a-z][a-zA-Z]*))$"/>
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="MethodTypeParameterName">
|
||||||
|
<property name="format" value="^(((T|K|V|W|X|R)[0-9]*)|([A-Z][a-z][a-zA-Z]*T))$"/>
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="InterfaceTypeParameterName">
|
||||||
|
<property name="format" value="^(((T|K|V|W|X|R)[0-9]*)|([A-Z][a-z][a-zA-Z]*T))$"/>
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
LENGTH and CODING CHECKS
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
<module name="LineLength">
|
||||||
|
<!-- Checks if a line is too long. -->
|
||||||
|
<property name="max" value="120"/>
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The default ignore pattern exempts the following elements:
|
||||||
|
- import statements
|
||||||
|
- long URLs inside comments
|
||||||
|
-->
|
||||||
|
|
||||||
|
<property name="ignorePattern"
|
||||||
|
value="^(package .*;\s*)|(import .*;\s*)|( *\* .*https?://.*)$"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="LeftCurly">
|
||||||
|
<!-- Checks for placement of the left curly brace ('{'). -->
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="RightCurly">
|
||||||
|
<!-- Checks right curlies on CATCH, ELSE, and TRY blocks are on
|
||||||
|
the same line. e.g., the following example is fine:
|
||||||
|
<pre>
|
||||||
|
if {
|
||||||
|
...
|
||||||
|
} else
|
||||||
|
</pre>
|
||||||
|
-->
|
||||||
|
<!-- This next example is not fine:
|
||||||
|
<pre>
|
||||||
|
if {
|
||||||
|
...
|
||||||
|
}
|
||||||
|
else
|
||||||
|
</pre>
|
||||||
|
-->
|
||||||
|
<property name="option" value="same"/>
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<!-- Checks for braces around if and else blocks -->
|
||||||
|
<module name="NeedBraces">
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
<property name="tokens" value="LITERAL_IF, LITERAL_ELSE, LITERAL_FOR, LITERAL_WHILE, LITERAL_DO"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="UpperEll">
|
||||||
|
<!-- Checks that long constants are defined with an upper ell.-->
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="FallThrough">
|
||||||
|
<!-- Warn about falling through to the next case statement. Similar to
|
||||||
|
javac -Xlint:fallthrough, but the check is suppressed if a single-line comment
|
||||||
|
on the last non-blank line preceding the fallen-into case contains 'fall through' (or
|
||||||
|
some other variants that we don't publicized to promote consistency).
|
||||||
|
-->
|
||||||
|
<property name="reliefPattern"
|
||||||
|
value="fall through|Fall through|fallthru|Fallthru|falls through|Falls through|fallthrough|Fallthrough|No break|NO break|no break|continue on"/>
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<!-- Checks for over-complicated boolean expressions. -->
|
||||||
|
<module name="SimplifyBooleanExpression"/>
|
||||||
|
|
||||||
|
<!-- Detects empty statements (standalone ";" semicolon). -->
|
||||||
|
<module name="EmptyStatement"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
MODIFIERS CHECKS
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
<module name="ModifierOrder">
|
||||||
|
<!-- Warn if modifier order is inconsistent with JLS3 8.1.1, 8.3.1, and
|
||||||
|
8.4.3. The prescribed order is:
|
||||||
|
public, protected, private, abstract, static, final, transient, volatile,
|
||||||
|
synchronized, native, strictfp
|
||||||
|
-->
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
WHITESPACE CHECKS
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
<module name="WhitespaceAround">
|
||||||
|
<!-- Checks that various tokens are surrounded by whitespace.
|
||||||
|
This includes most binary operators and keywords followed
|
||||||
|
by regular or curly braces.
|
||||||
|
-->
|
||||||
|
<property name="tokens" value="ASSIGN, BAND, BAND_ASSIGN, BOR,
|
||||||
|
BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR, BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN,
|
||||||
|
EQUAL, GE, GT, LAND, LE, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE,
|
||||||
|
LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF, LITERAL_RETURN,
|
||||||
|
LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, LOR, LT, MINUS,
|
||||||
|
MINUS_ASSIGN, MOD, MOD_ASSIGN, NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION,
|
||||||
|
SL, SL_ASSIGN, SR_ASSIGN, STAR, STAR_ASSIGN"/>
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="WhitespaceAfter">
|
||||||
|
<!-- Checks that commas, semicolons and typecasts are followed by
|
||||||
|
whitespace.
|
||||||
|
-->
|
||||||
|
<property name="tokens" value="COMMA, SEMI, TYPECAST"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="NoWhitespaceAfter">
|
||||||
|
<!-- Checks that there is no whitespace after various unary operators.
|
||||||
|
Linebreaks are allowed.
|
||||||
|
-->
|
||||||
|
<property name="tokens" value="BNOT, DEC, DOT, INC, LNOT, UNARY_MINUS,
|
||||||
|
UNARY_PLUS"/>
|
||||||
|
<property name="allowLineBreaks" value="true"/>
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="NoWhitespaceBefore">
|
||||||
|
<!-- Checks that there is no whitespace before various unary operators.
|
||||||
|
Linebreaks are allowed.
|
||||||
|
-->
|
||||||
|
<property name="tokens" value="SEMI, DOT, POST_DEC, POST_INC"/>
|
||||||
|
<property name="allowLineBreaks" value="true"/>
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="OperatorWrap">
|
||||||
|
<!-- Checks that operators like + and ? appear at newlines rather than
|
||||||
|
at the end of the previous line.
|
||||||
|
-->
|
||||||
|
<property name="option" value="NL"/>
|
||||||
|
<property name="tokens" value="BAND, BOR, BSR, BXOR, DIV, EQUAL,
|
||||||
|
GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR, LT, MINUS, MOD,
|
||||||
|
NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR "/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="OperatorWrap">
|
||||||
|
<!-- Checks that assignment operators are at the end of the line. -->
|
||||||
|
<property name="option" value="eol"/>
|
||||||
|
<property name="tokens" value="ASSIGN"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="ParenPad">
|
||||||
|
<!-- Checks that there is no whitespace before close parens or after
|
||||||
|
open parens.
|
||||||
|
-->
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
</module>
|
||||||
|
</module>
|
35
checkstyleSuppressions.xml
Normal file
35
checkstyleSuppressions.xml
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License. See accompanying LICENSE file.
|
||||||
|
-->
|
||||||
|
<!DOCTYPE suppressions PUBLIC
|
||||||
|
"-//Puppy Crawl//DTD Suppressions 1.1//EN"
|
||||||
|
"http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
|
||||||
|
|
||||||
|
<suppressions>
|
||||||
|
<!-- suppress all checks in the generated directories -->
|
||||||
|
<suppress checks=".*" files=".+[\\/]classes[\\/].+\.java" />
|
||||||
|
<suppress checks=".*" files=".+[\\/]generated[\\/].+\.java" />
|
||||||
|
<suppress checks=".*" files=".+[\\/]generated-sources[\\/].+\.java" />
|
||||||
|
<suppress checks=".*" files=".+[\\/]generated-test-sources[\\/].+\.java" />
|
||||||
|
<suppress checks="LineLength" files=".+[\\/]jute[\\/].+\.java"/>
|
||||||
|
|
||||||
|
<!-- TODO ZOOKEEPER-3508 -->
|
||||||
|
<suppress checks="LineLength" files=".+[\\/]zookeeper-server[\\/].+\.java"/>
|
||||||
|
|
||||||
|
<!-- TODO ZOOKEEPER-3507 -->
|
||||||
|
<suppress checks=".*Name.*" files=".+[\\/]zookeeper-server[\\/].+\.java"/>
|
||||||
|
|
||||||
|
<!-- TODO ZOOKEEPER-3469 -->
|
||||||
|
<suppress checks="Javadoc.+" files=".+[\\/]zookeeper-server[\\/].+\.java"/>
|
||||||
|
</suppressions>
|
24
conf/configuration.xsl
Normal file
24
conf/configuration.xsl
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||||
|
<xsl:output method="html"/>
|
||||||
|
<xsl:template match="configuration">
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<table border="1">
|
||||||
|
<tr>
|
||||||
|
<td>name</td>
|
||||||
|
<td>value</td>
|
||||||
|
<td>description</td>
|
||||||
|
</tr>
|
||||||
|
<xsl:for-each select="property">
|
||||||
|
<tr>
|
||||||
|
<td><a name="{name}"><xsl:value-of select="name"/></a></td>
|
||||||
|
<td><xsl:value-of select="value"/></td>
|
||||||
|
<td><xsl:value-of select="description"/></td>
|
||||||
|
</tr>
|
||||||
|
</xsl:for-each>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</xsl:template>
|
||||||
|
</xsl:stylesheet>
|
82
conf/log4j.properties
Normal file
82
conf/log4j.properties
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
# Copyright 2012 The Apache Software Foundation
|
||||||
|
#
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
# or more contributor license agreements. See the NOTICE file
|
||||||
|
# distributed with this work for additional information
|
||||||
|
# regarding copyright ownership. The ASF licenses this file
|
||||||
|
# to you under the Apache License, Version 2.0 (the
|
||||||
|
# "License"); you may not use this file except in compliance
|
||||||
|
# with the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
# Define some default values that can be overridden by system properties
|
||||||
|
zookeeper.root.logger=INFO, CONSOLE
|
||||||
|
|
||||||
|
zookeeper.console.threshold=INFO
|
||||||
|
|
||||||
|
zookeeper.log.dir=.
|
||||||
|
zookeeper.log.file=zookeeper.log
|
||||||
|
zookeeper.log.threshold=INFO
|
||||||
|
zookeeper.log.maxfilesize=256MB
|
||||||
|
zookeeper.log.maxbackupindex=20
|
||||||
|
|
||||||
|
zookeeper.tracelog.dir=${zookeeper.log.dir}
|
||||||
|
zookeeper.tracelog.file=zookeeper_trace.log
|
||||||
|
|
||||||
|
log4j.rootLogger=${zookeeper.root.logger}
|
||||||
|
|
||||||
|
#
|
||||||
|
# console
|
||||||
|
# Add "console" to rootlogger above if you want to use this
|
||||||
|
#
|
||||||
|
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
|
||||||
|
log4j.appender.CONSOLE.Threshold=${zookeeper.console.threshold}
|
||||||
|
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
|
||||||
|
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L] - %m%n
|
||||||
|
|
||||||
|
#
|
||||||
|
# Add ROLLINGFILE to rootLogger to get log file output
|
||||||
|
#
|
||||||
|
log4j.appender.ROLLINGFILE=org.apache.log4j.RollingFileAppender
|
||||||
|
log4j.appender.ROLLINGFILE.Threshold=${zookeeper.log.threshold}
|
||||||
|
log4j.appender.ROLLINGFILE.File=${zookeeper.log.dir}/${zookeeper.log.file}
|
||||||
|
log4j.appender.ROLLINGFILE.MaxFileSize=${zookeeper.log.maxfilesize}
|
||||||
|
log4j.appender.ROLLINGFILE.MaxBackupIndex=${zookeeper.log.maxbackupindex}
|
||||||
|
log4j.appender.ROLLINGFILE.layout=org.apache.log4j.PatternLayout
|
||||||
|
log4j.appender.ROLLINGFILE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L] - %m%n
|
||||||
|
|
||||||
|
#
|
||||||
|
# Add TRACEFILE to rootLogger to get log file output
|
||||||
|
# Log TRACE level and above messages to a log file
|
||||||
|
#
|
||||||
|
log4j.appender.TRACEFILE=org.apache.log4j.FileAppender
|
||||||
|
log4j.appender.TRACEFILE.Threshold=TRACE
|
||||||
|
log4j.appender.TRACEFILE.File=${zookeeper.tracelog.dir}/${zookeeper.tracelog.file}
|
||||||
|
|
||||||
|
log4j.appender.TRACEFILE.layout=org.apache.log4j.PatternLayout
|
||||||
|
### Notice we are including log4j's NDC here (%x)
|
||||||
|
log4j.appender.TRACEFILE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L][%x] - %m%n
|
||||||
|
#
|
||||||
|
# zk audit logging
|
||||||
|
#
|
||||||
|
zookeeper.auditlog.file=zookeeper_audit.log
|
||||||
|
zookeeper.auditlog.threshold=INFO
|
||||||
|
audit.logger=INFO, RFAAUDIT
|
||||||
|
log4j.logger.org.apache.zookeeper.audit.Log4jAuditLogger=${audit.logger}
|
||||||
|
log4j.additivity.org.apache.zookeeper.audit.Log4jAuditLogger=false
|
||||||
|
log4j.appender.RFAAUDIT=org.apache.log4j.RollingFileAppender
|
||||||
|
log4j.appender.RFAAUDIT.File=${zookeeper.log.dir}/${zookeeper.auditlog.file}
|
||||||
|
log4j.appender.RFAAUDIT.layout=org.apache.log4j.PatternLayout
|
||||||
|
log4j.appender.RFAAUDIT.layout.ConversionPattern=%d{ISO8601} %p %c{2}: %m%n
|
||||||
|
log4j.appender.RFAAUDIT.Threshold=${zookeeper.auditlog.threshold}
|
||||||
|
|
||||||
|
# Max log file size of 10MB
|
||||||
|
log4j.appender.RFAAUDIT.MaxFileSize=10MB
|
||||||
|
log4j.appender.RFAAUDIT.MaxBackupIndex=10
|
36
conf/zoo.cfg
Normal file
36
conf/zoo.cfg
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# The number of milliseconds of each tick
|
||||||
|
tickTime=2000
|
||||||
|
# The number of ticks that the initial synchronization phase can take
|
||||||
|
initLimit=10
|
||||||
|
# The number of ticks that can pass between sending a request and getting an acknowledgement
|
||||||
|
syncLimit=5
|
||||||
|
# the directory where the snapshot is stored.
|
||||||
|
# do not use /tmp for storage, /tmp here is just
|
||||||
|
# example sakes.
|
||||||
|
dataDir=/home/bigdata/data/zkdata
|
||||||
|
dataLogDir=/home/bigdata/data/zklog/
|
||||||
|
# the port at which the clients will connect
|
||||||
|
clientPort=2181
|
||||||
|
# the maximum number of client connections.
|
||||||
|
# increase this if you need to handle more clients
|
||||||
|
#maxClientCnxns=60
|
||||||
|
# electionAlg=3 = FastLeaderElection
|
||||||
|
electionAlg=3
|
||||||
|
maxClientCnxns=60
|
||||||
|
# 服务器的类型: observer/participant(具有选举权的节点:leader follower)
|
||||||
|
peerType=observer/participant
|
||||||
|
# Be sure to read the maintenance section of the
|
||||||
|
# administrator guide before turning on autopurge.
|
||||||
|
#
|
||||||
|
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
|
||||||
|
#
|
||||||
|
# The number of snapshots to retain in dataDir
|
||||||
|
autopurge.snapRetainCount=3
|
||||||
|
# Purge task interval in hours
|
||||||
|
# Set to "0" to disable auto purge feature
|
||||||
|
autopurge.purgeInterval=1
|
||||||
|
|
||||||
|
server.2=bigdata02:2888
|
||||||
|
server.3=bigdata03:2888:3888
|
||||||
|
server.4=bigdata04:2888:3888:participant
|
||||||
|
server.5=bigdata05:2888:3888:observer
|
36
conf/zoo_sample.cfg
Normal file
36
conf/zoo_sample.cfg
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# The number of milliseconds of each tick
|
||||||
|
tickTime=2000
|
||||||
|
# The number of ticks that the initial
|
||||||
|
# synchronization phase can take
|
||||||
|
initLimit=10
|
||||||
|
# The number of ticks that can pass between
|
||||||
|
# sending a request and getting an acknowledgement
|
||||||
|
syncLimit=5
|
||||||
|
# the directory where the snapshot is stored.
|
||||||
|
# do not use /tmp for storage, /tmp here is just
|
||||||
|
# example sakes.
|
||||||
|
dataDir=/tmp/zookeeper
|
||||||
|
# the port at which the clients will connect
|
||||||
|
clientPort=2181
|
||||||
|
# the maximum number of client connections.
|
||||||
|
# increase this if you need to handle more clients
|
||||||
|
#maxClientCnxns=60
|
||||||
|
#
|
||||||
|
# Be sure to read the maintenance section of the
|
||||||
|
# administrator guide before turning on autopurge.
|
||||||
|
#
|
||||||
|
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
|
||||||
|
#
|
||||||
|
# The number of snapshots to retain in dataDir
|
||||||
|
#autopurge.snapRetainCount=3
|
||||||
|
# Purge task interval in hours
|
||||||
|
# Set to "0" to disable auto purge feature
|
||||||
|
#autopurge.purgeInterval=1
|
||||||
|
|
||||||
|
## Metrics Providers
|
||||||
|
#
|
||||||
|
# https://prometheus.io Metrics Exporter
|
||||||
|
#metricsProvider.className=org.apache.zookeeper.metrics.prometheus.PrometheusMetricsProvider
|
||||||
|
#metricsProvider.httpPort=7000
|
||||||
|
#metricsProvider.exportJvmInfo=true
|
||||||
|
|
31
dev/docker/Dockerfile
Normal file
31
dev/docker/Dockerfile
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
# or more contributor license agreements. See the NOTICE file
|
||||||
|
# distributed with this work for additional information
|
||||||
|
# regarding copyright ownership. The ASF licenses this file
|
||||||
|
# to you under the Apache License, Version 2.0 (the
|
||||||
|
# "License"); you may not use this file except in compliance
|
||||||
|
# with the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing,
|
||||||
|
# software distributed under the License is distributed on an
|
||||||
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
# KIND, either express or implied. See the License for the
|
||||||
|
# specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
FROM maven:3.6.3-jdk-8
|
||||||
|
|
||||||
|
RUN apt-get update
|
||||||
|
RUN apt-get install -y \
|
||||||
|
g++ \
|
||||||
|
cmake \
|
||||||
|
autoconf \
|
||||||
|
pkg-config \
|
||||||
|
libcppunit-dev \
|
||||||
|
libtool \
|
||||||
|
openssl \
|
||||||
|
libssl-dev
|
72
dev/docker/run.sh
Normal file
72
dev/docker/run.sh
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
# contributor license agreements. See the NOTICE file distributed with
|
||||||
|
# this work for additional information regarding copyright ownership.
|
||||||
|
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
# (the "License"); you may not use this file except in compliance with
|
||||||
|
# the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
set -e -x -u
|
||||||
|
|
||||||
|
SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||||
|
|
||||||
|
export IMAGE_NAME="zookeeper/dev"
|
||||||
|
|
||||||
|
pushd ${SCRIPT_DIR}
|
||||||
|
|
||||||
|
docker build --rm=true -t ${IMAGE_NAME} .
|
||||||
|
|
||||||
|
popd
|
||||||
|
|
||||||
|
if [ "$(uname -s)" == "Linux" ]; then
|
||||||
|
USER_NAME=${SUDO_USER:=$USER}
|
||||||
|
USER_ID=$(id -u "${USER_NAME}")
|
||||||
|
GROUP_ID=$(id -g "${USER_NAME}")
|
||||||
|
LOCAL_HOME=$(realpath ~)
|
||||||
|
else # boot2docker uid and gid
|
||||||
|
USER_NAME=$USER
|
||||||
|
USER_ID=1000
|
||||||
|
GROUP_ID=50
|
||||||
|
LOCAL_HOME="/Users/${USER_NAME}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
docker build -t "${IMAGE_NAME}-${USER_NAME}" - <<UserSpecificDocker
|
||||||
|
FROM ${IMAGE_NAME}
|
||||||
|
RUN groupadd --non-unique -g ${GROUP_ID} ${USER_NAME} && \
|
||||||
|
useradd -g ${GROUP_ID} -u ${USER_ID} -k /root -m ${USER_NAME}
|
||||||
|
ENV HOME /home/${USER_NAME}
|
||||||
|
UserSpecificDocker
|
||||||
|
|
||||||
|
ZOOKEEPER_ROOT=${SCRIPT_DIR}/../..
|
||||||
|
|
||||||
|
CMD="
|
||||||
|
echo
|
||||||
|
echo 'Welcome to Apache ZooKeeper Development Env'
|
||||||
|
echo 'To build, execute'
|
||||||
|
echo ' mvn clean install'
|
||||||
|
echo
|
||||||
|
bash
|
||||||
|
"
|
||||||
|
|
||||||
|
pushd ${ZOOKEEPER_ROOT}
|
||||||
|
|
||||||
|
docker run -i -t \
|
||||||
|
--rm=true \
|
||||||
|
-w ${ZOOKEEPER_ROOT} \
|
||||||
|
-u "${USER}" \
|
||||||
|
-v "$(realpath $ZOOKEEPER_ROOT):${ZOOKEEPER_ROOT}" \
|
||||||
|
-v "${LOCAL_HOME}:/home/${USER_NAME}" \
|
||||||
|
${IMAGE_NAME}-${USER_NAME} \
|
||||||
|
bash -c "${CMD}"
|
||||||
|
|
||||||
|
popd
|
||||||
|
|
11
excludeFindBugsFilter.xml
Normal file
11
excludeFindBugsFilter.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<FindBugsFilter>
|
||||||
|
<!-- this work work on JDK11 https://github.com/spotbugs/spotbugs-maven-plugin/issues/92 -->
|
||||||
|
<Bug pattern="RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE"/>
|
||||||
|
|
||||||
|
<!-- this problem is to be addressed in ZOOKEEPER-3227 -->
|
||||||
|
<Bug pattern="DM_DEFAULT_ENCODING"/>
|
||||||
|
|
||||||
|
</FindBugsFilter>
|
||||||
|
|
54
owaspSuppressions.xml
Normal file
54
owaspSuppressions.xml
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.2.xsd">
|
||||||
|
<suppress>
|
||||||
|
<!-- ZOOKEEPER-3217 -->
|
||||||
|
<cve>CVE-2018-8088</cve>
|
||||||
|
</suppress>
|
||||||
|
<suppress>
|
||||||
|
<!-- ZOOKEEPER-3262 -->
|
||||||
|
<cve>CVE-2018-8012</cve>
|
||||||
|
</suppress>
|
||||||
|
<suppress>
|
||||||
|
<!-- ZOOKEEPER-3262 -->
|
||||||
|
<cve>CVE-2016-5017</cve>
|
||||||
|
</suppress>
|
||||||
|
<suppress>
|
||||||
|
<!-- https://github.com/jeremylong/DependencyCheck/issues/1653
|
||||||
|
False positive on Netty 4.x-->
|
||||||
|
<cve>CVE-2018-12056</cve>
|
||||||
|
</suppress>
|
||||||
|
<suppress>
|
||||||
|
<!-- Seems like false positive - we are not using Prometheus
|
||||||
|
2.x, rather the client which lastest is 0.6. at the time of
|
||||||
|
this writing -->
|
||||||
|
<cve>CVE-2019-3826</cve>
|
||||||
|
</suppress>
|
||||||
|
<suppress>
|
||||||
|
<!-- false positive for us, it is about log4j server in log4j-1.2.17.jar
|
||||||
|
ZOOKEEPER-3677 -->
|
||||||
|
<cve>CVE-2019-17571</cve>
|
||||||
|
</suppress>
|
||||||
|
<suppress>
|
||||||
|
<!-- it only affects the log4j SmtpAppender users. As Log4J 1.2 is EOL now, we can't fix this unless we
|
||||||
|
upgrade to log4j 2. See ZOOKEEPER-3817 -->
|
||||||
|
<cve>CVE-2020-9488</cve>
|
||||||
|
</suppress>
|
||||||
|
</suppressions>
|
997
pom.xml
Normal file
997
pom.xml
Normal file
@ -0,0 +1,997 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<!--
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.apache</groupId>
|
||||||
|
<artifactId>apache</artifactId>
|
||||||
|
<version>23</version>
|
||||||
|
<relativePath />
|
||||||
|
<!-- no parent resolution -->
|
||||||
|
</parent>
|
||||||
|
<groupId>org.apache.zookeeper</groupId>
|
||||||
|
<artifactId>parent</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<!-- to change version: mvn -\-batch-mode release:update-versions -DdevelopmentVersion=3.6.0-SNAPSHOT -->
|
||||||
|
<version>3.6.3</version>
|
||||||
|
<name>Apache ZooKeeper</name>
|
||||||
|
<description>
|
||||||
|
ZooKeeper is a centralized service for maintaining configuration information, naming,
|
||||||
|
providing distributed synchronization, and providing group services. All of these kinds
|
||||||
|
of services are used in some form or another by distributed applications. Each time they
|
||||||
|
are implemented there is a lot of work that goes into fixing the bugs and race conditions
|
||||||
|
that are inevitable. Because of the difficulty of implementing these kinds of services,
|
||||||
|
applications initially usually skimp on them ,which make them brittle in the presence of
|
||||||
|
change and difficult to manage. Even when done correctly, different implementations of
|
||||||
|
these services lead to management complexity when the applications are deployed.
|
||||||
|
</description>
|
||||||
|
<url>http://zookeeper.apache.org</url>
|
||||||
|
<inceptionYear>2008</inceptionYear>
|
||||||
|
<!-- Set here so we can consistently use the correct name, even on branches with
|
||||||
|
an ASF parent pom older than v15. Also uses the url from v18.
|
||||||
|
-->
|
||||||
|
<licenses>
|
||||||
|
<license>
|
||||||
|
<name>Apache License, Version 2.0</name>
|
||||||
|
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||||
|
<distribution>repo</distribution>
|
||||||
|
</license>
|
||||||
|
</licenses>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<module>zookeeper-docs</module>
|
||||||
|
<module>zookeeper-jute</module>
|
||||||
|
<module>zookeeper-server</module>
|
||||||
|
<module>zookeeper-metrics-providers</module>
|
||||||
|
<module>zookeeper-client</module>
|
||||||
|
<module>zookeeper-recipes</module>
|
||||||
|
<module>zookeeper-assembly</module>
|
||||||
|
<module>zookeeper-compatibility-tests</module>
|
||||||
|
</modules>
|
||||||
|
|
||||||
|
<scm>
|
||||||
|
<connection>scm:git:https://gitbox.apache.org/repos/asf/zookeeper.git</connection>
|
||||||
|
<developerConnection>scm:git:https://gitbox.apache.org/repos/asf/zookeeper.git</developerConnection>
|
||||||
|
<url>https://gitbox.apache.org/repos/asf/zookeeper.git</url>
|
||||||
|
<tag>release-3.6.3-2</tag>
|
||||||
|
</scm>
|
||||||
|
<issueManagement>
|
||||||
|
<system>JIRA</system>
|
||||||
|
<url>http://issues.apache.org/jira/browse/ZOOKEEPER</url>
|
||||||
|
</issueManagement>
|
||||||
|
<ciManagement>
|
||||||
|
<system>jenkins</system>
|
||||||
|
<url>https://ci-hadoop.apache.org/view/ZooKeeper/</url>
|
||||||
|
</ciManagement>
|
||||||
|
<mailingLists>
|
||||||
|
<mailingList>
|
||||||
|
<name>User List</name>
|
||||||
|
<subscribe>user-subscribe@zookeeper.apache.org</subscribe>
|
||||||
|
<unsubscribe>user-unsubscribe@zookeeper.apache.org</unsubscribe>
|
||||||
|
<post>user@zookeeper.apache.org</post>
|
||||||
|
<archive>http://mail-archives.apache.org/mod_mbox/zookeeper-user/</archive>
|
||||||
|
</mailingList>
|
||||||
|
<mailingList>
|
||||||
|
<name>Developer List</name>
|
||||||
|
<subscribe>dev-subscribe@zookeeper.apache.org</subscribe>
|
||||||
|
<unsubscribe>dev-unsubscribe@zookeeper.apache.org</unsubscribe>
|
||||||
|
<post>dev@zookeeper.apache.org</post>
|
||||||
|
<archive>http://mail-archives.apache.org/mod_mbox/zookeeper-dev/</archive>
|
||||||
|
</mailingList>
|
||||||
|
<mailingList>
|
||||||
|
<name>Commits List</name>
|
||||||
|
<subscribe>commits-subscribe@zookeeper.apache.org</subscribe>
|
||||||
|
<unsubscribe>commits-unsubscribe@zookeeper.apache.org</unsubscribe>
|
||||||
|
<archive>http://mail-archives.apache.org/mod_mbox/zookeeper-commits/</archive>
|
||||||
|
</mailingList>
|
||||||
|
<mailingList>
|
||||||
|
<name>Issues List</name>
|
||||||
|
<subscribe>issues-subscribe@zookeeper.apache.org</subscribe>
|
||||||
|
<unsubscribe>issues-unsubscribe@zookeeper.apache.org</unsubscribe>
|
||||||
|
<archive>https://lists.apache.org/list.html?issues@zookeeper.apache.org</archive>
|
||||||
|
</mailingList>
|
||||||
|
<mailingList>
|
||||||
|
<name>Notifications List</name>
|
||||||
|
<subscribe>notifications-subscribe@zookeeper.apache.org</subscribe>
|
||||||
|
<unsubscribe>notifications-unsubscribe@zookeeper.apache.org</unsubscribe>
|
||||||
|
<archive>https://lists.apache.org/list.html?notifications@zookeeper.apache.org</archive>
|
||||||
|
</mailingList>
|
||||||
|
</mailingLists>
|
||||||
|
<developers>
|
||||||
|
<developer>
|
||||||
|
<id>tdunning</id>
|
||||||
|
<name>Ted Dunning </name>
|
||||||
|
<email>tdunning@apache.org</email>
|
||||||
|
<timezone>-8</timezone>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>camille</id>
|
||||||
|
<name>Camille Fournier</name>
|
||||||
|
<email>camille@apache.org</email>
|
||||||
|
<timezone>-5</timezone>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>phunt</id>
|
||||||
|
<name>Patrick Hunt</name>
|
||||||
|
<email>phunt@apache.org</email>
|
||||||
|
<timezone>-8</timezone>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>fpj</id>
|
||||||
|
<name>Flavio Junqueira</name>
|
||||||
|
<email>fpj@apache.org</email>
|
||||||
|
<timezone>+0</timezone>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>ivank</id>
|
||||||
|
<name>Ivan Kelly</name>
|
||||||
|
<email>ivank@apache.org</email>
|
||||||
|
<timezone>+2</timezone>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>mahadev</id>
|
||||||
|
<name>Mahadev Konar</name>
|
||||||
|
<email>mahadev@apache.org</email>
|
||||||
|
<timezone>-8</timezone>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>michim</id>
|
||||||
|
<name>Michi Mutsuzaki</name>
|
||||||
|
<email>michim@apache.org</email>
|
||||||
|
<timezone>-8</timezone>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>cnauroth</id>
|
||||||
|
<name>Chris Nauroth</name>
|
||||||
|
<email>cnauroth@apache.org</email>
|
||||||
|
<timezone>-8</timezone>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>breed</id>
|
||||||
|
<name>Benjamin Reed</name>
|
||||||
|
<email>breed@apache.org</email>
|
||||||
|
<timezone>-8</timezone>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>henry</id>
|
||||||
|
<name>Henry Robinson</name>
|
||||||
|
<email>henry@apache.org</email>
|
||||||
|
<timezone>-8</timezone>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>rgs</id>
|
||||||
|
<name>Raul Gutierrez Segales</name>
|
||||||
|
<email>rgs@apache.org</email>
|
||||||
|
<timezone>-8</timezone>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>rakeshr</id>
|
||||||
|
<name>Rakesh Radhakrishnan</name>
|
||||||
|
<email>rakeshr@apache.org</email>
|
||||||
|
<timezone>+5:30</timezone>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>hanm</id>
|
||||||
|
<name>Michael Han</name>
|
||||||
|
<email>hanm@apache.org</email>
|
||||||
|
<timezone>-8</timezone>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>gkesavan</id>
|
||||||
|
<name>Giridharan Kesavan</name>
|
||||||
|
<email>gkesavan@apache.org</email>
|
||||||
|
<timezone>-8</timezone>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>akornev</id>
|
||||||
|
<name>Andrew Kornev</name>
|
||||||
|
<email>akornev@apache.org</email>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>shralex</id>
|
||||||
|
<name>Alex Shraer</name>
|
||||||
|
<email>shralex@apache.org</email>
|
||||||
|
<timezone>-8</timezone>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>thawan</id>
|
||||||
|
<name>Thawan Kooburat</name>
|
||||||
|
<email>thawan@apache.org</email>
|
||||||
|
<timezone>-8</timezone>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>hdeng</id>
|
||||||
|
<name>Hongchao Deng</name>
|
||||||
|
<email>hdeng@apache.org</email>
|
||||||
|
<timezone>-8</timezone>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>arshad</id>
|
||||||
|
<name>Mohammad Arshad</name>
|
||||||
|
<email>arshad@apache.org</email>
|
||||||
|
<timezone>+5:30</timezone>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>afine</id>
|
||||||
|
<name>Abraham Fine</name>
|
||||||
|
<email>afine@apache.org</email>
|
||||||
|
<timezone>-8</timezone>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>andor</id>
|
||||||
|
<name>Andor Molnar</name>
|
||||||
|
<email>andor@apache.org</email>
|
||||||
|
<timezone>+1</timezone>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>lvfangmin</id>
|
||||||
|
<name>Allan Lyu</name>
|
||||||
|
<email>fangmin@apache.org</email>
|
||||||
|
<timezone>-8</timezone>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>eolivelli</id>
|
||||||
|
<name>Enrico Olivelli</name>
|
||||||
|
<email>eolivelli@apache.org</email>
|
||||||
|
<timezone>+1</timezone>
|
||||||
|
</developer>
|
||||||
|
</developers>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>full-build</id>
|
||||||
|
<modules>
|
||||||
|
<module>zookeeper-it</module>
|
||||||
|
<module>zookeeper-contrib</module>
|
||||||
|
</modules>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>fatjar</id>
|
||||||
|
<modules>
|
||||||
|
<module>zookeeper-it</module>
|
||||||
|
<module>zookeeper-contrib</module>
|
||||||
|
</modules>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>java-build</id>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>true</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>apache-release</id>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.apache.resources</groupId>
|
||||||
|
<artifactId>apache-source-release-assembly-descriptor</artifactId>
|
||||||
|
<version>1.0.6</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>source-release-assembly-tar-gz</id>
|
||||||
|
<phase>initialize</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>single</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<runOnlyAtExecutionRoot>true</runOnlyAtExecutionRoot>
|
||||||
|
<descriptorRefs>
|
||||||
|
<!-- defined in Apache Parent Pom -->
|
||||||
|
<descriptorRef>${sourceReleaseAssemblyDescriptor}</descriptorRef>
|
||||||
|
</descriptorRefs>
|
||||||
|
<finalName>apache-zookeeper-${project.version}</finalName>
|
||||||
|
<appendAssemblyId>false</appendAssemblyId>
|
||||||
|
<formats>
|
||||||
|
<format>tar.gz</format>
|
||||||
|
</formats>
|
||||||
|
<tarLongFileMode>posix</tarLongFileMode>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>m2e</id>
|
||||||
|
<activation>
|
||||||
|
<property>
|
||||||
|
<name>m2e.version</name>
|
||||||
|
</property>
|
||||||
|
</activation>
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.release>8</maven.compiler.release>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>jdk-release-flag</id>
|
||||||
|
<activation>
|
||||||
|
<jdk>[9,)</jdk>
|
||||||
|
</activation>
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.release>8</maven.compiler.release>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<!-- maven properties -->
|
||||||
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
|
<dependency.locations.enabled>false</dependency.locations.enabled>
|
||||||
|
|
||||||
|
<surefire-forkcount>8</surefire-forkcount>
|
||||||
|
|
||||||
|
<!-- dependency versions -->
|
||||||
|
<slf4j.version>1.7.25</slf4j.version>
|
||||||
|
<audience-annotations.version>0.5.0</audience-annotations.version>
|
||||||
|
<jmockit.version>1.48</jmockit.version>
|
||||||
|
<junit.version>4.12</junit.version>
|
||||||
|
<log4j.version>1.2.17</log4j.version>
|
||||||
|
<mockito.version>2.27.0</mockito.version>
|
||||||
|
<hamcrest.version>1.3</hamcrest.version>
|
||||||
|
<commons-cli.version>1.2</commons-cli.version>
|
||||||
|
<netty.version>4.1.63.Final</netty.version>
|
||||||
|
<jetty.version>9.4.39.v20210325</jetty.version>
|
||||||
|
<jackson.version>2.10.5.1</jackson.version>
|
||||||
|
<json.version>1.1.1</json.version>
|
||||||
|
<jline.version>2.14.6</jline.version>
|
||||||
|
<snappy.version>1.1.7</snappy.version>
|
||||||
|
<kerby.version>2.0.0</kerby.version>
|
||||||
|
<bouncycastle.version>1.60</bouncycastle.version>
|
||||||
|
<commons-collections.version>3.2.2</commons-collections.version>
|
||||||
|
<dropwizard.version>3.2.5</dropwizard.version>
|
||||||
|
<spotbugsannotations.version>4.0.2</spotbugsannotations.version>
|
||||||
|
<checkstyle.version>8.17</checkstyle.version>
|
||||||
|
<enforcer.version>3.0.0-M3</enforcer.version>
|
||||||
|
|
||||||
|
<!-- parameter to pass to C client build -->
|
||||||
|
<c-client-openssl>yes</c-client-openssl>
|
||||||
|
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hamcrest</groupId>
|
||||||
|
<artifactId>hamcrest-all</artifactId>
|
||||||
|
<version>${hamcrest.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-collections</groupId>
|
||||||
|
<artifactId>commons-collections</artifactId>
|
||||||
|
<version>${commons-collections.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.yetus</groupId>
|
||||||
|
<artifactId>audience-annotations</artifactId>
|
||||||
|
<version>${audience-annotations.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-cli</groupId>
|
||||||
|
<artifactId>commons-cli</artifactId>
|
||||||
|
<version>${commons-cli.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.kerby</groupId>
|
||||||
|
<artifactId>kerb-core</artifactId>
|
||||||
|
<version>${kerby.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.kerby</groupId>
|
||||||
|
<artifactId>kerb-simplekdc</artifactId>
|
||||||
|
<version>${kerby.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.kerby</groupId>
|
||||||
|
<artifactId>kerby-config</artifactId>
|
||||||
|
<version>${kerby.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-log4j12</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.bouncycastle</groupId>
|
||||||
|
<artifactId>bcprov-jdk15on</artifactId>
|
||||||
|
<version>${bouncycastle.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.bouncycastle</groupId>
|
||||||
|
<artifactId>bcpkix-jdk15on</artifactId>
|
||||||
|
<version>${bouncycastle.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
<version>${slf4j.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-log4j12</artifactId>
|
||||||
|
<version>${slf4j.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>*</groupId>
|
||||||
|
<artifactId>*</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>log4j</groupId>
|
||||||
|
<artifactId>log4j</artifactId>
|
||||||
|
<version>${log4j.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jmockit</groupId>
|
||||||
|
<artifactId>jmockit</artifactId>
|
||||||
|
<version>${jmockit.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>${junit.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-core</artifactId>
|
||||||
|
<version>${mockito.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.netty</groupId>
|
||||||
|
<artifactId>netty-handler</artifactId>
|
||||||
|
<version>${netty.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.netty</groupId>
|
||||||
|
<artifactId>netty-transport-native-epoll</artifactId>
|
||||||
|
<version>${netty.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-server</artifactId>
|
||||||
|
<version>${jetty.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-servlet</artifactId>
|
||||||
|
<version>${jetty.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.dropwizard.metrics</groupId>
|
||||||
|
<artifactId>metrics-core</artifactId>
|
||||||
|
<version>${dropwizard.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-databind</artifactId>
|
||||||
|
<version>${jackson.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.googlecode.json-simple</groupId>
|
||||||
|
<artifactId>json-simple</artifactId>
|
||||||
|
<version>${json.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>jline</groupId>
|
||||||
|
<artifactId>jline</artifactId>
|
||||||
|
<version>${jline.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.spotbugs</groupId>
|
||||||
|
<artifactId>spotbugs-annotations</artifactId>
|
||||||
|
<version>${spotbugsannotations.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.xerial.snappy</groupId>
|
||||||
|
<artifactId>snappy-java</artifactId>
|
||||||
|
<version>${snappy.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.8.1</version>
|
||||||
|
<configuration>
|
||||||
|
<showWarnings>true</showWarnings>
|
||||||
|
<compilerArgs>
|
||||||
|
<compilerArg>-Werror</compilerArg>
|
||||||
|
<compilerArg>-Xlint:deprecation</compilerArg>
|
||||||
|
<compilerArg>-Xlint:unchecked</compilerArg>
|
||||||
|
<compilerArg>-Xlint:-options</compilerArg>
|
||||||
|
<compilerArg>-Xdoclint:-missing</compilerArg>
|
||||||
|
<!-- https://issues.apache.org/jira/browse/MCOMPILER-205 -->
|
||||||
|
<compilerArg>-Xpkginfo:always</compilerArg>
|
||||||
|
</compilerArgs>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>3.1.0</version>
|
||||||
|
<configuration>
|
||||||
|
<archive>
|
||||||
|
<manifestEntries>
|
||||||
|
<Implementation-Build>${mvngit.commit.id}</Implementation-Build>
|
||||||
|
</manifestEntries>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
|
<version>3.0.1</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
<version>3.0.1</version>
|
||||||
|
<configuration>
|
||||||
|
<doclint>none</doclint>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
<version>3.1.0</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-release-plugin</artifactId>
|
||||||
|
<version>2.5.3</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-scm-plugin</artifactId>
|
||||||
|
<version>1.11.2</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>2.22.1</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-antrun-plugin</artifactId>
|
||||||
|
<version>1.8</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<version>3.1.1</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
|
<artifactId>exec-maven-plugin</artifactId>
|
||||||
|
<version>1.6.0</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.github.koraktor</groupId>
|
||||||
|
<artifactId>mavanagaiata</artifactId>
|
||||||
|
<version>0.9.4</version>
|
||||||
|
<configuration>
|
||||||
|
<skipNoGit>true</skipNoGit>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
|
<artifactId>build-helper-maven-plugin</artifactId>
|
||||||
|
<version>3.0.0</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>net.nicoulaj.maven.plugins</groupId>
|
||||||
|
<artifactId>checksum-maven-plugin</artifactId>
|
||||||
|
<version>1.8</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.openclover</groupId>
|
||||||
|
<artifactId>clover-maven-plugin</artifactId>
|
||||||
|
<version>4.3.1</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.github.spotbugs</groupId>
|
||||||
|
<artifactId>spotbugs-maven-plugin</artifactId>
|
||||||
|
<version>4.0.0</version>
|
||||||
|
<configuration>
|
||||||
|
<excludeFilterFile>excludeFindBugsFilter.xml</excludeFilterFile>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.owasp</groupId>
|
||||||
|
<artifactId>dependency-check-maven</artifactId>
|
||||||
|
<version>5.3.0</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||||
|
<version>3.1.0</version>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.puppycrawl.tools</groupId>
|
||||||
|
<artifactId>checkstyle</artifactId>
|
||||||
|
<version>${checkstyle.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<configuration>
|
||||||
|
<configLocation>checkstyle-strict.xml</configLocation>
|
||||||
|
<suppressionsLocation>checkstyleSuppressions.xml</suppressionsLocation>
|
||||||
|
<encoding>UTF-8</encoding>
|
||||||
|
<consoleOutput>true</consoleOutput>
|
||||||
|
<failOnViolation>true</failOnViolation>
|
||||||
|
<includeResources>false</includeResources>
|
||||||
|
<includeTestResources>false</includeTestResources>
|
||||||
|
<includeTestSourceDirectory>true</includeTestSourceDirectory>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>checkstyle</id>
|
||||||
|
<phase>validate</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>check</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<!-- we don't need this plugin-->
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-remote-resources-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>process-resource-bundles</id>
|
||||||
|
<phase>none</phase>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</pluginManagement>
|
||||||
|
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.github.koraktor</groupId>
|
||||||
|
<artifactId>mavanagaiata</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>find-current-git-revision</id>
|
||||||
|
<goals>
|
||||||
|
<goal>commit</goal>
|
||||||
|
</goals>
|
||||||
|
<phase>validate</phase>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.openclover</groupId>
|
||||||
|
<artifactId>clover-maven-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<generateHtml>true</generateHtml>
|
||||||
|
<generateXml>true</generateXml>
|
||||||
|
<includes>
|
||||||
|
<include>org/apache/zookeeper/**/*</include>
|
||||||
|
</includes>
|
||||||
|
<excludes>
|
||||||
|
<exclude>org/apache/zookeeper/version/**/*</exclude>
|
||||||
|
</excludes>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>pre-site</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>instrument</goal>
|
||||||
|
<goal>aggregate</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-antrun-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>validate</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>run</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<exportAntProperties>true</exportAntProperties>
|
||||||
|
<target>
|
||||||
|
<property environment="env" />
|
||||||
|
<exec executable="hostname" outputproperty="host.name" />
|
||||||
|
</target>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>Jar Tests Package</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>test-jar</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<includes>
|
||||||
|
<include>org/**</include>
|
||||||
|
<include>META_INF/**</include>
|
||||||
|
</includes>
|
||||||
|
<skipIfEmpty>true</skipIfEmpty>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>attach-sources</id>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>attach-javadocs</id>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>aggregate</id>
|
||||||
|
<phase>site</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>aggregate</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<overview>zookeeper-server/src/main/resources/overview.html</overview>
|
||||||
|
<excludePackageNames>*.recipes.*</excludePackageNames>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<!-- Maven's deploy plugin only creates checksums during the deployment of the jar artifacts to repo. -->
|
||||||
|
<!-- We also want to sign tarballs. Nicoulaj's plugin is the recommended solution by the community. -->
|
||||||
|
<groupId>net.nicoulaj.maven.plugins</groupId>
|
||||||
|
<artifactId>checksum-maven-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>artifacts</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<algorithms>
|
||||||
|
<algorithm>SHA-512</algorithm>
|
||||||
|
</algorithms>
|
||||||
|
<appendFilename>true</appendFilename>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.github.spotbugs</groupId>
|
||||||
|
<artifactId>spotbugs-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.owasp</groupId>
|
||||||
|
<artifactId>dependency-check-maven</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<format>ALL</format>
|
||||||
|
<failBuildOnCVSS>0</failBuildOnCVSS>
|
||||||
|
<suppressionFiles>
|
||||||
|
<suppressionsFile>owaspSuppressions.xml</suppressionsFile>
|
||||||
|
</suppressionFiles>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.rat</groupId>
|
||||||
|
<artifactId>apache-rat-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<excludes>
|
||||||
|
<exclude>**/log4j.properties</exclude>
|
||||||
|
<exclude>**/README.md</exclude>
|
||||||
|
<exclude>**/findbugsExcludeFile.xml</exclude>
|
||||||
|
<exclude>**/checkstyle-noframes-sorted.xsl</exclude>
|
||||||
|
<exclude>**/configure.ac</exclude>
|
||||||
|
<exclude>**/Makefile.am</exclude>
|
||||||
|
<exclude>conf/zoo_sample.cfg</exclude>
|
||||||
|
<exclude>conf/configuration.xsl</exclude>
|
||||||
|
<exclude>.travis.yml</exclude>
|
||||||
|
<exclude>excludeFindBugsFilter.xml</exclude>
|
||||||
|
<exclude>README_packaging.md</exclude>
|
||||||
|
<exclude>src/main/resources/markdown/skin/*</exclude>
|
||||||
|
<exclude>src/main/resources/markdown/html/*</exclude>
|
||||||
|
<exclude>src/main/resources/markdown/images/*</exclude>
|
||||||
|
<!-- contrib -->
|
||||||
|
<exclude>**/JMX-RESOURCES</exclude>
|
||||||
|
<exclude>**/src/main/resources/mainClasses</exclude>
|
||||||
|
<exclude>**/Changes</exclude>
|
||||||
|
<exclude>**/MANIFEST</exclude>
|
||||||
|
<exclude>**/src/test/zoo.cfg</exclude>
|
||||||
|
<exclude>**/src/main/resources/webapp/org/apache/zookeeper/graph/resources/*</exclude>
|
||||||
|
<exclude>**/src/main/java/com/nitido/utils/toaster/Toaster.java</exclude>
|
||||||
|
<exclude>**/TODO</exclude>
|
||||||
|
<!-- c client -->
|
||||||
|
<exclude>**/acinclude.m4</exclude>
|
||||||
|
<exclude>**/aminclude.am</exclude>
|
||||||
|
<exclude>**/src/hashtable/*</exclude>
|
||||||
|
<exclude>**/include/winconfig.h</exclude>
|
||||||
|
<exclude>**/tests/wrappers.opt</exclude>
|
||||||
|
<exclude>**/tests/zoo.cfg</exclude>
|
||||||
|
<exclude>**/tests/wrappers-mt.opt</exclude>
|
||||||
|
<exclude>**/c-doc.Doxyfile</exclude>
|
||||||
|
</excludes>
|
||||||
|
<consoleOutput>true</consoleOutput>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-release-plugin</artifactId>
|
||||||
|
<inherited>false</inherited>
|
||||||
|
<configuration>
|
||||||
|
<!-- update the version inside the C sources -->
|
||||||
|
<preparationGoals>clean install -DskipTests antrun:run@replace-cclient-files-during-release scm:add@add-cclient-files-during-release scm:checkin@commit-cclient-files-during-release</preparationGoals>
|
||||||
|
<completionGoals>clean install -DskipTests antrun:run@replace-cclient-files-during-release scm:add@add-cclient-files-during-release scm:checkin@commit-cclient-files-during-release</completionGoals>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-scm-plugin</artifactId>
|
||||||
|
<inherited>false</inherited>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>add-cclient-files-during-release</id>
|
||||||
|
<phase>none</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>add</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<pushChanges>false</pushChanges>
|
||||||
|
<includes>zookeeper-client/zookeeper-client-c/CMakeLists.txt,zookeeper-client/zookeeper-client-c/configure.ac,zookeeper-client/zookeeper-client-c/include/zookeeper_version.h</includes>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>commit-cclient-files-during-release</id>
|
||||||
|
<phase>none</phase>
|
||||||
|
<goals>
|
||||||
|
<!-- git commit -->
|
||||||
|
<goal>checkin</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<pushChanges>false</pushChanges>
|
||||||
|
<message>Prepared ${project.version}</message>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-enforcer-plugin</artifactId>
|
||||||
|
<version>${enforcer.version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>banned-commons-lang</id>
|
||||||
|
<goals>
|
||||||
|
<goal>enforce</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<rules>
|
||||||
|
<bannedDependencies>
|
||||||
|
<excludes>
|
||||||
|
<exclude>commons-lang:commons-lang</exclude>
|
||||||
|
</excludes>
|
||||||
|
<searchTransitive>false</searchTransitive>
|
||||||
|
<message>We don't use commons-lang any more, so do not depend on it directly.</message>
|
||||||
|
</bannedDependencies>
|
||||||
|
</rules>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>banned-commons-lang3</id>
|
||||||
|
<goals>
|
||||||
|
<goal>enforce</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<rules>
|
||||||
|
<bannedDependencies>
|
||||||
|
<excludes>
|
||||||
|
<exclude>org.apache.commons:commons-lang3</exclude>
|
||||||
|
</excludes>
|
||||||
|
<searchTransitive>false</searchTransitive>
|
||||||
|
<message>We don't use commons-lang3, so do not depend on it directly.</message>
|
||||||
|
</bannedDependencies>
|
||||||
|
</rules>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>${project.basedir}src/main/java/resources</directory>
|
||||||
|
<excludes>
|
||||||
|
<exclude>**/*.*</exclude>
|
||||||
|
</excludes>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<reporting>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.openclover</groupId>
|
||||||
|
<artifactId>clover-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</reporting>
|
||||||
|
|
||||||
|
</project>
|
533
zk-merge-pr.py
Normal file
533
zk-merge-pr.py
Normal file
@ -0,0 +1,533 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
# contributor license agreements. See the NOTICE file distributed with
|
||||||
|
# this work for additional information regarding copyright ownership.
|
||||||
|
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
# (the "License"); you may not use this file except in compliance with
|
||||||
|
# the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
# Utility for creating well-formed pull request merges and pushing them to Apache. This script is a modified version
|
||||||
|
# of the one created by the Spark project (https://github.com/apache/spark/blob/master/dev/merge_spark_pr.py).
|
||||||
|
#
|
||||||
|
# Usage: ./zk-merge-pr.py (see config env vars below)
|
||||||
|
#
|
||||||
|
# This utility assumes you already have a local ZooKeeper git folder and that you
|
||||||
|
# have added remotes corresponding to both:
|
||||||
|
# (i) the github apache ZooKeeper mirror and
|
||||||
|
# (ii) the apache ZooKeeper git repo.
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import urllib.request, urllib.error, urllib.parse
|
||||||
|
import getpass
|
||||||
|
|
||||||
|
try:
|
||||||
|
import jira.client
|
||||||
|
JIRA_IMPORTED = True
|
||||||
|
except ImportError:
|
||||||
|
JIRA_IMPORTED = False
|
||||||
|
|
||||||
|
PROJECT_NAME = "zookeeper"
|
||||||
|
|
||||||
|
CAPITALIZED_PROJECT_NAME = PROJECT_NAME.upper()
|
||||||
|
|
||||||
|
# Remote name which points to the GitHub site
|
||||||
|
PR_REMOTE_NAME = os.environ.get("PR_REMOTE_NAME", "apache-github")
|
||||||
|
# Remote name which points to Apache git
|
||||||
|
PUSH_REMOTE_NAME = os.environ.get("PUSH_REMOTE_NAME", "apache")
|
||||||
|
# ASF JIRA username
|
||||||
|
JIRA_USERNAME = os.environ.get("JIRA_USERNAME", "")
|
||||||
|
# ASF JIRA password
|
||||||
|
JIRA_PASSWORD = os.environ.get("JIRA_PASSWORD", "")
|
||||||
|
# OAuth key used for issuing requests against the GitHub API. If this is not defined, then requests
|
||||||
|
# will be unauthenticated. You should only need to configure this if you find yourself regularly
|
||||||
|
# exceeding your IP's unauthenticated request rate limit. You can create an OAuth key at
|
||||||
|
# https://github.com/settings/tokens. This script only requires the "public_repo" scope.
|
||||||
|
GITHUB_OAUTH_KEY = os.environ.get("GITHUB_OAUTH_KEY")
|
||||||
|
|
||||||
|
GITHUB_USER = os.environ.get("GITHUB_USER", "apache")
|
||||||
|
GITHUB_BASE = "https://github.com/%s/%s/pull" % (GITHUB_USER, PROJECT_NAME)
|
||||||
|
GITHUB_API_BASE = "https://api.github.com/repos/%s/%s" % (GITHUB_USER, PROJECT_NAME)
|
||||||
|
JIRA_BASE = "https://issues.apache.org/jira/browse"
|
||||||
|
JIRA_API_BASE = "https://issues.apache.org/jira"
|
||||||
|
# Prefix added to temporary branches
|
||||||
|
TEMP_BRANCH_PREFIX = "PR_TOOL"
|
||||||
|
# TODO Introduce a convention as this is too brittle
|
||||||
|
RELEASE_BRANCH_PREFIX = "branch-"
|
||||||
|
|
||||||
|
DEV_BRANCH_NAME = "master"
|
||||||
|
|
||||||
|
DEFAULT_FIX_VERSION = os.environ.get("DEFAULT_FIX_VERSION", "branch-3.5")
|
||||||
|
|
||||||
|
def get_json(url):
|
||||||
|
try:
|
||||||
|
request = urllib.request.Request(url)
|
||||||
|
if GITHUB_OAUTH_KEY:
|
||||||
|
request.add_header('Authorization', 'token %s' % GITHUB_OAUTH_KEY)
|
||||||
|
return json.load(urllib.request.urlopen(request))
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if "X-RateLimit-Remaining" in e.headers and e.headers["X-RateLimit-Remaining"] == '0':
|
||||||
|
print("Exceeded the GitHub API rate limit; see the instructions in " + \
|
||||||
|
"zk-merge-pr.py to configure an OAuth token for making authenticated " + \
|
||||||
|
"GitHub requests.")
|
||||||
|
else:
|
||||||
|
print("Unable to fetch URL, exiting: %s" % url)
|
||||||
|
sys.exit(-1)
|
||||||
|
|
||||||
|
|
||||||
|
def fail(msg):
|
||||||
|
print(msg)
|
||||||
|
clean_up()
|
||||||
|
sys.exit(-1)
|
||||||
|
|
||||||
|
|
||||||
|
def run_cmd(cmd):
|
||||||
|
print(cmd)
|
||||||
|
if isinstance(cmd, list):
|
||||||
|
return subprocess.check_output(cmd, encoding='utf8')
|
||||||
|
else:
|
||||||
|
return subprocess.check_output(cmd.split(" "), encoding='utf8')
|
||||||
|
|
||||||
|
|
||||||
|
def continue_maybe(prompt):
|
||||||
|
result = input("\n%s (y/n): " % prompt)
|
||||||
|
if result.lower().strip() != "y":
|
||||||
|
fail("Okay, exiting")
|
||||||
|
|
||||||
|
def clean_up():
|
||||||
|
if original_head != get_current_branch():
|
||||||
|
print("Restoring head pointer to %s" % original_head)
|
||||||
|
run_cmd("git checkout %s" % original_head)
|
||||||
|
|
||||||
|
branches = run_cmd("git branch").replace(" ", "").split("\n")
|
||||||
|
|
||||||
|
for branch in [x for x in branches if x.startswith(TEMP_BRANCH_PREFIX)]:
|
||||||
|
print("Deleting local branch %s" % branch)
|
||||||
|
run_cmd("git branch -D %s" % branch)
|
||||||
|
|
||||||
|
def get_current_branch():
|
||||||
|
return run_cmd("git rev-parse --abbrev-ref HEAD").replace("\n", "")
|
||||||
|
|
||||||
|
# merge the requested PR and return the merge hash
|
||||||
|
def merge_pr(pr_num, target_ref, title, body, pr_repo_desc):
|
||||||
|
pr_branch_name = "%s_MERGE_PR_%s" % (TEMP_BRANCH_PREFIX, pr_num)
|
||||||
|
target_branch_name = "%s_MERGE_PR_%s_%s" % (TEMP_BRANCH_PREFIX, pr_num, target_ref.upper())
|
||||||
|
run_cmd("git fetch %s pull/%s/head:%s" % (PR_REMOTE_NAME, pr_num, pr_branch_name))
|
||||||
|
run_cmd("git fetch %s %s:%s" % (PUSH_REMOTE_NAME, target_ref, target_branch_name))
|
||||||
|
run_cmd("git checkout %s" % target_branch_name)
|
||||||
|
|
||||||
|
had_conflicts = False
|
||||||
|
try:
|
||||||
|
run_cmd(['git', 'merge', pr_branch_name, '--squash'])
|
||||||
|
except Exception as e:
|
||||||
|
msg = "Error merging: %s\nWould you like to manually fix-up this merge?" % e
|
||||||
|
continue_maybe(msg)
|
||||||
|
msg = "Okay, please fix any conflicts and 'git add' conflicting files... Finished?"
|
||||||
|
continue_maybe(msg)
|
||||||
|
had_conflicts = True
|
||||||
|
|
||||||
|
commit_authors = run_cmd(['git', 'log', 'HEAD..%s' % pr_branch_name,
|
||||||
|
'--pretty=format:%an <%ae>']).split("\n")
|
||||||
|
distinct_authors = sorted(set(commit_authors),
|
||||||
|
key=lambda x: commit_authors.count(x), reverse=True)
|
||||||
|
primary_author = input(
|
||||||
|
"Enter primary author in the format of \"name <email>\" [%s]: " %
|
||||||
|
distinct_authors[0])
|
||||||
|
if primary_author == "":
|
||||||
|
primary_author = distinct_authors[0]
|
||||||
|
|
||||||
|
reviewers = input(
|
||||||
|
"Enter reviewers in the format of \"name1 <email1>, name2 <email2>\": ").strip()
|
||||||
|
|
||||||
|
commits = run_cmd(['git', 'log', 'HEAD..%s' % pr_branch_name,
|
||||||
|
'--pretty=format:%h [%an] %s']).split("\n")
|
||||||
|
|
||||||
|
if len(commits) > 1:
|
||||||
|
result = input("List pull request commits in squashed commit message? (y/n): ")
|
||||||
|
if result.lower().strip() == "y":
|
||||||
|
should_list_commits = True
|
||||||
|
else:
|
||||||
|
should_list_commits = False
|
||||||
|
else:
|
||||||
|
should_list_commits = False
|
||||||
|
|
||||||
|
merge_message_flags = []
|
||||||
|
|
||||||
|
merge_message_flags += ["-m", title]
|
||||||
|
if body is not None:
|
||||||
|
# We remove @ symbols from the body to avoid triggering e-mails
|
||||||
|
# to people every time someone creates a public fork of the project.
|
||||||
|
merge_message_flags += ["-m", body.replace("@", "")]
|
||||||
|
|
||||||
|
authors = "\n".join(["Author: %s" % a for a in distinct_authors])
|
||||||
|
|
||||||
|
merge_message_flags += ["-m", authors]
|
||||||
|
|
||||||
|
if (reviewers != ""):
|
||||||
|
merge_message_flags += ["-m", "Reviewers: %s" % reviewers]
|
||||||
|
|
||||||
|
if had_conflicts:
|
||||||
|
committer_name = run_cmd("git config --get user.name").strip()
|
||||||
|
committer_email = run_cmd("git config --get user.email").strip()
|
||||||
|
message = "This patch had conflicts when merged, resolved by\nCommitter: %s <%s>" % (
|
||||||
|
committer_name, committer_email)
|
||||||
|
merge_message_flags += ["-m", message]
|
||||||
|
|
||||||
|
# The string "Closes #%s" string is required for GitHub to correctly close the PR
|
||||||
|
close_line = "Closes #%s from %s" % (pr_num, pr_repo_desc)
|
||||||
|
if should_list_commits:
|
||||||
|
close_line += " and squashes the following commits:"
|
||||||
|
merge_message_flags += ["-m", close_line]
|
||||||
|
|
||||||
|
if should_list_commits:
|
||||||
|
merge_message_flags += ["-m", "\n".join(commits)]
|
||||||
|
|
||||||
|
run_cmd(['git', 'commit', '--author="%s"' % primary_author] + merge_message_flags)
|
||||||
|
|
||||||
|
continue_maybe("Merge complete (local ref %s). Push to %s?" % (
|
||||||
|
target_branch_name, PUSH_REMOTE_NAME))
|
||||||
|
|
||||||
|
try:
|
||||||
|
run_cmd('git push %s %s:%s' % (PUSH_REMOTE_NAME, target_branch_name, target_ref))
|
||||||
|
except Exception as e:
|
||||||
|
clean_up()
|
||||||
|
fail("Exception while pushing: %s" % e)
|
||||||
|
|
||||||
|
merge_hash = run_cmd("git rev-parse %s" % target_branch_name)[:8]
|
||||||
|
clean_up()
|
||||||
|
print(("Pull request #%s merged!" % pr_num))
|
||||||
|
print(("Merge hash: %s" % merge_hash))
|
||||||
|
return merge_hash
|
||||||
|
|
||||||
|
|
||||||
|
def cherry_pick(pr_num, merge_hash, default_branch):
|
||||||
|
pick_ref = input("Enter a branch name [%s]: " % default_branch)
|
||||||
|
if pick_ref == "":
|
||||||
|
pick_ref = default_branch
|
||||||
|
|
||||||
|
pick_branch_name = "%s_PICK_PR_%s_%s" % (TEMP_BRANCH_PREFIX, pr_num, pick_ref.upper())
|
||||||
|
|
||||||
|
run_cmd("git fetch %s %s:%s" % (PUSH_REMOTE_NAME, pick_ref, pick_branch_name))
|
||||||
|
run_cmd("git checkout %s" % pick_branch_name)
|
||||||
|
|
||||||
|
try:
|
||||||
|
run_cmd("git cherry-pick -sx %s" % merge_hash)
|
||||||
|
except Exception as e:
|
||||||
|
msg = "Error cherry-picking: %s\nWould you like to manually fix-up this merge?" % e
|
||||||
|
continue_maybe(msg)
|
||||||
|
msg = "Okay, please fix any conflicts and finish the cherry-pick. Finished?"
|
||||||
|
continue_maybe(msg)
|
||||||
|
|
||||||
|
continue_maybe("Pick complete (local ref %s). Push to %s?" % (
|
||||||
|
pick_branch_name, PUSH_REMOTE_NAME))
|
||||||
|
|
||||||
|
try:
|
||||||
|
run_cmd('git push %s %s:%s' % (PUSH_REMOTE_NAME, pick_branch_name, pick_ref))
|
||||||
|
except Exception as e:
|
||||||
|
clean_up()
|
||||||
|
fail("Exception while pushing: %s" % e)
|
||||||
|
|
||||||
|
pick_hash = run_cmd("git rev-parse %s" % pick_branch_name)[:8]
|
||||||
|
clean_up()
|
||||||
|
|
||||||
|
print(("Pull request #%s picked into %s!" % (pr_num, pick_ref)))
|
||||||
|
print(("Pick hash: %s" % pick_hash))
|
||||||
|
return pick_ref
|
||||||
|
|
||||||
|
|
||||||
|
def fix_version_from_branch(branch, versions):
|
||||||
|
# Note: Assumes this is a sorted (newest->oldest) list of un-released versions
|
||||||
|
if branch == DEV_BRANCH_NAME:
|
||||||
|
versions = [x for x in versions if x == DEFAULT_FIX_VERSION]
|
||||||
|
if len(versions) > 0:
|
||||||
|
return versions[0]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
versions = [x for x in versions if x.startswith(branch)]
|
||||||
|
if len(versions) > 0:
|
||||||
|
return versions[-1]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_jira_issue(merge_branches, comment, default_jira_id=""):
|
||||||
|
asf_jira = jira.client.JIRA({'server': JIRA_API_BASE},
|
||||||
|
basic_auth=(JIRA_USERNAME, JIRA_PASSWORD))
|
||||||
|
|
||||||
|
jira_id = input("Enter a JIRA id [%s]: " % default_jira_id)
|
||||||
|
if jira_id == "":
|
||||||
|
jira_id = default_jira_id
|
||||||
|
|
||||||
|
try:
|
||||||
|
issue = asf_jira.issue(jira_id)
|
||||||
|
except Exception as e:
|
||||||
|
fail("ASF JIRA could not find %s\n%s" % (jira_id, e))
|
||||||
|
|
||||||
|
cur_status = issue.fields.status.name
|
||||||
|
cur_summary = issue.fields.summary
|
||||||
|
cur_assignee = issue.fields.assignee
|
||||||
|
if cur_assignee is None:
|
||||||
|
cur_assignee = "NOT ASSIGNED!!!"
|
||||||
|
else:
|
||||||
|
cur_assignee = cur_assignee.displayName
|
||||||
|
|
||||||
|
if cur_status == "Resolved" or cur_status == "Closed":
|
||||||
|
fail("JIRA issue %s already has status '%s'" % (jira_id, cur_status))
|
||||||
|
print(("=== JIRA %s ===" % jira_id))
|
||||||
|
print(("summary\t\t%s\nassignee\t%s\nstatus\t\t%s\nurl\t\t%s/%s\n" % (
|
||||||
|
cur_summary, cur_assignee, cur_status, JIRA_BASE, jira_id)))
|
||||||
|
|
||||||
|
versions = asf_jira.project_versions(CAPITALIZED_PROJECT_NAME)
|
||||||
|
versions = sorted(versions, key=lambda x: x.name, reverse=True)
|
||||||
|
versions = [x for x in versions if x.raw['released'] is False]
|
||||||
|
|
||||||
|
version_names = [x.name for x in versions]
|
||||||
|
default_fix_versions = [fix_version_from_branch(x, version_names) for x in merge_branches]
|
||||||
|
default_fix_versions = [x for x in default_fix_versions if x != None]
|
||||||
|
default_fix_versions = ",".join(default_fix_versions)
|
||||||
|
|
||||||
|
fix_versions = input("Enter comma-separated fix version(s) [%s]: " % default_fix_versions)
|
||||||
|
if fix_versions == "":
|
||||||
|
fix_versions = default_fix_versions
|
||||||
|
fix_versions = fix_versions.replace(" ", "").split(",")
|
||||||
|
|
||||||
|
def get_version_json(version_str):
|
||||||
|
return filter(lambda v: v.name == version_str, versions)[0].raw
|
||||||
|
|
||||||
|
jira_fix_versions = [get_version_json(v) for v in fix_versions]
|
||||||
|
|
||||||
|
resolve = filter(lambda a: a['name'] == "Resolve Issue", asf_jira.transitions(jira_id))[0]
|
||||||
|
resolution = filter(lambda r: r.raw['name'] == "Fixed", asf_jira.resolutions())[0]
|
||||||
|
asf_jira.transition_issue(
|
||||||
|
jira_id, resolve["id"], fixVersions = jira_fix_versions,
|
||||||
|
comment = comment, resolution = {'id': resolution.raw['id']})
|
||||||
|
|
||||||
|
print("Successfully resolved %s with fixVersions=%s!" % (jira_id, fix_versions))
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_jira_issues(title, merge_branches, comment):
|
||||||
|
jira_ids = re.findall("%s-[0-9]{4,5}" % CAPITALIZED_PROJECT_NAME, title)
|
||||||
|
|
||||||
|
if len(jira_ids) == 0:
|
||||||
|
resolve_jira_issue(merge_branches, comment)
|
||||||
|
for jira_id in jira_ids:
|
||||||
|
resolve_jira_issue(merge_branches, comment, jira_id)
|
||||||
|
|
||||||
|
|
||||||
|
def standardize_jira_ref(text):
|
||||||
|
"""
|
||||||
|
Standardize the jira reference commit message prefix to "PROJECT_NAME-XXX: Issue"
|
||||||
|
|
||||||
|
>>> standardize_jira_ref("%s-5954: Top by key" % CAPITALIZED_PROJECT_NAME)
|
||||||
|
'ZOOKEEPER-5954: Top by key'
|
||||||
|
>>> standardize_jira_ref("%s-5821: ParquetRelation2 CTAS should check if delete is successful" % PROJECT_NAME)
|
||||||
|
'ZOOKEEPER-5821: ParquetRelation2 CTAS should check if delete is successful'
|
||||||
|
>>> standardize_jira_ref("%s-4123: [WIP] Show new dependencies added in pull requests" % PROJECT_NAME)
|
||||||
|
'ZOOKEEPER-4123: [WIP] Show new dependencies added in pull requests'
|
||||||
|
>>> standardize_jira_ref("%s 5954: Top by key" % PROJECT_NAME)
|
||||||
|
'ZOOKEEPER-5954: Top by key'
|
||||||
|
>>> standardize_jira_ref("%s-979: a LRU scheduler for load balancing in TaskSchedulerImpl" % PROJECT_NAME)
|
||||||
|
'ZOOKEEPER-979: a LRU scheduler for load balancing in TaskSchedulerImpl'
|
||||||
|
>>> standardize_jira_ref("%s-1094: Support MiMa for reporting binary compatibility across versions." % CAPITALIZED_PROJECT_NAME)
|
||||||
|
'ZOOKEEPER-1094: Support MiMa for reporting binary compatibility across versions.'
|
||||||
|
>>> standardize_jira_ref("%s-1146: [WIP] Vagrant support" % CAPITALIZED_PROJECT_NAME)
|
||||||
|
'ZOOKEEPER-1146: [WIP] Vagrant support'
|
||||||
|
>>> standardize_jira_ref("%s-1032: If Yarn app fails before registering, app master stays aroun..." % PROJECT_NAME)
|
||||||
|
'ZOOKEEPER-1032: If Yarn app fails before registering, app master stays aroun...'
|
||||||
|
>>> standardize_jira_ref("%s-6250 %s-6146 %s-5911: Types are now reserved words in DDL parser." % (PROJECT_NAME, PROJECT_NAME, CAPITALIZED_PROJECT_NAME))
|
||||||
|
'ZOOKEEPER-6250 ZOOKEEPER-6146 ZOOKEEPER-5911: Types are now reserved words in DDL parser.'
|
||||||
|
>>> standardize_jira_ref("Additional information for users building from source code")
|
||||||
|
'Additional information for users building from source code'
|
||||||
|
"""
|
||||||
|
jira_refs = []
|
||||||
|
components = []
|
||||||
|
|
||||||
|
# Extract JIRA ref(s):
|
||||||
|
pattern = re.compile(r'(%s[-\s]*[0-9]{3,6})+' % CAPITALIZED_PROJECT_NAME, re.IGNORECASE)
|
||||||
|
for ref in pattern.findall(text):
|
||||||
|
# Add brackets, replace spaces with a dash, & convert to uppercase
|
||||||
|
jira_refs.append(re.sub(r'\s+', '-', ref.upper()))
|
||||||
|
text = text.replace(ref, '')
|
||||||
|
|
||||||
|
# Extract project name component(s):
|
||||||
|
# Look for alphanumeric chars, spaces, dashes, periods, and/or commas
|
||||||
|
pattern = re.compile(r'(\[[\w\s,-\.]+\])', re.IGNORECASE)
|
||||||
|
for component in pattern.findall(text):
|
||||||
|
components.append(component.upper())
|
||||||
|
text = text.replace(component, '')
|
||||||
|
|
||||||
|
# Cleanup any remaining symbols:
|
||||||
|
pattern = re.compile(r'^\W+(.*)', re.IGNORECASE)
|
||||||
|
if (pattern.search(text) is not None):
|
||||||
|
text = pattern.search(text).groups()[0]
|
||||||
|
|
||||||
|
# Assemble full text (JIRA ref(s), module(s), remaining text)
|
||||||
|
jira_prefix = ' '.join(jira_refs).strip()
|
||||||
|
if jira_prefix:
|
||||||
|
jira_prefix = jira_prefix + ": "
|
||||||
|
clean_text = jira_prefix + ' '.join(components).strip() + " " + text.strip()
|
||||||
|
|
||||||
|
# Replace multiple spaces with a single space, e.g. if no jira refs and/or components were included
|
||||||
|
clean_text = re.sub(r'\s+', ' ', clean_text.strip())
|
||||||
|
|
||||||
|
return clean_text
|
||||||
|
|
||||||
|
def get_remote_repos():
|
||||||
|
repos = run_cmd("git remote -v").split()
|
||||||
|
|
||||||
|
dict = {}
|
||||||
|
for i in range(0, len(repos), 3):
|
||||||
|
dict[repos[i]] = repos[i+1]
|
||||||
|
return dict
|
||||||
|
|
||||||
|
|
||||||
|
def check_git_remote():
|
||||||
|
repos = get_remote_repos()
|
||||||
|
|
||||||
|
# check if all remote endpoints' URLs point to project git repo
|
||||||
|
name = PROJECT_NAME + ".git"
|
||||||
|
for url in list(repos.values()):
|
||||||
|
if not url.endswith(name):
|
||||||
|
fail("Error: not a %s git repo or at least one remote is invalid" % PROJECT_NAME)
|
||||||
|
|
||||||
|
if not PR_REMOTE_NAME in repos:
|
||||||
|
fail("Error: PR_REMOTE_NAME (%s) environment variable has not been set!" % PR_REMOTE_NAME)
|
||||||
|
|
||||||
|
if not PUSH_REMOTE_NAME in repos:
|
||||||
|
fail("Error: PUSH_REMOTE_NAME (%s) environment variable has not been set!" % PUSH_REMOTE_NAME)
|
||||||
|
|
||||||
|
|
||||||
|
def check_jira_env():
|
||||||
|
|
||||||
|
global JIRA_PASSWORD
|
||||||
|
|
||||||
|
if JIRA_IMPORTED:
|
||||||
|
|
||||||
|
if JIRA_USERNAME.strip() != "" and JIRA_PASSWORD.strip() == "":
|
||||||
|
inform_pwd = input("JIRA_USERNAME set but JIRA_PASSWORD is not. Want to inform it? ")
|
||||||
|
if inform_pwd.strip() == "y":
|
||||||
|
JIRA_PASSWORD = getpass.getpass('JIRA PASSWORD: ')
|
||||||
|
|
||||||
|
if JIRA_USERNAME.strip() == "" or JIRA_PASSWORD.strip() == "":
|
||||||
|
msg ="JIRA_USERNAME and/or JIRA_PASSWORD are not set. Want to continue? "
|
||||||
|
continue_maybe(msg)
|
||||||
|
else:
|
||||||
|
msg = "JIRA lib not installed. Want to continue? "
|
||||||
|
continue_maybe(msg)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
global original_head
|
||||||
|
|
||||||
|
original_head = get_current_branch()
|
||||||
|
|
||||||
|
check_jira_env()
|
||||||
|
|
||||||
|
check_git_remote()
|
||||||
|
|
||||||
|
branches = get_json("%s/branches" % GITHUB_API_BASE)
|
||||||
|
branch_names = [x for x in [x['name'] for x in branches] if x.startswith(RELEASE_BRANCH_PREFIX)]
|
||||||
|
# Assumes branch names can be sorted lexicographically
|
||||||
|
latest_branch = sorted(branch_names, reverse=True)[0]
|
||||||
|
|
||||||
|
pr_num = input("Which pull request would you like to merge? (e.g. 34): ")
|
||||||
|
pr = get_json("%s/pulls/%s" % (GITHUB_API_BASE, pr_num))
|
||||||
|
pr_events = get_json("%s/issues/%s/events" % (GITHUB_API_BASE, pr_num))
|
||||||
|
|
||||||
|
url = pr["url"]
|
||||||
|
|
||||||
|
pr_title = pr["title"]
|
||||||
|
commit_title = input("Commit title [%s]: " % pr_title)
|
||||||
|
if commit_title == "":
|
||||||
|
commit_title = pr_title
|
||||||
|
|
||||||
|
# Decide whether to use the modified title or not
|
||||||
|
modified_title = standardize_jira_ref(commit_title)
|
||||||
|
if modified_title != commit_title:
|
||||||
|
print("I've re-written the title as follows to match the standard format:")
|
||||||
|
print("Original: %s" % commit_title)
|
||||||
|
print("Modified: %s" % modified_title)
|
||||||
|
result = input("Would you like to use the modified title? (y/n): ")
|
||||||
|
if result.lower().strip() == "y":
|
||||||
|
commit_title = modified_title
|
||||||
|
print("Using modified title:")
|
||||||
|
else:
|
||||||
|
print("Using original title:")
|
||||||
|
print(commit_title)
|
||||||
|
|
||||||
|
body = pr["body"]
|
||||||
|
target_ref = pr["base"]["ref"]
|
||||||
|
user_login = pr["user"]["login"]
|
||||||
|
base_ref = pr["head"]["ref"]
|
||||||
|
pr_repo_desc = "%s/%s" % (user_login, base_ref)
|
||||||
|
|
||||||
|
# Merged pull requests don't appear as merged in the GitHub API;
|
||||||
|
# Instead, they're closed by asfgit.
|
||||||
|
merge_commits = \
|
||||||
|
[e for e in pr_events if e["actor"]["login"] == "asfgit" and e["event"] == "closed"]
|
||||||
|
|
||||||
|
if merge_commits:
|
||||||
|
merge_hash = merge_commits[0]["commit_id"]
|
||||||
|
message = get_json("%s/commits/%s" % (GITHUB_API_BASE, merge_hash))["commit"]["message"]
|
||||||
|
|
||||||
|
print("Pull request %s has already been merged, assuming you want to backport" % pr_num)
|
||||||
|
commit_is_downloaded = run_cmd(['git', 'rev-parse', '--quiet', '--verify',
|
||||||
|
"%s^{commit}" % merge_hash]).strip() != ""
|
||||||
|
if not commit_is_downloaded:
|
||||||
|
fail("Couldn't find any merge commit for #%s, you may need to update HEAD." % pr_num)
|
||||||
|
|
||||||
|
print("Found commit %s:\n%s" % (merge_hash, message))
|
||||||
|
cherry_pick(pr_num, merge_hash, latest_branch)
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
if not bool(pr["mergeable"]):
|
||||||
|
msg = "Pull request %s is not mergeable in its current form.\n" % pr_num + \
|
||||||
|
"Continue? (experts only!)"
|
||||||
|
continue_maybe(msg)
|
||||||
|
|
||||||
|
print(("\n=== Pull Request #%s ===" % pr_num))
|
||||||
|
print(("PR title\t%s\nCommit title\t%s\nSource\t\t%s\nTarget\t\t%s\nURL\t\t%s" % (
|
||||||
|
pr_title, commit_title, pr_repo_desc, target_ref, url)))
|
||||||
|
continue_maybe("Proceed with merging pull request #%s?" % pr_num)
|
||||||
|
|
||||||
|
merged_refs = [target_ref]
|
||||||
|
|
||||||
|
merge_hash = merge_pr(pr_num, target_ref, commit_title, body, pr_repo_desc)
|
||||||
|
|
||||||
|
pick_prompt = "Would you like to pick %s into another branch?" % merge_hash
|
||||||
|
while input("\n%s (y/n): " % pick_prompt).lower().strip() == "y":
|
||||||
|
merged_refs = merged_refs + [cherry_pick(pr_num, merge_hash, latest_branch)]
|
||||||
|
|
||||||
|
if JIRA_IMPORTED:
|
||||||
|
if JIRA_USERNAME and JIRA_PASSWORD:
|
||||||
|
continue_maybe("Would you like to update an associated JIRA?")
|
||||||
|
jira_comment = "Issue resolved by pull request %s\n[%s/%s]" % (pr_num, GITHUB_BASE, pr_num)
|
||||||
|
resolve_jira_issues(commit_title, merged_refs, jira_comment)
|
||||||
|
else:
|
||||||
|
print("JIRA_USERNAME and JIRA_PASSWORD not set")
|
||||||
|
print("Exiting without trying to close the associated JIRA.")
|
||||||
|
else:
|
||||||
|
print("Could not find jira-python library. Run 'sudo pip install jira' to install.")
|
||||||
|
print("Exiting without trying to close the associated JIRA.")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import doctest
|
||||||
|
(failure_count, test_count) = doctest.testmod()
|
||||||
|
if (failure_count):
|
||||||
|
exit(-1)
|
||||||
|
|
||||||
|
main()
|
178
zookeeper-assembly/pom.xml
Normal file
178
zookeeper-assembly/pom.xml
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<!--
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.apache.zookeeper</groupId>
|
||||||
|
<artifactId>parent</artifactId>
|
||||||
|
<version>3.6.3</version>
|
||||||
|
<relativePath>..</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>zookeeper-assembly</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<name>Apache ZooKeeper - Assembly</name>
|
||||||
|
<description>ZooKeeper Assembly</description>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>full-build</id>
|
||||||
|
<properties>
|
||||||
|
<skip.lib.artifact>false</skip.lib.artifact>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<rw.file.permission>0644</rw.file.permission>
|
||||||
|
<rwx.file.permission>0755</rwx.file.permission>
|
||||||
|
<skip.lib.artifact>true</skip.lib.artifact>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.zookeeper</groupId>
|
||||||
|
<artifactId>zookeeper-docs</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.zookeeper</groupId>
|
||||||
|
<artifactId>zookeeper-jute</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.zookeeper</groupId>
|
||||||
|
<artifactId>zookeeper</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.zookeeper</groupId>
|
||||||
|
<artifactId>zookeeper-client</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.zookeeper</groupId>
|
||||||
|
<artifactId>zookeeper-prometheus-metrics</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.zookeeper</groupId>
|
||||||
|
<artifactId>zookeeper-recipes</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
</dependency>
|
||||||
|
<!-- list here all the jars we want to put in "lib"
|
||||||
|
and are in scope 'provided' -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-cli</groupId>
|
||||||
|
<artifactId>commons-cli</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-server</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-servlet</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-databind</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.googlecode.json-simple</groupId>
|
||||||
|
<artifactId>json-simple</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>jline</groupId>
|
||||||
|
<artifactId>jline</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.dropwizard.metrics</groupId>
|
||||||
|
<artifactId>metrics-core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.xerial.snappy</groupId>
|
||||||
|
<artifactId>snappy-java</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>bin-assembly</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>single</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<descriptors>
|
||||||
|
<descriptor>${project.basedir}/src/main/assembly/bin-package.xml</descriptor>
|
||||||
|
</descriptors>
|
||||||
|
<finalName>apache-zookeeper-${project.version}-bin</finalName>
|
||||||
|
<appendAssemblyId>false</appendAssemblyId>
|
||||||
|
<tarLongFileMode>posix</tarLongFileMode>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>lib-assembly</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>single</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<descriptors>
|
||||||
|
<descriptor>${project.basedir}/src/main/assembly/lib-package.xml</descriptor>
|
||||||
|
</descriptors>
|
||||||
|
<finalName>apache-zookeeper-${project.version}-lib</finalName>
|
||||||
|
<appendAssemblyId>false</appendAssemblyId>
|
||||||
|
<tarLongFileMode>posix</tarLongFileMode>
|
||||||
|
<skipAssembly>${skip.lib.artifact}</skipAssembly>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.github.spotbugs</groupId>
|
||||||
|
<artifactId>spotbugs-maven-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<skip>true</skip>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-deploy-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<!-- this module isn't to be deployed to Maven Central -->
|
||||||
|
<skip>true</skip>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
84
zookeeper-assembly/src/main/assembly/bin-package.xml
Normal file
84
zookeeper-assembly/src/main/assembly/bin-package.xml
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
|
||||||
|
<!--
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
<id>bin-package</id>
|
||||||
|
<formats>
|
||||||
|
<format>tar.gz</format>
|
||||||
|
</formats>
|
||||||
|
<includeBaseDirectory>true</includeBaseDirectory>
|
||||||
|
<componentDescriptors>
|
||||||
|
<componentDescriptor>src/main/assembly/components.xml</componentDescriptor>
|
||||||
|
</componentDescriptors>
|
||||||
|
|
||||||
|
<dependencySets>
|
||||||
|
<dependencySet>
|
||||||
|
<includes>
|
||||||
|
<include>*:*</include>
|
||||||
|
</includes>
|
||||||
|
<excludes>
|
||||||
|
<exclude>org.apache.zookeeper:zookeeper-recipes</exclude>
|
||||||
|
<exclude>org.apache.zookeeper:zookeeper-client</exclude>
|
||||||
|
<exclude>org.apache.zookeeper:zookeeper-docs</exclude>
|
||||||
|
</excludes>
|
||||||
|
<useProjectArtifact>false</useProjectArtifact>
|
||||||
|
<useTransitiveDependencies>true</useTransitiveDependencies>
|
||||||
|
<outputDirectory>lib</outputDirectory>
|
||||||
|
<fileMode>${rw.file.permission}</fileMode>
|
||||||
|
<directoryMode>${rwx.file.permission}</directoryMode>
|
||||||
|
<useStrictFiltering>true</useStrictFiltering>
|
||||||
|
</dependencySet>
|
||||||
|
</dependencySets>
|
||||||
|
|
||||||
|
<fileSets>
|
||||||
|
<fileSet>
|
||||||
|
<!-- ZooKeeper generated documents -->
|
||||||
|
<directory>${project.basedir}/../zookeeper-docs/target/html</directory>
|
||||||
|
<outputDirectory>docs</outputDirectory>
|
||||||
|
<fileMode>${rw.file.permission}</fileMode>
|
||||||
|
<directoryMode>${rwx.file.permission}</directoryMode>
|
||||||
|
</fileSet>
|
||||||
|
<fileSet>
|
||||||
|
<!-- ZooKeeper jute generated api document -->
|
||||||
|
<directory>${project.basedir}/../zookeeper-jute/target/apidocs</directory>
|
||||||
|
<outputDirectory>docs/apidocs/zookeeper-jute</outputDirectory>
|
||||||
|
<fileMode>${rw.file.permission}</fileMode>
|
||||||
|
<directoryMode>${rwx.file.permission}</directoryMode>
|
||||||
|
</fileSet>
|
||||||
|
<fileSet>
|
||||||
|
<!-- ZooKeeper server generated api document -->
|
||||||
|
<directory>${project.basedir}/../zookeeper-server/target/apidocs</directory>
|
||||||
|
<outputDirectory>docs/apidocs/zookeeper-server</outputDirectory>
|
||||||
|
<fileMode>${rw.file.permission}</fileMode>
|
||||||
|
<directoryMode>${rwx.file.permission}</directoryMode>
|
||||||
|
</fileSet>
|
||||||
|
<fileSet>
|
||||||
|
<!-- License files for 3rd party libs -->
|
||||||
|
<directory>${project.basedir}/../zookeeper-server/src/main/resources/lib</directory>
|
||||||
|
<includes>
|
||||||
|
<include>*.txt</include>
|
||||||
|
</includes>
|
||||||
|
<outputDirectory>lib</outputDirectory>
|
||||||
|
<fileMode>${rw.file.permission}</fileMode>
|
||||||
|
</fileSet>
|
||||||
|
</fileSets>
|
||||||
|
|
||||||
|
</assembly>
|
49
zookeeper-assembly/src/main/assembly/components.xml
Normal file
49
zookeeper-assembly/src/main/assembly/components.xml
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
|
||||||
|
<component>
|
||||||
|
<!-- Resources that both bin and source package include -->
|
||||||
|
<fileSets>
|
||||||
|
<fileSet>
|
||||||
|
<directory>${project.basedir}/..</directory>
|
||||||
|
<outputDirectory>.</outputDirectory>
|
||||||
|
<includes>
|
||||||
|
<include>NOTICE.txt</include>
|
||||||
|
<include>LICENSE.txt</include>
|
||||||
|
<include>README.md</include>
|
||||||
|
<include>README_packaging.md</include>
|
||||||
|
</includes>
|
||||||
|
<fileMode>${rw.file.permission}</fileMode>
|
||||||
|
</fileSet>
|
||||||
|
<fileSet>
|
||||||
|
<directory>${project.basedir}/../conf</directory>
|
||||||
|
<outputDirectory>conf</outputDirectory>
|
||||||
|
<fileMode>${rw.file.permission}</fileMode>
|
||||||
|
<directoryMode>${rwx.file.permission}</directoryMode>
|
||||||
|
</fileSet>
|
||||||
|
<fileSet>
|
||||||
|
<directory>${project.basedir}/../bin</directory>
|
||||||
|
<outputDirectory>bin</outputDirectory>
|
||||||
|
<fileMode>${rwx.file.permission}</fileMode>
|
||||||
|
<directoryMode>${rwx.file.permission}</directoryMode>
|
||||||
|
</fileSet>
|
||||||
|
</fileSets>
|
||||||
|
</component>
|
64
zookeeper-assembly/src/main/assembly/lib-package.xml
Normal file
64
zookeeper-assembly/src/main/assembly/lib-package.xml
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
|
||||||
|
<!--
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
<id>lib-package</id>
|
||||||
|
<formats>
|
||||||
|
<format>tar.gz</format>
|
||||||
|
</formats>
|
||||||
|
<includeBaseDirectory>true</includeBaseDirectory>
|
||||||
|
|
||||||
|
<fileSets>
|
||||||
|
<fileSet>
|
||||||
|
<!-- ZooKeeper C client lib and include files -->
|
||||||
|
<directory>${project.basedir}/../zookeeper-client/zookeeper-client-c/target/c</directory>
|
||||||
|
<outputDirectory>usr</outputDirectory>
|
||||||
|
<includes>
|
||||||
|
<include>include/**/*</include>
|
||||||
|
<include>lib/*</include>
|
||||||
|
</includes>
|
||||||
|
<fileMode>${rw.file.permission}</fileMode>
|
||||||
|
<directoryMode>${rwx.file.permission}</directoryMode>
|
||||||
|
</fileSet>
|
||||||
|
<fileSet>
|
||||||
|
<!-- ZooKeeper C client binaries-->
|
||||||
|
<directory>${project.basedir}/../zookeeper-client/zookeeper-client-c/target/c</directory>
|
||||||
|
<outputDirectory>usr</outputDirectory>
|
||||||
|
<includes>
|
||||||
|
<include>bin/*</include>
|
||||||
|
</includes>
|
||||||
|
<fileMode>${rwx.file.permission}</fileMode>
|
||||||
|
<directoryMode>${rwx.file.permission}</directoryMode>
|
||||||
|
</fileSet>
|
||||||
|
<fileSet>
|
||||||
|
<!-- ZooKeeper license -->
|
||||||
|
<directory>${project.basedir}/../zookeeper-client/zookeeper-client-c</directory>
|
||||||
|
<includes>
|
||||||
|
<include>LICENSE</include>
|
||||||
|
</includes>
|
||||||
|
<outputDirectory>/</outputDirectory>
|
||||||
|
<fileMode>${rw.file.permission}</fileMode>
|
||||||
|
<directoryMode>${rwx.file.permission}</directoryMode>
|
||||||
|
</fileSet>
|
||||||
|
|
||||||
|
</fileSets>
|
||||||
|
|
||||||
|
</assembly>
|
58
zookeeper-client/pom.xml
Normal file
58
zookeeper-client/pom.xml
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<!--
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.apache.zookeeper</groupId>
|
||||||
|
<artifactId>parent</artifactId>
|
||||||
|
<version>3.6.3</version>
|
||||||
|
<relativePath>..</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>zookeeper-client</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<name>Apache ZooKeeper - Client</name>
|
||||||
|
<description>ZooKeeper client</description>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>full-build</id>
|
||||||
|
<modules>
|
||||||
|
<module>zookeeper-client-c</module>
|
||||||
|
</modules>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>java-build</id>
|
||||||
|
<modules />
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-deploy-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<!-- this module isn't to be deployed to Maven Central -->
|
||||||
|
<skip>true</skip>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
267
zookeeper-client/zookeeper-client-c/CMakeLists.txt
Normal file
267
zookeeper-client/zookeeper-client-c/CMakeLists.txt
Normal file
@ -0,0 +1,267 @@
|
|||||||
|
# Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
# or more contributor license agreements. See the NOTICE file
|
||||||
|
# distributed with this work for additional information
|
||||||
|
# regarding copyright ownership. The ASF licenses this file
|
||||||
|
# to you under the Apache License, Version 2.0 (the
|
||||||
|
# "License"); you may not use this file except in compliance
|
||||||
|
# with the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
|
project(zookeeper VERSION 3.6.3)
|
||||||
|
set(email user@zookeeper.apache.org)
|
||||||
|
set(description "zookeeper C client")
|
||||||
|
|
||||||
|
# general options
|
||||||
|
if(UNIX)
|
||||||
|
add_compile_options(-Wall -fPIC)
|
||||||
|
elseif(WIN32)
|
||||||
|
add_compile_options(/W3)
|
||||||
|
endif()
|
||||||
|
add_definitions(-DUSE_STATIC_LIB)
|
||||||
|
|
||||||
|
# TODO: Enable /WX and /W4 on Windows. Currently there are ~1000 warnings.
|
||||||
|
# TODO: Add Solaris support.
|
||||||
|
# TODO: Add a shared library option.
|
||||||
|
# TODO: Specify symbols to export.
|
||||||
|
# TODO: Generate doxygen documentation.
|
||||||
|
|
||||||
|
# Sync API option
|
||||||
|
option(WANT_SYNCAPI "Enables Sync API support" ON)
|
||||||
|
if(WANT_SYNCAPI)
|
||||||
|
add_definitions(-DTHREADED)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# CppUnit option
|
||||||
|
if(WIN32 OR APPLE)
|
||||||
|
# The tests do not yet compile on Windows or macOS,
|
||||||
|
# so we set this to off by default.
|
||||||
|
#
|
||||||
|
# Note that CMake does not have expressions except in conditionals,
|
||||||
|
# so we're left with this if/else/endif pattern.
|
||||||
|
set(DEFAULT_WANT_CPPUNIT OFF)
|
||||||
|
else()
|
||||||
|
set(DEFAULT_WANT_CPPUNIT ON)
|
||||||
|
endif()
|
||||||
|
option(WANT_CPPUNIT "Enables CppUnit and tests" ${DEFAULT_WANT_CPPUNIT})
|
||||||
|
|
||||||
|
# SOCK_CLOEXEC
|
||||||
|
option(WANT_SOCK_CLOEXEC "Enables SOCK_CLOEXEC on sockets" OFF)
|
||||||
|
include(CheckSymbolExists)
|
||||||
|
check_symbol_exists(SOCK_CLOEXEC sys/socket.h HAVE_SOCK_CLOEXEC)
|
||||||
|
if(WANT_SOCK_CLOEXEC AND HAVE_SOCK_CLOEXEC)
|
||||||
|
set(SOCK_CLOEXEC_ENABLED 1)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
# The function `to_have(in out)` converts a header name like `arpa/inet.h`
|
||||||
|
# into an Autotools style preprocessor definition `HAVE_ARPA_INET_H`.
|
||||||
|
# This is then set or unset in `configure_file()` step.
|
||||||
|
#
|
||||||
|
# Note that CMake functions do not have return values; instead an "out"
|
||||||
|
# variable must be passed, and explicitly set with parent scope.
|
||||||
|
function(to_have in out)
|
||||||
|
string(TOUPPER ${in} str)
|
||||||
|
string(REGEX REPLACE "/|\\." "_" str ${str})
|
||||||
|
set(${out} "HAVE_${str}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# include file checks
|
||||||
|
foreach(f generated/zookeeper.jute.h generated/zookeeper.jute.c)
|
||||||
|
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${f}")
|
||||||
|
to_have(${f} name)
|
||||||
|
set(${name} 1)
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"jute files are missing!\n"
|
||||||
|
"Please run 'ant compile_jute' while in the ZooKeeper top level directory.")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# header checks
|
||||||
|
include(CheckIncludeFile)
|
||||||
|
set(check_headers
|
||||||
|
arpa/inet.h
|
||||||
|
dlfcn.h
|
||||||
|
fcntl.h
|
||||||
|
inttypes.h
|
||||||
|
memory.h
|
||||||
|
netdb.h
|
||||||
|
netinet/in.h
|
||||||
|
stdint.h
|
||||||
|
stdlib.h
|
||||||
|
string.h
|
||||||
|
strings.h
|
||||||
|
sys/socket.h
|
||||||
|
sys/stat.h
|
||||||
|
sys/time.h
|
||||||
|
sys/types.h
|
||||||
|
unistd.h
|
||||||
|
sys/utsname.h)
|
||||||
|
|
||||||
|
foreach(f ${check_headers})
|
||||||
|
to_have(${f} name)
|
||||||
|
check_include_file(${f} ${name})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# function checks
|
||||||
|
include(CheckFunctionExists)
|
||||||
|
set(check_functions
|
||||||
|
getcwd
|
||||||
|
gethostbyname
|
||||||
|
gethostname
|
||||||
|
getlogin
|
||||||
|
getpwuid_r
|
||||||
|
gettimeofday
|
||||||
|
getuid
|
||||||
|
memmove
|
||||||
|
memset
|
||||||
|
poll
|
||||||
|
socket
|
||||||
|
strchr
|
||||||
|
strdup
|
||||||
|
strerror
|
||||||
|
strtol)
|
||||||
|
|
||||||
|
foreach(fn ${check_functions})
|
||||||
|
to_have(${fn} name)
|
||||||
|
check_function_exists(${fn} ${name})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# library checks
|
||||||
|
set(check_libraries rt m pthread)
|
||||||
|
foreach(lib ${check_libraries})
|
||||||
|
to_have("lib${lib}" name)
|
||||||
|
find_library(${name} ${lib})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# IPv6 check
|
||||||
|
include(CheckStructHasMember)
|
||||||
|
check_struct_has_member("struct sockaddr_in6" sin6_addr "netinet/in.h" ZOO_IPV6_ENABLED)
|
||||||
|
|
||||||
|
# configure
|
||||||
|
configure_file(cmake_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/include/config.h)
|
||||||
|
|
||||||
|
# hashtable library
|
||||||
|
set(hashtable_sources src/hashtable/hashtable_itr.c src/hashtable/hashtable.c)
|
||||||
|
add_library(hashtable STATIC ${hashtable_sources})
|
||||||
|
target_include_directories(hashtable PUBLIC include)
|
||||||
|
target_link_libraries(hashtable PUBLIC $<$<OR:$<PLATFORM_ID:Linux>,$<PLATFORM_ID:FreeBSD>>:m>)
|
||||||
|
|
||||||
|
# zookeeper library
|
||||||
|
set(zookeeper_sources
|
||||||
|
src/zookeeper.c
|
||||||
|
src/recordio.c
|
||||||
|
generated/zookeeper.jute.c
|
||||||
|
src/zk_log.c
|
||||||
|
src/zk_hashtable.c
|
||||||
|
src/addrvec.c)
|
||||||
|
|
||||||
|
if(WANT_SYNCAPI)
|
||||||
|
list(APPEND zookeeper_sources src/mt_adaptor.c)
|
||||||
|
else()
|
||||||
|
list(APPEND zookeeper_sources src/st_adaptor.c)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
list(APPEND zookeeper_sources src/winport.c)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_library(zookeeper STATIC ${zookeeper_sources})
|
||||||
|
target_include_directories(zookeeper PUBLIC include ${CMAKE_CURRENT_BINARY_DIR}/include generated)
|
||||||
|
target_link_libraries(zookeeper PUBLIC
|
||||||
|
hashtable
|
||||||
|
$<$<PLATFORM_ID:Linux>:rt> # clock_gettime
|
||||||
|
$<$<PLATFORM_ID:Windows>:ws2_32>) # Winsock 2.0
|
||||||
|
|
||||||
|
option(WITH_OPENSSL "turn ON/OFF SSL support, or define openssl library location (default: ON)" ON)
|
||||||
|
message("-- using WITH_OPENSSL=${WITH_OPENSSL}")
|
||||||
|
if(NOT WITH_OPENSSL STREQUAL "OFF")
|
||||||
|
if(NOT WITH_OPENSSL STREQUAL "ON")
|
||||||
|
set(OPENSSL_ROOT_DIR,${WITH_OPENSSL})
|
||||||
|
endif()
|
||||||
|
find_package(OpenSSL)
|
||||||
|
if(OPENSSL_FOUND)
|
||||||
|
target_compile_definitions(zookeeper PUBLIC HAVE_OPENSSL_H)
|
||||||
|
target_link_libraries(zookeeper PUBLIC OpenSSL::SSL OpenSSL::Crypto)
|
||||||
|
message("-- OpenSSL libraries found! will build with SSL support.")
|
||||||
|
else()
|
||||||
|
message("-- WARNING: unable to find OpenSSL libraries! will build without SSL support.")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WANT_SYNCAPI AND NOT WIN32)
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
target_link_libraries(zookeeper PUBLIC Threads::Threads)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# cli executable
|
||||||
|
add_executable(cli src/cli.c)
|
||||||
|
target_link_libraries(cli zookeeper)
|
||||||
|
|
||||||
|
# load_gen executable
|
||||||
|
if(WANT_SYNCAPI AND NOT WIN32)
|
||||||
|
add_executable(load_gen src/load_gen.c)
|
||||||
|
target_link_libraries(load_gen zookeeper)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# tests
|
||||||
|
set(test_sources
|
||||||
|
tests/TestDriver.cc
|
||||||
|
tests/LibCMocks.cc
|
||||||
|
tests/LibCSymTable.cc
|
||||||
|
tests/MocksBase.cc
|
||||||
|
tests/ZKMocks.cc
|
||||||
|
tests/Util.cc
|
||||||
|
tests/ThreadingUtil.cc
|
||||||
|
tests/TestZookeeperInit.cc
|
||||||
|
tests/TestZookeeperClose.cc
|
||||||
|
tests/TestReconfig.cc
|
||||||
|
tests/TestReconfigServer.cc
|
||||||
|
tests/TestClientRetry.cc
|
||||||
|
tests/TestOperations.cc
|
||||||
|
tests/TestMulti.cc
|
||||||
|
tests/TestWatchers.cc
|
||||||
|
tests/TestClient.cc
|
||||||
|
tests/ZooKeeperQuorumServer.cc
|
||||||
|
tests/TestReadOnlyClient.cc
|
||||||
|
tests/TestLogClientEnv.cc)
|
||||||
|
|
||||||
|
if(WANT_SYNCAPI)
|
||||||
|
list(APPEND test_sources tests/PthreadMocks.cc)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WANT_CPPUNIT)
|
||||||
|
set (CMAKE_CXX_STANDARD 11)
|
||||||
|
add_executable(zktest ${test_sources})
|
||||||
|
target_include_directories(zktest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
|
target_compile_definitions(zktest
|
||||||
|
PRIVATE -DZKSERVER_CMD="${CMAKE_CURRENT_SOURCE_DIR}/tests/zkServer.sh")
|
||||||
|
# TODO: Use `find_library()` for `cppunit`.
|
||||||
|
target_link_libraries(zktest zookeeper cppunit dl)
|
||||||
|
|
||||||
|
# This reads the link flags from the file `tests/wrappers.opt` into
|
||||||
|
# the variable `symbol_wrappers` for use in `target_link_libraries`.
|
||||||
|
# It is a holdover from the original build system.
|
||||||
|
file(STRINGS tests/wrappers.opt symbol_wrappers)
|
||||||
|
if(WANT_SYNCAPI)
|
||||||
|
file(STRINGS tests/wrappers-mt.opt symbol_wrappers_mt)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_link_libraries(zktest ${symbol_wrappers} ${symbol_wrappers_mt})
|
||||||
|
|
||||||
|
enable_testing()
|
||||||
|
add_test(NAME zktest_runner COMMAND zktest)
|
||||||
|
set_property(TEST zktest_runner PROPERTY ENVIRONMENT
|
||||||
|
"ZKROOT=${CMAKE_CURRENT_SOURCE_DIR}/../.."
|
||||||
|
"CLASSPATH=$CLASSPATH:$CLOVER_HOME/lib/clover*.jar")
|
||||||
|
endif()
|
116
zookeeper-client/zookeeper-client-c/ChangeLog
Normal file
116
zookeeper-client/zookeeper-client-c/ChangeLog
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
Release 2.1.1
|
||||||
|
2008-04-30 Andrew Kornev <akornev@users.sourceforge.net>
|
||||||
|
|
||||||
|
* changed the distributino package name to "c-client-src"
|
||||||
|
|
||||||
|
Release 2.1.0
|
||||||
|
2008-04-30 Andrew Kornev <akornev@users.sourceforge.net>
|
||||||
|
|
||||||
|
* added the client latency diagnostics; the client prints a warning when the
|
||||||
|
reponse latency exceeds 20ms
|
||||||
|
|
||||||
|
* modified logging format to report the znode path for which the zookeeper
|
||||||
|
operation is called
|
||||||
|
|
||||||
|
* fixed a minor bug where error messages were missing for some of the newer
|
||||||
|
zookeeper error codes (ZCLOSING and ZNOTHING).
|
||||||
|
|
||||||
|
* improved logging by adding the XID to the message to make it easy to match
|
||||||
|
requests to responses
|
||||||
|
|
||||||
|
* fixed the bug causing sporadic session termination and timeouts
|
||||||
|
|
||||||
|
* added a new return code to zookeeper_process() -- ZNOTHING --
|
||||||
|
that indicates that the socket has no more data to read
|
||||||
|
|
||||||
|
* more unit tests added
|
||||||
|
|
||||||
|
Release 1.1.3
|
||||||
|
2008-02-07 Andrew Kornev <akornev@users.sourceforge.net>
|
||||||
|
|
||||||
|
* get_xid() is not thread-safe (xid initialization race condition
|
||||||
|
in the multi-threaded mode).
|
||||||
|
|
||||||
|
* the I/O thread doesn’t automatically terminate on AUTH_FAILURE and
|
||||||
|
SESSION_EXPIRED events.
|
||||||
|
|
||||||
|
* all session events should be processed on the completion thread.
|
||||||
|
|
||||||
|
* PING operation doesn’t atomically enqueue the completion and
|
||||||
|
send buffers like other operations do.
|
||||||
|
|
||||||
|
* corrected zookeeper_init() doxygen docs.
|
||||||
|
|
||||||
|
* new unit tests added.
|
||||||
|
|
||||||
|
|
||||||
|
Release 1.1.2
|
||||||
|
2008-01-24 Andrew Kornev <akornev@users.sourceforge.net>
|
||||||
|
|
||||||
|
* fixed a race condition caused by the code in zookeeper_process()
|
||||||
|
and free_completions() setting sc->complete to 1 without proper
|
||||||
|
synchronization;
|
||||||
|
|
||||||
|
* fixed zoo_get() not updating buffer_len value with the actual
|
||||||
|
buffer length on return; added missing enter_critical/leave_critical
|
||||||
|
calls to the async ZK operations.
|
||||||
|
|
||||||
|
* Replaced select() with poll() to fix the problem with the FD_SET
|
||||||
|
macro causing stack corruption for FDs higher than 1024
|
||||||
|
|
||||||
|
* Added zoo_set_log_stream() to the public API. The function allows
|
||||||
|
applications to specify a different log file.
|
||||||
|
|
||||||
|
* Removed unused declarations from zookeeper.h (ACL related)
|
||||||
|
|
||||||
|
* changed zoo_get() signature to take a pointer to buffer length.
|
||||||
|
The function sets the parameter to the actual data length upon return.
|
||||||
|
|
||||||
|
* the watcher callback now takes the zhandle as its first parameter. This
|
||||||
|
is to avoid a race condition in the multi-threaded client when a watcher
|
||||||
|
is called before zookeeper_init() has returned.
|
||||||
|
|
||||||
|
* fixed zookeeper_close() resource leaks and race conditions,
|
||||||
|
fixed the race condition causing xid mismatch.
|
||||||
|
|
||||||
|
* added support for cppunit, added new targets: "check" and "run-check"
|
||||||
|
to build and run unit tests.
|
||||||
|
|
||||||
|
* Changed the signature of zookeeper_init(): it now takes a context pointer
|
||||||
|
as a parameter. This is to avoid a race condition in the multi-threaded client.
|
||||||
|
|
||||||
|
* Using a self-pipe rather than SIGUSR1 to wake up select() in the I/O thread
|
||||||
|
|
||||||
|
* Added the doxygen target to the autoconf scripts
|
||||||
|
|
||||||
|
* Pulled out the logging functionality from zookeeper.c to zk_log.c/.h.
|
||||||
|
Fixed a minor issue with PING responses being unnecessarily put on
|
||||||
|
the completion queue rather than simply dropped. Make use of DLL_EXPORT
|
||||||
|
symbol for building shared lib on cygwin.
|
||||||
|
|
||||||
|
* Implemented new Zookeeper operation sync() to flush the leader channel
|
||||||
|
to ensure that all updates have reached the followers.
|
||||||
|
|
||||||
|
* Synchronous methods not being handled properly on disconnect
|
||||||
|
|
||||||
|
* breed: fixed an incorrect parameter passed to zookeeper API by
|
||||||
|
the Sync API wrapper functions
|
||||||
|
|
||||||
|
* breed: the set and delete commands now support both Sync and Async API.
|
||||||
|
Prefix the command name with an 'a' to call the Async API: aset, adelete
|
||||||
|
|
||||||
|
* Make sure mutexes and condition variables are properly initialized
|
||||||
|
and destroyed
|
||||||
|
|
||||||
|
* Fixed zookeeper_close() causing core dumps with mt_adaptor
|
||||||
|
|
||||||
|
|
||||||
|
Release 1.0.0
|
||||||
|
2007-11-27 Andrew Kornev <akornev@users.sourceforge.net>
|
||||||
|
|
||||||
|
* configure.ac and Makefile.am added support for GNU autotools
|
||||||
|
|
||||||
|
* recordio.c/.h updated jute IO routines to use bit-explicit integer types
|
||||||
|
(int32_t vs. int, and int64_t vs. long long)
|
||||||
|
|
||||||
|
* README rough draft
|
234
zookeeper-client/zookeeper-client-c/INSTALL
Normal file
234
zookeeper-client/zookeeper-client-c/INSTALL
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
Installation Instructions
|
||||||
|
*************************
|
||||||
|
|
||||||
|
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
|
||||||
|
2006 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is free documentation; the Free Software Foundation gives
|
||||||
|
unlimited permission to copy, distribute and modify it.
|
||||||
|
|
||||||
|
Basic Installation
|
||||||
|
==================
|
||||||
|
|
||||||
|
Briefly, the shell commands `./configure; make; make install' should
|
||||||
|
configure, build, and install this package. The following
|
||||||
|
more-detailed instructions are generic; see the `README' file for
|
||||||
|
instructions specific to this package.
|
||||||
|
|
||||||
|
The `configure' shell script attempts to guess correct values for
|
||||||
|
various system-dependent variables used during compilation. It uses
|
||||||
|
those values to create a `Makefile' in each directory of the package.
|
||||||
|
It may also create one or more `.h' files containing system-dependent
|
||||||
|
definitions. Finally, it creates a shell script `config.status' that
|
||||||
|
you can run in the future to recreate the current configuration, and a
|
||||||
|
file `config.log' containing compiler output (useful mainly for
|
||||||
|
debugging `configure').
|
||||||
|
|
||||||
|
It can also use an optional file (typically called `config.cache'
|
||||||
|
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||||
|
the results of its tests to speed up reconfiguring. Caching is
|
||||||
|
disabled by default to prevent problems with accidental use of stale
|
||||||
|
cache files.
|
||||||
|
|
||||||
|
If you need to do unusual things to compile the package, please try
|
||||||
|
to figure out how `configure' could check whether to do them, and mail
|
||||||
|
diffs or instructions to the address given in the `README' so they can
|
||||||
|
be considered for the next release. If you are using the cache, and at
|
||||||
|
some point `config.cache' contains results you don't want to keep, you
|
||||||
|
may remove or edit it.
|
||||||
|
|
||||||
|
The file `configure.ac' (or `configure.in') is used to create
|
||||||
|
`configure' by a program called `autoconf'. You need `configure.ac' if
|
||||||
|
you want to change it or regenerate `configure' using a newer version
|
||||||
|
of `autoconf'.
|
||||||
|
|
||||||
|
The simplest way to compile this package is:
|
||||||
|
|
||||||
|
1. `cd' to the directory containing the package's source code and type
|
||||||
|
`./configure' to configure the package for your system.
|
||||||
|
|
||||||
|
Running `configure' might take a while. While running, it prints
|
||||||
|
some messages telling which features it is checking for.
|
||||||
|
|
||||||
|
2. Type `make' to compile the package.
|
||||||
|
|
||||||
|
3. Optionally, type `make check' to run any self-tests that come with
|
||||||
|
the package.
|
||||||
|
|
||||||
|
4. Type `make install' to install the programs and any data files and
|
||||||
|
documentation.
|
||||||
|
|
||||||
|
5. You can remove the program binaries and object files from the
|
||||||
|
source code directory by typing `make clean'. To also remove the
|
||||||
|
files that `configure' created (so you can compile the package for
|
||||||
|
a different kind of computer), type `make distclean'. There is
|
||||||
|
also a `make maintainer-clean' target, but that is intended mainly
|
||||||
|
for the package's developers. If you use it, you may have to get
|
||||||
|
all sorts of other programs in order to regenerate files that came
|
||||||
|
with the distribution.
|
||||||
|
|
||||||
|
Compilers and Options
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Some systems require unusual options for compilation or linking that the
|
||||||
|
`configure' script does not know about. Run `./configure --help' for
|
||||||
|
details on some of the pertinent environment variables.
|
||||||
|
|
||||||
|
You can give `configure' initial values for configuration parameters
|
||||||
|
by setting variables in the command line or in the environment. Here
|
||||||
|
is an example:
|
||||||
|
|
||||||
|
./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
||||||
|
|
||||||
|
*Note Defining Variables::, for more details.
|
||||||
|
|
||||||
|
Compiling For Multiple Architectures
|
||||||
|
====================================
|
||||||
|
|
||||||
|
You can compile the package for more than one kind of computer at the
|
||||||
|
same time, by placing the object files for each architecture in their
|
||||||
|
own directory. To do this, you can use GNU `make'. `cd' to the
|
||||||
|
directory where you want the object files and executables to go and run
|
||||||
|
the `configure' script. `configure' automatically checks for the
|
||||||
|
source code in the directory that `configure' is in and in `..'.
|
||||||
|
|
||||||
|
With a non-GNU `make', it is safer to compile the package for one
|
||||||
|
architecture at a time in the source code directory. After you have
|
||||||
|
installed the package for one architecture, use `make distclean' before
|
||||||
|
reconfiguring for another architecture.
|
||||||
|
|
||||||
|
Installation Names
|
||||||
|
==================
|
||||||
|
|
||||||
|
By default, `make install' installs the package's commands under
|
||||||
|
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||||
|
can specify an installation prefix other than `/usr/local' by giving
|
||||||
|
`configure' the option `--prefix=PREFIX'.
|
||||||
|
|
||||||
|
You can specify separate installation prefixes for
|
||||||
|
architecture-specific files and architecture-independent files. If you
|
||||||
|
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
||||||
|
PREFIX as the prefix for installing programs and libraries.
|
||||||
|
Documentation and other data files still use the regular prefix.
|
||||||
|
|
||||||
|
In addition, if you use an unusual directory layout you can give
|
||||||
|
options like `--bindir=DIR' to specify different values for particular
|
||||||
|
kinds of files. Run `configure --help' for a list of the directories
|
||||||
|
you can set and what kinds of files go in them.
|
||||||
|
|
||||||
|
If the package supports it, you can cause programs to be installed
|
||||||
|
with an extra prefix or suffix on their names by giving `configure' the
|
||||||
|
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||||
|
|
||||||
|
Optional Features
|
||||||
|
=================
|
||||||
|
|
||||||
|
Some packages pay attention to `--enable-FEATURE' options to
|
||||||
|
`configure', where FEATURE indicates an optional part of the package.
|
||||||
|
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||||
|
is something like `gnu-as' or `x' (for the X Window System). The
|
||||||
|
`README' should mention any `--enable-' and `--with-' options that the
|
||||||
|
package recognizes.
|
||||||
|
|
||||||
|
For packages that use the X Window System, `configure' can usually
|
||||||
|
find the X include and library files automatically, but if it doesn't,
|
||||||
|
you can use the `configure' options `--x-includes=DIR' and
|
||||||
|
`--x-libraries=DIR' to specify their locations.
|
||||||
|
|
||||||
|
Specifying the System Type
|
||||||
|
==========================
|
||||||
|
|
||||||
|
There may be some features `configure' cannot figure out automatically,
|
||||||
|
but needs to determine by the type of machine the package will run on.
|
||||||
|
Usually, assuming the package is built to be run on the _same_
|
||||||
|
architectures, `configure' can figure that out, but if it prints a
|
||||||
|
message saying it cannot guess the machine type, give it the
|
||||||
|
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||||
|
type, such as `sun4', or a canonical name which has the form:
|
||||||
|
|
||||||
|
CPU-COMPANY-SYSTEM
|
||||||
|
|
||||||
|
where SYSTEM can have one of these forms:
|
||||||
|
|
||||||
|
OS KERNEL-OS
|
||||||
|
|
||||||
|
See the file `config.sub' for the possible values of each field. If
|
||||||
|
`config.sub' isn't included in this package, then this package doesn't
|
||||||
|
need to know the machine type.
|
||||||
|
|
||||||
|
If you are _building_ compiler tools for cross-compiling, you should
|
||||||
|
use the option `--target=TYPE' to select the type of system they will
|
||||||
|
produce code for.
|
||||||
|
|
||||||
|
If you want to _use_ a cross compiler, that generates code for a
|
||||||
|
platform different from the build platform, you should specify the
|
||||||
|
"host" platform (i.e., that on which the generated programs will
|
||||||
|
eventually be run) with `--host=TYPE'.
|
||||||
|
|
||||||
|
Sharing Defaults
|
||||||
|
================
|
||||||
|
|
||||||
|
If you want to set default values for `configure' scripts to share, you
|
||||||
|
can create a site shell script called `config.site' that gives default
|
||||||
|
values for variables like `CC', `cache_file', and `prefix'.
|
||||||
|
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||||
|
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||||
|
`CONFIG_SITE' environment variable to the location of the site script.
|
||||||
|
A warning: not all `configure' scripts look for a site script.
|
||||||
|
|
||||||
|
Defining Variables
|
||||||
|
==================
|
||||||
|
|
||||||
|
Variables not defined in a site shell script can be set in the
|
||||||
|
environment passed to `configure'. However, some packages may run
|
||||||
|
configure again during the build, and the customized values of these
|
||||||
|
variables may be lost. In order to avoid this problem, you should set
|
||||||
|
them in the `configure' command line, using `VAR=value'. For example:
|
||||||
|
|
||||||
|
./configure CC=/usr/local2/bin/gcc
|
||||||
|
|
||||||
|
causes the specified `gcc' to be used as the C compiler (unless it is
|
||||||
|
overridden in the site shell script).
|
||||||
|
|
||||||
|
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
|
||||||
|
an Autoconf bug. Until the bug is fixed you can use this workaround:
|
||||||
|
|
||||||
|
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||||
|
|
||||||
|
`configure' Invocation
|
||||||
|
======================
|
||||||
|
|
||||||
|
`configure' recognizes the following options to control how it operates.
|
||||||
|
|
||||||
|
`--help'
|
||||||
|
`-h'
|
||||||
|
Print a summary of the options to `configure', and exit.
|
||||||
|
|
||||||
|
`--version'
|
||||||
|
`-V'
|
||||||
|
Print the version of Autoconf used to generate the `configure'
|
||||||
|
script, and exit.
|
||||||
|
|
||||||
|
`--cache-file=FILE'
|
||||||
|
Enable the cache: use and save the results of the tests in FILE,
|
||||||
|
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||||
|
disable caching.
|
||||||
|
|
||||||
|
`--config-cache'
|
||||||
|
`-C'
|
||||||
|
Alias for `--cache-file=config.cache'.
|
||||||
|
|
||||||
|
`--quiet'
|
||||||
|
`--silent'
|
||||||
|
`-q'
|
||||||
|
Do not print messages saying which checks are being made. To
|
||||||
|
suppress all normal output, redirect it to `/dev/null' (any error
|
||||||
|
messages will still be shown).
|
||||||
|
|
||||||
|
`--srcdir=DIR'
|
||||||
|
Look for the package's source code in directory DIR. Usually
|
||||||
|
`configure' can determine that directory automatically.
|
||||||
|
|
||||||
|
`configure' also accepts some other, not widely useful, options. Run
|
||||||
|
`configure --help' for more details.
|
||||||
|
|
335
zookeeper-client/zookeeper-client-c/LICENSE
Normal file
335
zookeeper-client/zookeeper-client-c/LICENSE
Normal file
@ -0,0 +1,335 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
===========================================================================================
|
||||||
|
=== The following part contains the dual OpenSSL and SSLeay license ===
|
||||||
|
=== for OpenSSL versions 1.1.1, 1.1.0, 1.0.2 and all prior releases ===
|
||||||
|
=== (see https://www.openssl.org/source/license.html) ===
|
||||||
|
===========================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
LICENSE ISSUES
|
||||||
|
==============
|
||||||
|
|
||||||
|
The OpenSSL toolkit stays under a double license, i.e. both the conditions of
|
||||||
|
the OpenSSL License and the original SSLeay license apply to the toolkit.
|
||||||
|
See below for the actual license texts.
|
||||||
|
|
||||||
|
OpenSSL License
|
||||||
|
---------------
|
||||||
|
|
||||||
|
/* ====================================================================
|
||||||
|
* Copyright (c) 1998-2019 The OpenSSL Project. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
* 3. All advertising materials mentioning features or use of this
|
||||||
|
* software must display the following acknowledgment:
|
||||||
|
* "This product includes software developed by the OpenSSL Project
|
||||||
|
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||||
|
*
|
||||||
|
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||||
|
* endorse or promote products derived from this software without
|
||||||
|
* prior written permission. For written permission, please contact
|
||||||
|
* openssl-core@openssl.org.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called "OpenSSL"
|
||||||
|
* nor may "OpenSSL" appear in their names without prior written
|
||||||
|
* permission of the OpenSSL Project.
|
||||||
|
*
|
||||||
|
* 6. Redistributions of any form whatsoever must retain the following
|
||||||
|
* acknowledgment:
|
||||||
|
* "This product includes software developed by the OpenSSL Project
|
||||||
|
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||||
|
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||||
|
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
* ====================================================================
|
||||||
|
*
|
||||||
|
* This product includes cryptographic software written by Eric Young
|
||||||
|
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||||
|
* Hudson (tjh@cryptsoft.com).
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
Original SSLeay License
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This package is an SSL implementation written
|
||||||
|
* by Eric Young (eay@cryptsoft.com).
|
||||||
|
* The implementation was written so as to conform with Netscapes SSL.
|
||||||
|
*
|
||||||
|
* This library is free for commercial and non-commercial use as long as
|
||||||
|
* the following conditions are aheared to. The following conditions
|
||||||
|
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||||
|
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||||
|
* included with this distribution is covered by the same copyright terms
|
||||||
|
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||||
|
*
|
||||||
|
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||||
|
* the code are not to be removed.
|
||||||
|
* If this package is used in a product, Eric Young should be given attribution
|
||||||
|
* as the author of the parts of the library used.
|
||||||
|
* This can be in the form of a textual message at program startup or
|
||||||
|
* in documentation (online or textual) provided with the package.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* "This product includes cryptographic software written by
|
||||||
|
* Eric Young (eay@cryptsoft.com)"
|
||||||
|
* The word 'cryptographic' can be left out if the rouines from the library
|
||||||
|
* being used are not cryptographic related :-).
|
||||||
|
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||||
|
* the apps directory (application code) you must include an acknowledgement:
|
||||||
|
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The licence and distribution terms for any publically available version or
|
||||||
|
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||||
|
* copied and put under another distribution licence
|
||||||
|
* [including the GNU Public Licence.]
|
||||||
|
*/
|
154
zookeeper-client/zookeeper-client-c/Makefile.am
Normal file
154
zookeeper-client/zookeeper-client-c/Makefile.am
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
# need this for Doxygen integration
|
||||||
|
include $(top_srcdir)/aminclude.am
|
||||||
|
|
||||||
|
AUTOMAKE_OPTIONS = serial-tests
|
||||||
|
|
||||||
|
if SOLARIS
|
||||||
|
SOLARIS_CPPFLAGS = -D_POSIX_PTHREAD_SEMANTICS
|
||||||
|
SOLARIS_LIB_LDFLAGS = -lnsl -lsocket
|
||||||
|
endif
|
||||||
|
|
||||||
|
if WANT_OPENSSL
|
||||||
|
OPENSSL_CPPFLAGS = -DHAVE_OPENSSL_H
|
||||||
|
OPENSSL_LIB_LDFLAGS = -lssl -lcrypto
|
||||||
|
endif
|
||||||
|
|
||||||
|
AM_CPPFLAGS = -I${srcdir}/include -I${srcdir}/tests -I${srcdir}/generated $(SOLARIS_CPPFLAGS) $(OPENSSL_CPPFLAGS)
|
||||||
|
AM_CFLAGS = -Wall -Werror -Wdeclaration-after-statement
|
||||||
|
AM_CXXFLAGS = -Wall $(USEIPV6)
|
||||||
|
LIB_LDFLAGS = -no-undefined -version-info 2 $(SOLARIS_LIB_LDFLAGS) $(OPENSSL_LIB_LDFLAGS)
|
||||||
|
|
||||||
|
# Additional flags for coverage testing (if enabled)
|
||||||
|
if ENABLEGCOV
|
||||||
|
AM_CFLAGS += -fprofile-arcs -ftest-coverage
|
||||||
|
AM_LDFLAGS = -lgcov
|
||||||
|
endif
|
||||||
|
|
||||||
|
pkginclude_HEADERS = include/zookeeper.h include/zookeeper_version.h include/zookeeper_log.h include/proto.h include/recordio.h generated/zookeeper.jute.h
|
||||||
|
EXTRA_DIST=LICENSE
|
||||||
|
|
||||||
|
HASHTABLE_SRC = src/hashtable/hashtable_itr.h src/hashtable/hashtable_itr.c \
|
||||||
|
src/hashtable/hashtable_private.h src/hashtable/hashtable.h src/hashtable/hashtable.c
|
||||||
|
|
||||||
|
noinst_LTLIBRARIES = libhashtable.la
|
||||||
|
libhashtable_la_SOURCES = $(HASHTABLE_SRC)
|
||||||
|
|
||||||
|
COMMON_SRC = src/zookeeper.c include/zookeeper.h include/zookeeper_version.h include/zookeeper_log.h\
|
||||||
|
src/recordio.c include/recordio.h include/proto.h \
|
||||||
|
src/zk_adaptor.h generated/zookeeper.jute.c \
|
||||||
|
src/zk_log.c src/zk_hashtable.h src/zk_hashtable.c \
|
||||||
|
src/addrvec.h src/addrvec.c
|
||||||
|
|
||||||
|
# These are the symbols (classes, mostly) we want to export from our library.
|
||||||
|
EXPORT_SYMBOLS = '(zoo_|zookeeper_|zhandle|Z|format_log_message|log_message|logLevel|deallocate_|allocate_|zerror|is_unrecoverable)'
|
||||||
|
noinst_LTLIBRARIES += libzkst.la
|
||||||
|
libzkst_la_SOURCES =$(COMMON_SRC) src/st_adaptor.c
|
||||||
|
libzkst_la_LIBADD = -lm $(CLOCK_GETTIME_LIBS)
|
||||||
|
|
||||||
|
lib_LTLIBRARIES = libzookeeper_st.la
|
||||||
|
libzookeeper_st_la_SOURCES =
|
||||||
|
libzookeeper_st_la_LIBADD=libzkst.la libhashtable.la
|
||||||
|
libzookeeper_st_la_DEPENDENCIES=libzkst.la libhashtable.la
|
||||||
|
libzookeeper_st_la_LDFLAGS = $(LIB_LDFLAGS) -export-symbols-regex $(EXPORT_SYMBOLS)
|
||||||
|
|
||||||
|
if WANT_SYNCAPI
|
||||||
|
noinst_LTLIBRARIES += libzkmt.la
|
||||||
|
libzkmt_la_SOURCES =$(COMMON_SRC) src/mt_adaptor.c
|
||||||
|
libzkmt_la_CFLAGS = -DTHREADED
|
||||||
|
libzkmt_la_LIBADD = -lm $(CLOCK_GETTIME_LIBS)
|
||||||
|
|
||||||
|
lib_LTLIBRARIES += libzookeeper_mt.la
|
||||||
|
libzookeeper_mt_la_SOURCES =
|
||||||
|
libzookeeper_mt_la_LIBADD=libzkmt.la libhashtable.la -lpthread
|
||||||
|
libzookeeper_mt_la_DEPENDENCIES=libzkmt.la libhashtable.la
|
||||||
|
libzookeeper_mt_la_LDFLAGS = $(LIB_LDFLAGS) -export-symbols-regex $(EXPORT_SYMBOLS)
|
||||||
|
endif
|
||||||
|
|
||||||
|
bin_PROGRAMS = cli_st
|
||||||
|
|
||||||
|
cli_st_SOURCES = src/cli.c
|
||||||
|
cli_st_LDADD = libzookeeper_st.la
|
||||||
|
|
||||||
|
if WANT_SYNCAPI
|
||||||
|
bin_PROGRAMS += cli_mt load_gen
|
||||||
|
|
||||||
|
cli_mt_SOURCES = src/cli.c
|
||||||
|
cli_mt_LDADD = libzookeeper_mt.la
|
||||||
|
cli_mt_CFLAGS = -DTHREADED
|
||||||
|
|
||||||
|
load_gen_SOURCES = src/load_gen.c
|
||||||
|
load_gen_LDADD = libzookeeper_mt.la
|
||||||
|
load_gen_CFLAGS = -DTHREADED
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
#########################################################################
|
||||||
|
# build and run unit tests
|
||||||
|
|
||||||
|
EXTRA_DIST+=$(wildcard ${srcdir}/tests/*.cc) $(wildcard ${srcdir}/tests/*.h) \
|
||||||
|
${srcdir}/tests/wrappers.opt ${srcdir}/tests/wrappers-mt.opt
|
||||||
|
|
||||||
|
# These tests are ordered in a logical manner such that each builds upon basic
|
||||||
|
# functionality tested in prior tests. e.g. the most basic functionality is
|
||||||
|
# tested in TestZookeeperInit and TestZookeeperClose and as such should be tested
|
||||||
|
# first as a foundation with more complex test suites to follow.
|
||||||
|
TEST_SOURCES = \
|
||||||
|
tests/TestDriver.cc \
|
||||||
|
tests/LibCMocks.cc \
|
||||||
|
tests/LibCSymTable.cc \
|
||||||
|
tests/MocksBase.cc \
|
||||||
|
tests/ZKMocks.cc \
|
||||||
|
tests/Util.cc \
|
||||||
|
tests/ThreadingUtil.cc \
|
||||||
|
tests/TestZookeeperInit.cc \
|
||||||
|
tests/TestZookeeperClose.cc \
|
||||||
|
tests/TestReconfig.cc \
|
||||||
|
tests/TestReconfigServer.cc \
|
||||||
|
tests/TestClientRetry.cc \
|
||||||
|
tests/TestOperations.cc \
|
||||||
|
tests/TestMulti.cc \
|
||||||
|
tests/TestWatchers.cc \
|
||||||
|
tests/TestClient.cc \
|
||||||
|
tests/ZooKeeperQuorumServer.cc \
|
||||||
|
tests/ZooKeeperQuorumServer.h \
|
||||||
|
tests/TestReadOnlyClient.cc \
|
||||||
|
tests/TestLogClientEnv.cc \
|
||||||
|
tests/TestServerRequireClientSASLAuth.cc \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
if SOLARIS
|
||||||
|
SHELL_SYMBOL_WRAPPERS = cat ${srcdir}/tests/wrappers.opt
|
||||||
|
SYMBOL_WRAPPERS=$(SHELL_SYMBOL_WRAPPERS:sh)
|
||||||
|
else
|
||||||
|
SYMBOL_WRAPPERS=$(shell cat ${srcdir}/tests/wrappers.opt)
|
||||||
|
endif
|
||||||
|
|
||||||
|
check_PROGRAMS = zktest-st
|
||||||
|
TESTS_ENVIRONMENT = ZKROOT=${srcdir}/../.. \
|
||||||
|
CLASSPATH=$$CLASSPATH:$$CLOVER_HOME/lib/clover*.jar
|
||||||
|
nodist_zktest_st_SOURCES = $(TEST_SOURCES)
|
||||||
|
zktest_st_LDADD = libzkst.la libhashtable.la $(CPPUNIT_LIBS) $(OPENSSL_LIB_LDFLAGS) -ldl
|
||||||
|
zktest_st_CXXFLAGS = -DUSE_STATIC_LIB $(CPPUNIT_CFLAGS) $(USEIPV6) $(SOLARIS_CPPFLAGS)
|
||||||
|
zktest_st_LDFLAGS = -shared $(SYMBOL_WRAPPERS) $(SOLARIS_LIB_LDFLAGS)
|
||||||
|
|
||||||
|
if WANT_SYNCAPI
|
||||||
|
check_PROGRAMS += zktest-mt
|
||||||
|
nodist_zktest_mt_SOURCES = $(TEST_SOURCES) tests/PthreadMocks.cc
|
||||||
|
zktest_mt_LDADD = libzkmt.la libhashtable.la -lpthread $(CPPUNIT_LIBS) $(OPENSSL_LIB_LDFLAGS) -ldl
|
||||||
|
zktest_mt_CXXFLAGS = -DUSE_STATIC_LIB -DTHREADED $(CPPUNIT_CFLAGS) $(USEIPV6)
|
||||||
|
if SOLARIS
|
||||||
|
SHELL_SYMBOL_WRAPPERS_MT = cat ${srcdir}/tests/wrappers-mt.opt
|
||||||
|
SYMBOL_WRAPPERS_MT=$(SYMBOL_WRAPPERS) $(SHELL_SYMBOL_WRAPPERS_MT:sh)
|
||||||
|
else
|
||||||
|
SYMBOL_WRAPPERS_MT=$(SYMBOL_WRAPPERS) $(shell cat ${srcdir}/tests/wrappers-mt.opt)
|
||||||
|
endif
|
||||||
|
zktest_mt_LDFLAGS = -shared $(SYMBOL_WRAPPERS_MT) $(SOLARIS_LIB_LDFLAGS)
|
||||||
|
endif
|
||||||
|
|
||||||
|
TESTS = $(check_PROGRAMS)
|
||||||
|
|
||||||
|
clean-local: clean-check
|
||||||
|
$(RM) $(DX_CLEANFILES)
|
||||||
|
|
||||||
|
clean-check:
|
||||||
|
$(RM) $(nodist_zktest_st_OBJECTS) $(nodist_zktest_mt_OBJECTS)
|
41
zookeeper-client/zookeeper-client-c/NOTICE.txt
Normal file
41
zookeeper-client/zookeeper-client-c/NOTICE.txt
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
Apache ZooKeeper
|
||||||
|
Copyright 2009-2011 The Apache Software Foundation
|
||||||
|
|
||||||
|
This product includes software developed at
|
||||||
|
The Apache Software Foundation (http://www.apache.org/).
|
||||||
|
|
||||||
|
----------
|
||||||
|
include/winstdint.h is included only for Windows Client support, as follows:
|
||||||
|
|
||||||
|
// ISO C9x compliant stdint.h for Microsoft Visual Studio
|
||||||
|
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
|
||||||
|
//
|
||||||
|
// Copyright (c) 2006-2008 Alexander Chemeris
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. The name of the author may be used to endorse or promote products
|
||||||
|
// derived from this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||||
|
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||||
|
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||||
|
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
----------
|
163
zookeeper-client/zookeeper-client-c/README
Normal file
163
zookeeper-client/zookeeper-client-c/README
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
Zookeeper C client library
|
||||||
|
|
||||||
|
|
||||||
|
This package provides a C client interface to Zookeeper server.
|
||||||
|
|
||||||
|
For the latest information about ZooKeeper, please visit our website at:
|
||||||
|
http://zookeeper.apache.org/
|
||||||
|
and our wiki, at:
|
||||||
|
https://cwiki.apache.org/confluence/display/ZOOKEEPER
|
||||||
|
|
||||||
|
Full documentation for this release can also be found in ../../docs/index.html
|
||||||
|
|
||||||
|
|
||||||
|
OVERVIEW
|
||||||
|
|
||||||
|
The client supports two types of APIs -- synchronous and asynchronous.
|
||||||
|
|
||||||
|
Asynchronous API provides non-blocking operations with completion callbacks and
|
||||||
|
relies on the application to implement event multiplexing on its behalf.
|
||||||
|
|
||||||
|
On the other hand, Synchronous API provides a blocking flavor of
|
||||||
|
zookeeper operations and runs its own event loop in a separate thread.
|
||||||
|
|
||||||
|
Sync and Async APIs can be mixed and matched within the same application.
|
||||||
|
|
||||||
|
The package includes two shared libraries: zookeeper_st and
|
||||||
|
zookeeper_mt. The former only provides the Async API and is not
|
||||||
|
thread-safe. The only reason this library exists is to support the
|
||||||
|
platforms were pthread library is not available or unstable
|
||||||
|
(i.e. FreeBSD 4.x). In all other cases the application developers are
|
||||||
|
advised to link against zookeeper_mt as it includes support for both
|
||||||
|
Sync and Async API.
|
||||||
|
|
||||||
|
|
||||||
|
INSTALLATION
|
||||||
|
|
||||||
|
If you're building the client from a source checkout you need to
|
||||||
|
follow the steps outlined below. If you're building from a release
|
||||||
|
tar downloaded from Apache please skip to step 2.
|
||||||
|
|
||||||
|
1) do a "ant compile_jute" from the zookeeper top level directory (.../trunk).
|
||||||
|
This will create a directory named "generated" under zookeeper-client/zookeeper-client-c.
|
||||||
|
Skip to step 3.
|
||||||
|
2) unzip/untar the source tarball and cd to the zookeeper-x.x.x/zookeeper-client/zookeeper-client-c directory
|
||||||
|
3) change directory to zookeeper-client/zookeeper-client-c and do a "autoreconf -if" to bootstrap
|
||||||
|
autoconf, automake and libtool. Please make sure you have autoconf
|
||||||
|
version 2.59 or greater installed. If cppunit is installed in a non-standard
|
||||||
|
directory, you need to specify where to find cppunit.m4. For example, if
|
||||||
|
cppunit is installed under /usr/local, run:
|
||||||
|
|
||||||
|
ACLOCAL="aclocal -I /usr/local/share/aclocal" autoreconf -if
|
||||||
|
|
||||||
|
4) do a "./configure [OPTIONS]" to generate the makefile. See INSTALL
|
||||||
|
for general information about running configure. Additionally, the
|
||||||
|
configure supports the following options:
|
||||||
|
--enable-debug enables optimization and enables debug info compiler
|
||||||
|
options, disabled by default
|
||||||
|
--without-syncapi disables Sync API support; zookeeper_mt library won't
|
||||||
|
be built, enabled by default
|
||||||
|
--disable-static do not build static libraries, enabled by default
|
||||||
|
--disable-shared do not build shared libraries, enabled by default
|
||||||
|
--without-cppunit do not build the test library, enabled by default.
|
||||||
|
|
||||||
|
5) do a "make" or "make install" to build the libraries and install them.
|
||||||
|
Alternatively, you can also build and run a unit test suite (and
|
||||||
|
you probably should). Please make sure you have cppunit-1.10.x or
|
||||||
|
higher installed before you execute step 4. Once ./configure has
|
||||||
|
finished, do a "make check". It will build the libraries, build
|
||||||
|
the tests and run them.
|
||||||
|
6) to generate doxygen documentation do a "make doxygen-doc". All
|
||||||
|
documentations will be placed to a new subfolder named docs. By
|
||||||
|
default only HTML documentation is generated. For information on
|
||||||
|
other document formats please use "./configure --help"
|
||||||
|
|
||||||
|
Alternatively you can use the CMake build system. On Windows, this is required.
|
||||||
|
Follow steps 1 and 2 above, and then continue here.
|
||||||
|
|
||||||
|
1) do a "cmake [OPTIONS]" to generate the makefile or msbuild files (the correct
|
||||||
|
build system will be generated based on your platform). Some options from above
|
||||||
|
are supported:
|
||||||
|
-DCMAKE_BUILD_TYPE Debug by default, Release enables optimzation etc.
|
||||||
|
-DWANT_SYNCAPI ON by default, OFF disables the Sync API support
|
||||||
|
-DWANT_CPPUNIT ON except on Windows, OFF disables the tests
|
||||||
|
-DWITH_OPENSSL ON by default, OFF disables the SSL support. You can also
|
||||||
|
specify a custom path by -DWITH_OPENSSL=/path/to/openssl/
|
||||||
|
-DBUILD_SHARED_LIBS not yet supported, only static libraries are built
|
||||||
|
other CMake options see "cmake --help" for generic options, such as generator
|
||||||
|
|
||||||
|
2) do a "cmake --build ." to build the default targets. Alternatively you can
|
||||||
|
invoke "make" or "msbuild" manually. If the tests were enabled, use "ctest -V"
|
||||||
|
to run them.
|
||||||
|
|
||||||
|
Current limitations of the CMake build system include lack of Solaris support,
|
||||||
|
no shared library option, no explicitly exported symbols (all are exported by
|
||||||
|
default), no versions on the libraries, and no documentation generation.
|
||||||
|
Features of CMake include a single, easily consumed cross-platform build system
|
||||||
|
to generate the ZooKeeper C Client libraries for any project, with little to no
|
||||||
|
configuration.
|
||||||
|
|
||||||
|
EXAMPLE/SAMPLE C CLIENT SHELL
|
||||||
|
|
||||||
|
NOTE: the ZooKeeper C client shell (cli_st and cli_mt) is meant as a
|
||||||
|
example/sample of ZooKeeper C client API usage. It is not a full
|
||||||
|
fledged client and not meant for production usage - see the Java
|
||||||
|
client shell for a fully featured shell.
|
||||||
|
|
||||||
|
You can test your client by running a zookeeper server (see
|
||||||
|
instructions on the project wiki page on how to run it) and connecting
|
||||||
|
to it using the zookeeper shell application cli that is built as part
|
||||||
|
of the installation procedure.
|
||||||
|
|
||||||
|
cli_mt (multithreaded, built against zookeeper_mt library) is shown in
|
||||||
|
this example, but you could also use cli_st (singlethreaded, built
|
||||||
|
against zookeeper_st library):
|
||||||
|
|
||||||
|
$ cli_mt zookeeper_host:9876
|
||||||
|
|
||||||
|
To start a client with read-only mode enabled, use the -r flag:
|
||||||
|
|
||||||
|
$ cli_mt -r zookeeper_host:9876
|
||||||
|
|
||||||
|
This is a client application that gives you a shell for executing
|
||||||
|
simple zookeeper commands. Once successfully started and connected to
|
||||||
|
the server it displays a shell prompt.
|
||||||
|
|
||||||
|
You can now enter zookeeper commands. For example, to create a node:
|
||||||
|
|
||||||
|
> create /my_new_node
|
||||||
|
|
||||||
|
To verify that the node's been created:
|
||||||
|
|
||||||
|
> ls /
|
||||||
|
|
||||||
|
You should see a list of nodes who are the children of the root node "/".
|
||||||
|
|
||||||
|
Here's a list of command supported by the cli shell:
|
||||||
|
|
||||||
|
ls <path> -- list children of a znode identified by <path>. The
|
||||||
|
command set a children watch on the znode.
|
||||||
|
get <path> -- get the value of a znode at <path>
|
||||||
|
set <path> <value> -- set the value of a znode at <path> to <value>
|
||||||
|
create [+e|+s] <path> -- create a znode as a child of znode <path>;
|
||||||
|
use +e option to create an ephemeral znode,
|
||||||
|
use +s option to create a znode with a sequence number
|
||||||
|
appended to the name. The operation will fail if
|
||||||
|
the parent znode (the one identified by <path>) doesn't
|
||||||
|
exist.
|
||||||
|
delete <path> -- delete the znode at <path>. The command will fail if the znode
|
||||||
|
has children.
|
||||||
|
sync <path> -- make sure all pending updates have been applied to znode at <path>
|
||||||
|
exists <path> -- returns a result code indicating whether the znode at <path>
|
||||||
|
exists. The command also sets a znode watch.
|
||||||
|
myid -- prints out the current zookeeper session id.
|
||||||
|
quit -- exit the shell.
|
||||||
|
|
||||||
|
In order to be able to use the zookeeper API in your application you have to
|
||||||
|
1) remember to include the zookeeper header
|
||||||
|
#include <zookeeper/zookeeper.h>
|
||||||
|
2) use -DTHREADED compiler option to enable Sync API; in this case you should
|
||||||
|
be linking your code against zookeeper_mt library
|
||||||
|
|
||||||
|
Please take a look at cli.c to understand how to use the two API types.
|
||||||
|
(TODO: some kind of short tutorial would be helpful, I guess)
|
327
zookeeper-client/zookeeper-client-c/acinclude.m4
Normal file
327
zookeeper-client/zookeeper-client-c/acinclude.m4
Normal file
@ -0,0 +1,327 @@
|
|||||||
|
# This file is part of Autoconf. -*- Autoconf -*-
|
||||||
|
|
||||||
|
# Copyright (C) 2004 Oren Ben-Kiki
|
||||||
|
# This file is distributed under the same terms as the Autoconf macro files.
|
||||||
|
|
||||||
|
# Generate automatic documentation using Doxygen. Works in concert with the
|
||||||
|
# aminclude.m4 file and a compatible doxygen configuration file. Defines the
|
||||||
|
# following public macros:
|
||||||
|
#
|
||||||
|
# DX_???_FEATURE(ON|OFF) - control the default setting of a Doxygen feature.
|
||||||
|
# Supported features are 'DOXYGEN' itself, 'DOT' for generating graphics,
|
||||||
|
# 'HTML' for plain HTML, 'CHM' for compressed HTML help (for MS users), 'CHI'
|
||||||
|
# for generating a seperate .chi file by the .chm file, and 'MAN', 'RTF',
|
||||||
|
# 'XML', 'PDF' and 'PS' for the appropriate output formats. The environment
|
||||||
|
# variable DOXYGEN_PAPER_SIZE may be specified to override the default 'a4wide'
|
||||||
|
# paper size.
|
||||||
|
#
|
||||||
|
# By default, HTML, PDF and PS documentation is generated as this seems to be
|
||||||
|
# the most popular and portable combination. MAN pages created by Doxygen are
|
||||||
|
# usually problematic, though by picking an appropriate subset and doing some
|
||||||
|
# massaging they might be better than nothing. CHM and RTF are specific for MS
|
||||||
|
# (note that you can't generate both HTML and CHM at the same time). The XML is
|
||||||
|
# rather useless unless you apply specialized post-processing to it.
|
||||||
|
#
|
||||||
|
# The macro mainly controls the default state of the feature. The use can
|
||||||
|
# override the default by specifying --enable or --disable. The macros ensure
|
||||||
|
# that contradictory flags are not given (e.g., --enable-doxygen-html and
|
||||||
|
# --enable-doxygen-chm, --enable-doxygen-anything with --disable-doxygen, etc.)
|
||||||
|
# Finally, each feature will be automatically disabled (with a warning) if the
|
||||||
|
# required programs are missing.
|
||||||
|
#
|
||||||
|
# Once all the feature defaults have been specified, call DX_INIT_DOXYGEN with
|
||||||
|
# the following parameters: a one-word name for the project for use as a
|
||||||
|
# filename base etc., an optional configuration file name (the default is
|
||||||
|
# 'Doxyfile', the same as Doxygen's default), and an optional output directory
|
||||||
|
# name (the default is 'doxygen-doc').
|
||||||
|
|
||||||
|
## ----------##
|
||||||
|
## Defaults. ##
|
||||||
|
## ----------##
|
||||||
|
|
||||||
|
DX_ENV=""
|
||||||
|
AC_DEFUN([DX_FEATURE_doc], ON)
|
||||||
|
AC_DEFUN([DX_FEATURE_dot], ON)
|
||||||
|
AC_DEFUN([DX_FEATURE_man], OFF)
|
||||||
|
AC_DEFUN([DX_FEATURE_html], ON)
|
||||||
|
AC_DEFUN([DX_FEATURE_chm], OFF)
|
||||||
|
AC_DEFUN([DX_FEATURE_chi], OFF)
|
||||||
|
AC_DEFUN([DX_FEATURE_rtf], OFF)
|
||||||
|
AC_DEFUN([DX_FEATURE_xml], OFF)
|
||||||
|
AC_DEFUN([DX_FEATURE_pdf], ON)
|
||||||
|
AC_DEFUN([DX_FEATURE_ps], ON)
|
||||||
|
|
||||||
|
## --------------- ##
|
||||||
|
## Private macros. ##
|
||||||
|
## --------------- ##
|
||||||
|
|
||||||
|
# DX_ENV_APPEND(VARIABLE, VALUE)
|
||||||
|
# ------------------------------
|
||||||
|
# Append VARIABLE="VALUE" to DX_ENV for invoking doxygen.
|
||||||
|
AC_DEFUN([DX_ENV_APPEND], [AC_SUBST([DX_ENV], ["$DX_ENV $1='$2'"])])
|
||||||
|
|
||||||
|
# DX_DIRNAME_EXPR
|
||||||
|
# ---------------
|
||||||
|
# Expand into a shell expression prints the directory part of a path.
|
||||||
|
AC_DEFUN([DX_DIRNAME_EXPR],
|
||||||
|
[[expr ".$1" : '\(\.\)[^/]*$' \| "x$1" : 'x\(.*\)/[^/]*$']])
|
||||||
|
|
||||||
|
# DX_IF_FEATURE(FEATURE, IF-ON, IF-OFF)
|
||||||
|
# -------------------------------------
|
||||||
|
# Expands according to the M4 (static) status of the feature.
|
||||||
|
AC_DEFUN([DX_IF_FEATURE], [ifelse(DX_FEATURE_$1, ON, [$2], [$3])])
|
||||||
|
|
||||||
|
# DX_REQUIRE_PROG(VARIABLE, PROGRAM)
|
||||||
|
# ----------------------------------
|
||||||
|
# Require the specified program to be found for the DX_CURRENT_FEATURE to work.
|
||||||
|
AC_DEFUN([DX_REQUIRE_PROG], [
|
||||||
|
AC_PATH_TOOL([$1], [$2])
|
||||||
|
if test "$DX_FLAG_$[DX_CURRENT_FEATURE$$1]" = 1; then
|
||||||
|
AC_MSG_WARN([$2 not found - will not DX_CURRENT_DESCRIPTION])
|
||||||
|
AC_SUBST([DX_FLAG_]DX_CURRENT_FEATURE, 0)
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
|
||||||
|
# DX_TEST_FEATURE(FEATURE)
|
||||||
|
# ------------------------
|
||||||
|
# Expand to a shell expression testing whether the feature is active.
|
||||||
|
AC_DEFUN([DX_TEST_FEATURE], [test "$DX_FLAG_$1" = 1])
|
||||||
|
|
||||||
|
# DX_CHECK_DEPEND(REQUIRED_FEATURE, REQUIRED_STATE)
|
||||||
|
# -------------------------------------------------
|
||||||
|
# Verify that a required features has the right state before trying to turn on
|
||||||
|
# the DX_CURRENT_FEATURE.
|
||||||
|
AC_DEFUN([DX_CHECK_DEPEND], [
|
||||||
|
test "$DX_FLAG_$1" = "$2" \
|
||||||
|
|| AC_MSG_ERROR([doxygen-DX_CURRENT_FEATURE ifelse([$2], 1,
|
||||||
|
requires, contradicts) doxygen-DX_CURRENT_FEATURE])
|
||||||
|
])
|
||||||
|
|
||||||
|
# DX_CLEAR_DEPEND(FEATURE, REQUIRED_FEATURE, REQUIRED_STATE)
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
# Turn off the DX_CURRENT_FEATURE if the required feature is off.
|
||||||
|
AC_DEFUN([DX_CLEAR_DEPEND], [
|
||||||
|
test "$DX_FLAG_$1" = "$2" || AC_SUBST([DX_FLAG_]DX_CURRENT_FEATURE, 0)
|
||||||
|
])
|
||||||
|
|
||||||
|
# DX_FEATURE_ARG(FEATURE, DESCRIPTION,
|
||||||
|
# CHECK_DEPEND, CLEAR_DEPEND,
|
||||||
|
# REQUIRE, DO-IF-ON, DO-IF-OFF)
|
||||||
|
# --------------------------------------------
|
||||||
|
# Parse the command-line option controlling a feature. CHECK_DEPEND is called
|
||||||
|
# if the user explicitly turns the feature on (and invokes DX_CHECK_DEPEND),
|
||||||
|
# otherwise CLEAR_DEPEND is called to turn off the default state if a required
|
||||||
|
# feature is disabled (using DX_CLEAR_DEPEND). REQUIRE performs additional
|
||||||
|
# requirement tests (DX_REQUIRE_PROG). Finally, an automake flag is set and
|
||||||
|
# DO-IF-ON or DO-IF-OFF are called according to the final state of the feature.
|
||||||
|
AC_DEFUN([DX_ARG_ABLE], [
|
||||||
|
AC_DEFUN([DX_CURRENT_FEATURE], [$1])
|
||||||
|
AC_DEFUN([DX_CURRENT_DESCRIPTION], [$2])
|
||||||
|
AC_ARG_ENABLE(doxygen-$1,
|
||||||
|
[AS_HELP_STRING(DX_IF_FEATURE([$1], [--disable-doxygen-$1],
|
||||||
|
[--enable-doxygen-$1]),
|
||||||
|
DX_IF_FEATURE([$1], [don't $2], [$2]))],
|
||||||
|
[
|
||||||
|
case "$enableval" in
|
||||||
|
#(
|
||||||
|
y|Y|yes|Yes|YES)
|
||||||
|
AC_SUBST([DX_FLAG_$1], 1)
|
||||||
|
$3
|
||||||
|
;; #(
|
||||||
|
n|N|no|No|NO)
|
||||||
|
AC_SUBST([DX_FLAG_$1], 0)
|
||||||
|
;; #(
|
||||||
|
*)
|
||||||
|
AC_MSG_ERROR([invalid value '$enableval' given to doxygen-$1])
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
], [
|
||||||
|
AC_SUBST([DX_FLAG_$1], [DX_IF_FEATURE([$1], 1, 0)])
|
||||||
|
$4
|
||||||
|
])
|
||||||
|
if DX_TEST_FEATURE([$1]); then
|
||||||
|
$5
|
||||||
|
:
|
||||||
|
fi
|
||||||
|
if DX_TEST_FEATURE([$1]); then
|
||||||
|
AM_CONDITIONAL(DX_COND_$1, :)
|
||||||
|
$6
|
||||||
|
:
|
||||||
|
else
|
||||||
|
AM_CONDITIONAL(DX_COND_$1, false)
|
||||||
|
$7
|
||||||
|
:
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
|
||||||
|
## -------------- ##
|
||||||
|
## Public macros. ##
|
||||||
|
## -------------- ##
|
||||||
|
|
||||||
|
# DX_XXX_FEATURE(DEFAULT_STATE)
|
||||||
|
# -----------------------------
|
||||||
|
AC_DEFUN([DX_DOXYGEN_FEATURE], [AC_DEFUN([DX_FEATURE_doc], [$1])])
|
||||||
|
AC_DEFUN([DX_MAN_FEATURE], [AC_DEFUN([DX_FEATURE_man], [$1])])
|
||||||
|
AC_DEFUN([DX_HTML_FEATURE], [AC_DEFUN([DX_FEATURE_html], [$1])])
|
||||||
|
AC_DEFUN([DX_CHM_FEATURE], [AC_DEFUN([DX_FEATURE_chm], [$1])])
|
||||||
|
AC_DEFUN([DX_CHI_FEATURE], [AC_DEFUN([DX_FEATURE_chi], [$1])])
|
||||||
|
AC_DEFUN([DX_RTF_FEATURE], [AC_DEFUN([DX_FEATURE_rtf], [$1])])
|
||||||
|
AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])])
|
||||||
|
AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])])
|
||||||
|
AC_DEFUN([DX_PDF_FEATURE], [AC_DEFUN([DX_FEATURE_pdf], [$1])])
|
||||||
|
AC_DEFUN([DX_PS_FEATURE], [AC_DEFUN([DX_FEATURE_ps], [$1])])
|
||||||
|
|
||||||
|
# DX_INIT_DOXYGEN(PROJECT, [CONFIG-FILE], [OUTPUT-DOC-DIR])
|
||||||
|
# ---------------------------------------------------------
|
||||||
|
# PROJECT also serves as the base name for the documentation files.
|
||||||
|
# The default CONFIG-FILE is "Doxyfile" and OUTPUT-DOC-DIR is "doxygen-doc".
|
||||||
|
AC_DEFUN([DX_INIT_DOXYGEN], [
|
||||||
|
|
||||||
|
# Files:
|
||||||
|
AC_SUBST([DX_PROJECT], [$1])
|
||||||
|
AC_SUBST([DX_CONFIG], [ifelse([$2], [], Doxyfile, [$2])])
|
||||||
|
AC_SUBST([DX_DOCDIR], [ifelse([$3], [], doxygen-doc, [$3])])
|
||||||
|
|
||||||
|
# Environment variables used inside doxygen.cfg:
|
||||||
|
DX_ENV_APPEND(SRCDIR, $srcdir)
|
||||||
|
DX_ENV_APPEND(PROJECT, $DX_PROJECT)
|
||||||
|
DX_ENV_APPEND(DOCDIR, $DX_DOCDIR)
|
||||||
|
DX_ENV_APPEND(VERSION, $PACKAGE_VERSION)
|
||||||
|
|
||||||
|
# Doxygen itself:
|
||||||
|
DX_ARG_ABLE(doc, [generate any doxygen documentation],
|
||||||
|
[],
|
||||||
|
[],
|
||||||
|
[DX_REQUIRE_PROG([DX_DOXYGEN], doxygen)
|
||||||
|
DX_REQUIRE_PROG([DX_PERL], perl)],
|
||||||
|
[DX_ENV_APPEND(PERL_PATH, $DX_PERL)])
|
||||||
|
|
||||||
|
# Dot for graphics:
|
||||||
|
DX_ARG_ABLE(dot, [generate graphics for doxygen documentation],
|
||||||
|
[DX_CHECK_DEPEND(doc, 1)],
|
||||||
|
[DX_CLEAR_DEPEND(doc, 1)],
|
||||||
|
[DX_REQUIRE_PROG([DX_DOT], dot)],
|
||||||
|
[DX_ENV_APPEND(HAVE_DOT, YES)
|
||||||
|
DX_ENV_APPEND(DOT_PATH, [`DX_DIRNAME_EXPR($DX_DOT)`])],
|
||||||
|
[DX_ENV_APPEND(HAVE_DOT, NO)])
|
||||||
|
|
||||||
|
# Man pages generation:
|
||||||
|
DX_ARG_ABLE(man, [generate doxygen manual pages],
|
||||||
|
[DX_CHECK_DEPEND(doc, 1)],
|
||||||
|
[DX_CLEAR_DEPEND(doc, 1)],
|
||||||
|
[],
|
||||||
|
[DX_ENV_APPEND(GENERATE_MAN, YES)],
|
||||||
|
[DX_ENV_APPEND(GENERATE_MAN, NO)])
|
||||||
|
|
||||||
|
# RTF file generation:
|
||||||
|
DX_ARG_ABLE(rtf, [generate doxygen RTF documentation],
|
||||||
|
[DX_CHECK_DEPEND(doc, 1)],
|
||||||
|
[DX_CLEAR_DEPEND(doc, 1)],
|
||||||
|
[],
|
||||||
|
[DX_ENV_APPEND(GENERATE_RTF, YES)],
|
||||||
|
[DX_ENV_APPEND(GENERATE_RTF, NO)])
|
||||||
|
|
||||||
|
# XML file generation:
|
||||||
|
DX_ARG_ABLE(xml, [generate doxygen XML documentation],
|
||||||
|
[DX_CHECK_DEPEND(doc, 1)],
|
||||||
|
[DX_CLEAR_DEPEND(doc, 1)],
|
||||||
|
[],
|
||||||
|
[DX_ENV_APPEND(GENERATE_XML, YES)],
|
||||||
|
[DX_ENV_APPEND(GENERATE_XML, NO)])
|
||||||
|
|
||||||
|
# (Compressed) HTML help generation:
|
||||||
|
DX_ARG_ABLE(chm, [generate doxygen compressed HTML help documentation],
|
||||||
|
[DX_CHECK_DEPEND(doc, 1)],
|
||||||
|
[DX_CLEAR_DEPEND(doc, 1)],
|
||||||
|
[DX_REQUIRE_PROG([DX_HHC], hhc)],
|
||||||
|
[DX_ENV_APPEND(HHC_PATH, $DX_HHC)
|
||||||
|
DX_ENV_APPEND(GENERATE_HTML, YES)
|
||||||
|
DX_ENV_APPEND(GENERATE_HTMLHELP, YES)],
|
||||||
|
[DX_ENV_APPEND(GENERATE_HTMLHELP, NO)])
|
||||||
|
|
||||||
|
# Seperate CHI file generation.
|
||||||
|
DX_ARG_ABLE(chi, [generate doxygen seperate compressed HTML help index file],
|
||||||
|
[DX_CHECK_DEPEND(chm, 1)],
|
||||||
|
[DX_CLEAR_DEPEND(chm, 1)],
|
||||||
|
[],
|
||||||
|
[DX_ENV_APPEND(GENERATE_CHI, YES)],
|
||||||
|
[DX_ENV_APPEND(GENERATE_CHI, NO)])
|
||||||
|
|
||||||
|
# Plain HTML pages generation:
|
||||||
|
DX_ARG_ABLE(html, [generate doxygen plain HTML documentation],
|
||||||
|
[DX_CHECK_DEPEND(doc, 1) DX_CHECK_DEPEND(chm, 0)],
|
||||||
|
[DX_CLEAR_DEPEND(doc, 1) DX_CLEAR_DEPEND(chm, 0)],
|
||||||
|
[],
|
||||||
|
[DX_ENV_APPEND(GENERATE_HTML, YES)],
|
||||||
|
[DX_TEST_FEATURE(chm) || DX_ENV_APPEND(GENERATE_HTML, NO)])
|
||||||
|
|
||||||
|
# PostScript file generation:
|
||||||
|
DX_ARG_ABLE(ps, [generate doxygen PostScript documentation],
|
||||||
|
[DX_CHECK_DEPEND(doc, 1)],
|
||||||
|
[DX_CLEAR_DEPEND(doc, 1)],
|
||||||
|
[DX_REQUIRE_PROG([DX_LATEX], latex)
|
||||||
|
DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
|
||||||
|
DX_REQUIRE_PROG([DX_DVIPS], dvips)
|
||||||
|
DX_REQUIRE_PROG([DX_EGREP], egrep)])
|
||||||
|
|
||||||
|
# PDF file generation:
|
||||||
|
DX_ARG_ABLE(pdf, [generate doxygen PDF documentation],
|
||||||
|
[DX_CHECK_DEPEND(doc, 1)],
|
||||||
|
[DX_CLEAR_DEPEND(doc, 1)],
|
||||||
|
[DX_REQUIRE_PROG([DX_PDFLATEX], pdflatex)
|
||||||
|
DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
|
||||||
|
DX_REQUIRE_PROG([DX_EGREP], egrep)])
|
||||||
|
|
||||||
|
# LaTeX generation for PS and/or PDF:
|
||||||
|
if DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf); then
|
||||||
|
AM_CONDITIONAL(DX_COND_latex, :)
|
||||||
|
DX_ENV_APPEND(GENERATE_LATEX, YES)
|
||||||
|
else
|
||||||
|
AM_CONDITIONAL(DX_COND_latex, false)
|
||||||
|
DX_ENV_APPEND(GENERATE_LATEX, NO)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Paper size for PS and/or PDF:
|
||||||
|
AC_ARG_VAR(DOXYGEN_PAPER_SIZE,
|
||||||
|
[a4wide (default), a4, letter, legal or executive])
|
||||||
|
case "$DOXYGEN_PAPER_SIZE" in
|
||||||
|
#(
|
||||||
|
"")
|
||||||
|
AC_SUBST(DOXYGEN_PAPER_SIZE, "")
|
||||||
|
;; #(
|
||||||
|
a4wide|a4|letter|legal|executive)
|
||||||
|
DX_ENV_APPEND(PAPER_SIZE, $DOXYGEN_PAPER_SIZE)
|
||||||
|
;; #(
|
||||||
|
*)
|
||||||
|
AC_MSG_ERROR([unknown DOXYGEN_PAPER_SIZE='$DOXYGEN_PAPER_SIZE'])
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
#For debugging:
|
||||||
|
#echo DX_FLAG_doc=$DX_FLAG_doc
|
||||||
|
#echo DX_FLAG_dot=$DX_FLAG_dot
|
||||||
|
#echo DX_FLAG_man=$DX_FLAG_man
|
||||||
|
#echo DX_FLAG_html=$DX_FLAG_html
|
||||||
|
#echo DX_FLAG_chm=$DX_FLAG_chm
|
||||||
|
#echo DX_FLAG_chi=$DX_FLAG_chi
|
||||||
|
#echo DX_FLAG_rtf=$DX_FLAG_rtf
|
||||||
|
#echo DX_FLAG_xml=$DX_FLAG_xml
|
||||||
|
#echo DX_FLAG_pdf=$DX_FLAG_pdf
|
||||||
|
#echo DX_FLAG_ps=$DX_FLAG_ps
|
||||||
|
#echo DX_ENV=$DX_ENV
|
||||||
|
])
|
||||||
|
|
||||||
|
# CHECK_CPPUNIT
|
||||||
|
# ------------------
|
||||||
|
# Check for cppunit presence.
|
||||||
|
AC_DEFUN([CHECK_CPPUNIT], [
|
||||||
|
ifdef(
|
||||||
|
[AM_PATH_CPPUNIT],
|
||||||
|
[AM_PATH_CPPUNIT($1)],
|
||||||
|
[ifdef(
|
||||||
|
[PKG_CHECK_MODULES],
|
||||||
|
[PKG_CHECK_MODULES([CPPUNIT], [cppunit >= $1])],
|
||||||
|
[m4_fatal([Missing AM_PATH_CPPUNIT or PKG_CHECK_MODULES m4 macro.])]
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
])
|
186
zookeeper-client/zookeeper-client-c/aminclude.am
Normal file
186
zookeeper-client/zookeeper-client-c/aminclude.am
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
# Copyright (C) 2004 Oren Ben-Kiki
|
||||||
|
# This file is distributed under the same terms as the Automake macro files.
|
||||||
|
|
||||||
|
# Generate automatic documentation using Doxygen. Goals and variables values
|
||||||
|
# are controlled by the various DX_COND_??? conditionals set by autoconf.
|
||||||
|
#
|
||||||
|
# The provided goals are:
|
||||||
|
# doxygen-doc: Generate all doxygen documentation.
|
||||||
|
# doxygen-run: Run doxygen, which will generate some of the documentation
|
||||||
|
# (HTML, CHM, CHI, MAN, RTF, XML) but will not do the post
|
||||||
|
# processing required for the rest of it (PS, PDF, and some MAN).
|
||||||
|
# doxygen-man: Rename some doxygen generated man pages.
|
||||||
|
# doxygen-ps: Generate doxygen PostScript documentation.
|
||||||
|
# doxygen-pdf: Generate doxygen PDF documentation.
|
||||||
|
#
|
||||||
|
# Note that by default these are not integrated into the automake goals. If
|
||||||
|
# doxygen is used to generate man pages, you can achieve this integration by
|
||||||
|
# setting man3_MANS to the list of man pages generated and then adding the
|
||||||
|
# dependency:
|
||||||
|
#
|
||||||
|
# $(man3_MANS): doxygen-doc
|
||||||
|
#
|
||||||
|
# This will cause make to run doxygen and generate all the documentation.
|
||||||
|
#
|
||||||
|
# The following variable is intended for use in Makefile.am:
|
||||||
|
#
|
||||||
|
# DX_CLEANFILES = everything to clean.
|
||||||
|
#
|
||||||
|
# This is usually added to MOSTLYCLEANFILES.
|
||||||
|
|
||||||
|
## --------------------------------- ##
|
||||||
|
## Format-independent Doxygen rules. ##
|
||||||
|
## --------------------------------- ##
|
||||||
|
|
||||||
|
if DX_COND_doc
|
||||||
|
|
||||||
|
## ------------------------------- ##
|
||||||
|
## Rules specific for HTML output. ##
|
||||||
|
## ------------------------------- ##
|
||||||
|
|
||||||
|
if DX_COND_html
|
||||||
|
|
||||||
|
DX_CLEAN_HTML = @DX_DOCDIR@/html
|
||||||
|
|
||||||
|
endif DX_COND_html
|
||||||
|
|
||||||
|
## ------------------------------ ##
|
||||||
|
## Rules specific for CHM output. ##
|
||||||
|
## ------------------------------ ##
|
||||||
|
|
||||||
|
if DX_COND_chm
|
||||||
|
|
||||||
|
DX_CLEAN_CHM = @DX_DOCDIR@/chm
|
||||||
|
|
||||||
|
if DX_COND_chi
|
||||||
|
|
||||||
|
DX_CLEAN_CHI = @DX_DOCDIR@/@PACKAGE@.chi
|
||||||
|
|
||||||
|
endif DX_COND_chi
|
||||||
|
|
||||||
|
endif DX_COND_chm
|
||||||
|
|
||||||
|
## ------------------------------ ##
|
||||||
|
## Rules specific for MAN output. ##
|
||||||
|
## ------------------------------ ##
|
||||||
|
|
||||||
|
if DX_COND_man
|
||||||
|
|
||||||
|
DX_CLEAN_MAN = @DX_DOCDIR@/man
|
||||||
|
|
||||||
|
endif DX_COND_man
|
||||||
|
|
||||||
|
## ------------------------------ ##
|
||||||
|
## Rules specific for RTF output. ##
|
||||||
|
## ------------------------------ ##
|
||||||
|
|
||||||
|
if DX_COND_rtf
|
||||||
|
|
||||||
|
DX_CLEAN_RTF = @DX_DOCDIR@/rtf
|
||||||
|
|
||||||
|
endif DX_COND_rtf
|
||||||
|
|
||||||
|
## ------------------------------ ##
|
||||||
|
## Rules specific for XML output. ##
|
||||||
|
## ------------------------------ ##
|
||||||
|
|
||||||
|
if DX_COND_xml
|
||||||
|
|
||||||
|
DX_CLEAN_XML = @DX_DOCDIR@/xml
|
||||||
|
|
||||||
|
endif DX_COND_xml
|
||||||
|
|
||||||
|
## ----------------------------- ##
|
||||||
|
## Rules specific for PS output. ##
|
||||||
|
## ----------------------------- ##
|
||||||
|
|
||||||
|
if DX_COND_ps
|
||||||
|
|
||||||
|
DX_CLEAN_PS = @DX_DOCDIR@/@PACKAGE@.ps
|
||||||
|
|
||||||
|
DX_PS_GOAL = doxygen-ps
|
||||||
|
|
||||||
|
doxygen-ps: @DX_DOCDIR@/@PACKAGE@.ps
|
||||||
|
|
||||||
|
@DX_DOCDIR@/@PACKAGE@.ps: @DX_DOCDIR@/@PACKAGE@.tag
|
||||||
|
cd @DX_DOCDIR@/latex; \
|
||||||
|
rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
|
||||||
|
$(DX_LATEX) refman.tex; \
|
||||||
|
$(MAKEINDEX_PATH) refman.idx; \
|
||||||
|
$(DX_LATEX) refman.tex; \
|
||||||
|
countdown=5; \
|
||||||
|
while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
|
||||||
|
refman.log > /dev/null 2>&1 \
|
||||||
|
&& test $$countdown -gt 0; do \
|
||||||
|
$(DX_LATEX) refman.tex; \
|
||||||
|
countdown=`expr $$countdown - 1`; \
|
||||||
|
done; \
|
||||||
|
$(DX_DVIPS) -o ../@PACKAGE@.ps refman.dvi
|
||||||
|
|
||||||
|
endif DX_COND_ps
|
||||||
|
|
||||||
|
## ------------------------------ ##
|
||||||
|
## Rules specific for PDF output. ##
|
||||||
|
## ------------------------------ ##
|
||||||
|
|
||||||
|
if DX_COND_pdf
|
||||||
|
|
||||||
|
DX_CLEAN_PDF = @DX_DOCDIR@/@PACKAGE@.pdf
|
||||||
|
|
||||||
|
DX_PDF_GOAL = doxygen-pdf
|
||||||
|
|
||||||
|
doxygen-pdf: @DX_DOCDIR@/@PACKAGE@.pdf
|
||||||
|
|
||||||
|
@DX_DOCDIR@/@PACKAGE@.pdf: @DX_DOCDIR@/@PACKAGE@.tag
|
||||||
|
cd @DX_DOCDIR@/latex; \
|
||||||
|
rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
|
||||||
|
$(DX_PDFLATEX) refman.tex; \
|
||||||
|
$(DX_MAKEINDEX) refman.idx; \
|
||||||
|
$(DX_PDFLATEX) refman.tex; \
|
||||||
|
countdown=5; \
|
||||||
|
while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
|
||||||
|
refman.log > /dev/null 2>&1 \
|
||||||
|
&& test $$countdown -gt 0; do \
|
||||||
|
$(DX_PDFLATEX) refman.tex; \
|
||||||
|
countdown=`expr $$countdown - 1`; \
|
||||||
|
done; \
|
||||||
|
mv refman.pdf ../@PACKAGE@.pdf
|
||||||
|
|
||||||
|
endif DX_COND_pdf
|
||||||
|
|
||||||
|
## ------------------------------------------------- ##
|
||||||
|
## Rules specific for LaTeX (shared for PS and PDF). ##
|
||||||
|
## ------------------------------------------------- ##
|
||||||
|
|
||||||
|
if DX_COND_latex
|
||||||
|
|
||||||
|
DX_CLEAN_LATEX = @DX_DOCDIR@/latex
|
||||||
|
|
||||||
|
endif DX_COND_latex
|
||||||
|
|
||||||
|
.PHONY: doxygen-run doxygen-doc $(DX_PS_GOAL) $(DX_PDF_GOAL)
|
||||||
|
|
||||||
|
.INTERMEDIATE: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
|
||||||
|
|
||||||
|
doxygen-run: @DX_DOCDIR@/@PACKAGE@.tag
|
||||||
|
|
||||||
|
doxygen-doc: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
|
||||||
|
|
||||||
|
@DX_DOCDIR@/@PACKAGE@.tag: $(DX_CONFIG) $(pkginclude_HEADERS)
|
||||||
|
rm -rf @DX_DOCDIR@
|
||||||
|
$(DX_ENV) $(DX_DOXYGEN) $(srcdir)/$(DX_CONFIG)
|
||||||
|
|
||||||
|
DX_CLEANFILES = \
|
||||||
|
@DX_DOCDIR@/@PACKAGE@.tag \
|
||||||
|
-r \
|
||||||
|
$(DX_CLEAN_HTML) \
|
||||||
|
$(DX_CLEAN_CHM) \
|
||||||
|
$(DX_CLEAN_CHI) \
|
||||||
|
$(DX_CLEAN_MAN) \
|
||||||
|
$(DX_CLEAN_RTF) \
|
||||||
|
$(DX_CLEAN_XML) \
|
||||||
|
$(DX_CLEAN_PS) \
|
||||||
|
$(DX_CLEAN_PDF) \
|
||||||
|
$(DX_CLEAN_LATEX)
|
||||||
|
|
||||||
|
endif DX_COND_doc
|
1252
zookeeper-client/zookeeper-client-c/c-doc.Doxyfile
Normal file
1252
zookeeper-client/zookeeper-client-c/c-doc.Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
157
zookeeper-client/zookeeper-client-c/cmake_config.h.in
Normal file
157
zookeeper-client/zookeeper-client-c/cmake_config.h.in
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CONFIG_H_
|
||||||
|
#define CONFIG_H_
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||||
|
#cmakedefine HAVE_ARPA_INET_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||||
|
#cmakedefine HAVE_DLFCN_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||||
|
#cmakedefine HAVE_FCNTL_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the file `generated/zookeeper.jute.c'. */
|
||||||
|
#cmakedefine HAVE_GENERATED_ZOOKEEPER_JUTE_C 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the file `generated/zookeeper.jute.h'. */
|
||||||
|
#cmakedefine HAVE_GENERATED_ZOOKEEPER_JUTE_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getcwd' function. */
|
||||||
|
#cmakedefine HAVE_GETCWD 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `gethostbyname' function. */
|
||||||
|
#cmakedefine HAVE_GETHOSTBYNAME 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `gethostname' function. */
|
||||||
|
#cmakedefine HAVE_GETHOSTNAME 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getlogin' function. */
|
||||||
|
#cmakedefine HAVE_GETLOGIN 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getpwuid_r' function. */
|
||||||
|
#cmakedefine HAVE_GETPWUID_R 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `gettimeofday' function. */
|
||||||
|
#cmakedefine HAVE_GETTIMEOFDAY 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getuid' function. */
|
||||||
|
#cmakedefine HAVE_GETUID 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||||
|
#cmakedefine HAVE_INTTYPES_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `rt' library (-lrt). */
|
||||||
|
#cmakedefine HAVE_LIBRT 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `memmove' function. */
|
||||||
|
#cmakedefine HAVE_MEMMOVE 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <memory.h> header file. */
|
||||||
|
#cmakedefine HAVE_MEMORY_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `memset' function. */
|
||||||
|
#cmakedefine HAVE_MEMSET 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <netdb.h> header file. */
|
||||||
|
#cmakedefine HAVE_NETDB_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||||
|
#cmakedefine HAVE_NETINET_IN_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `poll' function. */
|
||||||
|
#cmakedefine HAVE_POLL 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `socket' function. */
|
||||||
|
#cmakedefine HAVE_SOCKET 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdint.h> header file. */
|
||||||
|
#cmakedefine HAVE_STDINT_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||||
|
#cmakedefine HAVE_STDLIB_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strchr' function. */
|
||||||
|
#cmakedefine HAVE_STRCHR 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strdup' function. */
|
||||||
|
#cmakedefine HAVE_STRDUP 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strerror' function. */
|
||||||
|
#cmakedefine HAVE_STRERROR 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <strings.h> header file. */
|
||||||
|
#cmakedefine HAVE_STRINGS_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <string.h> header file. */
|
||||||
|
#cmakedefine HAVE_STRING_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strtol' function. */
|
||||||
|
#cmakedefine HAVE_STRTOL 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||||
|
#cmakedefine HAVE_SYS_SOCKET_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||||
|
#cmakedefine HAVE_SYS_STAT_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||||
|
#cmakedefine HAVE_SYS_TIME_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||||
|
#cmakedefine HAVE_SYS_TYPES_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/utsname.h> header file. */
|
||||||
|
#cmakedefine HAVE_SYS_UTSNAME_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <unistd.h> header file. */
|
||||||
|
#cmakedefine HAVE_UNISTD_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if IPv6 support is available. */
|
||||||
|
#cmakedefine ZOO_IPV6_ENABLED 1
|
||||||
|
|
||||||
|
/* Define to 1 if SOCK_CLOEXEC is available and wanted */
|
||||||
|
#cmakedefine SOCK_CLOEXEC_ENABLED 1
|
||||||
|
|
||||||
|
/* poll() second argument type */
|
||||||
|
#define POLL_NFDS_TYPE nfds_t
|
||||||
|
|
||||||
|
/* Name of package */
|
||||||
|
#define PACKAGE "${PROJECT_NAME}"
|
||||||
|
|
||||||
|
/* Define to the address where bug reports for this package should be sent. */
|
||||||
|
#define PACKAGE_BUGREPORT "${email}"
|
||||||
|
|
||||||
|
/* Define to the full name of this package. */
|
||||||
|
#define PACKAGE_NAME "${description}"
|
||||||
|
|
||||||
|
/* Define to the full name and version of this package. */
|
||||||
|
#define PACKAGE_STRING "${description} ${PROJECT_VERSION}"
|
||||||
|
|
||||||
|
/* Define to the one symbol short name of this package. */
|
||||||
|
#define PACKAGE_TARNAME "${PROJECT_NAME}"
|
||||||
|
|
||||||
|
/* Define to the version of this package. */
|
||||||
|
#define PACKAGE_VERSION "${PROJECT_VERSION}"
|
||||||
|
|
||||||
|
/* Version number of package */
|
||||||
|
#define VERSION "${PROJECT_VERSION}"
|
||||||
|
|
||||||
|
#endif
|
245
zookeeper-client/zookeeper-client-c/configure.ac
Normal file
245
zookeeper-client/zookeeper-client-c/configure.ac
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
# -*- Autoconf -*-
|
||||||
|
# Process this file with autoconf to produce a configure script.
|
||||||
|
|
||||||
|
AC_PREREQ(2.59)
|
||||||
|
|
||||||
|
AC_INIT([zookeeper C client],3.6.3,[user@zookeeper.apache.org],[zookeeper])
|
||||||
|
AC_CONFIG_SRCDIR([src/zookeeper.c])
|
||||||
|
|
||||||
|
# Save initial CFLAGS and CXXFLAGS values before AC_PROG_CC and AC_PROG_CXX
|
||||||
|
init_cflags="$CFLAGS"
|
||||||
|
init_cxxflags="$CXXFLAGS"
|
||||||
|
|
||||||
|
# initialize Doxygen support
|
||||||
|
DX_HTML_FEATURE(ON)
|
||||||
|
DX_CHM_FEATURE(OFF)
|
||||||
|
DX_CHI_FEATURE(OFF)
|
||||||
|
DX_MAN_FEATURE(OFF)
|
||||||
|
DX_RTF_FEATURE(OFF)
|
||||||
|
DX_XML_FEATURE(OFF)
|
||||||
|
DX_PDF_FEATURE(OFF)
|
||||||
|
DX_PS_FEATURE(OFF)
|
||||||
|
DX_INIT_DOXYGEN([zookeeper],[c-doc.Doxyfile],[docs])
|
||||||
|
|
||||||
|
# initialize automake
|
||||||
|
AM_INIT_AUTOMAKE([-Wall foreign])
|
||||||
|
|
||||||
|
AC_CONFIG_HEADER([config.h])
|
||||||
|
|
||||||
|
# Checks for programs.
|
||||||
|
AC_ARG_WITH(cppunit,
|
||||||
|
[ --without-cppunit do not use CPPUNIT])
|
||||||
|
|
||||||
|
if test "$with_cppunit" = "no" ; then
|
||||||
|
CPPUNIT_PATH="No_CPPUNIT"
|
||||||
|
CPPUNIT_INCLUDE=
|
||||||
|
CPPUNIT_LIBS=
|
||||||
|
else
|
||||||
|
CHECK_CPPUNIT(1.10.2)
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl OpenSSL
|
||||||
|
AC_ARG_WITH(openssl,
|
||||||
|
[AC_HELP_STRING([--with-openssl[=DIR]], [build with openssl (autodetect openssl library by default) )])],
|
||||||
|
[], [with_openssl=yes])
|
||||||
|
AC_MSG_NOTICE([configuring SSL using --with-openssl=$with_openssl])
|
||||||
|
saved_CPPFLAGS="$CPPFLAGS"
|
||||||
|
saved_LDFLAGS="$LDFLAGS"
|
||||||
|
if test "x$with_openssl" != "xno" && test "x$with_openssl" != "xyes" ; then
|
||||||
|
CPPFLAGS="$CPPFLAGS -I$with_openssl/include"
|
||||||
|
LDFLAGS="$LDFLAGS -L$with_openssl/lib"
|
||||||
|
fi
|
||||||
|
have_openssl=no
|
||||||
|
AC_CHECK_HEADER(openssl/ssl.h, [ AC_CHECK_LIB(ssl, SSL_CTX_new, [have_openssl=yes]) ])
|
||||||
|
if test "x$with_openssl" != "xno" && test "x$with_openssl" != "xyes" && test "x$have_openssl" != "xyes"; then
|
||||||
|
CPPFLAGS="$saved_CPPFLAGS"
|
||||||
|
LDFLAGS="$saved_LDFLAGS"
|
||||||
|
fi
|
||||||
|
if test "x$with_openssl" != xno && test "x$have_openssl" = xno; then
|
||||||
|
AC_MSG_WARN([cannot build SSL support -- openssl not found])
|
||||||
|
with_openssl=no
|
||||||
|
fi
|
||||||
|
if test "x$with_openssl" != xno; then
|
||||||
|
AC_MSG_NOTICE([building with SSL support])
|
||||||
|
else
|
||||||
|
AC_MSG_NOTICE([building without SSL support])
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL([WANT_OPENSSL],[test "x$with_openssl" != xno])
|
||||||
|
|
||||||
|
if test "$CALLER" = "ANT" ; then
|
||||||
|
CPPUNIT_CFLAGS="$CPPUNIT_CFLAGS -DZKSERVER_CMD=\"\\\"${base_dir}/zookeeper-client/zookeeper-client-c/tests/zkServer.sh\\\"\""
|
||||||
|
else
|
||||||
|
CPPUNIT_CFLAGS="$CPPUNIT_CFLAGS -DZKSERVER_CMD=\"\\\"./tests/zkServer.sh\\\"\""
|
||||||
|
AC_CHECK_FILES([$srcdir/generated/zookeeper.jute.c $srcdir/generated/zookeeper.jute.h],[],
|
||||||
|
[AC_MSG_ERROR([jute files are missing! Please run "ant compile_jute" while in the zookeeper top level directory.])
|
||||||
|
])
|
||||||
|
fi
|
||||||
|
AC_SUBST(CPPUNIT_CFLAGS)
|
||||||
|
|
||||||
|
AC_PROG_CC
|
||||||
|
AM_PROG_CC_C_O
|
||||||
|
AC_PROG_CXX
|
||||||
|
AC_PROG_INSTALL
|
||||||
|
AC_PROG_LN_S
|
||||||
|
|
||||||
|
# AC_DISABLE_SHARED
|
||||||
|
AC_PROG_LIBTOOL
|
||||||
|
|
||||||
|
#enable -D_GNU_SOURCE since the return code value of getaddrinfo
|
||||||
|
#ifdefed with __USE_GNU
|
||||||
|
#features.h header undef's __USE_GNU and defines it only if _GNU_SOURCE is defined
|
||||||
|
#hence this define for gcc
|
||||||
|
AC_ARG_ENABLE([debug],
|
||||||
|
[AS_HELP_STRING([--enable-debug],[enable debug build [default=no]])],
|
||||||
|
[],[enable_debug=no])
|
||||||
|
|
||||||
|
if test "x$enable_debug" = xyes; then
|
||||||
|
if test "x$init_cflags" = x; then
|
||||||
|
CFLAGS=""
|
||||||
|
fi
|
||||||
|
CFLAGS="$CFLAGS -g -O0 -D_GNU_SOURCE"
|
||||||
|
else
|
||||||
|
if test "x$init_cflags" = x; then
|
||||||
|
CFLAGS="-g -O2 -D_GNU_SOURCE"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$enable_debug" = xyes; then
|
||||||
|
if test "x$init_cxxflags" = x; then
|
||||||
|
CXXFLAGS=""
|
||||||
|
fi
|
||||||
|
CXXFLAGS="$CXXFLAGS -g -O0"
|
||||||
|
else
|
||||||
|
if test "x$init_cxxflags" = x; then
|
||||||
|
CXXFLAGS="-g -O2"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check whether to enable gcov (coverage test)
|
||||||
|
AC_ARG_ENABLE(gcov, [AS_HELP_STRING([--enable-gcov],[enable coverage test])])
|
||||||
|
AC_MSG_CHECKING([whether to enable gcov])
|
||||||
|
AS_IF([test "x${enable_gcov}" = "xyes"],AC_MSG_RESULT([yes]),AC_MSG_RESULT([no]))
|
||||||
|
AM_CONDITIONAL([ENABLEGCOV],[test "x${enable_gcov}" = "xyes"])
|
||||||
|
|
||||||
|
|
||||||
|
CXXFLAGS="$CXXFLAGS -std=c++11"
|
||||||
|
|
||||||
|
AC_ARG_WITH([syncapi],
|
||||||
|
[AS_HELP_STRING([--with-syncapi],[build with support for SyncAPI [default=yes]])],
|
||||||
|
[],[with_syncapi=yes])
|
||||||
|
|
||||||
|
# Checks for libraries.
|
||||||
|
AC_CHECK_LIB([pthread], [pthread_mutex_lock],[have_pthread=yes],[have_pthread=no])
|
||||||
|
|
||||||
|
if test "x$with_syncapi" != xno && test "x$have_pthread" = xno; then
|
||||||
|
AC_MSG_WARN([cannot build SyncAPI -- pthread not found])
|
||||||
|
with_syncapi=no
|
||||||
|
fi
|
||||||
|
if test "x$with_syncapi" != xno; then
|
||||||
|
AC_MSG_NOTICE([building with SyncAPI support])
|
||||||
|
else
|
||||||
|
AC_MSG_NOTICE([building without SyncAPI support])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AM_CONDITIONAL([WANT_SYNCAPI],[test "x$with_syncapi" != xno])
|
||||||
|
|
||||||
|
# Checks for header files.
|
||||||
|
AC_HEADER_STDC
|
||||||
|
AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h sys/time.h unistd.h sys/utsname.h])
|
||||||
|
|
||||||
|
# Checks for typedefs, structures, and compiler characteristics.
|
||||||
|
AC_C_CONST
|
||||||
|
AC_C_INLINE
|
||||||
|
AC_HEADER_TIME
|
||||||
|
AC_CHECK_TYPE([nfds_t],
|
||||||
|
[AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[poll() second argument type])],
|
||||||
|
[AC_DEFINE([POLL_NFDS_TYPE],[unsigned int],[poll() second argument type])],
|
||||||
|
[#include <poll.h>])
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([whether to enable ipv6])
|
||||||
|
|
||||||
|
AC_TRY_RUN([ /* is AF_INET6 available? */
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
if (socket(AF_INET6, SOCK_STREAM, 0) < 0)
|
||||||
|
exit(1);
|
||||||
|
else
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
], AC_MSG_RESULT(yes)
|
||||||
|
ipv6=yes,
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
ipv6=no,
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
ipv6=no)
|
||||||
|
|
||||||
|
if test x"$ipv6" = xyes; then
|
||||||
|
USEIPV6="-DZOO_IPV6_ENABLED"
|
||||||
|
AC_SUBST(USEIPV6)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# use SOCK_CLOEXEC if available and wanted
|
||||||
|
AC_ARG_WITH([sock_cloexec],
|
||||||
|
[AS_HELP_STRING([--with-sock-cloexec],[build with SOCK_CLOEXEC flag set on the connections])],
|
||||||
|
[],[with_sock_cloexec=no])
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([whether SOCK_CLOEXEC is available])
|
||||||
|
|
||||||
|
AC_TRY_RUN([ /* is SOCK_CLOEXEC available ? */
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
#ifdef SOCK_CLOEXEC
|
||||||
|
exit(0);
|
||||||
|
#else
|
||||||
|
exit(1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
], AC_MSG_RESULT(yes)
|
||||||
|
has_sock_cloexec=yes,
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
has_sock_cloexec=no,
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
has_sock_cloexec=no)
|
||||||
|
|
||||||
|
if test "x$with_sock_cloexec" != xno && test "x$has_sock_cloexec" = xno; then
|
||||||
|
AC_MSG_WARN([cannot use SOCK_CLOEXEC -- SOCK_CLOEXEC undefined on this platform])
|
||||||
|
with_sock_cloexec=no
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$with_sock_cloexec" != xno; then
|
||||||
|
AC_MSG_NOTICE([building with SOCK_CLOEXEC])
|
||||||
|
else
|
||||||
|
AC_MSG_NOTICE([building without SOCK_CLOEXEC])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AS_IF([test x"$with_sock_cloexec" != xno], [AC_DEFINE([SOCK_CLOEXEC_ENABLED], [1], [Define to 1, if SOCK_CLOEXEC is defined and wanted])])
|
||||||
|
AM_CONDITIONAL([SOCK_CLOEXEC_ENABLED],[test "x$with_sock_cloexec" != xno])
|
||||||
|
|
||||||
|
# Determine which libraries we need to use clock_gettime
|
||||||
|
saved_LIBS="$LIBS"
|
||||||
|
LIBS=""
|
||||||
|
AC_CHECK_LIB(rt, clock_gettime)
|
||||||
|
CLOCK_GETTIME_LIBS=$LIBS
|
||||||
|
AC_SUBST(CLOCK_GETTIME_LIBS)
|
||||||
|
LIBS="$saved_LIBS"
|
||||||
|
|
||||||
|
# Checks for library functions.
|
||||||
|
AC_CHECK_FUNCS([getcwd gethostbyname gethostname getlogin getpwuid_r gettimeofday getuid memmove memset poll socket strchr strdup strerror strtol])
|
||||||
|
|
||||||
|
AC_CONFIG_FILES([Makefile])
|
||||||
|
AC_CANONICAL_HOST
|
||||||
|
AM_CONDITIONAL([SOLARIS],[
|
||||||
|
case "$host_os" in
|
||||||
|
*solaris*)
|
||||||
|
true
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
false
|
||||||
|
;;
|
||||||
|
esac ])
|
||||||
|
AC_OUTPUT
|
1622
zookeeper-client/zookeeper-client-c/generated/zookeeper.jute.c
Normal file
1622
zookeeper-client/zookeeper-client-c/generated/zookeeper.jute.c
Normal file
File diff suppressed because it is too large
Load Diff
595
zookeeper-client/zookeeper-client-c/generated/zookeeper.jute.h
Normal file
595
zookeeper-client/zookeeper-client-c/generated/zookeeper.jute.h
Normal file
@ -0,0 +1,595 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ZOOKEEPER_JUTE__
|
||||||
|
#define __ZOOKEEPER_JUTE__
|
||||||
|
#include "recordio.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct Id {
|
||||||
|
char * scheme;
|
||||||
|
char * id;
|
||||||
|
};
|
||||||
|
int serialize_Id(struct oarchive *out, const char *tag, struct Id *v);
|
||||||
|
int deserialize_Id(struct iarchive *in, const char *tag, struct Id*v);
|
||||||
|
void deallocate_Id(struct Id*);
|
||||||
|
struct ACL {
|
||||||
|
int32_t perms;
|
||||||
|
struct Id id;
|
||||||
|
};
|
||||||
|
int serialize_ACL(struct oarchive *out, const char *tag, struct ACL *v);
|
||||||
|
int deserialize_ACL(struct iarchive *in, const char *tag, struct ACL*v);
|
||||||
|
void deallocate_ACL(struct ACL*);
|
||||||
|
struct Stat {
|
||||||
|
int64_t czxid;
|
||||||
|
int64_t mzxid;
|
||||||
|
int64_t ctime;
|
||||||
|
int64_t mtime;
|
||||||
|
int32_t version;
|
||||||
|
int32_t cversion;
|
||||||
|
int32_t aversion;
|
||||||
|
int64_t ephemeralOwner;
|
||||||
|
int32_t dataLength;
|
||||||
|
int32_t numChildren;
|
||||||
|
int64_t pzxid;
|
||||||
|
};
|
||||||
|
int serialize_Stat(struct oarchive *out, const char *tag, struct Stat *v);
|
||||||
|
int deserialize_Stat(struct iarchive *in, const char *tag, struct Stat*v);
|
||||||
|
void deallocate_Stat(struct Stat*);
|
||||||
|
struct StatPersisted {
|
||||||
|
int64_t czxid;
|
||||||
|
int64_t mzxid;
|
||||||
|
int64_t ctime;
|
||||||
|
int64_t mtime;
|
||||||
|
int32_t version;
|
||||||
|
int32_t cversion;
|
||||||
|
int32_t aversion;
|
||||||
|
int64_t ephemeralOwner;
|
||||||
|
int64_t pzxid;
|
||||||
|
};
|
||||||
|
int serialize_StatPersisted(struct oarchive *out, const char *tag, struct StatPersisted *v);
|
||||||
|
int deserialize_StatPersisted(struct iarchive *in, const char *tag, struct StatPersisted*v);
|
||||||
|
void deallocate_StatPersisted(struct StatPersisted*);
|
||||||
|
struct ConnectRequest {
|
||||||
|
int32_t protocolVersion;
|
||||||
|
int64_t lastZxidSeen;
|
||||||
|
int32_t timeOut;
|
||||||
|
int64_t sessionId;
|
||||||
|
struct buffer passwd;
|
||||||
|
};
|
||||||
|
int serialize_ConnectRequest(struct oarchive *out, const char *tag, struct ConnectRequest *v);
|
||||||
|
int deserialize_ConnectRequest(struct iarchive *in, const char *tag, struct ConnectRequest*v);
|
||||||
|
void deallocate_ConnectRequest(struct ConnectRequest*);
|
||||||
|
struct ConnectResponse {
|
||||||
|
int32_t protocolVersion;
|
||||||
|
int32_t timeOut;
|
||||||
|
int64_t sessionId;
|
||||||
|
struct buffer passwd;
|
||||||
|
};
|
||||||
|
int serialize_ConnectResponse(struct oarchive *out, const char *tag, struct ConnectResponse *v);
|
||||||
|
int deserialize_ConnectResponse(struct iarchive *in, const char *tag, struct ConnectResponse*v);
|
||||||
|
void deallocate_ConnectResponse(struct ConnectResponse*);
|
||||||
|
struct String_vector {
|
||||||
|
int32_t count;
|
||||||
|
char * *data;
|
||||||
|
|
||||||
|
};
|
||||||
|
int serialize_String_vector(struct oarchive *out, const char *tag, struct String_vector *v);
|
||||||
|
int deserialize_String_vector(struct iarchive *in, const char *tag, struct String_vector *v);
|
||||||
|
int allocate_String_vector(struct String_vector *v, int32_t len);
|
||||||
|
int deallocate_String_vector(struct String_vector *v);
|
||||||
|
struct SetWatches {
|
||||||
|
int64_t relativeZxid;
|
||||||
|
struct String_vector dataWatches;
|
||||||
|
struct String_vector existWatches;
|
||||||
|
struct String_vector childWatches;
|
||||||
|
};
|
||||||
|
int serialize_SetWatches(struct oarchive *out, const char *tag, struct SetWatches *v);
|
||||||
|
int deserialize_SetWatches(struct iarchive *in, const char *tag, struct SetWatches*v);
|
||||||
|
void deallocate_SetWatches(struct SetWatches*);
|
||||||
|
struct SetWatches2 {
|
||||||
|
int64_t relativeZxid;
|
||||||
|
struct String_vector dataWatches;
|
||||||
|
struct String_vector existWatches;
|
||||||
|
struct String_vector childWatches;
|
||||||
|
struct String_vector persistentWatches;
|
||||||
|
struct String_vector persistentRecursiveWatches;
|
||||||
|
};
|
||||||
|
int serialize_SetWatches2(struct oarchive *out, const char *tag, struct SetWatches2 *v);
|
||||||
|
int deserialize_SetWatches2(struct iarchive *in, const char *tag, struct SetWatches2*v);
|
||||||
|
void deallocate_SetWatches2(struct SetWatches2*);
|
||||||
|
struct RequestHeader {
|
||||||
|
int32_t xid;
|
||||||
|
int32_t type;
|
||||||
|
};
|
||||||
|
int serialize_RequestHeader(struct oarchive *out, const char *tag, struct RequestHeader *v);
|
||||||
|
int deserialize_RequestHeader(struct iarchive *in, const char *tag, struct RequestHeader*v);
|
||||||
|
void deallocate_RequestHeader(struct RequestHeader*);
|
||||||
|
struct MultiHeader {
|
||||||
|
int32_t type;
|
||||||
|
int32_t done;
|
||||||
|
int32_t err;
|
||||||
|
};
|
||||||
|
int serialize_MultiHeader(struct oarchive *out, const char *tag, struct MultiHeader *v);
|
||||||
|
int deserialize_MultiHeader(struct iarchive *in, const char *tag, struct MultiHeader*v);
|
||||||
|
void deallocate_MultiHeader(struct MultiHeader*);
|
||||||
|
struct AuthPacket {
|
||||||
|
int32_t type;
|
||||||
|
char * scheme;
|
||||||
|
struct buffer auth;
|
||||||
|
};
|
||||||
|
int serialize_AuthPacket(struct oarchive *out, const char *tag, struct AuthPacket *v);
|
||||||
|
int deserialize_AuthPacket(struct iarchive *in, const char *tag, struct AuthPacket*v);
|
||||||
|
void deallocate_AuthPacket(struct AuthPacket*);
|
||||||
|
struct ReplyHeader {
|
||||||
|
int32_t xid;
|
||||||
|
int64_t zxid;
|
||||||
|
int32_t err;
|
||||||
|
};
|
||||||
|
int serialize_ReplyHeader(struct oarchive *out, const char *tag, struct ReplyHeader *v);
|
||||||
|
int deserialize_ReplyHeader(struct iarchive *in, const char *tag, struct ReplyHeader*v);
|
||||||
|
void deallocate_ReplyHeader(struct ReplyHeader*);
|
||||||
|
struct GetDataRequest {
|
||||||
|
char * path;
|
||||||
|
int32_t watch;
|
||||||
|
};
|
||||||
|
int serialize_GetDataRequest(struct oarchive *out, const char *tag, struct GetDataRequest *v);
|
||||||
|
int deserialize_GetDataRequest(struct iarchive *in, const char *tag, struct GetDataRequest*v);
|
||||||
|
void deallocate_GetDataRequest(struct GetDataRequest*);
|
||||||
|
struct SetDataRequest {
|
||||||
|
char * path;
|
||||||
|
struct buffer data;
|
||||||
|
int32_t version;
|
||||||
|
};
|
||||||
|
int serialize_SetDataRequest(struct oarchive *out, const char *tag, struct SetDataRequest *v);
|
||||||
|
int deserialize_SetDataRequest(struct iarchive *in, const char *tag, struct SetDataRequest*v);
|
||||||
|
void deallocate_SetDataRequest(struct SetDataRequest*);
|
||||||
|
struct ReconfigRequest {
|
||||||
|
char * joiningServers;
|
||||||
|
char * leavingServers;
|
||||||
|
char * newMembers;
|
||||||
|
int64_t curConfigId;
|
||||||
|
};
|
||||||
|
int serialize_ReconfigRequest(struct oarchive *out, const char *tag, struct ReconfigRequest *v);
|
||||||
|
int deserialize_ReconfigRequest(struct iarchive *in, const char *tag, struct ReconfigRequest*v);
|
||||||
|
void deallocate_ReconfigRequest(struct ReconfigRequest*);
|
||||||
|
struct SetDataResponse {
|
||||||
|
struct Stat stat;
|
||||||
|
};
|
||||||
|
int serialize_SetDataResponse(struct oarchive *out, const char *tag, struct SetDataResponse *v);
|
||||||
|
int deserialize_SetDataResponse(struct iarchive *in, const char *tag, struct SetDataResponse*v);
|
||||||
|
void deallocate_SetDataResponse(struct SetDataResponse*);
|
||||||
|
struct GetSASLRequest {
|
||||||
|
struct buffer token;
|
||||||
|
};
|
||||||
|
int serialize_GetSASLRequest(struct oarchive *out, const char *tag, struct GetSASLRequest *v);
|
||||||
|
int deserialize_GetSASLRequest(struct iarchive *in, const char *tag, struct GetSASLRequest*v);
|
||||||
|
void deallocate_GetSASLRequest(struct GetSASLRequest*);
|
||||||
|
struct SetSASLRequest {
|
||||||
|
struct buffer token;
|
||||||
|
};
|
||||||
|
int serialize_SetSASLRequest(struct oarchive *out, const char *tag, struct SetSASLRequest *v);
|
||||||
|
int deserialize_SetSASLRequest(struct iarchive *in, const char *tag, struct SetSASLRequest*v);
|
||||||
|
void deallocate_SetSASLRequest(struct SetSASLRequest*);
|
||||||
|
struct SetSASLResponse {
|
||||||
|
struct buffer token;
|
||||||
|
};
|
||||||
|
int serialize_SetSASLResponse(struct oarchive *out, const char *tag, struct SetSASLResponse *v);
|
||||||
|
int deserialize_SetSASLResponse(struct iarchive *in, const char *tag, struct SetSASLResponse*v);
|
||||||
|
void deallocate_SetSASLResponse(struct SetSASLResponse*);
|
||||||
|
struct ACL_vector {
|
||||||
|
int32_t count;
|
||||||
|
struct ACL *data;
|
||||||
|
|
||||||
|
};
|
||||||
|
int serialize_ACL_vector(struct oarchive *out, const char *tag, struct ACL_vector *v);
|
||||||
|
int deserialize_ACL_vector(struct iarchive *in, const char *tag, struct ACL_vector *v);
|
||||||
|
int allocate_ACL_vector(struct ACL_vector *v, int32_t len);
|
||||||
|
int deallocate_ACL_vector(struct ACL_vector *v);
|
||||||
|
struct CreateRequest {
|
||||||
|
char * path;
|
||||||
|
struct buffer data;
|
||||||
|
struct ACL_vector acl;
|
||||||
|
int32_t flags;
|
||||||
|
};
|
||||||
|
int serialize_CreateRequest(struct oarchive *out, const char *tag, struct CreateRequest *v);
|
||||||
|
int deserialize_CreateRequest(struct iarchive *in, const char *tag, struct CreateRequest*v);
|
||||||
|
void deallocate_CreateRequest(struct CreateRequest*);
|
||||||
|
struct CreateTTLRequest {
|
||||||
|
char * path;
|
||||||
|
struct buffer data;
|
||||||
|
struct ACL_vector acl;
|
||||||
|
int32_t flags;
|
||||||
|
int64_t ttl;
|
||||||
|
};
|
||||||
|
int serialize_CreateTTLRequest(struct oarchive *out, const char *tag, struct CreateTTLRequest *v);
|
||||||
|
int deserialize_CreateTTLRequest(struct iarchive *in, const char *tag, struct CreateTTLRequest*v);
|
||||||
|
void deallocate_CreateTTLRequest(struct CreateTTLRequest*);
|
||||||
|
struct DeleteRequest {
|
||||||
|
char * path;
|
||||||
|
int32_t version;
|
||||||
|
};
|
||||||
|
int serialize_DeleteRequest(struct oarchive *out, const char *tag, struct DeleteRequest *v);
|
||||||
|
int deserialize_DeleteRequest(struct iarchive *in, const char *tag, struct DeleteRequest*v);
|
||||||
|
void deallocate_DeleteRequest(struct DeleteRequest*);
|
||||||
|
struct GetChildrenRequest {
|
||||||
|
char * path;
|
||||||
|
int32_t watch;
|
||||||
|
};
|
||||||
|
int serialize_GetChildrenRequest(struct oarchive *out, const char *tag, struct GetChildrenRequest *v);
|
||||||
|
int deserialize_GetChildrenRequest(struct iarchive *in, const char *tag, struct GetChildrenRequest*v);
|
||||||
|
void deallocate_GetChildrenRequest(struct GetChildrenRequest*);
|
||||||
|
struct GetAllChildrenNumberRequest {
|
||||||
|
char * path;
|
||||||
|
};
|
||||||
|
int serialize_GetAllChildrenNumberRequest(struct oarchive *out, const char *tag, struct GetAllChildrenNumberRequest *v);
|
||||||
|
int deserialize_GetAllChildrenNumberRequest(struct iarchive *in, const char *tag, struct GetAllChildrenNumberRequest*v);
|
||||||
|
void deallocate_GetAllChildrenNumberRequest(struct GetAllChildrenNumberRequest*);
|
||||||
|
struct GetChildren2Request {
|
||||||
|
char * path;
|
||||||
|
int32_t watch;
|
||||||
|
};
|
||||||
|
int serialize_GetChildren2Request(struct oarchive *out, const char *tag, struct GetChildren2Request *v);
|
||||||
|
int deserialize_GetChildren2Request(struct iarchive *in, const char *tag, struct GetChildren2Request*v);
|
||||||
|
void deallocate_GetChildren2Request(struct GetChildren2Request*);
|
||||||
|
struct CheckVersionRequest {
|
||||||
|
char * path;
|
||||||
|
int32_t version;
|
||||||
|
};
|
||||||
|
int serialize_CheckVersionRequest(struct oarchive *out, const char *tag, struct CheckVersionRequest *v);
|
||||||
|
int deserialize_CheckVersionRequest(struct iarchive *in, const char *tag, struct CheckVersionRequest*v);
|
||||||
|
void deallocate_CheckVersionRequest(struct CheckVersionRequest*);
|
||||||
|
struct GetMaxChildrenRequest {
|
||||||
|
char * path;
|
||||||
|
};
|
||||||
|
int serialize_GetMaxChildrenRequest(struct oarchive *out, const char *tag, struct GetMaxChildrenRequest *v);
|
||||||
|
int deserialize_GetMaxChildrenRequest(struct iarchive *in, const char *tag, struct GetMaxChildrenRequest*v);
|
||||||
|
void deallocate_GetMaxChildrenRequest(struct GetMaxChildrenRequest*);
|
||||||
|
struct GetMaxChildrenResponse {
|
||||||
|
int32_t max;
|
||||||
|
};
|
||||||
|
int serialize_GetMaxChildrenResponse(struct oarchive *out, const char *tag, struct GetMaxChildrenResponse *v);
|
||||||
|
int deserialize_GetMaxChildrenResponse(struct iarchive *in, const char *tag, struct GetMaxChildrenResponse*v);
|
||||||
|
void deallocate_GetMaxChildrenResponse(struct GetMaxChildrenResponse*);
|
||||||
|
struct SetMaxChildrenRequest {
|
||||||
|
char * path;
|
||||||
|
int32_t max;
|
||||||
|
};
|
||||||
|
int serialize_SetMaxChildrenRequest(struct oarchive *out, const char *tag, struct SetMaxChildrenRequest *v);
|
||||||
|
int deserialize_SetMaxChildrenRequest(struct iarchive *in, const char *tag, struct SetMaxChildrenRequest*v);
|
||||||
|
void deallocate_SetMaxChildrenRequest(struct SetMaxChildrenRequest*);
|
||||||
|
struct SyncRequest {
|
||||||
|
char * path;
|
||||||
|
};
|
||||||
|
int serialize_SyncRequest(struct oarchive *out, const char *tag, struct SyncRequest *v);
|
||||||
|
int deserialize_SyncRequest(struct iarchive *in, const char *tag, struct SyncRequest*v);
|
||||||
|
void deallocate_SyncRequest(struct SyncRequest*);
|
||||||
|
struct SyncResponse {
|
||||||
|
char * path;
|
||||||
|
};
|
||||||
|
int serialize_SyncResponse(struct oarchive *out, const char *tag, struct SyncResponse *v);
|
||||||
|
int deserialize_SyncResponse(struct iarchive *in, const char *tag, struct SyncResponse*v);
|
||||||
|
void deallocate_SyncResponse(struct SyncResponse*);
|
||||||
|
struct GetACLRequest {
|
||||||
|
char * path;
|
||||||
|
};
|
||||||
|
int serialize_GetACLRequest(struct oarchive *out, const char *tag, struct GetACLRequest *v);
|
||||||
|
int deserialize_GetACLRequest(struct iarchive *in, const char *tag, struct GetACLRequest*v);
|
||||||
|
void deallocate_GetACLRequest(struct GetACLRequest*);
|
||||||
|
struct SetACLRequest {
|
||||||
|
char * path;
|
||||||
|
struct ACL_vector acl;
|
||||||
|
int32_t version;
|
||||||
|
};
|
||||||
|
int serialize_SetACLRequest(struct oarchive *out, const char *tag, struct SetACLRequest *v);
|
||||||
|
int deserialize_SetACLRequest(struct iarchive *in, const char *tag, struct SetACLRequest*v);
|
||||||
|
void deallocate_SetACLRequest(struct SetACLRequest*);
|
||||||
|
struct SetACLResponse {
|
||||||
|
struct Stat stat;
|
||||||
|
};
|
||||||
|
int serialize_SetACLResponse(struct oarchive *out, const char *tag, struct SetACLResponse *v);
|
||||||
|
int deserialize_SetACLResponse(struct iarchive *in, const char *tag, struct SetACLResponse*v);
|
||||||
|
void deallocate_SetACLResponse(struct SetACLResponse*);
|
||||||
|
struct AddWatchRequest {
|
||||||
|
char * path;
|
||||||
|
int32_t mode;
|
||||||
|
};
|
||||||
|
int serialize_AddWatchRequest(struct oarchive *out, const char *tag, struct AddWatchRequest *v);
|
||||||
|
int deserialize_AddWatchRequest(struct iarchive *in, const char *tag, struct AddWatchRequest*v);
|
||||||
|
void deallocate_AddWatchRequest(struct AddWatchRequest*);
|
||||||
|
struct WatcherEvent {
|
||||||
|
int32_t type;
|
||||||
|
int32_t state;
|
||||||
|
char * path;
|
||||||
|
};
|
||||||
|
int serialize_WatcherEvent(struct oarchive *out, const char *tag, struct WatcherEvent *v);
|
||||||
|
int deserialize_WatcherEvent(struct iarchive *in, const char *tag, struct WatcherEvent*v);
|
||||||
|
void deallocate_WatcherEvent(struct WatcherEvent*);
|
||||||
|
struct ErrorResponse {
|
||||||
|
int32_t err;
|
||||||
|
};
|
||||||
|
int serialize_ErrorResponse(struct oarchive *out, const char *tag, struct ErrorResponse *v);
|
||||||
|
int deserialize_ErrorResponse(struct iarchive *in, const char *tag, struct ErrorResponse*v);
|
||||||
|
void deallocate_ErrorResponse(struct ErrorResponse*);
|
||||||
|
struct CreateResponse {
|
||||||
|
char * path;
|
||||||
|
};
|
||||||
|
int serialize_CreateResponse(struct oarchive *out, const char *tag, struct CreateResponse *v);
|
||||||
|
int deserialize_CreateResponse(struct iarchive *in, const char *tag, struct CreateResponse*v);
|
||||||
|
void deallocate_CreateResponse(struct CreateResponse*);
|
||||||
|
struct Create2Response {
|
||||||
|
char * path;
|
||||||
|
struct Stat stat;
|
||||||
|
};
|
||||||
|
int serialize_Create2Response(struct oarchive *out, const char *tag, struct Create2Response *v);
|
||||||
|
int deserialize_Create2Response(struct iarchive *in, const char *tag, struct Create2Response*v);
|
||||||
|
void deallocate_Create2Response(struct Create2Response*);
|
||||||
|
struct ExistsRequest {
|
||||||
|
char * path;
|
||||||
|
int32_t watch;
|
||||||
|
};
|
||||||
|
int serialize_ExistsRequest(struct oarchive *out, const char *tag, struct ExistsRequest *v);
|
||||||
|
int deserialize_ExistsRequest(struct iarchive *in, const char *tag, struct ExistsRequest*v);
|
||||||
|
void deallocate_ExistsRequest(struct ExistsRequest*);
|
||||||
|
struct ExistsResponse {
|
||||||
|
struct Stat stat;
|
||||||
|
};
|
||||||
|
int serialize_ExistsResponse(struct oarchive *out, const char *tag, struct ExistsResponse *v);
|
||||||
|
int deserialize_ExistsResponse(struct iarchive *in, const char *tag, struct ExistsResponse*v);
|
||||||
|
void deallocate_ExistsResponse(struct ExistsResponse*);
|
||||||
|
struct GetDataResponse {
|
||||||
|
struct buffer data;
|
||||||
|
struct Stat stat;
|
||||||
|
};
|
||||||
|
int serialize_GetDataResponse(struct oarchive *out, const char *tag, struct GetDataResponse *v);
|
||||||
|
int deserialize_GetDataResponse(struct iarchive *in, const char *tag, struct GetDataResponse*v);
|
||||||
|
void deallocate_GetDataResponse(struct GetDataResponse*);
|
||||||
|
struct GetChildrenResponse {
|
||||||
|
struct String_vector children;
|
||||||
|
};
|
||||||
|
int serialize_GetChildrenResponse(struct oarchive *out, const char *tag, struct GetChildrenResponse *v);
|
||||||
|
int deserialize_GetChildrenResponse(struct iarchive *in, const char *tag, struct GetChildrenResponse*v);
|
||||||
|
void deallocate_GetChildrenResponse(struct GetChildrenResponse*);
|
||||||
|
struct GetAllChildrenNumberResponse {
|
||||||
|
int32_t totalNumber;
|
||||||
|
};
|
||||||
|
int serialize_GetAllChildrenNumberResponse(struct oarchive *out, const char *tag, struct GetAllChildrenNumberResponse *v);
|
||||||
|
int deserialize_GetAllChildrenNumberResponse(struct iarchive *in, const char *tag, struct GetAllChildrenNumberResponse*v);
|
||||||
|
void deallocate_GetAllChildrenNumberResponse(struct GetAllChildrenNumberResponse*);
|
||||||
|
struct GetChildren2Response {
|
||||||
|
struct String_vector children;
|
||||||
|
struct Stat stat;
|
||||||
|
};
|
||||||
|
int serialize_GetChildren2Response(struct oarchive *out, const char *tag, struct GetChildren2Response *v);
|
||||||
|
int deserialize_GetChildren2Response(struct iarchive *in, const char *tag, struct GetChildren2Response*v);
|
||||||
|
void deallocate_GetChildren2Response(struct GetChildren2Response*);
|
||||||
|
struct GetACLResponse {
|
||||||
|
struct ACL_vector acl;
|
||||||
|
struct Stat stat;
|
||||||
|
};
|
||||||
|
int serialize_GetACLResponse(struct oarchive *out, const char *tag, struct GetACLResponse *v);
|
||||||
|
int deserialize_GetACLResponse(struct iarchive *in, const char *tag, struct GetACLResponse*v);
|
||||||
|
void deallocate_GetACLResponse(struct GetACLResponse*);
|
||||||
|
struct CheckWatchesRequest {
|
||||||
|
char * path;
|
||||||
|
int32_t type;
|
||||||
|
};
|
||||||
|
int serialize_CheckWatchesRequest(struct oarchive *out, const char *tag, struct CheckWatchesRequest *v);
|
||||||
|
int deserialize_CheckWatchesRequest(struct iarchive *in, const char *tag, struct CheckWatchesRequest*v);
|
||||||
|
void deallocate_CheckWatchesRequest(struct CheckWatchesRequest*);
|
||||||
|
struct RemoveWatchesRequest {
|
||||||
|
char * path;
|
||||||
|
int32_t type;
|
||||||
|
};
|
||||||
|
int serialize_RemoveWatchesRequest(struct oarchive *out, const char *tag, struct RemoveWatchesRequest *v);
|
||||||
|
int deserialize_RemoveWatchesRequest(struct iarchive *in, const char *tag, struct RemoveWatchesRequest*v);
|
||||||
|
void deallocate_RemoveWatchesRequest(struct RemoveWatchesRequest*);
|
||||||
|
struct GetEphemeralsRequest {
|
||||||
|
char * prefixPath;
|
||||||
|
};
|
||||||
|
int serialize_GetEphemeralsRequest(struct oarchive *out, const char *tag, struct GetEphemeralsRequest *v);
|
||||||
|
int deserialize_GetEphemeralsRequest(struct iarchive *in, const char *tag, struct GetEphemeralsRequest*v);
|
||||||
|
void deallocate_GetEphemeralsRequest(struct GetEphemeralsRequest*);
|
||||||
|
struct GetEphemeralsResponse {
|
||||||
|
struct String_vector ephemerals;
|
||||||
|
};
|
||||||
|
int serialize_GetEphemeralsResponse(struct oarchive *out, const char *tag, struct GetEphemeralsResponse *v);
|
||||||
|
int deserialize_GetEphemeralsResponse(struct iarchive *in, const char *tag, struct GetEphemeralsResponse*v);
|
||||||
|
void deallocate_GetEphemeralsResponse(struct GetEphemeralsResponse*);
|
||||||
|
struct LearnerInfo {
|
||||||
|
int64_t serverid;
|
||||||
|
int32_t protocolVersion;
|
||||||
|
int64_t configVersion;
|
||||||
|
};
|
||||||
|
int serialize_LearnerInfo(struct oarchive *out, const char *tag, struct LearnerInfo *v);
|
||||||
|
int deserialize_LearnerInfo(struct iarchive *in, const char *tag, struct LearnerInfo*v);
|
||||||
|
void deallocate_LearnerInfo(struct LearnerInfo*);
|
||||||
|
struct Id_vector {
|
||||||
|
int32_t count;
|
||||||
|
struct Id *data;
|
||||||
|
|
||||||
|
};
|
||||||
|
int serialize_Id_vector(struct oarchive *out, const char *tag, struct Id_vector *v);
|
||||||
|
int deserialize_Id_vector(struct iarchive *in, const char *tag, struct Id_vector *v);
|
||||||
|
int allocate_Id_vector(struct Id_vector *v, int32_t len);
|
||||||
|
int deallocate_Id_vector(struct Id_vector *v);
|
||||||
|
struct QuorumPacket {
|
||||||
|
int32_t type;
|
||||||
|
int64_t zxid;
|
||||||
|
struct buffer data;
|
||||||
|
struct Id_vector authinfo;
|
||||||
|
};
|
||||||
|
int serialize_QuorumPacket(struct oarchive *out, const char *tag, struct QuorumPacket *v);
|
||||||
|
int deserialize_QuorumPacket(struct iarchive *in, const char *tag, struct QuorumPacket*v);
|
||||||
|
void deallocate_QuorumPacket(struct QuorumPacket*);
|
||||||
|
struct QuorumAuthPacket {
|
||||||
|
int64_t magic;
|
||||||
|
int32_t status;
|
||||||
|
struct buffer token;
|
||||||
|
};
|
||||||
|
int serialize_QuorumAuthPacket(struct oarchive *out, const char *tag, struct QuorumAuthPacket *v);
|
||||||
|
int deserialize_QuorumAuthPacket(struct iarchive *in, const char *tag, struct QuorumAuthPacket*v);
|
||||||
|
void deallocate_QuorumAuthPacket(struct QuorumAuthPacket*);
|
||||||
|
struct FileHeader {
|
||||||
|
int32_t magic;
|
||||||
|
int32_t version;
|
||||||
|
int64_t dbid;
|
||||||
|
};
|
||||||
|
int serialize_FileHeader(struct oarchive *out, const char *tag, struct FileHeader *v);
|
||||||
|
int deserialize_FileHeader(struct iarchive *in, const char *tag, struct FileHeader*v);
|
||||||
|
void deallocate_FileHeader(struct FileHeader*);
|
||||||
|
struct TxnDigest {
|
||||||
|
int32_t version;
|
||||||
|
int64_t treeDigest;
|
||||||
|
};
|
||||||
|
int serialize_TxnDigest(struct oarchive *out, const char *tag, struct TxnDigest *v);
|
||||||
|
int deserialize_TxnDigest(struct iarchive *in, const char *tag, struct TxnDigest*v);
|
||||||
|
void deallocate_TxnDigest(struct TxnDigest*);
|
||||||
|
struct TxnHeader {
|
||||||
|
int64_t clientId;
|
||||||
|
int32_t cxid;
|
||||||
|
int64_t zxid;
|
||||||
|
int64_t time;
|
||||||
|
int32_t type;
|
||||||
|
};
|
||||||
|
int serialize_TxnHeader(struct oarchive *out, const char *tag, struct TxnHeader *v);
|
||||||
|
int deserialize_TxnHeader(struct iarchive *in, const char *tag, struct TxnHeader*v);
|
||||||
|
void deallocate_TxnHeader(struct TxnHeader*);
|
||||||
|
struct CreateTxnV0 {
|
||||||
|
char * path;
|
||||||
|
struct buffer data;
|
||||||
|
struct ACL_vector acl;
|
||||||
|
int32_t ephemeral;
|
||||||
|
};
|
||||||
|
int serialize_CreateTxnV0(struct oarchive *out, const char *tag, struct CreateTxnV0 *v);
|
||||||
|
int deserialize_CreateTxnV0(struct iarchive *in, const char *tag, struct CreateTxnV0*v);
|
||||||
|
void deallocate_CreateTxnV0(struct CreateTxnV0*);
|
||||||
|
struct CreateTxn {
|
||||||
|
char * path;
|
||||||
|
struct buffer data;
|
||||||
|
struct ACL_vector acl;
|
||||||
|
int32_t ephemeral;
|
||||||
|
int32_t parentCVersion;
|
||||||
|
};
|
||||||
|
int serialize_CreateTxn(struct oarchive *out, const char *tag, struct CreateTxn *v);
|
||||||
|
int deserialize_CreateTxn(struct iarchive *in, const char *tag, struct CreateTxn*v);
|
||||||
|
void deallocate_CreateTxn(struct CreateTxn*);
|
||||||
|
struct CreateTTLTxn {
|
||||||
|
char * path;
|
||||||
|
struct buffer data;
|
||||||
|
struct ACL_vector acl;
|
||||||
|
int32_t parentCVersion;
|
||||||
|
int64_t ttl;
|
||||||
|
};
|
||||||
|
int serialize_CreateTTLTxn(struct oarchive *out, const char *tag, struct CreateTTLTxn *v);
|
||||||
|
int deserialize_CreateTTLTxn(struct iarchive *in, const char *tag, struct CreateTTLTxn*v);
|
||||||
|
void deallocate_CreateTTLTxn(struct CreateTTLTxn*);
|
||||||
|
struct CreateContainerTxn {
|
||||||
|
char * path;
|
||||||
|
struct buffer data;
|
||||||
|
struct ACL_vector acl;
|
||||||
|
int32_t parentCVersion;
|
||||||
|
};
|
||||||
|
int serialize_CreateContainerTxn(struct oarchive *out, const char *tag, struct CreateContainerTxn *v);
|
||||||
|
int deserialize_CreateContainerTxn(struct iarchive *in, const char *tag, struct CreateContainerTxn*v);
|
||||||
|
void deallocate_CreateContainerTxn(struct CreateContainerTxn*);
|
||||||
|
struct DeleteTxn {
|
||||||
|
char * path;
|
||||||
|
};
|
||||||
|
int serialize_DeleteTxn(struct oarchive *out, const char *tag, struct DeleteTxn *v);
|
||||||
|
int deserialize_DeleteTxn(struct iarchive *in, const char *tag, struct DeleteTxn*v);
|
||||||
|
void deallocate_DeleteTxn(struct DeleteTxn*);
|
||||||
|
struct SetDataTxn {
|
||||||
|
char * path;
|
||||||
|
struct buffer data;
|
||||||
|
int32_t version;
|
||||||
|
};
|
||||||
|
int serialize_SetDataTxn(struct oarchive *out, const char *tag, struct SetDataTxn *v);
|
||||||
|
int deserialize_SetDataTxn(struct iarchive *in, const char *tag, struct SetDataTxn*v);
|
||||||
|
void deallocate_SetDataTxn(struct SetDataTxn*);
|
||||||
|
struct CheckVersionTxn {
|
||||||
|
char * path;
|
||||||
|
int32_t version;
|
||||||
|
};
|
||||||
|
int serialize_CheckVersionTxn(struct oarchive *out, const char *tag, struct CheckVersionTxn *v);
|
||||||
|
int deserialize_CheckVersionTxn(struct iarchive *in, const char *tag, struct CheckVersionTxn*v);
|
||||||
|
void deallocate_CheckVersionTxn(struct CheckVersionTxn*);
|
||||||
|
struct SetACLTxn {
|
||||||
|
char * path;
|
||||||
|
struct ACL_vector acl;
|
||||||
|
int32_t version;
|
||||||
|
};
|
||||||
|
int serialize_SetACLTxn(struct oarchive *out, const char *tag, struct SetACLTxn *v);
|
||||||
|
int deserialize_SetACLTxn(struct iarchive *in, const char *tag, struct SetACLTxn*v);
|
||||||
|
void deallocate_SetACLTxn(struct SetACLTxn*);
|
||||||
|
struct SetMaxChildrenTxn {
|
||||||
|
char * path;
|
||||||
|
int32_t max;
|
||||||
|
};
|
||||||
|
int serialize_SetMaxChildrenTxn(struct oarchive *out, const char *tag, struct SetMaxChildrenTxn *v);
|
||||||
|
int deserialize_SetMaxChildrenTxn(struct iarchive *in, const char *tag, struct SetMaxChildrenTxn*v);
|
||||||
|
void deallocate_SetMaxChildrenTxn(struct SetMaxChildrenTxn*);
|
||||||
|
struct CreateSessionTxn {
|
||||||
|
int32_t timeOut;
|
||||||
|
};
|
||||||
|
int serialize_CreateSessionTxn(struct oarchive *out, const char *tag, struct CreateSessionTxn *v);
|
||||||
|
int deserialize_CreateSessionTxn(struct iarchive *in, const char *tag, struct CreateSessionTxn*v);
|
||||||
|
void deallocate_CreateSessionTxn(struct CreateSessionTxn*);
|
||||||
|
struct CloseSessionTxn {
|
||||||
|
struct String_vector paths2Delete;
|
||||||
|
};
|
||||||
|
int serialize_CloseSessionTxn(struct oarchive *out, const char *tag, struct CloseSessionTxn *v);
|
||||||
|
int deserialize_CloseSessionTxn(struct iarchive *in, const char *tag, struct CloseSessionTxn*v);
|
||||||
|
void deallocate_CloseSessionTxn(struct CloseSessionTxn*);
|
||||||
|
struct ErrorTxn {
|
||||||
|
int32_t err;
|
||||||
|
};
|
||||||
|
int serialize_ErrorTxn(struct oarchive *out, const char *tag, struct ErrorTxn *v);
|
||||||
|
int deserialize_ErrorTxn(struct iarchive *in, const char *tag, struct ErrorTxn*v);
|
||||||
|
void deallocate_ErrorTxn(struct ErrorTxn*);
|
||||||
|
struct Txn {
|
||||||
|
int32_t type;
|
||||||
|
struct buffer data;
|
||||||
|
};
|
||||||
|
int serialize_Txn(struct oarchive *out, const char *tag, struct Txn *v);
|
||||||
|
int deserialize_Txn(struct iarchive *in, const char *tag, struct Txn*v);
|
||||||
|
void deallocate_Txn(struct Txn*);
|
||||||
|
struct Txn_vector {
|
||||||
|
int32_t count;
|
||||||
|
struct Txn *data;
|
||||||
|
|
||||||
|
};
|
||||||
|
int serialize_Txn_vector(struct oarchive *out, const char *tag, struct Txn_vector *v);
|
||||||
|
int deserialize_Txn_vector(struct iarchive *in, const char *tag, struct Txn_vector *v);
|
||||||
|
int allocate_Txn_vector(struct Txn_vector *v, int32_t len);
|
||||||
|
int deallocate_Txn_vector(struct Txn_vector *v);
|
||||||
|
struct MultiTxn {
|
||||||
|
struct Txn_vector txns;
|
||||||
|
};
|
||||||
|
int serialize_MultiTxn(struct oarchive *out, const char *tag, struct MultiTxn *v);
|
||||||
|
int deserialize_MultiTxn(struct iarchive *in, const char *tag, struct MultiTxn*v);
|
||||||
|
void deallocate_MultiTxn(struct MultiTxn*);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif //ZOOKEEPER_JUTE__
|
54
zookeeper-client/zookeeper-client-c/include/proto.h
Normal file
54
zookeeper-client/zookeeper-client-c/include/proto.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#ifndef PROTO_H_
|
||||||
|
#define PROTO_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ZOO_NOTIFY_OP 0
|
||||||
|
#define ZOO_CREATE_OP 1
|
||||||
|
#define ZOO_DELETE_OP 2
|
||||||
|
#define ZOO_EXISTS_OP 3
|
||||||
|
#define ZOO_GETDATA_OP 4
|
||||||
|
#define ZOO_SETDATA_OP 5
|
||||||
|
#define ZOO_GETACL_OP 6
|
||||||
|
#define ZOO_SETACL_OP 7
|
||||||
|
#define ZOO_GETCHILDREN_OP 8
|
||||||
|
#define ZOO_SYNC_OP 9
|
||||||
|
#define ZOO_PING_OP 11
|
||||||
|
#define ZOO_GETCHILDREN2_OP 12
|
||||||
|
#define ZOO_CHECK_OP 13
|
||||||
|
#define ZOO_MULTI_OP 14
|
||||||
|
#define ZOO_CREATE2_OP 15
|
||||||
|
#define ZOO_RECONFIG_OP 16
|
||||||
|
#define ZOO_CHECK_WATCHES 17
|
||||||
|
#define ZOO_REMOVE_WATCHES 18
|
||||||
|
#define ZOO_CREATE_CONTAINER_OP 19
|
||||||
|
#define ZOO_DELETE_CONTAINER_OP 20
|
||||||
|
#define ZOO_CREATE_TTL_OP 21
|
||||||
|
#define ZOO_CLOSE_OP -11
|
||||||
|
#define ZOO_SETAUTH_OP 100
|
||||||
|
#define ZOO_SETWATCHES_OP 101
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*PROTO_H_*/
|
80
zookeeper-client/zookeeper-client-c/include/recordio.h
Normal file
80
zookeeper-client/zookeeper-client-c/include/recordio.h
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#ifndef __RECORDIO_H__
|
||||||
|
#define __RECORDIO_H__
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <stdint.h> /* for int64_t */
|
||||||
|
#ifdef WIN32
|
||||||
|
#include "winconfig.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct buffer {
|
||||||
|
int32_t len;
|
||||||
|
char *buff;
|
||||||
|
};
|
||||||
|
|
||||||
|
void deallocate_String(char **s);
|
||||||
|
void deallocate_Buffer(struct buffer *b);
|
||||||
|
void deallocate_vector(void *d);
|
||||||
|
struct iarchive {
|
||||||
|
int (*start_record)(struct iarchive *ia, const char *tag);
|
||||||
|
int (*end_record)(struct iarchive *ia, const char *tag);
|
||||||
|
int (*start_vector)(struct iarchive *ia, const char *tag, int32_t *count);
|
||||||
|
int (*end_vector)(struct iarchive *ia, const char *tag);
|
||||||
|
int (*deserialize_Bool)(struct iarchive *ia, const char *name, int32_t *);
|
||||||
|
int (*deserialize_Int)(struct iarchive *ia, const char *name, int32_t *);
|
||||||
|
int (*deserialize_Long)(struct iarchive *ia, const char *name, int64_t *);
|
||||||
|
int (*deserialize_Buffer)(struct iarchive *ia, const char *name,
|
||||||
|
struct buffer *);
|
||||||
|
int (*deserialize_String)(struct iarchive *ia, const char *name, char **);
|
||||||
|
void *priv;
|
||||||
|
};
|
||||||
|
struct oarchive {
|
||||||
|
int (*start_record)(struct oarchive *oa, const char *tag);
|
||||||
|
int (*end_record)(struct oarchive *oa, const char *tag);
|
||||||
|
int (*start_vector)(struct oarchive *oa, const char *tag, const int32_t *count);
|
||||||
|
int (*end_vector)(struct oarchive *oa, const char *tag);
|
||||||
|
int (*serialize_Bool)(struct oarchive *oa, const char *name, const int32_t *);
|
||||||
|
int (*serialize_Int)(struct oarchive *oa, const char *name, const int32_t *);
|
||||||
|
int (*serialize_Long)(struct oarchive *oa, const char *name,
|
||||||
|
const int64_t *);
|
||||||
|
int (*serialize_Buffer)(struct oarchive *oa, const char *name,
|
||||||
|
const struct buffer *);
|
||||||
|
int (*serialize_String)(struct oarchive *oa, const char *name, char **);
|
||||||
|
void *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct oarchive *create_buffer_oarchive(void);
|
||||||
|
void close_buffer_oarchive(struct oarchive **oa, int free_buffer);
|
||||||
|
struct iarchive *create_buffer_iarchive(char *buffer, int len);
|
||||||
|
void close_buffer_iarchive(struct iarchive **ia);
|
||||||
|
char *get_buffer(struct oarchive *);
|
||||||
|
int get_buffer_len(struct oarchive *);
|
||||||
|
|
||||||
|
int64_t zoo_htonll(int64_t v);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
674
zookeeper-client/zookeeper-client-c/include/win_getopt.h
Normal file
674
zookeeper-client/zookeeper-client-c/include/win_getopt.h
Normal file
@ -0,0 +1,674 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DISCLAIMER
|
||||||
|
* This file is part of the mingw-w64 runtime package.
|
||||||
|
*
|
||||||
|
* The mingw-w64 runtime package and its code is distributed in the hope that it
|
||||||
|
* will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR
|
||||||
|
* IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to
|
||||||
|
* warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* Sponsored in part by the Defense Advanced Research Projects
|
||||||
|
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||||
|
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
* by Dieter Baron and Thomas Klausner.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GETOPT_H__
|
||||||
|
|
||||||
|
#pragma warning(disable:4996);
|
||||||
|
|
||||||
|
#define __GETOPT_H__
|
||||||
|
|
||||||
|
/* All the headers include this file. */
|
||||||
|
#include <crtdefs.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */
|
||||||
|
|
||||||
|
#ifdef REPLACE_GETOPT
|
||||||
|
int opterr = 1; /* if error message should be printed */
|
||||||
|
int optind = 1; /* index into parent argv vector */
|
||||||
|
int optopt = '?'; /* character checked for validity */
|
||||||
|
#undef optreset /* see getopt.h */
|
||||||
|
#define optreset __mingw_optreset
|
||||||
|
int optreset; /* reset getopt */
|
||||||
|
char *optarg; /* argument associated with option */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//extern int optind; /* index of first non-option in argv */
|
||||||
|
//extern int optopt; /* single option character, as parsed */
|
||||||
|
//extern int opterr; /* flag to enable built-in diagnostics... */
|
||||||
|
// /* (user may set to zero, to suppress) */
|
||||||
|
//
|
||||||
|
//extern char *optarg; /* pointer to argument of current option */
|
||||||
|
|
||||||
|
#define PRINT_ERROR ((opterr) && (*options != ':'))
|
||||||
|
|
||||||
|
#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
|
||||||
|
#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
|
||||||
|
#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
|
||||||
|
|
||||||
|
/* return values */
|
||||||
|
#define BADCH (int)'?'
|
||||||
|
#define BADARG ((*options == ':') ? (int)':' : (int)'?')
|
||||||
|
#define INORDER (int)1
|
||||||
|
|
||||||
|
#ifndef __CYGWIN__
|
||||||
|
#define __progname __argv[0]
|
||||||
|
#else
|
||||||
|
extern char __declspec(dllimport) *__progname;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __CYGWIN__
|
||||||
|
static char EMSG[] = "";
|
||||||
|
#else
|
||||||
|
#define EMSG ""
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int getopt_internal(int, char * const *, const char *,
|
||||||
|
const struct option *, int *, int);
|
||||||
|
static int parse_long_options(char * const *, const char *,
|
||||||
|
const struct option *, int *, int);
|
||||||
|
static int gcd(int, int);
|
||||||
|
static void permute_args(int, int, int, char * const *);
|
||||||
|
|
||||||
|
static char *place = EMSG; /* option letter processing */
|
||||||
|
|
||||||
|
/* XXX: set optreset to 1 rather than these two */
|
||||||
|
static int nonopt_start = -1; /* first non option argument (for permute) */
|
||||||
|
static int nonopt_end = -1; /* first option after non options (for permute) */
|
||||||
|
|
||||||
|
/* Error messages */
|
||||||
|
static const char recargchar[] = "option requires an argument -- %c";
|
||||||
|
static const char recargstring[] = "option requires an argument -- %s";
|
||||||
|
static const char ambig[] = "ambiguous option -- %.*s";
|
||||||
|
static const char noarg[] = "option doesn't take an argument -- %.*s";
|
||||||
|
static const char illoptchar[] = "unknown option -- %c";
|
||||||
|
static const char illoptstring[] = "unknown option -- %s";
|
||||||
|
|
||||||
|
static void
|
||||||
|
_vwarnx(const char *fmt,va_list ap)
|
||||||
|
{
|
||||||
|
(void)fprintf(stderr,"%s: ",__progname);
|
||||||
|
if (fmt != NULL)
|
||||||
|
(void)vfprintf(stderr,fmt,ap);
|
||||||
|
(void)fprintf(stderr,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
warnx(const char *fmt,...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap,fmt);
|
||||||
|
_vwarnx(fmt,ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute the greatest common divisor of a and b.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
gcd(int a, int b)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
c = a % b;
|
||||||
|
while (c != 0) {
|
||||||
|
a = b;
|
||||||
|
b = c;
|
||||||
|
c = a % b;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exchange the block from nonopt_start to nonopt_end with the block
|
||||||
|
* from nonopt_end to opt_end (keeping the same order of arguments
|
||||||
|
* in each block).
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
permute_args(int panonopt_start, int panonopt_end, int opt_end,
|
||||||
|
char * const *nargv)
|
||||||
|
{
|
||||||
|
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
|
||||||
|
char *swap;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* compute lengths of blocks and number and size of cycles
|
||||||
|
*/
|
||||||
|
nnonopts = panonopt_end - panonopt_start;
|
||||||
|
nopts = opt_end - panonopt_end;
|
||||||
|
ncycle = gcd(nnonopts, nopts);
|
||||||
|
cyclelen = (opt_end - panonopt_start) / ncycle;
|
||||||
|
|
||||||
|
for (i = 0; i < ncycle; i++) {
|
||||||
|
cstart = panonopt_end+i;
|
||||||
|
pos = cstart;
|
||||||
|
for (j = 0; j < cyclelen; j++) {
|
||||||
|
if (pos >= panonopt_end)
|
||||||
|
pos -= nnonopts;
|
||||||
|
else
|
||||||
|
pos += nopts;
|
||||||
|
swap = nargv[pos];
|
||||||
|
/* LINTED const cast */
|
||||||
|
((char **) nargv)[pos] = nargv[cstart];
|
||||||
|
/* LINTED const cast */
|
||||||
|
((char **)nargv)[cstart] = swap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef REPLACE_GETOPT
|
||||||
|
/*
|
||||||
|
* getopt --
|
||||||
|
* Parse argc/argv argument vector.
|
||||||
|
*
|
||||||
|
* [eventually this will replace the BSD getopt]
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
getopt(int nargc, char * const *nargv, const char *options)
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We don't pass FLAG_PERMUTE to getopt_internal() since
|
||||||
|
* the BSD getopt(3) (unlike GNU) has never done this.
|
||||||
|
*
|
||||||
|
* Furthermore, since many privileged programs call getopt()
|
||||||
|
* before dropping privileges it makes sense to keep things
|
||||||
|
* as simple (and bug-free) as possible.
|
||||||
|
*/
|
||||||
|
return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
|
||||||
|
}
|
||||||
|
#endif /* REPLACE_GETOPT */
|
||||||
|
|
||||||
|
//extern int getopt(int nargc, char * const *nargv, const char *options);
|
||||||
|
|
||||||
|
#ifdef _BSD_SOURCE
|
||||||
|
/*
|
||||||
|
* BSD adds the non-standard `optreset' feature, for reinitialisation
|
||||||
|
* of `getopt' parsing. We support this feature, for applications which
|
||||||
|
* proclaim their BSD heritage, before including this header; however,
|
||||||
|
* to maintain portability, developers are advised to avoid it.
|
||||||
|
*/
|
||||||
|
# define optreset __mingw_optreset
|
||||||
|
extern int optreset;
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* POSIX requires the `getopt' API to be specified in `unistd.h';
|
||||||
|
* thus, `unistd.h' includes this header. However, we do not want
|
||||||
|
* to expose the `getopt_long' or `getopt_long_only' APIs, when
|
||||||
|
* included in this manner. Thus, close the standard __GETOPT_H__
|
||||||
|
* declarations block, and open an additional __GETOPT_LONG_H__
|
||||||
|
* specific block, only when *not* __UNISTD_H_SOURCED__, in which
|
||||||
|
* to declare the extended API.
|
||||||
|
*/
|
||||||
|
#endif /* !defined(__GETOPT_H__) */
|
||||||
|
|
||||||
|
#if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__)
|
||||||
|
#define __GETOPT_LONG_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct option /* specification for a long form option... */
|
||||||
|
{
|
||||||
|
const char *name; /* option name, without leading hyphens */
|
||||||
|
int has_arg; /* does it take an argument? */
|
||||||
|
int *flag; /* where to save its status, or NULL */
|
||||||
|
int val; /* its associated status value */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum /* permitted values for its `has_arg' field... */
|
||||||
|
{
|
||||||
|
no_argument = 0, /* option never takes an argument */
|
||||||
|
required_argument, /* option always requires an argument */
|
||||||
|
optional_argument /* option may take an argument */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* parse_long_options --
|
||||||
|
* Parse long options in argc/argv argument vector.
|
||||||
|
* Returns -1 if short_too is set and the option does not match long_options.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
parse_long_options(char * const *nargv, const char *options,
|
||||||
|
const struct option *long_options, int *idx, int short_too)
|
||||||
|
{
|
||||||
|
char *current_argv, *has_equal;
|
||||||
|
size_t current_argv_len;
|
||||||
|
int i, ambiguous, match;
|
||||||
|
|
||||||
|
#define IDENTICAL_INTERPRETATION(_x, _y) \
|
||||||
|
(long_options[(_x)].has_arg == long_options[(_y)].has_arg && \
|
||||||
|
long_options[(_x)].flag == long_options[(_y)].flag && \
|
||||||
|
long_options[(_x)].val == long_options[(_y)].val)
|
||||||
|
|
||||||
|
current_argv = place;
|
||||||
|
match = -1;
|
||||||
|
ambiguous = 0;
|
||||||
|
|
||||||
|
optind++;
|
||||||
|
|
||||||
|
if ((has_equal = strchr(current_argv, '=')) != NULL) {
|
||||||
|
/* argument found (--option=arg) */
|
||||||
|
current_argv_len = has_equal - current_argv;
|
||||||
|
has_equal++;
|
||||||
|
} else
|
||||||
|
current_argv_len = strlen(current_argv);
|
||||||
|
|
||||||
|
for (i = 0; long_options[i].name; i++) {
|
||||||
|
/* find matching long option */
|
||||||
|
if (strncmp(current_argv, long_options[i].name,
|
||||||
|
current_argv_len))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (strlen(long_options[i].name) == current_argv_len) {
|
||||||
|
/* exact match */
|
||||||
|
match = i;
|
||||||
|
ambiguous = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* If this is a known short option, don't allow
|
||||||
|
* a partial match of a single character.
|
||||||
|
*/
|
||||||
|
if (short_too && current_argv_len == 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (match == -1) /* partial match */
|
||||||
|
match = i;
|
||||||
|
else if (!IDENTICAL_INTERPRETATION(i, match))
|
||||||
|
ambiguous = 1;
|
||||||
|
}
|
||||||
|
if (ambiguous) {
|
||||||
|
/* ambiguous abbreviation */
|
||||||
|
if (PRINT_ERROR)
|
||||||
|
warnx(ambig, (int)current_argv_len,
|
||||||
|
current_argv);
|
||||||
|
optopt = 0;
|
||||||
|
return (BADCH);
|
||||||
|
}
|
||||||
|
if (match != -1) { /* option found */
|
||||||
|
if (long_options[match].has_arg == no_argument
|
||||||
|
&& has_equal) {
|
||||||
|
if (PRINT_ERROR)
|
||||||
|
warnx(noarg, (int)current_argv_len,
|
||||||
|
current_argv);
|
||||||
|
/*
|
||||||
|
* XXX: GNU sets optopt to val regardless of flag
|
||||||
|
*/
|
||||||
|
if (long_options[match].flag == NULL)
|
||||||
|
optopt = long_options[match].val;
|
||||||
|
else
|
||||||
|
optopt = 0;
|
||||||
|
return (BADARG);
|
||||||
|
}
|
||||||
|
if (long_options[match].has_arg == required_argument ||
|
||||||
|
long_options[match].has_arg == optional_argument) {
|
||||||
|
if (has_equal)
|
||||||
|
optarg = has_equal;
|
||||||
|
else if (long_options[match].has_arg ==
|
||||||
|
required_argument) {
|
||||||
|
/*
|
||||||
|
* optional argument doesn't use next nargv
|
||||||
|
*/
|
||||||
|
optarg = nargv[optind++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((long_options[match].has_arg == required_argument)
|
||||||
|
&& (optarg == NULL)) {
|
||||||
|
/*
|
||||||
|
* Missing argument; leading ':' indicates no error
|
||||||
|
* should be generated.
|
||||||
|
*/
|
||||||
|
if (PRINT_ERROR)
|
||||||
|
warnx(recargstring,
|
||||||
|
current_argv);
|
||||||
|
/*
|
||||||
|
* XXX: GNU sets optopt to val regardless of flag
|
||||||
|
*/
|
||||||
|
if (long_options[match].flag == NULL)
|
||||||
|
optopt = long_options[match].val;
|
||||||
|
else
|
||||||
|
optopt = 0;
|
||||||
|
--optind;
|
||||||
|
return (BADARG);
|
||||||
|
}
|
||||||
|
} else { /* unknown option */
|
||||||
|
if (short_too) {
|
||||||
|
--optind;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if (PRINT_ERROR)
|
||||||
|
warnx(illoptstring, current_argv);
|
||||||
|
optopt = 0;
|
||||||
|
return (BADCH);
|
||||||
|
}
|
||||||
|
if (idx)
|
||||||
|
*idx = match;
|
||||||
|
if (long_options[match].flag) {
|
||||||
|
*long_options[match].flag = long_options[match].val;
|
||||||
|
return (0);
|
||||||
|
} else
|
||||||
|
return (long_options[match].val);
|
||||||
|
#undef IDENTICAL_INTERPRETATION
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* getopt_internal --
|
||||||
|
* Parse argc/argv argument vector. Called by user level routines.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
getopt_internal(int nargc, char * const *nargv, const char *options,
|
||||||
|
const struct option *long_options, int *idx, int flags)
|
||||||
|
{
|
||||||
|
char *oli; /* option letter list index */
|
||||||
|
int optchar, short_too;
|
||||||
|
static int posixly_correct = -1;
|
||||||
|
|
||||||
|
if (options == NULL)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX Some GNU programs (like cvs) set optind to 0 instead of
|
||||||
|
* XXX using optreset. Work around this braindamage.
|
||||||
|
*/
|
||||||
|
if (optind == 0)
|
||||||
|
optind = optreset = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Disable GNU extensions if POSIXLY_CORRECT is set or options
|
||||||
|
* string begins with a '+'.
|
||||||
|
*
|
||||||
|
* CV, 2009-12-14: Check POSIXLY_CORRECT anew if optind == 0 or
|
||||||
|
* optreset != 0 for GNU compatibility.
|
||||||
|
*/
|
||||||
|
if (posixly_correct == -1 || optreset != 0)
|
||||||
|
posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
|
||||||
|
if (*options == '-')
|
||||||
|
flags |= FLAG_ALLARGS;
|
||||||
|
else if (posixly_correct || *options == '+')
|
||||||
|
flags &= ~FLAG_PERMUTE;
|
||||||
|
if (*options == '+' || *options == '-')
|
||||||
|
options++;
|
||||||
|
|
||||||
|
optarg = NULL;
|
||||||
|
if (optreset)
|
||||||
|
nonopt_start = nonopt_end = -1;
|
||||||
|
start:
|
||||||
|
if (optreset || !*place) { /* update scanning pointer */
|
||||||
|
optreset = 0;
|
||||||
|
if (optind >= nargc) { /* end of argument vector */
|
||||||
|
place = EMSG;
|
||||||
|
if (nonopt_end != -1) {
|
||||||
|
/* do permutation, if we have to */
|
||||||
|
permute_args(nonopt_start, nonopt_end,
|
||||||
|
optind, nargv);
|
||||||
|
optind -= nonopt_end - nonopt_start;
|
||||||
|
}
|
||||||
|
else if (nonopt_start != -1) {
|
||||||
|
/*
|
||||||
|
* If we skipped non-options, set optind
|
||||||
|
* to the first of them.
|
||||||
|
*/
|
||||||
|
optind = nonopt_start;
|
||||||
|
}
|
||||||
|
nonopt_start = nonopt_end = -1;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if (*(place = nargv[optind]) != '-' ||
|
||||||
|
(place[1] == '\0' && strchr(options, '-') == NULL)) {
|
||||||
|
place = EMSG; /* found non-option */
|
||||||
|
if (flags & FLAG_ALLARGS) {
|
||||||
|
/*
|
||||||
|
* GNU extension:
|
||||||
|
* return non-option as argument to option 1
|
||||||
|
*/
|
||||||
|
optarg = nargv[optind++];
|
||||||
|
return (INORDER);
|
||||||
|
}
|
||||||
|
if (!(flags & FLAG_PERMUTE)) {
|
||||||
|
/*
|
||||||
|
* If no permutation wanted, stop parsing
|
||||||
|
* at first non-option.
|
||||||
|
*/
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
/* do permutation */
|
||||||
|
if (nonopt_start == -1)
|
||||||
|
nonopt_start = optind;
|
||||||
|
else if (nonopt_end != -1) {
|
||||||
|
permute_args(nonopt_start, nonopt_end,
|
||||||
|
optind, nargv);
|
||||||
|
nonopt_start = optind -
|
||||||
|
(nonopt_end - nonopt_start);
|
||||||
|
nonopt_end = -1;
|
||||||
|
}
|
||||||
|
optind++;
|
||||||
|
/* process next argument */
|
||||||
|
goto start;
|
||||||
|
}
|
||||||
|
if (nonopt_start != -1 && nonopt_end == -1)
|
||||||
|
nonopt_end = optind;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we have "-" do nothing, if "--" we are done.
|
||||||
|
*/
|
||||||
|
if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
|
||||||
|
optind++;
|
||||||
|
place = EMSG;
|
||||||
|
/*
|
||||||
|
* We found an option (--), so if we skipped
|
||||||
|
* non-options, we have to permute.
|
||||||
|
*/
|
||||||
|
if (nonopt_end != -1) {
|
||||||
|
permute_args(nonopt_start, nonopt_end,
|
||||||
|
optind, nargv);
|
||||||
|
optind -= nonopt_end - nonopt_start;
|
||||||
|
}
|
||||||
|
nonopt_start = nonopt_end = -1;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check long options if:
|
||||||
|
* 1) we were passed some
|
||||||
|
* 2) the arg is not just "-"
|
||||||
|
* 3) either the arg starts with -- we are getopt_long_only()
|
||||||
|
*/
|
||||||
|
if (long_options != NULL && place != nargv[optind] &&
|
||||||
|
(*place == '-' || (flags & FLAG_LONGONLY))) {
|
||||||
|
short_too = 0;
|
||||||
|
if (*place == '-')
|
||||||
|
place++; /* --foo long option */
|
||||||
|
else if (*place != ':' && strchr(options, *place) != NULL)
|
||||||
|
short_too = 1; /* could be short option too */
|
||||||
|
|
||||||
|
optchar = parse_long_options(nargv, options, long_options,
|
||||||
|
idx, short_too);
|
||||||
|
if (optchar != -1) {
|
||||||
|
place = EMSG;
|
||||||
|
return (optchar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((optchar = (int)*place++) == (int)':' ||
|
||||||
|
(optchar == (int)'-' && *place != '\0') ||
|
||||||
|
(oli = (char*)strchr(options, optchar)) == NULL) {
|
||||||
|
/*
|
||||||
|
* If the user specified "-" and '-' isn't listed in
|
||||||
|
* options, return -1 (non-option) as per POSIX.
|
||||||
|
* Otherwise, it is an unknown option character (or ':').
|
||||||
|
*/
|
||||||
|
if (optchar == (int)'-' && *place == '\0')
|
||||||
|
return (-1);
|
||||||
|
if (!*place)
|
||||||
|
++optind;
|
||||||
|
if (PRINT_ERROR)
|
||||||
|
warnx(illoptchar, optchar);
|
||||||
|
optopt = optchar;
|
||||||
|
return (BADCH);
|
||||||
|
}
|
||||||
|
if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
|
||||||
|
/* -W long-option */
|
||||||
|
if (*place) /* no space */
|
||||||
|
/* NOTHING */;
|
||||||
|
else if (++optind >= nargc) { /* no arg */
|
||||||
|
place = EMSG;
|
||||||
|
if (PRINT_ERROR)
|
||||||
|
warnx(recargchar, optchar);
|
||||||
|
optopt = optchar;
|
||||||
|
return (BADARG);
|
||||||
|
} else /* white space */
|
||||||
|
place = nargv[optind];
|
||||||
|
optchar = parse_long_options(nargv, options, long_options,
|
||||||
|
idx, 0);
|
||||||
|
place = EMSG;
|
||||||
|
return (optchar);
|
||||||
|
}
|
||||||
|
if (*++oli != ':') { /* doesn't take argument */
|
||||||
|
if (!*place)
|
||||||
|
++optind;
|
||||||
|
} else { /* takes (optional) argument */
|
||||||
|
optarg = NULL;
|
||||||
|
if (*place) /* no white space */
|
||||||
|
optarg = place;
|
||||||
|
else if (oli[1] != ':') { /* arg not optional */
|
||||||
|
if (++optind >= nargc) { /* no arg */
|
||||||
|
place = EMSG;
|
||||||
|
if (PRINT_ERROR)
|
||||||
|
warnx(recargchar, optchar);
|
||||||
|
optopt = optchar;
|
||||||
|
return (BADARG);
|
||||||
|
} else
|
||||||
|
optarg = nargv[optind];
|
||||||
|
}
|
||||||
|
place = EMSG;
|
||||||
|
++optind;
|
||||||
|
}
|
||||||
|
/* dump back option letter */
|
||||||
|
return (optchar);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* getopt_long --
|
||||||
|
* Parse argc/argv argument vector.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
getopt_long(int nargc, char * const *nargv, const char *options,
|
||||||
|
const struct option *long_options, int *idx)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (getopt_internal(nargc, nargv, options, long_options, idx,
|
||||||
|
FLAG_PERMUTE));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* getopt_long_only --
|
||||||
|
* Parse argc/argv argument vector.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
getopt_long_only(int nargc, char * const *nargv, const char *options,
|
||||||
|
const struct option *long_options, int *idx)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (getopt_internal(nargc, nargv, options, long_options, idx,
|
||||||
|
FLAG_PERMUTE|FLAG_LONGONLY));
|
||||||
|
}
|
||||||
|
|
||||||
|
//extern int getopt_long(int nargc, char * const *nargv, const char *options,
|
||||||
|
// const struct option *long_options, int *idx);
|
||||||
|
//extern int getopt_long_only(int nargc, char * const *nargv, const char *options,
|
||||||
|
// const struct option *long_options, int *idx);
|
||||||
|
/*
|
||||||
|
* Previous MinGW implementation had...
|
||||||
|
*/
|
||||||
|
#ifndef HAVE_DECL_GETOPT
|
||||||
|
/*
|
||||||
|
* ...for the long form API only; keep this for compatibility.
|
||||||
|
*/
|
||||||
|
# define HAVE_DECL_GETOPT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */
|
15
zookeeper-client/zookeeper-client-c/include/winconfig.h
Normal file
15
zookeeper-client/zookeeper-client-c/include/winconfig.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef WINCONFIG_H_
|
||||||
|
#define WINCONFIG_H_
|
||||||
|
|
||||||
|
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||||
|
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#define inline __inline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define __attribute__(x)
|
||||||
|
#define __func__ __FUNCTION__
|
||||||
|
|
||||||
|
#define ACL ZKACL /* Conflict with windows API */
|
||||||
|
|
||||||
|
#endif
|
2336
zookeeper-client/zookeeper-client-c/include/zookeeper.h
Normal file
2336
zookeeper-client/zookeeper-client-c/include/zookeeper.h
Normal file
File diff suppressed because it is too large
Load Diff
50
zookeeper-client/zookeeper-client-c/include/zookeeper_log.h
Normal file
50
zookeeper-client/zookeeper-client-c/include/zookeeper_log.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZK_LOG_H_
|
||||||
|
#define ZK_LOG_H_
|
||||||
|
|
||||||
|
#include <zookeeper.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern ZOOAPI ZooLogLevel logLevel;
|
||||||
|
#define LOGCALLBACK(_zh) zoo_get_log_callback(_zh)
|
||||||
|
#define LOGSTREAM NULL
|
||||||
|
|
||||||
|
#define LOG_ERROR(_cb, ...) if(logLevel>=ZOO_LOG_LEVEL_ERROR) \
|
||||||
|
log_message(_cb, ZOO_LOG_LEVEL_ERROR, __LINE__, __func__, __VA_ARGS__)
|
||||||
|
#define LOG_WARN(_cb, ...) if(logLevel>=ZOO_LOG_LEVEL_WARN) \
|
||||||
|
log_message(_cb, ZOO_LOG_LEVEL_WARN, __LINE__, __func__, __VA_ARGS__)
|
||||||
|
#define LOG_INFO(_cb, ...) if(logLevel>=ZOO_LOG_LEVEL_INFO) \
|
||||||
|
log_message(_cb, ZOO_LOG_LEVEL_INFO, __LINE__, __func__, __VA_ARGS__)
|
||||||
|
#define LOG_DEBUG(_cb, ...) if(logLevel==ZOO_LOG_LEVEL_DEBUG) \
|
||||||
|
log_message(_cb, ZOO_LOG_LEVEL_DEBUG, __LINE__, __func__, __VA_ARGS__)
|
||||||
|
|
||||||
|
ZOOAPI void log_message(log_callback_fn callback, ZooLogLevel curLevel,
|
||||||
|
int line, const char* funcName, const char* format, ...);
|
||||||
|
|
||||||
|
FILE* zoo_get_log_stream();
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*ZK_LOG_H_*/
|
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#ifndef ZOOKEEPER_VERSION_H_
|
||||||
|
#define ZOOKEEPER_VERSION_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ZOO_VERSION "3.6.0"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZOOKEEPER_VERSION_H_ */
|
182
zookeeper-client/zookeeper-client-c/pom.xml
Normal file
182
zookeeper-client/zookeeper-client-c/pom.xml
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<!--
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.apache.zookeeper</groupId>
|
||||||
|
<artifactId>zookeeper-client</artifactId>
|
||||||
|
<version>3.6.3</version>
|
||||||
|
<relativePath>..</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>zookeeper-client-c</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<name>Apache ZooKeeper - Client - C</name>
|
||||||
|
<description>ZooKeeper c client</description>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>c-test-coverage</id>
|
||||||
|
<properties>
|
||||||
|
<c-test-coverage-arg>--enable-gcov</c-test-coverage-arg>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>no-c-test-coverage</id>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>true</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
<properties>
|
||||||
|
<c-test-coverage-arg> </c-test-coverage-arg>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
|
<artifactId>exec-maven-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>autoreconf</id>
|
||||||
|
<phase>process-sources</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>exec</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<workingDirectory>${project.basedir}</workingDirectory>
|
||||||
|
<executable>autoreconf</executable>
|
||||||
|
<environmentVariables>
|
||||||
|
<ACLOCAL>aclocal -I /usr/share/aclocal</ACLOCAL>
|
||||||
|
</environmentVariables>
|
||||||
|
<arguments>
|
||||||
|
<argument>-if</argument>
|
||||||
|
</arguments>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>configure</id>
|
||||||
|
<phase>process-sources</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>exec</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<workingDirectory>${project.build.directory}/c</workingDirectory>
|
||||||
|
<executable>${project.basedir}/configure</executable>
|
||||||
|
<environmentVariables>
|
||||||
|
<base_dir>${project.basedir}/../..</base_dir>
|
||||||
|
<CALLER>ANT</CALLER>
|
||||||
|
</environmentVariables>
|
||||||
|
<arguments>
|
||||||
|
<argument>--with-openssl=${c-client-openssl}</argument>
|
||||||
|
<argument>--prefix=${project.build.directory}/c</argument>
|
||||||
|
<argument>${c-test-coverage-arg}</argument>
|
||||||
|
</arguments>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-antrun-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>generate-sources</id>
|
||||||
|
<phase>generate-sources</phase>
|
||||||
|
<configuration>
|
||||||
|
<tasks>
|
||||||
|
<mkdir dir="target/c" />
|
||||||
|
</tasks>
|
||||||
|
</configuration>
|
||||||
|
<goals>
|
||||||
|
<goal>run</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>build-c-client</id>
|
||||||
|
<phase>compile</phase>
|
||||||
|
<configuration>
|
||||||
|
<tasks>
|
||||||
|
<exec dir="${basedir}/target/c" executable="make" failonerror="true">
|
||||||
|
<env key="LD_LIBRARY_PATH" value="${env.LD_LIBRARY_PATH};/usr/lib" />
|
||||||
|
<env key="PATH" path="${env.PATH};${basedir};" />
|
||||||
|
<env key="CALLER" value="ANT" />
|
||||||
|
<env key="CLOVER_HOME" value="${basedir}/../../zookeeper-server/target" />
|
||||||
|
<env key="base_dir" value="${basedir}/../.." />
|
||||||
|
<arg line="clean install" />
|
||||||
|
</exec>
|
||||||
|
</tasks>
|
||||||
|
</configuration>
|
||||||
|
<goals>
|
||||||
|
<goal>run</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>test-cppunit</id>
|
||||||
|
<phase>test</phase>
|
||||||
|
<configuration>
|
||||||
|
<!-- do not run cpp tests if tests are globally skipped -->
|
||||||
|
<skip>${skipTests}</skip>
|
||||||
|
<tasks>
|
||||||
|
<exec dir="${basedir}/target/c" executable="make" failonerror="true">
|
||||||
|
<env key="LD_LIBRARY_PATH" value="${env.LD_LIBRARY_PATH};/usr/lib" />
|
||||||
|
<env key="PATH" path="${env.PATH};${basedir};" />
|
||||||
|
<env key="CALLER" value="ANT" />
|
||||||
|
<env key="CLOVER_HOME" value="${basedir}/../../zookeeper-server/target" />
|
||||||
|
<env key="base_dir" value="${basedir}/../.." />
|
||||||
|
<arg line="check" />
|
||||||
|
</exec>
|
||||||
|
</tasks>
|
||||||
|
</configuration>
|
||||||
|
<goals>
|
||||||
|
<goal>run</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>replace-cclient-files-during-release</id>
|
||||||
|
<phase>none</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>run</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<target>
|
||||||
|
<replaceregexp file="include/zookeeper_version.h" match="project.*" replace="project(zookeeper VERSION ${project.version})" byline="true" />
|
||||||
|
<replace file="include/zookeeper_version.h" value="">
|
||||||
|
<replaceToken>-SNAPSHOT</replaceToken>
|
||||||
|
</replace>
|
||||||
|
<replaceregexp file="CMakeLists.txt" match="project.*" replace="project(zookeeper VERSION ${project.version})" byline="true" />
|
||||||
|
<replace file="CMakeLists.txt" value="">
|
||||||
|
<replaceToken>-SNAPSHOT</replaceToken>
|
||||||
|
</replace>
|
||||||
|
<replaceregexp file="configure.ac" match="AC_INIT.*" replace="AC_INIT([zookeeper C client],${project.version},[user@zookeeper.apache.org],[zookeeper])" byline="true" />
|
||||||
|
<replace file="configure.ac" value="">
|
||||||
|
<replaceToken>-SNAPSHOT</replaceToken>
|
||||||
|
</replace>
|
||||||
|
</target>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
271
zookeeper-client/zookeeper-client-c/src/addrvec.c
Normal file
271
zookeeper-client/zookeeper-client-c/src/addrvec.c
Normal file
@ -0,0 +1,271 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#ifdef WIN32
|
||||||
|
#define random rand /* replace POSIX random with Windows rand */
|
||||||
|
#include <winsock2.h> /* must always be included before ws2tcpip.h */
|
||||||
|
#include <ws2tcpip.h> /* for sockaddr_storage */
|
||||||
|
#include "winport.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "addrvec.h"
|
||||||
|
|
||||||
|
#define ADDRVEC_DEFAULT_GROW_AMOUNT 16
|
||||||
|
|
||||||
|
void addrvec_init(addrvec_t *avec)
|
||||||
|
{
|
||||||
|
assert(avec);
|
||||||
|
avec->next = 0;
|
||||||
|
avec->count = 0;
|
||||||
|
avec->capacity = 0;
|
||||||
|
avec->data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addrvec_free(addrvec_t *avec)
|
||||||
|
{
|
||||||
|
if (avec == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
avec->next = 0;
|
||||||
|
avec->count = 0;
|
||||||
|
avec->capacity = 0;
|
||||||
|
if (avec->data) {
|
||||||
|
free(avec->data);
|
||||||
|
avec->data = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int addrvec_alloc(addrvec_t *avec)
|
||||||
|
{
|
||||||
|
addrvec_init(avec);
|
||||||
|
return addrvec_grow_default(avec);
|
||||||
|
}
|
||||||
|
|
||||||
|
int addrvec_alloc_capacity(addrvec_t* avec, uint32_t capacity)
|
||||||
|
{
|
||||||
|
addrvec_init(avec);
|
||||||
|
return addrvec_grow(avec, capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
int addrvec_grow(addrvec_t *avec, uint32_t grow_amount)
|
||||||
|
{
|
||||||
|
unsigned int old_capacity = 0;
|
||||||
|
struct sockaddr_storage *old_data = NULL;
|
||||||
|
assert(avec);
|
||||||
|
|
||||||
|
if (grow_amount == 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save off old data and capacity in case there is a realloc failure
|
||||||
|
old_capacity = avec->capacity;
|
||||||
|
old_data = avec->data;
|
||||||
|
|
||||||
|
avec->capacity += grow_amount;
|
||||||
|
avec->data = realloc(avec->data, sizeof(*avec->data) * avec->capacity);
|
||||||
|
if (avec->data == NULL)
|
||||||
|
{
|
||||||
|
avec->capacity = old_capacity;
|
||||||
|
avec->data = old_data;
|
||||||
|
errno = ENOMEM;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int addrvec_grow_default(addrvec_t *avec)
|
||||||
|
{
|
||||||
|
return addrvec_grow(avec, ADDRVEC_DEFAULT_GROW_AMOUNT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int addrvec_grow_if_full(addrvec_t *avec)
|
||||||
|
{
|
||||||
|
assert(avec);
|
||||||
|
if (avec->count == avec->capacity)
|
||||||
|
{
|
||||||
|
int rc = addrvec_grow_default(avec);
|
||||||
|
if (rc != 0)
|
||||||
|
{
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int addrvec_contains(const addrvec_t *avec, const struct sockaddr_storage *addr)
|
||||||
|
{
|
||||||
|
uint32_t i = 0;
|
||||||
|
if (!avec || !addr)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < avec->count; i++)
|
||||||
|
{
|
||||||
|
if (avec->data[i].ss_family != addr->ss_family)
|
||||||
|
continue;
|
||||||
|
switch (addr->ss_family) {
|
||||||
|
case AF_INET:
|
||||||
|
if (memcmp(&((struct sockaddr_in*)&avec->data[i])->sin_addr,
|
||||||
|
&((struct sockaddr_in*)addr)->sin_addr,
|
||||||
|
sizeof(struct in_addr)) == 0)
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
#ifdef AF_INET6
|
||||||
|
case AF_INET6:
|
||||||
|
if (memcmp(&((struct sockaddr_in6*)&avec->data[i])->sin6_addr,
|
||||||
|
&((struct sockaddr_in6*)addr)->sin6_addr,
|
||||||
|
sizeof(struct in6_addr)) == 0)
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int addrvec_append(addrvec_t *avec, const struct sockaddr_storage *addr)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
assert(avec);
|
||||||
|
assert(addr);
|
||||||
|
|
||||||
|
rc = addrvec_grow_if_full(avec);
|
||||||
|
if (rc != 0)
|
||||||
|
{
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy addrinfo into address list
|
||||||
|
memcpy(avec->data + avec->count, addr, sizeof(*addr));
|
||||||
|
++avec->count;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int addrvec_append_addrinfo(addrvec_t *avec, const struct addrinfo *addrinfo)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
assert(avec);
|
||||||
|
assert(addrinfo);
|
||||||
|
|
||||||
|
rc = addrvec_grow_if_full(avec);
|
||||||
|
if (rc != 0)
|
||||||
|
{
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy addrinfo into address list
|
||||||
|
memcpy(avec->data + avec->count, addrinfo->ai_addr, addrinfo->ai_addrlen);
|
||||||
|
++avec->count;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addrvec_shuffle(addrvec_t *avec)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
for (i = avec->count - 1; i > 0; --i) {
|
||||||
|
long int j = random()%(i+1);
|
||||||
|
if (i != j) {
|
||||||
|
struct sockaddr_storage t = avec->data[i];
|
||||||
|
avec->data[i] = avec->data[j];
|
||||||
|
avec->data[j] = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int addrvec_hasnext(const addrvec_t *avec)
|
||||||
|
{
|
||||||
|
return avec->count > 0 && (avec->next < avec->count);
|
||||||
|
}
|
||||||
|
|
||||||
|
int addrvec_atend(const addrvec_t *avec)
|
||||||
|
{
|
||||||
|
return avec->count > 0 && avec->next >= avec->count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addrvec_next(addrvec_t *avec, struct sockaddr_storage *next)
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
|
||||||
|
// If we're at the end of the list, then reset index to start
|
||||||
|
if (addrvec_atend(avec)) {
|
||||||
|
avec->next = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!addrvec_hasnext(avec)) {
|
||||||
|
if (next) {
|
||||||
|
memset(next, 0, sizeof(*next));
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = avec->next++;
|
||||||
|
|
||||||
|
if (next) {
|
||||||
|
*next = avec->data[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void addrvec_peek(addrvec_t *avec, struct sockaddr_storage *next)
|
||||||
|
{
|
||||||
|
int index = avec->next;
|
||||||
|
|
||||||
|
if (avec->count == 0) {
|
||||||
|
memset(next, 0, sizeof(*next));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addrvec_atend(avec)) {
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*next = avec->data[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int addrvec_eq(const addrvec_t *a1, const addrvec_t *a2)
|
||||||
|
{
|
||||||
|
uint32_t i = 0;
|
||||||
|
if (a1->count != a2->count)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < a1->count; ++i)
|
||||||
|
{
|
||||||
|
if (!addrvec_contains(a2, &a1->data[i]))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
138
zookeeper-client/zookeeper-client-c/src/addrvec.h
Normal file
138
zookeeper-client/zookeeper-client-c/src/addrvec.h
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ADDRVEC_H_
|
||||||
|
#define ADDRVEC_H_
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#else
|
||||||
|
#include <WinSock2.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This structure represents a list of addresses. It stores the count of the
|
||||||
|
* number of elements that have been inserted via calls to addrvec_append and
|
||||||
|
* addrvec_append_addrinfo. It also has a capacity field for the number of
|
||||||
|
* addresses it has the ability to hold without needing to be enlarged.
|
||||||
|
*/
|
||||||
|
typedef struct _addrvec {
|
||||||
|
unsigned int next; // next index to use
|
||||||
|
unsigned int count; // number of addresses in this list
|
||||||
|
unsigned int capacity; // number of address this list can hold
|
||||||
|
struct sockaddr_storage *data; // list of addresses
|
||||||
|
} addrvec_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize an addrvec by clearing out all its state.
|
||||||
|
*/
|
||||||
|
void addrvec_init(addrvec_t *avec);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free any memory used internally by an addrvec
|
||||||
|
*/
|
||||||
|
void addrvec_free(addrvec_t *avec);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate an addrvec with a default capacity (16)
|
||||||
|
*/
|
||||||
|
int addrvec_alloc(addrvec_t *avec);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocates an addrvec with a specified capacity
|
||||||
|
*/
|
||||||
|
int addrvec_alloc_capacity(addrvec_t *avec, uint32_t capacity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grow an addrvec by the specified amount. This will increase the capacity
|
||||||
|
* of the vector and not the contents.
|
||||||
|
*/
|
||||||
|
int addrvec_grow(addrvec_t *avec, uint32_t grow_amount);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to addrvec_grow but uses a default growth amount of 16.
|
||||||
|
*/
|
||||||
|
int addrvec_grow_default(addrvec_t *avec);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an addrvec contains the specificed sockaddr_storage value.
|
||||||
|
* \returns 1 if it contains the value and 0 otherwise.
|
||||||
|
*/
|
||||||
|
int addrvec_contains(const addrvec_t *avec, const struct sockaddr_storage *addr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append the given sockaddr_storage pointer into the addrvec. The contents of
|
||||||
|
* the given 'addr' are copied into the addrvec via memcpy.
|
||||||
|
*/
|
||||||
|
int addrvec_append(addrvec_t *avec, const struct sockaddr_storage *addr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append the given addrinfo pointer into the addrvec. The contents of the given
|
||||||
|
* 'addrinfo' are copied into the addrvec via memcpy.
|
||||||
|
*/
|
||||||
|
int addrvec_append_addrinfo(addrvec_t *avec, const struct addrinfo *addrinfo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shuffle the addrvec so that it's internal list of addresses are randomized.
|
||||||
|
* Uses random() and assumes it has been properly seeded.
|
||||||
|
*/
|
||||||
|
void addrvec_shuffle(addrvec_t *avec);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the addrvec has a next element (e.g. it's safe to call addrvec_next)
|
||||||
|
*
|
||||||
|
* \returns 1 if it has a next element and 0 otherwise
|
||||||
|
*/
|
||||||
|
int addrvec_hasnext(const addrvec_t *avec);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the addrvec is at the end or not. Specifically, this means a
|
||||||
|
* subsequent call to addrvec_next will loop around to the start again.
|
||||||
|
*/
|
||||||
|
int addrvec_atend(const addrvec_t *avec);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the next entry from the addrvec and update the associated index.
|
||||||
|
*
|
||||||
|
* If next is NULL, the index will still be updated.
|
||||||
|
*
|
||||||
|
* If the current index points at (or after) the last element in the vector then
|
||||||
|
* it will loop back around and start at the beginning of the list.
|
||||||
|
*/
|
||||||
|
void addrvec_next(addrvec_t *avec, struct sockaddr_storage *next);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the next entry from the addrvec but doesn't update the index.
|
||||||
|
*/
|
||||||
|
void addrvec_peek(addrvec_t *avec, struct sockaddr_storage *next);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare two addrvecs for equality.
|
||||||
|
*
|
||||||
|
* \returns 1 if the contents of the two lists are identical and and 0 otherwise.
|
||||||
|
*/
|
||||||
|
int addrvec_eq(const addrvec_t *a1, const addrvec_t *a2);
|
||||||
|
|
||||||
|
#endif // ADDRVEC_H
|
||||||
|
|
||||||
|
|
||||||
|
|
1015
zookeeper-client/zookeeper-client-c/src/cli.c
Normal file
1015
zookeeper-client/zookeeper-client-c/src/cli.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,30 @@
|
|||||||
|
Copyright (c) 2002, 2004, Christopher Clark
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the original author; nor the names of any contributors
|
||||||
|
may be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
274
zookeeper-client/zookeeper-client-c/src/hashtable/hashtable.c
Normal file
274
zookeeper-client/zookeeper-client-c/src/hashtable/hashtable.c
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
/* Copyright (C) 2004 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
|
||||||
|
|
||||||
|
#include "hashtable.h"
|
||||||
|
#include "hashtable_private.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
Credit for primes table: Aaron Krowne
|
||||||
|
http://br.endernet.org/~akrowne/
|
||||||
|
http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
|
||||||
|
*/
|
||||||
|
static const unsigned int primes[] = {
|
||||||
|
53, 97, 193, 389,
|
||||||
|
769, 1543, 3079, 6151,
|
||||||
|
12289, 24593, 49157, 98317,
|
||||||
|
196613, 393241, 786433, 1572869,
|
||||||
|
3145739, 6291469, 12582917, 25165843,
|
||||||
|
50331653, 100663319, 201326611, 402653189,
|
||||||
|
805306457, 1610612741
|
||||||
|
};
|
||||||
|
const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]);
|
||||||
|
const float max_load_factor = 0.65;
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
struct hashtable *
|
||||||
|
create_hashtable(unsigned int minsize,
|
||||||
|
unsigned int (*hashf) (void*),
|
||||||
|
int (*eqf) (void*,void*))
|
||||||
|
{
|
||||||
|
struct hashtable *h;
|
||||||
|
unsigned int pindex, size = primes[0];
|
||||||
|
/* Check requested hashtable isn't too large */
|
||||||
|
if (minsize > (1u << 30)) return NULL;
|
||||||
|
/* Enforce size as prime */
|
||||||
|
for (pindex=0; pindex < prime_table_length; pindex++) {
|
||||||
|
if (primes[pindex] > minsize) { size = primes[pindex]; break; }
|
||||||
|
}
|
||||||
|
h = (struct hashtable *)malloc(sizeof(struct hashtable));
|
||||||
|
if (NULL == h) return NULL; /*oom*/
|
||||||
|
h->table = (struct entry **)malloc(sizeof(struct entry*) * size);
|
||||||
|
if (NULL == h->table) { free(h); return NULL; } /*oom*/
|
||||||
|
memset(h->table, 0, size * sizeof(struct entry *));
|
||||||
|
h->tablelength = size;
|
||||||
|
h->primeindex = pindex;
|
||||||
|
h->entrycount = 0;
|
||||||
|
h->hashfn = hashf;
|
||||||
|
h->eqfn = eqf;
|
||||||
|
h->loadlimit = (unsigned int) ceil(size * max_load_factor);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
unsigned int
|
||||||
|
hash(struct hashtable *h, void *k)
|
||||||
|
{
|
||||||
|
/* Aim to protect against poor hash functions by adding logic here
|
||||||
|
* - logic taken from java 1.4 hashtable source */
|
||||||
|
unsigned int i = h->hashfn(k);
|
||||||
|
i += ~(i << 9);
|
||||||
|
i ^= ((i >> 14) | (i << 18)); /* >>> */
|
||||||
|
i += (i << 4);
|
||||||
|
i ^= ((i >> 10) | (i << 22)); /* >>> */
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
static int
|
||||||
|
hashtable_expand(struct hashtable *h)
|
||||||
|
{
|
||||||
|
/* Double the size of the table to accomodate more entries */
|
||||||
|
struct entry **newtable;
|
||||||
|
struct entry *e;
|
||||||
|
struct entry **pE;
|
||||||
|
unsigned int newsize, i, index;
|
||||||
|
/* Check we're not hitting max capacity */
|
||||||
|
if (h->primeindex == (prime_table_length - 1)) return 0;
|
||||||
|
newsize = primes[++(h->primeindex)];
|
||||||
|
|
||||||
|
newtable = (struct entry **)malloc(sizeof(struct entry*) * newsize);
|
||||||
|
if (NULL != newtable)
|
||||||
|
{
|
||||||
|
memset(newtable, 0, newsize * sizeof(struct entry *));
|
||||||
|
/* This algorithm is not 'stable'. ie. it reverses the list
|
||||||
|
* when it transfers entries between the tables */
|
||||||
|
for (i = 0; i < h->tablelength; i++) {
|
||||||
|
while (NULL != (e = h->table[i])) {
|
||||||
|
h->table[i] = e->next;
|
||||||
|
index = indexFor(newsize,e->h);
|
||||||
|
e->next = newtable[index];
|
||||||
|
newtable[index] = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(h->table);
|
||||||
|
h->table = newtable;
|
||||||
|
}
|
||||||
|
/* Plan B: realloc instead */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newtable = (struct entry **)
|
||||||
|
realloc(h->table, newsize * sizeof(struct entry *));
|
||||||
|
if (NULL == newtable) { (h->primeindex)--; return 0; }
|
||||||
|
h->table = newtable;
|
||||||
|
memset(newtable[h->tablelength], 0, newsize - h->tablelength);
|
||||||
|
for (i = 0; i < h->tablelength; i++) {
|
||||||
|
for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) {
|
||||||
|
index = indexFor(newsize,e->h);
|
||||||
|
if (index == i)
|
||||||
|
{
|
||||||
|
pE = &(e->next);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*pE = e->next;
|
||||||
|
e->next = newtable[index];
|
||||||
|
newtable[index] = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h->tablelength = newsize;
|
||||||
|
h->loadlimit = (unsigned int) ceil(newsize * max_load_factor);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
unsigned int
|
||||||
|
hashtable_count(struct hashtable *h)
|
||||||
|
{
|
||||||
|
return h->entrycount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
int
|
||||||
|
hashtable_insert(struct hashtable *h, void *k, void *v)
|
||||||
|
{
|
||||||
|
/* This method allows duplicate keys - but they shouldn't be used */
|
||||||
|
unsigned int index;
|
||||||
|
struct entry *e;
|
||||||
|
if (++(h->entrycount) > h->loadlimit)
|
||||||
|
{
|
||||||
|
/* Ignore the return value. If expand fails, we should
|
||||||
|
* still try cramming just this value into the existing table
|
||||||
|
* -- we may not have memory for a larger table, but one more
|
||||||
|
* element may be ok. Next time we insert, we'll try expanding again.*/
|
||||||
|
hashtable_expand(h);
|
||||||
|
}
|
||||||
|
e = (struct entry *)malloc(sizeof(struct entry));
|
||||||
|
if (NULL == e) { --(h->entrycount); return 0; } /*oom*/
|
||||||
|
e->h = hash(h,k);
|
||||||
|
index = indexFor(h->tablelength,e->h);
|
||||||
|
e->k = k;
|
||||||
|
e->v = v;
|
||||||
|
e->next = h->table[index];
|
||||||
|
h->table[index] = e;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
void * /* returns value associated with key */
|
||||||
|
hashtable_search(struct hashtable *h, void *k)
|
||||||
|
{
|
||||||
|
struct entry *e;
|
||||||
|
unsigned int hashvalue, index;
|
||||||
|
hashvalue = hash(h,k);
|
||||||
|
index = indexFor(h->tablelength,hashvalue);
|
||||||
|
e = h->table[index];
|
||||||
|
while (NULL != e)
|
||||||
|
{
|
||||||
|
/* Check hash value to short circuit heavier comparison */
|
||||||
|
if ((hashvalue == e->h) && (h->eqfn(k, e->k))) return e->v;
|
||||||
|
e = e->next;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
void * /* returns value associated with key */
|
||||||
|
hashtable_remove(struct hashtable *h, void *k)
|
||||||
|
{
|
||||||
|
/* TODO: consider compacting the table when the load factor drops enough,
|
||||||
|
* or provide a 'compact' method. */
|
||||||
|
|
||||||
|
struct entry *e;
|
||||||
|
struct entry **pE;
|
||||||
|
void *v;
|
||||||
|
unsigned int hashvalue, index;
|
||||||
|
|
||||||
|
hashvalue = hash(h,k);
|
||||||
|
index = indexFor(h->tablelength, hashvalue);
|
||||||
|
pE = &(h->table[index]);
|
||||||
|
e = *pE;
|
||||||
|
while (NULL != e)
|
||||||
|
{
|
||||||
|
/* Check hash value to short circuit heavier comparison */
|
||||||
|
if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
|
||||||
|
{
|
||||||
|
*pE = e->next;
|
||||||
|
h->entrycount--;
|
||||||
|
v = e->v;
|
||||||
|
freekey(e->k);
|
||||||
|
free(e);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
pE = &(e->next);
|
||||||
|
e = e->next;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* destroy */
|
||||||
|
void
|
||||||
|
hashtable_destroy(struct hashtable *h, int free_values)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
struct entry *e, *f;
|
||||||
|
struct entry **table = h->table;
|
||||||
|
if (free_values)
|
||||||
|
{
|
||||||
|
for (i = 0; i < h->tablelength; i++)
|
||||||
|
{
|
||||||
|
e = table[i];
|
||||||
|
while (NULL != e)
|
||||||
|
{ f = e; e = e->next; freekey(f->k); free(f->v); free(f); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i = 0; i < h->tablelength; i++)
|
||||||
|
{
|
||||||
|
e = table[i];
|
||||||
|
while (NULL != e)
|
||||||
|
{ f = e; e = e->next; freekey(f->k); free(f); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(h->table);
|
||||||
|
free(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2002, Christopher Clark
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name of the original author; nor the names of any contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
209
zookeeper-client/zookeeper-client-c/src/hashtable/hashtable.h
Normal file
209
zookeeper-client/zookeeper-client-c/src/hashtable/hashtable.h
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
/* Copyright (C) 2002 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
|
||||||
|
|
||||||
|
#ifndef __HASHTABLE_CWC22_H__
|
||||||
|
#define __HASHTABLE_CWC22_H__
|
||||||
|
#ifdef WIN32
|
||||||
|
#include "winconfig.h"
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct hashtable;
|
||||||
|
|
||||||
|
/* Example of use:
|
||||||
|
*
|
||||||
|
* struct hashtable *h;
|
||||||
|
* struct some_key *k;
|
||||||
|
* struct some_value *v;
|
||||||
|
*
|
||||||
|
* static unsigned int hash_from_key_fn( void *k );
|
||||||
|
* static int keys_equal_fn ( void *key1, void *key2 );
|
||||||
|
*
|
||||||
|
* h = create_hashtable(16, hash_from_key_fn, keys_equal_fn);
|
||||||
|
* k = (struct some_key *) malloc(sizeof(struct some_key));
|
||||||
|
* v = (struct some_value *) malloc(sizeof(struct some_value));
|
||||||
|
*
|
||||||
|
* (initialise k and v to suitable values)
|
||||||
|
*
|
||||||
|
* if (! hashtable_insert(h,k,v) )
|
||||||
|
* { exit(-1); }
|
||||||
|
*
|
||||||
|
* if (NULL == (found = hashtable_search(h,k) ))
|
||||||
|
* { printf("not found!"); }
|
||||||
|
*
|
||||||
|
* if (NULL == (found = hashtable_remove(h,k) ))
|
||||||
|
* { printf("Not found\n"); }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Macros may be used to define type-safe(r) hashtable access functions, with
|
||||||
|
* methods specialized to take known key and value types as parameters.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* Insert this at the start of your file:
|
||||||
|
*
|
||||||
|
* DEFINE_HASHTABLE_INSERT(insert_some, struct some_key, struct some_value);
|
||||||
|
* DEFINE_HASHTABLE_SEARCH(search_some, struct some_key, struct some_value);
|
||||||
|
* DEFINE_HASHTABLE_REMOVE(remove_some, struct some_key, struct some_value);
|
||||||
|
*
|
||||||
|
* This defines the functions 'insert_some', 'search_some' and 'remove_some'.
|
||||||
|
* These operate just like hashtable_insert etc., with the same parameters,
|
||||||
|
* but their function signatures have 'struct some_key *' rather than
|
||||||
|
* 'void *', and hence can generate compile time errors if your program is
|
||||||
|
* supplying incorrect data as a key (and similarly for value).
|
||||||
|
*
|
||||||
|
* Note that the hash and key equality functions passed to create_hashtable
|
||||||
|
* still take 'void *' parameters instead of 'some key *'. This shouldn't be
|
||||||
|
* a difficult issue as they're only defined and passed once, and the other
|
||||||
|
* functions will ensure that only valid keys are supplied to them.
|
||||||
|
*
|
||||||
|
* The cost for this checking is increased code size and runtime overhead
|
||||||
|
* - if performance is important, it may be worth switching back to the
|
||||||
|
* unsafe methods once your program has been debugged with the safe methods.
|
||||||
|
* This just requires switching to some simple alternative defines - eg:
|
||||||
|
* #define insert_some hashtable_insert
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* create_hashtable
|
||||||
|
|
||||||
|
* @name create_hashtable
|
||||||
|
* @param minsize minimum initial size of hashtable
|
||||||
|
* @param hashfunction function for hashing keys
|
||||||
|
* @param key_eq_fn function for determining key equality
|
||||||
|
* @return newly created hashtable or NULL on failure
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct hashtable *
|
||||||
|
create_hashtable(unsigned int minsize,
|
||||||
|
unsigned int (*hashfunction) (void*),
|
||||||
|
int (*key_eq_fn) (void*,void*));
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* hashtable_insert
|
||||||
|
|
||||||
|
* @name hashtable_insert
|
||||||
|
* @param h the hashtable to insert into
|
||||||
|
* @param k the key - hashtable claims ownership and will free on removal
|
||||||
|
* @param v the value - does not claim ownership
|
||||||
|
* @return non-zero for successful insertion
|
||||||
|
*
|
||||||
|
* This function will cause the table to expand if the insertion would take
|
||||||
|
* the ratio of entries to table size over the maximum load factor.
|
||||||
|
*
|
||||||
|
* This function does not check for repeated insertions with a duplicate key.
|
||||||
|
* The value returned when using a duplicate key is undefined -- when
|
||||||
|
* the hashtable changes size, the order of retrieval of duplicate key
|
||||||
|
* entries is reversed.
|
||||||
|
* If in doubt, remove before insert.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
hashtable_insert(struct hashtable *h, void *k, void *v);
|
||||||
|
|
||||||
|
#define DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \
|
||||||
|
int fnname (struct hashtable *h, keytype *k, valuetype *v) \
|
||||||
|
{ \
|
||||||
|
return hashtable_insert(h,k,v); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* hashtable_search
|
||||||
|
|
||||||
|
* @name hashtable_search
|
||||||
|
* @param h the hashtable to search
|
||||||
|
* @param k the key to search for - does not claim ownership
|
||||||
|
* @return the value associated with the key, or NULL if none found
|
||||||
|
*/
|
||||||
|
|
||||||
|
void *
|
||||||
|
hashtable_search(struct hashtable *h, void *k);
|
||||||
|
|
||||||
|
#define DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \
|
||||||
|
valuetype * fnname (struct hashtable *h, keytype *k) \
|
||||||
|
{ \
|
||||||
|
return (valuetype *) (hashtable_search(h,k)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* hashtable_remove
|
||||||
|
|
||||||
|
* @name hashtable_remove
|
||||||
|
* @param h the hashtable to remove the item from
|
||||||
|
* @param k the key to search for - does not claim ownership
|
||||||
|
* @return the value associated with the key, or NULL if none found
|
||||||
|
*/
|
||||||
|
|
||||||
|
void * /* returns value */
|
||||||
|
hashtable_remove(struct hashtable *h, void *k);
|
||||||
|
|
||||||
|
#define DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \
|
||||||
|
valuetype * fnname (struct hashtable *h, keytype *k) \
|
||||||
|
{ \
|
||||||
|
return (valuetype *) (hashtable_remove(h,k)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* hashtable_count
|
||||||
|
|
||||||
|
* @name hashtable_count
|
||||||
|
* @param h the hashtable
|
||||||
|
* @return the number of items stored in the hashtable
|
||||||
|
*/
|
||||||
|
unsigned int
|
||||||
|
hashtable_count(struct hashtable *h);
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* hashtable_destroy
|
||||||
|
|
||||||
|
* @name hashtable_destroy
|
||||||
|
* @param h the hashtable
|
||||||
|
* @param free_values whether to call 'free' on the remaining values
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
hashtable_destroy(struct hashtable *h, int free_values);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __HASHTABLE_CWC22_H__ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2002, Christopher Clark
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name of the original author; nor the names of any contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
@ -0,0 +1,176 @@
|
|||||||
|
/* Copyright (C) 2002, 2004 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
|
||||||
|
|
||||||
|
#include "hashtable.h"
|
||||||
|
#include "hashtable_private.h"
|
||||||
|
#include "hashtable_itr.h"
|
||||||
|
#include <stdlib.h> /* defines NULL */
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* hashtable_iterator - iterator constructor */
|
||||||
|
|
||||||
|
struct hashtable_itr *
|
||||||
|
hashtable_iterator(struct hashtable *h)
|
||||||
|
{
|
||||||
|
unsigned int i, tablelength;
|
||||||
|
struct hashtable_itr *itr = (struct hashtable_itr *)
|
||||||
|
malloc(sizeof(struct hashtable_itr));
|
||||||
|
if (NULL == itr) return NULL;
|
||||||
|
itr->h = h;
|
||||||
|
itr->e = NULL;
|
||||||
|
itr->parent = NULL;
|
||||||
|
tablelength = h->tablelength;
|
||||||
|
itr->index = tablelength;
|
||||||
|
if (0 == h->entrycount) return itr;
|
||||||
|
|
||||||
|
for (i = 0; i < tablelength; i++)
|
||||||
|
{
|
||||||
|
if (NULL != h->table[i])
|
||||||
|
{
|
||||||
|
itr->e = h->table[i];
|
||||||
|
itr->index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return itr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* advance - advance the iterator to the next element
|
||||||
|
* returns zero if advanced to end of table */
|
||||||
|
|
||||||
|
int
|
||||||
|
hashtable_iterator_advance(struct hashtable_itr *itr)
|
||||||
|
{
|
||||||
|
unsigned int j,tablelength;
|
||||||
|
struct entry **table;
|
||||||
|
struct entry *next;
|
||||||
|
if (NULL == itr->e) return 0; /* stupidity check */
|
||||||
|
|
||||||
|
next = itr->e->next;
|
||||||
|
if (NULL != next)
|
||||||
|
{
|
||||||
|
itr->parent = itr->e;
|
||||||
|
itr->e = next;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
tablelength = itr->h->tablelength;
|
||||||
|
itr->parent = NULL;
|
||||||
|
if (tablelength <= (j = ++(itr->index)))
|
||||||
|
{
|
||||||
|
itr->e = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
table = itr->h->table;
|
||||||
|
while (NULL == (next = table[j]))
|
||||||
|
{
|
||||||
|
if (++j >= tablelength)
|
||||||
|
{
|
||||||
|
itr->index = tablelength;
|
||||||
|
itr->e = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
itr->index = j;
|
||||||
|
itr->e = next;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* remove - remove the entry at the current iterator position
|
||||||
|
* and advance the iterator, if there is a successive
|
||||||
|
* element.
|
||||||
|
* If you want the value, read it before you remove:
|
||||||
|
* beware memory leaks if you don't.
|
||||||
|
* Returns zero if end of iteration. */
|
||||||
|
|
||||||
|
int
|
||||||
|
hashtable_iterator_remove(struct hashtable_itr *itr)
|
||||||
|
{
|
||||||
|
struct entry *remember_e, *remember_parent;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Do the removal */
|
||||||
|
if (NULL == (itr->parent))
|
||||||
|
{
|
||||||
|
/* element is head of a chain */
|
||||||
|
itr->h->table[itr->index] = itr->e->next;
|
||||||
|
} else {
|
||||||
|
/* element is mid-chain */
|
||||||
|
itr->parent->next = itr->e->next;
|
||||||
|
}
|
||||||
|
/* itr->e is now outside the hashtable */
|
||||||
|
remember_e = itr->e;
|
||||||
|
itr->h->entrycount--;
|
||||||
|
freekey(remember_e->k);
|
||||||
|
|
||||||
|
/* Advance the iterator, correcting the parent */
|
||||||
|
remember_parent = itr->parent;
|
||||||
|
ret = hashtable_iterator_advance(itr);
|
||||||
|
if (itr->parent == remember_e) { itr->parent = remember_parent; }
|
||||||
|
free(remember_e);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
int /* returns zero if not found */
|
||||||
|
hashtable_iterator_search(struct hashtable_itr *itr,
|
||||||
|
struct hashtable *h, void *k)
|
||||||
|
{
|
||||||
|
struct entry *e, *parent;
|
||||||
|
unsigned int hashvalue, index;
|
||||||
|
|
||||||
|
hashvalue = hash(h,k);
|
||||||
|
index = indexFor(h->tablelength,hashvalue);
|
||||||
|
|
||||||
|
e = h->table[index];
|
||||||
|
parent = NULL;
|
||||||
|
while (NULL != e)
|
||||||
|
{
|
||||||
|
/* Check hash value to short circuit heavier comparison */
|
||||||
|
if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
|
||||||
|
{
|
||||||
|
itr->index = index;
|
||||||
|
itr->e = e;
|
||||||
|
itr->parent = parent;
|
||||||
|
itr->h = h;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
parent = e;
|
||||||
|
e = e->next;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2002, 2004, Christopher Clark
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name of the original author; nor the names of any contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
@ -0,0 +1,119 @@
|
|||||||
|
/* Copyright (C) 2002, 2004 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
|
||||||
|
|
||||||
|
#ifndef __HASHTABLE_ITR_CWC22__
|
||||||
|
#define __HASHTABLE_ITR_CWC22__
|
||||||
|
#include "hashtable.h"
|
||||||
|
#include "hashtable_private.h" /* needed to enable inlining */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* This struct is only concrete here to allow the inlining of two of the
|
||||||
|
* accessor functions. */
|
||||||
|
struct hashtable_itr
|
||||||
|
{
|
||||||
|
struct hashtable *h;
|
||||||
|
struct entry *e;
|
||||||
|
struct entry *parent;
|
||||||
|
unsigned int index;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* hashtable_iterator
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct hashtable_itr *
|
||||||
|
hashtable_iterator(struct hashtable *h);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* hashtable_iterator_key
|
||||||
|
* - return the value of the (key,value) pair at the current position */
|
||||||
|
|
||||||
|
static inline void *
|
||||||
|
hashtable_iterator_key(struct hashtable_itr *i)
|
||||||
|
{
|
||||||
|
return i->e->k;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* value - return the value of the (key,value) pair at the current position */
|
||||||
|
|
||||||
|
static inline void *
|
||||||
|
hashtable_iterator_value(struct hashtable_itr *i)
|
||||||
|
{
|
||||||
|
return i->e->v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* advance - advance the iterator to the next element
|
||||||
|
* returns zero if advanced to end of table */
|
||||||
|
|
||||||
|
int
|
||||||
|
hashtable_iterator_advance(struct hashtable_itr *itr);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* remove - remove current element and advance the iterator to the next element
|
||||||
|
* NB: if you need the value to free it, read it before
|
||||||
|
* removing. ie: beware memory leaks!
|
||||||
|
* returns zero if advanced to end of table */
|
||||||
|
|
||||||
|
int
|
||||||
|
hashtable_iterator_remove(struct hashtable_itr *itr);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* search - overwrite the supplied iterator, to point to the entry
|
||||||
|
* matching the supplied key.
|
||||||
|
h points to the hashtable to be searched.
|
||||||
|
* returns zero if not found. */
|
||||||
|
int
|
||||||
|
hashtable_iterator_search(struct hashtable_itr *itr,
|
||||||
|
struct hashtable *h, void *k);
|
||||||
|
|
||||||
|
#define DEFINE_HASHTABLE_ITERATOR_SEARCH(fnname, keytype) \
|
||||||
|
int fnname (struct hashtable_itr *i, struct hashtable *h, keytype *k) \
|
||||||
|
{ \
|
||||||
|
return (hashtable_iterator_search(i,h,k)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __HASHTABLE_ITR_CWC22__*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2002, 2004, Christopher Clark
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name of the original author; nor the names of any contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
@ -0,0 +1,85 @@
|
|||||||
|
/* Copyright (C) 2002, 2004 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
|
||||||
|
|
||||||
|
#ifndef __HASHTABLE_PRIVATE_CWC22_H__
|
||||||
|
#define __HASHTABLE_PRIVATE_CWC22_H__
|
||||||
|
|
||||||
|
#include "hashtable.h"
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
struct entry
|
||||||
|
{
|
||||||
|
void *k, *v;
|
||||||
|
unsigned int h;
|
||||||
|
struct entry *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hashtable {
|
||||||
|
unsigned int tablelength;
|
||||||
|
struct entry **table;
|
||||||
|
unsigned int entrycount;
|
||||||
|
unsigned int loadlimit;
|
||||||
|
unsigned int primeindex;
|
||||||
|
unsigned int (*hashfn) (void *k);
|
||||||
|
int (*eqfn) (void *k1, void *k2);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
unsigned int
|
||||||
|
hash(struct hashtable *h, void *k);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* indexFor */
|
||||||
|
static inline unsigned int
|
||||||
|
indexFor(unsigned int tablelength, unsigned int hashvalue) {
|
||||||
|
return (hashvalue % tablelength);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Only works if tablelength == 2^N */
|
||||||
|
/*static inline unsigned int
|
||||||
|
indexFor(unsigned int tablelength, unsigned int hashvalue)
|
||||||
|
{
|
||||||
|
return (hashvalue & (tablelength - 1u));
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
#define freekey(X) free(X)
|
||||||
|
/*define freekey(X) ; */
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#endif /* __HASHTABLE_PRIVATE_CWC22_H__*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2002, Christopher Clark
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name of the original author; nor the names of any contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
280
zookeeper-client/zookeeper-client-c/src/load_gen.c
Normal file
280
zookeeper-client/zookeeper-client-c/src/load_gen.c
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zookeeper.h>
|
||||||
|
#include "zookeeper_log.h"
|
||||||
|
#include <errno.h>
|
||||||
|
#ifdef THREADED
|
||||||
|
#include <pthread.h>
|
||||||
|
#endif
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static zhandle_t *zh;
|
||||||
|
|
||||||
|
// *****************************************************************************
|
||||||
|
//
|
||||||
|
static pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
|
||||||
|
static pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
|
static pthread_cond_t counterCond=PTHREAD_COND_INITIALIZER;
|
||||||
|
static pthread_mutex_t counterLock=PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
static int counter;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ensureConnected(){
|
||||||
|
pthread_mutex_lock(&lock);
|
||||||
|
while (zoo_state(zh)!=ZOO_CONNECTED_STATE) {
|
||||||
|
pthread_cond_wait(&cond,&lock);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void incCounter(int delta){
|
||||||
|
pthread_mutex_lock(&counterLock);
|
||||||
|
counter+=delta;
|
||||||
|
pthread_cond_broadcast(&counterCond);
|
||||||
|
pthread_mutex_unlock(&counterLock);
|
||||||
|
|
||||||
|
}
|
||||||
|
void setCounter(int cnt){
|
||||||
|
pthread_mutex_lock(&counterLock);
|
||||||
|
counter=cnt;
|
||||||
|
pthread_cond_broadcast(&counterCond);
|
||||||
|
pthread_mutex_unlock(&counterLock);
|
||||||
|
|
||||||
|
}
|
||||||
|
void waitCounter(){
|
||||||
|
pthread_mutex_lock(&counterLock);
|
||||||
|
while (counter>0) {
|
||||||
|
pthread_cond_wait(&counterCond,&counterLock);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&counterLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void listener(zhandle_t *zzh, int type, int state, const char *path,void* ctx) {
|
||||||
|
if (type == ZOO_SESSION_EVENT) {
|
||||||
|
if (state == ZOO_CONNECTED_STATE || state == ZOO_READONLY_STATE) {
|
||||||
|
pthread_mutex_lock(&lock);
|
||||||
|
pthread_cond_broadcast(&cond);
|
||||||
|
pthread_mutex_unlock(&lock);
|
||||||
|
}
|
||||||
|
setCounter(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void create_completion(int rc, const char *name, const void *data) {
|
||||||
|
incCounter(-1);
|
||||||
|
if(rc!=ZOK){
|
||||||
|
LOG_ERROR(LOGSTREAM, "Failed to create a node rc=%d",rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int doCreateNodes(const char* root, int count){
|
||||||
|
char nodeName[1024];
|
||||||
|
int i;
|
||||||
|
for(i=0; i<count;i++){
|
||||||
|
int rc = 0;
|
||||||
|
snprintf(nodeName, sizeof(nodeName),"%s/%d",root,i);
|
||||||
|
incCounter(1);
|
||||||
|
rc=zoo_acreate(zh, nodeName, "first", 5, &ZOO_OPEN_ACL_UNSAFE, 0,
|
||||||
|
create_completion, 0);
|
||||||
|
if(i%1000==0){
|
||||||
|
LOG_INFO(LOGSTREAM, "Created %s", nodeName);
|
||||||
|
}
|
||||||
|
if(rc!=ZOK) return rc;
|
||||||
|
}
|
||||||
|
return ZOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int createRoot(const char* root){
|
||||||
|
char realpath[1024];
|
||||||
|
return zoo_create(zh,root,"root",4,&ZOO_OPEN_ACL_UNSAFE,0,realpath,sizeof(realpath)-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_completion(int rc, const struct Stat *stat, const void *data) {
|
||||||
|
incCounter(-1);
|
||||||
|
if(rc!=ZOK){
|
||||||
|
LOG_ERROR(LOGSTREAM, "Failed to write a node rc=%d",rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int doWrites(const char* root, int count){
|
||||||
|
char nodeName[1024];
|
||||||
|
int i;
|
||||||
|
counter=0;
|
||||||
|
for(i=0; i<count;i++){
|
||||||
|
int rc = 0;
|
||||||
|
snprintf(nodeName, sizeof(nodeName),"%s/%d",root,i);
|
||||||
|
incCounter(1);
|
||||||
|
rc=zoo_aset(zh, nodeName, "second", 6,-1,write_completion, 0);
|
||||||
|
if(rc!=ZOK) return rc;
|
||||||
|
}
|
||||||
|
return ZOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_completion(int rc, const char *value, int value_len,
|
||||||
|
const struct Stat *stat, const void *data) {
|
||||||
|
incCounter(-1);
|
||||||
|
if(rc!=ZOK){
|
||||||
|
LOG_ERROR(LOGSTREAM, "Failed to read a node rc=%d",rc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(memcmp(value,"second",6)!=0){
|
||||||
|
char buf[value_len+1];
|
||||||
|
memcpy(buf,value,value_len);buf[value_len]=0;
|
||||||
|
LOG_ERROR(LOGSTREAM, "Invalid read, expected [second], received [%s]\n",buf);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int doReads(const char* root, int count){
|
||||||
|
char nodeName[1024];
|
||||||
|
int i;
|
||||||
|
counter=0;
|
||||||
|
for(i=0; i<count;i++){
|
||||||
|
int rc = 0;
|
||||||
|
snprintf(nodeName, sizeof(nodeName),"%s/%d",root,i);
|
||||||
|
incCounter(1);
|
||||||
|
rc=zoo_aget(zh, nodeName,0,read_completion, 0);
|
||||||
|
if(rc!=ZOK) return rc;
|
||||||
|
}
|
||||||
|
return ZOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void delete_completion(int rc, const void *data) {
|
||||||
|
incCounter(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int doDeletes(const char* root, int count){
|
||||||
|
char nodeName[1024];
|
||||||
|
int i;
|
||||||
|
counter=0;
|
||||||
|
for(i=0; i<count;i++){
|
||||||
|
int rc = 0;
|
||||||
|
snprintf(nodeName, sizeof(nodeName),"%s/%d",root,i);
|
||||||
|
incCounter(1);
|
||||||
|
rc=zoo_adelete(zh, nodeName,-1,delete_completion, 0);
|
||||||
|
if(rc!=ZOK) return rc;
|
||||||
|
}
|
||||||
|
return ZOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int free_String_vector(struct String_vector *v) {
|
||||||
|
if (v->data) {
|
||||||
|
int32_t i;
|
||||||
|
for(i=0;i<v->count; i++) {
|
||||||
|
free(v->data[i]);
|
||||||
|
}
|
||||||
|
free(v->data);
|
||||||
|
v->data = 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int deletedCounter;
|
||||||
|
|
||||||
|
int recursiveDelete(const char* root){
|
||||||
|
struct String_vector children;
|
||||||
|
int i;
|
||||||
|
int rc=zoo_get_children(zh,root,0,&children);
|
||||||
|
if(rc!=ZNONODE){
|
||||||
|
if(rc!=ZOK){
|
||||||
|
LOG_ERROR(LOGSTREAM, "Failed to get children of %s, rc=%d",root,rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
for(i=0;i<children.count; i++){
|
||||||
|
int rc = 0;
|
||||||
|
char nodeName[2048];
|
||||||
|
snprintf(nodeName, sizeof(nodeName),"%s/%s",root,children.data[i]);
|
||||||
|
rc=recursiveDelete(nodeName);
|
||||||
|
if(rc!=ZOK){
|
||||||
|
free_String_vector(&children);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free_String_vector(&children);
|
||||||
|
}
|
||||||
|
if(deletedCounter%1000==0)
|
||||||
|
LOG_INFO(LOGSTREAM, "Deleting %s",root);
|
||||||
|
rc=zoo_delete(zh,root,-1);
|
||||||
|
if(rc!=ZOK){
|
||||||
|
LOG_ERROR(LOGSTREAM, "Failed to delete znode %s, rc=%d",root,rc);
|
||||||
|
}else
|
||||||
|
deletedCounter++;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usage(char *argv[]){
|
||||||
|
fprintf(stderr, "USAGE:\t%s zookeeper_host_list path #children\nor", argv[0]);
|
||||||
|
fprintf(stderr, "\t%s zookeeper_host_list path clean\n", argv[0]);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
int nodeCount;
|
||||||
|
int cleaning=0;
|
||||||
|
if (argc < 4) {
|
||||||
|
usage(argv);
|
||||||
|
}
|
||||||
|
if(strcmp("clean",argv[3])==0){
|
||||||
|
cleaning=1;
|
||||||
|
}
|
||||||
|
zoo_set_debug_level(ZOO_LOG_LEVEL_INFO);
|
||||||
|
zoo_deterministic_conn_order(1); // enable deterministic order
|
||||||
|
|
||||||
|
zh = zookeeper_init(argv[1], listener, 10000, 0, 0, 0);
|
||||||
|
if (!zh)
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
LOG_INFO(LOGSTREAM, "Checking server connection...");
|
||||||
|
ensureConnected();
|
||||||
|
if(cleaning==1){
|
||||||
|
int rc = 0;
|
||||||
|
deletedCounter=0;
|
||||||
|
rc=recursiveDelete(argv[2]);
|
||||||
|
if(rc==ZOK){
|
||||||
|
LOG_INFO(LOGSTREAM, "Successfully deleted a subtree starting at %s (%d nodes)",
|
||||||
|
argv[2],deletedCounter);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
nodeCount=atoi(argv[3]);
|
||||||
|
createRoot(argv[2]);
|
||||||
|
while(1) {
|
||||||
|
ensureConnected();
|
||||||
|
LOG_INFO(LOGSTREAM, "Creating children for path %s",argv[2]);
|
||||||
|
doCreateNodes(argv[2],nodeCount);
|
||||||
|
waitCounter();
|
||||||
|
|
||||||
|
LOG_INFO(LOGSTREAM, "Starting the write cycle for path %s",argv[2]);
|
||||||
|
doWrites(argv[2],nodeCount);
|
||||||
|
waitCounter();
|
||||||
|
LOG_INFO(LOGSTREAM, "Starting the read cycle for path %s",argv[2]);
|
||||||
|
doReads(argv[2],nodeCount);
|
||||||
|
waitCounter();
|
||||||
|
|
||||||
|
LOG_INFO(LOGSTREAM, "Starting the delete cycle for path %s",argv[2]);
|
||||||
|
doDeletes(argv[2],nodeCount);
|
||||||
|
waitCounter();
|
||||||
|
}
|
||||||
|
zookeeper_close(zh);
|
||||||
|
return 0;
|
||||||
|
}
|
571
zookeeper-client/zookeeper-client-c/src/mt_adaptor.c
Normal file
571
zookeeper-client/zookeeper-client-c/src/mt_adaptor.c
Normal file
@ -0,0 +1,571 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#ifndef THREADED
|
||||||
|
#define THREADED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(DLL_EXPORT) && !defined(USE_STATIC_LIB)
|
||||||
|
# define USE_STATIC_LIB
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _GNU_SOURCE
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "zk_adaptor.h"
|
||||||
|
#include "zookeeper_log.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
#include <signal.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int zoo_lock_auth(zhandle_t *zh)
|
||||||
|
{
|
||||||
|
return pthread_mutex_lock(&zh->auth_h.lock);
|
||||||
|
}
|
||||||
|
int zoo_unlock_auth(zhandle_t *zh)
|
||||||
|
{
|
||||||
|
return pthread_mutex_unlock(&zh->auth_h.lock);
|
||||||
|
}
|
||||||
|
int lock_buffer_list(buffer_head_t *l)
|
||||||
|
{
|
||||||
|
return pthread_mutex_lock(&l->lock);
|
||||||
|
}
|
||||||
|
int unlock_buffer_list(buffer_head_t *l)
|
||||||
|
{
|
||||||
|
return pthread_mutex_unlock(&l->lock);
|
||||||
|
}
|
||||||
|
int lock_completion_list(completion_head_t *l)
|
||||||
|
{
|
||||||
|
return pthread_mutex_lock(&l->lock);
|
||||||
|
}
|
||||||
|
int unlock_completion_list(completion_head_t *l)
|
||||||
|
{
|
||||||
|
pthread_cond_broadcast(&l->cond);
|
||||||
|
return pthread_mutex_unlock(&l->lock);
|
||||||
|
}
|
||||||
|
struct sync_completion *alloc_sync_completion(void)
|
||||||
|
{
|
||||||
|
struct sync_completion *sc = (struct sync_completion*)calloc(1, sizeof(struct sync_completion));
|
||||||
|
if (sc) {
|
||||||
|
pthread_cond_init(&sc->cond, 0);
|
||||||
|
pthread_mutex_init(&sc->lock, 0);
|
||||||
|
}
|
||||||
|
return sc;
|
||||||
|
}
|
||||||
|
int wait_sync_completion(struct sync_completion *sc)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&sc->lock);
|
||||||
|
while (!sc->complete) {
|
||||||
|
pthread_cond_wait(&sc->cond, &sc->lock);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&sc->lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_sync_completion(struct sync_completion *sc)
|
||||||
|
{
|
||||||
|
if (sc) {
|
||||||
|
pthread_mutex_destroy(&sc->lock);
|
||||||
|
pthread_cond_destroy(&sc->cond);
|
||||||
|
free(sc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void notify_sync_completion(struct sync_completion *sc)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&sc->lock);
|
||||||
|
sc->complete = 1;
|
||||||
|
pthread_cond_broadcast(&sc->cond);
|
||||||
|
pthread_mutex_unlock(&sc->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
int process_async(int outstanding_sync)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
unsigned __stdcall do_io( void * );
|
||||||
|
unsigned __stdcall do_completion( void * );
|
||||||
|
|
||||||
|
int handle_error(zhandle_t* zh, SOCKET sock, char* message)
|
||||||
|
{
|
||||||
|
LOG_ERROR(LOGCALLBACK(zh), "%s. %d",message, WSAGetLastError());
|
||||||
|
closesocket (sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--create socket pair for interupting selects.
|
||||||
|
int create_socket_pair(zhandle_t* zh, SOCKET fds[2])
|
||||||
|
{
|
||||||
|
struct sockaddr_in inaddr;
|
||||||
|
struct sockaddr addr;
|
||||||
|
int yes=1;
|
||||||
|
int len=0;
|
||||||
|
|
||||||
|
SOCKET lst=socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);
|
||||||
|
if (lst == INVALID_SOCKET ){
|
||||||
|
LOG_ERROR(LOGCALLBACK(zh), "Error creating socket. %d",WSAGetLastError());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memset(&inaddr, 0, sizeof(inaddr));
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
inaddr.sin_family = AF_INET;
|
||||||
|
inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||||
|
inaddr.sin_port = 0; //--system assigns the port
|
||||||
|
|
||||||
|
if ( setsockopt(lst,SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(yes)) == SOCKET_ERROR ) {
|
||||||
|
return handle_error(zh, lst,"Error trying to set socket option.");
|
||||||
|
}
|
||||||
|
if (bind(lst,(struct sockaddr *)&inaddr,sizeof(inaddr)) == SOCKET_ERROR){
|
||||||
|
return handle_error(zh, lst,"Error trying to bind socket.");
|
||||||
|
}
|
||||||
|
if (listen(lst,1) == SOCKET_ERROR){
|
||||||
|
return handle_error(zh, lst,"Error trying to listen on socket.");
|
||||||
|
}
|
||||||
|
len=sizeof(inaddr);
|
||||||
|
getsockname(lst, &addr,&len);
|
||||||
|
fds[0]=socket(AF_INET, SOCK_STREAM,0);
|
||||||
|
if (connect(fds[0],&addr,len) == SOCKET_ERROR){
|
||||||
|
return handle_error(zh, lst, "Error while connecting to socket.");
|
||||||
|
}
|
||||||
|
if ((fds[1]=accept(lst,0,0)) == INVALID_SOCKET){
|
||||||
|
closesocket(fds[0]);
|
||||||
|
return handle_error(zh, lst, "Error while accepting socket connection.");
|
||||||
|
}
|
||||||
|
closesocket(lst);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void *do_io(void *);
|
||||||
|
void *do_completion(void *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
int wakeup_io_thread(zhandle_t *zh);
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
static int set_nonblock(SOCKET fd){
|
||||||
|
ULONG nonblocking_flag = 1;
|
||||||
|
if (ioctlsocket(fd, FIONBIO, &nonblocking_flag) == 0)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static int set_nonblock(int fd){
|
||||||
|
long l = fcntl(fd, F_GETFL);
|
||||||
|
if(l & O_NONBLOCK) return 0;
|
||||||
|
return fcntl(fd, F_SETFL, l | O_NONBLOCK);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void wait_for_others(zhandle_t* zh)
|
||||||
|
{
|
||||||
|
struct adaptor_threads* adaptor=zh->adaptor_priv;
|
||||||
|
pthread_mutex_lock(&adaptor->lock);
|
||||||
|
while(adaptor->threadsToWait>0)
|
||||||
|
pthread_cond_wait(&adaptor->cond,&adaptor->lock);
|
||||||
|
pthread_mutex_unlock(&adaptor->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void notify_thread_ready(zhandle_t* zh)
|
||||||
|
{
|
||||||
|
struct adaptor_threads* adaptor=zh->adaptor_priv;
|
||||||
|
pthread_mutex_lock(&adaptor->lock);
|
||||||
|
adaptor->threadsToWait--;
|
||||||
|
pthread_cond_broadcast(&adaptor->cond);
|
||||||
|
while(adaptor->threadsToWait>0)
|
||||||
|
pthread_cond_wait(&adaptor->cond,&adaptor->lock);
|
||||||
|
pthread_mutex_unlock(&adaptor->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void start_threads(zhandle_t* zh)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
struct adaptor_threads* adaptor=zh->adaptor_priv;
|
||||||
|
pthread_cond_init(&adaptor->cond,0);
|
||||||
|
pthread_mutex_init(&adaptor->lock,0);
|
||||||
|
adaptor->threadsToWait=2; // wait for 2 threads before opening the barrier
|
||||||
|
|
||||||
|
// use api_prolog() to make sure zhandle doesn't get destroyed
|
||||||
|
// while initialization is in progress
|
||||||
|
api_prolog(zh);
|
||||||
|
LOG_DEBUG(LOGCALLBACK(zh), "starting threads...");
|
||||||
|
rc=pthread_create(&adaptor->io, 0, do_io, zh);
|
||||||
|
assert("pthread_create() failed for the IO thread"&&!rc);
|
||||||
|
rc=pthread_create(&adaptor->completion, 0, do_completion, zh);
|
||||||
|
assert("pthread_create() failed for the completion thread"&&!rc);
|
||||||
|
wait_for_others(zh);
|
||||||
|
api_epilog(zh, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int adaptor_init(zhandle_t *zh)
|
||||||
|
{
|
||||||
|
pthread_mutexattr_t recursive_mx_attr;
|
||||||
|
struct adaptor_threads *adaptor_threads = calloc(1, sizeof(*adaptor_threads));
|
||||||
|
if (!adaptor_threads) {
|
||||||
|
LOG_ERROR(LOGCALLBACK(zh), "Out of memory");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We use a pipe for interrupting select() in unix/sol and socketpair in windows. */
|
||||||
|
#ifdef WIN32
|
||||||
|
if (create_socket_pair(zh, adaptor_threads->self_pipe) == -1){
|
||||||
|
LOG_ERROR(LOGCALLBACK(zh), "Can't make a socket.");
|
||||||
|
#else
|
||||||
|
if(pipe(adaptor_threads->self_pipe)==-1) {
|
||||||
|
LOG_ERROR(LOGCALLBACK(zh), "Can't make a pipe %d",errno);
|
||||||
|
#endif
|
||||||
|
free(adaptor_threads);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
set_nonblock(adaptor_threads->self_pipe[1]);
|
||||||
|
set_nonblock(adaptor_threads->self_pipe[0]);
|
||||||
|
|
||||||
|
pthread_mutex_init(&zh->auth_h.lock,0);
|
||||||
|
|
||||||
|
zh->adaptor_priv = adaptor_threads;
|
||||||
|
pthread_mutex_init(&zh->to_process.lock,0);
|
||||||
|
pthread_mutex_init(&adaptor_threads->zh_lock,0);
|
||||||
|
pthread_mutex_init(&adaptor_threads->reconfig_lock,0);
|
||||||
|
pthread_mutex_init(&adaptor_threads->watchers_lock,0);
|
||||||
|
// to_send must be recursive mutex
|
||||||
|
pthread_mutexattr_init(&recursive_mx_attr);
|
||||||
|
pthread_mutexattr_settype(&recursive_mx_attr, PTHREAD_MUTEX_RECURSIVE);
|
||||||
|
pthread_mutex_init(&zh->to_send.lock,&recursive_mx_attr);
|
||||||
|
pthread_mutexattr_destroy(&recursive_mx_attr);
|
||||||
|
|
||||||
|
pthread_mutex_init(&zh->sent_requests.lock,0);
|
||||||
|
pthread_cond_init(&zh->sent_requests.cond,0);
|
||||||
|
pthread_mutex_init(&zh->completions_to_process.lock,0);
|
||||||
|
pthread_cond_init(&zh->completions_to_process.cond,0);
|
||||||
|
start_threads(zh);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void adaptor_finish(zhandle_t *zh)
|
||||||
|
{
|
||||||
|
struct adaptor_threads *adaptor_threads;
|
||||||
|
// make sure zh doesn't get destroyed until after we're done here
|
||||||
|
api_prolog(zh);
|
||||||
|
adaptor_threads = zh->adaptor_priv;
|
||||||
|
if(adaptor_threads==0) {
|
||||||
|
api_epilog(zh,0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!pthread_equal(adaptor_threads->io,pthread_self())){
|
||||||
|
wakeup_io_thread(zh);
|
||||||
|
pthread_join(adaptor_threads->io, 0);
|
||||||
|
}else
|
||||||
|
pthread_detach(adaptor_threads->io);
|
||||||
|
|
||||||
|
if(!pthread_equal(adaptor_threads->completion,pthread_self())){
|
||||||
|
pthread_mutex_lock(&zh->completions_to_process.lock);
|
||||||
|
pthread_cond_broadcast(&zh->completions_to_process.cond);
|
||||||
|
pthread_mutex_unlock(&zh->completions_to_process.lock);
|
||||||
|
pthread_join(adaptor_threads->completion, 0);
|
||||||
|
}else
|
||||||
|
pthread_detach(adaptor_threads->completion);
|
||||||
|
|
||||||
|
api_epilog(zh,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void adaptor_destroy(zhandle_t *zh)
|
||||||
|
{
|
||||||
|
struct adaptor_threads *adaptor = zh->adaptor_priv;
|
||||||
|
if(adaptor==0) return;
|
||||||
|
|
||||||
|
pthread_cond_destroy(&adaptor->cond);
|
||||||
|
pthread_mutex_destroy(&adaptor->lock);
|
||||||
|
pthread_mutex_destroy(&zh->to_process.lock);
|
||||||
|
pthread_mutex_destroy(&zh->to_send.lock);
|
||||||
|
pthread_mutex_destroy(&zh->sent_requests.lock);
|
||||||
|
pthread_cond_destroy(&zh->sent_requests.cond);
|
||||||
|
pthread_mutex_destroy(&zh->completions_to_process.lock);
|
||||||
|
pthread_cond_destroy(&zh->completions_to_process.cond);
|
||||||
|
pthread_mutex_destroy(&adaptor->zh_lock);
|
||||||
|
|
||||||
|
pthread_mutex_destroy(&zh->auth_h.lock);
|
||||||
|
|
||||||
|
close(adaptor->self_pipe[0]);
|
||||||
|
close(adaptor->self_pipe[1]);
|
||||||
|
free(adaptor);
|
||||||
|
zh->adaptor_priv=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wakeup_io_thread(zhandle_t *zh)
|
||||||
|
{
|
||||||
|
struct adaptor_threads *adaptor_threads = zh->adaptor_priv;
|
||||||
|
char c=0;
|
||||||
|
#ifndef WIN32
|
||||||
|
return write(adaptor_threads->self_pipe[1],&c,1)==1? ZOK: ZSYSTEMERROR;
|
||||||
|
#else
|
||||||
|
return send(adaptor_threads->self_pipe[1], &c, 1, 0)==1? ZOK: ZSYSTEMERROR;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int adaptor_send_queue(zhandle_t *zh, int timeout)
|
||||||
|
{
|
||||||
|
if(!zh->close_requested)
|
||||||
|
return wakeup_io_thread(zh);
|
||||||
|
// don't rely on the IO thread to send the messages if the app has
|
||||||
|
// requested to close
|
||||||
|
return flush_send_queue(zh, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* These two are declared here because we will run the event loop
|
||||||
|
* and not the client */
|
||||||
|
#ifdef WIN32
|
||||||
|
int zookeeper_interest(zhandle_t *zh, SOCKET *fd, int *interest,
|
||||||
|
struct timeval *tv);
|
||||||
|
#else
|
||||||
|
int zookeeper_interest(zhandle_t *zh, int *fd, int *interest,
|
||||||
|
struct timeval *tv);
|
||||||
|
#endif
|
||||||
|
int zookeeper_process(zhandle_t *zh, int events);
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
unsigned __stdcall do_io( void * v)
|
||||||
|
#else
|
||||||
|
void *do_io(void *v)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
zhandle_t *zh = (zhandle_t*)v;
|
||||||
|
#ifndef WIN32
|
||||||
|
struct pollfd fds[2];
|
||||||
|
struct adaptor_threads *adaptor_threads = zh->adaptor_priv;
|
||||||
|
|
||||||
|
api_prolog(zh);
|
||||||
|
notify_thread_ready(zh);
|
||||||
|
LOG_DEBUG(LOGCALLBACK(zh), "started IO thread");
|
||||||
|
fds[0].fd=adaptor_threads->self_pipe[0];
|
||||||
|
fds[0].events=POLLIN;
|
||||||
|
while(!zh->close_requested) {
|
||||||
|
zh->io_count++;
|
||||||
|
struct timeval tv;
|
||||||
|
int fd;
|
||||||
|
int interest;
|
||||||
|
int timeout;
|
||||||
|
int maxfd=1;
|
||||||
|
|
||||||
|
zookeeper_interest(zh, &fd, &interest, &tv);
|
||||||
|
if (fd != -1) {
|
||||||
|
fds[1].fd=fd;
|
||||||
|
fds[1].events=(interest&ZOOKEEPER_READ)?POLLIN:0;
|
||||||
|
fds[1].events|=(interest&ZOOKEEPER_WRITE)?POLLOUT:0;
|
||||||
|
maxfd=2;
|
||||||
|
}
|
||||||
|
timeout=tv.tv_sec * 1000 + (tv.tv_usec/1000);
|
||||||
|
|
||||||
|
poll(fds,maxfd,timeout);
|
||||||
|
if (fd != -1) {
|
||||||
|
interest=(fds[1].revents&POLLIN)?ZOOKEEPER_READ:0;
|
||||||
|
interest|=((fds[1].revents&POLLOUT)||(fds[1].revents&POLLHUP))?ZOOKEEPER_WRITE:0;
|
||||||
|
}
|
||||||
|
if(fds[0].revents&POLLIN){
|
||||||
|
// flush the pipe
|
||||||
|
char b[128];
|
||||||
|
while(read(adaptor_threads->self_pipe[0],b,sizeof(b))==sizeof(b)){}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
fd_set rfds, wfds;
|
||||||
|
struct adaptor_threads *adaptor_threads = zh->adaptor_priv;
|
||||||
|
api_prolog(zh);
|
||||||
|
notify_thread_ready(zh);
|
||||||
|
LOG_DEBUG(LOGCALLBACK(zh), "started IO thread");
|
||||||
|
|
||||||
|
while(!zh->close_requested) {
|
||||||
|
struct timeval tv;
|
||||||
|
SOCKET fd;
|
||||||
|
int interest;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
zookeeper_interest(zh, &fd, &interest, &tv);
|
||||||
|
|
||||||
|
// FD_ZERO is cheap on Win32, it just sets count of elements to zero.
|
||||||
|
// It needs to be done to ensure no stale entries.
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_ZERO(&wfds);
|
||||||
|
|
||||||
|
if (fd != -1) {
|
||||||
|
if (interest&ZOOKEEPER_READ) {
|
||||||
|
FD_SET(fd, &rfds);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interest&ZOOKEEPER_WRITE) {
|
||||||
|
FD_SET(fd, &wfds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always interested in self_pipe.
|
||||||
|
FD_SET(adaptor_threads->self_pipe[0], &rfds);
|
||||||
|
|
||||||
|
rc = select(/* unused */0, &rfds, &wfds, NULL, &tv);
|
||||||
|
if (rc > 0) {
|
||||||
|
interest=(FD_ISSET(fd, &rfds))? ZOOKEEPER_READ: 0;
|
||||||
|
interest|=(FD_ISSET(fd, &wfds))? ZOOKEEPER_WRITE: 0;
|
||||||
|
|
||||||
|
if (FD_ISSET(adaptor_threads->self_pipe[0], &rfds)){
|
||||||
|
// flush the pipe/socket
|
||||||
|
char b[128];
|
||||||
|
while(recv(adaptor_threads->self_pipe[0],b,sizeof(b), 0)==sizeof(b)){}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (rc < 0) {
|
||||||
|
LOG_ERROR(LOGCALLBACK(zh), ("select() failed %d [%d].", rc, WSAGetLastError()));
|
||||||
|
|
||||||
|
// Clear interest events for zookeeper_process if select() fails.
|
||||||
|
interest = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
// dispatch zookeeper events
|
||||||
|
zookeeper_process(zh, interest);
|
||||||
|
// check the current state of the zhandle and terminate
|
||||||
|
// if it is_unrecoverable()
|
||||||
|
if(is_unrecoverable(zh))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
api_epilog(zh, 0);
|
||||||
|
LOG_DEBUG(LOGCALLBACK(zh), "IO thread terminated");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
unsigned __stdcall do_completion( void * v)
|
||||||
|
#else
|
||||||
|
void *do_completion(void *v)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
zhandle_t *zh = v;
|
||||||
|
api_prolog(zh);
|
||||||
|
notify_thread_ready(zh);
|
||||||
|
LOG_DEBUG(LOGCALLBACK(zh), "started completion thread");
|
||||||
|
while(!zh->close_requested) {
|
||||||
|
pthread_mutex_lock(&zh->completions_to_process.lock);
|
||||||
|
while(!zh->completions_to_process.head && !zh->close_requested) {
|
||||||
|
pthread_cond_wait(&zh->completions_to_process.cond, &zh->completions_to_process.lock);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&zh->completions_to_process.lock);
|
||||||
|
process_completions(zh);
|
||||||
|
}
|
||||||
|
api_epilog(zh, 0);
|
||||||
|
LOG_DEBUG(LOGCALLBACK(zh), "completion thread terminated");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t inc_ref_counter(zhandle_t* zh,int i)
|
||||||
|
{
|
||||||
|
int incr=(i<0?-1:(i>0?1:0));
|
||||||
|
// fetch_and_add implements atomic post-increment
|
||||||
|
int v=fetch_and_add(&zh->ref_counter,incr);
|
||||||
|
// inc_ref_counter wants pre-increment
|
||||||
|
v+=incr; // simulate pre-increment
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t fetch_and_add(volatile int32_t* operand, int incr)
|
||||||
|
{
|
||||||
|
#ifndef WIN32
|
||||||
|
return __sync_fetch_and_add(operand, incr);
|
||||||
|
#else
|
||||||
|
return InterlockedExchangeAdd(operand, incr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure the static xid is initialized before any threads started
|
||||||
|
__attribute__((constructor)) int32_t get_xid()
|
||||||
|
{
|
||||||
|
static int32_t xid = -1;
|
||||||
|
if (xid == -1) {
|
||||||
|
xid = time(0);
|
||||||
|
}
|
||||||
|
return fetch_and_add(&xid,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int lock_reconfig(struct _zhandle *zh)
|
||||||
|
{
|
||||||
|
struct adaptor_threads *adaptor = zh->adaptor_priv;
|
||||||
|
if (adaptor) {
|
||||||
|
return pthread_mutex_lock(&adaptor->reconfig_lock);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int unlock_reconfig(struct _zhandle *zh)
|
||||||
|
{
|
||||||
|
struct adaptor_threads *adaptor = zh->adaptor_priv;
|
||||||
|
if (adaptor) {
|
||||||
|
return pthread_mutex_unlock(&adaptor->reconfig_lock);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int lock_watchers(struct _zhandle *zh)
|
||||||
|
{
|
||||||
|
struct adaptor_threads *adaptor = zh->adaptor_priv;
|
||||||
|
if (adaptor) {
|
||||||
|
return pthread_mutex_lock(&adaptor->watchers_lock);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int unlock_watchers(struct _zhandle *zh)
|
||||||
|
{
|
||||||
|
struct adaptor_threads *adaptor = zh->adaptor_priv;
|
||||||
|
if (adaptor) {
|
||||||
|
return pthread_mutex_unlock(&adaptor->watchers_lock);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int enter_critical(zhandle_t* zh)
|
||||||
|
{
|
||||||
|
struct adaptor_threads *adaptor = zh->adaptor_priv;
|
||||||
|
if (adaptor) {
|
||||||
|
return pthread_mutex_lock(&adaptor->zh_lock);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int leave_critical(zhandle_t* zh)
|
||||||
|
{
|
||||||
|
struct adaptor_threads *adaptor = zh->adaptor_priv;
|
||||||
|
if (adaptor) {
|
||||||
|
return pthread_mutex_unlock(&adaptor->zh_lock);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
372
zookeeper-client/zookeeper-client-c/src/recordio.c
Normal file
372
zookeeper-client/zookeeper-client-c/src/recordio.c
Normal file
@ -0,0 +1,372 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <recordio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#ifndef WIN32
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#else
|
||||||
|
#include <winsock2.h> /* for _htonl and _ntohl */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void deallocate_String(char **s)
|
||||||
|
{
|
||||||
|
if (*s)
|
||||||
|
free(*s);
|
||||||
|
*s = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void deallocate_Buffer(struct buffer *b)
|
||||||
|
{
|
||||||
|
if (b->buff)
|
||||||
|
free(b->buff);
|
||||||
|
b->buff = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct buff_struct {
|
||||||
|
int32_t len;
|
||||||
|
int32_t off;
|
||||||
|
char *buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int resize_buffer(struct buff_struct *s, int newlen)
|
||||||
|
{
|
||||||
|
char *buffer= NULL;
|
||||||
|
while (s->len < newlen) {
|
||||||
|
s->len *= 2;
|
||||||
|
}
|
||||||
|
buffer = (char*)realloc(s->buffer, s->len);
|
||||||
|
if (!buffer) {
|
||||||
|
s->buffer = 0;
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
s->buffer = buffer;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int oa_start_record(struct oarchive *oa, const char *tag)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int oa_end_record(struct oarchive *oa, const char *tag)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int oa_serialize_int(struct oarchive *oa, const char *tag, const int32_t *d)
|
||||||
|
{
|
||||||
|
struct buff_struct *priv = oa->priv;
|
||||||
|
int32_t i = htonl(*d);
|
||||||
|
if ((priv->len - priv->off) < sizeof(i)) {
|
||||||
|
int rc = resize_buffer(priv, priv->len + sizeof(i));
|
||||||
|
if (rc < 0) return rc;
|
||||||
|
}
|
||||||
|
memcpy(priv->buffer+priv->off, &i, sizeof(i));
|
||||||
|
priv->off+=sizeof(i);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int64_t zoo_htonll(int64_t v)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
char *s = (char *)&v;
|
||||||
|
if (htonl(1) == 1) {
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
int tmp = s[i];
|
||||||
|
s[i] = s[8-i-1];
|
||||||
|
s[8-i-1] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
int oa_serialize_long(struct oarchive *oa, const char *tag, const int64_t *d)
|
||||||
|
{
|
||||||
|
const int64_t i = zoo_htonll(*d);
|
||||||
|
struct buff_struct *priv = oa->priv;
|
||||||
|
if ((priv->len - priv->off) < sizeof(i)) {
|
||||||
|
int rc = resize_buffer(priv, priv->len + sizeof(i));
|
||||||
|
if (rc < 0) return rc;
|
||||||
|
}
|
||||||
|
memcpy(priv->buffer+priv->off, &i, sizeof(i));
|
||||||
|
priv->off+=sizeof(i);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int oa_start_vector(struct oarchive *oa, const char *tag, const int32_t *count)
|
||||||
|
{
|
||||||
|
return oa_serialize_int(oa, tag, count);
|
||||||
|
}
|
||||||
|
int oa_end_vector(struct oarchive *oa, const char *tag)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int oa_serialize_bool(struct oarchive *oa, const char *name, const int32_t *i)
|
||||||
|
{
|
||||||
|
//return oa_serialize_int(oa, name, i);
|
||||||
|
struct buff_struct *priv = oa->priv;
|
||||||
|
if ((priv->len - priv->off) < 1) {
|
||||||
|
int rc = resize_buffer(priv, priv->len + 1);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
priv->buffer[priv->off] = (*i == 0 ? '\0' : '\1');
|
||||||
|
priv->off++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static const int32_t negone = -1;
|
||||||
|
int oa_serialize_buffer(struct oarchive *oa, const char *name,
|
||||||
|
const struct buffer *b)
|
||||||
|
{
|
||||||
|
struct buff_struct *priv = oa->priv;
|
||||||
|
int rc;
|
||||||
|
if (!b) {
|
||||||
|
return oa_serialize_int(oa, "len", &negone);
|
||||||
|
}
|
||||||
|
rc = oa_serialize_int(oa, "len", &b->len);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
// this means a buffer of NUll
|
||||||
|
// with size of -1. This is
|
||||||
|
// waht we use in java serialization for NULL
|
||||||
|
if (b->len == -1) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
if ((priv->len - priv->off) < b->len) {
|
||||||
|
rc = resize_buffer(priv, priv->len + b->len);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
memcpy(priv->buffer+priv->off, b->buff, b->len);
|
||||||
|
priv->off += b->len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int oa_serialize_string(struct oarchive *oa, const char *name, char **s)
|
||||||
|
{
|
||||||
|
struct buff_struct *priv = oa->priv;
|
||||||
|
int32_t len;
|
||||||
|
int rc;
|
||||||
|
if (!*s) {
|
||||||
|
oa_serialize_int(oa, "len", &negone);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
len = strlen(*s);
|
||||||
|
rc = oa_serialize_int(oa, "len", &len);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
if ((priv->len - priv->off) < len) {
|
||||||
|
rc = resize_buffer(priv, priv->len + len);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
memcpy(priv->buffer+priv->off, *s, len);
|
||||||
|
priv->off += len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int ia_start_record(struct iarchive *ia, const char *tag)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int ia_end_record(struct iarchive *ia, const char *tag)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int ia_deserialize_int(struct iarchive *ia, const char *tag, int32_t *count)
|
||||||
|
{
|
||||||
|
struct buff_struct *priv = ia->priv;
|
||||||
|
if ((priv->len - priv->off) < sizeof(*count)) {
|
||||||
|
return -E2BIG;
|
||||||
|
}
|
||||||
|
memcpy(count, priv->buffer+priv->off, sizeof(*count));
|
||||||
|
priv->off+=sizeof(*count);
|
||||||
|
*count = ntohl(*count);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ia_deserialize_long(struct iarchive *ia, const char *tag, int64_t *count)
|
||||||
|
{
|
||||||
|
struct buff_struct *priv = ia->priv;
|
||||||
|
int64_t v = 0;
|
||||||
|
if ((priv->len - priv->off) < sizeof(*count)) {
|
||||||
|
return -E2BIG;
|
||||||
|
}
|
||||||
|
memcpy(count, priv->buffer+priv->off, sizeof(*count));
|
||||||
|
priv->off+=sizeof(*count);
|
||||||
|
v = zoo_htonll(*count); // htonll and ntohll do the same
|
||||||
|
*count = v;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int ia_start_vector(struct iarchive *ia, const char *tag, int32_t *count)
|
||||||
|
{
|
||||||
|
return ia_deserialize_int(ia, tag, count);
|
||||||
|
}
|
||||||
|
int ia_end_vector(struct iarchive *ia, const char *tag)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int ia_deserialize_bool(struct iarchive *ia, const char *name, int32_t *v)
|
||||||
|
{
|
||||||
|
struct buff_struct *priv = ia->priv;
|
||||||
|
//fprintf(stderr, "Deserializing bool %d\n", priv->off);
|
||||||
|
//return ia_deserialize_int(ia, name, v);
|
||||||
|
if ((priv->len - priv->off) < 1) {
|
||||||
|
return -E2BIG;
|
||||||
|
}
|
||||||
|
*v = priv->buffer[priv->off];
|
||||||
|
priv->off+=1;
|
||||||
|
//fprintf(stderr, "Deserializing bool end %d\n", priv->off);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int ia_deserialize_buffer(struct iarchive *ia, const char *name,
|
||||||
|
struct buffer *b)
|
||||||
|
{
|
||||||
|
struct buff_struct *priv = ia->priv;
|
||||||
|
int rc = ia_deserialize_int(ia, "len", &b->len);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
if ((priv->len - priv->off) < b->len) {
|
||||||
|
return -E2BIG;
|
||||||
|
}
|
||||||
|
// set the buffer to null
|
||||||
|
if (b->len == -1) {
|
||||||
|
b->buff = NULL;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
b->buff = malloc(b->len);
|
||||||
|
if (!b->buff) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
memcpy(b->buff, priv->buffer+priv->off, b->len);
|
||||||
|
priv->off += b->len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int ia_deserialize_string(struct iarchive *ia, const char *name, char **s)
|
||||||
|
{
|
||||||
|
struct buff_struct *priv = ia->priv;
|
||||||
|
int32_t len;
|
||||||
|
int rc = ia_deserialize_int(ia, "len", &len);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
if ((priv->len - priv->off) < len) {
|
||||||
|
return -E2BIG;
|
||||||
|
}
|
||||||
|
if (len < 0) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
*s = malloc(len+1);
|
||||||
|
if (!*s) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
memcpy(*s, priv->buffer+priv->off, len);
|
||||||
|
(*s)[len] = '\0';
|
||||||
|
priv->off += len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct iarchive ia_default = {
|
||||||
|
ia_start_record,
|
||||||
|
ia_end_record,
|
||||||
|
ia_start_vector,
|
||||||
|
ia_end_vector,
|
||||||
|
ia_deserialize_bool,
|
||||||
|
ia_deserialize_int,
|
||||||
|
ia_deserialize_long ,
|
||||||
|
ia_deserialize_buffer,
|
||||||
|
ia_deserialize_string};
|
||||||
|
|
||||||
|
static struct oarchive oa_default = {
|
||||||
|
oa_start_record,
|
||||||
|
oa_end_record,
|
||||||
|
oa_start_vector,
|
||||||
|
oa_end_vector,
|
||||||
|
oa_serialize_bool,
|
||||||
|
oa_serialize_int,
|
||||||
|
oa_serialize_long ,
|
||||||
|
oa_serialize_buffer,
|
||||||
|
oa_serialize_string};
|
||||||
|
|
||||||
|
struct iarchive *create_buffer_iarchive(char *buffer, int len)
|
||||||
|
{
|
||||||
|
struct iarchive *ia;
|
||||||
|
struct buff_struct *buff;
|
||||||
|
ia = malloc(sizeof(*ia));
|
||||||
|
if (!ia) return 0;
|
||||||
|
buff = malloc(sizeof(struct buff_struct));
|
||||||
|
if (!buff) {
|
||||||
|
free(ia);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*ia = ia_default;
|
||||||
|
buff->off = 0;
|
||||||
|
buff->buffer = buffer;
|
||||||
|
buff->len = len;
|
||||||
|
ia->priv = buff;
|
||||||
|
return ia;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct oarchive *create_buffer_oarchive()
|
||||||
|
{
|
||||||
|
struct oarchive *oa;
|
||||||
|
struct buff_struct *buff;
|
||||||
|
oa = malloc(sizeof(*oa));
|
||||||
|
if (!oa) return 0;
|
||||||
|
buff = malloc(sizeof(struct buff_struct));
|
||||||
|
if (!buff) {
|
||||||
|
free(oa);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*oa = oa_default;
|
||||||
|
buff->off = 0;
|
||||||
|
buff->buffer = malloc(128);
|
||||||
|
buff->len = 128;
|
||||||
|
oa->priv = buff;
|
||||||
|
return oa;
|
||||||
|
}
|
||||||
|
|
||||||
|
void close_buffer_iarchive(struct iarchive **ia)
|
||||||
|
{
|
||||||
|
free((*ia)->priv);
|
||||||
|
free(*ia);
|
||||||
|
*ia = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void close_buffer_oarchive(struct oarchive **oa, int free_buffer)
|
||||||
|
{
|
||||||
|
if (free_buffer) {
|
||||||
|
struct buff_struct *buff = (struct buff_struct *)(*oa)->priv;
|
||||||
|
if (buff->buffer) {
|
||||||
|
free(buff->buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free((*oa)->priv);
|
||||||
|
free(*oa);
|
||||||
|
*oa = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *get_buffer(struct oarchive *oa)
|
||||||
|
{
|
||||||
|
struct buff_struct *buff = oa->priv;
|
||||||
|
return buff->buffer;
|
||||||
|
}
|
||||||
|
int get_buffer_len(struct oarchive *oa)
|
||||||
|
{
|
||||||
|
struct buff_struct *buff = oa->priv;
|
||||||
|
return buff->off;
|
||||||
|
}
|
115
zookeeper-client/zookeeper-client-c/src/st_adaptor.c
Normal file
115
zookeeper-client/zookeeper-client-c/src/st_adaptor.c
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(DLL_EXPORT) && !defined(USE_STATIC_LIB)
|
||||||
|
# define USE_STATIC_LIB
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "zk_adaptor.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
int zoo_lock_auth(zhandle_t *zh)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int zoo_unlock_auth(zhandle_t *zh)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int lock_buffer_list(buffer_head_t *l)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int unlock_buffer_list(buffer_head_t *l)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int lock_completion_list(completion_head_t *l)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int unlock_completion_list(completion_head_t *l)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int process_async(int outstanding_sync)
|
||||||
|
{
|
||||||
|
return outstanding_sync == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int adaptor_init(zhandle_t *zh)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void adaptor_finish(zhandle_t *zh){}
|
||||||
|
|
||||||
|
void adaptor_destroy(zhandle_t *zh){}
|
||||||
|
|
||||||
|
int flush_send_queue(zhandle_t *, int);
|
||||||
|
|
||||||
|
int adaptor_send_queue(zhandle_t *zh, int timeout)
|
||||||
|
{
|
||||||
|
return flush_send_queue(zh, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t inc_ref_counter(zhandle_t* zh,int i)
|
||||||
|
{
|
||||||
|
zh->ref_counter+=(i<0?-1:(i>0?1:0));
|
||||||
|
return zh->ref_counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t get_xid()
|
||||||
|
{
|
||||||
|
static int32_t xid = -1;
|
||||||
|
if (xid == -1) {
|
||||||
|
xid = time(0);
|
||||||
|
}
|
||||||
|
return xid++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lock_reconfig(struct _zhandle *zh)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int unlock_reconfig(struct _zhandle *zh)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lock_watchers(struct _zhandle *zh)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int unlock_watchers(struct _zhandle *zh)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int enter_critical(zhandle_t* zh)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int leave_critical(zhandle_t* zh)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
307
zookeeper-client/zookeeper-client-c/src/winport.c
Normal file
307
zookeeper-client/zookeeper-client-c/src/winport.c
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include "winport.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h> /* for int64_t */
|
||||||
|
#include <winsock2.h> /* must always be included before ws2tcpip.h */
|
||||||
|
#include <ws2tcpip.h> /* for SOCKET */
|
||||||
|
|
||||||
|
int pthread_mutex_lock(pthread_mutex_t* _mutex ){
|
||||||
|
int rc = WaitForSingleObject( *_mutex, // handle to mutex
|
||||||
|
INFINITE); // no time-out interval
|
||||||
|
return ((rc == WAIT_OBJECT_0) ? 0: rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_mutex_unlock( pthread_mutex_t* _mutex ){
|
||||||
|
int rc = ReleaseMutex(*_mutex);
|
||||||
|
return ((rc != 0)? 0: GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_mutex_init(pthread_mutex_t* _mutex, void* ignoredAttr){
|
||||||
|
//use CreateMutex as we are using the HANDLES in pthread_cond
|
||||||
|
*_mutex = CreateMutex(
|
||||||
|
NULL, // default security attributes
|
||||||
|
FALSE, // initially not owned
|
||||||
|
NULL); // unnamed mutex
|
||||||
|
return ((*_mutex == NULL) ? GetLastError() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_mutex_destroy(pthread_mutex_t* _mutex)
|
||||||
|
{
|
||||||
|
int rc = CloseHandle(*_mutex);
|
||||||
|
return ((rc != 0)? 0: GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, unsigned (__stdcall* start_routine)(void* a), void *arg)
|
||||||
|
{
|
||||||
|
int _intThreadId;
|
||||||
|
(*thread).thread_handle = (HANDLE)_beginthreadex( NULL, 0, start_routine , arg, 0, (unsigned int*)&_intThreadId );
|
||||||
|
(*thread).thread_id = _intThreadId;
|
||||||
|
return (((*thread).thread_handle == 0 ) ? errno : 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int pthread_equal(pthread_t t1, pthread_t t2){
|
||||||
|
//Is there a better way to do this? GetThreadId(handle) is only supported Windows 2003 n above.
|
||||||
|
return ((t1.thread_id == t2.thread_id) ? 1:0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_t pthread_self(){
|
||||||
|
pthread_t thread_self;
|
||||||
|
thread_self.thread_handle = GetCurrentThread();
|
||||||
|
thread_self.thread_id = GetCurrentThreadId();
|
||||||
|
return thread_self;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_join(pthread_t _thread, void** ignore)
|
||||||
|
{
|
||||||
|
int rc = WaitForSingleObject( _thread.thread_handle, INFINITE );
|
||||||
|
return ((rc == WAIT_OBJECT_0) ? 0: rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_detach(pthread_t _thread)
|
||||||
|
{
|
||||||
|
int rc = CloseHandle(_thread.thread_handle) ;
|
||||||
|
return (rc != 0) ? 0: GetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
void pthread_mutexattr_init(pthread_mutexattr_t* ignore){}
|
||||||
|
void pthread_mutexattr_settype(pthread_mutexattr_t* ingore_attr, int ignore){}
|
||||||
|
void pthread_mutexattr_destroy(pthread_mutexattr_t* ignore_attr){}
|
||||||
|
|
||||||
|
int
|
||||||
|
pthread_cond_init (pthread_cond_t *cv,
|
||||||
|
const pthread_condattr_t * ignore)
|
||||||
|
{
|
||||||
|
cv->waiters_count_ = 0;
|
||||||
|
cv->was_broadcast_ = 0;
|
||||||
|
cv->sema_ = CreateSemaphore (NULL, // no security
|
||||||
|
0, // initially 0
|
||||||
|
0x7fffffff, // max count
|
||||||
|
NULL); // unnamed
|
||||||
|
if (cv->sema_ == NULL )
|
||||||
|
return GetLastError();
|
||||||
|
InitializeCriticalSection (&cv->waiters_count_lock_);
|
||||||
|
cv->waiters_done_ = CreateEvent (NULL, // no security
|
||||||
|
FALSE, // auto-reset
|
||||||
|
FALSE, // non-signaled initially
|
||||||
|
NULL); // unnamed
|
||||||
|
return (cv->waiters_done_ == NULL) ? GetLastError() : 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int pthread_cond_destroy(pthread_cond_t *cond)
|
||||||
|
{
|
||||||
|
CloseHandle( cond->sema_);
|
||||||
|
DeleteCriticalSection(&cond->waiters_count_lock_);
|
||||||
|
return (CloseHandle( cond->waiters_done_ ) == 0)? GetLastError(): 0 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
pthread_cond_signal (pthread_cond_t *cv)
|
||||||
|
{
|
||||||
|
int have_waiters;
|
||||||
|
EnterCriticalSection (& (cv->waiters_count_lock_));
|
||||||
|
have_waiters = cv->waiters_count_ > 0;
|
||||||
|
LeaveCriticalSection (&cv->waiters_count_lock_);
|
||||||
|
|
||||||
|
// If there aren't any waiters, then this is a no-op.
|
||||||
|
if (have_waiters){
|
||||||
|
return (ReleaseSemaphore (cv->sema_, 1, 0) == 0 ) ? GetLastError() : 0 ;
|
||||||
|
}else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
pthread_cond_broadcast (pthread_cond_t *cv)
|
||||||
|
{
|
||||||
|
// This is needed to ensure that <waiters_count_> and <was_broadcast_> are
|
||||||
|
// consistent relative to each other.
|
||||||
|
int have_waiters = 0;
|
||||||
|
EnterCriticalSection (&cv->waiters_count_lock_);
|
||||||
|
|
||||||
|
if (cv->waiters_count_ > 0) {
|
||||||
|
// We are broadcasting, even if there is just one waiter...
|
||||||
|
// Record that we are broadcasting, which helps optimize
|
||||||
|
// <pthread_cond_wait> for the non-broadcast case.
|
||||||
|
cv->was_broadcast_ = 1;
|
||||||
|
have_waiters = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (have_waiters) {
|
||||||
|
// Wake up all the waiters atomically.
|
||||||
|
ReleaseSemaphore (cv->sema_, cv->waiters_count_, 0);
|
||||||
|
|
||||||
|
LeaveCriticalSection (&cv->waiters_count_lock_);
|
||||||
|
|
||||||
|
// Wait for all the awakened threads to acquire the counting
|
||||||
|
// semaphore.
|
||||||
|
WaitForSingleObject (cv->waiters_done_, INFINITE);
|
||||||
|
// This assignment is okay, even without the <waiters_count_lock_> held
|
||||||
|
// because no other waiter threads can wake up to access it.
|
||||||
|
cv->was_broadcast_ = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LeaveCriticalSection (&cv->waiters_count_lock_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
pthread_cond_wait (pthread_cond_t *cv,
|
||||||
|
pthread_mutex_t *external_mutex)
|
||||||
|
{
|
||||||
|
int last_waiter;
|
||||||
|
// Avoid race conditions.
|
||||||
|
EnterCriticalSection (&cv->waiters_count_lock_);
|
||||||
|
cv->waiters_count_++;
|
||||||
|
LeaveCriticalSection (&cv->waiters_count_lock_);
|
||||||
|
|
||||||
|
// This call atomically releases the mutex and waits on the
|
||||||
|
// semaphore until <pthread_cond_signal> or <pthread_cond_broadcast>
|
||||||
|
// are called by another thread.
|
||||||
|
SignalObjectAndWait (*external_mutex, cv->sema_, INFINITE, FALSE);
|
||||||
|
|
||||||
|
// Reacquire lock to avoid race conditions.
|
||||||
|
EnterCriticalSection (&cv->waiters_count_lock_);
|
||||||
|
|
||||||
|
// We're no longer waiting...
|
||||||
|
cv->waiters_count_--;
|
||||||
|
|
||||||
|
// Check to see if we're the last waiter after <pthread_cond_broadcast>.
|
||||||
|
last_waiter = cv->was_broadcast_ && cv->waiters_count_ == 0;
|
||||||
|
|
||||||
|
LeaveCriticalSection (&cv->waiters_count_lock_);
|
||||||
|
|
||||||
|
// If we're the last waiter thread during this particular broadcast
|
||||||
|
// then let all the other threads proceed.
|
||||||
|
if (last_waiter)
|
||||||
|
// This call atomically signals the <waiters_done_> event and waits until
|
||||||
|
// it can acquire the <external_mutex>. This is required to ensure fairness.
|
||||||
|
SignalObjectAndWait (cv->waiters_done_, *external_mutex, INFINITE, FALSE);
|
||||||
|
else
|
||||||
|
// Always regain the external mutex since that's the guarantee we
|
||||||
|
// give to our callers.
|
||||||
|
WaitForSingleObject (*external_mutex, INFINITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_key_create(pthread_key_t *key, void (*destructor)(void *) )
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
pthread_key_t* newkey;
|
||||||
|
|
||||||
|
if ((newkey = (pthread_key_t*) calloc (1, sizeof (pthread_key_t))) == NULL)
|
||||||
|
{
|
||||||
|
result = ENOMEM;
|
||||||
|
}
|
||||||
|
else if ((newkey->key = TlsAlloc ()) == TLS_OUT_OF_INDEXES)
|
||||||
|
{
|
||||||
|
result = EAGAIN;
|
||||||
|
free (newkey);
|
||||||
|
newkey = NULL;
|
||||||
|
}
|
||||||
|
else if (destructor != NULL)
|
||||||
|
{
|
||||||
|
//--we have to store the function pointer for destructor, so that we can call it
|
||||||
|
//--to free up the user allocated storage--
|
||||||
|
newkey->destructor = destructor;
|
||||||
|
}
|
||||||
|
key = newkey;
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_key_delete(pthread_key_t key)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
LPVOID lpvData = TlsGetValue(key.key);
|
||||||
|
rc = TlsFree (key.key);
|
||||||
|
rc = (rc != 0 ) ? 0 : GetLastError();
|
||||||
|
if (key.destructor != NULL && lpvData != 0){
|
||||||
|
key.destructor(lpvData); //we take control of calling destructor, instead of calling it on thread exit.
|
||||||
|
}
|
||||||
|
free (&key);
|
||||||
|
return (rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *pthread_getspecific(pthread_key_t key)
|
||||||
|
{
|
||||||
|
LPVOID lpvData = TlsGetValue(key.key);
|
||||||
|
if ((lpvData == 0) && (GetLastError() != ERROR_SUCCESS))
|
||||||
|
return NULL;
|
||||||
|
else
|
||||||
|
return lpvData;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_setspecific(pthread_key_t key, const void *value)
|
||||||
|
{
|
||||||
|
int rc = TlsSetValue (key.key, value);
|
||||||
|
return ((rc != 0 ) ? 0 : GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
int gettimeofday(struct timeval *tp, void *tzp) {
|
||||||
|
int64_t now = 0;
|
||||||
|
if (tzp != 0) { errno = EINVAL; return -1; }
|
||||||
|
GetSystemTimeAsFileTime( (LPFILETIME)&now );
|
||||||
|
tp->tv_sec = (long)(now / 10000000 - 11644473600LL);
|
||||||
|
tp->tv_usec = (now / 10) % 1000000;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int close(SOCKET fd) {
|
||||||
|
return closesocket(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Win32WSAStartup()
|
||||||
|
{
|
||||||
|
WORD wVersionRq;
|
||||||
|
WSADATA wsaData;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
wVersionRq = MAKEWORD(2,0);
|
||||||
|
err = WSAStartup(wVersionRq, &wsaData);
|
||||||
|
if (err != 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
// confirm the version information
|
||||||
|
if ((LOBYTE(wsaData.wVersion) != 2) ||
|
||||||
|
(HIBYTE(wsaData.wVersion) != 0))
|
||||||
|
{
|
||||||
|
Win32WSACleanup();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Win32WSACleanup()
|
||||||
|
{
|
||||||
|
WSACleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
double drand48(void)
|
||||||
|
{
|
||||||
|
return (double)(rand()) / RAND_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //WIN32
|
||||||
|
|
||||||
|
|
||||||
|
|
139
zookeeper-client/zookeeper-client-c/src/winport.h
Normal file
139
zookeeper-client/zookeeper-client-c/src/winport.h
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This header file is to port pthread lib , sockets and other utility methods on windows.
|
||||||
|
* Specifically the threads function, mutexes, keys, and socket initialization.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WINPORT_H_
|
||||||
|
#define WINPORT_H_
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include "winconfig.h"
|
||||||
|
|
||||||
|
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||||
|
#include <winsock2.h> /* must always be included before ws2tcpip.h */
|
||||||
|
#include <ws2tcpip.h> /* for struct sock_addr used in zookeeper.h */
|
||||||
|
|
||||||
|
/* POSIX names are deprecated, use ISO conformant names instead. */
|
||||||
|
#define strdup _strdup
|
||||||
|
#define getcwd _getcwd
|
||||||
|
#define getpid _getpid
|
||||||
|
|
||||||
|
/* Windows "secure" versions of POSIX reentrant functions */
|
||||||
|
#define strtok_r strtok_s
|
||||||
|
#define localtime_r(a,b) localtime_s(b,a)
|
||||||
|
|
||||||
|
/* After this version of MSVC, snprintf became a defined function,
|
||||||
|
and so cannot be redefined, nor can #ifndef be used to guard it. */
|
||||||
|
#if ((defined(_MSC_VER) && _MSC_VER < 1900) || !defined(_MSC_VER))
|
||||||
|
#define snprintf _snprintf
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <process.h>
|
||||||
|
#include <stdint.h> /* for int64_t */
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
|
||||||
|
typedef int ssize_t;
|
||||||
|
typedef HANDLE pthread_mutex_t;
|
||||||
|
|
||||||
|
struct pthread_t_
|
||||||
|
{
|
||||||
|
HANDLE thread_handle;
|
||||||
|
DWORD thread_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct pthread_t_ pthread_t;
|
||||||
|
typedef int pthread_mutexattr_t;
|
||||||
|
typedef int pthread_condattr_t;
|
||||||
|
typedef int pthread_attr_t;
|
||||||
|
#define PTHREAD_MUTEX_RECURSIVE 0
|
||||||
|
|
||||||
|
int pthread_mutex_lock(pthread_mutex_t* _mutex );
|
||||||
|
int pthread_mutex_unlock( pthread_mutex_t* _mutex );
|
||||||
|
int pthread_mutex_init(pthread_mutex_t* _mutex, void* ignoredAttr);
|
||||||
|
int pthread_mutex_destroy(pthread_mutex_t* _mutex);
|
||||||
|
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, unsigned (__stdcall* start_routine)(void* a), void *arg);
|
||||||
|
int pthread_equal(pthread_t t1, pthread_t t2);
|
||||||
|
pthread_t pthread_self();
|
||||||
|
int pthread_join(pthread_t _thread, void** ignore);
|
||||||
|
int pthread_detach(pthread_t _thread);
|
||||||
|
|
||||||
|
void pthread_mutexattr_init(pthread_mutexattr_t* ignore);
|
||||||
|
void pthread_mutexattr_settype(pthread_mutexattr_t* ingore_attr, int ignore);
|
||||||
|
void pthread_mutexattr_destroy(pthread_mutexattr_t* ignore_attr);
|
||||||
|
|
||||||
|
|
||||||
|
// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int waiters_count_;
|
||||||
|
// Number of waiting threads.
|
||||||
|
|
||||||
|
CRITICAL_SECTION waiters_count_lock_;
|
||||||
|
// Serialize access to <waiters_count_>.
|
||||||
|
|
||||||
|
HANDLE sema_;
|
||||||
|
// Semaphore used to queue up threads waiting for the condition to
|
||||||
|
// become signaled.
|
||||||
|
|
||||||
|
HANDLE waiters_done_;
|
||||||
|
// An auto-reset event used by the broadcast/signal thread to wait
|
||||||
|
// for all the waiting thread(s) to wake up and be released from the
|
||||||
|
// semaphore.
|
||||||
|
|
||||||
|
size_t was_broadcast_;
|
||||||
|
// Keeps track of whether we were broadcasting or signaling. This
|
||||||
|
// allows us to optimize the code if we're just signaling.
|
||||||
|
}pthread_cond_t;
|
||||||
|
|
||||||
|
int pthread_cond_init (pthread_cond_t *cv,const pthread_condattr_t * ignore);
|
||||||
|
int pthread_cond_destroy(pthread_cond_t *cond);
|
||||||
|
int pthread_cond_signal (pthread_cond_t *cv);
|
||||||
|
int pthread_cond_broadcast (pthread_cond_t *cv);
|
||||||
|
int pthread_cond_wait (pthread_cond_t *cv, pthread_mutex_t *external_mutex);
|
||||||
|
|
||||||
|
|
||||||
|
struct pthread_key_t_
|
||||||
|
{
|
||||||
|
DWORD key;
|
||||||
|
void (*destructor) (void *);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct pthread_key_t_ pthread_key_t;
|
||||||
|
int pthread_key_create(pthread_key_t *key, void (*destructor)(void *) );
|
||||||
|
int pthread_key_delete(pthread_key_t key);
|
||||||
|
void *pthread_getspecific(pthread_key_t key);
|
||||||
|
int pthread_setspecific(pthread_key_t key, const void *value);
|
||||||
|
|
||||||
|
int gettimeofday(struct timeval *tp, void *tzp);
|
||||||
|
int close(SOCKET fd);
|
||||||
|
int Win32WSAStartup();
|
||||||
|
void Win32WSACleanup();
|
||||||
|
double drand48(void);
|
||||||
|
#endif //WIN32
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif //WINPORT_H_
|
327
zookeeper-client/zookeeper-client-c/src/zk_adaptor.h
Normal file
327
zookeeper-client/zookeeper-client-c/src/zk_adaptor.h
Normal file
@ -0,0 +1,327 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZK_ADAPTOR_H_
|
||||||
|
#define ZK_ADAPTOR_H_
|
||||||
|
#include <zookeeper.jute.h>
|
||||||
|
#ifdef THREADED
|
||||||
|
#ifndef WIN32
|
||||||
|
#include <pthread.h>
|
||||||
|
#else
|
||||||
|
#include "winport.h"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#include "zookeeper.h"
|
||||||
|
#include "zk_hashtable.h"
|
||||||
|
#include "addrvec.h"
|
||||||
|
|
||||||
|
/* predefined xid's values recognized as special by the server */
|
||||||
|
#define WATCHER_EVENT_XID -1
|
||||||
|
#define PING_XID -2
|
||||||
|
#define AUTH_XID -4
|
||||||
|
#define SET_WATCHES_XID -8
|
||||||
|
|
||||||
|
/* zookeeper state constants */
|
||||||
|
#define EXPIRED_SESSION_STATE_DEF -112
|
||||||
|
#define AUTH_FAILED_STATE_DEF -113
|
||||||
|
#define CONNECTING_STATE_DEF 1
|
||||||
|
#define ASSOCIATING_STATE_DEF 2
|
||||||
|
#define CONNECTED_STATE_DEF 3
|
||||||
|
#define READONLY_STATE_DEF 5
|
||||||
|
#define SSL_CONNECTING_STATE_DEF 7
|
||||||
|
#define NOTCONNECTED_STATE_DEF 999
|
||||||
|
|
||||||
|
/* zookeeper event type constants */
|
||||||
|
#define CREATED_EVENT_DEF 1
|
||||||
|
#define DELETED_EVENT_DEF 2
|
||||||
|
#define CHANGED_EVENT_DEF 3
|
||||||
|
#define CHILD_EVENT_DEF 4
|
||||||
|
#define SESSION_EVENT_DEF -1
|
||||||
|
#define NOTWATCHING_EVENT_DEF -2
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct _buffer_list;
|
||||||
|
struct _completion_list;
|
||||||
|
|
||||||
|
typedef struct _buffer_head {
|
||||||
|
struct _buffer_list *volatile head;
|
||||||
|
struct _buffer_list *last;
|
||||||
|
#ifdef THREADED
|
||||||
|
pthread_mutex_t lock;
|
||||||
|
#endif
|
||||||
|
} buffer_head_t;
|
||||||
|
|
||||||
|
typedef struct _completion_head {
|
||||||
|
struct _completion_list *volatile head;
|
||||||
|
struct _completion_list *last;
|
||||||
|
#ifdef THREADED
|
||||||
|
pthread_cond_t cond;
|
||||||
|
pthread_mutex_t lock;
|
||||||
|
#endif
|
||||||
|
} completion_head_t;
|
||||||
|
|
||||||
|
int lock_buffer_list(buffer_head_t *l);
|
||||||
|
int unlock_buffer_list(buffer_head_t *l);
|
||||||
|
int lock_completion_list(completion_head_t *l);
|
||||||
|
int unlock_completion_list(completion_head_t *l);
|
||||||
|
|
||||||
|
struct sync_completion {
|
||||||
|
int rc;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
char *str;
|
||||||
|
int str_len;
|
||||||
|
} str;
|
||||||
|
struct Stat stat;
|
||||||
|
struct {
|
||||||
|
char *buffer;
|
||||||
|
int buff_len;
|
||||||
|
struct Stat stat;
|
||||||
|
} data;
|
||||||
|
struct {
|
||||||
|
struct ACL_vector acl;
|
||||||
|
struct Stat stat;
|
||||||
|
} acl;
|
||||||
|
struct String_vector strs2;
|
||||||
|
struct {
|
||||||
|
struct String_vector strs2;
|
||||||
|
struct Stat stat2;
|
||||||
|
} strs_stat;
|
||||||
|
} u;
|
||||||
|
int complete;
|
||||||
|
#ifdef THREADED
|
||||||
|
pthread_cond_t cond;
|
||||||
|
pthread_mutex_t lock;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _auth_info {
|
||||||
|
int state; /* 0=>inactive, >0 => active */
|
||||||
|
char* scheme;
|
||||||
|
struct buffer auth;
|
||||||
|
void_completion_t completion;
|
||||||
|
const char* data;
|
||||||
|
struct _auth_info *next;
|
||||||
|
} auth_info;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This structure represents a packet being read or written.
|
||||||
|
*/
|
||||||
|
typedef struct _buffer_list {
|
||||||
|
char *buffer;
|
||||||
|
int len; /* This represents the length of sizeof(header) + length of buffer */
|
||||||
|
int curr_offset; /* This is the offset into the header followed by offset into the buffer */
|
||||||
|
struct _buffer_list *next;
|
||||||
|
} buffer_list_t;
|
||||||
|
|
||||||
|
/* the size of connect request */
|
||||||
|
#define HANDSHAKE_REQ_SIZE 45
|
||||||
|
/* connect request */
|
||||||
|
struct connect_req {
|
||||||
|
int32_t protocolVersion;
|
||||||
|
int64_t lastZxidSeen;
|
||||||
|
int32_t timeOut;
|
||||||
|
int64_t sessionId;
|
||||||
|
int32_t passwd_len;
|
||||||
|
char passwd[16];
|
||||||
|
char readOnly;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* the connect response */
|
||||||
|
struct prime_struct {
|
||||||
|
int32_t len;
|
||||||
|
int32_t protocolVersion;
|
||||||
|
int32_t timeOut;
|
||||||
|
int64_t sessionId;
|
||||||
|
int32_t passwd_len;
|
||||||
|
char passwd[16];
|
||||||
|
char readOnly;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef THREADED
|
||||||
|
/* this is used by mt_adaptor internally for thread management */
|
||||||
|
struct adaptor_threads {
|
||||||
|
pthread_t io;
|
||||||
|
pthread_t completion;
|
||||||
|
int threadsToWait; // barrier
|
||||||
|
pthread_cond_t cond; // barrier's conditional
|
||||||
|
pthread_mutex_t lock; // ... and a lock
|
||||||
|
pthread_mutex_t zh_lock; // critical section lock
|
||||||
|
pthread_mutex_t reconfig_lock; // lock for reconfiguring cluster's ensemble
|
||||||
|
pthread_mutex_t watchers_lock; // lock for watcher operations
|
||||||
|
#ifdef WIN32
|
||||||
|
SOCKET self_pipe[2];
|
||||||
|
#else
|
||||||
|
int self_pipe[2];
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** the auth list for adding auth */
|
||||||
|
typedef struct _auth_list_head {
|
||||||
|
auth_info *auth;
|
||||||
|
#ifdef THREADED
|
||||||
|
pthread_mutex_t lock;
|
||||||
|
#endif
|
||||||
|
} auth_list_head_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This structure represents the connection to zookeeper.
|
||||||
|
*/
|
||||||
|
struct _zhandle {
|
||||||
|
zsock_t *fd;
|
||||||
|
|
||||||
|
// Hostlist and list of addresses
|
||||||
|
char *hostname; // hostname contains list of zookeeper servers to connect to
|
||||||
|
struct sockaddr_storage addr_cur; // address of server we're currently connecting/connected to
|
||||||
|
struct sockaddr_storage addr_rw_server; // address of last known read/write server found.
|
||||||
|
|
||||||
|
addrvec_t addrs; // current list of addresses we're connected to
|
||||||
|
addrvec_t addrs_old; // old list of addresses that we are no longer connected to
|
||||||
|
addrvec_t addrs_new; // new list of addresses to connect to if we're reconfiguring
|
||||||
|
|
||||||
|
int reconfig; // Are we in the process of reconfiguring cluster's ensemble
|
||||||
|
double pOld, pNew; // Probability for selecting between 'addrs_old' and 'addrs_new'
|
||||||
|
int delay;
|
||||||
|
int disable_reconnection_attempt; // When set, client will not try reconnect to a different server in
|
||||||
|
// server list. This makes a sticky server for client, and is useful
|
||||||
|
// for testing if a sticky server is required, or if client wants to
|
||||||
|
// explicitly shuffle server by calling zoo_cycle_next_server.
|
||||||
|
// The default value is 0.
|
||||||
|
|
||||||
|
watcher_fn watcher; // the registered watcher
|
||||||
|
|
||||||
|
// Message timings
|
||||||
|
struct timeval last_recv; // time last message was received
|
||||||
|
struct timeval last_send; // time last message was sent
|
||||||
|
struct timeval last_ping; // time last PING was sent
|
||||||
|
struct timeval next_deadline; // time of the next deadline
|
||||||
|
int recv_timeout; // max receive timeout for messages from server
|
||||||
|
|
||||||
|
// Buffers
|
||||||
|
buffer_list_t *input_buffer; // current buffer being read in
|
||||||
|
buffer_head_t to_process; // buffers that have been read and ready to be processed
|
||||||
|
buffer_head_t to_send; // packets queued to send
|
||||||
|
completion_head_t sent_requests; // outstanding requests
|
||||||
|
completion_head_t completions_to_process; // completions that are ready to run
|
||||||
|
int outstanding_sync; // number of outstanding synchronous requests
|
||||||
|
|
||||||
|
/* read-only mode specific fields */
|
||||||
|
struct timeval last_ping_rw; /* The last time we checked server for being r/w */
|
||||||
|
int ping_rw_timeout; /* The time that can go by before checking next server */
|
||||||
|
|
||||||
|
// State info
|
||||||
|
volatile int state; // Current zookeeper state
|
||||||
|
void *context; // client-side provided context
|
||||||
|
clientid_t client_id; // client-id
|
||||||
|
long long last_zxid; // last zookeeper ID
|
||||||
|
auth_list_head_t auth_h; // authentication data list
|
||||||
|
log_callback_fn log_callback; // Callback for logging (falls back to logging to stderr)
|
||||||
|
int io_count; // counts the number of iterations of do_io
|
||||||
|
|
||||||
|
// Primer storage
|
||||||
|
struct _buffer_list primer_buffer; // The buffer used for the handshake at the start of a connection
|
||||||
|
struct prime_struct primer_storage; // the connect response
|
||||||
|
char primer_storage_buffer[41]; // the true size of primer_storage
|
||||||
|
|
||||||
|
/* zookeeper_close is not reentrant because it de-allocates the zhandler.
|
||||||
|
* This guard variable is used to defer the destruction of zhandle till
|
||||||
|
* right before top-level API call returns to the caller */
|
||||||
|
int32_t ref_counter;
|
||||||
|
volatile int close_requested;
|
||||||
|
void *adaptor_priv;
|
||||||
|
|
||||||
|
/* Used for debugging only: non-zero value indicates the time when the zookeeper_process
|
||||||
|
* call returned while there was at least one unprocessed server response
|
||||||
|
* available in the socket recv buffer */
|
||||||
|
struct timeval socket_readable;
|
||||||
|
|
||||||
|
// Watchers
|
||||||
|
zk_hashtable* active_node_watchers;
|
||||||
|
zk_hashtable* active_exist_watchers;
|
||||||
|
zk_hashtable* active_child_watchers;
|
||||||
|
|
||||||
|
/** used for chroot path at the client side **/
|
||||||
|
char *chroot;
|
||||||
|
|
||||||
|
/** Indicates if this client is allowed to go to r/o mode */
|
||||||
|
char allow_read_only;
|
||||||
|
/** Indicates if we connected to a majority server before */
|
||||||
|
char seen_rw_server_before;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int adaptor_init(zhandle_t *zh);
|
||||||
|
void adaptor_finish(zhandle_t *zh);
|
||||||
|
void adaptor_destroy(zhandle_t *zh);
|
||||||
|
#if THREADED
|
||||||
|
struct sync_completion *alloc_sync_completion(void);
|
||||||
|
int wait_sync_completion(struct sync_completion *sc);
|
||||||
|
void free_sync_completion(struct sync_completion *sc);
|
||||||
|
void notify_sync_completion(struct sync_completion *sc);
|
||||||
|
#endif
|
||||||
|
int adaptor_send_queue(zhandle_t *zh, int timeout);
|
||||||
|
int process_async(int outstanding_sync);
|
||||||
|
void process_completions(zhandle_t *zh);
|
||||||
|
int flush_send_queue(zhandle_t*zh, int timeout);
|
||||||
|
char* sub_string(zhandle_t *zh, const char* server_path);
|
||||||
|
void free_duplicate_path(const char* free_path, const char* path);
|
||||||
|
int zoo_lock_auth(zhandle_t *zh);
|
||||||
|
int zoo_unlock_auth(zhandle_t *zh);
|
||||||
|
|
||||||
|
// ensemble reconfigure access guards
|
||||||
|
int lock_reconfig(struct _zhandle *zh);
|
||||||
|
int unlock_reconfig(struct _zhandle *zh);
|
||||||
|
|
||||||
|
// watchers hashtable lock
|
||||||
|
int lock_watchers(struct _zhandle *zh);
|
||||||
|
int unlock_watchers(struct _zhandle *zh);
|
||||||
|
|
||||||
|
// critical section guards
|
||||||
|
int enter_critical(zhandle_t* zh);
|
||||||
|
int leave_critical(zhandle_t* zh);
|
||||||
|
|
||||||
|
// zhandle object reference counting
|
||||||
|
void api_prolog(zhandle_t* zh);
|
||||||
|
int api_epilog(zhandle_t *zh, int rc);
|
||||||
|
int32_t get_xid();
|
||||||
|
|
||||||
|
// returns the new value of the ref counter
|
||||||
|
int32_t inc_ref_counter(zhandle_t* zh,int i);
|
||||||
|
|
||||||
|
#ifdef THREADED
|
||||||
|
// atomic post-increment
|
||||||
|
int32_t fetch_and_add(volatile int32_t* operand, int incr);
|
||||||
|
// in mt mode process session event asynchronously by the completion thread
|
||||||
|
#define PROCESS_SESSION_EVENT(zh,newstate) queue_session_event(zh,newstate)
|
||||||
|
#else
|
||||||
|
// in single-threaded mode process session event immediately
|
||||||
|
//#define PROCESS_SESSION_EVENT(zh,newstate) deliverWatchers(zh,ZOO_SESSION_EVENT,newstate,0)
|
||||||
|
#define PROCESS_SESSION_EVENT(zh,newstate) queue_session_event(zh,newstate)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*ZK_ADAPTOR_H_*/
|
||||||
|
|
||||||
|
|
476
zookeeper-client/zookeeper-client-c/src/zk_hashtable.c
Normal file
476
zookeeper-client/zookeeper-client-c/src/zk_hashtable.c
Normal file
@ -0,0 +1,476 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "zk_hashtable.h"
|
||||||
|
#include "zk_adaptor.h"
|
||||||
|
#include "hashtable/hashtable.h"
|
||||||
|
#include "hashtable/hashtable_itr.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
typedef struct _watcher_object {
|
||||||
|
watcher_fn watcher;
|
||||||
|
void* context;
|
||||||
|
struct _watcher_object* next;
|
||||||
|
} watcher_object_t;
|
||||||
|
|
||||||
|
|
||||||
|
struct _zk_hashtable {
|
||||||
|
struct hashtable* ht;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct watcher_object_list {
|
||||||
|
watcher_object_t* head;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* the following functions are for testing only */
|
||||||
|
typedef struct hashtable hashtable_impl;
|
||||||
|
|
||||||
|
hashtable_impl* getImpl(zk_hashtable* ht){
|
||||||
|
return ht->ht;
|
||||||
|
}
|
||||||
|
|
||||||
|
watcher_object_t* getFirstWatcher(zk_hashtable* ht,const char* path)
|
||||||
|
{
|
||||||
|
watcher_object_list_t* wl=hashtable_search(ht->ht,(void*)path);
|
||||||
|
if(wl!=0)
|
||||||
|
return wl->head;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* end of testing functions */
|
||||||
|
|
||||||
|
watcher_object_t* clone_watcher_object(watcher_object_t* wo)
|
||||||
|
{
|
||||||
|
watcher_object_t* res=calloc(1,sizeof(watcher_object_t));
|
||||||
|
assert(res);
|
||||||
|
res->watcher=wo->watcher;
|
||||||
|
res->context=wo->context;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int string_hash_djb2(void *str)
|
||||||
|
{
|
||||||
|
unsigned int hash = 5381;
|
||||||
|
int c;
|
||||||
|
const char* cstr = (const char*)str;
|
||||||
|
while ((c = *cstr++))
|
||||||
|
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int string_equal(void *key1,void *key2)
|
||||||
|
{
|
||||||
|
return strcmp((const char*)key1,(const char*)key2)==0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static watcher_object_t* create_watcher_object(watcher_fn watcher,void* ctx)
|
||||||
|
{
|
||||||
|
watcher_object_t* wo=calloc(1,sizeof(watcher_object_t));
|
||||||
|
assert(wo);
|
||||||
|
wo->watcher=watcher;
|
||||||
|
wo->context=ctx;
|
||||||
|
return wo;
|
||||||
|
}
|
||||||
|
|
||||||
|
static watcher_object_list_t* create_watcher_object_list(watcher_object_t* head)
|
||||||
|
{
|
||||||
|
watcher_object_list_t* wl=calloc(1,sizeof(watcher_object_list_t));
|
||||||
|
assert(wl);
|
||||||
|
wl->head=head;
|
||||||
|
return wl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destroy_watcher_object_list(watcher_object_list_t* list)
|
||||||
|
{
|
||||||
|
watcher_object_t* e = NULL;
|
||||||
|
|
||||||
|
if(list==0)
|
||||||
|
return;
|
||||||
|
e=list->head;
|
||||||
|
while(e!=0){
|
||||||
|
watcher_object_t* this=e;
|
||||||
|
e=e->next;
|
||||||
|
free(this);
|
||||||
|
}
|
||||||
|
free(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
zk_hashtable* create_zk_hashtable()
|
||||||
|
{
|
||||||
|
struct _zk_hashtable *ht=calloc(1,sizeof(struct _zk_hashtable));
|
||||||
|
assert(ht);
|
||||||
|
ht->ht=create_hashtable(32,string_hash_djb2,string_equal);
|
||||||
|
return ht;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_clean_hashtable(zk_hashtable* ht)
|
||||||
|
{
|
||||||
|
struct hashtable_itr *it;
|
||||||
|
int hasMore;
|
||||||
|
if(hashtable_count(ht->ht)==0)
|
||||||
|
return;
|
||||||
|
it=hashtable_iterator(ht->ht);
|
||||||
|
do {
|
||||||
|
watcher_object_list_t* w=hashtable_iterator_value(it);
|
||||||
|
destroy_watcher_object_list(w);
|
||||||
|
hasMore=hashtable_iterator_remove(it);
|
||||||
|
} while(hasMore);
|
||||||
|
free(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy_zk_hashtable(zk_hashtable* ht)
|
||||||
|
{
|
||||||
|
if(ht!=0){
|
||||||
|
do_clean_hashtable(ht);
|
||||||
|
hashtable_destroy(ht->ht,0);
|
||||||
|
free(ht);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// searches for a watcher object instance in a watcher object list;
|
||||||
|
// two watcher objects are equal if their watcher function and context pointers
|
||||||
|
// are equal
|
||||||
|
static watcher_object_t* search_watcher(watcher_object_list_t** wl,watcher_object_t* wo)
|
||||||
|
{
|
||||||
|
watcher_object_t* wobj=(*wl)->head;
|
||||||
|
while(wobj!=0){
|
||||||
|
if(wobj->watcher==wo->watcher && wobj->context==wo->context)
|
||||||
|
return wobj;
|
||||||
|
wobj=wobj->next;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int add_to_list(watcher_object_list_t **wl, watcher_object_t *wo,
|
||||||
|
int clone)
|
||||||
|
{
|
||||||
|
if (search_watcher(wl, wo)==0) {
|
||||||
|
watcher_object_t* cloned=wo;
|
||||||
|
if (clone) {
|
||||||
|
cloned = clone_watcher_object(wo);
|
||||||
|
assert(cloned);
|
||||||
|
}
|
||||||
|
cloned->next = (*wl)->head;
|
||||||
|
(*wl)->head = cloned;
|
||||||
|
return 1;
|
||||||
|
} else if (!clone) {
|
||||||
|
// If it's here and we aren't supposed to clone, we must destroy
|
||||||
|
free(wo);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_insert_watcher_object(zk_hashtable *ht, const char *path, watcher_object_t* wo)
|
||||||
|
{
|
||||||
|
int res=1;
|
||||||
|
watcher_object_list_t* wl;
|
||||||
|
|
||||||
|
wl=hashtable_search(ht->ht,(void*)path);
|
||||||
|
if(wl==0){
|
||||||
|
int res;
|
||||||
|
/* inserting a new path element */
|
||||||
|
res=hashtable_insert(ht->ht,strdup(path),create_watcher_object_list(wo));
|
||||||
|
assert(res);
|
||||||
|
}else{
|
||||||
|
/*
|
||||||
|
* Path already exists; check if the watcher already exists.
|
||||||
|
* Don't clone the watcher since it's allocated on the heap --- avoids
|
||||||
|
* a memory leak and saves a clone operation (calloc + copy).
|
||||||
|
*/
|
||||||
|
res = add_to_list(&wl, wo, 0);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char **collect_keys(zk_hashtable *ht, int *count)
|
||||||
|
{
|
||||||
|
char **list;
|
||||||
|
struct hashtable_itr *it;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
*count = hashtable_count(ht->ht);
|
||||||
|
list = calloc(*count, sizeof(char*));
|
||||||
|
it=hashtable_iterator(ht->ht);
|
||||||
|
for(i = 0; i < *count; i++) {
|
||||||
|
list[i] = strdup(hashtable_iterator_key(it));
|
||||||
|
hashtable_iterator_advance(it);
|
||||||
|
}
|
||||||
|
free(it);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int insert_watcher_object(zk_hashtable *ht, const char *path,
|
||||||
|
watcher_object_t* wo)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
res=do_insert_watcher_object(ht,path,wo);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void copy_watchers(watcher_object_list_t *from, watcher_object_list_t *to, int clone)
|
||||||
|
{
|
||||||
|
watcher_object_t* wo=from->head;
|
||||||
|
while(wo){
|
||||||
|
watcher_object_t *next = wo->next;
|
||||||
|
add_to_list(&to, wo, clone);
|
||||||
|
wo=next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void copy_table(zk_hashtable *from, watcher_object_list_t *to) {
|
||||||
|
struct hashtable_itr *it;
|
||||||
|
int hasMore;
|
||||||
|
if(hashtable_count(from->ht)==0)
|
||||||
|
return;
|
||||||
|
it=hashtable_iterator(from->ht);
|
||||||
|
do {
|
||||||
|
watcher_object_list_t *w = hashtable_iterator_value(it);
|
||||||
|
copy_watchers(w, to, 1);
|
||||||
|
hasMore=hashtable_iterator_advance(it);
|
||||||
|
} while(hasMore);
|
||||||
|
free(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void collect_session_watchers(zhandle_t *zh,
|
||||||
|
watcher_object_list_t **list)
|
||||||
|
{
|
||||||
|
copy_table(zh->active_node_watchers, *list);
|
||||||
|
copy_table(zh->active_exist_watchers, *list);
|
||||||
|
copy_table(zh->active_child_watchers, *list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_for_event(zk_hashtable *ht, char *path, watcher_object_list_t **list)
|
||||||
|
{
|
||||||
|
watcher_object_list_t* wl;
|
||||||
|
wl = (watcher_object_list_t*)hashtable_remove(ht->ht, path);
|
||||||
|
if (wl) {
|
||||||
|
copy_watchers(wl, *list, 0);
|
||||||
|
// Since we move, not clone the watch_objects, we just need to free the
|
||||||
|
// head pointer
|
||||||
|
free(wl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_foreach_watcher(watcher_object_t* wo,zhandle_t* zh,
|
||||||
|
const char* path,int type,int state)
|
||||||
|
{
|
||||||
|
// session event's don't have paths
|
||||||
|
const char *client_path =
|
||||||
|
(type != ZOO_SESSION_EVENT ? sub_string(zh, path) : path);
|
||||||
|
while(wo!=0){
|
||||||
|
wo->watcher(zh,type,state,client_path,wo->context);
|
||||||
|
wo=wo->next;
|
||||||
|
}
|
||||||
|
free_duplicate_path(client_path, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
watcher_object_list_t *collectWatchers(zhandle_t *zh,int type, char *path)
|
||||||
|
{
|
||||||
|
struct watcher_object_list *list = create_watcher_object_list(0);
|
||||||
|
|
||||||
|
if(type==ZOO_SESSION_EVENT){
|
||||||
|
watcher_object_t defWatcher;
|
||||||
|
defWatcher.watcher=zh->watcher;
|
||||||
|
defWatcher.context=zh->context;
|
||||||
|
add_to_list(&list, &defWatcher, 1);
|
||||||
|
collect_session_watchers(zh, &list);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
switch(type){
|
||||||
|
case CREATED_EVENT_DEF:
|
||||||
|
case CHANGED_EVENT_DEF:
|
||||||
|
// look up the watchers for the path and move them to a delivery list
|
||||||
|
add_for_event(zh->active_node_watchers,path,&list);
|
||||||
|
add_for_event(zh->active_exist_watchers,path,&list);
|
||||||
|
break;
|
||||||
|
case CHILD_EVENT_DEF:
|
||||||
|
// look up the watchers for the path and move them to a delivery list
|
||||||
|
add_for_event(zh->active_child_watchers,path,&list);
|
||||||
|
break;
|
||||||
|
case DELETED_EVENT_DEF:
|
||||||
|
// look up the watchers for the path and move them to a delivery list
|
||||||
|
add_for_event(zh->active_node_watchers,path,&list);
|
||||||
|
add_for_event(zh->active_exist_watchers,path,&list);
|
||||||
|
add_for_event(zh->active_child_watchers,path,&list);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
void deliverWatchers(zhandle_t *zh, int type,int state, char *path, watcher_object_list_t **list)
|
||||||
|
{
|
||||||
|
if (!list || !(*list)) return;
|
||||||
|
do_foreach_watcher((*list)->head, zh, path, type, state);
|
||||||
|
destroy_watcher_object_list(*list);
|
||||||
|
*list = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void activateWatcher(zhandle_t *zh, watcher_registration_t* reg, int rc)
|
||||||
|
{
|
||||||
|
if(reg){
|
||||||
|
/* in multithreaded lib, this code is executed
|
||||||
|
* by the IO thread */
|
||||||
|
zk_hashtable *ht = reg->checker(zh, rc);
|
||||||
|
if(ht){
|
||||||
|
insert_watcher_object(ht,reg->path,
|
||||||
|
create_watcher_object(reg->watcher, reg->context));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If watcher is NULL, we return TRUE since we consider it a match */
|
||||||
|
static int containsWatcher(zk_hashtable *watchers, const char *path,
|
||||||
|
watcher_fn watcher, void *watcherCtx)
|
||||||
|
{
|
||||||
|
watcher_object_list_t *wl;
|
||||||
|
watcher_object_t e;
|
||||||
|
|
||||||
|
if (!watcher)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
wl = hashtable_search(watchers->ht, (void *)path);
|
||||||
|
if (!wl)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
e.watcher = watcher;
|
||||||
|
e.context = watcherCtx;
|
||||||
|
|
||||||
|
return search_watcher(&wl, &e) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* remove any watcher_object that has a matching (watcher, watcherCtx)
|
||||||
|
*/
|
||||||
|
static void removeWatcherFromList(watcher_object_list_t *wl, watcher_fn watcher,
|
||||||
|
void *watcherCtx)
|
||||||
|
{
|
||||||
|
watcher_object_t *e = NULL;
|
||||||
|
|
||||||
|
if (!wl || (wl && !wl->head))
|
||||||
|
return;
|
||||||
|
|
||||||
|
e = wl->head;
|
||||||
|
while (e){
|
||||||
|
if (e->next &&
|
||||||
|
e->next->watcher == watcher &&
|
||||||
|
e->next->context == watcherCtx) {
|
||||||
|
watcher_object_t *this = e->next;
|
||||||
|
e->next = e->next->next;
|
||||||
|
free(this);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
e = e->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wl->head &&
|
||||||
|
wl->head->watcher == watcher && wl->head->context == watcherCtx) {
|
||||||
|
watcher_object_t *this = wl->head;
|
||||||
|
wl->head = wl->head->next;
|
||||||
|
free(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void removeWatcher(zk_hashtable *watchers, const char *path,
|
||||||
|
watcher_fn watcher, void *watcherCtx)
|
||||||
|
{
|
||||||
|
watcher_object_list_t *wl = hashtable_search(watchers->ht, (void *)path);
|
||||||
|
|
||||||
|
if (!wl)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!watcher) {
|
||||||
|
wl = (watcher_object_list_t *) hashtable_remove(watchers->ht,
|
||||||
|
(void *)path);
|
||||||
|
destroy_watcher_object_list(wl);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
removeWatcherFromList(wl, watcher, watcherCtx);
|
||||||
|
|
||||||
|
if (!wl->head) {
|
||||||
|
wl = (watcher_object_list_t *) hashtable_remove(watchers->ht,
|
||||||
|
(void *)path);
|
||||||
|
destroy_watcher_object_list(wl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void deactivateWatcher(zhandle_t *zh, watcher_deregistration_t *dereg, int rc)
|
||||||
|
{
|
||||||
|
if (rc != ZOK || !dereg)
|
||||||
|
return;
|
||||||
|
|
||||||
|
removeWatchers(zh, dereg->path, dereg->type, dereg->watcher,
|
||||||
|
dereg->context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeWatchers(zhandle_t *zh, const char* path, ZooWatcherType type,
|
||||||
|
watcher_fn watcher, void *watcherCtx)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case ZWATCHTYPE_CHILD:
|
||||||
|
removeWatcher(zh->active_child_watchers, path, watcher, watcherCtx);
|
||||||
|
break;
|
||||||
|
case ZWATCHTYPE_DATA:
|
||||||
|
removeWatcher(zh->active_node_watchers, path, watcher, watcherCtx);
|
||||||
|
removeWatcher(zh->active_exist_watchers, path, watcher, watcherCtx);
|
||||||
|
break;
|
||||||
|
case ZWATCHTYPE_ANY:
|
||||||
|
removeWatcher(zh->active_child_watchers, path, watcher, watcherCtx);
|
||||||
|
removeWatcher(zh->active_node_watchers, path, watcher, watcherCtx);
|
||||||
|
removeWatcher(zh->active_exist_watchers, path, watcher, watcherCtx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int pathHasWatcher(zhandle_t *zh, const char *path, int wtype,
|
||||||
|
watcher_fn watcher, void *watcherCtx)
|
||||||
|
{
|
||||||
|
int watcher_found = 0;
|
||||||
|
|
||||||
|
switch (wtype) {
|
||||||
|
case ZWATCHTYPE_CHILD:
|
||||||
|
watcher_found = containsWatcher(zh->active_child_watchers,
|
||||||
|
path, watcher, watcherCtx);
|
||||||
|
break;
|
||||||
|
case ZWATCHTYPE_DATA:
|
||||||
|
watcher_found = containsWatcher(zh->active_node_watchers, path,
|
||||||
|
watcher, watcherCtx);
|
||||||
|
if (!watcher_found) {
|
||||||
|
watcher_found = containsWatcher(zh->active_exist_watchers, path,
|
||||||
|
watcher, watcherCtx);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ZWATCHTYPE_ANY:
|
||||||
|
watcher_found = containsWatcher(zh->active_child_watchers, path,
|
||||||
|
watcher, watcherCtx);
|
||||||
|
if (!watcher_found) {
|
||||||
|
watcher_found = containsWatcher(zh->active_node_watchers, path,
|
||||||
|
watcher, watcherCtx);
|
||||||
|
}
|
||||||
|
if (!watcher_found) {
|
||||||
|
watcher_found = containsWatcher(zh->active_exist_watchers, path,
|
||||||
|
watcher, watcherCtx);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return watcher_found;
|
||||||
|
}
|
86
zookeeper-client/zookeeper-client-c/src/zk_hashtable.h
Normal file
86
zookeeper-client/zookeeper-client-c/src/zk_hashtable.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZK_HASHTABLE_H_
|
||||||
|
#define ZK_HASHTABLE_H_
|
||||||
|
|
||||||
|
#include <zookeeper.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct watcher_object_list watcher_object_list_t;
|
||||||
|
typedef struct _zk_hashtable zk_hashtable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The function must return a non-zero value if the watcher object can be activated
|
||||||
|
* as a result of the server response. Normally, a watch can only be activated
|
||||||
|
* if the server returns a success code (ZOK). However in the case when zoo_exists()
|
||||||
|
* returns a ZNONODE code the watcher should be activated nevertheless.
|
||||||
|
*/
|
||||||
|
typedef zk_hashtable *(*result_checker_fn)(zhandle_t *, int rc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A watcher object gets temporarily stored with the completion entry until
|
||||||
|
* the server response comes back at which moment the watcher object is moved
|
||||||
|
* to the active watchers map.
|
||||||
|
*/
|
||||||
|
typedef struct _watcher_registration {
|
||||||
|
watcher_fn watcher;
|
||||||
|
void* context;
|
||||||
|
result_checker_fn checker;
|
||||||
|
const char* path;
|
||||||
|
} watcher_registration_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A watcher deregistration gets temporarily stored with the completion entry until
|
||||||
|
* the server response comes back at which moment we can remove the watchers from
|
||||||
|
* the active watchers map.
|
||||||
|
*/
|
||||||
|
typedef struct _watcher_deregistration {
|
||||||
|
watcher_fn watcher;
|
||||||
|
void* context;
|
||||||
|
ZooWatcherType type;
|
||||||
|
const char* path;
|
||||||
|
} watcher_deregistration_t;
|
||||||
|
|
||||||
|
zk_hashtable* create_zk_hashtable();
|
||||||
|
void destroy_zk_hashtable(zk_hashtable* ht);
|
||||||
|
|
||||||
|
char **collect_keys(zk_hashtable *ht, int *count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check if the completion has a watcher object associated
|
||||||
|
* with it. If it does, move the watcher object to the map of
|
||||||
|
* active watchers (only if the checker allows to do so)
|
||||||
|
*/
|
||||||
|
void activateWatcher(zhandle_t *zh, watcher_registration_t* reg, int rc);
|
||||||
|
void deactivateWatcher(zhandle_t *zh, watcher_deregistration_t *dereg, int rc);
|
||||||
|
watcher_object_list_t *collectWatchers(zhandle_t *zh,int type, char *path);
|
||||||
|
void deliverWatchers(zhandle_t *zh, int type, int state, char *path, struct watcher_object_list **list);
|
||||||
|
void removeWatchers(zhandle_t *zh, const char* path, ZooWatcherType type,
|
||||||
|
watcher_fn watcher, void *watcherCtx);
|
||||||
|
int pathHasWatcher(zhandle_t *zh, const char *path, int wtype,
|
||||||
|
watcher_fn watcher, void *watcherCtx);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*ZK_HASHTABLE_H_*/
|
203
zookeeper-client/zookeeper-client-c/src/zk_log.c
Normal file
203
zookeeper-client/zookeeper-client-c/src/zk_log.c
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(DLL_EXPORT) && !defined(USE_STATIC_LIB)
|
||||||
|
# define USE_STATIC_LIB
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "zookeeper_log.h"
|
||||||
|
#ifndef WIN32
|
||||||
|
#include <unistd.h>
|
||||||
|
#else
|
||||||
|
typedef DWORD pid_t;
|
||||||
|
#include <process.h> /* for getpid */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#define TIME_NOW_BUF_SIZE 1024
|
||||||
|
#define FORMAT_LOG_BUF_SIZE 4096
|
||||||
|
|
||||||
|
#ifdef THREADED
|
||||||
|
#ifndef WIN32
|
||||||
|
#include <pthread.h>
|
||||||
|
#else
|
||||||
|
#include "winport.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static pthread_key_t time_now_buffer;
|
||||||
|
static pthread_key_t format_log_msg_buffer;
|
||||||
|
|
||||||
|
void freeBuffer(void* p){
|
||||||
|
if(p) free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((constructor)) void prepareTSDKeys() {
|
||||||
|
pthread_key_create (&time_now_buffer, freeBuffer);
|
||||||
|
pthread_key_create (&format_log_msg_buffer, freeBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* getTSData(pthread_key_t key,int size){
|
||||||
|
char* p=pthread_getspecific(key);
|
||||||
|
if(p==0){
|
||||||
|
int res;
|
||||||
|
p=calloc(1,size);
|
||||||
|
res=pthread_setspecific(key,p);
|
||||||
|
if(res!=0){
|
||||||
|
fprintf(stderr,"Failed to set TSD key: %d",res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* get_time_buffer(){
|
||||||
|
return getTSData(time_now_buffer,TIME_NOW_BUF_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* get_format_log_buffer(){
|
||||||
|
return getTSData(format_log_msg_buffer,FORMAT_LOG_BUF_SIZE);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
char* get_time_buffer(){
|
||||||
|
static char buf[TIME_NOW_BUF_SIZE];
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* get_format_log_buffer(){
|
||||||
|
static char buf[FORMAT_LOG_BUF_SIZE];
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ZooLogLevel logLevel=ZOO_LOG_LEVEL_INFO;
|
||||||
|
|
||||||
|
static FILE* logStream=0;
|
||||||
|
FILE* zoo_get_log_stream(){
|
||||||
|
if(logStream==0)
|
||||||
|
logStream=stderr;
|
||||||
|
return logStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
void zoo_set_log_stream(FILE* stream){
|
||||||
|
logStream=stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* time_now(char* now_str){
|
||||||
|
struct timeval tv;
|
||||||
|
struct tm lt;
|
||||||
|
time_t now = 0;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
gettimeofday(&tv,0);
|
||||||
|
|
||||||
|
now = tv.tv_sec;
|
||||||
|
localtime_r(&now, <);
|
||||||
|
|
||||||
|
// clone the format used by log4j ISO8601DateFormat
|
||||||
|
// specifically: "yyyy-MM-dd HH:mm:ss,SSS"
|
||||||
|
|
||||||
|
len = strftime(now_str, TIME_NOW_BUF_SIZE,
|
||||||
|
"%Y-%m-%d %H:%M:%S",
|
||||||
|
<);
|
||||||
|
|
||||||
|
len += snprintf(now_str + len,
|
||||||
|
TIME_NOW_BUF_SIZE - len,
|
||||||
|
",%03d",
|
||||||
|
(int)(tv.tv_usec/1000));
|
||||||
|
|
||||||
|
return now_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_message(log_callback_fn callback, ZooLogLevel curLevel,
|
||||||
|
int line, const char* funcName, const char* format, ...)
|
||||||
|
{
|
||||||
|
static const char* dbgLevelStr[]={"ZOO_INVALID","ZOO_ERROR","ZOO_WARN",
|
||||||
|
"ZOO_INFO","ZOO_DEBUG"};
|
||||||
|
static pid_t pid=0;
|
||||||
|
va_list va;
|
||||||
|
int ofs = 0;
|
||||||
|
#ifdef THREADED
|
||||||
|
unsigned long int tid = 0;
|
||||||
|
#endif
|
||||||
|
#ifdef WIN32
|
||||||
|
char timebuf [TIME_NOW_BUF_SIZE];
|
||||||
|
const char* time = time_now(timebuf);
|
||||||
|
#else
|
||||||
|
const char* time = time_now(get_time_buffer());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char* buf = get_format_log_buffer();
|
||||||
|
if(!buf)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "log_message: Unable to allocate memory buffer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pid==0)
|
||||||
|
{
|
||||||
|
pid=getpid();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef THREADED
|
||||||
|
|
||||||
|
// pid_t is long on Solaris
|
||||||
|
ofs = snprintf(buf, FORMAT_LOG_BUF_SIZE,
|
||||||
|
"%s:%ld:%s@%s@%d: ", time, (long)pid,
|
||||||
|
dbgLevelStr[curLevel], funcName, line);
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
tid = (unsigned long int)(pthread_self().thread_id);
|
||||||
|
#else
|
||||||
|
tid = (unsigned long int)(pthread_self());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ofs = snprintf(buf, FORMAT_LOG_BUF_SIZE-1,
|
||||||
|
"%s:%ld(0x%lx):%s@%s@%d: ", time, (long)pid, tid,
|
||||||
|
dbgLevelStr[curLevel], funcName, line);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Now grab the actual message out of the variadic arg list
|
||||||
|
va_start(va, format);
|
||||||
|
vsnprintf(buf+ofs, FORMAT_LOG_BUF_SIZE-1-ofs, format, va);
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
if (callback)
|
||||||
|
{
|
||||||
|
callback(buf);
|
||||||
|
} else {
|
||||||
|
fprintf(zoo_get_log_stream(), "%s\n", buf);
|
||||||
|
fflush(zoo_get_log_stream());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void zoo_set_debug_level(ZooLogLevel level)
|
||||||
|
{
|
||||||
|
if(level==0){
|
||||||
|
// disable logging (unit tests do this)
|
||||||
|
logLevel=(ZooLogLevel)0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(level<ZOO_LOG_LEVEL_ERROR)level=ZOO_LOG_LEVEL_ERROR;
|
||||||
|
if(level>ZOO_LOG_LEVEL_DEBUG)level=ZOO_LOG_LEVEL_DEBUG;
|
||||||
|
logLevel=level;
|
||||||
|
}
|
||||||
|
|
5405
zookeeper-client/zookeeper-client-c/src/zookeeper.c
Normal file
5405
zookeeper-client/zookeeper-client-c/src/zookeeper.c
Normal file
File diff suppressed because it is too large
Load Diff
127
zookeeper-client/zookeeper-client-c/ssl/gencerts.sh
Normal file
127
zookeeper-client/zookeeper-client-c/ssl/gencerts.sh
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
# contributor license agreements. See the NOTICE file distributed with
|
||||||
|
# this work for additional information regarding copyright ownership.
|
||||||
|
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
# (the "License"); you may not use this file except in compliance with
|
||||||
|
# the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
#
|
||||||
|
# This script cleans up old transaction logs and snapshots
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# If this scripted is run out of /usr/bin or some other system bin directory
|
||||||
|
# it should be linked to and not copied. Things like java jar files are found
|
||||||
|
# relative to the canonical path of this script.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
# determining the domain name in the certificates:
|
||||||
|
# - use the first commandline argument, if present
|
||||||
|
# - if not, then use the fully qualified domain name
|
||||||
|
# - if `hostname` command fails, fall back to zookeeper.apache.org
|
||||||
|
FQDN=`hostname -f`
|
||||||
|
FQDN=${1:-$FQDN}
|
||||||
|
FQDN=${FQDN:-"zookeeper.apache.org"}
|
||||||
|
|
||||||
|
# Generate the root key
|
||||||
|
openssl genrsa -out rootkey.pem 2048
|
||||||
|
|
||||||
|
#Generate the root Cert
|
||||||
|
openssl req -x509 -new -key rootkey.pem -out root.crt -config <(
|
||||||
|
cat <<-EOF
|
||||||
|
[ req ]
|
||||||
|
default_bits = 2048
|
||||||
|
prompt = no
|
||||||
|
default_md = sha256
|
||||||
|
distinguished_name = dn
|
||||||
|
|
||||||
|
[ dn ]
|
||||||
|
C = US
|
||||||
|
ST = California
|
||||||
|
L = San Francisco
|
||||||
|
O = ZooKeeper
|
||||||
|
emailAddress = dev@$FQDN
|
||||||
|
CN = $FQDN
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
|
||||||
|
#Generate Client Key
|
||||||
|
openssl genrsa -out clientkey.pem 2048
|
||||||
|
|
||||||
|
#Generate Client Cert
|
||||||
|
openssl req -new -key clientkey.pem -out client.csr -config <(
|
||||||
|
cat <<-EOF
|
||||||
|
[ req ]
|
||||||
|
default_bits = 2048
|
||||||
|
prompt = no
|
||||||
|
default_md = sha256
|
||||||
|
distinguished_name = dn
|
||||||
|
|
||||||
|
[ dn ]
|
||||||
|
C = US
|
||||||
|
ST = California
|
||||||
|
L = San Francisco
|
||||||
|
O = ZooKeeper
|
||||||
|
emailAddress = dev@$FQDN
|
||||||
|
CN = $FQDN
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
openssl x509 -req -in client.csr -CA root.crt -CAkey rootkey.pem -CAcreateserial -days 3650 -out client.crt
|
||||||
|
|
||||||
|
#Export in pkcs12 format
|
||||||
|
openssl pkcs12 -export -in client.crt -inkey clientkey.pem -out client.pkcs12 -password pass:password
|
||||||
|
|
||||||
|
# Import Keystore in JKS
|
||||||
|
keytool -importkeystore -srckeystore client.pkcs12 -destkeystore client.jks -srcstoretype pkcs12 -srcstorepass password -deststorepass password
|
||||||
|
|
||||||
|
############################################################
|
||||||
|
|
||||||
|
#Generate Server key
|
||||||
|
openssl genrsa -out serverkey.pem 2048
|
||||||
|
|
||||||
|
#Generate Server Cert
|
||||||
|
openssl req -new -key serverkey.pem -out server.csr -config <(
|
||||||
|
cat <<-EOF
|
||||||
|
[ req ]
|
||||||
|
default_bits = 2048
|
||||||
|
prompt = no
|
||||||
|
default_md = sha256
|
||||||
|
distinguished_name = dn
|
||||||
|
|
||||||
|
[ dn ]
|
||||||
|
C = US
|
||||||
|
ST = California
|
||||||
|
L = San Francisco
|
||||||
|
O = ZooKeeper
|
||||||
|
emailAddress = dev@$FQDN
|
||||||
|
CN = $FQDN
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
openssl x509 -req -in server.csr -CA root.crt -CAkey rootkey.pem -CAcreateserial -days 3650 -out server.crt
|
||||||
|
|
||||||
|
#Export in pkcs12 format
|
||||||
|
openssl pkcs12 -export -in server.crt -inkey serverkey.pem -out server.pkcs12 -password pass:password
|
||||||
|
|
||||||
|
# Import Keystore in JKS
|
||||||
|
keytool -importkeystore -srckeystore server.pkcs12 -destkeystore server.jks -srcstoretype pkcs12 -srcstorepass password -deststorepass password
|
||||||
|
|
||||||
|
|
||||||
|
keytool -importcert -keystore server.jks -file root.crt -storepass password -noprompt
|
||||||
|
|
||||||
|
keytool -importcert -alias ca -file root.crt -keystore clienttrust.jks -storepass password -noprompt
|
||||||
|
|
||||||
|
keytool -importcert -alias clientcert -file client.crt -keystore clienttrust.jks -storepass password -noprompt
|
||||||
|
|
||||||
|
keytool -importcert -alias ca -file root.crt -keystore servertrust.jks -storepass password -noprompt
|
||||||
|
keytool -importcert -alias servercert -file server.crt -keystore servertrust.jks -storepass password -noprompt
|
195
zookeeper-client/zookeeper-client-c/tests/CollectionUtil.h
Normal file
195
zookeeper-client/zookeeper-client-c/tests/CollectionUtil.h
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#ifndef _COLLECTION_UTIL_H_
|
||||||
|
#define _COLLECTION_UTIL_H_
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* CollectionBuilder and DictionaryBuilder classes and collection utility functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Util
|
||||||
|
{
|
||||||
|
|
||||||
|
// *********************************************************
|
||||||
|
/** A shortcut to use for building collections.
|
||||||
|
* This class is a wrapper around standard STL collection containers such as vector.
|
||||||
|
* It allows one to conveniently build collections at the variable initialization time:
|
||||||
|
* \code
|
||||||
|
* #include "CollectionUtil.h"
|
||||||
|
* #include "Vector.h" // for ostream << operator overload for STL vector
|
||||||
|
* using Util;
|
||||||
|
*
|
||||||
|
* int main()
|
||||||
|
* {
|
||||||
|
* typedef vector<string> MyVector;
|
||||||
|
* MyVector myVector=CollectionBuilder<MyVector>()("str1")("str2")("str3");
|
||||||
|
* cout<<myVector;
|
||||||
|
* // the following output will be produced:
|
||||||
|
* // [str1,str2,str3]
|
||||||
|
* }
|
||||||
|
* \endcode
|
||||||
|
*/
|
||||||
|
template <class CONT>
|
||||||
|
class CollectionBuilder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// Type of the collection container.
|
||||||
|
typedef CONT CollectionType;
|
||||||
|
/// Container's value type.
|
||||||
|
typedef typename CollectionType::value_type value_type;
|
||||||
|
/// Container's constant iterator type.
|
||||||
|
typedef typename CollectionType::const_iterator const_iterator;
|
||||||
|
/// Container's size type.
|
||||||
|
typedef typename CollectionType::size_type size_type;
|
||||||
|
|
||||||
|
/** Operator function call overload to allow call chaining.
|
||||||
|
* \param value the value to be inserted into the container
|
||||||
|
*/
|
||||||
|
CollectionBuilder<CONT>& operator()(const value_type& value){
|
||||||
|
return push_back(value);
|
||||||
|
}
|
||||||
|
/** Same as regular STL push_back() but allows call chaining.
|
||||||
|
* \param value the value to be inserted into the container
|
||||||
|
*/
|
||||||
|
CollectionBuilder<CONT>& push_back(const value_type& value){
|
||||||
|
collection_.push_back(value);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
/// \name Standard STL container interface
|
||||||
|
/// @{
|
||||||
|
const_iterator begin() const{return collection_.begin();}
|
||||||
|
const_iterator end() const{return collection_.end();}
|
||||||
|
size_type size() const{return collection_.size();}
|
||||||
|
void clear() {collection_.clear();}
|
||||||
|
///@}
|
||||||
|
/// Explicit typecast operator.
|
||||||
|
operator const CollectionType&() const {return collection_;}
|
||||||
|
private:
|
||||||
|
/// \cond PRIVATE
|
||||||
|
CollectionType collection_;
|
||||||
|
/// \endcond
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// *********************************************************
|
||||||
|
/** A shortcut to use for building dictionaries.
|
||||||
|
* This class is a wrapper around standard STL associative containers such as map.
|
||||||
|
* It allows one to conveniently build dictionaries at the variable initialization time:
|
||||||
|
* \code
|
||||||
|
* #include "CollectionUtil.h"
|
||||||
|
* #include "Map.h" // for ostream << operator overload for STL map
|
||||||
|
* using Util;
|
||||||
|
*
|
||||||
|
* int main()
|
||||||
|
* {
|
||||||
|
* typedef map<string,int> MyMap;
|
||||||
|
* MyMap myMap=DictionaryBuilder<MyMap>()("str1",1)("str2",2)("str3",3);
|
||||||
|
* cout<<myMap;
|
||||||
|
* // the following output will be produced:
|
||||||
|
* // [str1=1,str2=2,str3=3]
|
||||||
|
* }
|
||||||
|
* \endcode
|
||||||
|
*/
|
||||||
|
template <class CONT>
|
||||||
|
class DictionaryBuilder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// The type of the associative container
|
||||||
|
typedef CONT DictionaryType;
|
||||||
|
/// Container's element type (usually a pair<key_type,mapped_type>)
|
||||||
|
typedef typename DictionaryType::value_type value_type;
|
||||||
|
/// Container's key type
|
||||||
|
typedef typename DictionaryType::key_type key_type;
|
||||||
|
/// Container's value type
|
||||||
|
typedef typename DictionaryType::mapped_type mapped_type;
|
||||||
|
/// Container's constant iterator type
|
||||||
|
typedef typename DictionaryType::const_iterator const_iterator;
|
||||||
|
/// Container's writable iterator type
|
||||||
|
typedef typename DictionaryType::iterator iterator;
|
||||||
|
/// Container's size type
|
||||||
|
typedef typename DictionaryType::size_type size_type;
|
||||||
|
|
||||||
|
/** Operator function call overload to allow call chaining.
|
||||||
|
* \param key the value key to be inserted
|
||||||
|
* \param value the value to be inserted into the container
|
||||||
|
* \return a non-const reference to self
|
||||||
|
*/
|
||||||
|
DictionaryBuilder<CONT>& operator()(const key_type& key,const mapped_type& value){
|
||||||
|
dict_.insert(value_type(key,value));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
/** Lookup value by key.
|
||||||
|
* \param key the key associated with the value.
|
||||||
|
* \return a non-const iterator pointing to the element whose key matched the \a key parameter
|
||||||
|
*/
|
||||||
|
iterator find(const key_type& key){
|
||||||
|
return dict_.find(key);
|
||||||
|
}
|
||||||
|
/** Lookup value by key.
|
||||||
|
* \param key the key associated with the value.
|
||||||
|
* \return a const iterator pointing to the element whose key matched the \a key parameter
|
||||||
|
*/
|
||||||
|
const_iterator find(const key_type& key) const{
|
||||||
|
return dict_.find(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \name Standard STL container interface
|
||||||
|
/// @{
|
||||||
|
const_iterator begin() const{return dict_.begin();}
|
||||||
|
const_iterator end() const{return dict_.end();}
|
||||||
|
size_type size() const{return dict_.size();}
|
||||||
|
void clear() {dict_.clear();}
|
||||||
|
///@}
|
||||||
|
/// Explicit typecast operator.
|
||||||
|
operator const DictionaryType&() const {return dict_;}
|
||||||
|
private:
|
||||||
|
DictionaryType dict_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// ***********************************************************
|
||||||
|
/** Deletes all dynamically allocated elements of a collection.
|
||||||
|
* C::value_type is expected to be a pointer to a dynamically allocated object, or it won't compile.
|
||||||
|
* The function will iterate over all container elements and call delete for each of them.
|
||||||
|
* \param c a collection (vector,set) whose elements are being deleted.
|
||||||
|
*/
|
||||||
|
template <class C>
|
||||||
|
void clearCollection(C& c){
|
||||||
|
for(typename C::const_iterator it=c.begin();it!=c.end();++it)
|
||||||
|
delete *it;
|
||||||
|
c.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Deletes all dynamically allocated values of the assotiative container.
|
||||||
|
* The function expects the M::value_type to be a pair<..., ptr_to_type>, or it won't compile.
|
||||||
|
* It first deletes the objects pointed to by ptr_to_type
|
||||||
|
* and then clears (calls m.clear()) the container.
|
||||||
|
* \param m an associative container (map,hash_map) whose elements are being deleted.
|
||||||
|
*/
|
||||||
|
template <class M>
|
||||||
|
void clearMap(M& m){
|
||||||
|
for(typename M::const_iterator it=m.begin();it!=m.end();++it)
|
||||||
|
delete it->second;
|
||||||
|
m.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Util
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _COLLECTION_UTIL_H_
|
37
zookeeper-client/zookeeper-client-c/tests/CppAssertHelper.h
Normal file
37
zookeeper-client/zookeeper-client-c/tests/CppAssertHelper.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPPASSERTHELPER_H_
|
||||||
|
#define CPPASSERTHELPER_H_
|
||||||
|
|
||||||
|
#include <cppunit/TestAssert.h>
|
||||||
|
|
||||||
|
// make it possible to specify location of the ASSERT call
|
||||||
|
#define CPPUNIT_ASSERT_EQUAL_LOC(expected,actual,file,line) \
|
||||||
|
( CPPUNIT_NS::assertEquals( (expected), \
|
||||||
|
(actual), \
|
||||||
|
CPPUNIT_NS::SourceLine(file,line), \
|
||||||
|
"" ) )
|
||||||
|
|
||||||
|
#define CPPUNIT_ASSERT_EQUAL_MESSAGE_LOC(message,expected,actual,file,line) \
|
||||||
|
( CPPUNIT_NS::assertEquals( (expected), \
|
||||||
|
(actual), \
|
||||||
|
CPPUNIT_NS::SourceLine(file,line), \
|
||||||
|
(message) ) )
|
||||||
|
|
||||||
|
#endif /*CPPASSERTHELPER_H_*/
|
352
zookeeper-client/zookeeper-client-c/tests/LibCMocks.cc
Normal file
352
zookeeper-client/zookeeper-client-c/tests/LibCMocks.cc
Normal file
@ -0,0 +1,352 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstdarg>
|
||||||
|
#include <iostream>
|
||||||
|
#include <unistd.h> // needed for _POSIX_MONOTONIC_CLOCK
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "Util.h"
|
||||||
|
#include "LibCMocks.h"
|
||||||
|
|
||||||
|
#undef USING_DUMA
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// *****************************************************************************
|
||||||
|
// gethostbyname
|
||||||
|
|
||||||
|
struct hostent* gethostbyname(const char *name) {
|
||||||
|
if(!Mock_gethostbyname::mock_)
|
||||||
|
return LIBC_SYMBOLS.gethostbyname(name);
|
||||||
|
return Mock_gethostbyname::mock_->call(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
Mock_gethostbyname* Mock_gethostbyname::mock_=0;
|
||||||
|
|
||||||
|
Mock_gethostbyname::~Mock_gethostbyname(){
|
||||||
|
mock_=0;
|
||||||
|
for(unsigned int i=0;i<gethostbynameReturns.size();i++)
|
||||||
|
delete gethostbynameReturns[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
Mock_gethostbyname::HostEntry& Mock_gethostbyname::addHostEntry(
|
||||||
|
const char* hostName, short addrtype) {
|
||||||
|
gethostbynameReturns.push_back(new HostEntry(hostName, addrtype));
|
||||||
|
return *gethostbynameReturns.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
hostent* Mock_gethostbyname::call(const char* name) {
|
||||||
|
assert("Must add one or more mock hostent entries first"&&
|
||||||
|
(gethostbynameReturns.size()!=0));
|
||||||
|
return gethostbynameReturns[current++ % gethostbynameReturns.size()];
|
||||||
|
}
|
||||||
|
|
||||||
|
static char** appendString(char **list,const char* str,int len=0){
|
||||||
|
const int SIZE_INCREMENT=16;
|
||||||
|
if(list==0)
|
||||||
|
list=(char**)LIBC_SYMBOLS.calloc(SIZE_INCREMENT,sizeof(char*));
|
||||||
|
// find the first available slot
|
||||||
|
int count=0;
|
||||||
|
for(char** ptr=list; *ptr!=0; ptr++,count++);
|
||||||
|
if(((count+1)%SIZE_INCREMENT)==0){
|
||||||
|
list=(char**)LIBC_SYMBOLS.realloc(list,(count+1+SIZE_INCREMENT)*sizeof(char*));
|
||||||
|
memset(list+count+1,0,SIZE_INCREMENT*sizeof(char*));
|
||||||
|
}
|
||||||
|
if(len==0){
|
||||||
|
len=strlen(str)+1;
|
||||||
|
}
|
||||||
|
char* ptr=(char*)malloc(len);
|
||||||
|
memcpy(ptr,str,len);
|
||||||
|
list[count]=ptr;
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void freeList(char **list){
|
||||||
|
if(list==0) return;
|
||||||
|
for(char** ptr=list; *ptr!=0; ptr++)
|
||||||
|
LIBC_SYMBOLS.free((void*)*ptr);
|
||||||
|
LIBC_SYMBOLS.free((void*)list);
|
||||||
|
}
|
||||||
|
|
||||||
|
Mock_gethostbyname::HostEntry::HostEntry(const char* hostName, short addrtype) {
|
||||||
|
h_name=strdup(hostName);
|
||||||
|
h_addrtype=addrtype;
|
||||||
|
if(addrtype==AF_INET)
|
||||||
|
h_length=4;
|
||||||
|
else{
|
||||||
|
#ifdef AF_INET6
|
||||||
|
h_length=6; // TODO: not really sure, verify!
|
||||||
|
#else
|
||||||
|
assert("AF_INET6 not supported yet"&&false);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
h_aliases=h_addr_list=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mock_gethostbyname::HostEntry::~HostEntry(){
|
||||||
|
if(h_name) LIBC_SYMBOLS.free((void*)h_name);
|
||||||
|
freeList(h_aliases); h_aliases=0;
|
||||||
|
freeList(h_addr_list); h_addr_list=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mock_gethostbyname::HostEntry& Mock_gethostbyname::HostEntry::addAlias(
|
||||||
|
const char* alias) {
|
||||||
|
h_aliases=appendString(h_aliases,alias);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mock_gethostbyname::HostEntry& Mock_gethostbyname::HostEntry::addAddress(
|
||||||
|
const char* addr4) {
|
||||||
|
h_addr_list=appendString(h_addr_list,addr4,4);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// *****************************************************************************
|
||||||
|
// calloc
|
||||||
|
#ifndef USING_DUMA
|
||||||
|
DECLARE_WRAPPER(void*,calloc,(size_t p1, size_t p2)){
|
||||||
|
if(!Mock_calloc::mock_)
|
||||||
|
return CALL_REAL(calloc,(p1,p2));
|
||||||
|
return Mock_calloc::mock_->call(p1,p2);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void* Mock_calloc::call(size_t p1, size_t p2){
|
||||||
|
#ifndef USING_DUMA
|
||||||
|
if(counter++ ==callsBeforeFailure){
|
||||||
|
counter=0;
|
||||||
|
errno=errnoOnFailure;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return CALL_REAL(calloc,(p1,p2));
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Mock_calloc* Mock_calloc::mock_=0;
|
||||||
|
|
||||||
|
// *****************************************************************************
|
||||||
|
// realloc
|
||||||
|
|
||||||
|
#ifndef USING_DUMA
|
||||||
|
DECLARE_WRAPPER(void*,realloc,(void* p, size_t s)){
|
||||||
|
if(!Mock_realloc::mock_)
|
||||||
|
return LIBC_SYMBOLS.realloc(p,s);
|
||||||
|
return Mock_realloc::mock_->call(p,s);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Mock_realloc* Mock_realloc::mock_=0;
|
||||||
|
|
||||||
|
void* Mock_realloc::call(void* p, size_t s){
|
||||||
|
if(counter++ ==callsBeforeFailure){
|
||||||
|
counter=0;
|
||||||
|
errno=errnoOnFailure;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return LIBC_SYMBOLS.realloc(p,s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// *****************************************************************************
|
||||||
|
// random
|
||||||
|
RANDOM_RET_TYPE random(){
|
||||||
|
if(!Mock_random::mock_)
|
||||||
|
return LIBC_SYMBOLS.random();
|
||||||
|
return Mock_random::mock_->call();
|
||||||
|
}
|
||||||
|
|
||||||
|
void srandom(unsigned long seed){
|
||||||
|
if (!Mock_random::mock_)
|
||||||
|
LIBC_SYMBOLS.srandom(seed);
|
||||||
|
else
|
||||||
|
Mock_random::mock_->setSeed(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
Mock_random* Mock_random::mock_=0;
|
||||||
|
|
||||||
|
int Mock_random::call(){
|
||||||
|
assert("Must specify one or more random integers"&&(randomReturns.size()!=0));
|
||||||
|
return randomReturns[currentIdx++ % randomReturns.size()];
|
||||||
|
}
|
||||||
|
|
||||||
|
// *****************************************************************************
|
||||||
|
// free
|
||||||
|
#ifndef USING_DUMA
|
||||||
|
DECLARE_WRAPPER(void,free,(void* p)){
|
||||||
|
if(Mock_free_noop::mock_ && !Mock_free_noop::mock_->nested)
|
||||||
|
Mock_free_noop::mock_->call(p);
|
||||||
|
else
|
||||||
|
CALL_REAL(free,(p));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void Mock_free_noop::call(void* p){
|
||||||
|
// on cygwin libc++ is linked statically
|
||||||
|
// push_back() may call free(), hence the nesting guards
|
||||||
|
synchronized(mx);
|
||||||
|
nested++;
|
||||||
|
callCounter++;
|
||||||
|
requested.push_back(p);
|
||||||
|
nested--;
|
||||||
|
}
|
||||||
|
void Mock_free_noop::freeRequested(){
|
||||||
|
#ifndef USING_DUMA
|
||||||
|
synchronized(mx);
|
||||||
|
for(unsigned i=0; i<requested.size();i++)
|
||||||
|
CALL_REAL(free,(requested[i]));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int Mock_free_noop::getFreeCount(void* p){
|
||||||
|
int cnt=0;
|
||||||
|
synchronized(mx);
|
||||||
|
for(unsigned i=0;i<requested.size();i++)
|
||||||
|
if(requested[i]==p)cnt++;
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Mock_free_noop::isFreed(void* p){
|
||||||
|
synchronized(mx);
|
||||||
|
for(unsigned i=0;i<requested.size();i++)
|
||||||
|
if(requested[i]==p)return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mock_free_noop* Mock_free_noop::mock_=0;
|
||||||
|
|
||||||
|
// *****************************************************************************
|
||||||
|
// socket
|
||||||
|
int socket(int domain, int type, int protocol){
|
||||||
|
if (!Mock_socket::mock_)
|
||||||
|
return LIBC_SYMBOLS.socket(domain,type,protocol);
|
||||||
|
return Mock_socket::mock_->callSocket(domain,type,protocol);
|
||||||
|
}
|
||||||
|
|
||||||
|
int close(int fd){
|
||||||
|
if (!Mock_socket::mock_)
|
||||||
|
return LIBC_SYMBOLS.close(fd);
|
||||||
|
return Mock_socket::mock_->callClose(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getsockopt(int s,int level,int optname,void *optval,socklen_t *optlen){
|
||||||
|
if (!Mock_socket::mock_)
|
||||||
|
return LIBC_SYMBOLS.getsockopt(s,level,optname,optval,optlen);
|
||||||
|
return Mock_socket::mock_->callGet(s,level,optname,optval,optlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int setsockopt(int s,int level,int optname,const void *optval,socklen_t optlen){
|
||||||
|
if (!Mock_socket::mock_)
|
||||||
|
return LIBC_SYMBOLS.setsockopt(s,level,optname,optval,optlen);
|
||||||
|
return Mock_socket::mock_->callSet(s,level,optname,optval,optlen);
|
||||||
|
}
|
||||||
|
int connect(int s,const struct sockaddr *addr,socklen_t len){
|
||||||
|
#ifdef AF_UNIX
|
||||||
|
/* don't mock UNIX domain sockets */
|
||||||
|
if (!Mock_socket::mock_ || addr->sa_family == AF_UNIX)
|
||||||
|
#else
|
||||||
|
if (!Mock_socket::mock_)
|
||||||
|
#endif
|
||||||
|
return LIBC_SYMBOLS.connect(s,addr,len);
|
||||||
|
return Mock_socket::mock_->callConnect(s,addr,len);
|
||||||
|
}
|
||||||
|
ssize_t send(int s,const void *buf,size_t len,int flags){
|
||||||
|
if (!Mock_socket::mock_)
|
||||||
|
return LIBC_SYMBOLS.send(s,buf,len,flags);
|
||||||
|
return Mock_socket::mock_->callSend(s,buf,len,flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t recv(int s,void *buf,size_t len,int flags){
|
||||||
|
if (!Mock_socket::mock_)
|
||||||
|
return LIBC_SYMBOLS.recv(s,buf,len,flags);
|
||||||
|
return Mock_socket::mock_->callRecv(s,buf,len,flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
Mock_socket* Mock_socket::mock_=0;
|
||||||
|
|
||||||
|
// *****************************************************************************
|
||||||
|
// fcntl
|
||||||
|
extern "C" int fcntl(int fd,int cmd,...){
|
||||||
|
va_list va;
|
||||||
|
va_start(va,cmd);
|
||||||
|
void* arg = va_arg(va, void *);
|
||||||
|
va_end (va);
|
||||||
|
if (!Mock_fcntl::mock_)
|
||||||
|
return LIBC_SYMBOLS.fcntl(fd,cmd,arg);
|
||||||
|
return Mock_fcntl::mock_->call(fd,cmd,arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
Mock_fcntl* Mock_fcntl::mock_=0;
|
||||||
|
|
||||||
|
// *****************************************************************************
|
||||||
|
// select
|
||||||
|
int select(int nfds,fd_set *rfds,fd_set *wfds,fd_set *efds,struct timeval *timeout){
|
||||||
|
if (!Mock_select::mock_)
|
||||||
|
return LIBC_SYMBOLS.select(nfds,rfds,wfds,efds,timeout);
|
||||||
|
return Mock_select::mock_->call(nfds,rfds,wfds,efds,timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
Mock_select* Mock_select::mock_=0;
|
||||||
|
|
||||||
|
// *****************************************************************************
|
||||||
|
// poll
|
||||||
|
Mock_poll* Mock_poll::mock_=0;
|
||||||
|
int poll(struct pollfd *fds, POLL_NFDS_TYPE nfds, int timeout){
|
||||||
|
if (!Mock_poll::mock_)
|
||||||
|
return LIBC_SYMBOLS.poll(fds,nfds,timeout);
|
||||||
|
return Mock_poll::mock_->call(fds,nfds,timeout);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Recent gcc with -O2 and glibc FORTIFY feature may cause our poll
|
||||||
|
* mock to be ignored.
|
||||||
|
*/
|
||||||
|
#if __USE_FORTIFY_LEVEL > 0
|
||||||
|
int __poll_chk (struct pollfd *__fds, nfds_t __nfds, int __timeout,
|
||||||
|
__SIZE_TYPE__ __fdslen) {
|
||||||
|
return poll(__fds, __nfds, __timeout);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// *****************************************************************************
|
||||||
|
// gettimeofday
|
||||||
|
int gettimeofday(struct timeval *tp, GETTIMEOFDAY_ARG2_TYPE tzp){
|
||||||
|
if (!Mock_gettimeofday::mock_)
|
||||||
|
return LIBC_SYMBOLS.gettimeofday(tp,tzp);
|
||||||
|
return Mock_gettimeofday::mock_->call(tp,tzp);
|
||||||
|
}
|
||||||
|
|
||||||
|
Mock_gettimeofday* Mock_gettimeofday::mock_=0;
|
||||||
|
|
||||||
|
// *****************************************************************************
|
||||||
|
#ifdef _POSIX_MONOTONIC_CLOCK
|
||||||
|
// clock_gettime
|
||||||
|
int clock_gettime(clockid_t id, struct timespec *tp) {
|
||||||
|
if (!Mock_gettimeofday::mock_)
|
||||||
|
return LIBC_SYMBOLS.clock_gettime(id,tp);
|
||||||
|
struct timeval tv = { 0 };
|
||||||
|
int res = Mock_gettimeofday::mock_->call(&tv, NULL);
|
||||||
|
tp->tv_sec = tv.tv_sec;
|
||||||
|
tp->tv_nsec = tv.tv_usec * 1000;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#endif
|
408
zookeeper-client/zookeeper-client-c/tests/LibCMocks.h
Normal file
408
zookeeper-client/zookeeper-client-c/tests/LibCMocks.h
Normal file
@ -0,0 +1,408 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIBCMOCKS_H_
|
||||||
|
#define LIBCMOCKS_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "MocksBase.h"
|
||||||
|
#include "LibCSymTable.h"
|
||||||
|
#include "ThreadingUtil.h"
|
||||||
|
|
||||||
|
// *****************************************************************************
|
||||||
|
// gethostbyname
|
||||||
|
|
||||||
|
class Mock_gethostbyname: public Mock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct HostEntry: public hostent {
|
||||||
|
HostEntry(const char* hostName,short addrtype);
|
||||||
|
~HostEntry();
|
||||||
|
HostEntry& addAlias(const char* alias);
|
||||||
|
HostEntry& addAddress(const char* addr4);
|
||||||
|
};
|
||||||
|
|
||||||
|
Mock_gethostbyname():current(0){mock_=this;}
|
||||||
|
virtual ~Mock_gethostbyname();
|
||||||
|
HostEntry& addHostEntry(const char* hostName,short addrtype=AF_INET);
|
||||||
|
virtual hostent* call(const char* name);
|
||||||
|
|
||||||
|
typedef std::vector<HostEntry*> HostEntryCollection;
|
||||||
|
HostEntryCollection gethostbynameReturns;
|
||||||
|
int current;
|
||||||
|
static Mock_gethostbyname* mock_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MockFailed_gethostbyname: public Mock_gethostbyname
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MockFailed_gethostbyname():h_errnoReturn(HOST_NOT_FOUND) {}
|
||||||
|
|
||||||
|
int h_errnoReturn;
|
||||||
|
virtual hostent* call(const char* name) {
|
||||||
|
h_errno=h_errnoReturn;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// *****************************************************************************
|
||||||
|
// calloc
|
||||||
|
|
||||||
|
class Mock_calloc: public Mock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Mock_calloc():errnoOnFailure(ENOMEM),callsBeforeFailure(-1),counter(0) {
|
||||||
|
mock_=this;
|
||||||
|
}
|
||||||
|
virtual ~Mock_calloc() {mock_=0;}
|
||||||
|
|
||||||
|
int errnoOnFailure;
|
||||||
|
int callsBeforeFailure;
|
||||||
|
int counter;
|
||||||
|
virtual void* call(size_t p1, size_t p2);
|
||||||
|
|
||||||
|
static Mock_calloc* mock_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// *****************************************************************************
|
||||||
|
// realloc
|
||||||
|
|
||||||
|
class Mock_realloc: public Mock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Mock_realloc():errnoOnFailure(ENOMEM),callsBeforeFailure(-1),counter(0) {
|
||||||
|
mock_=this;
|
||||||
|
}
|
||||||
|
virtual ~Mock_realloc() {mock_=0;}
|
||||||
|
|
||||||
|
int errnoOnFailure;
|
||||||
|
int callsBeforeFailure;
|
||||||
|
int counter;
|
||||||
|
virtual void* call(void* p, size_t s);
|
||||||
|
|
||||||
|
static Mock_realloc* mock_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// *****************************************************************************
|
||||||
|
// random
|
||||||
|
|
||||||
|
class Mock_random: public Mock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Mock_random():currentIdx(0) {mock_=this;}
|
||||||
|
virtual ~Mock_random() {mock_=0;}
|
||||||
|
|
||||||
|
int currentIdx;
|
||||||
|
std::vector<int> randomReturns;
|
||||||
|
virtual int call();
|
||||||
|
void setSeed(unsigned long){currentIdx=0;}
|
||||||
|
|
||||||
|
static Mock_random* mock_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// *****************************************************************************
|
||||||
|
// no-op free; keeps track of all deallocation requests
|
||||||
|
class Mock_free_noop: public Mock
|
||||||
|
{
|
||||||
|
Mutex mx;
|
||||||
|
std::vector<void*> requested;
|
||||||
|
public:
|
||||||
|
Mock_free_noop():nested(0),callCounter(0){mock_=this;}
|
||||||
|
virtual ~Mock_free_noop(){
|
||||||
|
mock_=0;
|
||||||
|
freeRequested();
|
||||||
|
}
|
||||||
|
|
||||||
|
int nested;
|
||||||
|
int callCounter;
|
||||||
|
virtual void call(void* p);
|
||||||
|
void freeRequested();
|
||||||
|
void disable(){mock_=0;}
|
||||||
|
// returns number of times the pointer was freed
|
||||||
|
int getFreeCount(void*);
|
||||||
|
bool isFreed(void*);
|
||||||
|
|
||||||
|
static Mock_free_noop* mock_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// *****************************************************************************
|
||||||
|
// socket and related system calls
|
||||||
|
|
||||||
|
class Mock_socket: public Mock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const int FD=63;
|
||||||
|
Mock_socket():socketReturns(FD),closeReturns(0),getsocketoptReturns(0),
|
||||||
|
optvalSO_ERROR(0),
|
||||||
|
setsockoptReturns(0),connectReturns(0),connectErrno(0),
|
||||||
|
sendErrno(0),recvErrno(0)
|
||||||
|
{
|
||||||
|
mock_=this;
|
||||||
|
}
|
||||||
|
virtual ~Mock_socket(){mock_=0;}
|
||||||
|
|
||||||
|
int socketReturns;
|
||||||
|
virtual int callSocket(int domain, int type, int protocol){
|
||||||
|
return socketReturns;
|
||||||
|
}
|
||||||
|
int closeReturns;
|
||||||
|
virtual int callClose(int fd){
|
||||||
|
return closeReturns;
|
||||||
|
}
|
||||||
|
int getsocketoptReturns;
|
||||||
|
int optvalSO_ERROR;
|
||||||
|
virtual int callGet(int s,int level,int optname,void *optval,socklen_t *len){
|
||||||
|
if(level==SOL_SOCKET && optname==SO_ERROR){
|
||||||
|
setSO_ERROR(optval,*len);
|
||||||
|
}
|
||||||
|
return getsocketoptReturns;
|
||||||
|
}
|
||||||
|
virtual void setSO_ERROR(void *optval,socklen_t len){
|
||||||
|
memcpy(optval,&optvalSO_ERROR,len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int setsockoptReturns;
|
||||||
|
virtual int callSet(int s,int level,int optname,const void *optval,socklen_t len){
|
||||||
|
return setsockoptReturns;
|
||||||
|
}
|
||||||
|
int connectReturns;
|
||||||
|
int connectErrno;
|
||||||
|
virtual int callConnect(int s,const struct sockaddr *addr,socklen_t len){
|
||||||
|
errno=connectErrno;
|
||||||
|
return connectReturns;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void notifyBufferSent(const std::string& buffer){}
|
||||||
|
|
||||||
|
int sendErrno;
|
||||||
|
std::string sendBuffer;
|
||||||
|
virtual ssize_t callSend(int s,const void *buf,size_t len,int flags){
|
||||||
|
if(sendErrno!=0){
|
||||||
|
errno=sendErrno;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// first call to send() is always the length of the buffer to follow
|
||||||
|
bool sendingLength=sendBuffer.size()==0;
|
||||||
|
// overwrite the length bytes
|
||||||
|
sendBuffer.assign((const char*)buf,len);
|
||||||
|
if(!sendingLength){
|
||||||
|
notifyBufferSent(sendBuffer);
|
||||||
|
sendBuffer.erase();
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int recvErrno;
|
||||||
|
std::string recvReturnBuffer;
|
||||||
|
virtual ssize_t callRecv(int s,void *buf,size_t len,int flags){
|
||||||
|
if(recvErrno!=0){
|
||||||
|
errno=recvErrno;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int k=std::min(len,recvReturnBuffer.length());
|
||||||
|
if(k==0)
|
||||||
|
return 0;
|
||||||
|
memcpy(buf,recvReturnBuffer.data(),k);
|
||||||
|
recvReturnBuffer.erase(0,k);
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
virtual bool hasMoreRecv() const{
|
||||||
|
return recvReturnBuffer.size()!=0;
|
||||||
|
}
|
||||||
|
static Mock_socket* mock_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// *****************************************************************************
|
||||||
|
// fcntl
|
||||||
|
class Mock_fcntl: public Mock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Mock_fcntl():callReturns(0),trapFD(-1){mock_=this;}
|
||||||
|
~Mock_fcntl(){mock_=0;}
|
||||||
|
|
||||||
|
int callReturns;
|
||||||
|
int trapFD;
|
||||||
|
virtual int call(int fd, int cmd, void* arg){
|
||||||
|
if(trapFD==-1)
|
||||||
|
return LIBC_SYMBOLS.fcntl(fd,cmd,arg);
|
||||||
|
return callReturns;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Mock_fcntl* mock_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// *****************************************************************************
|
||||||
|
// select
|
||||||
|
class Mock_select: public Mock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Mock_select(Mock_socket* s,int fd):sock(s),
|
||||||
|
callReturns(0),myFD(fd),timeout(50)
|
||||||
|
{
|
||||||
|
mock_=this;
|
||||||
|
}
|
||||||
|
~Mock_select(){mock_=0;}
|
||||||
|
|
||||||
|
Mock_socket* sock;
|
||||||
|
int callReturns;
|
||||||
|
int myFD;
|
||||||
|
int timeout; //in millis
|
||||||
|
virtual int call(int nfds,fd_set *rfds,fd_set *wfds,fd_set *efds,struct timeval *tv){
|
||||||
|
bool isWritableRequested=(wfds && FD_ISSET(myFD,wfds));
|
||||||
|
if(rfds) FD_CLR(myFD,rfds);
|
||||||
|
if(wfds) FD_CLR(myFD,wfds);
|
||||||
|
// this timeout is only to prevent a tight loop
|
||||||
|
timeval myTimeout={0,0};
|
||||||
|
if(!isWritableRequested && !isFDReadable()){
|
||||||
|
myTimeout.tv_sec=timeout/1000;
|
||||||
|
myTimeout.tv_usec=(timeout%1000)*1000;
|
||||||
|
}
|
||||||
|
LIBC_SYMBOLS.select(nfds,rfds,wfds,efds,&myTimeout);
|
||||||
|
// myFD is always writable
|
||||||
|
if(isWritableRequested) FD_SET(myFD,wfds);
|
||||||
|
// myFD is only readable if the socket has anything to read
|
||||||
|
if(isFDReadable() && rfds) FD_SET(myFD,rfds);
|
||||||
|
return callReturns;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isFDReadable() const {
|
||||||
|
return sock->hasMoreRecv();
|
||||||
|
}
|
||||||
|
|
||||||
|
static Mock_select* mock_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// *****************************************************************************
|
||||||
|
// poll
|
||||||
|
// the last element of the pollfd array is expected to be test FD
|
||||||
|
class Mock_poll: public Mock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Mock_poll(Mock_socket* s,int fd):sock(s),
|
||||||
|
callReturns(1),myFD(fd),timeout(50)
|
||||||
|
{
|
||||||
|
mock_=this;
|
||||||
|
}
|
||||||
|
~Mock_poll(){mock_=0;}
|
||||||
|
|
||||||
|
Mock_socket* sock;
|
||||||
|
int callReturns;
|
||||||
|
int myFD;
|
||||||
|
int timeout; //in millis
|
||||||
|
virtual int call(struct pollfd *fds, POLL_NFDS_TYPE nfds, int to) {
|
||||||
|
pollfd* myPoll=0;
|
||||||
|
if(fds[nfds-1].fd==myFD)
|
||||||
|
myPoll=&fds[nfds-1];
|
||||||
|
bool isWritableRequested=false;
|
||||||
|
if(myPoll!=0){
|
||||||
|
isWritableRequested=myPoll->events&POLLOUT;
|
||||||
|
nfds--;
|
||||||
|
}
|
||||||
|
LIBC_SYMBOLS.poll(fds,nfds,(!isWritableRequested&&!isFDReadable())?timeout:0);
|
||||||
|
if(myPoll!=0){
|
||||||
|
// myFD is always writable if requested
|
||||||
|
myPoll->revents=isWritableRequested?POLLOUT:0;
|
||||||
|
// myFD is only readable if the socket has anything to read
|
||||||
|
myPoll->revents|=isFDReadable()?POLLIN:0;
|
||||||
|
}
|
||||||
|
return callReturns;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isFDReadable() const {
|
||||||
|
return sock->hasMoreRecv();
|
||||||
|
}
|
||||||
|
|
||||||
|
static Mock_poll* mock_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// *****************************************************************************
|
||||||
|
// gettimeofday
|
||||||
|
class Mock_gettimeofday: public Mock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Mock_gettimeofday(){
|
||||||
|
LIBC_SYMBOLS.gettimeofday(&tv,0);
|
||||||
|
mock_=this;
|
||||||
|
}
|
||||||
|
Mock_gettimeofday(const Mock_gettimeofday& other):tv(other.tv){}
|
||||||
|
Mock_gettimeofday(int32_t sec,int32_t usec){
|
||||||
|
tv.tv_sec=sec;
|
||||||
|
tv.tv_usec=usec;
|
||||||
|
}
|
||||||
|
~Mock_gettimeofday(){mock_=0;}
|
||||||
|
|
||||||
|
timeval tv;
|
||||||
|
virtual int call(struct timeval *tp, GETTIMEOFDAY_ARG2_TYPE tzp){
|
||||||
|
*tp=tv;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
operator timeval() const{
|
||||||
|
return tv;
|
||||||
|
}
|
||||||
|
// advance secs
|
||||||
|
virtual void tick(int howmuch=1){tv.tv_sec+=howmuch;}
|
||||||
|
// advance milliseconds
|
||||||
|
// can move the clock forward as well as backward by providing a negative
|
||||||
|
// number
|
||||||
|
virtual void millitick(int howmuch=1){
|
||||||
|
int ms=tv.tv_usec/1000+howmuch;
|
||||||
|
tv.tv_sec+=ms/1000;
|
||||||
|
// going backward?
|
||||||
|
if(ms<0){
|
||||||
|
ms=1000-(-ms%1000); //wrap millis around
|
||||||
|
}
|
||||||
|
tv.tv_usec=(ms%1000)*1000;
|
||||||
|
}
|
||||||
|
virtual void tick(const timeval& howmuch){
|
||||||
|
// add milliseconds (discarding microsecond portion)
|
||||||
|
long ms=tv.tv_usec/1000+howmuch.tv_usec/1000;
|
||||||
|
tv.tv_sec+=howmuch.tv_sec+ms/1000;
|
||||||
|
tv.tv_usec=(ms%1000)*1000;
|
||||||
|
}
|
||||||
|
static Mock_gettimeofday* mock_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// discard microseconds!
|
||||||
|
inline bool operator==(const timeval& lhs, const timeval& rhs){
|
||||||
|
return rhs.tv_sec==lhs.tv_sec && rhs.tv_usec/1000==lhs.tv_usec/1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
// simplistic implementation: no normalization, assume lhs >= rhs,
|
||||||
|
// discarding microseconds
|
||||||
|
inline timeval operator-(const timeval& lhs, const timeval& rhs){
|
||||||
|
timeval res;
|
||||||
|
res.tv_sec=lhs.tv_sec-rhs.tv_sec;
|
||||||
|
res.tv_usec=(lhs.tv_usec/1000-rhs.tv_usec/1000)*1000;
|
||||||
|
if(res.tv_usec<0){
|
||||||
|
res.tv_sec--;
|
||||||
|
res.tv_usec=1000000+res.tv_usec%1000000; // wrap the millis around
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int32_t toMilliseconds(const timeval& tv){
|
||||||
|
return tv.tv_sec*1000+tv.tv_usec/1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /*LIBCMOCKS_H_*/
|
87
zookeeper-client/zookeeper-client-c/tests/LibCSymTable.cc
Normal file
87
zookeeper-client/zookeeper-client-c/tests/LibCSymTable.cc
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "LibCSymTable.h"
|
||||||
|
#include <unistd.h> // needed for _POSIX_MONOTONIC_CLOCK
|
||||||
|
|
||||||
|
#define LOAD_SYM(sym) \
|
||||||
|
sym=(sym##_sig)dlsym(handle,#sym); \
|
||||||
|
assert("Unable to load "#sym" from libc"&&sym)
|
||||||
|
|
||||||
|
|
||||||
|
LibCSymTable& LibCSymTable::instance(){
|
||||||
|
static LibCSymTable tbl;
|
||||||
|
return tbl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//******************************************************************************
|
||||||
|
// preload original libc symbols
|
||||||
|
LibCSymTable::LibCSymTable()
|
||||||
|
{
|
||||||
|
void* handle=getHandle();
|
||||||
|
LOAD_SYM(gethostbyname);
|
||||||
|
LOAD_SYM(calloc);
|
||||||
|
LOAD_SYM(realloc);
|
||||||
|
LOAD_SYM(free);
|
||||||
|
LOAD_SYM(random);
|
||||||
|
LOAD_SYM(srandom);
|
||||||
|
LOAD_SYM(printf);
|
||||||
|
LOAD_SYM(socket);
|
||||||
|
LOAD_SYM(close);
|
||||||
|
LOAD_SYM(getsockopt);
|
||||||
|
LOAD_SYM(setsockopt);
|
||||||
|
LOAD_SYM(fcntl);
|
||||||
|
LOAD_SYM(connect);
|
||||||
|
LOAD_SYM(send);
|
||||||
|
LOAD_SYM(recv);
|
||||||
|
LOAD_SYM(select);
|
||||||
|
LOAD_SYM(poll);
|
||||||
|
LOAD_SYM(gettimeofday);
|
||||||
|
#ifdef _POSIX_MONOTONIC_CLOCK
|
||||||
|
LOAD_SYM(clock_gettime);
|
||||||
|
#endif
|
||||||
|
#ifdef THREADED
|
||||||
|
LOAD_SYM(pthread_create);
|
||||||
|
LOAD_SYM(pthread_detach);
|
||||||
|
LOAD_SYM(pthread_cond_broadcast);
|
||||||
|
LOAD_SYM(pthread_cond_destroy);
|
||||||
|
LOAD_SYM(pthread_cond_init);
|
||||||
|
LOAD_SYM(pthread_cond_signal);
|
||||||
|
LOAD_SYM(pthread_cond_timedwait);
|
||||||
|
LOAD_SYM(pthread_cond_wait);
|
||||||
|
LOAD_SYM(pthread_join);
|
||||||
|
LOAD_SYM(pthread_mutex_destroy);
|
||||||
|
LOAD_SYM(pthread_mutex_init);
|
||||||
|
LOAD_SYM(pthread_mutex_lock);
|
||||||
|
LOAD_SYM(pthread_mutex_trylock);
|
||||||
|
LOAD_SYM(pthread_mutex_unlock);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void* LibCSymTable::getHandle(){
|
||||||
|
static void* handle=0;
|
||||||
|
if(!handle){
|
||||||
|
#ifdef __CYGWIN__
|
||||||
|
handle=dlopen("cygwin1.dll",RTLD_LAZY);
|
||||||
|
assert("Unable to dlopen global sym table"&&handle);
|
||||||
|
#else
|
||||||
|
handle=RTLD_NEXT;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return handle;
|
||||||
|
}
|
111
zookeeper-client/zookeeper-client-c/tests/LibCSymTable.h
Normal file
111
zookeeper-client/zookeeper-client-c/tests/LibCSymTable.h
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIBCSYMTABLE_H_
|
||||||
|
#define LIBCSYMTABLE_H_
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <cassert>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <unistd.h> // needed for _POSIX_MONOTONIC_CLOCK
|
||||||
|
|
||||||
|
#ifdef THREADED
|
||||||
|
#include <pthread.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
// TODO: move all these macros to config.h (generated by autoconf)
|
||||||
|
#ifdef __CYGWIN__
|
||||||
|
#if (CYGWIN_VERSION_DLL_MAJOR < 1007)
|
||||||
|
#define RANDOM_RET_TYPE int
|
||||||
|
#else
|
||||||
|
#define RANDOM_RET_TYPE long int
|
||||||
|
#endif
|
||||||
|
#define GETTIMEOFDAY_ARG2_TYPE void*
|
||||||
|
#else
|
||||||
|
#define RANDOM_RET_TYPE long int
|
||||||
|
#define GETTIMEOFDAY_ARG2_TYPE struct timezone*
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DECLARE_SYM(ret,sym,sig) \
|
||||||
|
typedef ret (*sym##_sig)sig; \
|
||||||
|
static sym##_sig preload_##sym () { \
|
||||||
|
static sym##_sig ptr=0;\
|
||||||
|
if(!ptr){ void* h=getHandle(); ptr=(sym##_sig)dlsym(h,#sym); } \
|
||||||
|
assert("Unable to load "#sym" from libc"&&ptr); \
|
||||||
|
return ptr; \
|
||||||
|
} \
|
||||||
|
sym##_sig sym
|
||||||
|
|
||||||
|
#define LIBC_SYMBOLS LibCSymTable::instance()
|
||||||
|
|
||||||
|
//******************************************************************************
|
||||||
|
// preload original libc symbols
|
||||||
|
struct LibCSymTable
|
||||||
|
{
|
||||||
|
DECLARE_SYM(hostent*,gethostbyname,(const char*));
|
||||||
|
DECLARE_SYM(void*,calloc,(size_t, size_t));
|
||||||
|
DECLARE_SYM(void*,realloc,(void*, size_t));
|
||||||
|
DECLARE_SYM(void,free,(void*));
|
||||||
|
DECLARE_SYM(RANDOM_RET_TYPE,random,(void));
|
||||||
|
DECLARE_SYM(void,srandom,(unsigned long));
|
||||||
|
DECLARE_SYM(int,printf,(const char*, ...));
|
||||||
|
DECLARE_SYM(int,socket,(int,int,int));
|
||||||
|
DECLARE_SYM(int,close,(int));
|
||||||
|
DECLARE_SYM(int,getsockopt,(int,int,int,void*,socklen_t*));
|
||||||
|
DECLARE_SYM(int,setsockopt,(int,int,int,const void*,socklen_t));
|
||||||
|
DECLARE_SYM(int,fcntl,(int,int,...));
|
||||||
|
DECLARE_SYM(int,connect,(int,const struct sockaddr*,socklen_t));
|
||||||
|
DECLARE_SYM(ssize_t,send,(int,const void*,size_t,int));
|
||||||
|
DECLARE_SYM(ssize_t,recv,(int,const void*,size_t,int));
|
||||||
|
DECLARE_SYM(int,select,(int,fd_set*,fd_set*,fd_set*,struct timeval*));
|
||||||
|
DECLARE_SYM(int,poll,(struct pollfd*,POLL_NFDS_TYPE,int));
|
||||||
|
DECLARE_SYM(int,gettimeofday,(struct timeval*,GETTIMEOFDAY_ARG2_TYPE));
|
||||||
|
#ifdef _POSIX_MONOTONIC_CLOCK
|
||||||
|
DECLARE_SYM(int,clock_gettime,(clockid_t clk_id, struct timespec*));
|
||||||
|
#endif
|
||||||
|
#ifdef THREADED
|
||||||
|
DECLARE_SYM(int,pthread_create,(pthread_t *, const pthread_attr_t *,
|
||||||
|
void *(*)(void *), void *));
|
||||||
|
DECLARE_SYM(int,pthread_detach,(pthread_t));
|
||||||
|
DECLARE_SYM(int,pthread_cond_broadcast,(pthread_cond_t *));
|
||||||
|
DECLARE_SYM(int,pthread_cond_destroy,(pthread_cond_t *));
|
||||||
|
DECLARE_SYM(int,pthread_cond_init,(pthread_cond_t *, const pthread_condattr_t *));
|
||||||
|
DECLARE_SYM(int,pthread_cond_signal,(pthread_cond_t *));
|
||||||
|
DECLARE_SYM(int,pthread_cond_timedwait,(pthread_cond_t *,
|
||||||
|
pthread_mutex_t *, const struct timespec *));
|
||||||
|
DECLARE_SYM(int,pthread_cond_wait,(pthread_cond_t *, pthread_mutex_t *));
|
||||||
|
DECLARE_SYM(int,pthread_join,(pthread_t, void **));
|
||||||
|
DECLARE_SYM(int,pthread_mutex_destroy,(pthread_mutex_t *));
|
||||||
|
DECLARE_SYM(int,pthread_mutex_init,(pthread_mutex_t *, const pthread_mutexattr_t *));
|
||||||
|
DECLARE_SYM(int,pthread_mutex_lock,(pthread_mutex_t *));
|
||||||
|
DECLARE_SYM(int,pthread_mutex_trylock,(pthread_mutex_t *));
|
||||||
|
DECLARE_SYM(int,pthread_mutex_unlock,(pthread_mutex_t *));
|
||||||
|
#endif
|
||||||
|
LibCSymTable();
|
||||||
|
|
||||||
|
static void* getHandle();
|
||||||
|
static LibCSymTable& instance();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /*LIBCSYMTABLE_H_*/
|
36
zookeeper-client/zookeeper-client-c/tests/MocksBase.cc
Normal file
36
zookeeper-client/zookeeper-client-c/tests/MocksBase.cc
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include "MocksBase.h"
|
||||||
|
#include "LibCSymTable.h"
|
||||||
|
|
||||||
|
// *****************************************************************************
|
||||||
|
// Mock base
|
||||||
|
void* Mock::operator new(std::size_t s){
|
||||||
|
void* p=malloc(s);
|
||||||
|
if(!p)
|
||||||
|
throw std::bad_alloc();
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mock::operator delete(void* p){
|
||||||
|
LIBC_SYMBOLS.free(p);
|
||||||
|
}
|
36
zookeeper-client/zookeeper-client-c/tests/MocksBase.h
Normal file
36
zookeeper-client/zookeeper-client-c/tests/MocksBase.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MOCKSBASE_H_
|
||||||
|
#define MOCKSBASE_H_
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
// *****************************************************************************
|
||||||
|
// Mock base
|
||||||
|
|
||||||
|
class Mock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~Mock(){}
|
||||||
|
|
||||||
|
static void* operator new(std::size_t s);
|
||||||
|
static void operator delete(void* p);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /*MOCKSBASE_H_*/
|
106
zookeeper-client/zookeeper-client-c/tests/PthreadMocks.cc
Normal file
106
zookeeper-client/zookeeper-client-c/tests/PthreadMocks.cc
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PthreadMocks.h"
|
||||||
|
|
||||||
|
MockPthreadsBase* MockPthreadsBase::mock_=0;
|
||||||
|
|
||||||
|
#undef USING_DUMA
|
||||||
|
|
||||||
|
#ifndef USING_DUMA
|
||||||
|
int pthread_cond_broadcast (pthread_cond_t *c){
|
||||||
|
if(!MockPthreadsBase::mock_)
|
||||||
|
return LIBC_SYMBOLS.pthread_cond_broadcast(c);
|
||||||
|
return MockPthreadsBase::mock_->pthread_cond_broadcast(c);
|
||||||
|
}
|
||||||
|
int pthread_cond_destroy (pthread_cond_t *c){
|
||||||
|
if(!MockPthreadsBase::mock_)
|
||||||
|
return LIBC_SYMBOLS.pthread_cond_destroy(c);
|
||||||
|
return MockPthreadsBase::mock_->pthread_cond_destroy(c);
|
||||||
|
}
|
||||||
|
int pthread_cond_init (pthread_cond_t *c, const pthread_condattr_t *a){
|
||||||
|
if(!MockPthreadsBase::mock_)
|
||||||
|
return LIBC_SYMBOLS.pthread_cond_init(c,a);
|
||||||
|
return MockPthreadsBase::mock_->pthread_cond_init(c,a);
|
||||||
|
}
|
||||||
|
int pthread_cond_signal (pthread_cond_t *c){
|
||||||
|
if(!MockPthreadsBase::mock_)
|
||||||
|
return LIBC_SYMBOLS.pthread_cond_signal(c);
|
||||||
|
return MockPthreadsBase::mock_->pthread_cond_signal(c);
|
||||||
|
}
|
||||||
|
int pthread_cond_timedwait (pthread_cond_t *c,
|
||||||
|
pthread_mutex_t *m, const struct timespec *t){
|
||||||
|
if(!MockPthreadsBase::mock_)
|
||||||
|
return LIBC_SYMBOLS.pthread_cond_timedwait(c,m,t);
|
||||||
|
return MockPthreadsBase::mock_->pthread_cond_timedwait(c,m,t);
|
||||||
|
}
|
||||||
|
int pthread_cond_wait (pthread_cond_t *c, pthread_mutex_t *m){
|
||||||
|
if(!MockPthreadsBase::mock_)
|
||||||
|
return LIBC_SYMBOLS.pthread_cond_wait(c,m);
|
||||||
|
return MockPthreadsBase::mock_->pthread_cond_wait(c,m);
|
||||||
|
}
|
||||||
|
int pthread_create (pthread_t *t, const pthread_attr_t *a,
|
||||||
|
void *(*f)(void *), void *d){
|
||||||
|
if(!MockPthreadsBase::mock_)
|
||||||
|
return LIBC_SYMBOLS.pthread_create(t,a,f,d);
|
||||||
|
return MockPthreadsBase::mock_->pthread_create(t,a,f,d);
|
||||||
|
}
|
||||||
|
int pthread_detach(pthread_t t){
|
||||||
|
if(!MockPthreadsBase::mock_)
|
||||||
|
return LIBC_SYMBOLS.pthread_detach(t);
|
||||||
|
return MockPthreadsBase::mock_->pthread_detach(t);
|
||||||
|
}
|
||||||
|
int pthread_join (pthread_t t, void **r){
|
||||||
|
if(!MockPthreadsBase::mock_)
|
||||||
|
return LIBC_SYMBOLS.pthread_join(t,r);
|
||||||
|
return MockPthreadsBase::mock_->pthread_join(t,r);
|
||||||
|
}
|
||||||
|
int pthread_mutex_destroy (pthread_mutex_t *m){
|
||||||
|
if(!MockPthreadsBase::mock_)
|
||||||
|
return LIBC_SYMBOLS.pthread_mutex_destroy(m);
|
||||||
|
return MockPthreadsBase::mock_->pthread_mutex_destroy(m);
|
||||||
|
}
|
||||||
|
int pthread_mutex_init (pthread_mutex_t *m, const pthread_mutexattr_t *a){
|
||||||
|
if(!MockPthreadsBase::mock_)
|
||||||
|
return LIBC_SYMBOLS.pthread_mutex_init(m,a);
|
||||||
|
return MockPthreadsBase::mock_->pthread_mutex_init(m,a);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_WRAPPER(int,pthread_mutex_lock,(pthread_mutex_t *m)){
|
||||||
|
if(!MockPthreadsBase::mock_)
|
||||||
|
return CALL_REAL(pthread_mutex_lock,(m));
|
||||||
|
return MockPthreadsBase::mock_->pthread_mutex_lock(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_mutex_trylock (pthread_mutex_t *m){
|
||||||
|
if(!MockPthreadsBase::mock_)
|
||||||
|
return LIBC_SYMBOLS.pthread_mutex_trylock(m);
|
||||||
|
return MockPthreadsBase::mock_->pthread_mutex_trylock(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_WRAPPER(int,pthread_mutex_unlock,(pthread_mutex_t *m)){
|
||||||
|
if(!MockPthreadsBase::mock_)
|
||||||
|
return CALL_REAL(pthread_mutex_unlock,(m));
|
||||||
|
return MockPthreadsBase::mock_->pthread_mutex_unlock(m);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CheckedPthread::ThreadMap CheckedPthread::tmap_;
|
||||||
|
CheckedPthread::MutexMap CheckedPthread::mmap_;
|
||||||
|
CheckedPthread::CVMap CheckedPthread::cvmap_;
|
||||||
|
Mutex CheckedPthread::mx;
|
449
zookeeper-client/zookeeper-client-c/tests/PthreadMocks.h
Normal file
449
zookeeper-client/zookeeper-client-c/tests/PthreadMocks.h
Normal file
@ -0,0 +1,449 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PTHREADMOCKS_H_
|
||||||
|
#define PTHREADMOCKS_H_
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "src/zk_adaptor.h"
|
||||||
|
|
||||||
|
#include "Util.h"
|
||||||
|
#include "MocksBase.h"
|
||||||
|
#include "LibCSymTable.h"
|
||||||
|
#include "ThreadingUtil.h"
|
||||||
|
|
||||||
|
// an ABC for pthreads
|
||||||
|
class MockPthreadsBase: public Mock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MockPthreadsBase(){mock_=this;}
|
||||||
|
virtual ~MockPthreadsBase(){mock_=0;}
|
||||||
|
|
||||||
|
virtual int pthread_create(pthread_t * t, const pthread_attr_t *a,
|
||||||
|
void *(*f)(void *), void *d) =0;
|
||||||
|
virtual int pthread_join(pthread_t t, void ** r) =0;
|
||||||
|
virtual int pthread_detach(pthread_t t) =0;
|
||||||
|
virtual int pthread_cond_broadcast(pthread_cond_t *c) =0;
|
||||||
|
virtual int pthread_cond_destroy(pthread_cond_t *c) =0;
|
||||||
|
virtual int pthread_cond_init(pthread_cond_t *c, const pthread_condattr_t *a) =0;
|
||||||
|
virtual int pthread_cond_signal(pthread_cond_t *c) =0;
|
||||||
|
virtual int pthread_cond_timedwait(pthread_cond_t *c,
|
||||||
|
pthread_mutex_t *m, const struct timespec *t) =0;
|
||||||
|
virtual int pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m) =0;
|
||||||
|
virtual int pthread_mutex_destroy(pthread_mutex_t *m) =0;
|
||||||
|
virtual int pthread_mutex_init(pthread_mutex_t *m, const pthread_mutexattr_t *a) =0;
|
||||||
|
virtual int pthread_mutex_lock(pthread_mutex_t *m) =0;
|
||||||
|
virtual int pthread_mutex_trylock(pthread_mutex_t *m) =0;
|
||||||
|
virtual int pthread_mutex_unlock(pthread_mutex_t *m) =0;
|
||||||
|
|
||||||
|
static MockPthreadsBase* mock_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// all pthread functions simply return an error code
|
||||||
|
// and increment their invocation counter. No actual threads are spawned.
|
||||||
|
class MockPthreadsNull: public MockPthreadsBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MockPthreadsNull():
|
||||||
|
pthread_createReturns(0),pthread_createCounter(0),
|
||||||
|
pthread_joinReturns(0),pthread_joinCounter(0),pthread_joinResultReturn(0),
|
||||||
|
pthread_detachReturns(0),pthread_detachCounter(0),
|
||||||
|
pthread_cond_broadcastReturns(0),pthread_cond_broadcastCounter(0),
|
||||||
|
pthread_cond_destroyReturns(0),pthread_cond_destroyCounter(0),
|
||||||
|
pthread_cond_initReturns(0),pthread_cond_initCounter(0),
|
||||||
|
pthread_cond_signalReturns(0),pthread_cond_signalCounter(0),
|
||||||
|
pthread_cond_timedwaitReturns(0),pthread_cond_timedwaitCounter(0),
|
||||||
|
pthread_cond_waitReturns(0),pthread_cond_waitCounter(0),
|
||||||
|
pthread_mutex_destroyReturns(0),pthread_mutex_destroyCounter(0),
|
||||||
|
pthread_mutex_initReturns(0),pthread_mutex_initCounter(0),
|
||||||
|
pthread_mutex_lockReturns(0),pthread_mutex_lockCounter(0),
|
||||||
|
pthread_mutex_trylockReturns(0),pthread_mutex_trylockCounter(0),
|
||||||
|
pthread_mutex_unlockReturns(0),pthread_mutex_unlockCounter(0)
|
||||||
|
{
|
||||||
|
memset(threads,0,sizeof(threads));
|
||||||
|
}
|
||||||
|
|
||||||
|
short threads[512];
|
||||||
|
|
||||||
|
int pthread_createReturns;
|
||||||
|
int pthread_createCounter;
|
||||||
|
virtual int pthread_create(pthread_t * t, const pthread_attr_t *a,
|
||||||
|
void *(*f)(void *), void *d){
|
||||||
|
char* p=(char*)&threads[pthread_createCounter++];
|
||||||
|
p[0]='i'; // mark as created
|
||||||
|
*t=(pthread_t)p;
|
||||||
|
return pthread_createReturns;
|
||||||
|
}
|
||||||
|
int pthread_joinReturns;
|
||||||
|
int pthread_joinCounter;
|
||||||
|
void* pthread_joinResultReturn;
|
||||||
|
virtual int pthread_join(pthread_t t, void ** r){
|
||||||
|
pthread_joinCounter++;
|
||||||
|
if(r!=0)
|
||||||
|
*r=pthread_joinResultReturn;
|
||||||
|
char* p=(char*)t;
|
||||||
|
p[0]='x';p[1]+=1;
|
||||||
|
return pthread_joinReturns;
|
||||||
|
}
|
||||||
|
int pthread_detachReturns;
|
||||||
|
int pthread_detachCounter;
|
||||||
|
virtual int pthread_detach(pthread_t t){
|
||||||
|
pthread_detachCounter++;
|
||||||
|
char* p=(char*)t;
|
||||||
|
p[0]='x';p[1]+=1;
|
||||||
|
return pthread_detachReturns;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
static bool isInitialized(const T& t){
|
||||||
|
return ((char*)t)[0]=='i';
|
||||||
|
}
|
||||||
|
template<class T>
|
||||||
|
static bool isDestroyed(const T& t){
|
||||||
|
return ((char*)t)[0]=='x';
|
||||||
|
}
|
||||||
|
template<class T>
|
||||||
|
static int getDestroyCounter(const T& t){
|
||||||
|
return ((char*)t)[1];
|
||||||
|
}
|
||||||
|
template<class T>
|
||||||
|
static int getInvalidAccessCounter(const T& t){
|
||||||
|
return ((char*)t)[2];
|
||||||
|
}
|
||||||
|
int pthread_cond_broadcastReturns;
|
||||||
|
int pthread_cond_broadcastCounter;
|
||||||
|
virtual int pthread_cond_broadcast(pthread_cond_t *c){
|
||||||
|
pthread_cond_broadcastCounter++;
|
||||||
|
if(isDestroyed(c))((char*)c)[2]++;
|
||||||
|
return pthread_cond_broadcastReturns;
|
||||||
|
}
|
||||||
|
int pthread_cond_destroyReturns;
|
||||||
|
int pthread_cond_destroyCounter;
|
||||||
|
virtual int pthread_cond_destroy(pthread_cond_t *c){
|
||||||
|
pthread_cond_destroyCounter++;
|
||||||
|
char* p=(char*)c;
|
||||||
|
p[0]='x';p[1]+=1;
|
||||||
|
return pthread_cond_destroyReturns;
|
||||||
|
}
|
||||||
|
int pthread_cond_initReturns;
|
||||||
|
int pthread_cond_initCounter;
|
||||||
|
virtual int pthread_cond_init(pthread_cond_t *c, const pthread_condattr_t *a){
|
||||||
|
pthread_cond_initCounter++;
|
||||||
|
char* p=(char*)c;
|
||||||
|
p[0]='i'; // mark as created
|
||||||
|
p[1]=0; // destruction counter
|
||||||
|
p[2]=0; // access after destruction counter
|
||||||
|
return pthread_cond_initReturns;
|
||||||
|
}
|
||||||
|
int pthread_cond_signalReturns;
|
||||||
|
int pthread_cond_signalCounter;
|
||||||
|
virtual int pthread_cond_signal(pthread_cond_t *c){
|
||||||
|
pthread_cond_signalCounter++;
|
||||||
|
if(isDestroyed(c))((char*)c)[2]++;
|
||||||
|
return pthread_cond_signalReturns;
|
||||||
|
}
|
||||||
|
int pthread_cond_timedwaitReturns;
|
||||||
|
int pthread_cond_timedwaitCounter;
|
||||||
|
virtual int pthread_cond_timedwait(pthread_cond_t *c,
|
||||||
|
pthread_mutex_t *m, const struct timespec *t){
|
||||||
|
pthread_cond_timedwaitCounter++;
|
||||||
|
if(isDestroyed(c))((char*)c)[2]++;
|
||||||
|
return pthread_cond_timedwaitReturns;
|
||||||
|
}
|
||||||
|
int pthread_cond_waitReturns;
|
||||||
|
int pthread_cond_waitCounter;
|
||||||
|
virtual int pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m){
|
||||||
|
pthread_cond_waitCounter++;
|
||||||
|
if(isDestroyed(c))((char*)c)[2]++;
|
||||||
|
return pthread_cond_waitReturns;
|
||||||
|
}
|
||||||
|
int pthread_mutex_destroyReturns;
|
||||||
|
int pthread_mutex_destroyCounter;
|
||||||
|
virtual int pthread_mutex_destroy(pthread_mutex_t *m){
|
||||||
|
pthread_mutex_destroyCounter++;
|
||||||
|
char* p=(char*)m;
|
||||||
|
p[0]='x';p[1]+=1;
|
||||||
|
return pthread_mutex_destroyReturns;
|
||||||
|
}
|
||||||
|
int pthread_mutex_initReturns;
|
||||||
|
int pthread_mutex_initCounter;
|
||||||
|
virtual int pthread_mutex_init(pthread_mutex_t *m, const pthread_mutexattr_t *a){
|
||||||
|
pthread_mutex_initCounter++;
|
||||||
|
char* p=(char*)m;
|
||||||
|
p[0]='i'; // mark as created
|
||||||
|
p[1]=0; // destruction counter
|
||||||
|
p[2]=0; // access after destruction counter
|
||||||
|
return pthread_mutex_initReturns;
|
||||||
|
}
|
||||||
|
int pthread_mutex_lockReturns;
|
||||||
|
int pthread_mutex_lockCounter;
|
||||||
|
virtual int pthread_mutex_lock(pthread_mutex_t *m){
|
||||||
|
pthread_mutex_lockCounter++;
|
||||||
|
if(isDestroyed(m))((char*)m)[2]++;
|
||||||
|
return pthread_mutex_lockReturns;
|
||||||
|
}
|
||||||
|
int pthread_mutex_trylockReturns;
|
||||||
|
int pthread_mutex_trylockCounter;
|
||||||
|
virtual int pthread_mutex_trylock(pthread_mutex_t *m){
|
||||||
|
pthread_mutex_trylockCounter++;
|
||||||
|
if(isDestroyed(m))((char*)m)[2]++;
|
||||||
|
return pthread_mutex_trylockReturns;
|
||||||
|
}
|
||||||
|
int pthread_mutex_unlockReturns;
|
||||||
|
int pthread_mutex_unlockCounter;
|
||||||
|
virtual int pthread_mutex_unlock(pthread_mutex_t *m){
|
||||||
|
pthread_mutex_unlockCounter++;
|
||||||
|
if(isDestroyed(m))((char*)m)[2]++;
|
||||||
|
return pthread_mutex_unlockReturns;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// simulates the way zookeeper threads make use of api_prolog/epilog and
|
||||||
|
//
|
||||||
|
class MockPthreadZKNull: public MockPthreadsNull
|
||||||
|
{
|
||||||
|
typedef std::map<pthread_t,zhandle_t*> Map;
|
||||||
|
Map map_;
|
||||||
|
public:
|
||||||
|
virtual int pthread_create(pthread_t * t, const pthread_attr_t *a,
|
||||||
|
void *(*f)(void *), void *d){
|
||||||
|
int ret=MockPthreadsNull::pthread_create(t,a,f,d);
|
||||||
|
zhandle_t* zh=(zhandle_t*)d;
|
||||||
|
adaptor_threads* ad=(adaptor_threads*)zh->adaptor_priv;
|
||||||
|
api_prolog(zh);
|
||||||
|
ad->threadsToWait--;
|
||||||
|
putValue(map_,*t,zh);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
virtual int pthread_join(pthread_t t, void ** r){
|
||||||
|
zhandle_t* zh=0;
|
||||||
|
if(getValue(map_,t,zh))
|
||||||
|
api_epilog(zh,0);
|
||||||
|
return MockPthreadsNull::pthread_join(t,r);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ThreadInfo{
|
||||||
|
typedef enum {RUNNING,TERMINATED} ThreadState;
|
||||||
|
|
||||||
|
ThreadInfo():
|
||||||
|
destructionCounter_(0),invalidAccessCounter_(0),state_(RUNNING)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadInfo& incDestroyed() {
|
||||||
|
destructionCounter_++;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
ThreadInfo& incInvalidAccess(){
|
||||||
|
invalidAccessCounter_++;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
ThreadInfo& setTerminated(){
|
||||||
|
state_=TERMINATED;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
int destructionCounter_;
|
||||||
|
int invalidAccessCounter_;
|
||||||
|
ThreadState state_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CheckedPthread: public MockPthreadsBase
|
||||||
|
{
|
||||||
|
// first => destruction counter
|
||||||
|
// second => invalid access counter
|
||||||
|
//typedef std::pair<int,int> Entry;
|
||||||
|
typedef ThreadInfo Entry;
|
||||||
|
typedef std::map<pthread_t,Entry> ThreadMap;
|
||||||
|
static ThreadMap tmap_;
|
||||||
|
static ThreadMap& getMap(const TypeOp<pthread_t>::BareT&){return tmap_;}
|
||||||
|
typedef std::map<pthread_mutex_t*,Entry> MutexMap;
|
||||||
|
static MutexMap mmap_;
|
||||||
|
static MutexMap& getMap(const TypeOp<pthread_mutex_t>::BareT&){return mmap_;}
|
||||||
|
typedef std::map<pthread_cond_t*,Entry> CVMap;
|
||||||
|
static CVMap cvmap_;
|
||||||
|
static CVMap& getMap(const TypeOp<pthread_cond_t>::BareT&){return cvmap_;}
|
||||||
|
|
||||||
|
static Mutex mx;
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
static void markDestroyed(T& t){
|
||||||
|
typedef typename TypeOp<T>::BareT Type;
|
||||||
|
Entry e;
|
||||||
|
synchronized(mx);
|
||||||
|
if(getValue(getMap(Type()),t,e)){
|
||||||
|
putValue(getMap(Type()),t,Entry(e).incDestroyed());
|
||||||
|
}else{
|
||||||
|
putValue(getMap(Type()),t,Entry().incDestroyed());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template<class T>
|
||||||
|
static void markCreated(T& t){
|
||||||
|
typedef typename TypeOp<T>::BareT Type;
|
||||||
|
Entry e;
|
||||||
|
synchronized(mx);
|
||||||
|
if(!getValue(getMap(Type()),t,e))
|
||||||
|
putValue(getMap(Type()),t,Entry());
|
||||||
|
}
|
||||||
|
template<class T>
|
||||||
|
static void checkAccessed(T& t){
|
||||||
|
typedef typename TypeOp<T>::BareT Type;
|
||||||
|
Entry e;
|
||||||
|
synchronized(mx);
|
||||||
|
if(getValue(getMap(Type()),t,e) && e.destructionCounter_>0)
|
||||||
|
putValue(getMap(Type()),t,Entry(e).incInvalidAccess());
|
||||||
|
}
|
||||||
|
static void setTerminated(pthread_t t){
|
||||||
|
Entry e;
|
||||||
|
synchronized(mx);
|
||||||
|
if(getValue(tmap_,t,e))
|
||||||
|
putValue(tmap_,t,Entry(e).setTerminated());
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
bool verbose;
|
||||||
|
CheckedPthread():verbose(false){
|
||||||
|
tmap_.clear();
|
||||||
|
mmap_.clear();
|
||||||
|
cvmap_.clear();
|
||||||
|
mx.release();
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
static bool isInitialized(const T& t){
|
||||||
|
typedef typename TypeOp<T>::BareT Type;
|
||||||
|
Entry e;
|
||||||
|
synchronized(mx);
|
||||||
|
return getValue(getMap(Type()),t,e) && e.destructionCounter_==0;
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
static bool isDestroyed(const T& t){
|
||||||
|
typedef typename TypeOp<T>::BareT Type;
|
||||||
|
Entry e;
|
||||||
|
synchronized(mx);
|
||||||
|
return getValue(getMap(Type()),t,e) && e.destructionCounter_>0;
|
||||||
|
}
|
||||||
|
static bool isTerminated(pthread_t t){
|
||||||
|
Entry e;
|
||||||
|
synchronized(mx);
|
||||||
|
return getValue(tmap_,t,e) && e.state_==ThreadInfo::TERMINATED;
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
static int getDestroyCounter(const T& t){
|
||||||
|
typedef typename TypeOp<T>::BareT Type;
|
||||||
|
Entry e;
|
||||||
|
synchronized(mx);
|
||||||
|
return getValue(getMap(Type()),t,e)?e.destructionCounter_:-1;
|
||||||
|
}
|
||||||
|
template<class T>
|
||||||
|
static int getInvalidAccessCounter(const T& t){
|
||||||
|
typedef typename TypeOp<T>::BareT Type;
|
||||||
|
Entry e;
|
||||||
|
synchronized(mx);
|
||||||
|
return getValue(getMap(Type()),t,e)?e.invalidAccessCounter_:-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ThreadContext{
|
||||||
|
typedef void *(*ThreadFunc)(void *);
|
||||||
|
|
||||||
|
ThreadContext(ThreadFunc func,void* param):func_(func),param_(param){}
|
||||||
|
ThreadFunc func_;
|
||||||
|
void* param_;
|
||||||
|
};
|
||||||
|
static void* threadFuncWrapper(void* v){
|
||||||
|
ThreadContext* ctx=(ThreadContext*)v;
|
||||||
|
pthread_t t=pthread_self();
|
||||||
|
markCreated(t);
|
||||||
|
void* res=ctx->func_(ctx->param_);
|
||||||
|
setTerminated(pthread_self());
|
||||||
|
delete ctx;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
virtual int pthread_create(pthread_t * t, const pthread_attr_t *a,
|
||||||
|
void *(*f)(void *), void *d)
|
||||||
|
{
|
||||||
|
int ret=LIBC_SYMBOLS.pthread_create(t,a,threadFuncWrapper,
|
||||||
|
new ThreadContext(f,d));
|
||||||
|
if(verbose)
|
||||||
|
TEST_TRACE("thread created %p",*t);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
virtual int pthread_join(pthread_t t, void ** r){
|
||||||
|
if(verbose) TEST_TRACE("thread joined %p",t);
|
||||||
|
int ret=LIBC_SYMBOLS.pthread_join(t,r);
|
||||||
|
if(ret==0)
|
||||||
|
markDestroyed(t);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
virtual int pthread_detach(pthread_t t){
|
||||||
|
if(verbose) TEST_TRACE("thread detached %p",t);
|
||||||
|
int ret=LIBC_SYMBOLS.pthread_detach(t);
|
||||||
|
if(ret==0)
|
||||||
|
markDestroyed(t);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
virtual int pthread_cond_broadcast(pthread_cond_t *c){
|
||||||
|
checkAccessed(c);
|
||||||
|
return LIBC_SYMBOLS.pthread_cond_broadcast(c);
|
||||||
|
}
|
||||||
|
virtual int pthread_cond_destroy(pthread_cond_t *c){
|
||||||
|
markDestroyed(c);
|
||||||
|
return LIBC_SYMBOLS.pthread_cond_destroy(c);
|
||||||
|
}
|
||||||
|
virtual int pthread_cond_init(pthread_cond_t *c, const pthread_condattr_t *a){
|
||||||
|
markCreated(c);
|
||||||
|
return LIBC_SYMBOLS.pthread_cond_init(c,a);
|
||||||
|
}
|
||||||
|
virtual int pthread_cond_signal(pthread_cond_t *c){
|
||||||
|
checkAccessed(c);
|
||||||
|
return LIBC_SYMBOLS.pthread_cond_signal(c);
|
||||||
|
}
|
||||||
|
virtual int pthread_cond_timedwait(pthread_cond_t *c,
|
||||||
|
pthread_mutex_t *m, const struct timespec *t){
|
||||||
|
checkAccessed(c);
|
||||||
|
return LIBC_SYMBOLS.pthread_cond_timedwait(c,m,t);
|
||||||
|
}
|
||||||
|
virtual int pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m){
|
||||||
|
checkAccessed(c);
|
||||||
|
return LIBC_SYMBOLS.pthread_cond_wait(c,m);
|
||||||
|
}
|
||||||
|
virtual int pthread_mutex_destroy(pthread_mutex_t *m){
|
||||||
|
markDestroyed(m);
|
||||||
|
return LIBC_SYMBOLS.pthread_mutex_destroy(m);
|
||||||
|
}
|
||||||
|
virtual int pthread_mutex_init(pthread_mutex_t *m, const pthread_mutexattr_t *a){
|
||||||
|
markCreated(m);
|
||||||
|
return LIBC_SYMBOLS.pthread_mutex_init(m,a);
|
||||||
|
}
|
||||||
|
virtual int pthread_mutex_lock(pthread_mutex_t *m){
|
||||||
|
checkAccessed(m);
|
||||||
|
return LIBC_SYMBOLS.pthread_mutex_lock(m);
|
||||||
|
}
|
||||||
|
virtual int pthread_mutex_trylock(pthread_mutex_t *m){
|
||||||
|
checkAccessed(m);
|
||||||
|
return LIBC_SYMBOLS.pthread_mutex_trylock(m);
|
||||||
|
}
|
||||||
|
virtual int pthread_mutex_unlock(pthread_mutex_t *m){
|
||||||
|
checkAccessed(m);
|
||||||
|
return LIBC_SYMBOLS.pthread_mutex_unlock(m);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /*PTHREADMOCKS_H_*/
|
||||||
|
|
1508
zookeeper-client/zookeeper-client-c/tests/TestClient.cc
Normal file
1508
zookeeper-client/zookeeper-client-c/tests/TestClient.cc
Normal file
File diff suppressed because it is too large
Load Diff
147
zookeeper-client/zookeeper-client-c/tests/TestClientRetry.cc
Normal file
147
zookeeper-client/zookeeper-client-c/tests/TestClientRetry.cc
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cppunit/extensions/HelperMacros.h>
|
||||||
|
#include "CppAssertHelper.h"
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "Vector.h"
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
#include <zookeeper.h>
|
||||||
|
|
||||||
|
#include "Util.h"
|
||||||
|
#include "WatchUtil.h"
|
||||||
|
|
||||||
|
class Zookeeper_clientretry : public CPPUNIT_NS::TestFixture
|
||||||
|
{
|
||||||
|
CPPUNIT_TEST_SUITE(Zookeeper_clientretry);
|
||||||
|
#ifdef THREADED
|
||||||
|
CPPUNIT_TEST(testRetry);
|
||||||
|
#endif
|
||||||
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
|
static void watcher(zhandle_t *, int type, int state, const char *path,void*v){
|
||||||
|
watchctx_t *ctx = (watchctx_t*)v;
|
||||||
|
|
||||||
|
if (state == ZOO_CONNECTED_STATE) {
|
||||||
|
ctx->connected = true;
|
||||||
|
} else {
|
||||||
|
ctx->connected = false;
|
||||||
|
}
|
||||||
|
if (type != ZOO_SESSION_EVENT) {
|
||||||
|
evt_t evt;
|
||||||
|
evt.path = path;
|
||||||
|
evt.type = type;
|
||||||
|
ctx->putEvent(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char hostPorts[];
|
||||||
|
|
||||||
|
const char *getHostPorts() {
|
||||||
|
return hostPorts;
|
||||||
|
}
|
||||||
|
|
||||||
|
zhandle_t *createClient(watchctx_t *ctx) {
|
||||||
|
zhandle_t *zk = zookeeper_init(hostPorts, watcher, 10000, 0,
|
||||||
|
ctx, 0);
|
||||||
|
ctx->zh = zk;
|
||||||
|
sleep(1);
|
||||||
|
return zk;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *logfile;
|
||||||
|
public:
|
||||||
|
|
||||||
|
Zookeeper_clientretry() {
|
||||||
|
logfile = openlogfile("Zookeeper_clientretry");
|
||||||
|
}
|
||||||
|
|
||||||
|
~Zookeeper_clientretry() {
|
||||||
|
if (logfile) {
|
||||||
|
fflush(logfile);
|
||||||
|
fclose(logfile);
|
||||||
|
logfile = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setUp()
|
||||||
|
{
|
||||||
|
zoo_set_log_stream(logfile);
|
||||||
|
|
||||||
|
char cmd[1024];
|
||||||
|
sprintf(cmd, "%s stop %s", ZKSERVER_CMD, getHostPorts());
|
||||||
|
CPPUNIT_ASSERT(system(cmd) == 0);
|
||||||
|
|
||||||
|
/* we are testing that if max cnxns is exceeded the server does the right thing */
|
||||||
|
sprintf(cmd, "ZKMAXCNXNS=1 %s startClean %s", ZKSERVER_CMD, getHostPorts());
|
||||||
|
CPPUNIT_ASSERT(system(cmd) == 0);
|
||||||
|
|
||||||
|
struct sigaction act;
|
||||||
|
act.sa_handler = SIG_IGN;
|
||||||
|
sigemptyset(&act.sa_mask);
|
||||||
|
act.sa_flags = 0;
|
||||||
|
CPPUNIT_ASSERT(sigaction(SIGPIPE, &act, NULL) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tearDown()
|
||||||
|
{
|
||||||
|
char cmd[1024];
|
||||||
|
sprintf(cmd, "%s stop %s", ZKSERVER_CMD, getHostPorts());
|
||||||
|
CPPUNIT_ASSERT(system(cmd) == 0);
|
||||||
|
|
||||||
|
/* restart the server in "normal" mode */
|
||||||
|
sprintf(cmd, "%s startClean %s", ZKSERVER_CMD, getHostPorts());
|
||||||
|
CPPUNIT_ASSERT(system(cmd) == 0);
|
||||||
|
|
||||||
|
struct sigaction act;
|
||||||
|
act.sa_handler = SIG_IGN;
|
||||||
|
sigemptyset(&act.sa_mask);
|
||||||
|
act.sa_flags = 0;
|
||||||
|
CPPUNIT_ASSERT(sigaction(SIGPIPE, &act, NULL) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool waitForEvent(zhandle_t *zh, watchctx_t *ctx, int seconds) {
|
||||||
|
time_t expires = time(0) + seconds;
|
||||||
|
while(ctx->countEvents() == 0 && time(0) < expires) {
|
||||||
|
yield(zh, 1);
|
||||||
|
}
|
||||||
|
return ctx->countEvents() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static zhandle_t *async_zk;
|
||||||
|
|
||||||
|
void testRetry()
|
||||||
|
{
|
||||||
|
watchctx_t ctx1, ctx2;
|
||||||
|
zhandle_t *zk1 = createClient(&ctx1);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(true, ctx1.waitForConnected(zk1));
|
||||||
|
zhandle_t *zk2 = createClient(&ctx2);
|
||||||
|
zookeeper_close(zk1);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(true, ctx2.waitForConnected(zk2));
|
||||||
|
ctx1.zh = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
zhandle_t *Zookeeper_clientretry::async_zk;
|
||||||
|
const char Zookeeper_clientretry::hostPorts[] = "127.0.0.1:22181";
|
||||||
|
CPPUNIT_TEST_SUITE_REGISTRATION(Zookeeper_clientretry);
|
173
zookeeper-client/zookeeper-client-c/tests/TestDriver.cc
Normal file
173
zookeeper-client/zookeeper-client-c/tests/TestDriver.cc
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <cppunit/TestRunner.h>
|
||||||
|
#include <cppunit/CompilerOutputter.h>
|
||||||
|
#include <cppunit/TestResult.h>
|
||||||
|
#include <cppunit/TestResultCollector.h>
|
||||||
|
#include <cppunit/TextTestProgressListener.h>
|
||||||
|
#include <cppunit/BriefTestProgressListener.h>
|
||||||
|
#include <cppunit/extensions/TestFactoryRegistry.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <cppunit/Exception.h>
|
||||||
|
#include <cppunit/TestFailure.h>
|
||||||
|
#include <cppunit/XmlOutputter.h>
|
||||||
|
#include <cppunit/TestAssert.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "Util.h"
|
||||||
|
#include "zookeeper_log.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
CPPUNIT_NS_BEGIN
|
||||||
|
|
||||||
|
class EclipseOutputter: public CompilerOutputter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EclipseOutputter(TestResultCollector *result,ostream &stream):
|
||||||
|
CompilerOutputter(result,stream,"%p:%l: "),stream_(stream)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
virtual void printFailedTestName( TestFailure *failure ){}
|
||||||
|
virtual void printFailureMessage( TestFailure *failure )
|
||||||
|
{
|
||||||
|
stream_<<": ";
|
||||||
|
Message msg = failure->thrownException()->message();
|
||||||
|
stream_<< msg.shortDescription();
|
||||||
|
|
||||||
|
string text;
|
||||||
|
for(int i=0; i<msg.detailCount();i++){
|
||||||
|
text+=msg.detailAt(i);
|
||||||
|
if(i+1!=msg.detailCount())
|
||||||
|
text+=", ";
|
||||||
|
}
|
||||||
|
if(text.length()!=0)
|
||||||
|
stream_ <<" ["<<text<<"]";
|
||||||
|
stream_<<"\n";
|
||||||
|
}
|
||||||
|
ostream& stream_;
|
||||||
|
};
|
||||||
|
|
||||||
|
CPPUNIT_NS_END
|
||||||
|
|
||||||
|
class TimingListener : public CPPUNIT_NS::BriefTestProgressListener {
|
||||||
|
public:
|
||||||
|
void startTest( CPPUNIT_NS::Test *test )
|
||||||
|
{
|
||||||
|
gettimeofday(&_start_time, NULL);
|
||||||
|
|
||||||
|
CPPUNIT_NS::BriefTestProgressListener::startTest(test);
|
||||||
|
}
|
||||||
|
|
||||||
|
void endTest( CPPUNIT_NS::Test *test )
|
||||||
|
{
|
||||||
|
struct timeval end;
|
||||||
|
gettimeofday(&end, NULL);
|
||||||
|
|
||||||
|
long seconds = end.tv_sec - _start_time.tv_sec;
|
||||||
|
long useconds = end.tv_usec - _start_time.tv_usec;
|
||||||
|
|
||||||
|
long mtime = seconds * 1000 + useconds/1000.0;
|
||||||
|
CPPUNIT_NS::stdCOut() << " : elapsed " << mtime;
|
||||||
|
CPPUNIT_NS::BriefTestProgressListener::endTest(test);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct timeval _start_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ZKServer {
|
||||||
|
public:
|
||||||
|
ZKServer() {
|
||||||
|
char cmd[1024];
|
||||||
|
sprintf(cmd, "%s startClean %s", ZKSERVER_CMD, "127.0.0.1:22181");
|
||||||
|
CPPUNIT_ASSERT(system(cmd) == 0);
|
||||||
|
|
||||||
|
struct sigaction act;
|
||||||
|
act.sa_handler = SIG_IGN;
|
||||||
|
sigemptyset(&act.sa_mask);
|
||||||
|
act.sa_flags = 0;
|
||||||
|
CPPUNIT_ASSERT(sigaction(SIGPIPE, &act, NULL) == 0);
|
||||||
|
}
|
||||||
|
virtual ~ZKServer(){
|
||||||
|
char cmd[1024];
|
||||||
|
sprintf(cmd, "%s stop %s", ZKSERVER_CMD, "127.0.0.1:22181");
|
||||||
|
CPPUNIT_ASSERT(system(cmd) == 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main( int argc, char* argv[] ) {
|
||||||
|
// if command line contains "-ide" then this is the post build check
|
||||||
|
// => the output must be in the compiler error format.
|
||||||
|
//bool selfTest = (argc > 1) && (std::string("-ide") == argv[1]);
|
||||||
|
globalTestConfig.addConfigFromCmdLine(argc,argv);
|
||||||
|
|
||||||
|
ZKServer zkserver;
|
||||||
|
|
||||||
|
// Create the event manager and test controller
|
||||||
|
CPPUNIT_NS::TestResult controller;
|
||||||
|
// Add a listener that colllects test result
|
||||||
|
CPPUNIT_NS::TestResultCollector result;
|
||||||
|
controller.addListener( &result );
|
||||||
|
|
||||||
|
// A listener that print dots as tests run.
|
||||||
|
// CPPUNIT_NS::TextTestProgressListener progress;
|
||||||
|
// CPPUNIT_NS::BriefTestProgressListener progress;
|
||||||
|
|
||||||
|
// brief + elapsed time
|
||||||
|
TimingListener progress;
|
||||||
|
controller.addListener( &progress );
|
||||||
|
|
||||||
|
CPPUNIT_NS::TestRunner runner;
|
||||||
|
runner.addTest( CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest() );
|
||||||
|
|
||||||
|
try {
|
||||||
|
CPPUNIT_NS::stdCOut() << endl << "Running " << endl;
|
||||||
|
|
||||||
|
zoo_set_debug_level(ZOO_LOG_LEVEL_INFO);
|
||||||
|
//zoo_set_debug_level(ZOO_LOG_LEVEL_DEBUG);
|
||||||
|
|
||||||
|
runner.run( controller, globalTestConfig.getTestName());
|
||||||
|
|
||||||
|
// Print test in a compiler compatible format.
|
||||||
|
CPPUNIT_NS::EclipseOutputter outputter( &result,cout);
|
||||||
|
outputter.write();
|
||||||
|
|
||||||
|
// Uncomment this for XML output
|
||||||
|
#ifdef ENABLE_XML_OUTPUT
|
||||||
|
std::ofstream file( "tests.xml" );
|
||||||
|
CPPUNIT_NS::XmlOutputter xml( &result, file );
|
||||||
|
xml.setStyleSheet( "report.xsl" );
|
||||||
|
xml.write();
|
||||||
|
file.close();
|
||||||
|
#endif
|
||||||
|
} catch ( std::invalid_argument &e ) {
|
||||||
|
// Test path not resolved
|
||||||
|
cout<<"\nERROR: "<<e.what()<<endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.wasSuccessful() ? 0 : 1;
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cppunit/extensions/HelperMacros.h>
|
||||||
|
#include "CppAssertHelper.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <zookeeper.h>
|
||||||
|
|
||||||
|
class Zookeeper_logClientEnv : public CPPUNIT_NS::TestFixture {
|
||||||
|
CPPUNIT_TEST_SUITE(Zookeeper_logClientEnv);
|
||||||
|
CPPUNIT_TEST(testLogClientEnv);
|
||||||
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
|
static void log_no_clientenv(const char *message) {
|
||||||
|
CPPUNIT_ASSERT(::strstr(message, "Client environment") == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_clientenv(const char *message) {
|
||||||
|
static int first;
|
||||||
|
|
||||||
|
if (!first) {
|
||||||
|
CPPUNIT_ASSERT(::strstr(message, "Client environment") != NULL);
|
||||||
|
first = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void testLogClientEnv() {
|
||||||
|
zhandle_t* zh;
|
||||||
|
|
||||||
|
zh = zookeeper_init2("localhost:22181", NULL, 0, NULL, NULL, 0, log_clientenv);
|
||||||
|
CPPUNIT_ASSERT(zh != 0);
|
||||||
|
zookeeper_close(zh);
|
||||||
|
|
||||||
|
zh = zookeeper_init2("localhost:22181", NULL, 0, NULL, NULL, ZOO_NO_LOG_CLIENTENV, log_no_clientenv);
|
||||||
|
CPPUNIT_ASSERT(zh != 0);
|
||||||
|
zookeeper_close(zh);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
CPPUNIT_TEST_SUITE_REGISTRATION(Zookeeper_logClientEnv);
|
||||||
|
|
770
zookeeper-client/zookeeper-client-c/tests/TestMulti.cc
Normal file
770
zookeeper-client/zookeeper-client-c/tests/TestMulti.cc
Normal file
@ -0,0 +1,770 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cppunit/extensions/HelperMacros.h>
|
||||||
|
#include "CppAssertHelper.h"
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
|
||||||
|
#include "CollectionUtil.h"
|
||||||
|
#include "ThreadingUtil.h"
|
||||||
|
|
||||||
|
using namespace Util;
|
||||||
|
|
||||||
|
#include "Vector.h"
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#include <zookeeper.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <recordio.h>
|
||||||
|
#include "Util.h"
|
||||||
|
|
||||||
|
#ifdef THREADED
|
||||||
|
static void yield(zhandle_t *zh, int i)
|
||||||
|
{
|
||||||
|
sleep(i);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static void yield(zhandle_t *zh, int seconds)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
int interest;
|
||||||
|
int events;
|
||||||
|
struct timeval tv;
|
||||||
|
time_t expires = time(0) + seconds;
|
||||||
|
time_t timeLeft = seconds;
|
||||||
|
fd_set rfds, wfds, efds;
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_ZERO(&wfds);
|
||||||
|
FD_ZERO(&efds);
|
||||||
|
|
||||||
|
while(timeLeft >= 0) {
|
||||||
|
zookeeper_interest(zh, &fd, &interest, &tv);
|
||||||
|
if (fd != -1) {
|
||||||
|
if (interest&ZOOKEEPER_READ) {
|
||||||
|
FD_SET(fd, &rfds);
|
||||||
|
} else {
|
||||||
|
FD_CLR(fd, &rfds);
|
||||||
|
}
|
||||||
|
if (interest&ZOOKEEPER_WRITE) {
|
||||||
|
FD_SET(fd, &wfds);
|
||||||
|
} else {
|
||||||
|
FD_CLR(fd, &wfds);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fd = 0;
|
||||||
|
}
|
||||||
|
FD_SET(0, &rfds);
|
||||||
|
if (tv.tv_sec > timeLeft) {
|
||||||
|
tv.tv_sec = timeLeft;
|
||||||
|
}
|
||||||
|
select(fd+1, &rfds, &wfds, &efds, &tv);
|
||||||
|
timeLeft = expires - time(0);
|
||||||
|
events = 0;
|
||||||
|
if (FD_ISSET(fd, &rfds)) {
|
||||||
|
events |= ZOOKEEPER_READ;
|
||||||
|
}
|
||||||
|
if (FD_ISSET(fd, &wfds)) {
|
||||||
|
events |= ZOOKEEPER_WRITE;
|
||||||
|
}
|
||||||
|
zookeeper_process(zh, events);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct evt {
|
||||||
|
string path;
|
||||||
|
int type;
|
||||||
|
} evt_t;
|
||||||
|
|
||||||
|
typedef struct watchCtx {
|
||||||
|
private:
|
||||||
|
list<evt_t> events;
|
||||||
|
watchCtx(const watchCtx&);
|
||||||
|
watchCtx& operator=(const watchCtx&);
|
||||||
|
public:
|
||||||
|
bool connected;
|
||||||
|
zhandle_t *zh;
|
||||||
|
Mutex mutex;
|
||||||
|
|
||||||
|
watchCtx() {
|
||||||
|
connected = false;
|
||||||
|
zh = 0;
|
||||||
|
}
|
||||||
|
~watchCtx() {
|
||||||
|
if (zh) {
|
||||||
|
zookeeper_close(zh);
|
||||||
|
zh = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
evt_t getEvent() {
|
||||||
|
evt_t evt;
|
||||||
|
mutex.acquire();
|
||||||
|
CPPUNIT_ASSERT( events.size() > 0);
|
||||||
|
evt = events.front();
|
||||||
|
events.pop_front();
|
||||||
|
mutex.release();
|
||||||
|
return evt;
|
||||||
|
}
|
||||||
|
|
||||||
|
int countEvents() {
|
||||||
|
int count;
|
||||||
|
mutex.acquire();
|
||||||
|
count = events.size();
|
||||||
|
mutex.release();
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void putEvent(evt_t evt) {
|
||||||
|
mutex.acquire();
|
||||||
|
events.push_back(evt);
|
||||||
|
mutex.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool waitForConnected(zhandle_t *zh) {
|
||||||
|
time_t expires = time(0) + 10;
|
||||||
|
while(!connected && time(0) < expires) {
|
||||||
|
yield(zh, 1);
|
||||||
|
}
|
||||||
|
return connected;
|
||||||
|
}
|
||||||
|
bool waitForDisconnected(zhandle_t *zh) {
|
||||||
|
time_t expires = time(0) + 15;
|
||||||
|
while(connected && time(0) < expires) {
|
||||||
|
yield(zh, 1);
|
||||||
|
}
|
||||||
|
return !connected;
|
||||||
|
}
|
||||||
|
} watchctx_t;
|
||||||
|
|
||||||
|
#ifdef THREADED
|
||||||
|
class Zookeeper_multi : public CPPUNIT_NS::TestFixture
|
||||||
|
{
|
||||||
|
CPPUNIT_TEST_SUITE(Zookeeper_multi);
|
||||||
|
//FIXME: None of these tests pass in single-threaded mode. It seems to be a
|
||||||
|
//flaw in the test suite setup.
|
||||||
|
CPPUNIT_TEST(testCreate);
|
||||||
|
CPPUNIT_TEST(testCreateDelete);
|
||||||
|
CPPUNIT_TEST(testInvalidVersion);
|
||||||
|
CPPUNIT_TEST(testNestedCreate);
|
||||||
|
CPPUNIT_TEST(testSetData);
|
||||||
|
CPPUNIT_TEST(testUpdateConflict);
|
||||||
|
CPPUNIT_TEST(testDeleteUpdateConflict);
|
||||||
|
CPPUNIT_TEST(testAsyncMulti);
|
||||||
|
CPPUNIT_TEST(testMultiFail);
|
||||||
|
CPPUNIT_TEST(testCheck);
|
||||||
|
CPPUNIT_TEST(testWatch);
|
||||||
|
CPPUNIT_TEST(testSequentialNodeCreateInAsyncMulti);
|
||||||
|
CPPUNIT_TEST(testBigAsyncMulti);
|
||||||
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
|
static void watcher(zhandle_t *, int type, int state, const char *path,void*v){
|
||||||
|
watchctx_t *ctx = (watchctx_t*)v;
|
||||||
|
|
||||||
|
if (state == ZOO_CONNECTED_STATE) {
|
||||||
|
ctx->connected = true;
|
||||||
|
} else {
|
||||||
|
ctx->connected = false;
|
||||||
|
}
|
||||||
|
if (type != ZOO_SESSION_EVENT) {
|
||||||
|
evt_t evt;
|
||||||
|
evt.path = path;
|
||||||
|
evt.type = type;
|
||||||
|
ctx->putEvent(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char hostPorts[];
|
||||||
|
|
||||||
|
const char *getHostPorts() {
|
||||||
|
return hostPorts;
|
||||||
|
}
|
||||||
|
|
||||||
|
zhandle_t *createClient(watchctx_t *ctx) {
|
||||||
|
return createClient(hostPorts, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
zhandle_t *createClient(const char *hp, watchctx_t *ctx) {
|
||||||
|
zhandle_t *zk = zookeeper_init(hp, watcher, 10000, 0, ctx, 0);
|
||||||
|
ctx->zh = zk;
|
||||||
|
CPPUNIT_ASSERT_EQUAL(true, ctx->waitForConnected(zk));
|
||||||
|
return zk;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *logfile;
|
||||||
|
public:
|
||||||
|
|
||||||
|
Zookeeper_multi() {
|
||||||
|
logfile = openlogfile("Zookeeper_multi");
|
||||||
|
}
|
||||||
|
|
||||||
|
~Zookeeper_multi() {
|
||||||
|
if (logfile) {
|
||||||
|
fflush(logfile);
|
||||||
|
fclose(logfile);
|
||||||
|
logfile = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setUp()
|
||||||
|
{
|
||||||
|
zoo_set_log_stream(logfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tearDown()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static volatile int count;
|
||||||
|
|
||||||
|
static void multi_completion_fn(int rc, const void *data) {
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void multi_completion_fn_no_assert(int rc, const void *data) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void multi_completion_fn_rc(int rc, const void *data) {
|
||||||
|
count++;
|
||||||
|
*((int*) data) = rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void create_completion_fn_rc(int rc, const char* value, const void *data) {
|
||||||
|
count++;
|
||||||
|
*((int*) data) = rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void waitForMultiCompletion(int seconds) {
|
||||||
|
time_t expires = time(0) + seconds;
|
||||||
|
while(count == 0 && time(0) < expires) {
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void resetCounter() {
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test basic multi-op create functionality
|
||||||
|
*/
|
||||||
|
void testCreate() {
|
||||||
|
int rc;
|
||||||
|
watchctx_t ctx;
|
||||||
|
zhandle_t *zk = createClient(&ctx);
|
||||||
|
|
||||||
|
int sz = 512;
|
||||||
|
char p1[sz];
|
||||||
|
char p2[sz];
|
||||||
|
char p3[sz];
|
||||||
|
p1[0] = p2[0] = p3[0] = '\0';
|
||||||
|
|
||||||
|
int nops = 3 ;
|
||||||
|
zoo_op_t ops[nops];
|
||||||
|
zoo_op_result_t results[nops];
|
||||||
|
|
||||||
|
zoo_create_op_init(&ops[0], "/multi1", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
|
||||||
|
zoo_create_op_init(&ops[1], "/multi1/a", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p2, sz);
|
||||||
|
zoo_create_op_init(&ops[2], "/multi1/b", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p3, sz);
|
||||||
|
|
||||||
|
rc = zoo_multi(zk, nops, ops, results);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(strcmp(p1, "/multi1") == 0);
|
||||||
|
CPPUNIT_ASSERT(strcmp(p2, "/multi1/a") == 0);
|
||||||
|
CPPUNIT_ASSERT(strcmp(p3, "/multi1/b") == 0);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, results[0].err);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, results[1].err);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, results[2].err);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test create followed by delete
|
||||||
|
*/
|
||||||
|
void testCreateDelete() {
|
||||||
|
int rc;
|
||||||
|
watchctx_t ctx;
|
||||||
|
zhandle_t *zk = createClient(&ctx);
|
||||||
|
int sz = 512;
|
||||||
|
char p1[sz];
|
||||||
|
p1[0] = '\0';
|
||||||
|
int nops = 2 ;
|
||||||
|
zoo_op_t ops[nops];
|
||||||
|
zoo_op_result_t results[nops];
|
||||||
|
|
||||||
|
zoo_create_op_init(&ops[0], "/multi2", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
|
||||||
|
zoo_delete_op_init(&ops[1], "/multi2", 0);
|
||||||
|
|
||||||
|
rc = zoo_multi(zk, nops, ops, results);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
|
||||||
|
|
||||||
|
// '/multi2' should have been deleted
|
||||||
|
rc = zoo_exists(zk, "/multi2", 0, NULL);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test invalid versions
|
||||||
|
*/
|
||||||
|
void testInvalidVersion() {
|
||||||
|
int rc;
|
||||||
|
watchctx_t ctx;
|
||||||
|
zhandle_t *zk = createClient(&ctx);
|
||||||
|
int nops = 4;
|
||||||
|
zoo_op_t ops[nops];
|
||||||
|
zoo_op_result_t results[nops];
|
||||||
|
|
||||||
|
zoo_create_op_init(&ops[0], "/multi3", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, NULL, 0);
|
||||||
|
zoo_delete_op_init(&ops[1], "/multi3", 1);
|
||||||
|
zoo_create_op_init(&ops[2], "/multi3", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, NULL, 0);
|
||||||
|
zoo_create_op_init(&ops[3], "/multi3/a", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, NULL, 0);
|
||||||
|
|
||||||
|
rc = zoo_multi(zk, nops, ops, results);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZBADVERSION, rc);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, results[0].err);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZBADVERSION, results[1].err);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZRUNTIMEINCONSISTENCY, results[2].err);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZRUNTIMEINCONSISTENCY, results[3].err);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test nested creates that rely on state in earlier op in multi
|
||||||
|
*/
|
||||||
|
void testNestedCreate() {
|
||||||
|
int rc;
|
||||||
|
watchctx_t ctx;
|
||||||
|
zhandle_t *zk = createClient(&ctx);
|
||||||
|
int sz = 512;
|
||||||
|
char p1[sz];
|
||||||
|
p1[0] = '\0';
|
||||||
|
int nops = 6;
|
||||||
|
zoo_op_t ops[nops];
|
||||||
|
zoo_op_result_t results[nops];
|
||||||
|
|
||||||
|
/* Create */
|
||||||
|
zoo_create_op_init(&ops[0], "/multi4", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
|
||||||
|
zoo_create_op_init(&ops[1], "/multi4/a", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
|
||||||
|
zoo_create_op_init(&ops[2], "/multi4/a/1", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
|
||||||
|
|
||||||
|
/* Delete */
|
||||||
|
zoo_delete_op_init(&ops[3], "/multi4/a/1", 0);
|
||||||
|
zoo_delete_op_init(&ops[4], "/multi4/a", 0);
|
||||||
|
zoo_delete_op_init(&ops[5], "/multi4", 0);
|
||||||
|
|
||||||
|
rc = zoo_multi(zk, nops, ops, results);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
|
||||||
|
|
||||||
|
// Verify tree deleted
|
||||||
|
rc = zoo_exists(zk, "/multi4/a/1", 0, NULL);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
|
||||||
|
|
||||||
|
rc = zoo_exists(zk, "/multi4/a", 0, NULL);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
|
||||||
|
|
||||||
|
rc = zoo_exists(zk, "/multi4", 0, NULL);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test setdata functionality
|
||||||
|
*/
|
||||||
|
void testSetData() {
|
||||||
|
int rc;
|
||||||
|
watchctx_t ctx;
|
||||||
|
zhandle_t *zk = createClient(&ctx);
|
||||||
|
int sz = 512;
|
||||||
|
struct Stat s1;
|
||||||
|
|
||||||
|
char buf[sz];
|
||||||
|
int blen = sz ;
|
||||||
|
|
||||||
|
char p1[sz], p2[sz];
|
||||||
|
|
||||||
|
int nops = 2;
|
||||||
|
zoo_op_t ops[nops];
|
||||||
|
zoo_op_result_t results[nops];
|
||||||
|
|
||||||
|
zoo_create_op_init(&ops[0], "/multi5", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
|
||||||
|
zoo_create_op_init(&ops[1], "/multi5/a", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p2, sz);
|
||||||
|
|
||||||
|
rc = zoo_multi(zk, nops, ops, results);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
|
||||||
|
|
||||||
|
yield(zk, 5);
|
||||||
|
|
||||||
|
zoo_op_t setdata_ops[nops];
|
||||||
|
zoo_op_result_t setdata_results[nops];
|
||||||
|
|
||||||
|
zoo_set_op_init(&setdata_ops[0], "/multi5", "1", 1, 0, &s1);
|
||||||
|
zoo_set_op_init(&setdata_ops[1], "/multi5/a", "2", 1, 0, &s1);
|
||||||
|
|
||||||
|
rc = zoo_multi(zk, nops, setdata_ops, setdata_results);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, results[0].err);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, results[1].err);
|
||||||
|
|
||||||
|
memset(buf, '\0', blen);
|
||||||
|
rc = zoo_get(zk, "/multi5", 0, buf, &blen, &s1);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, blen);
|
||||||
|
CPPUNIT_ASSERT(strcmp("1", buf) == 0);
|
||||||
|
|
||||||
|
memset(buf, '\0', blen);
|
||||||
|
rc = zoo_get(zk, "/multi5/a", 0, buf, &blen, &s1);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, blen);
|
||||||
|
CPPUNIT_ASSERT(strcmp("2", buf) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test update conflicts
|
||||||
|
*/
|
||||||
|
void testUpdateConflict() {
|
||||||
|
int rc;
|
||||||
|
watchctx_t ctx;
|
||||||
|
zhandle_t *zk = createClient(&ctx);
|
||||||
|
int sz = 512;
|
||||||
|
char buf[sz];
|
||||||
|
int blen = sz;
|
||||||
|
char p1[sz];
|
||||||
|
p1[0] = '\0';
|
||||||
|
struct Stat s1;
|
||||||
|
int nops = 3;
|
||||||
|
zoo_op_t ops[nops];
|
||||||
|
zoo_op_result_t results[nops];
|
||||||
|
|
||||||
|
zoo_create_op_init(&ops[0], "/multi6", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
|
||||||
|
zoo_set_op_init(&ops[1], "/multi6", "X", 1, 0, &s1);
|
||||||
|
zoo_set_op_init(&ops[2], "/multi6", "Y", 1, 0, &s1);
|
||||||
|
|
||||||
|
rc = zoo_multi(zk, nops, ops, results);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZBADVERSION, rc);
|
||||||
|
|
||||||
|
//Updating version solves conflict -- order matters
|
||||||
|
ops[2].set_op.version = 1;
|
||||||
|
rc = zoo_multi(zk, nops, ops, results);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
|
||||||
|
|
||||||
|
memset(buf, 0, sz);
|
||||||
|
rc = zoo_get(zk, "/multi6", 0, buf, &blen, &s1);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(blen, 1);
|
||||||
|
CPPUNIT_ASSERT(strncmp(buf, "Y", 1) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test delete-update conflicts
|
||||||
|
*/
|
||||||
|
void testDeleteUpdateConflict() {
|
||||||
|
int rc;
|
||||||
|
watchctx_t ctx;
|
||||||
|
zhandle_t *zk = createClient(&ctx);
|
||||||
|
int sz = 512;
|
||||||
|
char buf[sz];
|
||||||
|
int blen;
|
||||||
|
char p1[sz];
|
||||||
|
p1[0] = '\0';
|
||||||
|
struct Stat stat;
|
||||||
|
int nops = 3;
|
||||||
|
zoo_op_t ops[nops];
|
||||||
|
zoo_op_result_t results[nops];
|
||||||
|
|
||||||
|
zoo_create_op_init(&ops[0], "/multi7", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
|
||||||
|
zoo_delete_op_init(&ops[1], "/multi7", 0);
|
||||||
|
zoo_set_op_init(&ops[2], "/multi7", "Y", 1, 0, &stat);
|
||||||
|
|
||||||
|
rc = zoo_multi(zk, nops, ops, results);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
|
||||||
|
|
||||||
|
// '/multi' should never have been created as entire op should fail
|
||||||
|
rc = zoo_exists(zk, "/multi7", 0, NULL);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testAsyncMulti() {
|
||||||
|
int rc;
|
||||||
|
watchctx_t ctx;
|
||||||
|
zhandle_t *zk = createClient(&ctx);
|
||||||
|
|
||||||
|
int sz = 512;
|
||||||
|
char p1[sz], p2[sz], p3[sz];
|
||||||
|
p1[0] = '\0';
|
||||||
|
p2[0] = '\0';
|
||||||
|
p3[0] = '\0';
|
||||||
|
|
||||||
|
int nops = 3;
|
||||||
|
zoo_op_t ops[nops];
|
||||||
|
zoo_op_result_t results[nops];
|
||||||
|
|
||||||
|
zoo_create_op_init(&ops[0], "/multi8", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
|
||||||
|
zoo_create_op_init(&ops[1], "/multi8/a", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p2, sz);
|
||||||
|
zoo_create_op_init(&ops[2], "/multi8/b", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p3, sz);
|
||||||
|
|
||||||
|
rc = zoo_amulti(zk, nops, ops, results, multi_completion_fn, 0);
|
||||||
|
waitForMultiCompletion(10);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(strcmp(p1, "/multi8") == 0);
|
||||||
|
CPPUNIT_ASSERT(strcmp(p2, "/multi8/a") == 0);
|
||||||
|
CPPUNIT_ASSERT(strcmp(p3, "/multi8/b") == 0);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, results[0].err);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, results[1].err);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, results[2].err);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testMultiFail() {
|
||||||
|
int rc;
|
||||||
|
watchctx_t ctx;
|
||||||
|
zhandle_t *zk = createClient(&ctx);
|
||||||
|
|
||||||
|
int sz = 512;
|
||||||
|
char p1[sz], p2[sz], p3[sz];
|
||||||
|
|
||||||
|
p1[0] = '\0';
|
||||||
|
p2[0] = '\0';
|
||||||
|
p3[0] = '\0';
|
||||||
|
|
||||||
|
int nops = 3;
|
||||||
|
zoo_op_t ops[nops];
|
||||||
|
zoo_op_result_t results[nops];
|
||||||
|
|
||||||
|
zoo_create_op_init(&ops[0], "/multi9", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
|
||||||
|
zoo_create_op_init(&ops[1], "/multi9", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p2, sz);
|
||||||
|
zoo_create_op_init(&ops[2], "/multi9/b", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p3, sz);
|
||||||
|
|
||||||
|
rc = zoo_multi(zk, nops, ops, results);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZNODEEXISTS, rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test basic multi-op check functionality
|
||||||
|
*/
|
||||||
|
void testCheck() {
|
||||||
|
int rc;
|
||||||
|
watchctx_t ctx;
|
||||||
|
zhandle_t *zk = createClient(&ctx);
|
||||||
|
int sz = 512;
|
||||||
|
char p1[sz];
|
||||||
|
p1[0] = '\0';
|
||||||
|
struct Stat s1;
|
||||||
|
|
||||||
|
rc = zoo_create(zk, "/multi0", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
|
||||||
|
|
||||||
|
// Conditionally create /multi0/a' only if '/multi0' at version 0
|
||||||
|
int nops = 2;
|
||||||
|
zoo_op_t ops[nops];
|
||||||
|
zoo_op_result_t results[nops];
|
||||||
|
|
||||||
|
zoo_check_op_init(&ops[0], "/multi0", 0);
|
||||||
|
zoo_create_op_init(&ops[1], "/multi0/a", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
|
||||||
|
|
||||||
|
rc = zoo_multi(zk, nops, ops, results);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, results[0].err);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, results[1].err);
|
||||||
|
|
||||||
|
// '/multi0/a' should have been created as it passed version check
|
||||||
|
rc = zoo_exists(zk, "/multi0/a", 0, NULL);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
|
||||||
|
|
||||||
|
// Only create '/multi0/b' if '/multi0' at version 10 (which it's not)
|
||||||
|
zoo_op_t ops2[nops];
|
||||||
|
zoo_check_op_init(&ops2[0], "/multi0", 10);
|
||||||
|
zoo_create_op_init(&ops2[1], "/multi0/b", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, p1, sz);
|
||||||
|
|
||||||
|
rc = zoo_multi(zk, nops, ops2, results);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZBADVERSION, rc);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZBADVERSION, results[0].err);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZRUNTIMEINCONSISTENCY, results[1].err);
|
||||||
|
|
||||||
|
// '/multi0/b' should NOT have been created
|
||||||
|
rc = zoo_exists(zk, "/multi0/b", 0, NULL);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do a multi op inside a watch callback context.
|
||||||
|
*/
|
||||||
|
static void doMultiInWatch(zhandle_t *zk, int type, int state, const char *path, void *ctx) {
|
||||||
|
int rc;
|
||||||
|
int sz = 512;
|
||||||
|
char p1[sz];
|
||||||
|
p1[0] = '\0';
|
||||||
|
struct Stat s1;
|
||||||
|
|
||||||
|
int nops = 1;
|
||||||
|
zoo_op_t ops[nops];
|
||||||
|
zoo_op_result_t results[nops];
|
||||||
|
|
||||||
|
zoo_set_op_init(&ops[0], "/multiwatch", "1", 1, -1, NULL);
|
||||||
|
|
||||||
|
rc = zoo_multi(zk, nops, ops, results);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, results[0].err);
|
||||||
|
|
||||||
|
memset(p1, '\0', sz);
|
||||||
|
rc = zoo_get(zk, "/multiwatch", 0, p1, &sz, &s1);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, sz);
|
||||||
|
CPPUNIT_ASSERT(strcmp("1", p1) == 0);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test multi-op called from a watch
|
||||||
|
*/
|
||||||
|
void testWatch() {
|
||||||
|
int rc;
|
||||||
|
watchctx_t ctx;
|
||||||
|
zhandle_t *zk = createClient(&ctx);
|
||||||
|
int sz = 512;
|
||||||
|
char p1[sz];
|
||||||
|
p1[0] = '\0';
|
||||||
|
|
||||||
|
rc = zoo_create(zk, "/multiwatch", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, NULL, 0);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
|
||||||
|
|
||||||
|
// create a watch on node '/multiwatch'
|
||||||
|
rc = zoo_wget(zk, "/multiwatch", doMultiInWatch, &ctx, p1, &sz, NULL);
|
||||||
|
|
||||||
|
// setdata on node '/multiwatch' this should trip the watch
|
||||||
|
rc = zoo_set(zk, "/multiwatch", NULL, -1, -1);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
|
||||||
|
|
||||||
|
// wait for multi completion in doMultiInWatch
|
||||||
|
waitForMultiCompletion(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ZOOKEEPER-1636: If request is too large, the server will cut the
|
||||||
|
* connection without sending response packet. The client will try to
|
||||||
|
* process completion on multi request and eventually cause SIGSEGV
|
||||||
|
*/
|
||||||
|
void testBigAsyncMulti() {
|
||||||
|
int rc;
|
||||||
|
int callback_rc = (int) ZOK;
|
||||||
|
watchctx_t ctx;
|
||||||
|
zhandle_t *zk = createClient(&ctx);
|
||||||
|
|
||||||
|
// The request should be more than 1MB which exceeds the default
|
||||||
|
// jute.maxbuffer and causes the server to drop client connection
|
||||||
|
const int iteration = 500;
|
||||||
|
const int type_count = 3;
|
||||||
|
const int nops = iteration * type_count;
|
||||||
|
char buff[1024];
|
||||||
|
|
||||||
|
zoo_op_result_t results[nops];
|
||||||
|
zoo_op_t ops[nops];
|
||||||
|
struct Stat* s[nops];
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
// Test that we deliver error to 3 types of sub-request
|
||||||
|
for (int i = 0; i < iteration; ++i) {
|
||||||
|
zoo_set_op_init(&ops[index++], "/x", buff, sizeof(buff), -1, s[i]);
|
||||||
|
zoo_create_op_init(&ops[index++], "/x", buff, sizeof(buff),
|
||||||
|
&ZOO_OPEN_ACL_UNSAFE, ZOO_SEQUENCE, NULL, 0);
|
||||||
|
zoo_delete_op_init(&ops[index++], "/x", -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = zoo_amulti(zk, nops, ops, results, multi_completion_fn_rc,
|
||||||
|
+ &callback_rc);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
|
||||||
|
|
||||||
|
waitForMultiCompletion(10);
|
||||||
|
// With the bug, we will get SIGSEGV before reaching this point
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int) ZCONNECTIONLOSS, callback_rc);
|
||||||
|
|
||||||
|
// Make sure that all sub-request completions get processed
|
||||||
|
for (int i = 0; i < nops; ++i) {
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int) ZCONNECTIONLOSS, results[i].err);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The handle should be able to recover itself.
|
||||||
|
ctx.waitForConnected(zk);
|
||||||
|
|
||||||
|
// Try to submit another async request to see if it get processed
|
||||||
|
// correctly
|
||||||
|
rc = zoo_acreate(zk, "/target", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0,
|
||||||
|
create_completion_fn_rc, &callback_rc);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
|
||||||
|
|
||||||
|
waitForMultiCompletion(10);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int) ZOK, callback_rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ZOOKEEPER-1624: PendingChanges of create sequential node request didn't
|
||||||
|
* get rollbacked correctly when multi-op failed. This caused
|
||||||
|
* create sequential node request in subsequent multi-op to failed because
|
||||||
|
* sequential node name generation is incorrect.
|
||||||
|
*
|
||||||
|
* The check is to make sure that each request in multi-op failed with
|
||||||
|
* the correct reason.
|
||||||
|
*/
|
||||||
|
void testSequentialNodeCreateInAsyncMulti() {
|
||||||
|
int rc;
|
||||||
|
watchctx_t ctx;
|
||||||
|
zhandle_t *zk = createClient(&ctx);
|
||||||
|
|
||||||
|
int iteration = 4;
|
||||||
|
int nops = 2;
|
||||||
|
|
||||||
|
zoo_op_result_t results[iteration][nops];
|
||||||
|
zoo_op_t ops[nops];
|
||||||
|
zoo_create_op_init(&ops[0], "/node-", "", 0, &ZOO_OPEN_ACL_UNSAFE, ZOO_SEQUENCE, NULL, 0);
|
||||||
|
zoo_create_op_init(&ops[1], "/dup", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, NULL, 0);
|
||||||
|
for (int i = 0; i < iteration ; ++i) {
|
||||||
|
rc = zoo_amulti(zk, nops, ops, results[i], multi_completion_fn_no_assert, 0);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
waitForMultiCompletion(10);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, results[0][0].err);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, results[1][0].err);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, results[2][0].err);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, results[3][0].err);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, results[0][1].err);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZNODEEXISTS, results[1][1].err);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZNODEEXISTS, results[2][1].err);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZNODEEXISTS, results[3][1].err);
|
||||||
|
|
||||||
|
resetCounter();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
volatile int Zookeeper_multi::count;
|
||||||
|
const char Zookeeper_multi::hostPorts[] = "127.0.0.1:22181";
|
||||||
|
CPPUNIT_TEST_SUITE_REGISTRATION(Zookeeper_multi);
|
||||||
|
#endif
|
976
zookeeper-client/zookeeper-client-c/tests/TestOperations.cc
Normal file
976
zookeeper-client/zookeeper-client-c/tests/TestOperations.cc
Normal file
@ -0,0 +1,976 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cppunit/extensions/HelperMacros.h>
|
||||||
|
#include "CppAssertHelper.h"
|
||||||
|
|
||||||
|
#include "ZKMocks.h"
|
||||||
|
#include <proto.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class Zookeeper_operations : public CPPUNIT_NS::TestFixture
|
||||||
|
{
|
||||||
|
CPPUNIT_TEST_SUITE(Zookeeper_operations);
|
||||||
|
#ifndef THREADED
|
||||||
|
CPPUNIT_TEST(testPing);
|
||||||
|
CPPUNIT_TEST(testUnsolicitedPing);
|
||||||
|
CPPUNIT_TEST(testTimeoutCausedByWatches1);
|
||||||
|
CPPUNIT_TEST(testTimeoutCausedByWatches2);
|
||||||
|
CPPUNIT_TEST(testCloseWhileInProgressFromMain);
|
||||||
|
CPPUNIT_TEST(testCloseWhileInProgressFromCompletion);
|
||||||
|
CPPUNIT_TEST(testCloseWhileMultiInProgressFromMain);
|
||||||
|
CPPUNIT_TEST(testCloseWhileMultiInProgressFromCompletion);
|
||||||
|
#else
|
||||||
|
CPPUNIT_TEST(testAsyncWatcher1);
|
||||||
|
CPPUNIT_TEST(testAsyncGetOperation);
|
||||||
|
#endif
|
||||||
|
CPPUNIT_TEST(testOperationsAndDisconnectConcurrently1);
|
||||||
|
CPPUNIT_TEST(testOperationsAndDisconnectConcurrently2);
|
||||||
|
CPPUNIT_TEST(testConcurrentOperations1);
|
||||||
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
zhandle_t *zh;
|
||||||
|
FILE *logfile;
|
||||||
|
|
||||||
|
static void watcher(zhandle_t *, int, int, const char *,void*){}
|
||||||
|
public:
|
||||||
|
Zookeeper_operations() {
|
||||||
|
logfile = openlogfile("Zookeeper_operations");
|
||||||
|
}
|
||||||
|
|
||||||
|
~Zookeeper_operations() {
|
||||||
|
if (logfile) {
|
||||||
|
fflush(logfile);
|
||||||
|
fclose(logfile);
|
||||||
|
logfile = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setUp()
|
||||||
|
{
|
||||||
|
zoo_set_log_stream(logfile);
|
||||||
|
|
||||||
|
zoo_deterministic_conn_order(0);
|
||||||
|
zh=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tearDown()
|
||||||
|
{
|
||||||
|
zookeeper_close(zh);
|
||||||
|
}
|
||||||
|
|
||||||
|
class AsyncGetOperationCompletion: public AsyncCompletion{
|
||||||
|
public:
|
||||||
|
AsyncGetOperationCompletion():called_(false),rc_(ZAPIERROR){}
|
||||||
|
virtual void dataCompl(int rc, const char *value, int len, const Stat *stat){
|
||||||
|
synchronized(mx_);
|
||||||
|
called_=true;
|
||||||
|
rc_=rc;
|
||||||
|
value_.erase();
|
||||||
|
if(rc!=ZOK) return;
|
||||||
|
value_.assign(value,len);
|
||||||
|
if(stat)
|
||||||
|
stat_=*stat;
|
||||||
|
}
|
||||||
|
bool operator()()const{
|
||||||
|
synchronized(mx_);
|
||||||
|
return called_;
|
||||||
|
}
|
||||||
|
mutable Mutex mx_;
|
||||||
|
bool called_;
|
||||||
|
int rc_;
|
||||||
|
string value_;
|
||||||
|
NodeStat stat_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AsyncVoidOperationCompletion: public AsyncCompletion{
|
||||||
|
public:
|
||||||
|
AsyncVoidOperationCompletion():called_(false),rc_(ZAPIERROR){}
|
||||||
|
virtual void voidCompl(int rc){
|
||||||
|
synchronized(mx_);
|
||||||
|
called_=true;
|
||||||
|
rc_=rc;
|
||||||
|
}
|
||||||
|
bool operator()()const{
|
||||||
|
synchronized(mx_);
|
||||||
|
return called_;
|
||||||
|
}
|
||||||
|
mutable Mutex mx_;
|
||||||
|
bool called_;
|
||||||
|
int rc_;
|
||||||
|
};
|
||||||
|
#ifndef THREADED
|
||||||
|
// send two get data requests; verify that the corresponding completions called
|
||||||
|
void testConcurrentOperations1()
|
||||||
|
{
|
||||||
|
Mock_gettimeofday timeMock;
|
||||||
|
ZookeeperServer zkServer;
|
||||||
|
// must call zookeeper_close() while all the mocks are in scope
|
||||||
|
CloseFinally guard(&zh);
|
||||||
|
|
||||||
|
zh=zookeeper_init("localhost:2121",watcher,10000,TEST_CLIENT_ID,0,0);
|
||||||
|
CPPUNIT_ASSERT(zh!=0);
|
||||||
|
// simulate connected state
|
||||||
|
forceConnected(zh);
|
||||||
|
|
||||||
|
int fd=0;
|
||||||
|
int interest=0;
|
||||||
|
timeval tv;
|
||||||
|
// first operation
|
||||||
|
AsyncGetOperationCompletion res1;
|
||||||
|
zkServer.addOperationResponse(new ZooGetResponse("1",1));
|
||||||
|
int rc=zoo_aget(zh,"/x/y/1",0,asyncCompletion,&res1);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
// second operation
|
||||||
|
AsyncGetOperationCompletion res2;
|
||||||
|
zkServer.addOperationResponse(new ZooGetResponse("2",1));
|
||||||
|
rc=zoo_aget(zh,"/x/y/2",0,asyncCompletion,&res2);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
// process the send queue
|
||||||
|
rc=zookeeper_interest(zh,&fd,&interest,&tv);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
while((rc=zookeeper_process(zh,interest))==ZOK) {
|
||||||
|
millisleep(100);
|
||||||
|
//printf("%d\n", rc);
|
||||||
|
}
|
||||||
|
//printf("RC = %d", rc);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,res1.rc_);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(string("1"),res1.value_);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,res2.rc_);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(string("2"),res2.value_);
|
||||||
|
}
|
||||||
|
// send two getData requests and disconnect while the second request is
|
||||||
|
// outstanding;
|
||||||
|
// verify the completions are called
|
||||||
|
void testOperationsAndDisconnectConcurrently1()
|
||||||
|
{
|
||||||
|
Mock_gettimeofday timeMock;
|
||||||
|
ZookeeperServer zkServer;
|
||||||
|
// must call zookeeper_close() while all the mocks are in scope
|
||||||
|
CloseFinally guard(&zh);
|
||||||
|
|
||||||
|
zh=zookeeper_init("localhost:2121",watcher,10000,TEST_CLIENT_ID,0,0);
|
||||||
|
CPPUNIT_ASSERT(zh!=0);
|
||||||
|
// simulate connected state
|
||||||
|
forceConnected(zh);
|
||||||
|
|
||||||
|
int fd=0;
|
||||||
|
int interest=0;
|
||||||
|
timeval tv;
|
||||||
|
// first operation
|
||||||
|
AsyncGetOperationCompletion res1;
|
||||||
|
zkServer.addOperationResponse(new ZooGetResponse("1",1));
|
||||||
|
int rc=zoo_aget(zh,"/x/y/1",0,asyncCompletion,&res1);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
// second operation
|
||||||
|
AsyncGetOperationCompletion res2;
|
||||||
|
zkServer.addOperationResponse(new ZooGetResponse("2",1));
|
||||||
|
rc=zoo_aget(zh,"/x/y/2",0,asyncCompletion,&res2);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
// process the send queue
|
||||||
|
rc=zookeeper_interest(zh,&fd,&interest,&tv);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
rc=zookeeper_process(zh,interest);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
// simulate a disconnect
|
||||||
|
zkServer.setConnectionLost();
|
||||||
|
rc=zookeeper_interest(zh,&fd,&interest,&tv);
|
||||||
|
rc=zookeeper_process(zh,interest);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZCONNECTIONLOSS,rc);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,res1.rc_);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(string("1"),res1.value_);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZCONNECTIONLOSS,res2.rc_);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(string(""),res2.value_);
|
||||||
|
}
|
||||||
|
// send two getData requests and simulate timeout while the both request
|
||||||
|
// are pending;
|
||||||
|
// verify the completions are called
|
||||||
|
void testOperationsAndDisconnectConcurrently2()
|
||||||
|
{
|
||||||
|
Mock_gettimeofday timeMock;
|
||||||
|
ZookeeperServer zkServer;
|
||||||
|
// must call zookeeper_close() while all the mocks are in scope
|
||||||
|
CloseFinally guard(&zh);
|
||||||
|
|
||||||
|
zh=zookeeper_init("localhost:2121",watcher,10000,TEST_CLIENT_ID,0,0);
|
||||||
|
CPPUNIT_ASSERT(zh!=0);
|
||||||
|
// simulate connected state
|
||||||
|
forceConnected(zh);
|
||||||
|
|
||||||
|
int fd=0;
|
||||||
|
int interest=0;
|
||||||
|
timeval tv;
|
||||||
|
// first operation
|
||||||
|
AsyncGetOperationCompletion res1;
|
||||||
|
zkServer.addOperationResponse(new ZooGetResponse("1",1));
|
||||||
|
int rc=zoo_aget(zh,"/x/y/1",0,asyncCompletion,&res1);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
// second operation
|
||||||
|
AsyncGetOperationCompletion res2;
|
||||||
|
zkServer.addOperationResponse(new ZooGetResponse("2",1));
|
||||||
|
rc=zoo_aget(zh,"/x/y/2",0,asyncCompletion,&res2);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
// simulate timeout
|
||||||
|
timeMock.tick(+10); // advance system time by 10 secs
|
||||||
|
// the next call to zookeeper_interest should return ZOPERATIONTIMEOUT
|
||||||
|
rc=zookeeper_interest(zh,&fd,&interest,&tv);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOPERATIONTIMEOUT,rc);
|
||||||
|
// make sure the completions have been called
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOPERATIONTIMEOUT,res1.rc_);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOPERATIONTIMEOUT,res2.rc_);
|
||||||
|
}
|
||||||
|
|
||||||
|
class PingCountingServer: public ZookeeperServer{
|
||||||
|
public:
|
||||||
|
PingCountingServer():pingCount_(0){}
|
||||||
|
// called when a client request is received
|
||||||
|
virtual void onMessageReceived(const RequestHeader& rh, iarchive* ia){
|
||||||
|
if(rh.type==ZOO_PING_OP){
|
||||||
|
pingCount_++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int pingCount_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// establish a connection; idle for a while
|
||||||
|
// verify ping was sent at least once
|
||||||
|
void testPing()
|
||||||
|
{
|
||||||
|
const int TIMEOUT=9; // timeout in secs
|
||||||
|
Mock_gettimeofday timeMock;
|
||||||
|
PingCountingServer zkServer;
|
||||||
|
// must call zookeeper_close() while all the mocks are in scope
|
||||||
|
CloseFinally guard(&zh);
|
||||||
|
|
||||||
|
// receive timeout is in milliseconds
|
||||||
|
zh=zookeeper_init("localhost:1234",watcher,TIMEOUT*1000,TEST_CLIENT_ID,0,0);
|
||||||
|
CPPUNIT_ASSERT(zh!=0);
|
||||||
|
// simulate connected state
|
||||||
|
forceConnected(zh);
|
||||||
|
|
||||||
|
int fd=0;
|
||||||
|
int interest=0;
|
||||||
|
timeval tv;
|
||||||
|
// Round 1.
|
||||||
|
int rc=zookeeper_interest(zh,&fd,&interest,&tv);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
// simulate waiting for the select() call to timeout;
|
||||||
|
// advance the system clock accordingly
|
||||||
|
timeMock.tick(tv);
|
||||||
|
rc=zookeeper_process(zh,interest);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
|
||||||
|
// verify no ping sent
|
||||||
|
CPPUNIT_ASSERT(zkServer.pingCount_==0);
|
||||||
|
|
||||||
|
// Round 2.
|
||||||
|
// the client should have the idle threshold exceeded, by now
|
||||||
|
rc=zookeeper_interest(zh,&fd,&interest,&tv);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
// assume the socket is writable, so no idling here; move on to
|
||||||
|
// zookeeper_process immediately
|
||||||
|
rc=zookeeper_process(zh,interest);
|
||||||
|
// ZNOTHING means the client hasn't received a ping response yet
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
|
||||||
|
// verify a ping is sent
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1,zkServer.pingCount_);
|
||||||
|
|
||||||
|
// Round 3.
|
||||||
|
// we're going to receive a server PING response and make sure
|
||||||
|
// that the client has updated its last_recv timestamp
|
||||||
|
zkServer.addRecvResponse(new PingResponse);
|
||||||
|
rc=zookeeper_interest(zh,&fd,&interest,&tv);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
// pseudo-sleep for a short while (10 ms)
|
||||||
|
timeMock.millitick(10);
|
||||||
|
rc=zookeeper_process(zh,interest);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
// only one ping so far?
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1,zkServer.pingCount_);
|
||||||
|
CPPUNIT_ASSERT(timeMock==zh->last_recv);
|
||||||
|
|
||||||
|
// Round 4
|
||||||
|
// make sure that a ping is not sent if something is outstanding
|
||||||
|
AsyncGetOperationCompletion res1;
|
||||||
|
rc=zoo_aget(zh,"/x/y/1",0,asyncCompletion,&res1);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
rc=zookeeper_interest(zh,&fd,&interest,&tv);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
timeMock.tick(tv);
|
||||||
|
rc=zookeeper_interest(zh,&fd,&interest,&tv);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
rc=zookeeper_process(zh,interest);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
|
||||||
|
rc=zookeeper_interest(zh,&fd,&interest,&tv);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
// pseudo-sleep for a short while (10 ms)
|
||||||
|
timeMock.millitick(10);
|
||||||
|
rc=zookeeper_process(zh,interest);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
|
||||||
|
// only one ping so far?
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1,zkServer.pingCount_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZOOKEEPER-2253: Permit unsolicited pings
|
||||||
|
void testUnsolicitedPing()
|
||||||
|
{
|
||||||
|
const int TIMEOUT=9; // timeout in secs
|
||||||
|
Mock_gettimeofday timeMock;
|
||||||
|
PingCountingServer zkServer;
|
||||||
|
// must call zookeeper_close() while all the mocks are in scope
|
||||||
|
CloseFinally guard(&zh);
|
||||||
|
|
||||||
|
// receive timeout is in milliseconds
|
||||||
|
zh=zookeeper_init("localhost:1234",watcher,TIMEOUT*1000,TEST_CLIENT_ID,0,0);
|
||||||
|
CPPUNIT_ASSERT(zh!=0);
|
||||||
|
// simulate connected state
|
||||||
|
forceConnected(zh);
|
||||||
|
|
||||||
|
int fd=0;
|
||||||
|
int interest=0;
|
||||||
|
timeval tv;
|
||||||
|
|
||||||
|
int rc=zookeeper_interest(zh,&fd,&interest,&tv);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
|
||||||
|
// verify no ping sent
|
||||||
|
CPPUNIT_ASSERT(zkServer.pingCount_==0);
|
||||||
|
|
||||||
|
// we're going to receive a unsolicited PING response; ensure
|
||||||
|
// that the client has updated its last_recv timestamp
|
||||||
|
timeMock.tick(tv);
|
||||||
|
zkServer.addRecvResponse(new PingResponse);
|
||||||
|
rc=zookeeper_process(zh,interest);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
CPPUNIT_ASSERT(timeMock==zh->last_recv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// simulate a watch arriving right before a ping is due
|
||||||
|
// assert the ping is sent nevertheless
|
||||||
|
void testTimeoutCausedByWatches1()
|
||||||
|
{
|
||||||
|
const int TIMEOUT=9; // timeout in secs
|
||||||
|
Mock_gettimeofday timeMock;
|
||||||
|
PingCountingServer zkServer;
|
||||||
|
// must call zookeeper_close() while all the mocks are in scope
|
||||||
|
CloseFinally guard(&zh);
|
||||||
|
|
||||||
|
// receive timeout is in milliseconds
|
||||||
|
zh=zookeeper_init("localhost:1234",watcher,TIMEOUT*1000,TEST_CLIENT_ID,0,0);
|
||||||
|
CPPUNIT_ASSERT(zh!=0);
|
||||||
|
// simulate connected state
|
||||||
|
forceConnected(zh);
|
||||||
|
|
||||||
|
int fd=0;
|
||||||
|
int interest=0;
|
||||||
|
timeval tv;
|
||||||
|
// Round 1.
|
||||||
|
int rc=zookeeper_interest(zh,&fd,&interest,&tv);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
// simulate waiting for the select() call to timeout;
|
||||||
|
// advance the system clock accordingly
|
||||||
|
timeMock.tick(tv);
|
||||||
|
timeMock.tick(-1); // set the clock to a millisecond before a ping is due
|
||||||
|
// trigger a watch now
|
||||||
|
zkServer.addRecvResponse(new ZNodeEvent(ZOO_CHANGED_EVENT,"/x/y/z"));
|
||||||
|
rc=zookeeper_process(zh,interest);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
// arrival of a watch sets the last_recv to the current time
|
||||||
|
CPPUNIT_ASSERT(timeMock==zh->last_recv);
|
||||||
|
// spend 1 millisecond by processing the watch
|
||||||
|
timeMock.tick(1);
|
||||||
|
|
||||||
|
// Round 2.
|
||||||
|
// a ping is due; zookeeper_interest() must send it now
|
||||||
|
rc=zookeeper_interest(zh,&fd,&interest,&tv);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
// no delay here -- as if the socket is immediately writable
|
||||||
|
rc=zookeeper_process(zh,interest);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
|
||||||
|
// verify a ping is sent
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1,zkServer.pingCount_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// similar to testTimeoutCausedByWatches1, but this time the watch is
|
||||||
|
// triggered while the client has an outstanding request
|
||||||
|
// assert the ping is sent on time
|
||||||
|
void testTimeoutCausedByWatches2()
|
||||||
|
{
|
||||||
|
const int TIMEOUT=9; // timeout in secs
|
||||||
|
Mock_gettimeofday now;
|
||||||
|
PingCountingServer zkServer;
|
||||||
|
// must call zookeeper_close() while all the mocks are in scope
|
||||||
|
CloseFinally guard(&zh);
|
||||||
|
|
||||||
|
// receive timeout is in milliseconds
|
||||||
|
zh=zookeeper_init("localhost:1234",watcher,TIMEOUT*1000,TEST_CLIENT_ID,0,0);
|
||||||
|
CPPUNIT_ASSERT(zh!=0);
|
||||||
|
// simulate connected state
|
||||||
|
forceConnected(zh);
|
||||||
|
|
||||||
|
// queue up a request; keep it pending (as if the server is busy or has died)
|
||||||
|
AsyncGetOperationCompletion res1;
|
||||||
|
zkServer.addOperationResponse(new ZooGetResponse("2",1));
|
||||||
|
int rc=zoo_aget(zh,"/x/y/1",0,asyncCompletion,&res1);
|
||||||
|
|
||||||
|
int fd=0;
|
||||||
|
int interest=0;
|
||||||
|
timeval tv;
|
||||||
|
// Round 1.
|
||||||
|
// send the queued up zoo_aget() request
|
||||||
|
Mock_gettimeofday beginningOfTimes(now); // remember when we started
|
||||||
|
rc=zookeeper_interest(zh,&fd,&interest,&tv);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
// no delay -- the socket is writable
|
||||||
|
rc=zookeeper_process(zh,interest);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
|
||||||
|
// Round 2.
|
||||||
|
// what's next?
|
||||||
|
rc=zookeeper_interest(zh,&fd,&interest,&tv);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
// no response from the server yet -- waiting in the select() call
|
||||||
|
now.tick(tv);
|
||||||
|
// a watch has arrived, thus preventing the connection from timing out
|
||||||
|
zkServer.addRecvResponse(new ZNodeEvent(ZOO_CHANGED_EVENT,"/x/y/z"));
|
||||||
|
rc=zookeeper_process(zh,interest);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc); // read the watch message
|
||||||
|
CPPUNIT_ASSERT_EQUAL(0,zkServer.pingCount_); // not yet!
|
||||||
|
|
||||||
|
//Round 3.
|
||||||
|
// now is the time to send a ping; make sure it's actually sent
|
||||||
|
rc=zookeeper_interest(zh,&fd,&interest,&tv);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
rc=zookeeper_process(zh,interest);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZNOTHING,rc);
|
||||||
|
// verify a ping is sent
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1,zkServer.pingCount_);
|
||||||
|
// make sure only 1/3 of the timeout has passed
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int32_t)TIMEOUT/3*1000,toMilliseconds(now-beginningOfTimes));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZOOKEEPER-2894: Memory and completions leak on zookeeper_close
|
||||||
|
// while there is a request waiting for being processed
|
||||||
|
// call zookeeper_close() from the main event loop
|
||||||
|
// assert the completion callback is called
|
||||||
|
void testCloseWhileInProgressFromMain()
|
||||||
|
{
|
||||||
|
Mock_gettimeofday timeMock;
|
||||||
|
ZookeeperServer zkServer;
|
||||||
|
CloseFinally guard(&zh);
|
||||||
|
|
||||||
|
zh=zookeeper_init("localhost:2121",watcher,10000,TEST_CLIENT_ID,0,0);
|
||||||
|
CPPUNIT_ASSERT(zh!=0);
|
||||||
|
forceConnected(zh);
|
||||||
|
zhandle_t* savezh=zh;
|
||||||
|
|
||||||
|
// issue a request
|
||||||
|
zkServer.addOperationResponse(new ZooGetResponse("1",1));
|
||||||
|
AsyncGetOperationCompletion res1;
|
||||||
|
int rc=zoo_aget(zh,"/x/y/1",0,asyncCompletion,&res1);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
|
||||||
|
// but do not allow Zookeeper C Client to process the request
|
||||||
|
// and call zookeeper_close() from the main event loop immediately
|
||||||
|
Mock_free_noop freeMock;
|
||||||
|
rc=zookeeper_close(zh); zh=0;
|
||||||
|
freeMock.disable();
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
|
||||||
|
// verify that memory for completions was freed (would be freed if no mock installed)
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(savezh));
|
||||||
|
CPPUNIT_ASSERT(savezh->completions_to_process.head==0);
|
||||||
|
CPPUNIT_ASSERT(savezh->completions_to_process.last==0);
|
||||||
|
|
||||||
|
// verify that completion was called, and it was called with ZCLOSING status
|
||||||
|
CPPUNIT_ASSERT(res1.called_);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZCLOSING,res1.rc_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZOOKEEPER-2894: Memory and completions leak on zookeeper_close
|
||||||
|
// send some request #1
|
||||||
|
// then, while there is a request #2 waiting for being processed
|
||||||
|
// call zookeeper_close() from the completion callback of request #1
|
||||||
|
// assert the completion callback #2 is called
|
||||||
|
void testCloseWhileInProgressFromCompletion()
|
||||||
|
{
|
||||||
|
Mock_gettimeofday timeMock;
|
||||||
|
ZookeeperServer zkServer;
|
||||||
|
CloseFinally guard(&zh);
|
||||||
|
|
||||||
|
zh=zookeeper_init("localhost:2121",watcher,10000,TEST_CLIENT_ID,0,0);
|
||||||
|
CPPUNIT_ASSERT(zh!=0);
|
||||||
|
forceConnected(zh);
|
||||||
|
zhandle_t* savezh=zh;
|
||||||
|
|
||||||
|
// will handle completion on request #1 and issue request #2 from it
|
||||||
|
class AsyncGetOperationCompletion1: public AsyncCompletion{
|
||||||
|
public:
|
||||||
|
AsyncGetOperationCompletion1(zhandle_t **zh, ZookeeperServer *zkServer,
|
||||||
|
AsyncGetOperationCompletion *res2)
|
||||||
|
:zh_(zh),zkServer_(zkServer),res2_(res2){}
|
||||||
|
|
||||||
|
virtual void dataCompl(int rc1, const char *value, int len, const Stat *stat){
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc1);
|
||||||
|
|
||||||
|
// from the completion #1 handler, issue request #2
|
||||||
|
zkServer_->addOperationResponse(new ZooGetResponse("2",1));
|
||||||
|
int rc2=zoo_aget(*zh_,"/x/y/2",0,asyncCompletion,res2_);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc2);
|
||||||
|
|
||||||
|
// but do not allow Zookeeper C Client to process the request #2
|
||||||
|
// and call zookeeper_close() from the completion callback of request #1
|
||||||
|
rc2=zookeeper_close(*zh_); *zh_=0;
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc2);
|
||||||
|
|
||||||
|
// do not disable freeMock here, let completion #2 handler
|
||||||
|
// return through ZooKeeper C Client internals to the main loop
|
||||||
|
// and fulfill the work
|
||||||
|
}
|
||||||
|
|
||||||
|
zhandle_t **zh_;
|
||||||
|
ZookeeperServer *zkServer_;
|
||||||
|
AsyncGetOperationCompletion *res2_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// issue request #1
|
||||||
|
AsyncGetOperationCompletion res2;
|
||||||
|
AsyncGetOperationCompletion1 res1(&zh,&zkServer,&res2);
|
||||||
|
zkServer.addOperationResponse(new ZooGetResponse("1",1));
|
||||||
|
int rc=zoo_aget(zh,"/x/y/1",0,asyncCompletion,&res1);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
|
||||||
|
// process the send queue
|
||||||
|
int fd; int interest; timeval tv;
|
||||||
|
rc=zookeeper_interest(zh,&fd,&interest,&tv);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
CPPUNIT_ASSERT(zh!=0);
|
||||||
|
Mock_free_noop freeMock;
|
||||||
|
while(zh!=0 && (rc=zookeeper_process(zh,interest))==ZOK) {
|
||||||
|
millisleep(100);
|
||||||
|
}
|
||||||
|
freeMock.disable();
|
||||||
|
CPPUNIT_ASSERT(zh==0);
|
||||||
|
|
||||||
|
// verify that memory for completions was freed (would be freed if no mock installed)
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(savezh));
|
||||||
|
CPPUNIT_ASSERT(savezh->completions_to_process.head==0);
|
||||||
|
CPPUNIT_ASSERT(savezh->completions_to_process.last==0);
|
||||||
|
|
||||||
|
// verify that completion #2 was called, and it was called with ZCLOSING status
|
||||||
|
CPPUNIT_ASSERT(res2.called_);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZCLOSING,res2.rc_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZOOKEEPER-2891: Invalid processing of zookeeper_close for mutli-request
|
||||||
|
// while there is a multi request waiting for being processed
|
||||||
|
// call zookeeper_close() from the main event loop
|
||||||
|
// assert the completion callback is called with status ZCLOSING
|
||||||
|
void testCloseWhileMultiInProgressFromMain()
|
||||||
|
{
|
||||||
|
Mock_gettimeofday timeMock;
|
||||||
|
ZookeeperServer zkServer;
|
||||||
|
CloseFinally guard(&zh);
|
||||||
|
|
||||||
|
zh=zookeeper_init("localhost:2121",watcher,10000,TEST_CLIENT_ID,0,0);
|
||||||
|
CPPUNIT_ASSERT(zh!=0);
|
||||||
|
forceConnected(zh);
|
||||||
|
zhandle_t* savezh=zh;
|
||||||
|
|
||||||
|
// issue a multi request
|
||||||
|
int nops=2;
|
||||||
|
zoo_op_t ops[nops];
|
||||||
|
zoo_op_result_t results[nops];
|
||||||
|
zoo_create_op_init(&ops[0],"/a",0,-1,&ZOO_OPEN_ACL_UNSAFE,0,0,0);
|
||||||
|
zoo_create_op_init(&ops[1],"/a/b",0,-1,&ZOO_OPEN_ACL_UNSAFE,0,0,0);
|
||||||
|
// TODO: Provide ZooMultiResponse. However, it's not required in this test.
|
||||||
|
// zkServer.addOperationResponse(new ZooMultiResponse(...));
|
||||||
|
AsyncVoidOperationCompletion res1;
|
||||||
|
int rc=zoo_amulti(zh,nops,ops,results,asyncCompletion,&res1);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
|
||||||
|
// but do not allow Zookeeper C Client to process the request
|
||||||
|
// and call zookeeper_close() from the main event loop immediately
|
||||||
|
Mock_free_noop freeMock;
|
||||||
|
rc=zookeeper_close(zh); zh=0;
|
||||||
|
freeMock.disable();
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
|
||||||
|
// verify that memory for completions was freed (would be freed if no mock installed)
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(savezh));
|
||||||
|
CPPUNIT_ASSERT(savezh->completions_to_process.head==0);
|
||||||
|
CPPUNIT_ASSERT(savezh->completions_to_process.last==0);
|
||||||
|
|
||||||
|
// verify that completion was called, and it was called with ZCLOSING status
|
||||||
|
CPPUNIT_ASSERT(res1.called_);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZCLOSING,res1.rc_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZOOKEEPER-2891: Invalid processing of zookeeper_close for mutli-request
|
||||||
|
// send some request #1 (not a multi request)
|
||||||
|
// then, while there is a multi request #2 waiting for being processed
|
||||||
|
// call zookeeper_close() from the completion callback of request #1
|
||||||
|
// assert the completion callback #2 is called with status ZCLOSING
|
||||||
|
void testCloseWhileMultiInProgressFromCompletion()
|
||||||
|
{
|
||||||
|
Mock_gettimeofday timeMock;
|
||||||
|
ZookeeperServer zkServer;
|
||||||
|
CloseFinally guard(&zh);
|
||||||
|
|
||||||
|
zh=zookeeper_init("localhost:2121",watcher,10000,TEST_CLIENT_ID,0,0);
|
||||||
|
CPPUNIT_ASSERT(zh!=0);
|
||||||
|
forceConnected(zh);
|
||||||
|
zhandle_t* savezh=zh;
|
||||||
|
|
||||||
|
// these shall persist during the test
|
||||||
|
int nops=2;
|
||||||
|
zoo_op_t ops[nops];
|
||||||
|
zoo_op_result_t results[nops];
|
||||||
|
|
||||||
|
// will handle completion on request #1 and issue request #2 from it
|
||||||
|
class AsyncGetOperationCompletion1: public AsyncCompletion{
|
||||||
|
public:
|
||||||
|
AsyncGetOperationCompletion1(zhandle_t **zh, ZookeeperServer *zkServer,
|
||||||
|
AsyncVoidOperationCompletion *res2,
|
||||||
|
int nops, zoo_op_t* ops, zoo_op_result_t* results)
|
||||||
|
:zh_(zh),zkServer_(zkServer),res2_(res2),nops_(nops),ops_(ops),results_(results){}
|
||||||
|
|
||||||
|
virtual void dataCompl(int rc1, const char *value, int len, const Stat *stat){
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc1);
|
||||||
|
|
||||||
|
// from the completion #1 handler, issue multi request #2
|
||||||
|
assert(nops_>=2);
|
||||||
|
zoo_create_op_init(&ops_[0],"/a",0,-1,&ZOO_OPEN_ACL_UNSAFE,0,0,0);
|
||||||
|
zoo_create_op_init(&ops_[1],"/a/b",0,-1,&ZOO_OPEN_ACL_UNSAFE,0,0,0);
|
||||||
|
// TODO: Provide ZooMultiResponse. However, it's not required in this test.
|
||||||
|
// zkServer_->addOperationResponse(new ZooMultiResponse(...));
|
||||||
|
int rc2=zoo_amulti(*zh_,nops_,ops_,results_,asyncCompletion,res2_);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc2);
|
||||||
|
|
||||||
|
// but do not allow Zookeeper C Client to process the request #2
|
||||||
|
// and call zookeeper_close() from the completion callback of request #1
|
||||||
|
rc2=zookeeper_close(*zh_); *zh_=0;
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc2);
|
||||||
|
|
||||||
|
// do not disable freeMock here, let completion #2 handler
|
||||||
|
// return through ZooKeeper C Client internals to the main loop
|
||||||
|
// and fulfill the work
|
||||||
|
}
|
||||||
|
|
||||||
|
zhandle_t **zh_;
|
||||||
|
ZookeeperServer *zkServer_;
|
||||||
|
AsyncVoidOperationCompletion *res2_;
|
||||||
|
int nops_;
|
||||||
|
zoo_op_t* ops_;
|
||||||
|
zoo_op_result_t* results_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// issue some request #1 (not a multi request)
|
||||||
|
AsyncVoidOperationCompletion res2;
|
||||||
|
AsyncGetOperationCompletion1 res1(&zh,&zkServer,&res2,nops,ops,results);
|
||||||
|
zkServer.addOperationResponse(new ZooGetResponse("1",1));
|
||||||
|
int rc=zoo_aget(zh,"/x/y/1",0,asyncCompletion,&res1);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
|
||||||
|
// process the send queue
|
||||||
|
int fd; int interest; timeval tv;
|
||||||
|
rc=zookeeper_interest(zh,&fd,&interest,&tv);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
CPPUNIT_ASSERT(zh!=0);
|
||||||
|
Mock_free_noop freeMock;
|
||||||
|
while(zh!=0 && (rc=zookeeper_process(zh,interest))==ZOK) {
|
||||||
|
millisleep(100);
|
||||||
|
}
|
||||||
|
freeMock.disable();
|
||||||
|
CPPUNIT_ASSERT(zh==0);
|
||||||
|
|
||||||
|
// verify that memory for completions was freed (would be freed if no mock installed)
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1,freeMock.getFreeCount(savezh));
|
||||||
|
CPPUNIT_ASSERT(savezh->completions_to_process.head==0);
|
||||||
|
CPPUNIT_ASSERT(savezh->completions_to_process.last==0);
|
||||||
|
|
||||||
|
// verify that completion #2 was called, and it was called with ZCLOSING status
|
||||||
|
CPPUNIT_ASSERT(res2.called_);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZCLOSING,res2.rc_);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
class TestGetDataJob: public TestJob{
|
||||||
|
public:
|
||||||
|
TestGetDataJob(ZookeeperServer* svr,zhandle_t* zh, int reps=500)
|
||||||
|
:svr_(svr),zh_(zh),rc_(ZAPIERROR),reps_(reps){}
|
||||||
|
virtual void run(){
|
||||||
|
int i;
|
||||||
|
for(i=0;i<reps_;i++){
|
||||||
|
char buf;
|
||||||
|
int size=sizeof(buf);
|
||||||
|
|
||||||
|
if (i % 10 == 0) {
|
||||||
|
// We need to pause every once in a while so we don't
|
||||||
|
// get too far ahead and finish before the disconnect
|
||||||
|
millisleep(1);
|
||||||
|
}
|
||||||
|
svr_->addOperationResponse(new ZooGetResponse("1",1));
|
||||||
|
rc_=zoo_get(zh_,"/x/y/z",0,&buf,&size,0);
|
||||||
|
if(rc_!=ZOK){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ZookeeperServer* svr_;
|
||||||
|
zhandle_t* zh_;
|
||||||
|
int rc_;
|
||||||
|
int reps_;
|
||||||
|
};
|
||||||
|
class TestConcurrentOpJob: public TestGetDataJob{
|
||||||
|
public:
|
||||||
|
static const int REPS=500;
|
||||||
|
TestConcurrentOpJob(ZookeeperServer* svr,zhandle_t* zh):
|
||||||
|
TestGetDataJob(svr,zh,REPS){}
|
||||||
|
virtual TestJob* clone() const {
|
||||||
|
return new TestConcurrentOpJob(svr_,zh_);
|
||||||
|
}
|
||||||
|
virtual void validate(const char* file, int line) const{
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE_LOC("ZOK != rc",(int)ZOK,rc_,file,line);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
void testConcurrentOperations1()
|
||||||
|
{
|
||||||
|
for(int counter=0; counter<50; counter++){
|
||||||
|
// frozen time -- no timeouts and no pings
|
||||||
|
Mock_gettimeofday timeMock;
|
||||||
|
|
||||||
|
ZookeeperServer zkServer;
|
||||||
|
Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
|
||||||
|
// must call zookeeper_close() while all the mocks are in the scope!
|
||||||
|
CloseFinally guard(&zh);
|
||||||
|
|
||||||
|
zh=zookeeper_init("localhost:2121",watcher,10000,TEST_CLIENT_ID,0,0);
|
||||||
|
CPPUNIT_ASSERT(zh!=0);
|
||||||
|
// make sure the client has connected
|
||||||
|
CPPUNIT_ASSERT(ensureCondition(ClientConnected(zh),1000)<1000);
|
||||||
|
|
||||||
|
TestJobManager jmgr(TestConcurrentOpJob(&zkServer,zh),10);
|
||||||
|
jmgr.startAllJobs();
|
||||||
|
jmgr.wait();
|
||||||
|
// validate test results
|
||||||
|
VALIDATE_JOBS(jmgr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class ZKGetJob: public TestJob{
|
||||||
|
public:
|
||||||
|
static const int REPS=1000;
|
||||||
|
ZKGetJob(zhandle_t* zh)
|
||||||
|
:zh_(zh),rc_(ZAPIERROR){}
|
||||||
|
virtual TestJob* clone() const {
|
||||||
|
return new ZKGetJob(zh_);
|
||||||
|
}
|
||||||
|
virtual void run(){
|
||||||
|
int i;
|
||||||
|
for(i=0;i<REPS;i++){
|
||||||
|
char buf;
|
||||||
|
int size=sizeof(buf);
|
||||||
|
rc_=zoo_get(zh_,"/xyz",0,&buf,&size,0);
|
||||||
|
if(rc_!=ZOK){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//TEST_TRACE("Finished %d iterations",i);
|
||||||
|
}
|
||||||
|
virtual void validate(const char* file, int line) const{
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE_LOC("ZOK != rc",(int)ZOK,rc_,file,line);
|
||||||
|
}
|
||||||
|
zhandle_t* zh_;
|
||||||
|
int rc_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// this test connects to a real ZK server and creates the /xyz node and sends
|
||||||
|
// lots of zoo_get requests.
|
||||||
|
// to run this test use the following command:
|
||||||
|
// zktest-mt Zookeeper_operations::testOperationsAndDisconnectConcurrently2 localhost:3181
|
||||||
|
// where the second parameter is the server host and port
|
||||||
|
void testOperationsAndDisconnectConcurrently2()
|
||||||
|
{
|
||||||
|
if(globalTestConfig.getTestName().find(__func__)==string::npos ||
|
||||||
|
globalTestConfig.getExtraOptCount()==0)
|
||||||
|
{
|
||||||
|
// only run this test when specifically asked so
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
string host(*(globalTestConfig.getExtraOptBegin()));
|
||||||
|
zhandle_t* lzh=zookeeper_init(host.c_str(),watcher,10000,0,0,0);
|
||||||
|
CPPUNIT_ASSERT(lzh!=0);
|
||||||
|
// make sure the client has connected
|
||||||
|
CPPUNIT_ASSERT_MESSAGE("Unable to connect to the host",
|
||||||
|
ensureCondition(ClientConnected(zh),5000)<5000);
|
||||||
|
|
||||||
|
char realpath[1024];
|
||||||
|
int rc=zoo_create(lzh,"/xyz","1",1,&ZOO_OPEN_ACL_UNSAFE,0,realpath,sizeof(realpath)-1);
|
||||||
|
CPPUNIT_ASSERT(rc==ZOK || rc==ZNODEEXISTS);
|
||||||
|
zookeeper_close(lzh);
|
||||||
|
|
||||||
|
for(int counter=0; counter<200; counter++){
|
||||||
|
TEST_TRACE("Loop count %d",counter);
|
||||||
|
|
||||||
|
CloseFinally guard(&zh);
|
||||||
|
|
||||||
|
zh=zookeeper_init(host.c_str(),watcher,10000,0,0,0);
|
||||||
|
CPPUNIT_ASSERT(zh!=0);
|
||||||
|
// make sure the client has connected
|
||||||
|
CPPUNIT_ASSERT_MESSAGE("Unable to connect to the host",
|
||||||
|
ensureCondition(ClientConnected(zh),5000)<5000);
|
||||||
|
|
||||||
|
TestJobManager jmgr(ZKGetJob(zh),10);
|
||||||
|
jmgr.startJobsImmediately();
|
||||||
|
jmgr.wait();
|
||||||
|
VALIDATE_JOBS(jmgr);
|
||||||
|
TEST_TRACE("run %d finished",counter);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestConcurrentOpWithDisconnectJob: public TestGetDataJob{
|
||||||
|
public:
|
||||||
|
static const int REPS=1000;
|
||||||
|
TestConcurrentOpWithDisconnectJob(ZookeeperServer* svr,zhandle_t* zh):
|
||||||
|
TestGetDataJob(svr,zh,REPS){}
|
||||||
|
virtual TestJob* clone() const {
|
||||||
|
return new TestConcurrentOpWithDisconnectJob(svr_,zh_);
|
||||||
|
}
|
||||||
|
virtual void validate(const char* file, int line) const{
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE_LOC("ZCONNECTIONLOSS != rc",(int)ZCONNECTIONLOSS,rc_,file,line);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// this test is not 100% accurate in a sense it may not detect all error cases.
|
||||||
|
// TODO: I can't think of a test that is 100% accurate and doesn't interfere
|
||||||
|
// with the code being tested (in terms of introducing additional
|
||||||
|
// implicit synchronization points)
|
||||||
|
void testOperationsAndDisconnectConcurrently1()
|
||||||
|
{
|
||||||
|
for(int counter=0; counter<50; counter++){
|
||||||
|
//TEST_TRACE("Loop count %d",counter);
|
||||||
|
// frozen time -- no timeouts and no pings
|
||||||
|
Mock_gettimeofday timeMock;
|
||||||
|
|
||||||
|
ZookeeperServer zkServer;
|
||||||
|
Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
|
||||||
|
// must call zookeeper_close() while all the mocks are in the scope!
|
||||||
|
CloseFinally guard(&zh);
|
||||||
|
|
||||||
|
zh=zookeeper_init("localhost:2121",watcher,10000,TEST_CLIENT_ID,0,0);
|
||||||
|
CPPUNIT_ASSERT(zh!=0);
|
||||||
|
// make sure the client has connected
|
||||||
|
CPPUNIT_ASSERT(ensureCondition(ClientConnected(zh),1000)<1000);
|
||||||
|
|
||||||
|
TestJobManager jmgr(TestConcurrentOpWithDisconnectJob(&zkServer,zh),10);
|
||||||
|
jmgr.startJobsImmediately();
|
||||||
|
// let everything startup before we shutdown the server
|
||||||
|
millisleep(4);
|
||||||
|
// reconnect attempts will start failing immediately
|
||||||
|
zkServer.setServerDown(0);
|
||||||
|
// next recv call will return 0
|
||||||
|
zkServer.setConnectionLost();
|
||||||
|
jmgr.wait();
|
||||||
|
VALIDATE_JOBS(jmgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// call zoo_aget() in the multithreaded mode
|
||||||
|
void testAsyncGetOperation()
|
||||||
|
{
|
||||||
|
Mock_gettimeofday timeMock;
|
||||||
|
|
||||||
|
ZookeeperServer zkServer;
|
||||||
|
Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
|
||||||
|
// must call zookeeper_close() while all the mocks are in the scope!
|
||||||
|
CloseFinally guard(&zh);
|
||||||
|
|
||||||
|
zh=zookeeper_init("localhost:2121",watcher,10000,TEST_CLIENT_ID,0,0);
|
||||||
|
CPPUNIT_ASSERT(zh!=0);
|
||||||
|
// make sure the client has connected
|
||||||
|
CPPUNIT_ASSERT(ensureCondition(ClientConnected(zh),1000)<1000);
|
||||||
|
|
||||||
|
AsyncGetOperationCompletion res1;
|
||||||
|
zkServer.addOperationResponse(new ZooGetResponse("1",1));
|
||||||
|
int rc=zoo_aget(zh,"/x/y/1",0,asyncCompletion,&res1);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(ensureCondition(res1,1000)<1000);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,res1.rc_);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(string("1"),res1.value_);
|
||||||
|
}
|
||||||
|
class ChangeNodeWatcher: public WatcherAction{
|
||||||
|
public:
|
||||||
|
ChangeNodeWatcher():changed_(false){}
|
||||||
|
virtual void onNodeValueChanged(zhandle_t*,const char* path){
|
||||||
|
synchronized(mx_);
|
||||||
|
changed_=true;
|
||||||
|
if(path!=0) path_=path;
|
||||||
|
}
|
||||||
|
// this predicate checks if CHANGE_EVENT event type was triggered, unlike
|
||||||
|
// the isWatcherTriggered() that returns true whenever a watcher is triggered
|
||||||
|
// regardless of the event type
|
||||||
|
SyncedBoolCondition isNodeChangedTriggered() const{
|
||||||
|
return SyncedBoolCondition(changed_,mx_);
|
||||||
|
}
|
||||||
|
bool changed_;
|
||||||
|
string path_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AsyncWatcherCompletion: public AsyncCompletion{
|
||||||
|
public:
|
||||||
|
AsyncWatcherCompletion(ZookeeperServer& zkServer):zkServer_(zkServer){}
|
||||||
|
virtual void statCompl(int rc, const Stat *stat){
|
||||||
|
// we received a server response, now enqueue a watcher event
|
||||||
|
// to trigger the watcher
|
||||||
|
zkServer_.addRecvResponse(new ZNodeEvent(ZOO_CHANGED_EVENT,"/x/y/z"));
|
||||||
|
}
|
||||||
|
ZookeeperServer& zkServer_;
|
||||||
|
};
|
||||||
|
// verify that async watcher is called for znode events (CREATED, DELETED etc.)
|
||||||
|
void testAsyncWatcher1(){
|
||||||
|
Mock_gettimeofday timeMock;
|
||||||
|
|
||||||
|
ZookeeperServer zkServer;
|
||||||
|
Mock_poll pollMock(&zkServer,ZookeeperServer::FD);
|
||||||
|
// must call zookeeper_close() while all the mocks are in the scope!
|
||||||
|
CloseFinally guard(&zh);
|
||||||
|
|
||||||
|
ChangeNodeWatcher action;
|
||||||
|
zh=zookeeper_init("localhost:2121",activeWatcher,10000,
|
||||||
|
TEST_CLIENT_ID,&action,0);
|
||||||
|
CPPUNIT_ASSERT(zh!=0);
|
||||||
|
// make sure the client has connected
|
||||||
|
CPPUNIT_ASSERT(ensureCondition(ClientConnected(zh),1000)<1000);
|
||||||
|
|
||||||
|
// set the watcher
|
||||||
|
AsyncWatcherCompletion completion(zkServer);
|
||||||
|
// prepare a response for the zoo_aexists() request
|
||||||
|
zkServer.addOperationResponse(new ZooStatResponse);
|
||||||
|
int rc=zoo_aexists(zh,"/x/y/z",1,asyncCompletion,&completion);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(ensureCondition(action.isNodeChangedTriggered(),1000)<1000);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(string("/x/y/z"),action.path_);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
CPPUNIT_TEST_SUITE_REGISTRATION(Zookeeper_operations);
|
153
zookeeper-client/zookeeper-client-c/tests/TestReadOnlyClient.cc
Normal file
153
zookeeper-client/zookeeper-client-c/tests/TestReadOnlyClient.cc
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cppunit/extensions/HelperMacros.h>
|
||||||
|
#include "CppAssertHelper.h"
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <zookeeper.h>
|
||||||
|
|
||||||
|
#include "Util.h"
|
||||||
|
#include "WatchUtil.h"
|
||||||
|
|
||||||
|
#ifdef THREADED
|
||||||
|
class Zookeeper_readOnly : public CPPUNIT_NS::TestFixture {
|
||||||
|
CPPUNIT_TEST_SUITE(Zookeeper_readOnly);
|
||||||
|
CPPUNIT_TEST(testReadOnly);
|
||||||
|
#ifdef HAVE_OPENSSL_H
|
||||||
|
CPPUNIT_TEST(testReadOnlyWithSSL);
|
||||||
|
#endif
|
||||||
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
|
static void watcher(zhandle_t* zh, int type, int state,
|
||||||
|
const char* path, void* v) {
|
||||||
|
watchctx_t *ctx = (watchctx_t*)v;
|
||||||
|
|
||||||
|
if (state==ZOO_CONNECTED_STATE || state==ZOO_READONLY_STATE) {
|
||||||
|
ctx->connected = true;
|
||||||
|
} else {
|
||||||
|
ctx->connected = false;
|
||||||
|
}
|
||||||
|
if (type != ZOO_SESSION_EVENT) {
|
||||||
|
evt_t evt;
|
||||||
|
evt.path = path;
|
||||||
|
evt.type = type;
|
||||||
|
ctx->putEvent(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *logfile;
|
||||||
|
public:
|
||||||
|
|
||||||
|
Zookeeper_readOnly() {
|
||||||
|
logfile = openlogfile("Zookeeper_readOnly");
|
||||||
|
}
|
||||||
|
|
||||||
|
~Zookeeper_readOnly() {
|
||||||
|
if (logfile) {
|
||||||
|
fflush(logfile);
|
||||||
|
fclose(logfile);
|
||||||
|
logfile = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setUp() {
|
||||||
|
zoo_set_log_stream(logfile);
|
||||||
|
zoo_set_debug_level(ZOO_LOG_LEVEL_DEBUG);
|
||||||
|
}
|
||||||
|
|
||||||
|
void startReadOnly() {
|
||||||
|
char cmd[1024];
|
||||||
|
sprintf(cmd, "%s startCleanReadOnly", ZKSERVER_CMD);
|
||||||
|
CPPUNIT_ASSERT(system(cmd) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stopPeer() {
|
||||||
|
char cmd[1024];
|
||||||
|
sprintf(cmd, "%s stop", ZKSERVER_CMD);
|
||||||
|
CPPUNIT_ASSERT(system(cmd) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
zhandle_t* connectReadOnly(const char *address, watchctx_t *watch) {
|
||||||
|
zhandle_t* zh = zookeeper_init(address, watcher, 10000, NULL, watch, ZOO_READONLY);
|
||||||
|
watch->zh = zh;
|
||||||
|
CPPUNIT_ASSERT(zh != 0);
|
||||||
|
sleep(1);
|
||||||
|
return zh;
|
||||||
|
}
|
||||||
|
|
||||||
|
void assertCanRead(zhandle_t* zh, const char *znode_path) {
|
||||||
|
int len = 1024;
|
||||||
|
char buf[len];
|
||||||
|
int res = zoo_get(zh, znode_path, 0, buf, &len, 0);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
void assertCanNotWrite(zhandle_t* zh, const char *znode_path) {
|
||||||
|
char path[1024];
|
||||||
|
char buf[1024];
|
||||||
|
int res = zoo_create(zh, znode_path, buf, 10, &ZOO_OPEN_ACL_UNSAFE, 0, path, 512);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZNOTREADONLY, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testReadOnly()
|
||||||
|
{
|
||||||
|
startReadOnly();
|
||||||
|
|
||||||
|
watchctx_t watch;
|
||||||
|
zhandle_t* zh = connectReadOnly("localhost:22181", &watch);
|
||||||
|
|
||||||
|
assertCanRead(zh, "/");
|
||||||
|
|
||||||
|
assertCanNotWrite(zh, "/test");
|
||||||
|
|
||||||
|
stopPeer();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_OPENSSL_H
|
||||||
|
|
||||||
|
zhandle_t* connectReadOnlySSL(const char *address, const char *certs, watchctx_t *watch) {
|
||||||
|
zhandle_t* zh = zookeeper_init_ssl(address, certs, watcher, 10000, NULL, watch, ZOO_READONLY);
|
||||||
|
watch->zh = zh;
|
||||||
|
CPPUNIT_ASSERT(zh != 0);
|
||||||
|
sleep(1);
|
||||||
|
return zh;
|
||||||
|
}
|
||||||
|
|
||||||
|
void testReadOnlyWithSSL() {
|
||||||
|
startReadOnly();
|
||||||
|
|
||||||
|
watchctx_t watch;
|
||||||
|
zhandle_t* zh = connectReadOnlySSL("localhost:22281",
|
||||||
|
"/tmp/certs/server.crt,/tmp/certs/client.crt,/tmp/certs/clientkey.pem,password",
|
||||||
|
&watch);
|
||||||
|
|
||||||
|
assertCanRead(zh, "/");
|
||||||
|
|
||||||
|
assertCanNotWrite(zh, "/testSSL");
|
||||||
|
|
||||||
|
stopPeer();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
CPPUNIT_TEST_SUITE_REGISTRATION(Zookeeper_readOnly);
|
||||||
|
#endif
|
697
zookeeper-client/zookeeper-client-c/tests/TestReconfig.cc
Normal file
697
zookeeper-client/zookeeper-client-c/tests/TestReconfig.cc
Normal file
@ -0,0 +1,697 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cppunit/extensions/HelperMacros.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <exception>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <src/addrvec.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "Util.h"
|
||||||
|
#include "LibCMocks.h"
|
||||||
|
#include "ZKMocks.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
static const int portOffset = 2000;
|
||||||
|
|
||||||
|
class Client
|
||||||
|
{
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Member variables
|
||||||
|
zhandle_t *zh;
|
||||||
|
unsigned int seed;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Create a client with given connection host string and add to our internal
|
||||||
|
* vector of clients. These are disconnected and cleaned up in tearDown().
|
||||||
|
*/
|
||||||
|
Client(const string hosts, unsigned int seed) :
|
||||||
|
seed((seed * seed) + 0xAFAFAFAF)
|
||||||
|
{
|
||||||
|
reSeed();
|
||||||
|
|
||||||
|
zh = zookeeper_init(hosts.c_str(),0,1000,0,0,0);
|
||||||
|
CPPUNIT_ASSERT(zh);
|
||||||
|
|
||||||
|
// Set the flag to disable ZK from reconnecting to a different server.
|
||||||
|
// Our reconfig test case will do explicit server shuffling through
|
||||||
|
// zoo_cycle_next_server, and the reconnection attempts would interfere
|
||||||
|
// with the server states the tests cases assume.
|
||||||
|
zh->disable_reconnection_attempt = 1;
|
||||||
|
reSeed();
|
||||||
|
|
||||||
|
cycleNextServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void close()
|
||||||
|
{
|
||||||
|
zookeeper_close(zh);
|
||||||
|
zh = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isReconfig()
|
||||||
|
{
|
||||||
|
return zh->reconfig != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* re-seed this client with it's own previously generated seed so its
|
||||||
|
* random choices are unique and separate from the other clients
|
||||||
|
*/
|
||||||
|
void reSeed()
|
||||||
|
{
|
||||||
|
srandom(seed);
|
||||||
|
srand48(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the server that this client is currently connected to.
|
||||||
|
*/
|
||||||
|
string getServer()
|
||||||
|
{
|
||||||
|
const char* addrstring = zoo_get_current_server(zh);
|
||||||
|
return string(addrstring);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the server this client is currently connected to with no port
|
||||||
|
* specification.
|
||||||
|
*/
|
||||||
|
string getServerNoPort()
|
||||||
|
{
|
||||||
|
string addrstring = getServer();
|
||||||
|
size_t found = addrstring.find_last_of(":");
|
||||||
|
CPPUNIT_ASSERT(found != string::npos);
|
||||||
|
|
||||||
|
// ipv6 address case (to remove leading and trailing bracket)
|
||||||
|
if (addrstring.find("[") != string::npos)
|
||||||
|
{
|
||||||
|
return addrstring.substr(1, found-2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return addrstring.substr(0, found);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the port of the server this client is currently connected to.
|
||||||
|
*/
|
||||||
|
uint32_t getServerPort()
|
||||||
|
{
|
||||||
|
string addrstring = getServer();
|
||||||
|
|
||||||
|
size_t found = addrstring.find_last_of(":");
|
||||||
|
CPPUNIT_ASSERT(found != string::npos);
|
||||||
|
|
||||||
|
string portStr = addrstring.substr(found+1);
|
||||||
|
|
||||||
|
stringstream ss(portStr);
|
||||||
|
uint32_t port;
|
||||||
|
ss >> port;
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(port >= portOffset);
|
||||||
|
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cycle to the next available server on the next connect attempt. It also
|
||||||
|
* calls into getServer (above) to return the server connected to.
|
||||||
|
*/
|
||||||
|
string cycleNextServer()
|
||||||
|
{
|
||||||
|
zoo_cycle_next_server(zh);
|
||||||
|
return getServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cycleUntilServer(const string requested)
|
||||||
|
{
|
||||||
|
// Call cycleNextServer until the one it's connected to is the one
|
||||||
|
// specified (disregarding port).
|
||||||
|
string first;
|
||||||
|
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
string next = cycleNextServer();
|
||||||
|
if (first.empty())
|
||||||
|
{
|
||||||
|
first = next;
|
||||||
|
}
|
||||||
|
// Else we've looped around!
|
||||||
|
else if (first == next)
|
||||||
|
{
|
||||||
|
CPPUNIT_ASSERT(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strip port off
|
||||||
|
string server = getServerNoPort();
|
||||||
|
|
||||||
|
// If it matches the requested host we're now 'connected' to the right host
|
||||||
|
if (server == requested)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set servers for this client.
|
||||||
|
*/
|
||||||
|
void setServers(const string new_hosts)
|
||||||
|
{
|
||||||
|
int rc = zoo_set_servers(zh, new_hosts.c_str());
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set servers for this client and validate reconfig value matches expected.
|
||||||
|
*/
|
||||||
|
void setServersAndVerifyReconfig(const string new_hosts, bool is_reconfig)
|
||||||
|
{
|
||||||
|
setServers(new_hosts);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(is_reconfig, isReconfig());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the server list this client is connecting to AND if this requires
|
||||||
|
* the client to be reconfigured (as dictated by internal client policy)
|
||||||
|
* then it will trigger a call to cycleNextServer.
|
||||||
|
*/
|
||||||
|
void setServersAndCycleIfNeeded(const string new_hosts)
|
||||||
|
{
|
||||||
|
setServers(new_hosts);
|
||||||
|
if (isReconfig())
|
||||||
|
{
|
||||||
|
cycleNextServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Zookeeper_reconfig : public CPPUNIT_NS::TestFixture
|
||||||
|
{
|
||||||
|
CPPUNIT_TEST_SUITE(Zookeeper_reconfig);
|
||||||
|
|
||||||
|
// Test cases
|
||||||
|
CPPUNIT_TEST(testcycleNextServer);
|
||||||
|
CPPUNIT_TEST(testMigrateOrNot);
|
||||||
|
CPPUNIT_TEST(testMigrationCycle);
|
||||||
|
CPPUNIT_TEST(testAddrVecContainsIPv4);
|
||||||
|
#ifdef AF_INET6
|
||||||
|
CPPUNIT_TEST(testAddrVecContainsIPv6);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// In threaded mode each 'create' is a thread -- it's not practical to create
|
||||||
|
// 10,000 threads to test load balancing. The load balancing code can easily
|
||||||
|
// be tested in single threaded mode as concurrency doesn't affect the algorithm.
|
||||||
|
#ifndef THREADED
|
||||||
|
CPPUNIT_TEST(testMigrateProbability);
|
||||||
|
CPPUNIT_TEST(testLoadBalancing);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
|
FILE *logfile;
|
||||||
|
|
||||||
|
double slackPercent;
|
||||||
|
static const int numClients = 10000;
|
||||||
|
static const int portOffset = 2000;
|
||||||
|
|
||||||
|
vector<Client> clients;
|
||||||
|
vector<uint32_t> numClientsPerHost;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Zookeeper_reconfig() :
|
||||||
|
slackPercent(10.0)
|
||||||
|
{
|
||||||
|
logfile = openlogfile("Zookeeper_reconfig");
|
||||||
|
}
|
||||||
|
|
||||||
|
~Zookeeper_reconfig()
|
||||||
|
{
|
||||||
|
if (logfile)
|
||||||
|
{
|
||||||
|
fflush(logfile);
|
||||||
|
fclose(logfile);
|
||||||
|
logfile = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setUp()
|
||||||
|
{
|
||||||
|
zoo_set_log_stream(logfile);
|
||||||
|
zoo_deterministic_conn_order(1);
|
||||||
|
|
||||||
|
numClientsPerHost.resize(numClients);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tearDown()
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < clients.size(); i++)
|
||||||
|
{
|
||||||
|
clients.at(i).close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a client with given connection host string and add to our internal
|
||||||
|
* vector of clients. These are disconnected and cleaned up in tearDown().
|
||||||
|
*/
|
||||||
|
Client& createClient(const string hosts)
|
||||||
|
{
|
||||||
|
Client client(hosts, clients.size());
|
||||||
|
clients.push_back(client);
|
||||||
|
|
||||||
|
return clients.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as createClient(hosts) only it takes a specific host that this client
|
||||||
|
* should simulate being connected to.
|
||||||
|
*/
|
||||||
|
Client& createClient(const string hosts, const string host)
|
||||||
|
{
|
||||||
|
// Ensure requested host is in the list
|
||||||
|
size_t found = hosts.find(host);
|
||||||
|
CPPUNIT_ASSERT(found != hosts.npos);
|
||||||
|
|
||||||
|
Client client(hosts, clients.size());
|
||||||
|
client.cycleUntilServer(host);
|
||||||
|
clients.push_back(client);
|
||||||
|
|
||||||
|
return clients.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a connection host list starting at 'start' and stopping at 'stop'
|
||||||
|
* where start >= stop. This creates a connection string with host:port pairs
|
||||||
|
* separated by commas. The given 'octet' is the starting octet that is used
|
||||||
|
* as the last octet in the host's IP. This is decremented on each iteration.
|
||||||
|
* Each port will be portOffset + octet.
|
||||||
|
*/
|
||||||
|
string createHostList(uint32_t start, uint32_t stop = 1, uint32_t octet = 0)
|
||||||
|
{
|
||||||
|
if (octet == 0)
|
||||||
|
{
|
||||||
|
octet = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
stringstream ss;
|
||||||
|
|
||||||
|
for (uint32_t i = start; i >= stop; i--, octet--)
|
||||||
|
{
|
||||||
|
ss << "10.10.10." << octet << ":" << portOffset + octet;
|
||||||
|
|
||||||
|
if (i > stop)
|
||||||
|
{
|
||||||
|
ss << ", ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the lower bound of the number of clients per server that we expect
|
||||||
|
* based on the probabilistic load balancing algorithm implemented by the
|
||||||
|
* client code.
|
||||||
|
*/
|
||||||
|
double lowerboundClientsPerServer(int numClients, int numServers)
|
||||||
|
{
|
||||||
|
return (1 - slackPercent/100.0) * numClients / numServers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the upper bound of the number of clients per server that we expect
|
||||||
|
* based on the probabilistic load balancing algorithm implemented by the
|
||||||
|
* client code.
|
||||||
|
*/
|
||||||
|
double upperboundClientsPerServer(int numClients, int numServers)
|
||||||
|
{
|
||||||
|
return (1 + slackPercent/100.0) * numClients / numServers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update all the clients to use a new list of servers. This will also cause
|
||||||
|
* the client to cycle to the next server as needed (e.g. due to a reconfig).
|
||||||
|
* It then updates the number of clients connected to the server based on
|
||||||
|
* this change.
|
||||||
|
*
|
||||||
|
* Afterwards it validates that all of the servers have the correct amount of
|
||||||
|
* clients based on the probabilistic load balancing algorithm.
|
||||||
|
*/
|
||||||
|
void updateAllClientsAndServers(int start, int stop = 1)
|
||||||
|
{
|
||||||
|
string newServers = createHostList(start, stop);
|
||||||
|
int numServers = start - stop + 1;
|
||||||
|
|
||||||
|
for (int i = 0; i < numClients; i++) {
|
||||||
|
|
||||||
|
Client &client = clients.at(i);
|
||||||
|
client.reSeed();
|
||||||
|
|
||||||
|
client.setServersAndCycleIfNeeded(newServers);
|
||||||
|
numClientsPerHost.at(client.getServerPort() - portOffset - 1)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int offset = stop - 1;
|
||||||
|
for (int index = offset; index < numServers; index++) {
|
||||||
|
|
||||||
|
if (numClientsPerHost.at(index) > upperboundClientsPerServer(numClients, numServers))
|
||||||
|
{
|
||||||
|
cout << "INDEX=" << index << " too many -- actual=" << numClientsPerHost.at(index)
|
||||||
|
<< " expected=" << upperboundClientsPerServer(numClients, numServers) << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(numClientsPerHost.at(index) <= upperboundClientsPerServer(numClients, numServers));
|
||||||
|
|
||||||
|
if (numClientsPerHost.at(index) < lowerboundClientsPerServer(numClients, numServers))
|
||||||
|
{
|
||||||
|
cout << "INDEX=" << index << " too few -- actual=" << numClientsPerHost.at(index)
|
||||||
|
<< " expected=" << lowerboundClientsPerServer(numClients, numServers) << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(numClientsPerHost.at(index) >= lowerboundClientsPerServer(numClients, numServers));
|
||||||
|
numClientsPerHost.at(index) = 0; // prepare for next test
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------*
|
||||||
|
* TESTCASES
|
||||||
|
*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Very basic sunny day test to ensure basic functionality of zoo_set_servers
|
||||||
|
* and zoo_cycle_next_server.
|
||||||
|
*/
|
||||||
|
void testcycleNextServer()
|
||||||
|
{
|
||||||
|
const string initial_hosts = createHostList(10); // 2010..2001
|
||||||
|
const string new_hosts = createHostList(4); // 2004..2001
|
||||||
|
|
||||||
|
Client &client = createClient(initial_hosts);
|
||||||
|
|
||||||
|
client.setServersAndVerifyReconfig(new_hosts, true);
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
string next = client.cycleNextServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the migration policy implicit within the probabilistic load balancing
|
||||||
|
* algorithm the Client implements. Tests all the corner cases whereby the
|
||||||
|
* list of servers is decreased, increased, and stays the same. Also combines
|
||||||
|
* various combinations of the currently connected server being in the new
|
||||||
|
* configuration and not.
|
||||||
|
*/
|
||||||
|
void testMigrateOrNot()
|
||||||
|
{
|
||||||
|
const string initial_hosts = createHostList(4); // 2004..2001
|
||||||
|
|
||||||
|
Client &client = createClient(initial_hosts, "10.10.10.3");
|
||||||
|
|
||||||
|
// Ensemble size decreasing, my server is in the new list
|
||||||
|
client.setServersAndVerifyReconfig(createHostList(3), false);
|
||||||
|
|
||||||
|
// Ensemble size decreasing, my server is NOT in the new list
|
||||||
|
client.setServersAndVerifyReconfig(createHostList(2), true);
|
||||||
|
|
||||||
|
// Ensemble size stayed the same, my server is NOT in the new list
|
||||||
|
client.setServersAndVerifyReconfig(createHostList(2), true);
|
||||||
|
|
||||||
|
// Ensemble size increased, my server is not in the new ensemble
|
||||||
|
client.setServers(createHostList(4));
|
||||||
|
client.cycleUntilServer("10.10.10.1");
|
||||||
|
client.setServersAndVerifyReconfig(createHostList(7,2), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This tests that as a client is in reconfig mode it will properly try to
|
||||||
|
* connect to all the new servers first. Then it will try to connect to all
|
||||||
|
* the 'old' servers that are staying in the new configuration. Finally it
|
||||||
|
* will fallback to the normal behavior of trying servers in round-robin.
|
||||||
|
*/
|
||||||
|
void testMigrationCycle()
|
||||||
|
{
|
||||||
|
int num_initial = 4;
|
||||||
|
const string initial_hosts = createHostList(num_initial); // {2004..2001}
|
||||||
|
|
||||||
|
int num_new = 10;
|
||||||
|
string new_hosts = createHostList(12, 3); // {2012..2003}
|
||||||
|
|
||||||
|
// servers from the old list that appear in the new list {2004..2003}
|
||||||
|
int num_staying = 2;
|
||||||
|
string oldStaying = createHostList(4, 3);
|
||||||
|
|
||||||
|
// servers in the new list that are not in the old list {2012..2005}
|
||||||
|
int num_coming = 8;
|
||||||
|
string newComing = createHostList(12, 5);
|
||||||
|
|
||||||
|
// Ensemble in increasing in size, my server is not in the new ensemble
|
||||||
|
// load on the old servers must be decreased, so must connect to one of
|
||||||
|
// new servers (pNew = 1)
|
||||||
|
Client &client = createClient(initial_hosts, "10.10.10.1");
|
||||||
|
client.setServersAndVerifyReconfig(new_hosts, true);
|
||||||
|
|
||||||
|
// Since we're in reconfig mode, next connect should be from new list
|
||||||
|
// We should try all the new servers *BEFORE* trying any old servers
|
||||||
|
string seen;
|
||||||
|
for (int i = 0; i < num_coming; i++) {
|
||||||
|
client.cycleNextServer();
|
||||||
|
|
||||||
|
// Assert next server is in the 'new' list
|
||||||
|
stringstream next;
|
||||||
|
next << client.getServerNoPort() << ":" << client.getServerPort();
|
||||||
|
size_t found = newComing.find(next.str());
|
||||||
|
CPPUNIT_ASSERT_MESSAGE(next.str() + " not in newComing list",
|
||||||
|
found != string::npos);
|
||||||
|
|
||||||
|
// Assert not in seen list then append
|
||||||
|
found = seen.find(next.str());
|
||||||
|
CPPUNIT_ASSERT_MESSAGE(next.str() + " in seen list",
|
||||||
|
found == string::npos);
|
||||||
|
seen += found + ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now it should start connecting to the old servers
|
||||||
|
seen.clear();
|
||||||
|
for (int i = 0; i < num_staying; i++) {
|
||||||
|
client.cycleNextServer();
|
||||||
|
|
||||||
|
// Assert it's in the old list
|
||||||
|
stringstream next;
|
||||||
|
next << client.getServerNoPort() << ":" << client.getServerPort();
|
||||||
|
size_t found = oldStaying.find(next.str());
|
||||||
|
CPPUNIT_ASSERT(found != string::npos);
|
||||||
|
|
||||||
|
// Assert not in seen list then append
|
||||||
|
found = seen.find(next.str());
|
||||||
|
CPPUNIT_ASSERT(found == string::npos);
|
||||||
|
seen += found + ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOW it goes back to normal as we've tried all the new and old
|
||||||
|
string first = client.cycleNextServer();
|
||||||
|
for (int i = 0; i < num_new - 1; i++) {
|
||||||
|
client.cycleNextServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(first, client.cycleNextServer());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the migration probability to ensure that it conforms to our expected
|
||||||
|
* lower and upper bounds of the number of clients per server as we are
|
||||||
|
* reconfigured.
|
||||||
|
*
|
||||||
|
* In this case, the list of servers is increased and the client's server is
|
||||||
|
* in the new list. Whether to move or not depends on the difference of
|
||||||
|
* server sizes with probability 1 - |old|/|new| the client disconnects.
|
||||||
|
*
|
||||||
|
* In the test below 1-9/10 = 1/10 chance of disconnecting
|
||||||
|
*/
|
||||||
|
void testMigrateProbability()
|
||||||
|
{
|
||||||
|
const string initial_hosts = createHostList(9); // 10.10.10.9:2009...10.10.10.1:2001
|
||||||
|
string new_hosts = createHostList(10); // 10.10.10.10:2010...10.10.10.1:2001
|
||||||
|
|
||||||
|
uint32_t numDisconnects = 0;
|
||||||
|
for (int i = 0; i < numClients; i++) {
|
||||||
|
Client &client = createClient(initial_hosts, "10.10.10.3");
|
||||||
|
client.setServers(new_hosts);
|
||||||
|
if (client.isReconfig())
|
||||||
|
{
|
||||||
|
numDisconnects++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// should be numClients/10 in expectation, we test that it's numClients/10 +- slackPercent
|
||||||
|
CPPUNIT_ASSERT(numDisconnects < upperboundClientsPerServer(numClients, 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the probabilistic load balancing algorithm implemented by the Client
|
||||||
|
* code.
|
||||||
|
*
|
||||||
|
* Test strategy:
|
||||||
|
*
|
||||||
|
* (1) Start with 9 servers and 10,000 clients. Remove a server, update
|
||||||
|
* everything, and ensure that the clients are redistributed properly.
|
||||||
|
*
|
||||||
|
* (2) Remove two more nodes and repeat the same validations of proper client
|
||||||
|
* redistribution. Ensure no clients are connected to the two removed
|
||||||
|
* nodes.
|
||||||
|
*
|
||||||
|
* (3) Remove the first server in the list and simultaneously add the three
|
||||||
|
* previously removed servers. Ensure everything is redistributed and
|
||||||
|
* no clients are connected to the one missing node.
|
||||||
|
*
|
||||||
|
* (4) Add the one missing server back into the mix and validate.
|
||||||
|
*/
|
||||||
|
void testLoadBalancing()
|
||||||
|
{
|
||||||
|
zoo_deterministic_conn_order(0);
|
||||||
|
|
||||||
|
uint32_t numServers = 9;
|
||||||
|
const string initial_hosts = createHostList(numServers); // 10.10.10.9:2009...10.10.10.1:2001
|
||||||
|
|
||||||
|
// Create connections to servers
|
||||||
|
for (int i = 0; i < numClients; i++) {
|
||||||
|
Client &client = createClient(initial_hosts);
|
||||||
|
numClientsPerHost.at(client.getServerPort() - portOffset - 1)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < numServers; i++) {
|
||||||
|
CPPUNIT_ASSERT(numClientsPerHost.at(i) <= upperboundClientsPerServer(numClients, numServers));
|
||||||
|
CPPUNIT_ASSERT(numClientsPerHost.at(i) >= lowerboundClientsPerServer(numClients, numServers));
|
||||||
|
numClientsPerHost.at(i) = 0; // prepare for next test
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove last server
|
||||||
|
numServers = 8;
|
||||||
|
updateAllClientsAndServers(numServers);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((uint32_t)0, numClientsPerHost.at(numServers));
|
||||||
|
|
||||||
|
// Remove two more nodes
|
||||||
|
numServers = 6;
|
||||||
|
updateAllClientsAndServers(numServers);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((uint32_t)0, numClientsPerHost.at(numServers));
|
||||||
|
CPPUNIT_ASSERT_EQUAL((uint32_t)0, numClientsPerHost.at(numServers+1));
|
||||||
|
CPPUNIT_ASSERT_EQUAL((uint32_t)0, numClientsPerHost.at(numServers+2));
|
||||||
|
|
||||||
|
// remove host 0 (first one in list) and add back 6, 7, and 8
|
||||||
|
numServers = 8;
|
||||||
|
updateAllClientsAndServers(numServers, 1);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((uint32_t)0, numClientsPerHost.at(0));
|
||||||
|
|
||||||
|
// add back host number 0
|
||||||
|
numServers = 9;
|
||||||
|
updateAllClientsAndServers(numServers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This tests that client can detect server's ipv4 address change.
|
||||||
|
*
|
||||||
|
* (1) We generate some address and put in addr, which saddr point to
|
||||||
|
* (2) Add all addresses that differ by one bit from the source
|
||||||
|
* (3) Add same address, but set ipv6 protocol
|
||||||
|
* (4) Ensure, that our address is not equal to any of generated,
|
||||||
|
* and that it equals to itself
|
||||||
|
*/
|
||||||
|
void testAddrVecContainsIPv4() {
|
||||||
|
addrvec_t vec;
|
||||||
|
addrvec_init(&vec);
|
||||||
|
|
||||||
|
sockaddr_storage addr;
|
||||||
|
sockaddr_in* saddr = (sockaddr_in*)&addr;
|
||||||
|
saddr->sin_family = AF_INET;
|
||||||
|
saddr->sin_port = htons((u_short)1234);
|
||||||
|
saddr->sin_addr.s_addr = INADDR_ANY;
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(sizeof(saddr->sin_addr.s_addr) == 4);
|
||||||
|
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
saddr->sin_addr.s_addr ^= (1 << i);
|
||||||
|
addrvec_append(&vec, &addr);
|
||||||
|
saddr->sin_addr.s_addr ^= (1 << i);
|
||||||
|
}
|
||||||
|
|
||||||
|
saddr->sin_family = AF_INET6;
|
||||||
|
addrvec_append(&vec, &addr);
|
||||||
|
saddr->sin_family = AF_INET;
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(!addrvec_contains(&vec, &addr));
|
||||||
|
addrvec_append(&vec, &addr);
|
||||||
|
CPPUNIT_ASSERT(addrvec_contains(&vec, &addr));
|
||||||
|
addrvec_free(&vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This tests that client can detect server's ipv6 address change.
|
||||||
|
*
|
||||||
|
* Same logic as in previous testAddrVecContainsIPv4 method,
|
||||||
|
* but we keep in mind, that ipv6 is 128-bit long.
|
||||||
|
*/
|
||||||
|
#ifdef AF_INET6
|
||||||
|
void testAddrVecContainsIPv6() {
|
||||||
|
addrvec_t vec;
|
||||||
|
addrvec_init(&vec);
|
||||||
|
|
||||||
|
sockaddr_storage addr;
|
||||||
|
sockaddr_in6* saddr = (sockaddr_in6*)&addr;
|
||||||
|
saddr->sin6_family = AF_INET6;
|
||||||
|
saddr->sin6_port = htons((u_short)1234);
|
||||||
|
saddr->sin6_addr = in6addr_any;
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(sizeof(saddr->sin6_addr.s6_addr) == 16);
|
||||||
|
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
for (int j = 0; j < 8; j++) {
|
||||||
|
saddr->sin6_addr.s6_addr[i] ^= (1 << j);
|
||||||
|
addrvec_append(&vec, &addr);
|
||||||
|
saddr->sin6_addr.s6_addr[i] ^= (1 << j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
saddr->sin6_family = AF_INET;
|
||||||
|
addrvec_append(&vec, &addr);
|
||||||
|
saddr->sin6_family = AF_INET6;
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(!addrvec_contains(&vec, &addr));
|
||||||
|
addrvec_append(&vec, &addr);
|
||||||
|
CPPUNIT_ASSERT(addrvec_contains(&vec, &addr));
|
||||||
|
addrvec_free(&vec);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
CPPUNIT_TEST_SUITE_REGISTRATION(Zookeeper_reconfig);
|
420
zookeeper-client/zookeeper-client-c/tests/TestReconfigServer.cc
Normal file
420
zookeeper-client/zookeeper-client-c/tests/TestReconfigServer.cc
Normal file
@ -0,0 +1,420 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with this
|
||||||
|
* work for additional information regarding copyright ownership. The ASF
|
||||||
|
* licenses this file to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
#include <algorithm>
|
||||||
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
#include <utility>
|
||||||
|
#include <cppunit/extensions/HelperMacros.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "zookeeper.h"
|
||||||
|
|
||||||
|
#include "Util.h"
|
||||||
|
#include "ZooKeeperQuorumServer.h"
|
||||||
|
|
||||||
|
#ifdef THREADED
|
||||||
|
class TestReconfigServer : public CPPUNIT_NS::TestFixture {
|
||||||
|
CPPUNIT_TEST_SUITE(TestReconfigServer);
|
||||||
|
CPPUNIT_TEST(testNonIncremental);
|
||||||
|
CPPUNIT_TEST(testRemoveConnectedFollower);
|
||||||
|
CPPUNIT_TEST(testRemoveFollower);
|
||||||
|
CPPUNIT_TEST(testReconfigFailureWithoutAuth);
|
||||||
|
CPPUNIT_TEST(testReconfigFailureWithoutServerSuperuserPasswordConfigured);
|
||||||
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
|
public:
|
||||||
|
TestReconfigServer();
|
||||||
|
virtual ~TestReconfigServer();
|
||||||
|
void setUp();
|
||||||
|
void tearDown();
|
||||||
|
void testNonIncremental();
|
||||||
|
void testRemoveConnectedFollower();
|
||||||
|
void testRemoveFollower();
|
||||||
|
void testReconfigFailureWithoutAuth();
|
||||||
|
void testReconfigFailureWithoutServerSuperuserPasswordConfigured();
|
||||||
|
private:
|
||||||
|
static const uint32_t NUM_SERVERS;
|
||||||
|
FILE* logfile_;
|
||||||
|
std::vector<ZooKeeperQuorumServer*> cluster_;
|
||||||
|
int32_t getLeader();
|
||||||
|
std::vector<int32_t> getFollowers();
|
||||||
|
void parseConfig(char* buf, int len, std::vector<std::string>& servers,
|
||||||
|
std::string& version);
|
||||||
|
bool waitForConnected(zhandle_t* zh, uint32_t timeout_sec);
|
||||||
|
zhandle_t* connectFollowers(std::vector<int32_t> &followers);
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint32_t TestReconfigServer::NUM_SERVERS = 3;
|
||||||
|
|
||||||
|
TestReconfigServer::
|
||||||
|
TestReconfigServer() :
|
||||||
|
logfile_(openlogfile("TestReconfigServer")) {
|
||||||
|
zoo_set_log_stream(logfile_);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestReconfigServer::
|
||||||
|
~TestReconfigServer() {
|
||||||
|
if (logfile_) {
|
||||||
|
fflush(logfile_);
|
||||||
|
fclose(logfile_);
|
||||||
|
logfile_ = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestReconfigServer::
|
||||||
|
setUp() {
|
||||||
|
ZooKeeperQuorumServer::tConfigPairs configs;
|
||||||
|
configs.push_back(std::make_pair("reconfigEnabled", "true"));
|
||||||
|
cluster_ = ZooKeeperQuorumServer::getCluster(NUM_SERVERS, configs,
|
||||||
|
"SERVER_JVMFLAGS=-Dzookeeper.DigestAuthenticationProvider.superDigest=super:D/InIHSb7yEEbrWz8b9l71RjZJU="/* password is test */);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestReconfigServer::
|
||||||
|
tearDown() {
|
||||||
|
for (int i = 0; i < cluster_.size(); i++) {
|
||||||
|
delete cluster_[i];
|
||||||
|
}
|
||||||
|
cluster_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t TestReconfigServer::
|
||||||
|
getLeader() {
|
||||||
|
for (int32_t i = 0; i < cluster_.size(); i++) {
|
||||||
|
if (cluster_[i]->isLeader()) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int32_t> TestReconfigServer::
|
||||||
|
getFollowers() {
|
||||||
|
std::vector<int32_t> followers;
|
||||||
|
for (int32_t i = 0; i < cluster_.size(); i++) {
|
||||||
|
if (cluster_[i]->isFollower()) {
|
||||||
|
followers.push_back(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return followers;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestReconfigServer::
|
||||||
|
parseConfig(char* buf, int len, std::vector<std::string>& servers,
|
||||||
|
std::string& version) {
|
||||||
|
std::string config(buf, len);
|
||||||
|
std::stringstream ss(config);
|
||||||
|
std::string line;
|
||||||
|
std::string serverPrefix("server.");
|
||||||
|
std::string versionPrefix("version=");
|
||||||
|
servers.clear();
|
||||||
|
while(std::getline(ss, line, '\n')) {
|
||||||
|
if (line.compare(0, serverPrefix.size(), serverPrefix) == 0) {
|
||||||
|
servers.push_back(line);
|
||||||
|
} else if (line.compare(0, versionPrefix.size(), versionPrefix) == 0) {
|
||||||
|
version = line.substr(versionPrefix.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TestReconfigServer::
|
||||||
|
waitForConnected(zhandle_t* zh, uint32_t timeout_sec) {
|
||||||
|
for (uint32_t i = 0; i < timeout_sec; i++) {
|
||||||
|
if (zoo_state(zh) == ZOO_CONNECTED_STATE) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Connect to the leader.
|
||||||
|
* 2. Remove a follower using incremental reconfig.
|
||||||
|
* 3. Add the follower back using incremental reconfig.
|
||||||
|
*/
|
||||||
|
void TestReconfigServer::
|
||||||
|
testRemoveFollower() {
|
||||||
|
std::vector<std::string> servers;
|
||||||
|
std::string version;
|
||||||
|
struct Stat stat;
|
||||||
|
int len = 1024;
|
||||||
|
char buf[len];
|
||||||
|
|
||||||
|
// get config from leader.
|
||||||
|
int32_t leader = getLeader();
|
||||||
|
CPPUNIT_ASSERT(leader >= 0);
|
||||||
|
std::string host = cluster_[leader]->getHostPort();
|
||||||
|
zhandle_t* zk = zookeeper_init(host.c_str(), NULL, 10000, NULL, NULL, 0);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(true, waitForConnected(zk, 10));
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, zoo_getconfig(zk, 0, buf, &len, &stat));
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, zoo_add_auth(zk, "digest", "super:test", 10, NULL,(void*)ZOK));
|
||||||
|
// check if all the servers are listed in the config.
|
||||||
|
parseConfig(buf, len, servers, version);
|
||||||
|
// initially should be 1<<32, which is 0x100000000. This is the zxid
|
||||||
|
// of the first NEWLEADER message, used as the initial version
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("100000000"), version);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(NUM_SERVERS, (uint32_t)(servers.size()));
|
||||||
|
for (int i = 0; i < cluster_.size(); i++) {
|
||||||
|
CPPUNIT_ASSERT(std::find(servers.begin(), servers.end(),
|
||||||
|
cluster_[i]->getServerString()) != servers.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove a follower.
|
||||||
|
std::vector<int32_t> followers = getFollowers();
|
||||||
|
len = 1024;
|
||||||
|
CPPUNIT_ASSERT_EQUAL(NUM_SERVERS - 1,
|
||||||
|
(uint32_t)(followers.size()));
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << followers[0];
|
||||||
|
int rc = zoo_reconfig(zk, NULL, ss.str().c_str(), NULL, -1, buf, &len,
|
||||||
|
&stat);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
|
||||||
|
parseConfig(buf, len, servers, version);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("100000002"), version);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(NUM_SERVERS - 1, (uint32_t)(servers.size()));
|
||||||
|
for (int i = 0; i < cluster_.size(); i++) {
|
||||||
|
if (i == followers[0]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
CPPUNIT_ASSERT(std::find(servers.begin(), servers.end(),
|
||||||
|
cluster_[i]->getServerString()) != servers.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the follower back.
|
||||||
|
len = 1024;
|
||||||
|
std::string serverString = cluster_[followers[0]]->getServerString();
|
||||||
|
rc = zoo_reconfig(zk, serverString.c_str(), NULL, NULL, -1, buf, &len,
|
||||||
|
&stat);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
|
||||||
|
parseConfig(buf, len, servers, version);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(NUM_SERVERS, (uint32_t)(servers.size()));
|
||||||
|
for (int i = 0; i < cluster_.size(); i++) {
|
||||||
|
CPPUNIT_ASSERT(std::find(servers.begin(), servers.end(),
|
||||||
|
cluster_[i]->getServerString()) != servers.end());
|
||||||
|
}
|
||||||
|
zookeeper_close(zk);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Connect to the leader.
|
||||||
|
* 2. Remove a follower using non-incremental reconfig.
|
||||||
|
* 3. Add the follower back using non-incremental reconfig.
|
||||||
|
*/
|
||||||
|
void TestReconfigServer::
|
||||||
|
testNonIncremental() {
|
||||||
|
std::vector<std::string> servers;
|
||||||
|
std::string version;
|
||||||
|
struct Stat stat;
|
||||||
|
int len = 1024;
|
||||||
|
char buf[len];
|
||||||
|
|
||||||
|
// get config from leader.
|
||||||
|
int32_t leader = getLeader();
|
||||||
|
CPPUNIT_ASSERT(leader >= 0);
|
||||||
|
std::string host = cluster_[leader]->getHostPort();
|
||||||
|
zhandle_t* zk = zookeeper_init(host.c_str(), NULL, 10000, NULL, NULL, 0);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(true, waitForConnected(zk, 10));
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, zoo_getconfig(zk, 0, buf, &len, &stat));
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, zoo_add_auth(zk, "digest", "super:test", 10, NULL,(void*)ZOK));
|
||||||
|
|
||||||
|
// check if all the servers are listed in the config.
|
||||||
|
parseConfig(buf, len, servers, version);
|
||||||
|
// initially should be 1<<32, which is 0x100000000. This is the zxid
|
||||||
|
// of the first NEWLEADER message, used as the initial version
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("100000000"), version);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(NUM_SERVERS, (uint32_t)(servers.size()));
|
||||||
|
for (int i = 0; i < cluster_.size(); i++) {
|
||||||
|
CPPUNIT_ASSERT(std::find(servers.begin(), servers.end(),
|
||||||
|
cluster_[i]->getServerString()) != servers.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove a follower.
|
||||||
|
std::vector<int32_t> followers = getFollowers();
|
||||||
|
len = 1024;
|
||||||
|
CPPUNIT_ASSERT_EQUAL(NUM_SERVERS - 1,
|
||||||
|
(uint32_t)(followers.size()));
|
||||||
|
std::stringstream ss;
|
||||||
|
for (int i = 1; i < followers.size(); i++) {
|
||||||
|
ss << cluster_[followers[i]]->getServerString() << ",";
|
||||||
|
}
|
||||||
|
ss << cluster_[leader]->getServerString();
|
||||||
|
|
||||||
|
int rc = zoo_reconfig(zk, NULL, NULL, ss.str().c_str(), -1, buf, &len,
|
||||||
|
&stat);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
|
||||||
|
parseConfig(buf, len, servers, version);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("100000002"), version);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(NUM_SERVERS - 1, (uint32_t)(servers.size()));
|
||||||
|
for (int i = 0; i < cluster_.size(); i++) {
|
||||||
|
if (i == followers[0]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
CPPUNIT_ASSERT(std::find(servers.begin(), servers.end(),
|
||||||
|
cluster_[i]->getServerString()) != servers.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the follower back.
|
||||||
|
len = 1024;
|
||||||
|
ss.str("");
|
||||||
|
for (int i = 0; i < cluster_.size(); i++) {
|
||||||
|
ss << cluster_[i]->getServerString() << ",";
|
||||||
|
}
|
||||||
|
rc = zoo_reconfig(zk, NULL, NULL, ss.str().c_str(), -1, buf, &len,
|
||||||
|
&stat);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
|
||||||
|
parseConfig(buf, len, servers, version);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(NUM_SERVERS, (uint32_t)(servers.size()));
|
||||||
|
for (int i = 0; i < cluster_.size(); i++) {
|
||||||
|
CPPUNIT_ASSERT(std::find(servers.begin(), servers.end(),
|
||||||
|
cluster_[i]->getServerString()) != servers.end());
|
||||||
|
}
|
||||||
|
zookeeper_close(zk);
|
||||||
|
}
|
||||||
|
|
||||||
|
zhandle_t* TestReconfigServer::
|
||||||
|
connectFollowers(std::vector<int32_t> &followers) {
|
||||||
|
std::stringstream ss;
|
||||||
|
int32_t leader = getLeader();
|
||||||
|
CPPUNIT_ASSERT(leader >= 0);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(NUM_SERVERS - 1, (uint32_t)(followers.size()));
|
||||||
|
for (int i = 0; i < followers.size(); i++) {
|
||||||
|
ss << cluster_[followers[i]]->getHostPort() << ",";
|
||||||
|
}
|
||||||
|
ss << cluster_[leader]->getHostPort();
|
||||||
|
std::string hosts = ss.str().c_str();
|
||||||
|
zoo_deterministic_conn_order(true);
|
||||||
|
zhandle_t* zk = zookeeper_init(hosts.c_str(), NULL, 10000, NULL, NULL, 0);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(true, waitForConnected(zk, 10));
|
||||||
|
|
||||||
|
std::string connectedHost(zoo_get_current_server(zk));
|
||||||
|
std::string portString = connectedHost.substr(connectedHost.find(":") + 1);
|
||||||
|
uint32_t port;
|
||||||
|
std::istringstream (portString) >> port;
|
||||||
|
CPPUNIT_ASSERT_EQUAL(cluster_[followers[0]]->getClientPort(), port);
|
||||||
|
return zk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Connect to a follower.
|
||||||
|
* 2. Remove the follower the client is connected to.
|
||||||
|
*/
|
||||||
|
void TestReconfigServer::
|
||||||
|
testRemoveConnectedFollower() {
|
||||||
|
std::vector<std::string> servers;
|
||||||
|
std::string version;
|
||||||
|
struct Stat stat;
|
||||||
|
int len = 1024;
|
||||||
|
char buf[len];
|
||||||
|
|
||||||
|
// connect to a follower.
|
||||||
|
std::stringstream ss;
|
||||||
|
std::vector<int32_t> followers = getFollowers();
|
||||||
|
zhandle_t* zk = connectFollowers(followers);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, zoo_add_auth(zk, "digest", "super:test", 10, NULL,(void*)ZOK));
|
||||||
|
|
||||||
|
// remove the follower.
|
||||||
|
len = 1024;
|
||||||
|
ss.str("");
|
||||||
|
ss << followers[0];
|
||||||
|
zoo_reconfig(zk, NULL, ss.str().c_str(), NULL, -1, buf, &len, &stat);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, zoo_getconfig(zk, 0, buf, &len, &stat));
|
||||||
|
parseConfig(buf, len, servers, version);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(NUM_SERVERS - 1, (uint32_t)(servers.size()));
|
||||||
|
for (int i = 0; i < cluster_.size(); i++) {
|
||||||
|
if (i == followers[0]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
CPPUNIT_ASSERT(std::find(servers.begin(), servers.end(),
|
||||||
|
cluster_[i]->getServerString()) != servers.end());
|
||||||
|
}
|
||||||
|
zookeeper_close(zk);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ZOOKEEPER-2014: only admin or users who are explicitly granted permission can do reconfig.
|
||||||
|
*/
|
||||||
|
void TestReconfigServer::
|
||||||
|
testReconfigFailureWithoutAuth() {
|
||||||
|
std::vector<std::string> servers;
|
||||||
|
std::string version;
|
||||||
|
struct Stat stat;
|
||||||
|
int len = 1024;
|
||||||
|
char buf[len];
|
||||||
|
|
||||||
|
// connect to a follower.
|
||||||
|
std::stringstream ss;
|
||||||
|
std::vector<int32_t> followers = getFollowers();
|
||||||
|
zhandle_t* zk = connectFollowers(followers);
|
||||||
|
|
||||||
|
// remove the follower.
|
||||||
|
len = 1024;
|
||||||
|
ss.str("");
|
||||||
|
ss << followers[0];
|
||||||
|
// No auth, should fail.
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZNOAUTH, zoo_reconfig(zk, NULL, ss.str().c_str(), NULL, -1, buf, &len, &stat));
|
||||||
|
// Wrong auth, should fail.
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, zoo_add_auth(zk, "digest", "super:wrong", 11, NULL,(void*)ZOK));
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZNOAUTH, zoo_reconfig(zk, NULL, ss.str().c_str(), NULL, -1, buf, &len, &stat));
|
||||||
|
// Right auth, should pass.
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, zoo_add_auth(zk, "digest", "super:test", 10, NULL,(void*)ZOK));
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, zoo_reconfig(zk, NULL, ss.str().c_str(), NULL, -1, buf, &len, &stat));
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, zoo_getconfig(zk, 0, buf, &len, &stat));
|
||||||
|
parseConfig(buf, len, servers, version);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(NUM_SERVERS - 1, (uint32_t)(servers.size()));
|
||||||
|
for (int i = 0; i < cluster_.size(); i++) {
|
||||||
|
if (i == followers[0]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
CPPUNIT_ASSERT(std::find(servers.begin(), servers.end(),
|
||||||
|
cluster_[i]->getServerString()) != servers.end());
|
||||||
|
}
|
||||||
|
zookeeper_close(zk);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestReconfigServer::
|
||||||
|
testReconfigFailureWithoutServerSuperuserPasswordConfigured() {
|
||||||
|
std::vector<std::string> servers;
|
||||||
|
std::string version;
|
||||||
|
struct Stat stat;
|
||||||
|
int len = 1024;
|
||||||
|
char buf[len];
|
||||||
|
|
||||||
|
// Create a new quorum with the super user's password not configured.
|
||||||
|
tearDown();
|
||||||
|
ZooKeeperQuorumServer::tConfigPairs configs;
|
||||||
|
configs.push_back(std::make_pair("reconfigEnabled", "true"));
|
||||||
|
cluster_ = ZooKeeperQuorumServer::getCluster(NUM_SERVERS, configs, "");
|
||||||
|
|
||||||
|
// connect to a follower.
|
||||||
|
std::stringstream ss;
|
||||||
|
std::vector<int32_t> followers = getFollowers();
|
||||||
|
zhandle_t* zk = connectFollowers(followers);
|
||||||
|
|
||||||
|
// remove the follower.
|
||||||
|
len = 1024;
|
||||||
|
ss.str("");
|
||||||
|
ss << followers[0];
|
||||||
|
// All cases should fail as server ensemble was not configured with the super user's password.
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZNOAUTH, zoo_reconfig(zk, NULL, ss.str().c_str(), NULL, -1, buf, &len, &stat));
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, zoo_add_auth(zk, "digest", "super:", 11, NULL,(void*)ZOK));
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZNOAUTH, zoo_reconfig(zk, NULL, ss.str().c_str(), NULL, -1, buf, &len, &stat));
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZOK, zoo_add_auth(zk, "digest", "super:test", 10, NULL,(void*)ZOK));
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZNOAUTH, zoo_reconfig(zk, NULL, ss.str().c_str(), NULL, -1, buf, &len, &stat));
|
||||||
|
zookeeper_close(zk);
|
||||||
|
}
|
||||||
|
|
||||||
|
CPPUNIT_TEST_SUITE_REGISTRATION(TestReconfigServer);
|
||||||
|
#endif
|
@ -0,0 +1,109 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cppunit/extensions/HelperMacros.h>
|
||||||
|
#include "CppAssertHelper.h"
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <zookeeper.h>
|
||||||
|
|
||||||
|
#include "Util.h"
|
||||||
|
#include "WatchUtil.h"
|
||||||
|
|
||||||
|
ZOOAPI int zoo_create2(zhandle_t *zh, const char *path, const char *value,
|
||||||
|
int valuelen, const struct ACL_vector *acl, int mode,
|
||||||
|
char *path_buffer, int path_buffer_len, struct Stat *stat);
|
||||||
|
|
||||||
|
class Zookeeper_serverRequireClientSASL : public CPPUNIT_NS::TestFixture {
|
||||||
|
CPPUNIT_TEST_SUITE(Zookeeper_serverRequireClientSASL);
|
||||||
|
#ifdef THREADED
|
||||||
|
CPPUNIT_TEST(testServerRequireClientSASL);
|
||||||
|
#endif
|
||||||
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
FILE *logfile;
|
||||||
|
static const char hostPorts[];
|
||||||
|
static void watcher(zhandle_t *, int type, int state, const char *path,void*v){
|
||||||
|
watchctx_t *ctx = (watchctx_t*)v;
|
||||||
|
|
||||||
|
if (state == ZOO_CONNECTED_STATE) {
|
||||||
|
ctx->connected = true;
|
||||||
|
} else {
|
||||||
|
ctx->connected = false;
|
||||||
|
}
|
||||||
|
if (type != ZOO_SESSION_EVENT) {
|
||||||
|
evt_t evt;
|
||||||
|
evt.path = path;
|
||||||
|
evt.type = type;
|
||||||
|
ctx->putEvent(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Zookeeper_serverRequireClientSASL() {
|
||||||
|
logfile = openlogfile("Zookeeper_serverRequireClientSASL");
|
||||||
|
}
|
||||||
|
|
||||||
|
~Zookeeper_serverRequireClientSASL() {
|
||||||
|
if (logfile) {
|
||||||
|
fflush(logfile);
|
||||||
|
fclose(logfile);
|
||||||
|
logfile = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setUp() {
|
||||||
|
zoo_set_log_stream(logfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
void startServer() {
|
||||||
|
char cmd[1024];
|
||||||
|
sprintf(cmd, "%s startRequireSASLAuth", ZKSERVER_CMD);
|
||||||
|
CPPUNIT_ASSERT(system(cmd) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stopServer() {
|
||||||
|
char cmd[1024];
|
||||||
|
sprintf(cmd, "%s stop", ZKSERVER_CMD);
|
||||||
|
CPPUNIT_ASSERT(system(cmd) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testServerRequireClientSASL() {
|
||||||
|
startServer();
|
||||||
|
|
||||||
|
watchctx_t ctx;
|
||||||
|
int rc = 0;
|
||||||
|
zhandle_t *zk = zookeeper_init(hostPorts, watcher, 10000, 0, &ctx, 0);
|
||||||
|
ctx.zh = zk;
|
||||||
|
CPPUNIT_ASSERT(zk);
|
||||||
|
|
||||||
|
char pathbuf[80];
|
||||||
|
struct Stat stat_a = {0};
|
||||||
|
|
||||||
|
rc = zoo_create2(zk, "/serverRequireClientSASL", "", 0,
|
||||||
|
&ZOO_OPEN_ACL_UNSAFE, 0, pathbuf, sizeof(pathbuf), &stat_a);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int)ZSESSIONCLOSEDREQUIRESASLAUTH, rc);
|
||||||
|
|
||||||
|
stopServer();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const char Zookeeper_serverRequireClientSASL::hostPorts[] = "127.0.0.1:22181";
|
||||||
|
|
||||||
|
CPPUNIT_TEST_SUITE_REGISTRATION(Zookeeper_serverRequireClientSASL);
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user