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