pax_global_header00006660000000000000000000000064131726560550014524gustar00rootroot0000000000000052 comment=b785959ecd5c16289856f9a598876a2f41218c82 carbon-c-relay-3.2/000077500000000000000000000000001317265605500141665ustar00rootroot00000000000000carbon-c-relay-3.2/.gitignore000066400000000000000000000002041317265605500161520ustar00rootroot00000000000000*.o /.deps/ /Makefile /autom4te.cache/ /config.h /config.h.in~ /config.log /config.status /stamp-h1 /relay /carbon-c-relay-*.tar.gz carbon-c-relay-3.2/.travis.yml000066400000000000000000000057241317265605500163070ustar00rootroot00000000000000script: make language: c matrix: include: - compiler: gcc os: linux - compiler: clang os: linux - compiler: coverity os: linux env: - COVERITY_SCAN_PROJECT_NAME="$TRAVIS_REPO_SLUG" - COVERITY_SCAN_BRANCH_PATTERN="master" - COVERITY_SCAN_NOTIFICATION_EMAIL="grobian@gentoo.org" - COVERITY_SCAN_BUILD_COMMAND="make" - compiler: clang os: osx # gcc is actually clang on OSX, so pointless to test twice script: - | if [ $TRAVIS_OS_NAME = osx ]; then brew update > /dev/null brew install lz4 openssl fi # workaround git not retaining mtimes and bison/flex not being uptodate - touch conffile.yy.c conffile.tab.c conffile.tab.h - touch configure.ac Makefile.am aclocal.m4 configure Makefile.in config.h.in - | if [[ ${CC} == coverity ]] ; then # ensure we end up with an existing compiler export CC=gcc ./configure || { cat config.log ; exit 1 ; } curl -s 'https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh' | bash else # everything disabled, this MUST work ./configure --without-gzip --without-lz4 --without-ssl \ || { cat config.log ; exit 1 ; } make CFLAGS="-O3 -Wall -Werror -Wshadow -pipe" clean check || exit 1 # compile some enabled/disabled variants compile only if ./configure --with-gzip --without-lz4 --without-ssl ; then make CFLAGS="-O3 -Wall -Werror -Wshadow -pipe" clean relay || exit 1 fi if ./configure --without-gzip --with-lz4 --without-ssl ; then make CFLAGS="-O3 -Wall -Werror -Wshadow -pipe" clean relay || exit 1 fi if ./configure --with-gzip --with-lz4 --without-ssl ; then make CFLAGS="-O3 -Wall -Werror -Wshadow -pipe" clean relay || exit 1 fi if ./configure --with-gzip --with-lz4 --with-ssl ; then make CFLAGS="-O3 -Wall -Werror -Wshadow -pipe" clean relay || exit 1 fi # final test with everything enabled that is detected ./configure || { cat config.log ; exit 1 ; } make CFLAGS="-O3 -Wall -Werror -Wshadow -pipe" clean check || exit 1 fi env: global: # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created # via the "travis encrypt" command using the project repo's public key - secure: "H844xDJC5CUXhUyB1SFsGiiz/Q4viVSALkj/KnWAuagrbrzIXJoK4tRWpPxCzUar5QsdEua1WIXTBezPA6V97w2cis2OGUXtgsMd1fWnwlG0RwPRj2+LAVxJ+i5z1Asx8hkYOiZIv8y0VkBGldjOrD0l0pBcxB+CDZC/zsGSRtnMLOs+smfEjOF6JPGw8Ye0XJ+YKrfbHOXhfS7XTMwUnjgAV7lTH/aAlKuedc3mYsuC3WHJOMptYLXaiPdbPKoIXfLdmszP91SkThr4f0elyQskugzGM3D7M1tIFhfmordSD+DfzLvvdSu32hHUNQjHvAm7Pz8QmdLC2IjjE8y8MkIkEy2+wR/5AjacnKR8OgFzXgt+yIH+CBc6qbTi40dZ7Go33Q8uNyKJGrA1CyL195NS8q0reMbuS7WIxI0rNOy7cdw8MO0sNjeofcb1RW90U5u5qciRQpbwhFwMFMCuD0LL41mjfN+IHGNeUwp148Qibbvyu+d7y4Y1F7/CsdMpZVBH9Ae7CHXetN8biT81fJp1rn0uEGQqoPuxvKeePsL40MXu6wvlrSf5wLKV3aqp5lzbjoJsPrOwV5iVwMHrvdhoAFlLc6Y1aJkCTPPt7yjLHgLBisqRXLTZ9lcD3AG8ubTLr03DsseUUM3/tWvhWfVRfxzkuOHsDRLMfdY2Q20=" carbon-c-relay-3.2/ChangeLog.md000066400000000000000000000345531317265605500163510ustar00rootroot00000000000000# 3.3 (unreleased master branch) # 3.2 (21-10-2017) ### Notes * The deprecated `-S` and `-m` options were removed. Use the `statistics` configuration file construct instead. * The `-i` option was removed. Use tue `listen` configuration file construct instead. ### New Features * **relay** the flag `-tt` can now be used to test the configuration and exit immediately. In this mode, any standard output is suppressed as well. [Issue #247](https://github.com/grobian/carbon-c-relay/issues/247) * **relay** the `listen` construct was added to precisely control listen ports and protocols. * **server** unresolvable hosts are now treated as failed servers, this means the relay will only warn about unresolvable hosts, but not error out. If a host becomes unresolvable this server is transitioned to failed state until it is resolvable again. [Issue #293](https://github.com/grobian/carbon-c-relay/issues/293) * **relay** compression and encryption support was added to listeners and servers. [Issue #212](https://github.com/grobian/carbon-c-relay/issues/212) [Issue #75](https://github.com/grobian/carbon-c-relay/issues/75) ### Bugfixes * [Issue #265](https://github.com/grobian/carbon-c-relay/issues/265) exit code is sucess on error when daemonised * [Issue #266](https://github.com/grobian/carbon-c-relay/issues/266) incorrect hash when using aggregate function * [Issue #267](https://github.com/grobian/carbon-c-relay/issues/267) segmentation fault when trying to use a file cluster * [PR #273](https://github.com/grobian/carbon-c-relay/pull/273) regex matching slow on glibc due to lock contention * [Issue #287](https://github.com/grobian/carbon-c-relay/issues/287) unexpected warning about rejected socket bufsize * [PR #282](https://github.com/grobian/carbon-c-relay/pull/282) route using should not change the metric key sent * [PR #274](https://github.com/grobian/carbon-c-relay/pull/274) aggregator expiry deadlocks under pressure * [buckytools Issue #17](https://github.com/jjneely/buckytools/issues/17) consistent-hash implementation returns a different distribution with the binary search approach # 3.1 (29-04-2017) ### New Features * **router** a new `route using` clause was added to `match` rules to set the string to be used as key for consistent-hash based clusters. [Pull Request #235](https://github.com/grobian/carbon-c-relay/pull/235) * **consistent-hash** node traversal is now done through a binary search instead of forward pointer chasing. ### Bugfixes * [Issue #261](https://github.com/grobian/carbon-c-relay/issues/261) unable to use numeric instance name * [Issue #262](https://github.com/grobian/carbon-c-relay/issues/262) DNS round-robin on any\_of cluster doesn't rotate and causes lots of hung connections * [Issue #263](https://github.com/grobian/carbon-c-relay/issues/263) parser fails on `%` in regular expressions, and exits with a crash * [Issue #264](https://github.com/grobian/carbon-c-relay/issues/264) carbon\_ch hash algorithm change between 2.6 and 3.0 # 3.0 (2017-04-07) ### Notes * Parsing of the configuration file has changed implementation in this version. Should you find problems with configurations that worked fine before, please report the problem. * The use of `send statistics to` is now deprecated, use the new `statistics send to` instead. * The use of statistics controlling flags `-S` sending interval and `-m` summary mode, are now deprecated because they can be set in the configuration. ### New Features * **collector** statistics now can be controlled via the configuration file using the new `statistics` clause. This overrides some command line flags, and adds some new posibilities. * **router** the rewrite rule got a new replacement mode: `\.` This mode replaces all dots with underscores in the matched group. A combination with upper/lowercasing is possible, e.g. `\_.`. * **collector** one can now set the internal statistics prefix [Issue #25](https://github.com/grobian/carbon-c-relay/issues/25) [Issue #113](https://github.com/grobian/carbon-c-relay/issues/113) [Issue #249](https://github.com/grobian/carbon-c-relay/issues/249). ### Bugfixes * [Issue #249](https://github.com/grobian/carbon-c-relay/issues/249) `send statistics` changes metric prefix from dots into underscores # 2.6 (2017-01-26) ### New Features * **router** `useall` is now also allowed for `forward` and `failover` clusters * **server** hostnames are now re-resolved at every connect [Issue #115](https://github.com/grobian/carbon-c-relay/issues/115) * **server** when connecting to a hostname, now /all/ resolved addresses are tried in order before failing * **relay** A new `-O` flag allows to set the minimum rules threshold before trying to optimise the rules. ### Bugfixes * [Issue #246](https://github.com/grobian/carbon-c-relay/issues/246) using `stop` in a `match` rule does not stop metrics from being processed afterwards * [Issue #206](https://github.com/grobian/carbon-c-relay/issues/206) some metrics are randomly prefixed with garbage characters # 2.5 (2017-01-09) ### Bugfixes * [Issue #239](https://github.com/grobian/carbon-c-relay/issues/239) segfault when date format is incorrect * [Issue #242](https://github.com/grobian/carbon-c-relay/issues/242) dispatcher/aggregations broken (relay seems too slow) # 2.4 (2017-01-03) ### New Features * **router** `match` rules now support a `validate` clause to do data filtering, [Issue #228](https://github.com/grobian/carbon-c-relay/issues/228), [Issue #142](https://github.com/grobian/carbon-c-relay/issues/142), [Issue #121](https://github.com/grobian/carbon-c-relay/issues/121), [Pull #127](https://github.com/grobian/carbon-c-relay/issues/127), [Pull #87](https://github.com/grobian/carbon-c-relay/issues/87). ### Bugfixes * **server** connection errors are no longer endlessly repeated * [Issue #240](https://github.com/grobian/carbon-c-relay/issues/240) 'include' directive doesn't care about rewrites. * [Issue #241](https://github.com/grobian/carbon-c-relay/issues/241) XXX characters being prepended to metrics when sent via UDP * [Issue #204](https://github.com/grobian/carbon-c-relay/issues/204) relay is sending data randomly while kill -HUP happens # 2.3 (2016-11-07) ### Bugfixes * [Issue #213](https://github.com/grobian/carbon-c-relay/issues/213) Change to aggregates to not cause HUP to reload when more than 10 aggregates are defined. * [Issue #214](https://github.com/grobian/carbon-c-relay/issues/214) `-U` option doesn't set UDP receive buffer size. * [Issue #218](https://github.com/grobian/carbon-c-relay/issues/218) zeros inserted after some metrics. * [Issue #219](https://github.com/grobian/carbon-c-relay/issues/219) should fail if port is unavailable * [Issue #224](https://github.com/grobian/carbon-c-relay/issues/224) segfault during SIGHUP # 2.2 (2016-09-11) ### New Features * **relay** socket receive and send buffer sizes can be adjusted the `-U` option was introduced to allow setting the socket buffer size in bytes, [Issue #207](https://github.com/grobian/carbon-c-relay/issues/207). ### Breaking Changes ### Enhancements * **relay** the listen backlog default got increased from 3 to 32 * **server** TCP\_NODELAY is now set to improve small writes ### Bugfixes * [Issue #188](https://github.com/grobian/carbon-c-relay/issues/188) SIGHUP leads to SIGSEGV when config didn't change, or a SIGHUP is received while a previous HUP is being processed * [Issue #193](https://github.com/grobian/carbon-c-relay/issues/193) race condition in aggregator leads to crash * [Issue #195](https://github.com/grobian/carbon-c-relay/issues/195) assertion fails when reloading config * [Issue #200](https://github.com/grobian/carbon-c-relay/issues/200) use after free during shutdown in aggregator * [Issue #203](https://github.com/grobian/carbon-c-relay/issues/203) change default connection listen backlog * [Issue #208](https://github.com/grobian/carbon-c-relay/issues/208) TCP\_NODELAY should be off for connections relaying data * [Issue #199](https://github.com/grobian/carbon-c-relay/issues/199) Various race conditions reported by TSAN # 2.1 (16-06-2016) ### Enhancements * **router** the optimiser now tries harder to form groups of consecutive rules that have a matching common pattern ### Bugfixes * [Issue #180](https://github.com/grobian/carbon-c-relay/issues/180) include directive possibly overrides previous included components * [Issue #184](https://github.com/grobian/carbon-c-relay/issues/184) router optimise doesn't work correctly with regex groups # 2.0 (30-05-2016) ### New Features * **router** `include` directive was added to add content of another file, see also [Issue #165](https://github.com/grobian/carbon-c-relay/issues/165). The include can also use glob patterns, see [Pull #174](https://github.com/grobian/carbon-c-relay/pull/174) * **server** the number of stalls performed on writes can now be controlled (and also disabled) using the `-L` flag. [Issue #172](https://github.com/grobian/carbon-c-relay/issues/172) ### Breaking Changes ### Enhancements * **server** incomplete writes are now retried a couple of times before they are considered fatal. This should reduce the amount of messages in the logs about them, and be more like the consumer expects, e.g. less sudden disconnects for the client. * **router** reloading the config now prints the difference between the old and the new config in `diff -u` format. * **router** reloading the config now maintains the queues for the servers, such that unavailable servers don't get metrics dropped. ### Bugfixes * [Issue #154](https://github.com/grobian/carbon-c-relay/issues/159) when a store becomes a bottleneck it shouldn't indefinitely stall * [Issue #164](https://github.com/grobian/carbon-c-relay/issues/164) config reload should re-use unmodified servers # 1.11 (23-03-2016) ### New Features * **router** `send statistics to` construct was added to direct internal statistics to a specific cluster ### Enhancements * **collector** UDP connections are now suffixed with `-udp` in destination target ### Bugfixes * [Issue #159](https://github.com/grobian/carbon-c-relay/issues/159) corrupted statistics for file clusters * [Issue #160](https://github.com/grobian/carbon-c-relay/issues/160) metricsBlackholed stays zero when blackhole target is used # 1.10 (09-03-2016) ### Breaking Changes * **statistics** dispatch\_busy and dispatch\_idle have been replaced with wallTime\_us and sleepTime\_us ### Bugfixes * [Issue #152](https://github.com/grobian/carbon-c-relay/issues/152) crash in aggregator\_expire for data-contained aggregations # 1.9 (07-03-2016) ### Enhancements * **statistics** dispatch\_busy is slightly more realistic now ### Bugfixes * [Issue #153](https://github.com/grobian/carbon-c-relay/issues/153) aggregator statistics are garbage with `-m` # 1.8 (23-02-2016) ### New Features * **relay** new flags `-D` for daemon mode and `-p` for pidfile creation ### Enhancements * **dispatcher** server stalling (to slow down too fast writers) is now based on a random timeout * **server** write timeout is now large enough to deal with upstream relay stalling * **relay** number of workers/dispatchers is now determined in a way that doesn''t need OpenMP any more # 1.7 (29-01-2016) ### New Features * **relay** new flag `-B` to set the listen backlog for TCP and UNIX connections, [issue #143](https://github.com/grobian/carbon-c-relay/issues/143) ### Enhancements * **dispatcher** switch from select() to poll() to fix crashes when too many connections were made to the relay * Misc (memory) leak fixes # 1.6 (27-01-2016) ### Breaking Changes * **relay** startup and shutdown messages are now better in line ### Enhancements * **relay** fixed segfault when issuing `SIGHUP` under active load # 1.5 (13-01-2016) ### Enhancements * **aggregator** metrics are now written directly to dispatchers to avoid overload of the internal\_submission queue, which is likely to to happen with many aggregates * **collector** properly report file-based servers in statistics * **collector** re-introduce the interal destination in statistics # 1.4 (04-01-2016) ### New Features * **collector** when run in debug and submission mode, there is a iostat like output ### Enhancements * **relay** reloading config now no longer unconditionally starts the aggregator * **aggregator** misc cleanup/free fixes * **relay** allow reloading aggregator ### Bugfixes * [Issue #133](https://github.com/grobian/carbon-c-relay/issues/133) _stub_aggregator metrics seen after a reload # 1.3 (16-12-2015) ### Enhancements * **consistent-hash** fix jump\_fnv1a\_ch metric submission, it didn''t work at all ### Bugfixes * [Issue #126](https://github.com/grobian/carbon-c-relay/issues/126) double free crash * [Issue #131](https://github.com/grobian/carbon-c-relay/issues/131) segfault using stddev in aggregator * [Issue #132](https://github.com/grobian/carbon-c-relay/issues/132) crash with glibc double free message # 1.2 (10-12-2015) ### New Features * **consistent-hash** new algorithm jump\_fnv1a\_ch for near perfect distribution of metrics * **distributiontest** test program used to see unbalancedness of clusters for a given input metric see [graphite-project/carbon#485](https://github.com/graphite-project/carbon/issues/485) ### Enhancements * **router** fix cluster checking with regards replication count and the number of servers to allow equal counts ### Bugfixes * [Issue #126](https://github.com/grobian/carbon-c-relay/issues/126) prevent calling read() too often # 1.1 (25-11-2015) ### Enhancements * **router** fix distribution of any\_of cluster if members have failed # 1.0 (23-11-2015) * many improvements # 0.45 (05-11-2015) * Many aggregator improvements, more flexible routing support. # 0.44 (13-08-2015) * Feature to set hash-keys for fnv1a\_ch. # 0.43 (27-07-2015) * Bugfix release for segfault when using any\_of clusters. # 0.42 (24-07-2015) * Reduced warning level for submission mode queue pileups. Allow writing to a file (cluster type). Fix splay on aggregator not to affect timestamps of input. No more dep on openssl for md5. # 0.40 (11-05-2015) * Hefty optimisations on aggregations. Fix for UDP port closure. carbon-c-relay-3.2/Dockerfile000066400000000000000000000011121317265605500161530ustar00rootroot00000000000000FROM alpine:3.6 MAINTAINER Fabian Groffen RUN mkdir -p /opt/carbon-c-relay-build RUN mkdir /etc/carbon-c-relay COPY . /opt/carbon-c-relay-build RUN \ apk --no-cache update && \ apk --no-cache upgrade && \ apk --no-cache add git bc build-base curl && \ cd /opt/carbon-c-relay-build && \ ./configure; make && \ cp relay /usr/bin/carbon-c-relay && \ apk del --purge git bc build-base ca-certificates curl && \ rm -rf /opt/* /tmp/* /var/cache/apk/* /opt/carbon-c-relay-build EXPOSE 2003 ENTRYPOINT ["carbon-c-relay", "-f", "/etc/carbon-c-relay/carbon-c-relay.conf"] carbon-c-relay-3.2/LICENSE.md000066400000000000000000000236761317265605500156100ustar00rootroot00000000000000 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 carbon-c-relay-3.2/Makefile.am000066400000000000000000000045031317265605500162240ustar00rootroot00000000000000# Copyright 2013-2017 Fabian Groffen # # 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. AUTOMAKE_OPTIONS = foreign CFLAGS ?= -O2 -Wall -Wshadow -pipe GIT_VERSION := $(shell git describe --abbrev=6 --dirty --always 2>/dev/null || date +%F) GVCFLAGS = -DGIT_VERSION=\"$(GIT_VERSION)\" override CFLAGS += $(GVCFLAGS) -pthread conffile.tab.c conffile.tab.h: conffile.y bison -d $^ conffile.yy.c: conffile.l conffile.tab.h flex -o $@ $< man: sed -e '/travis-ci.org\/grobian\/carbon-c-relay.svg/d' carbon-c-relay.md | \ ronn \ --manual="Graphite data collection and visualisation" \ --organization=Graphite \ --roff \ > carbon-c-relay.1 bin_PROGRAMS = relay relay_LINK = $(CCLD) $(AM_LDFLAGS) $(LDFLAGS) -o $@ relay_LDADD = $(LIBGZIP) $(LIBLZ4) $(LIBSSL) relay_SOURCES = \ relay.c \ md5.c \ consistent-hash.c \ receptor.c \ dispatcher.c \ conffile.tab.c \ conffile.yy.c \ allocator.c \ router.c \ queue.c \ server.c \ collector.c \ aggregator.c noinst_HEADERS = \ relay.h \ md5.h \ fnv1a.h \ consistent-hash.h \ conffile.h \ conffile.tab.h \ receptor.h \ dispatcher.h \ allocator.h \ router.h \ queue.h \ server.h \ collector.h \ aggregator.h man_MANS = carbon-c-relay.1 EXTRA_DIST = \ issues \ test \ ChangeLog.md \ LICENSE.md \ carbon-c-relay.md \ carbon-c-relay.1 \ README.md \ conffile.tab.c conffile.tab.h conffile.y \ conffile.yy.c conffile.l \ $(NULL) CRTESTS = \ issue10 \ issue27 \ issue117 \ issue156 \ issue157 \ issue163 \ issue165 \ issue180 \ issue184 \ issue202 \ issue213 \ issue218 \ issue228 \ issue235 \ issue236 \ issue246 \ issue252 \ issue253 \ issue263 \ issue267 \ issue288 \ issue293 \ issue310 \ $(NULL) test: check test-%: relay @( cd test && ./run-test.sh $* ) approve-%: relay @( cd test && ./run-test.sh -a $* ) check: relay @( cd test && ./run-test.sh $(CRTESTS) ) carbon-c-relay-3.2/Makefile.in000066400000000000000000000735201317265605500162420ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Copyright 2013-2017 Fabian Groffen # # 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. VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : bin_PROGRAMS = relay$(EXEEXT) subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ $(am__configure_deps) $(noinst_HEADERS) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" PROGRAMS = $(bin_PROGRAMS) am_relay_OBJECTS = relay.$(OBJEXT) md5.$(OBJEXT) \ consistent-hash.$(OBJEXT) receptor.$(OBJEXT) \ dispatcher.$(OBJEXT) conffile.tab.$(OBJEXT) \ conffile.yy.$(OBJEXT) allocator.$(OBJEXT) router.$(OBJEXT) \ queue.$(OBJEXT) server.$(OBJEXT) collector.$(OBJEXT) \ aggregator.$(OBJEXT) relay_OBJECTS = $(am_relay_OBJECTS) am__DEPENDENCIES_1 = relay_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(relay_SOURCES) DIST_SOURCES = $(relay_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } man1dir = $(mandir)/man1 NROFF = nroff MANS = $(man_MANS) HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ $(LISP)config.h.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags CSCOPE = cscope AM_RECURSIVE_TARGETS = cscope am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in compile \ depcomp install-sh missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBGZIP = @LIBGZIP@ LIBLZ4 = @LIBLZ4@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSSL = @LIBSSL@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign GIT_VERSION := $(shell git describe --abbrev=6 --dirty --always 2>/dev/null || date +%F) GVCFLAGS = -DGIT_VERSION=\"$(GIT_VERSION)\" relay_LINK = $(CCLD) $(AM_LDFLAGS) $(LDFLAGS) -o $@ relay_LDADD = $(LIBGZIP) $(LIBLZ4) $(LIBSSL) relay_SOURCES = \ relay.c \ md5.c \ consistent-hash.c \ receptor.c \ dispatcher.c \ conffile.tab.c \ conffile.yy.c \ allocator.c \ router.c \ queue.c \ server.c \ collector.c \ aggregator.c noinst_HEADERS = \ relay.h \ md5.h \ fnv1a.h \ consistent-hash.h \ conffile.h \ conffile.tab.h \ receptor.h \ dispatcher.h \ allocator.h \ router.h \ queue.h \ server.h \ collector.h \ aggregator.h man_MANS = carbon-c-relay.1 EXTRA_DIST = \ issues \ test \ ChangeLog.md \ LICENSE.md \ carbon-c-relay.md \ carbon-c-relay.1 \ README.md \ conffile.tab.c conffile.tab.h conffile.y \ conffile.yy.c conffile.l \ $(NULL) CRTESTS = \ issue10 \ issue27 \ issue117 \ issue156 \ issue157 \ issue163 \ issue165 \ issue180 \ issue184 \ issue202 \ issue213 \ issue218 \ issue228 \ issue235 \ issue236 \ issue246 \ issue252 \ issue253 \ issue263 \ issue267 \ issue288 \ issue293 \ issue310 \ $(NULL) all: config.h $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .o .obj am--refresh: Makefile @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): config.h: stamp-h1 @test -f $@ || rm -f stamp-h1 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config.h.in: $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) relay$(EXEEXT): $(relay_OBJECTS) $(relay_DEPENDENCIES) $(EXTRA_relay_DEPENDENCIES) @rm -f relay$(EXEEXT) $(AM_V_GEN)$(relay_LINK) $(relay_OBJECTS) $(relay_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aggregator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/allocator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collector.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conffile.tab.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conffile.yy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/consistent-hash.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dispatcher.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/queue.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/receptor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/relay.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/router.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` install-man1: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man1dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.1[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-tarZ: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build/sub \ && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(MANS) $(HEADERS) config.h installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic mostlyclean-am distclean: distclean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-man install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man1 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-man uninstall-man: uninstall-man1 .MAKE: all install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--refresh check check-am clean \ clean-binPROGRAMS clean-cscope clean-generic cscope \ cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \ dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \ distcheck distclean distclean-compile distclean-generic \ distclean-hdr distclean-tags distcleancheck distdir \ distuninstallcheck dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-man1 install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-binPROGRAMS uninstall-man \ uninstall-man1 .PRECIOUS: Makefile CFLAGS ?= -O2 -Wall -Wshadow -pipe override CFLAGS += $(GVCFLAGS) -pthread conffile.tab.c conffile.tab.h: conffile.y bison -d $^ conffile.yy.c: conffile.l conffile.tab.h flex -o $@ $< man: sed -e '/travis-ci.org\/grobian\/carbon-c-relay.svg/d' carbon-c-relay.md | \ ronn \ --manual="Graphite data collection and visualisation" \ --organization=Graphite \ --roff \ > carbon-c-relay.1 test: check test-%: relay @( cd test && ./run-test.sh $* ) approve-%: relay @( cd test && ./run-test.sh -a $* ) check: relay @( cd test && ./run-test.sh $(CRTESTS) ) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: carbon-c-relay-3.2/README.md000077700000000000000000000000001317265605500205602carbon-c-relay.mdustar00rootroot00000000000000carbon-c-relay-3.2/aclocal.m4000066400000000000000000001222431317265605500160320ustar00rootroot00000000000000# generated automatically by aclocal 1.15.1 -*- Autoconf -*- # Copyright (C) 1996-2017 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # Copyright (C) 2002-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.15' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.15.1], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.15.1])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each '.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC]) [_AM_PROG_CC_C_O ]) # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi dnl The trailing newline in this macro's definition is deliberate, for dnl backward compatibility and to allow trailing 'dnl'-style comments dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it is modern enough. # If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Copyright (C) 1999-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_CC_C_O # --------------- # Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC # to automatically call this. AC_DEFUN([_AM_PROG_CC_C_O], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl AC_LANG_PUSH([C])dnl AC_CACHE_CHECK( [whether $CC understands -c and -o together], [am_cv_prog_cc_c_o], [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i]) if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) # Copyright (C) 2001-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR carbon-c-relay-3.2/aggregator.c000066400000000000000000000461041317265605500164610ustar00rootroot00000000000000/* * Copyright 2013-2017 Fabian Groffen * * 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. */ #include #include #include #include #include #include #include #include #include #include #include "relay.h" #include "dispatcher.h" #include "server.h" #include "router.h" #include "fnv1a.h" #include "aggregator.h" static pthread_t aggregatorid; static size_t prevreceived = 0; static size_t prevsent = 0; static size_t prevdropped = 0; static char keep_running = 1; /** * Allocates a new aggregator setup to hold buckets matching interval * and expiry time. */ aggregator * aggregator_new( unsigned int interval, unsigned int expire, enum _aggr_timestamp tswhen) { aggregator *ret = malloc(sizeof(aggregator)); int intconn[2]; if (ret == NULL) return ret; assert(interval != 0); assert(interval < expire); if (pipe(intconn) < 0) { logerr("failed to create pipe for aggregator: %s\n", strerror(errno)); free(ret); return NULL; } ret->disp_conn = dispatch_addconnection_aggr(intconn[0]); ret->fd = intconn[1]; ret->interval = interval; ret->expire = expire; ret->tswhen = tswhen; ret->bucketcnt = (expire + (interval - 1)) / interval + 1 + 1; ret->received = 0; ret->sent = 0; ret->dropped = 0; ret->computes = NULL; ret->next = NULL; return ret; } /** * Adds a new compute part to this aggregator. Returns -1 if type is * not a recognised aggregation type. */ char aggregator_add_compute( aggregator *s, const char *metric, enum _aggr_compute_type act, unsigned char pctl) { struct _aggr_computes *ac = s->computes; char store = 0; if (act == MEDN) { pctl = 50; store = 1; } else if (act == PCTL || act == VAR || act == SDEV) { store = 1; } if (ac == NULL) { ac = s->computes = malloc(sizeof(*ac)); } else { while (ac->next != NULL) ac = ac->next; ac = ac->next = malloc(sizeof(*ac)); } if (ac == NULL) return -1; ac->type = act; ac->percentile = pctl; ac->metric = strdup(metric); if (ac->metric == NULL) return -1; memset(ac->invocations_ht, 0, sizeof(ac->invocations_ht)); ac->entries_needed = store; pthread_rwlock_init(&ac->invlock, NULL); ac->next = NULL; return 0; } void aggregator_set_stub( aggregator *s, const char *stubname) { struct _aggr_computes *ac; char newmetric[METRIC_BUFSIZ]; for (ac = s->computes; ac != NULL; ac = ac->next) { snprintf(newmetric, sizeof(newmetric), "%s%s", stubname, ac->metric); free((void *)ac->metric); ac->metric = strdup(newmetric); } } /** * Adds a new metric to aggregator s. The value from the metric is put * in the bucket matching the epoch contained in the metric. In cases * where the contained epoch is too old or too new, the metric is * dropped. */ void aggregator_putmetric( aggregator *s, const char *metric, const char *firstspace, size_t nmatch, regmatch_t *pmatch) { char *v; double val; long long int epoch; long long int itime; char newmetric[METRIC_BUFSIZ]; char *newfirstspace = NULL; size_t len; const char *ometric; const char *omp; unsigned int omhash; unsigned int omhtbucket; struct _aggr_computes *compute; struct _aggr_invocations *invocation; struct _aggr_bucket *bucket; struct _aggr_bucket_entries *entries; /* do not accept new values when shutting down, issue #200 */ if (__sync_bool_compare_and_swap(&keep_running, 0, 0)) return; /* get timestamp */ if ((v = strchr(firstspace + 1, ' ')) == NULL) { /* metric includes \n */ if (mode & MODE_DEBUG) logerr("aggregator: dropping incorrect metric: %s", metric); return; } __sync_add_and_fetch(&s->received, 1); val = atof(firstspace + 1); epoch = atoll(v + 1); for (compute = s->computes; compute != NULL; compute = compute->next) { if (nmatch == 0) { ometric = compute->metric; } else if ((len = router_rewrite_metric( &newmetric, &newfirstspace, metric, firstspace, compute->metric, nmatch, pmatch)) == 0) { /* fail, skip */ continue; } else { *newfirstspace = '\0'; ometric = newmetric; } omhash = FNV1A_32_OFFSET; for (omp = ometric; *omp != '\0'; omp++) omhash = (omhash ^ (unsigned int)*omp) * FNV1A_32_PRIME; omhtbucket = ((omhash >> AGGR_HT_POW_SIZE) ^ omhash) & (((unsigned int)1 << AGGR_HT_POW_SIZE) - 1); /* first "cheap" search for an invocation, using a read-lock */ pthread_rwlock_rdlock(&compute->invlock); invocation = compute->invocations_ht[omhtbucket]; for (; invocation != NULL; invocation = invocation->next) if (invocation->hash == omhash && strcmp(ometric, invocation->metric) == 0) /* match */ break; if (invocation == NULL) { /* no match, add */ long long int i; time_t now; /* swap the lock for an expensive exclusive lock to * add/update the invocation */ pthread_rwlock_unlock(&compute->invlock); pthread_rwlock_wrlock(&compute->invlock); /* recheck if invocation is still NULL */ invocation = compute->invocations_ht[omhtbucket]; for (; invocation != NULL; invocation = invocation->next) if (invocation->hash == omhash && strcmp(ometric, invocation->metric) == 0) /* match */ break; if (invocation == NULL) { if ((invocation = malloc(sizeof(*invocation))) == NULL) { logerr("aggregator: out of memory creating %s from %s", ometric, metric); pthread_rwlock_unlock(&compute->invlock); continue; } if ((invocation->metric = strdup(ometric)) == NULL) { logerr("aggregator: out of memory creating %s from %s", ometric, metric); free(invocation); pthread_rwlock_unlock(&compute->invlock); continue; } invocation->hash = omhash; /* Start buckets in the past such that expiry time * conditions are met. Add a splay to the expiry time to * avoid a thundering herd of expirations when the * aggregator is spammed with metrics, e.g. right after * startup when other relays flush their queues. This * approach shouldn't affect the timing of the buckets as * requested in issue #72. * For consistency with other tools/old carbon-aggregator * align the buckets to interval boundaries such that it is * predictable what intervals will be taken, issue #104. */ time(&now); now = ((now - s->expire) / s->interval) * s->interval; invocation->expire = s->expire + (rand() % s->interval); /* allocate enough buckets to hold the past + future */ invocation->buckets = malloc(sizeof(struct _aggr_bucket) * s->bucketcnt); if (invocation->buckets == NULL) { logerr("aggregator: out of memory creating %s from %s", ometric, metric); free(invocation->metric); free(invocation); pthread_rwlock_unlock(&compute->invlock); continue; } for (i = 0; i < s->bucketcnt; i++) { bucket = &invocation->buckets[i]; pthread_mutex_init(&bucket->bcklock, NULL); bucket->state = A_OPEN; bucket->start = now + (i * (long long int)s->interval); bucket->cnt = 0; bucket->entries.size = 0; bucket->entries.values = NULL; } invocation->next = compute->invocations_ht[omhtbucket]; compute->invocations_ht[omhtbucket] = invocation; } } /* finally, try to do the maths */ itime = epoch - invocation->buckets[0].start; if (itime < 0) { /* drop too old metric */ __sync_add_and_fetch(&s->dropped, 1); pthread_rwlock_unlock(&compute->invlock); continue; } if (itime >= (s->bucketcnt * s->interval)) { if (mode & MODE_DEBUG) logerr("aggregator: dropping metric too far in the " "future (%lld > %lld): %s from %s", epoch, invocation->buckets[s->bucketcnt - 1].start, ometric, metric); __sync_add_and_fetch(&s->dropped, 1); pthread_rwlock_unlock(&compute->invlock); continue; } bucket = &invocation->buckets[itime / s->interval]; if (__sync_bool_compare_and_swap(&bucket->state, A_EXPIRE, A_EXPIRE)) { /* drop too old metric */ __sync_add_and_fetch(&s->dropped, 1); pthread_rwlock_unlock(&compute->invlock); continue; } /* Since we have for most cases just a read-lock on invocation * here, run the bucket modification in a critical section of * its own. */ pthread_mutex_lock(&bucket->bcklock); if (bucket->cnt == 0) { bucket->sum = val; bucket->max = val; bucket->min = val; } else { bucket->sum += val; if (bucket->max < val) bucket->max = val; if (bucket->min > val) bucket->min = val; } entries = &bucket->entries; if (compute->entries_needed) { if (bucket->cnt == entries->size) { #define E_I_SZ 64 double *new = realloc(entries->values, sizeof(double) * (entries->size + E_I_SZ)); if (new == NULL) { logerr("aggregator: out of memory creating entry bucket " "(%s from %s)", ometric, metric); } else { entries->values = new; entries->size += E_I_SZ; } } if (bucket->cnt < entries->size) entries->values[bucket->cnt] = val; } bucket->cnt++; pthread_mutex_unlock(&bucket->bcklock); pthread_rwlock_unlock(&compute->invlock); } return; } static inline int cmp_entry(const void *l, const void *r) { return *(const double *)l - *(const double *)r; } static inline void write_metric( aggregator *s, struct _aggr_bucket *b, struct _aggr_computes *c, char *invmetric) { char metric[METRIC_BUFSIZ]; double *values; size_t len = 0; long long int ts = 0; int k; switch (s->tswhen) { case TS_START: ts = b->start; break; case TS_MIDDLE: ts = b->start + (s->interval / 2); break; case TS_END: ts = b->start + s->interval; break; default: assert(0); } pthread_mutex_lock(&b->bcklock); switch (c->type) { case SUM: len = snprintf(metric, sizeof(metric), "%s %f %lld\n", invmetric, b->sum, ts); break; case CNT: len = snprintf(metric, sizeof(metric), "%s %zu %lld\n", invmetric, b->cnt, ts); break; case MAX: len = snprintf(metric, sizeof(metric), "%s %f %lld\n", invmetric, b->max, ts); break; case MIN: len = snprintf(metric, sizeof(metric), "%s %f %lld\n", invmetric, b->min, ts); break; case AVG: len = snprintf(metric, sizeof(metric), "%s %f %lld\n", invmetric, b->sum / (double)b->cnt, ts); break; case MEDN: /* median == 50th percentile */ case PCTL: /* nearest rank method */ k = (int)(((double)c->percentile/100.0 * (double)b->cnt) + 0.9); values = b->entries.values; /* TODO: lazy approach, in case of 1 (first/last) or 2 * buckets distance we could do a forward run picking the * max entries and returning that iso sorting the full array */ qsort(values, b->cnt, sizeof(double), cmp_entry); len = snprintf(metric, sizeof(metric), "%s %f %lld\n", invmetric, values[k - 1], ts); break; case VAR: case SDEV: { double avg = b->sum / (double)b->cnt; double ksum = 0; values = b->entries.values; for (k = 0; k < b->cnt; k++) ksum += pow(values[k] - avg, 2); ksum /= (double)b->cnt; len = snprintf(metric, sizeof(metric), "%s %f %lld\n", invmetric, c->type == VAR ? ksum : sqrt(ksum), ts); } break; default: assert(0); /* for compiler (len) */ } pthread_mutex_unlock(&b->bcklock); /* perform the write outside of any lock */ pthread_rwlock_unlock(&c->invlock); ts = write(s->fd, metric, len); if (ts < 0) { logerr("aggregator: failed to write to " "pipe (fd=%d): %s\n", s->fd, strerror(errno)); __sync_add_and_fetch(&s->dropped, 1); } else if (ts < len) { logerr("aggregator: uncomplete write on " "pipe (fd=%d)\n", s->fd); __sync_add_and_fetch(&s->dropped, 1); } else { __sync_add_and_fetch(&s->sent, 1); } } /** * Checks if the oldest bucket should be expired, if so, sends out * computed aggregate metrics and moves the bucket to the end of the * list. When no buckets are in use for an invocation, it is removed to * cleanup resources. */ static void * aggregator_expire(void *sub) { aggregator *aggrs = (aggregator *)sub; time_t now; aggregator *s; struct _aggr_bucket *b; struct _aggr_computes *c; struct _aggr_invocations *inv; struct _aggr_invocations *lastinv; double *values; size_t len = 0; int i; unsigned char j; int work; char isempty; while (1) { work = 0; for (s = aggrs; s != NULL; s = s->next) { /* send metrics for buckets that are completely past the * expiry time, unless we are shutting down, then send * metrics for all buckets that have completed */ now = time(NULL) + (__sync_bool_compare_and_swap( &keep_running, 1, 1) ? 0 : s->expire - s->interval); for (c = s->computes; c != NULL; c = c->next) { pthread_rwlock_rdlock(&c->invlock); for (i = 0; i < (1 << AGGR_HT_POW_SIZE); i++) { isempty = 0; for (inv = c->invocations_ht[i]; inv != NULL; inv = inv->next) { for (b = &inv->buckets[0]; b->start + (__sync_bool_compare_and_swap( &keep_running, 1, 1) ? inv->expire : s->expire) < now; b++) { if (!__sync_bool_compare_and_swap( &b->state, A_OPEN, A_EXPIRE)) continue; /* avoid emitting empty/unitialised data */ if (b->cnt > 0) { /* write_metric unlocks before doing the * write to avoid any blocks */ write_metric(s, b, c, inv->metric); pthread_rwlock_rdlock(&c->invlock); } work++; } } } pthread_rwlock_unlock(&c->invlock); } /* now do some cleanup for A_EXPIREd buckets in an exclusive * lock */ for (c = s->computes; c != NULL; c = c->next) { pthread_rwlock_wrlock(&c->invlock); for (i = 0; i < (1 << AGGR_HT_POW_SIZE); i++) { lastinv = NULL; isempty = 0; for (inv = c->invocations_ht[i]; inv != NULL; ) { /* move expired buckets to the end */ b = &inv->buckets[0]; while (b->state == A_EXPIRE) { len = b->entries.size; values = b->entries.values; memmove(b, &inv->buckets[1], sizeof(*b) * (s->bucketcnt - 1)); b = &inv->buckets[s->bucketcnt - 1]; b->cnt = 0; b->start = inv->buckets[s->bucketcnt - 2].start + s->interval; b->entries.size = len; b->entries.values = values; b->state = A_OPEN; b = &inv->buckets[0]; } /* see if the entire invocation is empty */ isempty = 1; for (j = 0; j < s->bucketcnt; j++) { if (inv->buckets[j].cnt != 0) { isempty = 0; break; } } if (isempty) { /* free and unlink */ if (c->entries_needed) for (j = 0; j < s->bucketcnt; j++) if (inv->buckets[j].entries.values) free(inv->buckets[j].entries.values); free(inv->metric); for (j = 0; j < s->bucketcnt; j++) pthread_mutex_destroy(&inv->buckets[j].bcklock); free(inv->buckets); if (lastinv != NULL) { lastinv->next = inv->next; free(inv); inv = lastinv->next; } else { c->invocations_ht[i] = inv->next; free(inv); inv = c->invocations_ht[i]; } } else { lastinv = inv; inv = inv->next; } } } pthread_rwlock_unlock(&c->invlock); } } if (work == 0) { if (__sync_bool_compare_and_swap(&keep_running, 0, 0)) break; /* nothing done, avoid spinlocking */ usleep(250 * 1000); /* 250ms */ } } /* free up value buckets */ while ((s = aggrs) != NULL) { while (s->computes != NULL) { c = s->computes; free((void *)c->metric); for (i = 0; i < 1 << AGGR_HT_POW_SIZE; i++) { inv = c->invocations_ht[i]; while (inv != NULL) { struct _aggr_invocations *invocation = inv; free(inv->metric); if (c->entries_needed) for (j = 0; j < s->bucketcnt; j++) if (inv->buckets[j].entries.values) free(inv->buckets[j].entries.values); for (j = 0; j < s->bucketcnt; j++) pthread_mutex_destroy(&inv->buckets[j].bcklock); free(inv->buckets); inv = invocation->next; free(invocation); } } pthread_rwlock_destroy(&c->invlock); s->computes = c->next; free(c); } aggrs = aggrs->next; free(s); } return NULL; } /** * Returns the number of aggregators defined. */ size_t aggregator_numaggregators(aggregator *aggrs) { size_t totaggregators = 0; aggregator *a; for (a = aggrs; a != NULL; a = a->next) totaggregators++; return totaggregators; } /** * Returns the total number of computations defined. */ size_t aggregator_numcomputes(aggregator *aggrs) { size_t totcomputes = 0; aggregator *a; struct _aggr_computes *c; for (a = aggrs; a != NULL; a = a->next) for (c = a->computes; c != NULL; c = c->next) totcomputes++; return totcomputes; } /** * Initialises and starts the aggregator. Returns false when starting * failed, true otherwise. */ int aggregator_start(aggregator *aggrs) { keep_running = 1; if (pthread_create(&aggregatorid, NULL, aggregator_expire, aggrs) != 0) return 0; return 1; } /** * Shuts down the aggregator. */ void aggregator_stop(void) { __sync_bool_compare_and_swap(&keep_running, 1, 0); pthread_join(aggregatorid, NULL); } /** * Returns an approximate number of received metrics by all aggregators. */ size_t aggregator_get_received(aggregator *a) { size_t totreceived = 0; for ( ; a != NULL; a = a->next) totreceived += __sync_add_and_fetch(&a->received, 0); return totreceived; } /** * Returns an approximate number of metrics received by all aggregators * since the last call to this function. */ inline size_t aggregator_get_received_sub(aggregator *aggrs) { size_t r = aggregator_get_received(aggrs) - prevreceived; prevreceived += r; return r; } /** * Returns an approximate number of metrics sent by all aggregators. */ size_t aggregator_get_sent(aggregator *a) { size_t totsent = 0; for ( ; a != NULL; a = a->next) totsent += __sync_add_and_fetch(&a->sent, 0); return totsent; } /** * Returns an approximate number of metrics sent by all aggregators * since the last call to this function. */ inline size_t aggregator_get_sent_sub(aggregator *aggrs) { size_t r = aggregator_get_sent(aggrs) - prevsent; prevsent += r; return r; } /** * Returns an approximate number of dropped metrics by all aggregators. * Metrics are dropped if they are too much in the past (past expiry * time) or if they are too much in the future. */ size_t aggregator_get_dropped(aggregator *a) { size_t totdropped = 0; for ( ; a != NULL; a = a->next) totdropped += __sync_add_and_fetch(&a->dropped, 0); return totdropped; } /** * Returns an approximate number of metrics dropped by all aggregators * since the last call to this function. */ inline size_t aggregator_get_dropped_sub(aggregator *aggrs) { size_t r = aggregator_get_dropped(aggrs) - prevdropped; prevdropped += r; return r; } carbon-c-relay-3.2/aggregator.h000066400000000000000000000055341317265605500164700ustar00rootroot00000000000000/* * Copyright 2013-2017 Fabian Groffen * * 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. */ #ifndef AGGREGATOR_H #define AGGREGATOR_H 1 #include #include #include "server.h" #define AGGR_HT_POW_SIZE 12 /* 4096: too big? issue #60 */ typedef struct _aggregator { unsigned short interval; /* when to perform the aggregation */ unsigned short expire; /* when incoming metrics are no longer valid */ enum _aggr_timestamp { TS_START, TS_MIDDLE, TS_END } tswhen; unsigned char bucketcnt; int disp_conn; int fd; size_t received; size_t sent; size_t dropped; struct _aggr_computes { enum _aggr_compute_type { SUM, CNT, MAX, MIN, AVG, MEDN, PCTL, VAR, SDEV } type; const char *metric; /* name template of metric to produce */ struct _aggr_invocations { char *metric; /* actual name to emit */ unsigned int hash; /* to speed up matching */ unsigned short expire; /* expire + splay */ struct _aggr_bucket { pthread_mutex_t bcklock; enum { A_OPEN, A_EXPIRE } state; long long int start; size_t cnt; double sum; double max; double min; struct _aggr_bucket_entries { size_t size; double *values; } entries; } *buckets; struct _aggr_invocations *next; } *invocations_ht[1 << AGGR_HT_POW_SIZE]; unsigned char entries_needed:1; unsigned char percentile:7; pthread_rwlock_t invlock; struct _aggr_computes *next; } *computes; struct _aggregator *next; } aggregator; aggregator *aggregator_new(unsigned int interval, unsigned int expire, enum _aggr_timestamp tswhen); char aggregator_add_compute(aggregator *s, const char *metric, enum _aggr_compute_type type, unsigned char pctl); void aggregator_set_stub(aggregator *s, const char *stubname); void aggregator_putmetric(aggregator *s, const char *metric, const char *firstspace, size_t nmatch, regmatch_t *pmatch); int aggregator_start(aggregator *aggrs); void aggregator_stop(void); size_t aggregator_numaggregators(aggregator *agrs); size_t aggregator_numcomputes(aggregator *aggrs); size_t aggregator_get_received(aggregator *aggrs); size_t aggregator_get_sent(aggregator *aggrs); size_t aggregator_get_dropped(aggregator *aggrs); size_t aggregator_get_received_sub(aggregator *aggrs); size_t aggregator_get_sent_sub(aggregator *aggrs); size_t aggregator_get_dropped_sub(aggregator *aggrs); #endif carbon-c-relay-3.2/allocator.c000066400000000000000000000050351317265605500163150ustar00rootroot00000000000000/* * Copyright 2013-2017 Fabian Groffen * * 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. */ #include #include #include #include "allocator.h" struct _cr_allocator { void *memory_region; void *nextp; size_t sz; struct _cr_allocator *next; }; /** * Free the resources associated to this allocator. */ void ra_free(allocator *ra) { allocator *ra_next; for ( ; ra != NULL; ra = ra_next) { free(ra->memory_region); ra_next = ra->next; free(ra); ra = NULL; } } #define ra_alloc(RA, SZ) { \ assert(SZ >= 0); \ nsz = 256 * 1024; \ if (SZ > nsz) \ nsz = ((SZ / 1024) + 1) * 1024; \ RA = malloc(sizeof(allocator)); \ if (RA == NULL) \ return NULL; \ RA->memory_region = malloc(sizeof(char) * nsz); \ if (RA->memory_region == NULL) { \ free(RA); \ RA = NULL; \ return NULL; \ } \ RA->nextp = RA->memory_region; \ RA->sz = nsz; \ RA->next = NULL; \ } /** * Allocate a new allocator. */ allocator * ra_new(void) { allocator *ret; size_t nsz; ra_alloc(ret, 0); return ret; } /** * malloc() in one of the regions for this allocator. If insufficient * memory is available in the region, a new one is allocated. If * that fails, NULL is returned, else a pointer that can be written to * up to sz bytes. The returned region is aligned. */ void * ra_malloc(allocator *ra, size_t sz) { void *retp = NULL; size_t nsz; /* for ra_alloc macro */ for (; ra != NULL; ra = ra->next) { if (ra->sz - (ra->nextp - ra->memory_region) >= sz) { retp = ra->nextp; /* align to arch-width boundaries */ nsz = sz % sizeof(size_t); if (nsz != 0) sz += sizeof(size_t) - nsz; ra->nextp += sz; return retp; } if (ra->next == NULL) ra_alloc(ra->next, sz); } /* this should be unreachable code */ return NULL; } /** * strdup using ra_malloc, e.g. get memory from the region associated * to the given allocated. */ char * ra_strdup(allocator *ra, const char *s) { size_t sz = strlen(s) + 1; char *m = ra_malloc(ra, sz); if (m == NULL) return m; memcpy(m, s, sz); return m; } carbon-c-relay-3.2/allocator.h000066400000000000000000000015401317265605500163170ustar00rootroot00000000000000/* * Copyright 2013-2017 Fabian Groffen * * 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. */ #ifndef _ALLOCATOR_H #define _ALLOCATOR_H 1 #include typedef struct _cr_allocator allocator; void ra_free(allocator *ra); allocator *ra_new(void); void *ra_malloc(allocator *ra, size_t sz); char *ra_strdup(allocator *ra, const char *s); #endif carbon-c-relay-3.2/carbon-c-relay.1000066400000000000000000001254201317265605500170520ustar00rootroot00000000000000.\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . .TH "CARBON\-C\-RELAY" "1" "October 2017" "Graphite" "Graphite data collection and visualisation" . .SH "NAME" \fBcarbon\-c\-relay\fR \- graphite relay, aggregator and rewriter . .SH "SYNOPSIS" \fBcarbon\-c\-relay\fR \fB\-f\fR \fIconfig\-file\fR \fB[ options\fR \.\.\. \fB]\fR . .SH "DESCRIPTION" \fBcarbon\-c\-relay\fR accepts, cleanses, matches, rewrites, forwards and aggregates graphite metrics by listening for incoming connections and relaying the messages to other servers defined in its configuration\. The core functionality is to route messages via flexible rules to the desired destinations\. . .P \fBcarbon\-c\-relay\fR is a simple program that reads its routing information from a file\. The command line arguments allow to set the location for this file, as well as the amount of dispatchers (worker threads) to use for reading the data from incoming connections and passing them onto the right destination(s)\. The route file supports two main constructs: clusters and matches\. The first define groups of hosts data metrics can be sent to, the latter define which metrics should be sent to which cluster\. Aggregation rules are seen as matches\. . .P For every metric received by the relay, cleansing is performed\. The following changes are performed before any match, aggregate or rewrite rule sees the metric: . .IP "\(bu" 4 double dot elimination (necessary for correctly functioning consistent hash routing) . .IP "\(bu" 4 trailing/leading dot elimination . .IP "\(bu" 4 whitespace normalisation (this mostly affects output of the relay to other targets: metric, value and timestamp will be separated by a single space only, ever) . .IP "\(bu" 4 irregular char replacement with underscores (_), currently irregular is defined as not being in \fB[0\-9a\-zA\-Z\-_:#]\fR, but can be overridden on the command line\. . .IP "" 0 . .SH "OPTIONS" These options control the behaviour of \fBcarbon\-c\-relay\fR\. . .TP \fB\-v\fR Print version string and exit\. . .TP \fB\-d\fR Enable debug mode, this prints statistics to stdout and prints extra messages about some situations encountered by the relay that normally would be too verbose to be enabled\. When combined with \fB\-t\fR (test mode) this also prints stub routes and consistent\-hash ring contents\. . .TP \fB\-s\fR Enable submission mode\. In this mode, internal statistics are not generated\. Instead, queue pressure and metrics drops are reported on stdout\. This mode is useful when used as submission relay which\' job is just to forward to (a set of) main relays\. Statistics about the submission relays in this case are not needed, and could easily cause a non\-desired flood of metrics e\.g\. when used on each and every host locally\. . .TP \fB\-t\fR Test mode\. This mode doesn\'t do any routing at all, but instead reads input from stdin and prints what actions would be taken given the loaded configuration\. This mode is very useful for testing relay routes for regular expression syntax etc\. It also allows to give insight on how routing is applied in complex configurations, for it shows rewrites and aggregates taking place as well\. When \fB\-t\fR is repeated, the relay will only test the configuration for validity and exit immediately afterwards\. Any standard output is suppressed in this mode, making it ideal for start\-scripts to test a (new) configuration\. . .TP \fB\-D\fR Deamonise into the background after startup\. This option requires \fB\-l\fR and \fB\-P\fR flags to be set as well\. . .TP \fB\-f\fR \fIconfig\-file\fR Read configuration from \fIconfig\-file\fR\. A configuration consists of clusters and routes\. See \fICONFIGURATION SYNTAX\fR for more information on the options and syntax of this file\. . .TP \fB\-l\fR \fIlog\-file\fR Use \fIlog\-file\fR for writing messages\. Without this option, the relay writes both to \fIstdout\fR and \fIstderr\fR\. When logging to file, all messages are prefixed with \fBMSG\fR when they were sent to \fIstdout\fR, and \fBERR\fR when they were sent to \fIstderr\fR\. . .TP \fB\-p\fR \fIport\fR Listen for connections on port \fIport\fR\. The port number is used for both \fBTCP\fR, \fBUDP\fR and \fBUNIX sockets\fR\. In the latter case, the socket file contains the port number\. The port defaults to \fI2003\fR, which is also used by the original \fBcarbon\-cache\.py\fR\. Note that this only applies to the defaults, when \fBlisten\fR directives are in the config, this setting is ignored\. . .TP \fB\-w\fR \fIworkers\fR Use \fIworkers\fR number of threads\. The default number of workers is equal to the amount of detected CPU cores\. It makes sense to reduce this number on many\-core machines, or when the traffic is low\. . .TP \fB\-b\fR \fIbatchsize\fR Set the amount of metrics that sent to remote servers at once to \fIbatchsize\fR\. When the relay sends metrics to servers, it will retrieve \fBbatchsize\fR metrics from the pending queue of metrics waiting for that server and send those one by one\. The size of the batch will have minimal impact on sending performance, but it controls the amount of lock\-contention on the queue\. The default is \fI2500\fR\. . .TP \fB\-q\fR \fIqueuesize\fR Each server from the configuration where the relay will send metrics to, has a queue associated with it\. This queue allows for disruptions and bursts to be handled\. The size of this queue will be set to \fIqueuesize\fR which allows for that amount of metrics to be stored in the queue before it overflows, and the relay starts dropping metrics\. The larger the queue, more metrics can be absorbed, but also more memory will be used by the relay\. The default queue size is \fI25000\fR\. . .TP \fB\-L\fR \fIstalls\fR Sets the max mount of stalls to \fIstalls\fR before the relay starts dropping metrics for a server\. When a queue fills up, the relay uses a mechanism called stalling to signal the client (writing to the relay) of this event\. In particular when the client sends a large amount of metrics in very short time (burst), stalling can help to avoid dropping metrics, since the client just needs to slow down for a bit, which in many cases is possible (e\.g\. when catting a file with \fBnc\fR(1))\. However, this behaviour can also obstruct, artificially stalling writers which cannot stop that easily\. For this the stalls can be set from \fI0\fR to \fI15\fR, where each stall can take around 1 second on the client\. The default value is set to \fI4\fR, which is aimed at the occasional disruption scenario and max effort to not loose metrics with moderate slowing down of clients\. . .TP \fB\-B\fR \fIbacklog\fR Sets TCP connection listen backlog to \fIbacklog\fR connections\. The default value is \fI32\fR but on servers which receive many concurrent connections, this setting likely needs to be increased to avoid connection refused errors on the clients\. . .TP \fB\-U\fR \fIbufsize\fR Sets the socket send/receive buffer sizes in bytes, for both TCP and UDP scenarios\. When unset, the OS default is used\. The maximum is also determined by the OS\. The sizes are set using setsockopt with the flags SO_RCVBUF and SO_SNDBUF\. Setting this size may be necessary for large volume scenarios, for which also \fB\-B\fR might apply\. Checking the \fIRecv\-Q\fR and the \fIreceive errors\fR values from \fInetstat\fR gives a good hint about buffer usage\. . .TP \fB\-T\fR \fItimeout\fR Specifies the IO timeout in milliseconds used for server connections\. The default is \fI600\fR milliseconds, but may need increasing when WAN links are used for target servers\. A relatively low value for connection timeout allows the relay to quickly establish a server is unreachable, and as such failover strategies to kick in before the queue runs high\. . .TP \fB\-c\fR \fIchars\fR Defines the characters that are next to \fB[A\-Za\-z0\-9]\fR allowed in metrics to \fIchars\fR\. Any character not in this list, is replaced by the relay with \fB_\fR (underscore)\. The default list of allowed characters is \fI\-_:#\fR\. . .TP \fB\-H\fR \fIhostname\fR Override hostname determined by a call to \fBgethostname\fR(3) with \fIhostname\fR\. The hostname is used mainly in the statistics metrics \fBcarbon\.relays\.\.<\.\.\.>\fR sent by the relay\. . .TP \fB\-P\fR \fIpidfile\fR Write the pid of the relay process to a file called \fIpidfile\fR\. This is in particular useful when daemonised in combination with init managers\. . .TP \fB\-O\fR \fIthreshold\fR The minimum number of rules to find before trying to optimise the ruleset\. The default is \fB50\fR, to disable the optimiser, use \fB\-1\fR, to always run the optimiser use \fB0\fR\. The optimiser tries to group rules to avoid spending excessive time on matching expressions\. . .SH "CONFIGURATION SYNTAX" The config file supports the following syntax, where comments start with a \fB#\fR character and can appear at any position on a line and suppress input until the end of that line: . .IP "" 4 . .nf cluster < [useall] | [replication ] > ] [type linemode] [transport ]> \.\.\. ; cluster file [ip] \.\.\. ; match <* | expression \.\.\.> [validate else ] send to [stop] ; rewrite into ; aggregate \.\.\. every seconds expire after seconds [timestamp at of bucket] compute | variance | stddev> write to [compute \.\.\.] [send to ] [stop] ; send statistics to [stop] ; statistics [submit every seconds] [reset counters after interval] [prefix with ] [send to ] [stop] ; listen type linemode [transport >] < proto > \.\.\. \.\.\. ; include ; . .fi . .IP "" 0 . .SS "CLUSTERS" Multiple clusters can be defined, and need not to be referenced by a match rule\. All clusters point to one or more hosts, except the \fBfile\fR cluster which writes to files in the local filesystem\. \fBhost\fR may be an IPv4 or IPv6 address, or a hostname\. Since host is followed by an optional \fB:\fR and port, for IPv6 addresses not to be interpreted wrongly, either a port must be given, or the IPv6 address surrounded by brackets, e\.g\. \fB[::1]\fR\. Optional \fBtransport\fR and \fBproto\fR clauses can be used to wrap the connection in a compression or encryption later or specify the use of UDP or TCP to connect to the remote server\. When omitted the connection defaults to an unwrapped TCP connection\. \fBtype\fR can only be linemode at the moment\. . .P The \fBforward\fR and \fBfile\fR clusters simply send everything they receive to all defined members (host addresses or files)\. The \fBany_of\fR cluster is a small variant of the \fBforward\fR cluster, but instead of sending to all defined members, it sends each incoming metric to one of defined members\. This is not much useful in itself, but since any of the members can receive each metric, this means that when one of the members is unreachable, the other members will receive all of the metrics\. This can be useful when the cluster points to other relays\. The \fBany_of\fR router tries to send the same metrics consistently to the same destination\. The \fBfailover\fR cluster is like the \fBany_of\fR cluster, but sticks to the order in which servers are defined\. This is to implement a pure failover scenario between servers\. The \fBcarbon_ch\fR cluster sends the metrics to the member that is responsible according to the consistent hash algorithm (as used in the original carbon), or multiple members if replication is set to more than 1\. The \fBfnv1a_ch\fR cluster is a identical in behaviour to \fBcarbon_ch\fR, but it uses a different hash technique (FNV1a) which is faster but more importantly defined to get by a limitation of \fBcarbon_ch\fR to use both host and port from the members\. This is useful when multiple targets live on the same host just separated by port\. The instance that original carbon uses to get around this can be set by appending it after the port, separated by an equals sign, e\.g\. \fB127\.0\.0\.1:2006=a\fR for instance \fBa\fR\. When using the \fBfnv1a_ch\fR cluster, this instance overrides the hash key in use\. This allows for many things, including masquerading old IP addresses, but mostly to make the hash key location to become agnostic of the (physical) location of that key\. For example, usage like \fB10\.0\.0\.1:2003=4d79d13554fa1301476c1f9fe968b0ac\fR would allow to change port and/or ip address of the server that receives data for the instance key\. Obviously, this way migration of data can be dealt with much more conveniently\. The \fBjump_fnv1a_ch\fR cluster is also a consistent hash cluster like the previous two, but it does not take the server information into account at all\. Whether this is useful to you depends on your scenario\. The jump hash has a much better balancing over the servers defined in the cluster, at the expense of not being able to remove any server but the last in order\. What this means is that this hash is fine to use with ever growing clusters where older nodes are also replaced at some point\. If you have a cluster where removal of old nodes takes place often, the jump hash is not suitable for you\. Jump hash works with servers in an ordered list without gaps\. To influence the ordering, the instance given to the server will be used as sorting key\. Without, the order will be as given in the file\. It is a good practice to fix the order of the servers with instances such that it is explicit what the right nodes for the jump hash are\. . .P DNS hostnames are resolved to a single address, according to the preference rules in RFC 3484 \fIhttps://www\.ietf\.org/rfc/rfc3484\.txt\fR\. The \fBany_of\fR, \fBfailover\fR and \fBforward\fR clusters have an explicit \fBuseall\fR flag that enables expansion for hostnames resolving to multiple addresses\. Each address returned becomes a cluster destination\. . .SS "MATCHES" Match rules are the way to direct incoming metrics to one or more clusters\. Match rules are processed top to bottom as they are defined in the file\. It is possible to define multiple matches in the same rule\. Each match rule can send data to one or more clusters\. Since match rules "fall through" unless the \fBstop\fR keyword is added, carefully crafted match expression can be used to target multiple clusters or aggregations\. This ability allows to replicate metrics, as well as send certain metrics to alternative clusters with careful ordering and usage of the \fBstop\fR keyword\. The special cluster \fBblackhole\fR discards any metrics sent to it\. This can be useful for weeding out unwanted metrics in certain cases\. Because throwing metrics away is pointless if other matches would accept the same data, a match with as destination the blackhole cluster, has an implicit \fBstop\fR\. The \fBvalidation\fR clause adds a check to the data (what comes after the metric) in the form of a regular expression\. When this expression matches, the match rule will execute as if no validation clause was present\. However, if it fails, the match rule is aborted, and no metrics will be sent to destinations, this is the \fBdrop\fR behaviour\. When \fBlog\fR is used, the metric is logged to stderr\. Care should be taken with the latter to avoid log flooding\. When a validate clause is present, destinations need not to be present, this allows for applying a global validation rule\. Note that the cleansing rules are applied before validation is done, thus the data will not have duplicate spaces\. The \fBroute using\fR clause is used to perform a temporary modification to the key used for input to the consistent hashing routines\. The primary purpose is to route traffic so that appropriate data is sent to the needed aggregation instances\. . .SS "REWRITES" Rewrite rules take a regular expression as input to match incoming metrics, and transform them into the desired new metric name\. In the replacement, backreferences are allowed to match capture groups defined in the input regular expression\. A match of \fBserver\e\.(x|y|z)\e\.\fR allows to use e\.g\. \fBrole\.\e1\.\fR in the substitution\. A few caveats apply to the current implementation of rewrite rules\. First, their location in the config file determines when the rewrite is performed\. The rewrite is done in\-place, as such a match rule before the rewrite would match the original name, a match rule after the rewrite no longer matches the original name\. Care should be taken with the ordering, as multiple rewrite rules in succession can take place, e\.g\. \fBa\fR gets replaced by \fBb\fR and \fBb\fR gets replaced by \fBc\fR in a succeeding rewrite rule\. The second caveat with the current implementation, is that the rewritten metric names are not cleansed, like newly incoming metrics are\. Thus, double dots and potential dangerous characters can appear if the replacement string is crafted to produce them\. It is the responsibility of the writer to make sure the metrics are clean\. If this is an issue for routing, one can consider to have a rewrite\-only instance that forwards all metrics to another instance that will do the routing\. Obviously the second instance will cleanse the metrics as they come in\. The backreference notation allows to lowercase and uppercase the replacement string with the use of the underscore (\fB_\fR) and carret (\fB^\fR) symbols following directly after the backslash\. For example, \fBrole\.\e_1\.\fR as substitution will lowercase the contents of \fB\e1\fR\. The dot (\fB\.\fR) can be used in a similar fashion, or followed after the underscore or caret to replace dots with underscores in the substitution\. This can be handy for some situations where metrics are sent to graphite\. . .SS "AGGREGATIONS" The aggregations defined take one or more input metrics expressed by one or more regular expresions, similar to the match rules\. Incoming metrics are aggregated over a period of time defined by the interval in seconds\. Since events may arrive a bit later in time, the expiration time in seconds defines when the aggregations should be considered final, as no new entries are allowed to be added any more\. On top of an aggregation multiple aggregations can be computed\. They can be of the same or different aggregation types, but should write to a unique new metric\. The metric names can include back references like in rewrite expressions, allowing for powerful single aggregation rules that yield in many aggregations\. When no \fBsend to\fR clause is given, produced metrics are sent to the relay as if they were submitted from the outside, hence match and aggregation rules apply to those\. Care should be taken that loops are avoided this way\. For this reason, the use of the \fBsend to\fR clause is encouraged, to direct the output traffic where possible\. Like for match rules, it is possible to define multiple cluster targets\. Also, like match rules, the \fBstop\fR keyword applies to control the flow of metrics in the matching process\. . .SS "STATISTICS" The \fBsend statistics to\fR construct is deprecated and will be removed in the next release\. Use the special \fBstatistics\fR construct instead\. . .P The \fBstatistics\fR construct can control a couple of things about the (internal) statistics produced by the relay\. The \fBsend to\fR target can be used to avoid router loops by sending the statistics to a certain destination cluster(s)\. By default the metrics are prefixed with \fBcarbon\.relays\.\fR, where hostname is determinted on startup and can be overridden using the \fB\-H\fR argument\. This prefix can be set using the \fBprefix with\fR clause similar to a rewrite rule target\. The input match in this case is the pre\-set regular expression \fB^(([^\.]+)(\e\.\.*)?)$\fR on the hostname\. As such, one can see that the default prefix is set by \fBcarbon\.relays\.\e\.1\fR\. Note that this uses the replace\-dot\-with\-underscore replacement feature from rewrite rules\. Given the input expression, the following match groups are available: \fB\e1\fR the entire hostname, \fB\e2\fR the short hostname and \fB\e3\fR the domainname (with leading dot)\. It may make sense to replace the default by something like \fBcarbon\.relays\.\e_2\fR for certain scenarios, to always use the lowercased short hostname, which following the expression doesn\'t contain a dot\. By default, the metrics are submitted every 60 seconds, this can be changed using the \fBsubmit every seconds\fR clause\. . .br To obtain a more compatible set of values to carbon\-cache\.py, use the \fBreset counters after interval\fR clause to make values non\-cumulative, that is, they will report the change compared to the previous value\. . .SS "LISTENERS" The ports and protocols the relay should listen for incoming connections can be specified using the \fBlisten\fR directive\. Currently, all listeners need to be of \fBlinemode\fR type\. An optional compression or encryption wrapping can be specified for the port and optional interface given by ip address, or unix socket by file\. When interface is not specified, the any interface on all available ip protocols is assumed\. If no \fBlisten\fR directive is present, the relay will use the default listeners for port 2003 on tcp and udp, plus the unix socket \fB/tmp/\.s\.carbon\-c\-relay\.2003\fR\. This typically expands to 5 listeners on an IPv6 enabled system\. The default matches the behaviour of versions prior to v3\.2\. . .SS "INCLUDES" In case configuration becomes very long, or is managed better in separate files, the \fBinclude\fR directive can be used to read another file\. The given file will be read in place and added to the router configuration at the time of inclusion\. The end result is one big route configuration\. Multiple \fBinclude\fR statements can be used throughout the configuration file\. The positioning will influence the order of rules as normal\. Beware that recursive inclusion (\fBinclude\fR from an included file) is supported, and currently no safeguards exist for an inclusion loop\. For what is worth, this feature likely is best used with simple configuration files (e\.g\. not having \fBinclude\fR in them)\. . .SH "EXAMPLES" \fBcarbon\-c\-relay\fR evolved over time, growing features on demand as the tool proved to be stable and fitting the job well\. Below follow some annotated examples of constructs that can be used with the relay\. . .P Clusters can be defined as much as necessary\. They receive data from match rules, and their type defines which members of the cluster finally get the metric data\. The simplest cluster form is a \fBforward\fR cluster: . .IP "" 4 . .nf cluster send\-through forward 10\.1\.0\.1 ; . .fi . .IP "" 0 . .P Any metric sent to the \fBsend\-through\fR cluster would simply be forwarded to the server at IPv4 address \fB10\.1\.0\.1\fR\. If we define multiple servers, all of those servers would get the same metric, thus: . .IP "" 4 . .nf cluster send\-through forward 10\.1\.0\.1 10\.2\.0\.1 ; . .fi . .IP "" 0 . .P The above results in a duplication of metrics send to both machines\. This can be useful, but most of the time it is not\. The \fBany_of\fR cluster type is like \fBforward\fR, but it sends each incoming metric to any of the members\. The same example with such cluster would be: . .IP "" 4 . .nf cluster send\-to\-any\-one any_of 10\.1\.0\.1:2010 10\.1\.0\.1:2011; . .fi . .IP "" 0 . .P This would implement a multipath scenario, where two servers are used, the load between them is spread, but should any of them fail, all metrics are sent to the remaining one\. This typically works well for upstream relays, or for balancing carbon\-cache processes running on the same machine\. Should any member become unavailable, for instance due to a rolling restart, the other members receive the traffic\. If it is necessary to have true fail\-over, where the secondary server is only used if the first is down, the following would implement that: . .IP "" 4 . .nf cluster try\-first\-then\-second failover 10\.1\.0\.1:2010 10\.1\.0\.1:2011; . .fi . .IP "" 0 . .P These types are different from the two consistent hash cluster types: . .IP "" 4 . .nf cluster graphite carbon_ch 127\.0\.0\.1:2006=a 127\.0\.0\.1:2007=b 127\.0\.0\.1:2008=c ; . .fi . .IP "" 0 . .P If a member in this example fails, all metrics that would go to that member are kept in the queue, waiting for the member to return\. This is useful for clusters of carbon\-cache machines where it is desirable that the same metric ends up on the same server always\. The \fBcarbon_ch\fR cluster type is compatible with carbon\-relay consistent hash, and can be used for existing clusters populated by carbon\-relay\. For new clusters, however, it is better to use the \fBfnv1a_ch\fR cluster type, for it is faster, and allows to balance over the same address but different ports without an instance number, in constrast to \fBcarbon_ch\fR\. . .P Because we can use multiple clusters, we can also replicate without the use of the \fBforward\fR cluster type, in a more intelligent way: . .IP "" 4 . .nf cluster dc\-old carbon_ch replication 2 10\.1\.0\.1 10\.1\.0\.2 10\.1\.0\.3 ; cluster dc\-new1 fnv1a_ch replication 2 10\.2\.0\.1 10\.2\.0\.2 10\.2\.0\.3 ; cluster dc\-new2 fnv1a_ch replication 2 10\.3\.0\.1 10\.3\.0\.2 10\.3\.0\.3 ; match * send to dc\-old ; match * send to dc\-new1 dc\-new2 stop ; . .fi . .IP "" 0 . .P In this example all incoming metrics are first sent to \fBdc\-old\fR, then \fBdc\-new1\fR and finally to \fBdc\-new2\fR\. Note that the cluster type of \fBdc\-old\fR is different\. Each incoming metric will be send to 2 members of all three clusters, thus replicating to in total 6 destinations\. For each cluster the destination members are computed independently\. Failure of clusters or members does not affect the others, since all have individual queues\. The above example could also be written using three match rules for each dc, or one match rule for all three dcs\. The difference is mainly in performance, the number of times the incoming metric has to be matched against an expression\. The \fBstop\fR rule in \fBdc\-new\fR match rule is not strictly necessary in this example, because there are no more following match rules\. However, if the match would target a specific subset, e\.g\. \fB^sys\e\.\fR, and more clusters would be defined, this could be necessary, as for instance in the following abbreviated example: . .IP "" 4 . .nf cluster dc1\-sys \.\.\. ; cluster dc2\-sys \.\.\. ; cluster dc1\-misc \.\.\. ; cluster dc2\-misc \.\.\. ; match ^sys\e\. send to dc1\-sys; match ^sys\e\. send to dc2\-sys stop; match * send to dc1\-misc; match * send to dc2\-misc stop; . .fi . .IP "" 0 . .P As can be seen, without the \fBstop\fR in dc2\-sys\' match rule, all metrics starting with \fBsys\.\fR would also be send to dc1\-misc and dc2\-misc\. It can be that this is desired, of course, but in this example there is a dedicated cluster for the \fBsys\fR metrics\. . .P Suppose there would be some unwanted metric that unfortunately is generated, let\'s assume some bad/old software\. We don\'t want to store this metric\. The \fBblackhole\fR cluster is suitable for that, when it is harder to actually whitelist all wanted metrics\. Consider the following: . .IP "" 4 . .nf match some_legacy1$ some_legacy2$ send to blackhole stop; . .fi . .IP "" 0 . .P This would throw away all metrics that end with \fBsome_legacy\fR, that would otherwise be hard to filter out\. Since the order matters, it can be used in a construct like this: . .IP "" 4 . .nf cluster old \.\.\. ; cluster new \.\.\. ; match * send to old; match unwanted send to blackhole stop; match * send to new; . .fi . .IP "" 0 . .P In this example the old cluster would receive the metric that\'s unwanted for the new cluster\. So, the order in which the rules occur does matter for the execution\. . .P Validation can be used to ensure the data for metrics is as expected\. A global validation for just number (no floating point) values could be: . .IP "" 4 . .nf match * validate ^[0\-9]+\e [0\-9]+$ else drop ; . .fi . .IP "" 0 . .P (Note the escape with backslash \fB\e\fR of the space, you might be able to use \fB\es\fR or \fB[:space:]\fR instead, this depends on your libc implementation\.) . .P The validation clause can exist on every match rule, so in principle, the following is valid: . .IP "" 4 . .nf match ^foo validate ^[0\-9]+\e [0\-9]+$ else drop send to integer\-cluster ; match ^foo validate ^[0\-9\.e+\-]+\e [0\-9\.e+\-]+$ else drop send to float\-cluster stop; . .fi . .IP "" 0 . .P Note that the behaviour is different in the previous two examples\. When no \fBsend to\fR clusters are specified, a validation error makes the match behave like the \fBstop\fR keyword is present\. Likewise, when validation passes, processing continues with the next rule\. When destination clusters are present, the \fBmatch\fR respects the \fBstop\fR keyword as normal\. When specified, processing will always stop when specified so\. However, if validation fails, the rule does not send anything to the destination clusters, the metric will be dropped or logged, but never sent\. . .P The relay is capable of rewriting incoming metrics on the fly\. This process is done based on regular expressions with capture groups that allow to substitute parts in a replacement string\. Rewrite rules allow to cleanup metrics from applications, or provide a migration path\. In it\'s simplest form a rewrite rule looks like this: . .IP "" 4 . .nf rewrite ^server\e\.(\.+)\e\.(\.+)\e\.([a\-zA\-Z]+)([0\-9]+) into server\.\e_1\.\e2\.\e3\.\e3\e4 ; . .fi . .IP "" 0 . .P In this example a metric like \fBserver\.DC\.role\.name123\fR would be transformed into \fBserver\.dc\.role\.name\.name123\fR\. For rewrite rules hold the same as for matches, that their order matters\. Hence to build on top of the old/new cluster example done earlier, the following would store the original metric name in the old cluster, and the new metric name in the new cluster: . .IP "" 4 . .nf match * send to old; rewrite \.\.\. ; match * send to new; . .fi . .IP "" 0 . .P Note that after the rewrite, the original metric name is no longer available, as the rewrite happens in\-place\. . .P Aggregations are probably the most complex part of carbon\-c\-relay\. Two ways of specifying aggregates are supported by carbon\-c\-relay\. The first, static rules, are handled by an optimiser which tries to fold thousands of rules into groups to make the matching more efficient\. The second, dynamic rules, are very powerful compact definitions with possibly thousands of internal instantiations\. A typical static aggregation looks like: . .IP "" 4 . .nf aggregate ^sys\e\.dc1\e\.somehost\-[0\-9]+\e\.somecluster\e\.mysql\e\.replication_delay ^sys\e\.dc2\e\.somehost\-[0\-9]+\e\.somecluster\e\.mysql\e\.replication_delay every 10 seconds expire after 35 seconds timestamp at end of bucket compute sum write to mysql\.somecluster\.total_replication_delay compute average write to mysql\.somecluster\.average_replication_delay compute max write to mysql\.somecluster\.max_replication_delay compute count write to mysql\.somecluster\.replication_delay_metric_count ; . .fi . .IP "" 0 . .P In this example, four aggregations are produced from the incoming matching metrics\. In this example we could have written the two matches as one, but for demonstration purposes we did not\. Obviously they can refer to different metrics, if that makes sense\. The \fBevery 10 seconds\fR clause specifies in what interval the aggregator can expect new metrics to arrive\. This interval is used to produce the aggregations, thus each 10 seconds 4 new metrics are generated from the data received sofar\. Because data may be in transit for some reason, or generation stalled, the \fBexpire after\fR clause specifies how long the data should be kept before considering a data bucket (which is aggregated) to be complete\. In the example, 35 was used, which means after 35 seconds the first aggregates are produced\. It also means that metrics can arrive 35 seconds late, and still be taken into account\. The exact time at which the aggregate metrics are produced is random between 0 and interval (10 in this case) seconds after the expiry time\. This is done to prevent thundering herds of metrics for large aggregation sets\. The \fBtimestamp\fR that is used for the aggregations can be specified to be the \fBstart\fR, \fBmiddle\fR or \fBend\fR of the bucket\. Original carbon\-aggregator\.py uses \fBstart\fR, while carbon\-c\-relay\'s default has always been \fBend\fR\. The \fBcompute\fR clauses demonstrate a single aggregation rule can produce multiple aggregates, as often is the case\. Internally, this comes for free, since all possible aggregates are always calculated, whether or not they are used\. The produced new metrics are resubmitted to the relay, hence matches defined before in the configuration can match output of the aggregator\. It is important to avoid loops, that can be generated this way\. In general, splitting aggregations to their own carbon\-c\-relay instance, such that it is easy to forward the produced metrics to another relay instance is a good practice\. . .P The previous example could also be written as follows to be dynamic: . .IP "" 4 . .nf aggregate ^sys\e\.dc[0\-9]\.(somehost\-[0\-9]+)\e\.([^\.]+)\e\.mysql\e\.replication_delay every 10 seconds expire after 35 seconds compute sum write to mysql\.host\.\e1\.replication_delay compute sum write to mysql\.host\.all\.replication_delay compute sum write to mysql\.cluster\.\e2\.replication_delay compute sum write to mysql\.cluster\.all\.replication_delay ; . .fi . .IP "" 0 . .P Here a single match, results in four aggregations, each of a different scope\. In this example aggregation based on hostname and cluster are being made, as well as the more general \fBall\fR targets, which in this example have both identical values\. Note that with this single aggregation rule, both per\-cluster, per\-host and total aggregations are produced\. Obviously, the input metrics define which hosts and clusters are produced\. . .P With use of the \fBsend to\fR clause, aggregations can be made more intuitive and less error\-prone\. Consider the below example: . .IP "" 4 . .nf cluster graphite fnv1a_ch ip1 ip2 ip3; aggregate ^sys\e\.somemetric every 60 seconds expire after 75 seconds compute sum write to sys\.somemetric send to graphite stop ; match * send to graphite; . .fi . .IP "" 0 . .P It sends all incoming metrics to the graphite cluster, except the sys\.somemetric ones, which it replaces with a sum of all the incoming ones\. Without a \fBstop\fR in the aggregate, this causes a loop, and without the \fBsend to\fR, the metric name can\'t be kept its original name, for the output now directly goes to the cluster\. . .SH "STATISTICS" When \fBcarbon\-c\-relay\fR is run without \fB\-d\fR or \fB\-s\fR arguments, statistics will be produced\. By default they are sent to the relay itself in the form of \fBcarbon\.relays\.\.*\fR\. See the \fBstatistics\fR construct to override this prefix, sending interval and values produced\. While many metrics have a similar name to what carbon\-cache\.py would produce, their values are likely different\. By default, most values are running counters which only increase over time\. The use of the nonNegativeDerivative() function from graphite is useful with these\. . .P The following metrics are produced under the \fBcarbon\.relays\.\fR namespace: . .IP "\(bu" 4 metricsReceived . .IP The number of metrics that were received by the relay\. Received here means that they were seen and processed by any of the dispatchers\. . .IP "\(bu" 4 metricsSent . .IP The number of metrics that were sent from the relay\. This is a total count for all servers combined\. When incoming metrics are duplicated by the cluster configuration, this counter will include all those duplications\. In other words, the amount of metrics that were successfully sent to other systems\. Note that metrics that are processed (received) but still in the sending queue (queued) are not included in this counter\. . .IP "\(bu" 4 metricsQueued . .IP The total number of metrics that are currently in the queues for all the server targets\. This metric is not cumulative, for it is a sample of the queue size, which can (and should) go up and down\. Therefore you should not use the derivative function for this metric\. . .IP "\(bu" 4 metricsDropped . .IP The total number of metric that had to be dropped due to server queues overflowing\. A queue typically overflows when the server it tries to send its metrics to is not reachable, or too slow in ingesting the amount of metrics queued\. This can be network or resource related, and also greatly depends on the rate of metrics being sent to the particular server\. . .IP "\(bu" 4 metricsBlackholed . .IP The number of metrics that did not match any rule, or matched a rule with blackhole as target\. Depending on your configuration, a high value might be an indication of a misconfiguration somewhere\. These metrics were received by the relay, but never sent anywhere, thus they disappeared\. . .IP "\(bu" 4 metricStalls . .IP The number of times the relay had to stall a client to indicate that the downstream server cannot handle the stream of metrics\. A stall is only performed when the queue is full and the server is actually receptive of metrics, but just too slow at the moment\. Stalls typically happen during micro\-bursts, where the client typically is unaware that it should stop sending more data, while it is able to\. . .IP "\(bu" 4 connections . .IP The number of connect requests handled\. This is an ever increasing number just counting how many connections were accepted\. . .IP "\(bu" 4 disconnects . .IP The number of disconnected clients\. A disconnect either happens because the client goes away, or due to an idle timeout in the relay\. The difference between this metric and connections is the amount of connections actively held by the relay\. In normal situations this amount remains within reasonable bounds\. Many connections, but few disconnections typically indicate a possible connection leak in the client\. The idle connections disconnect in the relay here is to guard against resource drain in such scenarios\. . .IP "\(bu" 4 dispatch_wallTime_us . .IP The number of microseconds spent by the dispatchers to do their work\. In particular on multi\-core systems, this value can be confusing, however, it indicates how long the dispatchers were doing work handling clients\. It includes everything they do, from reading data from a socket, cleaning up the input metric, to adding the metric to the appropriate queues\. The larger the configuration, and more complex in terms of matches, the more time the dispatchers will spend on the cpu\. But also time they do /not/ spend on the cpu is included in this number\. It is the pure wallclock time the dispatcher was serving a client\. . .IP "\(bu" 4 dispatch_sleepTime_us . .IP The number of microseconds spent by the dispatchers sleeping waiting for work\. When this value gets small (or even zero) the dispatcher has so much work that it doesn\'t sleep any more, and likely can\'t process the work in a timely fashion any more\. This value plus the wallTime from above sort of sums up to the total uptime taken by this dispatcher\. Therefore, expressing the wallTime as percentage of this sum gives the busyness percentage draining all the way up to 100% if sleepTime goes to 0\. . .IP "\(bu" 4 server_wallTime_us . .IP The number of microseconds spent by the servers to send the metrics from their queues\. This value includes connection creation, reading from the queue, and sending metrics over the network\. . .IP "\(bu" 4 dispatcherX . .IP For each indivual dispatcher, the metrics received and blackholed plus the wall clock time\. The values are as described above\. . .IP "\(bu" 4 destinations\.X . .IP For all known destinations, the number of dropped, queued and sent metrics plus the wall clock time spent\. The values are as described above\. . .IP "\(bu" 4 aggregators\.metricsReceived . .IP The number of metrics that were matched an aggregator rule and were accepted by the aggregator\. When a metric matches multiple aggregators, this value will reflect that\. A metric is not counted when it is considered syntactically invalid, e\.g\. no value was found\. . .IP "\(bu" 4 aggregators\.metricsDropped . .IP The number of metrics that were sent to an aggregator, but did not fit timewise\. This is either because the metric was too far in the past or future\. The expire after clause in aggregate statements controls how long in the past metric values are accepted\. . .IP "\(bu" 4 aggregators\.metricsSent . .IP The number of metrics that were sent from the aggregators\. These metrics were produced and are the actual results of aggregations\. . .IP "" 0 . .SH "BUGS" Please report them at: \fIhttps://github\.com/grobian/carbon\-c\-relay/issues\fR . .SH "AUTHOR" Fabian Groffen . .SH "SEE ALSO" All other utilities from the graphite stack\. . .P This project aims to be a fast replacement of the original Carbon relay \fIhttp://graphite\.readthedocs\.org/en/1\.0/carbon\-daemons\.html#carbon\-relay\-py\fR\. \fBcarbon\-c\-relay\fR aims to deliver performance and configurability\. Carbon is single threaded, and sending metrics to multiple consistent\-hash clusters requires chaining of relays\. This project provides a multithreaded relay which can address multiple targets and clusters for each and every metric based on pattern matches\. . .P There are a couple more replacement projects out there, which are carbon\-relay\-ng \fIhttps://github\.com/graphite\-ng/carbon\-relay\-ng\fR and graphite\-relay \fIhttps://github\.com/markchadwick/graphite\-relay\fR\. . .P Compared to carbon\-relay\-ng, this project does provide carbon\'s consistent\-hash routing\. graphite\-relay, which does this, however doesn\'t do metric\-based matches to direct the traffic, which this project does as well\. To date, carbon\-c\-relay can do aggregations, failover targets and more\. . .SH "ACKNOWLEDGEMENTS" This program was originally developed for Booking\.com, which approved that the code was published and released as Open Source on GitHub, for which the author would like to express his gratitude\. Development has continued since with the help of many contributors suggesting features, reporting bugs, adding patches and more to make carbon\-c\-relay into what it is today\. carbon-c-relay-3.2/carbon-c-relay.md000066400000000000000000001217601317265605500173150ustar00rootroot00000000000000carbon-c-relay(1) -- graphite relay, aggregator and rewriter ============================================================ [![Build Status](https://travis-ci.org/grobian/carbon-c-relay.svg)](https://travis-ci.org/grobian/carbon-c-relay) ## SYNOPSIS `carbon-c-relay` `-f` *config-file* `[ options` ... `]` ## DESCRIPTION **carbon-c-relay** accepts, cleanses, matches, rewrites, forwards and aggregates graphite metrics by listening for incoming connections and relaying the messages to other servers defined in its configuration. The core functionality is to route messages via flexible rules to the desired destinations. **carbon-c-relay** is a simple program that reads its routing information from a file. The command line arguments allow to set the location for this file, as well as the amount of dispatchers (worker threads) to use for reading the data from incoming connections and passing them onto the right destination(s). The route file supports two main constructs: clusters and matches. The first define groups of hosts data metrics can be sent to, the latter define which metrics should be sent to which cluster. Aggregation rules are seen as matches. For every metric received by the relay, cleansing is performed. The following changes are performed before any match, aggregate or rewrite rule sees the metric: - double dot elimination (necessary for correctly functioning consistent hash routing) - trailing/leading dot elimination - whitespace normalisation (this mostly affects output of the relay to other targets: metric, value and timestamp will be separated by a single space only, ever) - irregular char replacement with underscores (\_), currently irregular is defined as not being in `[0-9a-zA-Z-_:#]`, but can be overridden on the command line. ## OPTIONS These options control the behaviour of **carbon-c-relay**. * `-v`: Print version string and exit. * `-d`: Enable debug mode, this prints statistics to stdout and prints extra messages about some situations encountered by the relay that normally would be too verbose to be enabled. When combined with `-t` (test mode) this also prints stub routes and consistent-hash ring contents. * `-s`: Enable submission mode. In this mode, internal statistics are not generated. Instead, queue pressure and metrics drops are reported on stdout. This mode is useful when used as submission relay which' job is just to forward to (a set of) main relays. Statistics about the submission relays in this case are not needed, and could easily cause a non-desired flood of metrics e.g. when used on each and every host locally. * `-t`: Test mode. This mode doesn't do any routing at all, but instead reads input from stdin and prints what actions would be taken given the loaded configuration. This mode is very useful for testing relay routes for regular expression syntax etc. It also allows to give insight on how routing is applied in complex configurations, for it shows rewrites and aggregates taking place as well. When `-t` is repeated, the relay will only test the configuration for validity and exit immediately afterwards. Any standard output is suppressed in this mode, making it ideal for start-scripts to test a (new) configuration. * `-D`: Deamonise into the background after startup. This option requires `-l` and `-P` flags to be set as well. * `-f` *config-file*: Read configuration from *config-file*. A configuration consists of clusters and routes. See [CONFIGURATION SYNTAX](#configuration-syntax) for more information on the options and syntax of this file. * `-l` *log-file*: Use *log-file* for writing messages. Without this option, the relay writes both to *stdout* and *stderr*. When logging to file, all messages are prefixed with `MSG` when they were sent to *stdout*, and `ERR` when they were sent to *stderr*. * `-p` *port*: Listen for connections on port *port*. The port number is used for both `TCP`, `UDP` and `UNIX sockets`. In the latter case, the socket file contains the port number. The port defaults to *2003*, which is also used by the original `carbon-cache.py`. Note that this only applies to the defaults, when `listen` directives are in the config, this setting is ignored. * `-w` *workers*: Use *workers* number of threads. The default number of workers is equal to the amount of detected CPU cores. It makes sense to reduce this number on many-core machines, or when the traffic is low. * `-b` *batchsize*: Set the amount of metrics that sent to remote servers at once to *batchsize*. When the relay sends metrics to servers, it will retrieve `batchsize` metrics from the pending queue of metrics waiting for that server and send those one by one. The size of the batch will have minimal impact on sending performance, but it controls the amount of lock-contention on the queue. The default is *2500*. * `-q` *queuesize*: Each server from the configuration where the relay will send metrics to, has a queue associated with it. This queue allows for disruptions and bursts to be handled. The size of this queue will be set to *queuesize* which allows for that amount of metrics to be stored in the queue before it overflows, and the relay starts dropping metrics. The larger the queue, more metrics can be absorbed, but also more memory will be used by the relay. The default queue size is *25000*. * `-L` *stalls*: Sets the max mount of stalls to *stalls* before the relay starts dropping metrics for a server. When a queue fills up, the relay uses a mechanism called stalling to signal the client (writing to the relay) of this event. In particular when the client sends a large amount of metrics in very short time (burst), stalling can help to avoid dropping metrics, since the client just needs to slow down for a bit, which in many cases is possible (e.g. when catting a file with `nc`(1)). However, this behaviour can also obstruct, artificially stalling writers which cannot stop that easily. For this the stalls can be set from *0* to *15*, where each stall can take around 1 second on the client. The default value is set to *4*, which is aimed at the occasional disruption scenario and max effort to not loose metrics with moderate slowing down of clients. * `-B` *backlog*: Sets TCP connection listen backlog to *backlog* connections. The default value is *32* but on servers which receive many concurrent connections, this setting likely needs to be increased to avoid connection refused errors on the clients. * `-U` *bufsize*: Sets the socket send/receive buffer sizes in bytes, for both TCP and UDP scenarios. When unset, the OS default is used. The maximum is also determined by the OS. The sizes are set using setsockopt with the flags SO_RCVBUF and SO_SNDBUF. Setting this size may be necessary for large volume scenarios, for which also `-B` might apply. Checking the *Recv-Q* and the *receive errors* values from *netstat* gives a good hint about buffer usage. * `-T` *timeout*: Specifies the IO timeout in milliseconds used for server connections. The default is *600* milliseconds, but may need increasing when WAN links are used for target servers. A relatively low value for connection timeout allows the relay to quickly establish a server is unreachable, and as such failover strategies to kick in before the queue runs high. * `-c` *chars*: Defines the characters that are next to `[A-Za-z0-9]` allowed in metrics to *chars*. Any character not in this list, is replaced by the relay with `_` (underscore). The default list of allowed characters is *-_:#*. * `-H` *hostname*: Override hostname determined by a call to `gethostname`(3) with *hostname*. The hostname is used mainly in the statistics metrics `carbon.relays..<...>` sent by the relay. * `-P` *pidfile*: Write the pid of the relay process to a file called *pidfile*. This is in particular useful when daemonised in combination with init managers. * `-O` *threshold*: The minimum number of rules to find before trying to optimise the ruleset. The default is `50`, to disable the optimiser, use `-1`, to always run the optimiser use `0`. The optimiser tries to group rules to avoid spending excessive time on matching expressions. ## CONFIGURATION SYNTAX The config file supports the following syntax, where comments start with a `#` character and can appear at any position on a line and suppress input until the end of that line: ``` cluster < [useall] | [replication ] > ] [type linemode] [transport ]> ... ; cluster file [ip] ... ; match <* | expression ...> [validate else ] send to [stop] ; rewrite into ; aggregate ... every seconds expire after seconds [timestamp at of bucket] compute | variance | stddev> write to [compute ...] [send to ] [stop] ; send statistics to [stop] ; statistics [submit every seconds] [reset counters after interval] [prefix with ] [send to ] [stop] ; listen type linemode [transport >] < proto > ... ... ; include ; ``` ### CLUSTERS Multiple clusters can be defined, and need not to be referenced by a match rule. All clusters point to one or more hosts, except the `file` cluster which writes to files in the local filesystem. `host` may be an IPv4 or IPv6 address, or a hostname. Since host is followed by an optional `:` and port, for IPv6 addresses not to be interpreted wrongly, either a port must be given, or the IPv6 address surrounded by brackets, e.g. `[::1]`. Optional `transport` and `proto` clauses can be used to wrap the connection in a compression or encryption later or specify the use of UDP or TCP to connect to the remote server. When omitted the connection defaults to an unwrapped TCP connection. `type` can only be linemode at the moment. The `forward` and `file` clusters simply send everything they receive to all defined members (host addresses or files). The `any_of` cluster is a small variant of the `forward` cluster, but instead of sending to all defined members, it sends each incoming metric to one of defined members. This is not much useful in itself, but since any of the members can receive each metric, this means that when one of the members is unreachable, the other members will receive all of the metrics. This can be useful when the cluster points to other relays. The `any_of` router tries to send the same metrics consistently to the same destination. The `failover` cluster is like the `any_of` cluster, but sticks to the order in which servers are defined. This is to implement a pure failover scenario between servers. The `carbon_ch` cluster sends the metrics to the member that is responsible according to the consistent hash algorithm (as used in the original carbon), or multiple members if replication is set to more than 1. The `fnv1a_ch` cluster is a identical in behaviour to `carbon_ch`, but it uses a different hash technique (FNV1a) which is faster but more importantly defined to get by a limitation of `carbon_ch` to use both host and port from the members. This is useful when multiple targets live on the same host just separated by port. The instance that original carbon uses to get around this can be set by appending it after the port, separated by an equals sign, e.g. `127.0.0.1:2006=a` for instance `a`. When using the `fnv1a_ch` cluster, this instance overrides the hash key in use. This allows for many things, including masquerading old IP addresses, but mostly to make the hash key location to become agnostic of the (physical) location of that key. For example, usage like `10.0.0.1:2003=4d79d13554fa1301476c1f9fe968b0ac` would allow to change port and/or ip address of the server that receives data for the instance key. Obviously, this way migration of data can be dealt with much more conveniently. The `jump_fnv1a_ch` cluster is also a consistent hash cluster like the previous two, but it does not take the server information into account at all. Whether this is useful to you depends on your scenario. The jump hash has a much better balancing over the servers defined in the cluster, at the expense of not being able to remove any server but the last in order. What this means is that this hash is fine to use with ever growing clusters where older nodes are also replaced at some point. If you have a cluster where removal of old nodes takes place often, the jump hash is not suitable for you. Jump hash works with servers in an ordered list without gaps. To influence the ordering, the instance given to the server will be used as sorting key. Without, the order will be as given in the file. It is a good practice to fix the order of the servers with instances such that it is explicit what the right nodes for the jump hash are. DNS hostnames are resolved to a single address, according to the preference rules in [RFC 3484](https://www.ietf.org/rfc/rfc3484.txt). The `any_of`, `failover` and `forward` clusters have an explicit `useall` flag that enables expansion for hostnames resolving to multiple addresses. Each address returned becomes a cluster destination. ### MATCHES Match rules are the way to direct incoming metrics to one or more clusters. Match rules are processed top to bottom as they are defined in the file. It is possible to define multiple matches in the same rule. Each match rule can send data to one or more clusters. Since match rules "fall through" unless the `stop` keyword is added, carefully crafted match expression can be used to target multiple clusters or aggregations. This ability allows to replicate metrics, as well as send certain metrics to alternative clusters with careful ordering and usage of the `stop` keyword. The special cluster `blackhole` discards any metrics sent to it. This can be useful for weeding out unwanted metrics in certain cases. Because throwing metrics away is pointless if other matches would accept the same data, a match with as destination the blackhole cluster, has an implicit `stop`. The `validation` clause adds a check to the data (what comes after the metric) in the form of a regular expression. When this expression matches, the match rule will execute as if no validation clause was present. However, if it fails, the match rule is aborted, and no metrics will be sent to destinations, this is the `drop` behaviour. When `log` is used, the metric is logged to stderr. Care should be taken with the latter to avoid log flooding. When a validate clause is present, destinations need not to be present, this allows for applying a global validation rule. Note that the cleansing rules are applied before validation is done, thus the data will not have duplicate spaces. The `route using` clause is used to perform a temporary modification to the key used for input to the consistent hashing routines. The primary purpose is to route traffic so that appropriate data is sent to the needed aggregation instances. ### REWRITES Rewrite rules take a regular expression as input to match incoming metrics, and transform them into the desired new metric name. In the replacement, backreferences are allowed to match capture groups defined in the input regular expression. A match of `server\.(x|y|z)\.` allows to use e.g. `role.\1.` in the substitution. A few caveats apply to the current implementation of rewrite rules. First, their location in the config file determines when the rewrite is performed. The rewrite is done in-place, as such a match rule before the rewrite would match the original name, a match rule after the rewrite no longer matches the original name. Care should be taken with the ordering, as multiple rewrite rules in succession can take place, e.g. `a` gets replaced by `b` and `b` gets replaced by `c` in a succeeding rewrite rule. The second caveat with the current implementation, is that the rewritten metric names are not cleansed, like newly incoming metrics are. Thus, double dots and potential dangerous characters can appear if the replacement string is crafted to produce them. It is the responsibility of the writer to make sure the metrics are clean. If this is an issue for routing, one can consider to have a rewrite-only instance that forwards all metrics to another instance that will do the routing. Obviously the second instance will cleanse the metrics as they come in. The backreference notation allows to lowercase and uppercase the replacement string with the use of the underscore (`_`) and carret (`^`) symbols following directly after the backslash. For example, `role.\_1.` as substitution will lowercase the contents of `\1`. The dot (`.`) can be used in a similar fashion, or followed after the underscore or caret to replace dots with underscores in the substitution. This can be handy for some situations where metrics are sent to graphite. ### AGGREGATIONS The aggregations defined take one or more input metrics expressed by one or more regular expresions, similar to the match rules. Incoming metrics are aggregated over a period of time defined by the interval in seconds. Since events may arrive a bit later in time, the expiration time in seconds defines when the aggregations should be considered final, as no new entries are allowed to be added any more. On top of an aggregation multiple aggregations can be computed. They can be of the same or different aggregation types, but should write to a unique new metric. The metric names can include back references like in rewrite expressions, allowing for powerful single aggregation rules that yield in many aggregations. When no `send to` clause is given, produced metrics are sent to the relay as if they were submitted from the outside, hence match and aggregation rules apply to those. Care should be taken that loops are avoided this way. For this reason, the use of the `send to` clause is encouraged, to direct the output traffic where possible. Like for match rules, it is possible to define multiple cluster targets. Also, like match rules, the `stop` keyword applies to control the flow of metrics in the matching process. ### STATISTICS The `send statistics to` construct is deprecated and will be removed in the next release. Use the special `statistics` construct instead. The `statistics` construct can control a couple of things about the (internal) statistics produced by the relay. The `send to` target can be used to avoid router loops by sending the statistics to a certain destination cluster(s). By default the metrics are prefixed with `carbon.relays.`, where hostname is determinted on startup and can be overridden using the `-H` argument. This prefix can be set using the `prefix with` clause similar to a rewrite rule target. The input match in this case is the pre-set regular expression `^(([^.]+)(\..*)?)$` on the hostname. As such, one can see that the default prefix is set by `carbon.relays.\.1`. Note that this uses the replace-dot-with-underscore replacement feature from rewrite rules. Given the input expression, the following match groups are available: `\1` the entire hostname, `\2` the short hostname and `\3` the domainname (with leading dot). It may make sense to replace the default by something like `carbon.relays.\_2` for certain scenarios, to always use the lowercased short hostname, which following the expression doesn't contain a dot. By default, the metrics are submitted every 60 seconds, this can be changed using the `submit every seconds` clause. To obtain a more compatible set of values to carbon-cache.py, use the `reset counters after interval` clause to make values non-cumulative, that is, they will report the change compared to the previous value. ### LISTENERS The ports and protocols the relay should listen for incoming connections can be specified using the `listen` directive. Currently, all listeners need to be of `linemode` type. An optional compression or encryption wrapping can be specified for the port and optional interface given by ip address, or unix socket by file. When interface is not specified, the any interface on all available ip protocols is assumed. If no `listen` directive is present, the relay will use the default listeners for port 2003 on tcp and udp, plus the unix socket `/tmp/.s.carbon-c-relay.2003`. This typically expands to 5 listeners on an IPv6 enabled system. The default matches the behaviour of versions prior to v3.2. ### INCLUDES In case configuration becomes very long, or is managed better in separate files, the `include` directive can be used to read another file. The given file will be read in place and added to the router configuration at the time of inclusion. The end result is one big route configuration. Multiple `include` statements can be used throughout the configuration file. The positioning will influence the order of rules as normal. Beware that recursive inclusion (`include` from an included file) is supported, and currently no safeguards exist for an inclusion loop. For what is worth, this feature likely is best used with simple configuration files (e.g. not having `include` in them). ## EXAMPLES **carbon-c-relay** evolved over time, growing features on demand as the tool proved to be stable and fitting the job well. Below follow some annotated examples of constructs that can be used with the relay. Clusters can be defined as much as necessary. They receive data from match rules, and their type defines which members of the cluster finally get the metric data. The simplest cluster form is a `forward` cluster: ``` cluster send-through forward 10.1.0.1 ; ``` Any metric sent to the `send-through` cluster would simply be forwarded to the server at IPv4 address `10.1.0.1`. If we define multiple servers, all of those servers would get the same metric, thus: ``` cluster send-through forward 10.1.0.1 10.2.0.1 ; ``` The above results in a duplication of metrics send to both machines. This can be useful, but most of the time it is not. The `any_of` cluster type is like `forward`, but it sends each incoming metric to any of the members. The same example with such cluster would be: ``` cluster send-to-any-one any_of 10.1.0.1:2010 10.1.0.1:2011; ``` This would implement a multipath scenario, where two servers are used, the load between them is spread, but should any of them fail, all metrics are sent to the remaining one. This typically works well for upstream relays, or for balancing carbon-cache processes running on the same machine. Should any member become unavailable, for instance due to a rolling restart, the other members receive the traffic. If it is necessary to have true fail-over, where the secondary server is only used if the first is down, the following would implement that: ``` cluster try-first-then-second failover 10.1.0.1:2010 10.1.0.1:2011; ``` These types are different from the two consistent hash cluster types: ``` cluster graphite carbon_ch 127.0.0.1:2006=a 127.0.0.1:2007=b 127.0.0.1:2008=c ; ``` If a member in this example fails, all metrics that would go to that member are kept in the queue, waiting for the member to return. This is useful for clusters of carbon-cache machines where it is desirable that the same metric ends up on the same server always. The `carbon_ch` cluster type is compatible with carbon-relay consistent hash, and can be used for existing clusters populated by carbon-relay. For new clusters, however, it is better to use the `fnv1a_ch` cluster type, for it is faster, and allows to balance over the same address but different ports without an instance number, in constrast to `carbon_ch`. Because we can use multiple clusters, we can also replicate without the use of the `forward` cluster type, in a more intelligent way: ``` cluster dc-old carbon_ch replication 2 10.1.0.1 10.1.0.2 10.1.0.3 ; cluster dc-new1 fnv1a_ch replication 2 10.2.0.1 10.2.0.2 10.2.0.3 ; cluster dc-new2 fnv1a_ch replication 2 10.3.0.1 10.3.0.2 10.3.0.3 ; match * send to dc-old ; match * send to dc-new1 dc-new2 stop ; ``` In this example all incoming metrics are first sent to `dc-old`, then `dc-new1` and finally to `dc-new2`. Note that the cluster type of `dc-old` is different. Each incoming metric will be send to 2 members of all three clusters, thus replicating to in total 6 destinations. For each cluster the destination members are computed independently. Failure of clusters or members does not affect the others, since all have individual queues. The above example could also be written using three match rules for each dc, or one match rule for all three dcs. The difference is mainly in performance, the number of times the incoming metric has to be matched against an expression. The `stop` rule in `dc-new` match rule is not strictly necessary in this example, because there are no more following match rules. However, if the match would target a specific subset, e.g. `^sys\.`, and more clusters would be defined, this could be necessary, as for instance in the following abbreviated example: ``` cluster dc1-sys ... ; cluster dc2-sys ... ; cluster dc1-misc ... ; cluster dc2-misc ... ; match ^sys\. send to dc1-sys; match ^sys\. send to dc2-sys stop; match * send to dc1-misc; match * send to dc2-misc stop; ``` As can be seen, without the `stop` in dc2-sys' match rule, all metrics starting with `sys.` would also be send to dc1-misc and dc2-misc. It can be that this is desired, of course, but in this example there is a dedicated cluster for the `sys` metrics. Suppose there would be some unwanted metric that unfortunately is generated, let's assume some bad/old software. We don't want to store this metric. The `blackhole` cluster is suitable for that, when it is harder to actually whitelist all wanted metrics. Consider the following: ``` match some_legacy1$ some_legacy2$ send to blackhole stop; ``` This would throw away all metrics that end with `some_legacy`, that would otherwise be hard to filter out. Since the order matters, it can be used in a construct like this: ``` cluster old ... ; cluster new ... ; match * send to old; match unwanted send to blackhole stop; match * send to new; ``` In this example the old cluster would receive the metric that's unwanted for the new cluster. So, the order in which the rules occur does matter for the execution. Validation can be used to ensure the data for metrics is as expected. A global validation for just number (no floating point) values could be: ``` match * validate ^[0-9]+\ [0-9]+$ else drop ; ``` (Note the escape with backslash `\` of the space, you might be able to use `\s` or `[:space:]` instead, this depends on your libc implementation.) The validation clause can exist on every match rule, so in principle, the following is valid: ``` match ^foo validate ^[0-9]+\ [0-9]+$ else drop send to integer-cluster ; match ^foo validate ^[0-9.e+-]+\ [0-9.e+-]+$ else drop send to float-cluster stop; ``` Note that the behaviour is different in the previous two examples. When no `send to` clusters are specified, a validation error makes the match behave like the `stop` keyword is present. Likewise, when validation passes, processing continues with the next rule. When destination clusters are present, the `match` respects the `stop` keyword as normal. When specified, processing will always stop when specified so. However, if validation fails, the rule does not send anything to the destination clusters, the metric will be dropped or logged, but never sent. The relay is capable of rewriting incoming metrics on the fly. This process is done based on regular expressions with capture groups that allow to substitute parts in a replacement string. Rewrite rules allow to cleanup metrics from applications, or provide a migration path. In it's simplest form a rewrite rule looks like this: ``` rewrite ^server\.(.+)\.(.+)\.([a-zA-Z]+)([0-9]+) into server.\_1.\2.\3.\3\4 ; ``` In this example a metric like `server.DC.role.name123` would be transformed into `server.dc.role.name.name123`. For rewrite rules hold the same as for matches, that their order matters. Hence to build on top of the old/new cluster example done earlier, the following would store the original metric name in the old cluster, and the new metric name in the new cluster: ``` match * send to old; rewrite ... ; match * send to new; ``` Note that after the rewrite, the original metric name is no longer available, as the rewrite happens in-place. Aggregations are probably the most complex part of carbon-c-relay. Two ways of specifying aggregates are supported by carbon-c-relay. The first, static rules, are handled by an optimiser which tries to fold thousands of rules into groups to make the matching more efficient. The second, dynamic rules, are very powerful compact definitions with possibly thousands of internal instantiations. A typical static aggregation looks like: ``` aggregate ^sys\.dc1\.somehost-[0-9]+\.somecluster\.mysql\.replication_delay ^sys\.dc2\.somehost-[0-9]+\.somecluster\.mysql\.replication_delay every 10 seconds expire after 35 seconds timestamp at end of bucket compute sum write to mysql.somecluster.total_replication_delay compute average write to mysql.somecluster.average_replication_delay compute max write to mysql.somecluster.max_replication_delay compute count write to mysql.somecluster.replication_delay_metric_count ; ``` In this example, four aggregations are produced from the incoming matching metrics. In this example we could have written the two matches as one, but for demonstration purposes we did not. Obviously they can refer to different metrics, if that makes sense. The `every 10 seconds` clause specifies in what interval the aggregator can expect new metrics to arrive. This interval is used to produce the aggregations, thus each 10 seconds 4 new metrics are generated from the data received sofar. Because data may be in transit for some reason, or generation stalled, the `expire after` clause specifies how long the data should be kept before considering a data bucket (which is aggregated) to be complete. In the example, 35 was used, which means after 35 seconds the first aggregates are produced. It also means that metrics can arrive 35 seconds late, and still be taken into account. The exact time at which the aggregate metrics are produced is random between 0 and interval (10 in this case) seconds after the expiry time. This is done to prevent thundering herds of metrics for large aggregation sets. The `timestamp` that is used for the aggregations can be specified to be the `start`, `middle` or `end` of the bucket. Original carbon-aggregator.py uses `start`, while carbon-c-relay's default has always been `end`. The `compute` clauses demonstrate a single aggregation rule can produce multiple aggregates, as often is the case. Internally, this comes for free, since all possible aggregates are always calculated, whether or not they are used. The produced new metrics are resubmitted to the relay, hence matches defined before in the configuration can match output of the aggregator. It is important to avoid loops, that can be generated this way. In general, splitting aggregations to their own carbon-c-relay instance, such that it is easy to forward the produced metrics to another relay instance is a good practice. The previous example could also be written as follows to be dynamic: ``` aggregate ^sys\.dc[0-9].(somehost-[0-9]+)\.([^.]+)\.mysql\.replication_delay every 10 seconds expire after 35 seconds compute sum write to mysql.host.\1.replication_delay compute sum write to mysql.host.all.replication_delay compute sum write to mysql.cluster.\2.replication_delay compute sum write to mysql.cluster.all.replication_delay ; ``` Here a single match, results in four aggregations, each of a different scope. In this example aggregation based on hostname and cluster are being made, as well as the more general `all` targets, which in this example have both identical values. Note that with this single aggregation rule, both per-cluster, per-host and total aggregations are produced. Obviously, the input metrics define which hosts and clusters are produced. With use of the `send to` clause, aggregations can be made more intuitive and less error-prone. Consider the below example: ``` cluster graphite fnv1a_ch ip1 ip2 ip3; aggregate ^sys\.somemetric every 60 seconds expire after 75 seconds compute sum write to sys.somemetric send to graphite stop ; match * send to graphite; ``` It sends all incoming metrics to the graphite cluster, except the sys.somemetric ones, which it replaces with a sum of all the incoming ones. Without a `stop` in the aggregate, this causes a loop, and without the `send to`, the metric name can't be kept its original name, for the output now directly goes to the cluster. ## STATISTICS When **carbon-c-relay** is run without `-d` or `-s` arguments, statistics will be produced. By default they are sent to the relay itself in the form of `carbon.relays..*`. See the `statistics` construct to override this prefix, sending interval and values produced. While many metrics have a similar name to what carbon-cache.py would produce, their values are likely different. By default, most values are running counters which only increase over time. The use of the nonNegativeDerivative() function from graphite is useful with these. The following metrics are produced under the `carbon.relays.` namespace: * metricsReceived The number of metrics that were received by the relay. Received here means that they were seen and processed by any of the dispatchers. * metricsSent The number of metrics that were sent from the relay. This is a total count for all servers combined. When incoming metrics are duplicated by the cluster configuration, this counter will include all those duplications. In other words, the amount of metrics that were successfully sent to other systems. Note that metrics that are processed (received) but still in the sending queue (queued) are not included in this counter. * metricsQueued The total number of metrics that are currently in the queues for all the server targets. This metric is not cumulative, for it is a sample of the queue size, which can (and should) go up and down. Therefore you should not use the derivative function for this metric. * metricsDropped The total number of metric that had to be dropped due to server queues overflowing. A queue typically overflows when the server it tries to send its metrics to is not reachable, or too slow in ingesting the amount of metrics queued. This can be network or resource related, and also greatly depends on the rate of metrics being sent to the particular server. * metricsBlackholed The number of metrics that did not match any rule, or matched a rule with blackhole as target. Depending on your configuration, a high value might be an indication of a misconfiguration somewhere. These metrics were received by the relay, but never sent anywhere, thus they disappeared. * metricStalls The number of times the relay had to stall a client to indicate that the downstream server cannot handle the stream of metrics. A stall is only performed when the queue is full and the server is actually receptive of metrics, but just too slow at the moment. Stalls typically happen during micro-bursts, where the client typically is unaware that it should stop sending more data, while it is able to. * connections The number of connect requests handled. This is an ever increasing number just counting how many connections were accepted. * disconnects The number of disconnected clients. A disconnect either happens because the client goes away, or due to an idle timeout in the relay. The difference between this metric and connections is the amount of connections actively held by the relay. In normal situations this amount remains within reasonable bounds. Many connections, but few disconnections typically indicate a possible connection leak in the client. The idle connections disconnect in the relay here is to guard against resource drain in such scenarios. * dispatch\_wallTime\_us The number of microseconds spent by the dispatchers to do their work. In particular on multi-core systems, this value can be confusing, however, it indicates how long the dispatchers were doing work handling clients. It includes everything they do, from reading data from a socket, cleaning up the input metric, to adding the metric to the appropriate queues. The larger the configuration, and more complex in terms of matches, the more time the dispatchers will spend on the cpu. But also time they do /not/ spend on the cpu is included in this number. It is the pure wallclock time the dispatcher was serving a client. * dispatch\_sleepTime\_us The number of microseconds spent by the dispatchers sleeping waiting for work. When this value gets small (or even zero) the dispatcher has so much work that it doesn't sleep any more, and likely can't process the work in a timely fashion any more. This value plus the wallTime from above sort of sums up to the total uptime taken by this dispatcher. Therefore, expressing the wallTime as percentage of this sum gives the busyness percentage draining all the way up to 100% if sleepTime goes to 0. * server\_wallTime\_us The number of microseconds spent by the servers to send the metrics from their queues. This value includes connection creation, reading from the queue, and sending metrics over the network. * dispatcherX For each indivual dispatcher, the metrics received and blackholed plus the wall clock time. The values are as described above. * destinations.X For all known destinations, the number of dropped, queued and sent metrics plus the wall clock time spent. The values are as described above. * aggregators.metricsReceived The number of metrics that were matched an aggregator rule and were accepted by the aggregator. When a metric matches multiple aggregators, this value will reflect that. A metric is not counted when it is considered syntactically invalid, e.g. no value was found. * aggregators.metricsDropped The number of metrics that were sent to an aggregator, but did not fit timewise. This is either because the metric was too far in the past or future. The expire after clause in aggregate statements controls how long in the past metric values are accepted. * aggregators.metricsSent The number of metrics that were sent from the aggregators. These metrics were produced and are the actual results of aggregations. ## BUGS Please report them at: ## AUTHOR Fabian Groffen <grobian@gentoo.org> ## SEE ALSO All other utilities from the graphite stack. This project aims to be a fast replacement of the original [Carbon relay](http://graphite.readthedocs.org/en/1.0/carbon-daemons.html#carbon-relay-py). **carbon-c-relay** aims to deliver performance and configurability. Carbon is single threaded, and sending metrics to multiple consistent-hash clusters requires chaining of relays. This project provides a multithreaded relay which can address multiple targets and clusters for each and every metric based on pattern matches. There are a couple more replacement projects out there, which are [carbon-relay-ng](https://github.com/graphite-ng/carbon-relay-ng) and [graphite-relay](https://github.com/markchadwick/graphite-relay ). Compared to carbon-relay-ng, this project does provide carbon's consistent-hash routing. graphite-relay, which does this, however doesn't do metric-based matches to direct the traffic, which this project does as well. To date, carbon-c-relay can do aggregations, failover targets and more. ## ACKNOWLEDGEMENTS This program was originally developed for Booking.com, which approved that the code was published and released as Open Source on GitHub, for which the author would like to express his gratitude. Development has continued since with the help of many contributors suggesting features, reporting bugs, adding patches and more to make carbon-c-relay into what it is today. carbon-c-relay-3.2/collector.c000066400000000000000000000327221317265605500163260ustar00rootroot00000000000000/* * Copyright 2013-2017 Fabian Groffen * * 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. */ #include #include #include #include #include #include #include "relay.h" #include "dispatcher.h" #include "server.h" #include "aggregator.h" #include "collector.h" static dispatcher **dispatchers; static char debug = 0; static pthread_t collectorid; static char keep_running = 1; static router *pending_router = NULL; /** * Collects metrics from dispatchers and servers and emits them. */ static void * collector_runner(void *s) { int i; size_t totticks; size_t totmetrics; size_t totblackholes; size_t totqueued; size_t totstalls; size_t totdropped; size_t totsleeps; size_t ticks; size_t metrics; size_t blackholes; size_t queued; size_t stalls; size_t dropped; size_t sleeps; time_t now; time_t nextcycle; char destbuf[1024]; /* sort of POSIX_MAX_PATH */ char *p; int collector_interval = 60; router *prtr; size_t numaggregators = 0; aggregator *aggrs = NULL; server *submission = (server *)s; server **srvs = NULL; char metric[METRIC_BUFSIZ]; char *m = NULL; size_t sizem = 0; size_t (*s_ticks)(server *) = NULL; size_t (*s_metrics)(server *) = NULL; size_t (*s_stalls)(server *) = NULL; size_t (*s_dropped)(server *) = NULL; size_t (*d_ticks)(dispatcher *) = NULL; size_t (*d_metrics)(dispatcher *) = NULL; size_t (*d_blackholes)(dispatcher *) = NULL; size_t (*d_sleeps)(dispatcher *) = NULL; size_t (*a_received)(aggregator *) = NULL; size_t (*a_sent)(aggregator *) = NULL; size_t (*a_dropped)(aggregator *) = NULL; #define send(metric) \ if (debug & 1) \ logout("%s", metric); \ else \ server_send(submission, strdup(metric), 1); nextcycle = time(NULL) + collector_interval; while (__sync_bool_compare_and_swap(&keep_running, 1, 1)) { if ((prtr = __sync_add_and_fetch(&pending_router, 0)) != NULL) { char *stub; char *prefix; server **newservers; if (srvs != NULL) free(srvs); stub = router_getcollectorstub(prtr); prefix = router_getcollectorprefix(prtr); srvs = newservers = router_getservers(prtr); aggrs = router_getaggregators(prtr); numaggregators = aggregator_numaggregators(aggrs); collector_interval = router_getcollectorinterval(prtr); nextcycle = time(NULL) + collector_interval; /* setup functions to target what the user wants */ if (router_getcollectormode(prtr) == SUB) { s_ticks = server_get_ticks_sub; s_metrics = server_get_metrics_sub; s_stalls = server_get_stalls_sub; s_dropped = server_get_dropped_sub; d_ticks = dispatch_get_ticks_sub; d_metrics = dispatch_get_metrics_sub; d_blackholes = dispatch_get_blackholes_sub; d_sleeps = dispatch_get_sleeps_sub; a_received = aggregator_get_received_sub; a_sent = aggregator_get_sent_sub; a_dropped = aggregator_get_dropped_sub; } else { s_ticks = server_get_ticks; s_metrics = server_get_metrics; s_stalls = server_get_stalls; s_dropped = server_get_dropped; d_ticks = dispatch_get_ticks; d_metrics = dispatch_get_metrics; d_blackholes = dispatch_get_blackholes; d_sleeps = dispatch_get_sleeps; a_received = aggregator_get_received; a_sent = aggregator_get_sent; a_dropped = aggregator_get_dropped; } /* prepare prefix for graphite metrics */ i = snprintf(metric, sizeof(metric), "%s%s", stub == NULL ? "" : stub, prefix); m = metric + i; *m++ = '.'; *m = '\0'; sizem = sizeof(metric) - (m - metric); (void)__sync_and_and_fetch(&pending_router, NULL); } assert(srvs != NULL); sleep(1); now = time(NULL); if (nextcycle > now) continue; nextcycle += collector_interval; totticks = 0; totmetrics = 0; totblackholes = 0; totsleeps = 0; for (i = 0; dispatchers[i] != NULL; i++) { totsleeps += sleeps = d_sleeps(dispatchers[i]); totticks += ticks = d_ticks(dispatchers[i]); totmetrics += metrics = d_metrics(dispatchers[i]); totblackholes += blackholes = d_blackholes(dispatchers[i]); snprintf(m, sizem, "dispatcher%d.metricsReceived %zu %zu\n", i + 1, metrics, (size_t)now); send(metric); snprintf(m, sizem, "dispatcher%d.metricsBlackholed %zu %zu\n", i + 1, blackholes, (size_t)now); send(metric); snprintf(m, sizem, "dispatcher%d.wallTime_us %zu %zu\n", i + 1, ticks, (size_t)now); send(metric); snprintf(m, sizem, "dispatcher%d.sleepTime_us %zu %zu\n", i + 1, sleeps, (size_t)now); send(metric); } snprintf(m, sizem, "metricsReceived %zu %zu\n", totmetrics, (size_t)now); send(metric); snprintf(m, sizem, "metricsBlackholed %zu %zu\n", totblackholes, (size_t)now); send(metric); snprintf(m, sizem, "dispatch_wallTime_us %zu %zu\n", totticks, (size_t)now); send(metric); snprintf(m, sizem, "dispatch_sleepTime_us %zu %zu\n", totsleeps, (size_t)now); send(metric); #define send_server_metrics(ipbuf, ticks, metrics, queued, stalls, dropped) \ snprintf(m, sizem, "destinations.%s.sent %zu %zu\n", \ ipbuf, metrics, (size_t)now); \ send(metric); \ snprintf(m, sizem, "destinations.%s.queued %zu %zu\n", \ ipbuf, queued, (size_t)now); \ send(metric); \ snprintf(m, sizem, "destinations.%s.stalls %zu %zu\n", \ ipbuf, stalls, (size_t)now); \ send(metric); \ snprintf(m, sizem, "destinations.%s.dropped %zu %zu\n", \ ipbuf, dropped, (size_t)now); \ send(metric); \ snprintf(m, sizem, "destinations.%s.wallTime_us %zu %zu\n", \ ipbuf, ticks, (size_t)now); \ send(metric); totticks = 0; totmetrics = 0; totqueued = 0; totstalls = 0; totdropped = 0; /* exclude internal_submission metrics from the totals to avoid * artificial doubles due to internal routing details */ ticks = s_ticks(submission); metrics = s_metrics(submission); queued = server_get_queue_len(submission); stalls = s_stalls(submission); dropped = s_dropped(submission); send_server_metrics(server_ip(submission), ticks, metrics, queued, stalls, dropped); for (i = 0; srvs[i] != NULL; i++) { switch (server_ctype(srvs[i])) { case CON_FILE: case CON_PIPE: snprintf(destbuf, sizeof(destbuf), "%s", server_ip(srvs[i])); break; case CON_TCP: snprintf(destbuf, sizeof(destbuf), "%s:%u", server_ip(srvs[i]), server_port(srvs[i])); break; case CON_UDP: snprintf(destbuf, sizeof(destbuf), "%s:%u-udp", server_ip(srvs[i]), server_port(srvs[i])); break; default: assert(0); /* help code analysis tools */ } for (p = destbuf; *p != '\0'; p++) if (*p == '.') *p = '_'; totticks += ticks = s_ticks(srvs[i]); totmetrics += metrics = s_metrics(srvs[i]); totqueued += queued = server_get_queue_len(srvs[i]); totstalls += stalls = s_stalls(srvs[i]); totdropped += dropped = s_dropped(srvs[i]); send_server_metrics(destbuf, ticks, metrics, queued, stalls, dropped); } snprintf(m, sizem, "metricsSent %zu %zu\n", totmetrics, (size_t)now); send(metric); snprintf(m, sizem, "metricsQueued %zu %zu\n", totqueued, (size_t)now); send(metric); snprintf(m, sizem, "metricStalls %zu %zu\n", totstalls, (size_t)now); send(metric); snprintf(m, sizem, "metricsDropped %zu %zu\n", totdropped, (size_t)now); send(metric); snprintf(m, sizem, "server_wallTime_us %zu %zu\n", totticks, (size_t)now); send(metric); snprintf(m, sizem, "connections %zu %zu\n", dispatch_get_accepted_connections(), (size_t)now); send(metric); snprintf(m, sizem, "disconnects %zu %zu\n", dispatch_get_closed_connections(), (size_t)now); send(metric); if (numaggregators > 0) { snprintf(m, sizem, "aggregators.metricsReceived %zu %zu\n", a_received(aggrs), (size_t)now); send(metric); snprintf(m, sizem, "aggregators.metricsSent %zu %zu\n", a_sent(aggrs), (size_t)now); send(metric); snprintf(m, sizem, "aggregators.metricsDropped %zu %zu\n", a_dropped(aggrs), (size_t)now); send(metric); } if (debug & 1) fflush(stdout); } if (srvs != NULL) free(srvs); return NULL; } /** * Writes messages about dropped events or high queue sizes. */ static size_t lastdropped = 0; static size_t lastaggrdropped = 0; static void * collector_writer(void *unused) { int i = 0; size_t queued; size_t queuesize; double queueusage; size_t totdropped; size_t lastconn = 0; size_t lastdisc = 0; size_t numaggregators = 0; router *prtr; server **srvs = NULL; aggregator *aggrs = NULL; int collector_interval = 60; while (__sync_bool_compare_and_swap(&keep_running, 1, 1)) { if ((prtr = __sync_add_and_fetch(&pending_router, 0)) != NULL) { server **newservers = router_getservers(prtr); if (srvs != NULL) free(srvs); srvs = newservers; aggrs = router_getaggregators(prtr); numaggregators = aggregator_numaggregators(aggrs); collector_interval = router_getcollectorinterval(prtr); (void)__sync_and_and_fetch(&pending_router, NULL); } assert(srvs != NULL); sleep(1); if (debug & 1) { size_t mpsout; size_t totout; size_t mpsdrop; size_t totdrop; size_t totqueue; size_t mpsin; size_t totin; size_t totconn; size_t totdisc; size_t dticks; size_t dsleeps; int j; /* Solaris iostat like output: metrics in metrics out metrics drop queue conns disconn workr mps tot mps tot dps tot cur cps tot dps tot act 99999 9999999 99999 9999999 99999 9999999 99999 999 99999 999 99999 99% */ if (i % 24 == 0) printf(" metrics in metrics out metrics drop queue conns disconn workr\n" " mps tot mps tot dps tot cur cps tot dps tot act\n"); mpsout = totout = 0; mpsdrop = totdrop = 0; totqueue = 0; for (j = 0; srvs[j] != NULL; j++) { mpsout += server_get_metrics_sub(srvs[j]); totout += server_get_metrics(srvs[j]); mpsdrop += server_get_dropped_sub(srvs[j]); totdrop += server_get_dropped(srvs[j]); totqueue += server_get_queue_len(srvs[j]); } mpsin = totin = 0; dticks = dsleeps = 0; for (j = 0; dispatchers[j] != NULL; j++) { mpsin += dispatch_get_metrics_sub(dispatchers[j]); totin += dispatch_get_metrics(dispatchers[j]); dticks += dispatch_get_ticks_sub(dispatchers[j]); dsleeps += dispatch_get_sleeps_sub(dispatchers[j]); } totconn = dispatch_get_accepted_connections(); totdisc = dispatch_get_closed_connections(); if (dticks == 0) dticks = 1; /* for Coverity */ printf("%5zu %7zu " /* metrics in */ "%5zu %7zu " /* metrics out */ "%5zu %7zu " /* metrics dropped */ "%5zu " /* queue */ "%3zu %5zu " /* conns */ "%3zu %5zu " /* disconns */ "%2d%%\n", /* workers */ mpsin, totin, mpsout, totout, mpsdrop, totdrop, totqueue, totconn - lastconn, totconn, totdisc - lastdisc, totdisc, (int)(((double)dticks * 100.0) / (double)(dticks + dsleeps)) ); lastconn = totconn; lastdisc = totdisc; } i++; if (i < collector_interval) continue; totdropped = 0; for (i = 0; srvs[i] != NULL; i++) { queued = server_get_queue_len(srvs[i]); queuesize = server_get_queue_size(srvs[i]); totdropped += server_get_dropped(srvs[i]); queueusage = (double)queued / (double)queuesize; if (queueusage >= 0.75) logout("warning: metrics queuing up " "for %s:%u: %zu metrics (%d%% of queue size)\n", server_ip(srvs[i]), server_port(srvs[i]), queued, (int)(queueusage * 100)); } if (totdropped - lastdropped > 0) logout("warning: dropped %zu metrics\n", totdropped - lastdropped); lastdropped = totdropped; if (numaggregators > 0) { totdropped = aggregator_get_dropped(aggrs); if (totdropped - lastaggrdropped > 0) logout("warning: aggregator dropped %zu metrics\n", totdropped - lastaggrdropped); lastaggrdropped = totdropped; } i = 0; } if (srvs != NULL) free(srvs); return NULL; } /** * Schedules routes r to be put in place for the current routes. The * replacement is performed at the next cycle of the collector. */ inline void collector_schedulereload(router *rtr) { __sync_bool_compare_and_swap(&pending_router, NULL, rtr); } /** * Returns true if the routes scheduled to be reloaded by a call to * collector_schedulereload() have been activated. */ inline char collector_reloadcomplete(void) { return __sync_bool_compare_and_swap(&pending_router, NULL, NULL); } /** * Initialises and starts the collector. */ void collector_start(dispatcher **d, router *rtr, server *submission, char cum) { dispatchers = d; collector_schedulereload(rtr); if (mode & MODE_DEBUG) debug = 1; debug |= (cum ? 0 : 2); if (mode & MODE_SUBMISSION) { if (pthread_create(&collectorid, NULL, collector_writer, NULL) != 0) logerr("failed to start collector!\n"); } else { if (pthread_create(&collectorid, NULL, collector_runner, submission) != 0) logerr("failed to start collector!\n"); } } /** * Shuts down the collector. */ void collector_stop(void) { __sync_bool_compare_and_swap(&keep_running, 1, 0); pthread_join(collectorid, NULL); } carbon-c-relay-3.2/collector.h000066400000000000000000000021041317265605500163220ustar00rootroot00000000000000/* * Copyright 2013-2017 Fabian Groffen * * 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. */ #ifndef COLLECTOR_H #define COLLECTOR_H 1 #include "dispatcher.h" #include "router.h" #include "aggregator.h" #include "server.h" #include "relay.h" #define timediff(X, Y) \ (Y.tv_sec > X.tv_sec ? (Y.tv_sec - X.tv_sec) * 1000 * 1000 + ((Y.tv_usec - X.tv_usec)) : Y.tv_usec - X.tv_usec) void collector_start(dispatcher **d, router *rtr, server *submission, char cum); void collector_stop(void); void collector_schedulereload(router *rtr); char collector_reloadcomplete(void); #endif carbon-c-relay-3.2/compile000077500000000000000000000162451317265605500155540ustar00rootroot00000000000000#! /bin/sh # Wrapper for compilers which do not understand '-c -o'. scriptversion=2012-10-14.11; # UTC # Copyright (C) 1999-2014 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . nl=' ' # We need space, tab and new line, in precisely that order. Quoting is # there to prevent tools from complaining about whitespace usage. IFS=" "" $nl" file_conv= # func_file_conv build_file lazy # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. If the determined conversion # type is listed in (the comma separated) LAZY, no conversion will # take place. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv/,$2, in *,$file_conv,*) ;; mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_cl_dashL linkdir # Make cl look for libraries in LINKDIR func_cl_dashL () { func_file_conv "$1" if test -z "$lib_path"; then lib_path=$file else lib_path="$lib_path;$file" fi linker_opts="$linker_opts -LIBPATH:$file" } # func_cl_dashl library # Do a library search-path lookup for cl func_cl_dashl () { lib=$1 found=no save_IFS=$IFS IFS=';' for dir in $lib_path $LIB do IFS=$save_IFS if $shared && test -f "$dir/$lib.dll.lib"; then found=yes lib=$dir/$lib.dll.lib break fi if test -f "$dir/$lib.lib"; then found=yes lib=$dir/$lib.lib break fi if test -f "$dir/lib$lib.a"; then found=yes lib=$dir/lib$lib.a break fi done IFS=$save_IFS if test "$found" != yes; then lib=$lib.lib fi } # func_cl_wrapper cl arg... # Adjust compile command to suit cl func_cl_wrapper () { # Assume a capable shell lib_path= shared=: linker_opts= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. eat=1 case $2 in *.o | *.[oO][bB][jJ]) func_file_conv "$2" set x "$@" -Fo"$file" shift ;; *) func_file_conv "$2" set x "$@" -Fe"$file" shift ;; esac ;; -I) eat=1 func_file_conv "$2" mingw set x "$@" -I"$file" shift ;; -I*) func_file_conv "${1#-I}" mingw set x "$@" -I"$file" shift ;; -l) eat=1 func_cl_dashl "$2" set x "$@" "$lib" shift ;; -l*) func_cl_dashl "${1#-l}" set x "$@" "$lib" shift ;; -L) eat=1 func_cl_dashL "$2" ;; -L*) func_cl_dashL "${1#-L}" ;; -static) shared=false ;; -Wl,*) arg=${1#-Wl,} save_ifs="$IFS"; IFS=',' for flag in $arg; do IFS="$save_ifs" linker_opts="$linker_opts $flag" done IFS="$save_ifs" ;; -Xlinker) eat=1 linker_opts="$linker_opts $2" ;; -*) set x "$@" "$1" shift ;; *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) func_file_conv "$1" set x "$@" -Tp"$file" shift ;; *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) func_file_conv "$1" mingw set x "$@" "$file" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -n "$linker_opts"; then linker_opts="-link$linker_opts" fi exec "$@" $linker_opts exit 1 } eat= case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand '-c -o'. Remove '-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file 'INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac ofile= cfile= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. # So we strip '-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no '-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # '.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use '[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: carbon-c-relay-3.2/conffile.h000066400000000000000000000104301317265605500161220ustar00rootroot00000000000000/* * Copyright 2013-2017 Fabian Groffen * * 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. */ #ifndef _CONFFILE_H #define _CONFFILE_H 1 #include "server.h" #include "aggregator.h" #include "consistent-hash.h" #include "allocator.h" #include "receptor.h" #define GRAPHITE_PORT 2003 enum clusttype { BLACKHOLE, /* /dev/null-like destination */ GROUP, /* pseudo type to create a matching tree */ AGGRSTUB, /* pseudo type to have stub matches for aggregation returns */ STATSTUB, /* pseudo type to have stub matches for collector returns */ VALIDATION, /* pseudo type to perform additional data validation */ FORWARD, FILELOG, /* like forward, write metric to file */ FILELOGIP, /* like forward, write ip metric to file */ CARBON_CH, /* original carbon-relay.py consistent-hash */ FNV1A_CH, /* FNV1a-based consistent-hash */ JUMP_CH, /* jump consistent hash with fnv1a input */ ANYOF, /* FNV1a-based hash, but with backup by others */ FAILOVER, /* ordered attempt delivery list */ AGGREGATION, REWRITE }; typedef struct _servers { server *server; int refcnt; struct _servers *next; } servers; typedef struct { unsigned char repl_factor; ch_ring *ring; servers *servers; } chashring; typedef struct { unsigned short count; server **servers; servers *list; } serverlist; typedef struct _validate { struct _route *rule; enum { VAL_LOG, VAL_DROP } action; } validate; typedef struct _cluster { char *name; enum clusttype type; union { chashring *ch; servers *forward; serverlist *anyof; aggregator *aggregation; struct _route *routes; char *replacement; struct _validate *validation; } members; struct _cluster *next; } cluster; typedef struct _destinations { cluster *cl; struct _destinations *next; } destinations; typedef struct _route { char *pattern; /* original regex input, used for printing only */ regex_t *rule; /* regex per worker on metric, only if type == REGEX */ size_t nmatch; /* number of match groups */ char *strmatch; /* string to search for if type not REGEX or MATCHALL */ destinations *dests; /* where matches should go */ char *masq; /* when set, what to feed to the hashfunc when routing */ char stop:1; /* whether to continue matching rules after this one */ enum { MATCHALL, /* the '*', don't do anything, just match everything */ REGEX, /* a regex match */ CONTAINS, /* find string occurrence */ STARTS_WITH, /* metric must start with string */ ENDS_WITH, /* metric must end with string */ MATCHES /* metric matches string exactly */ } matchtype; /* how to interpret the pattern */ struct _route *next; } route; void router_yyerror(void *locp, void *, router *r, allocator *ra, allocator *pa, const char *msg); char *router_validate_address(router *rtr, char **retip, int *retport, void **retsaddr, void **rethint, char *ip, con_proto proto); char *router_validate_path(router *rtr, char *path); char *router_validate_expression(router *rtr, route **retr, char *pat); char *router_validate_cluster(router *rtr, cluster **retcl, char *cluster); char *router_add_server(router *ret, char *ip, int port, char *inst, con_type type, con_trnsp transport, con_proto proto, struct addrinfo *saddrs, struct addrinfo *hint, char useall, cluster *cl); char *router_add_cluster(router *r, cluster *cl); char *router_add_route(router *r, route *rte); char *router_add_aggregator(router *rtr, aggregator *a); char *router_add_stubroute(router *rtr, enum clusttype type, cluster *w, destinations *dw); char *router_add_listener(router *rtr, con_type ltype, con_trnsp trnsp, char *pemcert, con_proto ctype, char *ip, int port, struct addrinfo *saddrs); char *router_set_statistics(router *rtr, destinations *dsts); char *router_set_collectorvals(router *rtr, int val, char *prefix, col_mode m); #endif carbon-c-relay-3.2/conffile.l000066400000000000000000000163471317265605500161430ustar00rootroot00000000000000%{ #include "allocator.h" #include "conffile.h" #include "conffile.tab.h" #define YYSTYPE ROUTER_YYSTYPE #define YY_DECL int router_yylex \ (YYSTYPE *yylval_param, ROUTER_YYLTYPE *llocp, yyscan_t yyscanner, router *rtr, allocator *ralloc, allocator *palloc) #define YY_USER_ACTION llocp->first_line = llocp->last_line = yylineno; \ llocp->first_column = yycolumn; llocp->last_column = yycolumn+yyleng-1; \ yycolumn += yyleng; #define YY_USER_INIT yycolumn = 0; yylineno = 0; int identstate = 0; %} %option nostdinit %option yylineno %option noyywrap %option prefix="router_yy" %option reentrant bison-bridge %option noinput %option nounput %x cl ma re ag se st li qu %x idcl idma idag idin idli IDCHR [a-zA-Z0-9[\](){}|\\^?*$&%<>:/,._+-] %% char string_buf[1024]; char *strbuf = NULL; cluster { identstate = cl; BEGIN(idcl); return crCLUSTER; } forward { identstate = idcl; BEGIN(idcl); return crFORWARD; } any_of { identstate = idcl; BEGIN(idcl); return crANY_OF; } failover { identstate = idcl; BEGIN(idcl); return crFAILOVER; } useall return crUSEALL; carbon_ch { identstate = idcl; BEGIN(idcl); return crCARBON_CH; } fnv1a_ch { identstate = idcl; BEGIN(idcl); return crFNV1A_CH; } jump_fnv1a_ch { identstate = idcl; BEGIN(idcl); return crJUMP_FNV1A_CH; } replication return crREPLICATION; file { identstate = idcl; BEGIN(idcl); return crFILE; } ip return crIP; proto return crPROTO; udp return crUDP; tcp return crTCP; type return crTYPE; linemode return crLINEMODE; transport return crTRANSPORT; gzip return crGZIP; lz4 return crLZ4; ssl return crSSL; = return '='; match { identstate = idma; BEGIN(idma); return crMATCH; } \* return '*'; validate { identstate = ma; BEGIN(idma); return crVALIDATE; } else return crELSE; log return crLOG; drop return crDROP; route { BEGIN(ma); return crROUTE; } using { identstate = ma; BEGIN(idma); return crUSING; } send { BEGIN(ma); return crSEND; } to { identstate = idcl; BEGIN(idcl); return crTO; } blackhole return crBLACKHOLE; stop return crSTOP; rewrite { identstate = re; BEGIN(idma); return crREWRITE; } into { identstate = re; BEGIN(idma); return crINTO; } aggregate { identstate = idag; BEGIN(idag); return crAGGREGATE; } every { BEGIN(ag); return crEVERY; } seconds return crSECONDS; expire return crEXPIRE; after return crAFTER; timestamp return crTIMESTAMP; at return crAT; start return crSTART; middle return crMIDDLE; end return crEND; of return crOF; bucket return crBUCKET; compute return crCOMPUTE; summary return crSUM; sum return crSUM; count return crCOUNT; cnt return crCOUNT; maximum return crMAX; max return crMAX; minimum return crMIN; min return crMIN; average return crAVERAGE; avg return crAVERAGE; median return crMEDIAN; percentile[0-9]* { yylval_param->crINTVAL = atoi(yytext + strlen("percentile")); return crPERCENTILE; } variance return crVARIANCE; stddev return crSTDDEV; write return crWRITE; to { identstate = ag; BEGIN(idag); return crTO; } send { /* reuse the match logic for send to ... stop */ BEGIN(ma); return crSEND; } send { BEGIN(se); return crSEND; } statistics { /* reuse the match logic for send to ... stop */ BEGIN(ma); return crSTATISTICS; } statistics { BEGIN(st); return crSTATISTICS; } submit return crSUBMIT; every return crEVERY; seconds return crSECONDS; reset return crRESET; counters return crCOUNTERS; after return crAFTER; interval return crINTERVAL; prefix return crPREFIX; with { identstate = st; BEGIN(idag); return crWITH; } send { /* reuse the match logic for send to ... stop */ BEGIN(ma); return crSEND; } listen { BEGIN(li); return crLISTEN; }
  • type return crTYPE;
  • linemode { identstate = li; BEGIN(idli); return crLINEMODE; } transport return crTRANSPORT; gzip { identstate = li; BEGIN(idli); return crGZIP; } lz4 { identstate = li; BEGIN(idli); return crLZ4; } ssl { identstate = idli; BEGIN(idli); return crSSL; } proto { BEGIN(li); return crPROTO; }
  • udp { identstate = li; BEGIN(idli); return crUDP; }
  • tcp { identstate = li; BEGIN(idli); return crTCP; }
  • unix { identstate = li; BEGIN(idli); return crUNIX; } include { identstate = INITIAL; BEGIN(idin); return crINCLUDE; } /* handle quoted strings */ \" { strbuf = string_buf; BEGIN(qu); } { \" { if (strbuf == string_buf) { router_yyerror(llocp, NULL, rtr, ralloc, palloc, "empty string"); yyterminate(); } BEGIN(identstate); *strbuf = '\0'; yylval_param->crSTRING = ra_strdup(palloc, string_buf); return crSTRING; } \n { router_yyerror(llocp, NULL, rtr, ralloc, palloc, "unterminated string"); yyterminate(); } <> { router_yyerror(llocp, NULL, rtr, ralloc, palloc, "unterminated string"); yyterminate(); } \\. { *strbuf++ = yytext[1]; if (strbuf == string_buf + sizeof(string_buf)) { router_yyerror(llocp, NULL, rtr, ralloc, palloc, "string too large"); yyterminate(); } } [^\\\n\"]+ { char *yptr = yytext; while (*yptr) { *strbuf++ = *yptr++; if (strbuf == string_buf + sizeof(string_buf)) { router_yyerror(llocp, NULL, rtr, ralloc, palloc, "string too large"); yyterminate(); } } } } <*>#.*\n { /* ignore for now yylval_param->crCOMMENT = ra_strdup(palloc, yytext); return crCOMMENT; */ yycolumn = 0; ; } <*>[ \t\r]+ ; /* whitespace */ <*>\n+ yycolumn = 0; [0-9]+ { yylval_param->crINTVAL = atoi(yytext); return crINTVAL; } {IDCHR}+(\\[ ]{IDCHR}+)* { yylval_param->crSTRING = ra_strdup(palloc, yytext); BEGIN(identstate); return crSTRING; } <*>; { BEGIN(INITIAL); return ';'; } <*>. { /* feed this back to the parser, it will give a * nice error message */ yylval_param->crSTRING = ra_strdup(palloc, yytext); return crUNEXPECTED; } %% carbon-c-relay-3.2/conffile.tab.c000066400000000000000000003047441317265605500167000ustar00rootroot00000000000000/* A Bison parser, made by GNU Bison 3.0.4. */ /* Bison implementation for Yacc-like parsers in C Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* C LALR(1) parser skeleton written by Richard Stallman, by simplifying the original so-called "semantic" parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ #define YYBISON_VERSION "3.0.4" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 2 /* Push parsers. */ #define YYPUSH 0 /* Pull parsers. */ #define YYPULL 1 /* Substitute the type names. */ #define YYSTYPE ROUTER_YYSTYPE #define YYLTYPE ROUTER_YYLTYPE /* Substitute the variable and function names. */ #define yyparse router_yyparse #define yylex router_yylex #define yyerror router_yyerror #define yydebug router_yydebug #define yynerrs router_yynerrs /* Copy the first part of user declarations. */ #line 1 "conffile.y" /* yacc.c:339 */ #include "allocator.h" #include "conffile.h" #include "conffile.tab.h" #include "aggregator.h" #include "receptor.h" #include "config.h" int router_yylex(ROUTER_YYSTYPE *, ROUTER_YYLTYPE *, void *, router *, allocator *, allocator *); #line 85 "conffile.tab.c" /* yacc.c:339 */ # ifndef YY_NULLPTR # if defined __cplusplus && 201103L <= __cplusplus # define YY_NULLPTR nullptr # else # define YY_NULLPTR 0 # endif # endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else # define YYERROR_VERBOSE 1 #endif /* In a future release of Bison, this section will be replaced by #include "conffile.tab.h". */ #ifndef YY_ROUTER_YY_CONFFILE_TAB_H_INCLUDED # define YY_ROUTER_YY_CONFFILE_TAB_H_INCLUDED /* Debug traces. */ #ifndef ROUTER_YYDEBUG # if defined YYDEBUG #if YYDEBUG # define ROUTER_YYDEBUG 1 # else # define ROUTER_YYDEBUG 0 # endif # else /* ! defined YYDEBUG */ # define ROUTER_YYDEBUG 0 # endif /* ! defined YYDEBUG */ #endif /* ! defined ROUTER_YYDEBUG */ #if ROUTER_YYDEBUG extern int router_yydebug; #endif /* "%code requires" blocks. */ #line 11 "conffile.y" /* yacc.c:355 */ struct _clust { enum clusttype t; int ival; }; struct _clhost { char *ip; int port; char *inst; int proto; con_trnsp trnsp; void *saddr; void *hint; struct _clhost *next; }; struct _maexpr { route *r; char drop; struct _maexpr *next; }; struct _agcomp { enum _aggr_compute_type ctype; unsigned char pctl; char *metric; struct _agcomp *next; }; struct _lsnr { con_type type; struct _rcptr_trsp *transport; struct _rcptr *rcptr; }; struct _rcptr { con_proto ctype; char *ip; int port; void *saddr; struct _rcptr *next; }; struct _rcptr_trsp { con_trnsp mode; char *pemcert; }; #line 167 "conffile.tab.c" /* yacc.c:355 */ /* Token type. */ #ifndef ROUTER_YYTOKENTYPE # define ROUTER_YYTOKENTYPE enum router_yytokentype { crCLUSTER = 258, crFORWARD = 259, crANY_OF = 260, crFAILOVER = 261, crCARBON_CH = 262, crFNV1A_CH = 263, crJUMP_FNV1A_CH = 264, crFILE = 265, crIP = 266, crREPLICATION = 267, crPROTO = 268, crUSEALL = 269, crUDP = 270, crTCP = 271, crMATCH = 272, crVALIDATE = 273, crELSE = 274, crLOG = 275, crDROP = 276, crROUTE = 277, crUSING = 278, crSEND = 279, crTO = 280, crBLACKHOLE = 281, crSTOP = 282, crREWRITE = 283, crINTO = 284, crAGGREGATE = 285, crEVERY = 286, crSECONDS = 287, crEXPIRE = 288, crAFTER = 289, crTIMESTAMP = 290, crAT = 291, crSTART = 292, crMIDDLE = 293, crEND = 294, crOF = 295, crBUCKET = 296, crCOMPUTE = 297, crSUM = 298, crCOUNT = 299, crMAX = 300, crMIN = 301, crAVERAGE = 302, crMEDIAN = 303, crVARIANCE = 304, crSTDDEV = 305, crPERCENTILE = 306, crWRITE = 307, crSTATISTICS = 308, crSUBMIT = 309, crRESET = 310, crCOUNTERS = 311, crINTERVAL = 312, crPREFIX = 313, crWITH = 314, crLISTEN = 315, crTYPE = 316, crLINEMODE = 317, crTRANSPORT = 318, crGZIP = 319, crLZ4 = 320, crSSL = 321, crUNIX = 322, crINCLUDE = 323, crCOMMENT = 324, crSTRING = 325, crUNEXPECTED = 326, crINTVAL = 327 }; #endif /* Value type. */ #if ! defined ROUTER_YYSTYPE && ! defined ROUTER_YYSTYPE_IS_DECLARED union ROUTER_YYSTYPE { /* crCOMMENT */ char * crCOMMENT; /* crSTRING */ char * crSTRING; /* crUNEXPECTED */ char * crUNEXPECTED; /* cluster_opt_instance */ char * cluster_opt_instance; /* match_opt_route */ char * match_opt_route; /* statistics_opt_prefix */ char * statistics_opt_prefix; /* cluster */ cluster * cluster; /* statistics_opt_counters */ col_mode statistics_opt_counters; /* cluster_opt_proto */ con_proto cluster_opt_proto; /* rcptr_proto */ con_proto rcptr_proto; /* cluster_opt_transport */ con_trnsp cluster_opt_transport; /* match_opt_send_to */ destinations * match_opt_send_to; /* match_send_to */ destinations * match_send_to; /* match_dsts */ destinations * match_dsts; /* match_dsts2 */ destinations * match_dsts2; /* match_opt_dst */ destinations * match_opt_dst; /* match_dst */ destinations * match_dst; /* aggregate_opt_send_to */ destinations * aggregate_opt_send_to; /* aggregate_opt_timestamp */ enum _aggr_timestamp aggregate_opt_timestamp; /* aggregate_ts_when */ enum _aggr_timestamp aggregate_ts_when; /* cluster_useall */ enum clusttype cluster_useall; /* cluster_ch */ enum clusttype cluster_ch; /* crPERCENTILE */ int crPERCENTILE; /* crINTVAL */ int crINTVAL; /* cluster_opt_useall */ int cluster_opt_useall; /* cluster_opt_repl */ int cluster_opt_repl; /* match_log_or_drop */ int match_log_or_drop; /* match_opt_stop */ int match_opt_stop; /* statistics_opt_interval */ int statistics_opt_interval; /* aggregate_comp_type */ struct _agcomp aggregate_comp_type; /* aggregate_computes */ struct _agcomp * aggregate_computes; /* aggregate_opt_compute */ struct _agcomp * aggregate_opt_compute; /* aggregate_compute */ struct _agcomp * aggregate_compute; /* cluster_paths */ struct _clhost * cluster_paths; /* cluster_opt_path */ struct _clhost * cluster_opt_path; /* cluster_path */ struct _clhost * cluster_path; /* cluster_hosts */ struct _clhost * cluster_hosts; /* cluster_opt_host */ struct _clhost * cluster_opt_host; /* cluster_host */ struct _clhost * cluster_host; /* cluster_type */ struct _clust cluster_type; /* cluster_file */ struct _clust cluster_file; /* listener */ struct _lsnr * listener; /* match_exprs */ struct _maexpr * match_exprs; /* match_exprs2 */ struct _maexpr * match_exprs2; /* match_opt_expr */ struct _maexpr * match_opt_expr; /* match_expr */ struct _maexpr * match_expr; /* match_opt_validate */ struct _maexpr * match_opt_validate; /* receptors */ struct _rcptr * receptors; /* opt_receptor */ struct _rcptr * opt_receptor; /* receptor */ struct _rcptr * receptor; /* transport_mode */ struct _rcptr_trsp * transport_mode; #line 355 "conffile.tab.c" /* yacc.c:355 */ }; typedef union ROUTER_YYSTYPE ROUTER_YYSTYPE; # define ROUTER_YYSTYPE_IS_TRIVIAL 1 # define ROUTER_YYSTYPE_IS_DECLARED 1 #endif /* Location type. */ #if ! defined ROUTER_YYLTYPE && ! defined ROUTER_YYLTYPE_IS_DECLARED typedef struct ROUTER_YYLTYPE ROUTER_YYLTYPE; struct ROUTER_YYLTYPE { int first_line; int first_column; int last_line; int last_column; }; # define ROUTER_YYLTYPE_IS_DECLARED 1 # define ROUTER_YYLTYPE_IS_TRIVIAL 1 #endif int router_yyparse (void *yyscanner, router *rtr, allocator *ralloc, allocator *palloc); #endif /* !YY_ROUTER_YY_CONFFILE_TAB_H_INCLUDED */ /* Copy the second part of user declarations. */ #line 385 "conffile.tab.c" /* yacc.c:358 */ #ifdef short # undef short #endif #ifdef YYTYPE_UINT8 typedef YYTYPE_UINT8 yytype_uint8; #else typedef unsigned char yytype_uint8; #endif #ifdef YYTYPE_INT8 typedef YYTYPE_INT8 yytype_int8; #else typedef signed char yytype_int8; #endif #ifdef YYTYPE_UINT16 typedef YYTYPE_UINT16 yytype_uint16; #else typedef unsigned short int yytype_uint16; #endif #ifdef YYTYPE_INT16 typedef YYTYPE_INT16 yytype_int16; #else typedef short int yytype_int16; #endif #ifndef YYSIZE_T # ifdef __SIZE_TYPE__ # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t # elif ! defined YYSIZE_T # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else # define YYSIZE_T unsigned int # endif #endif #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(Msgid) dgettext ("bison-runtime", Msgid) # endif # endif # ifndef YY_ # define YY_(Msgid) Msgid # endif #endif #ifndef YY_ATTRIBUTE # if (defined __GNUC__ \ && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C # define YY_ATTRIBUTE(Spec) __attribute__(Spec) # else # define YY_ATTRIBUTE(Spec) /* empty */ # endif #endif #ifndef YY_ATTRIBUTE_PURE # define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) #endif #ifndef YY_ATTRIBUTE_UNUSED # define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) #endif #if !defined _Noreturn \ && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) # if defined _MSC_VER && 1200 <= _MSC_VER # define _Noreturn __declspec (noreturn) # else # define _Noreturn YY_ATTRIBUTE ((__noreturn__)) # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(E) ((void) (E)) #else # define YYUSE(E) /* empty */ #endif #if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ /* Suppress an incorrect diagnostic about yylval being uninitialized. */ # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ _Pragma ("GCC diagnostic push") \ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") # define YY_IGNORE_MAYBE_UNINITIALIZED_END \ _Pragma ("GCC diagnostic pop") #else # define YY_INITIAL_VALUE(Value) Value #endif #ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN # define YY_IGNORE_MAYBE_UNINITIALIZED_END #endif #ifndef YY_INITIAL_VALUE # define YY_INITIAL_VALUE(Value) /* Nothing. */ #endif #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA # if YYSTACK_USE_ALLOCA # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # elif defined __BUILTIN_VA_ARG_INCR # include /* INFRINGES ON USER NAME SPACE */ # elif defined _AIX # define YYSTACK_ALLOC __alloca # elif defined _MSC_VER # include /* INFRINGES ON USER NAME SPACE */ # define alloca _alloca # else # define YYSTACK_ALLOC alloca # if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS # include /* INFRINGES ON USER NAME SPACE */ /* Use EXIT_SUCCESS as a witness for stdlib.h. */ # ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 # endif # endif # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's 'empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely invoke alloca (N) if N exceeds 4096. Use a slightly smaller number to allow for a few compiler-allocated temporary stack slots. */ # define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ # endif # else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif # if (defined __cplusplus && ! defined EXIT_SUCCESS \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ # ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc # if ! defined malloc && ! defined EXIT_SUCCESS void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free # if ! defined free && ! defined EXIT_SUCCESS void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif # endif #endif /* ! defined yyoverflow || YYERROR_VERBOSE */ #if (! defined yyoverflow \ && (! defined __cplusplus \ || (defined ROUTER_YYLTYPE_IS_TRIVIAL && ROUTER_YYLTYPE_IS_TRIVIAL \ && defined ROUTER_YYSTYPE_IS_TRIVIAL && ROUTER_YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { yytype_int16 yyss_alloc; YYSTYPE yyvs_alloc; YYLTYPE yyls_alloc; }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + 2 * YYSTACK_GAP_MAXIMUM) # define YYCOPY_NEEDED 1 /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack_alloc, Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ Stack = &yyptr->Stack_alloc; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (0) #endif #if defined YYCOPY_NEEDED && YYCOPY_NEEDED /* Copy COUNT objects from SRC to DST. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(Dst, Src, Count) \ __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) # else # define YYCOPY(Dst, Src, Count) \ do \ { \ YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (Dst)[yyi] = (Src)[yyi]; \ } \ while (0) # endif # endif #endif /* !YYCOPY_NEEDED */ /* YYFINAL -- State number of the termination state. */ #define YYFINAL 35 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 126 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 76 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 59 /* YYNRULES -- Number of rules. */ #define YYNRULES 117 /* YYNSTATES -- Number of states. */ #define YYNSTATES 180 /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned by yylex, with out-of-bounds checking. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 327 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM as returned by yylex, without out-of-bounds checking. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 75, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 73, 2, 74, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72 }; #if ROUTER_YYDEBUG /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { 0, 120, 120, 123, 124, 127, 130, 131, 132, 133, 134, 135, 136, 137, 141, 208, 249, 251, 255, 256, 257, 260, 261, 264, 265, 266, 269, 270, 273, 274, 277, 279, 280, 282, 302, 304, 305, 307, 328, 329, 330, 340, 341, 342, 345, 346, 349, 350, 360, 370, 384, 439, 451, 454, 456, 457, 460, 479, 480, 499, 500, 503, 504, 507, 508, 511, 514, 524, 527, 529, 530, 533, 549, 550, 555, 600, 691, 692, 697, 698, 699, 702, 706, 707, 709, 724, 725, 726, 727, 728, 729, 730, 740, 741, 744, 745, 750, 765, 790, 791, 802, 803, 806, 807, 812, 830, 854, 863, 879, 895, 914, 917, 918, 921, 958, 980, 981, 986 }; #endif #if ROUTER_YYDEBUG || YYERROR_VERBOSE || 1 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "crCLUSTER", "crFORWARD", "crANY_OF", "crFAILOVER", "crCARBON_CH", "crFNV1A_CH", "crJUMP_FNV1A_CH", "crFILE", "crIP", "crREPLICATION", "crPROTO", "crUSEALL", "crUDP", "crTCP", "crMATCH", "crVALIDATE", "crELSE", "crLOG", "crDROP", "crROUTE", "crUSING", "crSEND", "crTO", "crBLACKHOLE", "crSTOP", "crREWRITE", "crINTO", "crAGGREGATE", "crEVERY", "crSECONDS", "crEXPIRE", "crAFTER", "crTIMESTAMP", "crAT", "crSTART", "crMIDDLE", "crEND", "crOF", "crBUCKET", "crCOMPUTE", "crSUM", "crCOUNT", "crMAX", "crMIN", "crAVERAGE", "crMEDIAN", "crVARIANCE", "crSTDDEV", "crPERCENTILE", "crWRITE", "crSTATISTICS", "crSUBMIT", "crRESET", "crCOUNTERS", "crINTERVAL", "crPREFIX", "crWITH", "crLISTEN", "crTYPE", "crLINEMODE", "crTRANSPORT", "crGZIP", "crLZ4", "crSSL", "crUNIX", "crINCLUDE", "crCOMMENT", "crSTRING", "crUNEXPECTED", "crINTVAL", "';'", "'='", "'*'", "$accept", "stmts", "opt_stmt", "stmt", "command", "cluster", "cluster_type", "cluster_useall", "cluster_opt_useall", "cluster_ch", "cluster_opt_repl", "cluster_file", "cluster_paths", "cluster_opt_path", "cluster_path", "cluster_hosts", "cluster_opt_host", "cluster_host", "cluster_opt_instance", "cluster_opt_proto", "cluster_opt_type", "cluster_opt_transport", "match", "match_exprs", "match_exprs2", "match_opt_expr", "match_expr", "match_opt_validate", "match_log_or_drop", "match_opt_route", "match_opt_send_to", "match_send_to", "match_dsts", "match_dsts2", "match_opt_dst", "match_dst", "match_opt_stop", "rewrite", "aggregate", "aggregate_opt_timestamp", "aggregate_ts_when", "aggregate_computes", "aggregate_opt_compute", "aggregate_compute", "aggregate_comp_type", "aggregate_opt_send_to", "send", "statistics", "statistics_opt_interval", "statistics_opt_counters", "statistics_opt_prefix", "listen", "listener", "transport_mode", "receptors", "opt_receptor", "receptor", "rcptr_proto", "include", YY_NULLPTR }; #endif # ifdef YYPRINT /* YYTOKNUM[NUM] -- (External) token number corresponding to the (internal) symbol number NUM (which must be that of a token). */ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 59, 61, 42 }; # endif #define YYPACT_NINF -98 #define yypact_value_is_default(Yystate) \ (!!((Yystate) == (-98))) #define YYTABLE_NINF -1 #define yytable_value_is_error(Yytable_value) \ 0 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ static const yytype_int8 yypact[] = { -2, -50, -65, -28, -23, -20, -5, -9, -17, 55, -98, -2, -16, -98, -98, -98, -98, -98, -98, -98, -98, 34, -98, -98, 38, -98, -20, 35, 32, 28, 31, 8, 2, -98, -98, -98, -98, -98, -98, -98, -98, -98, -98, -98, 54, -3, 56, 57, 5, 6, 46, -98, -98, -22, 7, -1, 0, 17, 20, 16, -98, 9, -98, -3, -98, -98, 10, -98, -98, -98, 5, 61, 58, 60, -98, -98, 59, -98, 15, -98, 62, 63, 53, 29, 60, -57, 19, -51, 77, -98, -98, -98, -98, -98, 3, 21, 67, 59, -98, -98, -98, -98, -98, 64, -98, 36, 26, -98, 59, -98, -98, 33, 85, -98, 19, -98, -98, 30, 39, -98, -98, -98, -98, -22, -98, 65, -98, -98, -98, -98, -13, -98, -98, -98, -98, 40, 41, -98, 37, -98, -98, -98, -98, -98, -52, -98, 69, -98, -98, -98, 70, 71, 66, -21, -14, 60, 66, -98, -98, -98, 72, -98, -98, -98, -98, -98, -98, -98, -98, -98, 68, 59, -98, -98, 73, 81, -98, -98, 43, -98 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. Performed when YYTABLE does not specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { 3, 0, 0, 0, 0, 0, 98, 0, 0, 0, 2, 3, 0, 6, 7, 8, 9, 10, 11, 12, 13, 0, 56, 51, 57, 52, 54, 0, 0, 0, 0, 100, 0, 104, 117, 1, 4, 5, 18, 19, 20, 23, 24, 25, 29, 0, 21, 26, 0, 0, 61, 55, 53, 0, 0, 0, 0, 0, 102, 106, 28, 38, 14, 35, 22, 16, 0, 17, 33, 15, 31, 0, 0, 63, 66, 71, 72, 67, 69, 74, 0, 0, 0, 0, 94, 0, 0, 0, 41, 36, 34, 27, 30, 32, 0, 0, 0, 72, 64, 73, 96, 70, 68, 0, 99, 0, 0, 95, 72, 107, 108, 0, 0, 105, 111, 39, 40, 0, 44, 59, 60, 58, 62, 0, 50, 0, 101, 103, 97, 109, 0, 112, 110, 42, 43, 0, 46, 65, 0, 116, 115, 114, 113, 45, 0, 37, 0, 47, 48, 49, 76, 0, 0, 0, 0, 94, 82, 78, 79, 80, 0, 85, 86, 87, 88, 89, 90, 92, 93, 91, 0, 72, 83, 81, 0, 0, 75, 77, 0, 84 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { -98, -98, 99, -98, -98, -98, -98, -98, -98, -98, -98, -98, -98, -98, 45, 48, -98, -98, -98, -98, -98, -98, -98, -98, 1, -98, -98, -98, -98, -98, -98, 44, -7, 47, -98, -98, -97, -98, -98, -98, -98, -38, -98, -98, -98, -36, -98, -98, -98, -98, -98, -98, -98, -98, 12, -98, -98, -98, -98 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { -1, 9, 10, 11, 12, 13, 45, 46, 65, 47, 67, 48, 69, 92, 70, 62, 90, 63, 88, 118, 136, 145, 14, 24, 25, 52, 26, 50, 121, 73, 97, 107, 76, 77, 102, 78, 100, 15, 16, 152, 160, 155, 173, 156, 170, 108, 17, 18, 31, 58, 84, 19, 33, 86, 113, 132, 114, 142, 20 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule whose number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_uint8 yytable[] = { 124, 1, 139, 140, 74, 22, 29, 109, 110, 111, 23, 128, 147, 148, 149, 2, 157, 158, 159, 115, 21, 116, 3, 119, 120, 27, 4, 51, 5, 161, 162, 163, 164, 165, 166, 167, 168, 169, 38, 39, 40, 41, 42, 43, 44, 133, 134, 28, 75, 30, 22, 6, 32, 34, 141, 35, 49, 37, 7, 55, 53, 54, 56, 57, 59, 60, 8, 61, 72, 66, 64, 80, 81, 82, 176, 68, 71, 79, 83, 85, 94, 95, 91, 87, 96, 75, 99, 105, 106, 112, 117, 122, 123, 126, 103, 104, 127, 125, 130, 138, 135, 150, 143, 129, 144, 151, 178, 153, 154, 146, 36, 89, 174, 179, 177, 93, 137, 98, 172, 171, 175, 0, 0, 0, 0, 101, 131 }; static const yytype_int16 yycheck[] = { 97, 3, 15, 16, 26, 70, 5, 64, 65, 66, 75, 108, 64, 65, 66, 17, 37, 38, 39, 70, 70, 72, 24, 20, 21, 53, 28, 26, 30, 43, 44, 45, 46, 47, 48, 49, 50, 51, 4, 5, 6, 7, 8, 9, 10, 15, 16, 70, 70, 54, 70, 53, 61, 70, 67, 0, 18, 73, 60, 31, 25, 29, 31, 55, 62, 11, 68, 70, 22, 12, 14, 72, 72, 56, 171, 70, 70, 70, 58, 63, 19, 23, 72, 74, 24, 70, 27, 34, 59, 70, 13, 70, 25, 57, 32, 32, 70, 33, 13, 34, 61, 32, 62, 70, 63, 35, 25, 36, 42, 72, 11, 63, 40, 70, 41, 70, 123, 73, 156, 155, 52, -1, -1, -1, -1, 78, 114 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { 0, 3, 17, 24, 28, 30, 53, 60, 68, 77, 78, 79, 80, 81, 98, 113, 114, 122, 123, 127, 134, 70, 70, 75, 99, 100, 102, 53, 70, 100, 54, 124, 61, 128, 70, 0, 78, 73, 4, 5, 6, 7, 8, 9, 10, 82, 83, 85, 87, 18, 103, 100, 101, 25, 29, 31, 31, 55, 125, 62, 11, 70, 91, 93, 14, 84, 12, 86, 70, 88, 90, 70, 22, 105, 26, 70, 108, 109, 111, 70, 72, 72, 56, 58, 126, 63, 129, 74, 94, 91, 92, 72, 89, 90, 19, 23, 24, 106, 107, 27, 112, 109, 110, 32, 32, 34, 59, 107, 121, 64, 65, 66, 70, 130, 132, 70, 72, 13, 95, 20, 21, 104, 70, 25, 112, 33, 57, 70, 112, 70, 13, 130, 131, 15, 16, 61, 96, 108, 34, 15, 16, 67, 133, 62, 63, 97, 72, 64, 65, 66, 32, 35, 115, 36, 42, 117, 119, 37, 38, 39, 116, 43, 44, 45, 46, 47, 48, 49, 50, 51, 120, 121, 117, 118, 40, 52, 112, 41, 25, 70 }; /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { 0, 76, 77, 78, 78, 79, 80, 80, 80, 80, 80, 80, 80, 80, 81, 81, 82, 82, 83, 83, 83, 84, 84, 85, 85, 85, 86, 86, 87, 87, 88, 89, 89, 90, 91, 92, 92, 93, 94, 94, 94, 95, 95, 95, 96, 96, 97, 97, 97, 97, 98, 99, 99, 100, 101, 101, 102, 103, 103, 104, 104, 105, 105, 106, 106, 107, 108, 108, 109, 110, 110, 111, 112, 112, 113, 114, 115, 115, 116, 116, 116, 117, 118, 118, 119, 120, 120, 120, 120, 120, 120, 120, 120, 120, 121, 121, 122, 123, 124, 124, 125, 125, 126, 126, 127, 128, 129, 129, 129, 129, 130, 131, 131, 132, 132, 133, 133, 134 }; /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 1, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 2, 2, 1, 1, 1, 0, 1, 1, 1, 1, 0, 2, 2, 1, 2, 0, 1, 1, 2, 0, 1, 5, 0, 2, 2, 0, 2, 2, 0, 2, 0, 2, 2, 2, 6, 1, 1, 2, 0, 1, 1, 0, 4, 1, 1, 0, 3, 0, 1, 3, 1, 1, 2, 0, 1, 1, 0, 1, 4, 13, 0, 5, 1, 1, 1, 2, 0, 1, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 5, 6, 0, 4, 0, 4, 0, 3, 2, 4, 0, 2, 2, 3, 2, 0, 1, 3, 3, 1, 1, 2 }; #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY) \ { \ yychar = (Token); \ yylval = (Value); \ YYPOPSTACK (yylen); \ yystate = *yyssp; \ goto yybackup; \ } \ else \ { \ yyerror (&yylloc, yyscanner, rtr, ralloc, palloc, YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (0) /* Error token number */ #define YYTERROR 1 #define YYERRCODE 256 /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. If N is 0, then set CURRENT to the empty location which ends the previous symbol: RHS[0] (always defined). */ #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ do \ if (N) \ { \ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ } \ else \ { \ (Current).first_line = (Current).last_line = \ YYRHSLOC (Rhs, 0).last_line; \ (Current).first_column = (Current).last_column = \ YYRHSLOC (Rhs, 0).last_column; \ } \ while (0) #endif #define YYRHSLOC(Rhs, K) ((Rhs)[K]) /* Enable debugging if requested. */ #if ROUTER_YYDEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (0) /* YY_LOCATION_PRINT -- Print the location on the stream. This macro was not mandated originally: define only if we know we won't break user code: when these are the locations we know. */ #ifndef YY_LOCATION_PRINT # if defined ROUTER_YYLTYPE_IS_TRIVIAL && ROUTER_YYLTYPE_IS_TRIVIAL /* Print *YYLOCP on YYO. Private, do not rely on its existence. */ YY_ATTRIBUTE_UNUSED static unsigned yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp) { unsigned res = 0; int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0; if (0 <= yylocp->first_line) { res += YYFPRINTF (yyo, "%d", yylocp->first_line); if (0 <= yylocp->first_column) res += YYFPRINTF (yyo, ".%d", yylocp->first_column); } if (0 <= yylocp->last_line) { if (yylocp->first_line < yylocp->last_line) { res += YYFPRINTF (yyo, "-%d", yylocp->last_line); if (0 <= end_col) res += YYFPRINTF (yyo, ".%d", end_col); } else if (0 <= end_col && yylocp->first_column < end_col) res += YYFPRINTF (yyo, "-%d", end_col); } return res; } # define YY_LOCATION_PRINT(File, Loc) \ yy_location_print_ (File, &(Loc)) # else # define YY_LOCATION_PRINT(File, Loc) ((void) 0) # endif #endif # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ Type, Value, Location, yyscanner, rtr, ralloc, palloc); \ YYFPRINTF (stderr, "\n"); \ } \ } while (0) /*----------------------------------------. | Print this symbol's value on YYOUTPUT. | `----------------------------------------*/ static void yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, void *yyscanner, router *rtr, allocator *ralloc, allocator *palloc) { FILE *yyo = yyoutput; YYUSE (yyo); YYUSE (yylocationp); YYUSE (yyscanner); YYUSE (rtr); YYUSE (ralloc); YYUSE (palloc); if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); # endif YYUSE (yytype); } /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ static void yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, void *yyscanner, router *rtr, allocator *ralloc, allocator *palloc) { YYFPRINTF (yyoutput, "%s %s (", yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); YY_LOCATION_PRINT (yyoutput, *yylocationp); YYFPRINTF (yyoutput, ": "); yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, yyscanner, rtr, ralloc, palloc); YYFPRINTF (yyoutput, ")"); } /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ static void yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) { YYFPRINTF (stderr, "Stack now"); for (; yybottom <= yytop; yybottom++) { int yybot = *yybottom; YYFPRINTF (stderr, " %d", yybot); } YYFPRINTF (stderr, "\n"); } # define YY_STACK_PRINT(Bottom, Top) \ do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ } while (0) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ static void yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, void *yyscanner, router *rtr, allocator *ralloc, allocator *palloc) { unsigned long int yylno = yyrline[yyrule]; int yynrhs = yyr2[yyrule]; int yyi; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yystos[yyssp[yyi + 1 - yynrhs]], &yyvsp[(yyi + 1) - (yynrhs)] , &(yylsp[(yyi + 1) - (yynrhs)]) , yyscanner, rtr, ralloc, palloc); YYFPRINTF (stderr, "\n"); } } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ yy_reduce_print (yyssp, yyvsp, yylsp, Rule, yyscanner, rtr, ralloc, palloc); \ } while (0) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !ROUTER_YYDEBUG */ # define YYDPRINTF(Args) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !ROUTER_YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif #if YYERROR_VERBOSE # ifndef yystrlen # if defined __GLIBC__ && defined _STRING_H # define yystrlen strlen # else /* Return the length of YYSTR. */ static YYSIZE_T yystrlen (const char *yystr) { YYSIZE_T yylen; for (yylen = 0; yystr[yylen]; yylen++) continue; return yylen; } # endif # endif # ifndef yystpcpy # if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ static char * yystpcpy (char *yydest, const char *yysrc) { char *yyd = yydest; const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; return yyd - 1; } # endif # endif # ifndef yytnamerr /* Copy to YYRES the contents of YYSTR after stripping away unnecessary quotes and backslashes, so that it's suitable for yyerror. The heuristic is that double-quoting is unnecessary unless the string contains an apostrophe, a comma, or backslash (other than backslash-backslash). YYSTR is taken from yytname. If YYRES is null, do not copy; instead, return the length of what the result would have been. */ static YYSIZE_T yytnamerr (char *yyres, const char *yystr) { if (*yystr == '"') { YYSIZE_T yyn = 0; char const *yyp = yystr; for (;;) switch (*++yyp) { case '\'': case ',': goto do_not_strip_quotes; case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; /* Fall through. */ default: if (yyres) yyres[yyn] = *yyp; yyn++; break; case '"': if (yyres) yyres[yyn] = '\0'; return yyn; } do_not_strip_quotes: ; } if (! yyres) return yystrlen (yystr); return yystpcpy (yyres, yystr) - yyres; } # endif /* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message about the unexpected token YYTOKEN for the state stack whose top is YYSSP. Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is not large enough to hold the message. In that case, also set *YYMSG_ALLOC to the required number of bytes. Return 2 if the required number of bytes is too large to store. */ static int yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, yytype_int16 *yyssp, int yytoken) { YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); YYSIZE_T yysize = yysize0; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; /* Internationalized format string. */ const char *yyformat = YY_NULLPTR; /* Arguments of yyformat. */ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; /* Number of reported tokens (one for the "unexpected", one per "expected"). */ int yycount = 0; /* There are many possibilities here to consider: - If this state is a consistent state with a default action, then the only way this function was invoked is if the default action is an error action. In that case, don't check for expected tokens because there are none. - The only way there can be no lookahead present (in yychar) is if this state is a consistent state with a default action. Thus, detecting the absence of a lookahead is sufficient to determine that there is no unexpected or expected token to report. In that case, just report a simple "syntax error". - Don't assume there isn't a lookahead just because this state is a consistent state with a default action. There might have been a previous inconsistent state, consistent state with a non-default action, or user semantic action that manipulated yychar. - Of course, the expected token list depends on states to have correct lookahead information, and it depends on the parser not to perform extra reductions after fetching a lookahead from the scanner and before detecting a syntax error. Thus, state merging (from LALR or IELR) and default reductions corrupt the expected token list. However, the list is correct for canonical LR with one exception: it will still contain any token that will not be accepted due to an error action in a later state. */ if (yytoken != YYEMPTY) { int yyn = yypact[*yyssp]; yyarg[yycount++] = yytname[yytoken]; if (!yypact_value_is_default (yyn)) { /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. In other words, skip the first -YYN actions for this state because they are default actions. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn + 1; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yyx; for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR && !yytable_value_is_error (yytable[yyx + yyn])) { if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) { yycount = 1; yysize = yysize0; break; } yyarg[yycount++] = yytname[yyx]; { YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) return 2; yysize = yysize1; } } } } switch (yycount) { # define YYCASE_(N, S) \ case N: \ yyformat = S; \ break YYCASE_(0, YY_("syntax error")); YYCASE_(1, YY_("syntax error, unexpected %s")); YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); # undef YYCASE_ } { YYSIZE_T yysize1 = yysize + yystrlen (yyformat); if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) return 2; yysize = yysize1; } if (*yymsg_alloc < yysize) { *yymsg_alloc = 2 * yysize; if (! (yysize <= *yymsg_alloc && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; return 1; } /* Avoid sprintf, as that infringes on the user's name space. Don't have undefined behavior even if the translation produced a string with the wrong number of "%s"s. */ { char *yyp = *yymsg; int yyi = 0; while ((*yyp = *yyformat) != '\0') if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) { yyp += yytnamerr (yyp, yyarg[yyi++]); yyformat += 2; } else { yyp++; yyformat++; } } return 0; } #endif /* YYERROR_VERBOSE */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ static void yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, void *yyscanner, router *rtr, allocator *ralloc, allocator *palloc) { YYUSE (yyvaluep); YYUSE (yylocationp); YYUSE (yyscanner); YYUSE (rtr); YYUSE (ralloc); YYUSE (palloc); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN YYUSE (yytype); YY_IGNORE_MAYBE_UNINITIALIZED_END } /*----------. | yyparse. | `----------*/ int yyparse (void *yyscanner, router *rtr, allocator *ralloc, allocator *palloc) { /* The lookahead symbol. */ int yychar; /* The semantic value of the lookahead symbol. */ /* Default value used for initialization, for pacifying older GCCs or non-GCC compilers. */ YY_INITIAL_VALUE (static YYSTYPE yyval_default;) YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); /* Location data for the lookahead symbol. */ static YYLTYPE yyloc_default # if defined ROUTER_YYLTYPE_IS_TRIVIAL && ROUTER_YYLTYPE_IS_TRIVIAL = { 1, 1, 1, 1 } # endif ; YYLTYPE yylloc = yyloc_default; /* Number of syntax errors so far. */ int yynerrs; int yystate; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* The stacks and their tools: 'yyss': related to states. 'yyvs': related to semantic values. 'yyls': related to locations. Refer to the stacks through separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ yytype_int16 yyssa[YYINITDEPTH]; yytype_int16 *yyss; yytype_int16 *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs; YYSTYPE *yyvsp; /* The location stack. */ YYLTYPE yylsa[YYINITDEPTH]; YYLTYPE *yyls; YYLTYPE *yylsp; /* The locations where the error started and ended. */ YYLTYPE yyerror_range[3]; YYSIZE_T yystacksize; int yyn; int yyresult; /* Lookahead token as an internal (translated) token number. */ int yytoken = 0; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; YYLTYPE yyloc; #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; char *yymsg = yymsgbuf; YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N)) /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; yyssp = yyss = yyssa; yyvsp = yyvs = yyvsa; yylsp = yyls = yylsa; yystacksize = YYINITDEPTH; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ yylsp[0] = yylloc; goto yysetstate; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; yysetstate: *yyssp = yystate; if (yyss + yystacksize - 1 <= yyssp) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; YYLTYPE *yyls1 = yyls; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yyls1, yysize * sizeof (*yylsp), &yystacksize); yyls = yyls1; yyss = yyss1; yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE goto yyexhaustedlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { yytype_int16 *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); YYSTACK_RELOCATE (yyls_alloc, yyls); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; yylsp = yyls + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); if (yystate == YYFINAL) YYACCEPT; goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. Read a lookahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yypact_value_is_default (yyn)) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = yylex (&yylval, &yylloc, yyscanner, rtr, ralloc, palloc); } if (yychar <= YYEOF) { yychar = yytoken = YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } else { yytoken = YYTRANSLATE (yychar); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; yyn = yytable[yyn]; if (yyn <= 0) { if (yytable_value_is_error (yyn)) goto yyerrlab; yyn = -yyn; goto yyreduce; } /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; /* Shift the lookahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the shifted token. */ yychar = YYEMPTY; yystate = yyn; YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; YY_IGNORE_MAYBE_UNINITIALIZED_END *++yylsp = yylloc; goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: '$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. Assigning to YYVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; /* Default location. */ YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); YY_REDUCE_PRINT (yyn); switch (yyn) { case 14: #line 142 "conffile.y" /* yacc.c:1646 */ { struct _clhost *w; char *err; int srvcnt; /* count number of servers for ch_new */ for (srvcnt = 0, w = (*(struct _clhost **)(&yyvsp[0])); w != NULL; w = w->next, srvcnt++) ; if (((*(cluster **)(&yyval)) = ra_malloc(ralloc, sizeof(cluster))) == NULL) { logerr("malloc failed for cluster '%s'\n", (*(char **)(&yyvsp[-2]))); YYABORT; } (*(cluster **)(&yyval))->name = ra_strdup(ralloc, (*(char **)(&yyvsp[-2]))); (*(cluster **)(&yyval))->next = NULL; (*(cluster **)(&yyval))->type = (*(struct _clust*)(&yyvsp[-1])).t; switch ((*(cluster **)(&yyval))->type) { case CARBON_CH: case FNV1A_CH: case JUMP_CH: (*(cluster **)(&yyval))->members.ch = ra_malloc(ralloc, sizeof(chashring)); if ((*(cluster **)(&yyval))->members.ch == NULL) { logerr("malloc failed for ch in cluster '%s'\n", (*(char **)(&yyvsp[-2]))); YYABORT; } if ((*(struct _clust*)(&yyvsp[-1])).ival < 1 || (*(struct _clust*)(&yyvsp[-1])).ival > 255) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, "replication count must be between 1 and 255"); YYERROR; } (*(cluster **)(&yyval))->members.ch->repl_factor = (unsigned char)(*(struct _clust*)(&yyvsp[-1])).ival; (*(cluster **)(&yyval))->members.ch->ring = ch_new(ralloc, (*(cluster **)(&yyval))->type == CARBON_CH ? CARBON : (*(cluster **)(&yyval))->type == FNV1A_CH ? FNV1a : JUMP_FNV1a, srvcnt); (*(cluster **)(&yyval))->members.ch->servers = NULL; (*(struct _clust*)(&yyvsp[-1])).ival = 0; /* hack, avoid triggering use_all */ break; case FORWARD: (*(cluster **)(&yyval))->members.forward = NULL; break; case ANYOF: case FAILOVER: (*(cluster **)(&yyval))->members.anyof = NULL; break; default: logerr("unknown cluster type %zd!\n", (*(cluster **)(&yyval))->type); YYABORT; } for (w = (*(struct _clhost **)(&yyvsp[0])); w != NULL; w = w->next) { err = router_add_server(rtr, w->ip, w->port, w->inst, T_LINEMODE, w->trnsp, w->proto, w->saddr, w->hint, (*(struct _clust*)(&yyvsp[-1])).ival, (*(cluster **)(&yyval))); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } } err = router_add_cluster(rtr, (*(cluster **)(&yyval))); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } } #line 1783 "conffile.tab.c" /* yacc.c:1646 */ break; case 15: #line 209 "conffile.y" /* yacc.c:1646 */ { struct _clhost *w; char *err; if (((*(cluster **)(&yyval)) = ra_malloc(ralloc, sizeof(cluster))) == NULL) { logerr("malloc failed for cluster '%s'\n", (*(char **)(&yyvsp[-2]))); YYABORT; } (*(cluster **)(&yyval))->name = ra_strdup(ralloc, (*(char **)(&yyvsp[-2]))); (*(cluster **)(&yyval))->next = NULL; (*(cluster **)(&yyval))->type = (*(struct _clust*)(&yyvsp[-1])).t; switch ((*(cluster **)(&yyval))->type) { case FILELOG: case FILELOGIP: (*(cluster **)(&yyval))->members.forward = NULL; break; default: logerr("unknown cluster type %zd!\n", (*(cluster **)(&yyval))->type); YYABORT; } for (w = (*(struct _clhost **)(&yyvsp[0])); w != NULL; w = w->next) { err = router_add_server(rtr, w->ip, w->port, w->inst, T_LINEMODE, W_PLAIN, w->proto, w->saddr, w->hint, (*(struct _clust*)(&yyvsp[-1])).ival, (*(cluster **)(&yyval))); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } } err = router_add_cluster(rtr, (*(cluster **)(&yyval))); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } } #line 1825 "conffile.tab.c" /* yacc.c:1646 */ break; case 16: #line 250 "conffile.y" /* yacc.c:1646 */ { (*(struct _clust*)(&yyval)).t = (*(enum clusttype*)(&yyvsp[-1])); (*(struct _clust*)(&yyval)).ival = (*(int*)(&yyvsp[0])); } #line 1831 "conffile.tab.c" /* yacc.c:1646 */ break; case 17: #line 252 "conffile.y" /* yacc.c:1646 */ { (*(struct _clust*)(&yyval)).t = (*(enum clusttype*)(&yyvsp[-1])); (*(struct _clust*)(&yyval)).ival = (*(int*)(&yyvsp[0])); } #line 1837 "conffile.tab.c" /* yacc.c:1646 */ break; case 18: #line 255 "conffile.y" /* yacc.c:1646 */ { (*(enum clusttype*)(&yyval)) = FORWARD; } #line 1843 "conffile.tab.c" /* yacc.c:1646 */ break; case 19: #line 256 "conffile.y" /* yacc.c:1646 */ { (*(enum clusttype*)(&yyval)) = ANYOF; } #line 1849 "conffile.tab.c" /* yacc.c:1646 */ break; case 20: #line 257 "conffile.y" /* yacc.c:1646 */ { (*(enum clusttype*)(&yyval)) = FAILOVER; } #line 1855 "conffile.tab.c" /* yacc.c:1646 */ break; case 21: #line 260 "conffile.y" /* yacc.c:1646 */ { (*(int*)(&yyval)) = 0; } #line 1861 "conffile.tab.c" /* yacc.c:1646 */ break; case 22: #line 261 "conffile.y" /* yacc.c:1646 */ { (*(int*)(&yyval)) = 1; } #line 1867 "conffile.tab.c" /* yacc.c:1646 */ break; case 23: #line 264 "conffile.y" /* yacc.c:1646 */ { (*(enum clusttype*)(&yyval)) = CARBON_CH; } #line 1873 "conffile.tab.c" /* yacc.c:1646 */ break; case 24: #line 265 "conffile.y" /* yacc.c:1646 */ { (*(enum clusttype*)(&yyval)) = FNV1A_CH; } #line 1879 "conffile.tab.c" /* yacc.c:1646 */ break; case 25: #line 266 "conffile.y" /* yacc.c:1646 */ { (*(enum clusttype*)(&yyval)) = JUMP_CH; } #line 1885 "conffile.tab.c" /* yacc.c:1646 */ break; case 26: #line 269 "conffile.y" /* yacc.c:1646 */ { (*(int*)(&yyval)) = 1; } #line 1891 "conffile.tab.c" /* yacc.c:1646 */ break; case 27: #line 270 "conffile.y" /* yacc.c:1646 */ { (*(int*)(&yyval)) = (*(int*)(&yyvsp[0])); } #line 1897 "conffile.tab.c" /* yacc.c:1646 */ break; case 28: #line 273 "conffile.y" /* yacc.c:1646 */ { (*(struct _clust*)(&yyval)).t = FILELOGIP; (*(struct _clust*)(&yyval)).ival = 0; } #line 1903 "conffile.tab.c" /* yacc.c:1646 */ break; case 29: #line 274 "conffile.y" /* yacc.c:1646 */ { (*(struct _clust*)(&yyval)).t = FILELOG; (*(struct _clust*)(&yyval)).ival = 0; } #line 1909 "conffile.tab.c" /* yacc.c:1646 */ break; case 30: #line 277 "conffile.y" /* yacc.c:1646 */ { (*(struct _clhost **)(&yyvsp[-1]))->next = (*(struct _clhost **)(&yyvsp[0])); (*(struct _clhost **)(&yyval)) = (*(struct _clhost **)(&yyvsp[-1])); } #line 1915 "conffile.tab.c" /* yacc.c:1646 */ break; case 31: #line 279 "conffile.y" /* yacc.c:1646 */ { (*(struct _clhost **)(&yyval)) = NULL; } #line 1921 "conffile.tab.c" /* yacc.c:1646 */ break; case 32: #line 280 "conffile.y" /* yacc.c:1646 */ { (*(struct _clhost **)(&yyval)) = (*(struct _clhost **)(&yyvsp[0])); } #line 1927 "conffile.tab.c" /* yacc.c:1646 */ break; case 33: #line 283 "conffile.y" /* yacc.c:1646 */ { struct _clhost *ret = ra_malloc(palloc, sizeof(struct _clhost)); char *err = router_validate_path(rtr, (*(char **)(&yyvsp[0]))); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } ret->ip = (*(char **)(&yyvsp[0])); ret->port = GRAPHITE_PORT; ret->saddr = NULL; ret->hint = NULL; ret->inst = NULL; ret->proto = CON_FILE; ret->next = NULL; (*(struct _clhost **)(&yyval)) = ret; } #line 1949 "conffile.tab.c" /* yacc.c:1646 */ break; case 34: #line 302 "conffile.y" /* yacc.c:1646 */ { (*(struct _clhost **)(&yyvsp[-1]))->next = (*(struct _clhost **)(&yyvsp[0])); (*(struct _clhost **)(&yyval)) = (*(struct _clhost **)(&yyvsp[-1])); } #line 1955 "conffile.tab.c" /* yacc.c:1646 */ break; case 35: #line 304 "conffile.y" /* yacc.c:1646 */ { (*(struct _clhost **)(&yyval)) = NULL; } #line 1961 "conffile.tab.c" /* yacc.c:1646 */ break; case 36: #line 305 "conffile.y" /* yacc.c:1646 */ { (*(struct _clhost **)(&yyval)) = (*(struct _clhost **)(&yyvsp[0])); } #line 1967 "conffile.tab.c" /* yacc.c:1646 */ break; case 37: #line 310 "conffile.y" /* yacc.c:1646 */ { struct _clhost *ret = ra_malloc(palloc, sizeof(struct _clhost)); char *err = router_validate_address( rtr, &(ret->ip), &(ret->port), &(ret->saddr), &(ret->hint), (*(char **)(&yyvsp[-4])), (*(con_proto*)(&yyvsp[-2]))); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } ret->inst = (*(char **)(&yyvsp[-3])); ret->proto = (*(con_proto*)(&yyvsp[-2])); ret->trnsp = (*(con_trnsp*)(&yyvsp[0])); ret->next = NULL; (*(struct _clhost **)(&yyval)) = ret; } #line 1989 "conffile.tab.c" /* yacc.c:1646 */ break; case 38: #line 328 "conffile.y" /* yacc.c:1646 */ { (*(char **)(&yyval)) = NULL; } #line 1995 "conffile.tab.c" /* yacc.c:1646 */ break; case 39: #line 329 "conffile.y" /* yacc.c:1646 */ { (*(char **)(&yyval)) = (*(char **)(&yyvsp[0])); } #line 2001 "conffile.tab.c" /* yacc.c:1646 */ break; case 40: #line 331 "conffile.y" /* yacc.c:1646 */ { (*(char **)(&yyval)) = ra_malloc(palloc, sizeof(char) * 12); if ((*(char **)(&yyval)) == NULL) { logerr("out of memory\n"); YYABORT; } snprintf((*(char **)(&yyval)), 12, "%d", (*(int*)(&yyvsp[0]))); } #line 2014 "conffile.tab.c" /* yacc.c:1646 */ break; case 41: #line 340 "conffile.y" /* yacc.c:1646 */ { (*(con_proto*)(&yyval)) = CON_TCP; } #line 2020 "conffile.tab.c" /* yacc.c:1646 */ break; case 42: #line 341 "conffile.y" /* yacc.c:1646 */ { (*(con_proto*)(&yyval)) = CON_UDP; } #line 2026 "conffile.tab.c" /* yacc.c:1646 */ break; case 43: #line 342 "conffile.y" /* yacc.c:1646 */ { (*(con_proto*)(&yyval)) = CON_TCP; } #line 2032 "conffile.tab.c" /* yacc.c:1646 */ break; case 46: #line 349 "conffile.y" /* yacc.c:1646 */ { (*(con_trnsp*)(&yyval)) = W_PLAIN; } #line 2038 "conffile.tab.c" /* yacc.c:1646 */ break; case 47: #line 350 "conffile.y" /* yacc.c:1646 */ { #ifdef HAVE_GZIP (*(con_trnsp*)(&yyval)) = W_GZIP; #else router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, "feature gzip not compiled in"); YYERROR; #endif } #line 2053 "conffile.tab.c" /* yacc.c:1646 */ break; case 48: #line 360 "conffile.y" /* yacc.c:1646 */ { #ifdef HAVE_LZ4 (*(con_trnsp*)(&yyval)) = W_LZ4; #else router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, "feature lz4 not compiled in"); YYERROR; #endif } #line 2068 "conffile.tab.c" /* yacc.c:1646 */ break; case 49: #line 370 "conffile.y" /* yacc.c:1646 */ { #ifdef HAVE_SSL (*(con_trnsp*)(&yyval)) = W_SSL; #else router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, "feature ssl not compiled in"); YYERROR; #endif } #line 2083 "conffile.tab.c" /* yacc.c:1646 */ break; case 50: #line 386 "conffile.y" /* yacc.c:1646 */ { /* each expr comes with an allocated route, populate it */ struct _maexpr *we; destinations *d = NULL; char *err; if ((*(struct _maexpr **)(&yyvsp[-3])) != NULL) { /* optional validate clause */ if ((d = ra_malloc(ralloc, sizeof(destinations))) == NULL) { logerr("out of memory\n"); YYABORT; } d->next = NULL; if ((d->cl = ra_malloc(ralloc, sizeof(cluster))) == NULL) { logerr("out of memory\n"); YYABORT; } d->cl->name = NULL; d->cl->type = VALIDATION; d->cl->next = NULL; d->cl->members.validation = ra_malloc(ralloc, sizeof(validate)); if (d->cl->members.validation == NULL) { logerr("out of memory\n"); YYABORT; } d->cl->members.validation->rule = (*(struct _maexpr **)(&yyvsp[-3]))->r; d->cl->members.validation->action = (*(struct _maexpr **)(&yyvsp[-3]))->drop ? VAL_DROP : VAL_LOG; } /* add destinations to the chain */ if (d != NULL) { d->next = (*(destinations **)(&yyvsp[-1])); } else { d = (*(destinations **)(&yyvsp[-1])); } /* replace with copy on the router allocator */ if ((*(char **)(&yyvsp[-2])) != NULL) (*(char **)(&yyvsp[-2])) = ra_strdup(ralloc, (*(char **)(&yyvsp[-2]))); for (we = (*(struct _maexpr **)(&yyvsp[-4])); we != NULL; we = we->next) { we->r->next = NULL; we->r->dests = d; we->r->masq = (*(char **)(&yyvsp[-2])); we->r->stop = (*(destinations **)(&yyvsp[-1])) == NULL ? 0 : (*(destinations **)(&yyvsp[-1]))->cl->type == BLACKHOLE ? 1 : (*(int*)(&yyvsp[0])); err = router_add_route(rtr, we->r); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } } } #line 2139 "conffile.tab.c" /* yacc.c:1646 */ break; case 51: #line 440 "conffile.y" /* yacc.c:1646 */ { if (((*(struct _maexpr **)(&yyval)) = ra_malloc(palloc, sizeof(struct _maexpr))) == NULL) { logerr("out of memory\n"); YYABORT; } (*(struct _maexpr **)(&yyval))->r = NULL; if (router_validate_expression(rtr, &((*(struct _maexpr **)(&yyval))->r), "*") != NULL) YYABORT; (*(struct _maexpr **)(&yyval))->drop = 0; (*(struct _maexpr **)(&yyval))->next = NULL; } #line 2155 "conffile.tab.c" /* yacc.c:1646 */ break; case 52: #line 451 "conffile.y" /* yacc.c:1646 */ { (*(struct _maexpr **)(&yyval)) = (*(struct _maexpr **)(&yyvsp[0])); } #line 2161 "conffile.tab.c" /* yacc.c:1646 */ break; case 53: #line 454 "conffile.y" /* yacc.c:1646 */ { (*(struct _maexpr **)(&yyvsp[-1]))->next = (*(struct _maexpr **)(&yyvsp[0])); (*(struct _maexpr **)(&yyval)) = (*(struct _maexpr **)(&yyvsp[-1])); } #line 2167 "conffile.tab.c" /* yacc.c:1646 */ break; case 54: #line 456 "conffile.y" /* yacc.c:1646 */ { (*(struct _maexpr **)(&yyval)) = NULL; } #line 2173 "conffile.tab.c" /* yacc.c:1646 */ break; case 55: #line 457 "conffile.y" /* yacc.c:1646 */ { (*(struct _maexpr **)(&yyval)) = (*(struct _maexpr **)(&yyvsp[0])); } #line 2179 "conffile.tab.c" /* yacc.c:1646 */ break; case 56: #line 461 "conffile.y" /* yacc.c:1646 */ { char *err; if (((*(struct _maexpr **)(&yyval)) = ra_malloc(palloc, sizeof(struct _maexpr))) == NULL) { logerr("out of memory\n"); YYABORT; } (*(struct _maexpr **)(&yyval))->r = NULL; err = router_validate_expression(rtr, &((*(struct _maexpr **)(&yyval))->r), (*(char **)(&yyvsp[0]))); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } (*(struct _maexpr **)(&yyval))->drop = 0; (*(struct _maexpr **)(&yyval))->next = NULL; } #line 2200 "conffile.tab.c" /* yacc.c:1646 */ break; case 57: #line 479 "conffile.y" /* yacc.c:1646 */ { (*(struct _maexpr **)(&yyval)) = NULL; } #line 2206 "conffile.tab.c" /* yacc.c:1646 */ break; case 58: #line 481 "conffile.y" /* yacc.c:1646 */ { char *err; if (((*(struct _maexpr **)(&yyval)) = ra_malloc(palloc, sizeof(struct _maexpr))) == NULL) { logerr("out of memory\n"); YYABORT; } (*(struct _maexpr **)(&yyval))->r = NULL; err = router_validate_expression(rtr, &((*(struct _maexpr **)(&yyval))->r), (*(char **)(&yyvsp[-2]))); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } (*(struct _maexpr **)(&yyval))->drop = (*(int*)(&yyvsp[0])); (*(struct _maexpr **)(&yyval))->next = NULL; } #line 2227 "conffile.tab.c" /* yacc.c:1646 */ break; case 59: #line 499 "conffile.y" /* yacc.c:1646 */ { (*(int*)(&yyval)) = 0; } #line 2233 "conffile.tab.c" /* yacc.c:1646 */ break; case 60: #line 500 "conffile.y" /* yacc.c:1646 */ { (*(int*)(&yyval)) = 1; } #line 2239 "conffile.tab.c" /* yacc.c:1646 */ break; case 61: #line 503 "conffile.y" /* yacc.c:1646 */ { (*(char **)(&yyval)) = NULL; } #line 2245 "conffile.tab.c" /* yacc.c:1646 */ break; case 62: #line 504 "conffile.y" /* yacc.c:1646 */ { (*(char **)(&yyval)) = (*(char **)(&yyvsp[0])); } #line 2251 "conffile.tab.c" /* yacc.c:1646 */ break; case 63: #line 507 "conffile.y" /* yacc.c:1646 */ { (*(destinations **)(&yyval)) = NULL; } #line 2257 "conffile.tab.c" /* yacc.c:1646 */ break; case 64: #line 508 "conffile.y" /* yacc.c:1646 */ { (*(destinations **)(&yyval)) = (*(destinations **)(&yyvsp[0])); } #line 2263 "conffile.tab.c" /* yacc.c:1646 */ break; case 65: #line 511 "conffile.y" /* yacc.c:1646 */ { (*(destinations **)(&yyval)) = (*(destinations **)(&yyvsp[0])); } #line 2269 "conffile.tab.c" /* yacc.c:1646 */ break; case 66: #line 515 "conffile.y" /* yacc.c:1646 */ { if (((*(destinations **)(&yyval)) = ra_malloc(ralloc, sizeof(destinations))) == NULL) { logerr("out of memory\n"); YYABORT; } if (router_validate_cluster(rtr, &((*(destinations **)(&yyval))->cl), "blackhole") != NULL) YYABORT; (*(destinations **)(&yyval))->next = NULL; } #line 2283 "conffile.tab.c" /* yacc.c:1646 */ break; case 67: #line 524 "conffile.y" /* yacc.c:1646 */ { (*(destinations **)(&yyval)) = (*(destinations **)(&yyvsp[0])); } #line 2289 "conffile.tab.c" /* yacc.c:1646 */ break; case 68: #line 527 "conffile.y" /* yacc.c:1646 */ { (*(destinations **)(&yyvsp[-1]))->next = (*(destinations **)(&yyvsp[0])); (*(destinations **)(&yyval)) = (*(destinations **)(&yyvsp[-1])); } #line 2295 "conffile.tab.c" /* yacc.c:1646 */ break; case 69: #line 529 "conffile.y" /* yacc.c:1646 */ { (*(destinations **)(&yyval)) = NULL; } #line 2301 "conffile.tab.c" /* yacc.c:1646 */ break; case 70: #line 530 "conffile.y" /* yacc.c:1646 */ { (*(destinations **)(&yyval)) = (*(destinations **)(&yyvsp[0])); } #line 2307 "conffile.tab.c" /* yacc.c:1646 */ break; case 71: #line 534 "conffile.y" /* yacc.c:1646 */ { char *err; if (((*(destinations **)(&yyval)) = ra_malloc(ralloc, sizeof(destinations))) == NULL) { logerr("out of memory\n"); YYABORT; } err = router_validate_cluster(rtr, &((*(destinations **)(&yyval))->cl), (*(char **)(&yyvsp[0]))); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } (*(destinations **)(&yyval))->next = NULL; } #line 2325 "conffile.tab.c" /* yacc.c:1646 */ break; case 72: #line 549 "conffile.y" /* yacc.c:1646 */ { (*(int*)(&yyval)) = 0; } #line 2331 "conffile.tab.c" /* yacc.c:1646 */ break; case 73: #line 550 "conffile.y" /* yacc.c:1646 */ { (*(int*)(&yyval)) = 1; } #line 2337 "conffile.tab.c" /* yacc.c:1646 */ break; case 74: #line 556 "conffile.y" /* yacc.c:1646 */ { char *err; route *r = NULL; cluster *cl; err = router_validate_expression(rtr, &r, (*(char **)(&yyvsp[-2]))); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } cl = ra_malloc(ralloc, sizeof(cluster)); if (cl == NULL) { logerr("out of memory\n"); YYABORT; } cl->type = REWRITE; cl->name = NULL; cl->members.replacement = ra_strdup(ralloc, (*(char **)(&yyvsp[0]))); cl->next = NULL; if (cl->members.replacement == NULL) { logerr("out of memory\n"); YYABORT; } r->dests = ra_malloc(ralloc, sizeof(destinations)); if (r->dests == NULL) { logerr("out of memory\n"); YYABORT; } r->dests->cl = cl; r->dests->next = NULL; r->stop = 0; r->next = NULL; err = router_add_route(rtr, r); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } } #line 2382 "conffile.tab.c" /* yacc.c:1646 */ break; case 75: #line 606 "conffile.y" /* yacc.c:1646 */ { cluster *w; aggregator *a; destinations *d; struct _agcomp *acw; struct _maexpr *we; char *err; if ((*(int*)(&yyvsp[-9])) <= 0) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, "interval must be > 0"); YYERROR; } if ((*(int*)(&yyvsp[-5])) <= 0) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, "expire must be > 0"); YYERROR; } if ((*(int*)(&yyvsp[-5])) < (*(int*)(&yyvsp[-9]))) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, "expire must be greater than interval"); YYERROR; } w = ra_malloc(ralloc, sizeof(cluster)); if (w == NULL) { logerr("malloc failed for aggregate\n"); YYABORT; } w->name = NULL; w->type = AGGREGATION; w->next = NULL; a = aggregator_new((*(int*)(&yyvsp[-9])), (*(int*)(&yyvsp[-5])), (*(enum _aggr_timestamp*)(&yyvsp[-3]))); if (a == NULL) { logerr("out of memory\n"); YYABORT; } if ((err = router_add_aggregator(rtr, a)) != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } w->members.aggregation = a; for (acw = (*(struct _agcomp **)(&yyvsp[-2])); acw != NULL; acw = acw->next) { if (aggregator_add_compute(a, acw->metric, acw->ctype, acw->pctl) != 0) { logerr("out of memory\n"); YYABORT; } } err = router_add_cluster(rtr, w); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } d = ra_malloc(ralloc, sizeof(destinations)); if (d == NULL) { logerr("out of memory\n"); YYABORT; } d->cl = w; d->next = (*(destinations **)(&yyvsp[-1])); for (we = (*(struct _maexpr **)(&yyvsp[-11])); we != NULL; we = we->next) { we->r->next = NULL; we->r->dests = d; we->r->stop = (*(int*)(&yyvsp[0])); err = router_add_route(rtr, we->r); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } } if ((*(destinations **)(&yyvsp[-1])) != NULL) router_add_stubroute(rtr, AGGRSTUB, w, (*(destinations **)(&yyvsp[-1]))); } #line 2470 "conffile.tab.c" /* yacc.c:1646 */ break; case 76: #line 691 "conffile.y" /* yacc.c:1646 */ { (*(enum _aggr_timestamp*)(&yyval)) = TS_END; } #line 2476 "conffile.tab.c" /* yacc.c:1646 */ break; case 77: #line 694 "conffile.y" /* yacc.c:1646 */ { (*(enum _aggr_timestamp*)(&yyval)) = (*(enum _aggr_timestamp*)(&yyvsp[-2])); } #line 2482 "conffile.tab.c" /* yacc.c:1646 */ break; case 78: #line 697 "conffile.y" /* yacc.c:1646 */ { (*(enum _aggr_timestamp*)(&yyval)) = TS_START; } #line 2488 "conffile.tab.c" /* yacc.c:1646 */ break; case 79: #line 698 "conffile.y" /* yacc.c:1646 */ { (*(enum _aggr_timestamp*)(&yyval)) = TS_MIDDLE; } #line 2494 "conffile.tab.c" /* yacc.c:1646 */ break; case 80: #line 699 "conffile.y" /* yacc.c:1646 */ { (*(enum _aggr_timestamp*)(&yyval)) = TS_END; } #line 2500 "conffile.tab.c" /* yacc.c:1646 */ break; case 81: #line 703 "conffile.y" /* yacc.c:1646 */ { (*(struct _agcomp **)(&yyvsp[-1]))->next = (*(struct _agcomp **)(&yyvsp[0])); (*(struct _agcomp **)(&yyval)) = (*(struct _agcomp **)(&yyvsp[-1])); } #line 2506 "conffile.tab.c" /* yacc.c:1646 */ break; case 82: #line 706 "conffile.y" /* yacc.c:1646 */ { (*(struct _agcomp **)(&yyval)) = NULL; } #line 2512 "conffile.tab.c" /* yacc.c:1646 */ break; case 83: #line 707 "conffile.y" /* yacc.c:1646 */ { (*(struct _agcomp **)(&yyval)) = (*(struct _agcomp **)(&yyvsp[0])); } #line 2518 "conffile.tab.c" /* yacc.c:1646 */ break; case 84: #line 711 "conffile.y" /* yacc.c:1646 */ { (*(struct _agcomp **)(&yyval)) = ra_malloc(palloc, sizeof(struct _agcomp)); if ((*(struct _agcomp **)(&yyval)) == NULL) { logerr("malloc failed\n"); YYABORT; } (*(struct _agcomp **)(&yyval))->ctype = (*(struct _agcomp*)(&yyvsp[-3])).ctype; (*(struct _agcomp **)(&yyval))->pctl = (*(struct _agcomp*)(&yyvsp[-3])).pctl; (*(struct _agcomp **)(&yyval))->metric = (*(char **)(&yyvsp[0])); (*(struct _agcomp **)(&yyval))->next = NULL; } #line 2534 "conffile.tab.c" /* yacc.c:1646 */ break; case 85: #line 724 "conffile.y" /* yacc.c:1646 */ { (*(struct _agcomp*)(&yyval)).ctype = SUM; } #line 2540 "conffile.tab.c" /* yacc.c:1646 */ break; case 86: #line 725 "conffile.y" /* yacc.c:1646 */ { (*(struct _agcomp*)(&yyval)).ctype = CNT; } #line 2546 "conffile.tab.c" /* yacc.c:1646 */ break; case 87: #line 726 "conffile.y" /* yacc.c:1646 */ { (*(struct _agcomp*)(&yyval)).ctype = MAX; } #line 2552 "conffile.tab.c" /* yacc.c:1646 */ break; case 88: #line 727 "conffile.y" /* yacc.c:1646 */ { (*(struct _agcomp*)(&yyval)).ctype = MIN; } #line 2558 "conffile.tab.c" /* yacc.c:1646 */ break; case 89: #line 728 "conffile.y" /* yacc.c:1646 */ { (*(struct _agcomp*)(&yyval)).ctype = AVG; } #line 2564 "conffile.tab.c" /* yacc.c:1646 */ break; case 90: #line 729 "conffile.y" /* yacc.c:1646 */ { (*(struct _agcomp*)(&yyval)).ctype = MEDN; } #line 2570 "conffile.tab.c" /* yacc.c:1646 */ break; case 91: #line 731 "conffile.y" /* yacc.c:1646 */ { if ((*(int*)(&yyvsp[0])) < 1 || (*(int*)(&yyvsp[0])) > 99) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, "percentile: value x must be between 1 and 99"); YYERROR; } (*(struct _agcomp*)(&yyval)).ctype = PCTL; (*(struct _agcomp*)(&yyval)).pctl = (unsigned char)(*(int*)(&yyvsp[0])); } #line 2584 "conffile.tab.c" /* yacc.c:1646 */ break; case 92: #line 740 "conffile.y" /* yacc.c:1646 */ { (*(struct _agcomp*)(&yyval)).ctype = VAR; } #line 2590 "conffile.tab.c" /* yacc.c:1646 */ break; case 93: #line 741 "conffile.y" /* yacc.c:1646 */ { (*(struct _agcomp*)(&yyval)).ctype = SDEV; } #line 2596 "conffile.tab.c" /* yacc.c:1646 */ break; case 94: #line 744 "conffile.y" /* yacc.c:1646 */ { (*(destinations **)(&yyval)) = NULL; } #line 2602 "conffile.tab.c" /* yacc.c:1646 */ break; case 95: #line 745 "conffile.y" /* yacc.c:1646 */ { (*(destinations **)(&yyval)) = (*(destinations **)(&yyvsp[0])); } #line 2608 "conffile.tab.c" /* yacc.c:1646 */ break; case 96: #line 751 "conffile.y" /* yacc.c:1646 */ { char *err = router_set_statistics(rtr, (*(destinations **)(&yyvsp[-1]))); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } logerr("warning: 'send statistics to ...' is deprecated and will be " "removed in a future version, use 'statistics send to ...' " "instead\n"); } #line 2623 "conffile.tab.c" /* yacc.c:1646 */ break; case 97: #line 771 "conffile.y" /* yacc.c:1646 */ { char *err; err = router_set_collectorvals(rtr, (*(int*)(&yyvsp[-4])), (*(char **)(&yyvsp[-2])), (*(col_mode*)(&yyvsp[-3]))); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } if ((*(destinations **)(&yyvsp[-1])) != NULL) { err = router_set_statistics(rtr, (*(destinations **)(&yyvsp[-1]))); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } } } #line 2645 "conffile.tab.c" /* yacc.c:1646 */ break; case 98: #line 790 "conffile.y" /* yacc.c:1646 */ { (*(int*)(&yyval)) = -1; } #line 2651 "conffile.tab.c" /* yacc.c:1646 */ break; case 99: #line 792 "conffile.y" /* yacc.c:1646 */ { if ((*(int*)(&yyvsp[-1])) <= 0) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, "interval must be > 0"); YYERROR; } (*(int*)(&yyval)) = (*(int*)(&yyvsp[-1])); } #line 2664 "conffile.tab.c" /* yacc.c:1646 */ break; case 100: #line 802 "conffile.y" /* yacc.c:1646 */ { (*(col_mode*)(&yyval)) = CUM; } #line 2670 "conffile.tab.c" /* yacc.c:1646 */ break; case 101: #line 803 "conffile.y" /* yacc.c:1646 */ { (*(col_mode*)(&yyval)) = SUB; } #line 2676 "conffile.tab.c" /* yacc.c:1646 */ break; case 102: #line 806 "conffile.y" /* yacc.c:1646 */ { (*(char **)(&yyval)) = NULL; } #line 2682 "conffile.tab.c" /* yacc.c:1646 */ break; case 103: #line 807 "conffile.y" /* yacc.c:1646 */ { (*(char **)(&yyval)) = (*(char **)(&yyvsp[0])); } #line 2688 "conffile.tab.c" /* yacc.c:1646 */ break; case 104: #line 813 "conffile.y" /* yacc.c:1646 */ { struct _rcptr *walk; char *err; for (walk = (*(struct _lsnr **)(&yyvsp[0]))->rcptr; walk != NULL; walk = walk->next) { err = router_add_listener(rtr, (*(struct _lsnr **)(&yyvsp[0]))->type, (*(struct _lsnr **)(&yyvsp[0]))->transport->mode, (*(struct _lsnr **)(&yyvsp[0]))->transport->pemcert, walk->ctype, walk->ip, walk->port, walk->saddr); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } } } #line 2708 "conffile.tab.c" /* yacc.c:1646 */ break; case 105: #line 831 "conffile.y" /* yacc.c:1646 */ { if (((*(struct _lsnr **)(&yyval)) = ra_malloc(palloc, sizeof(struct _lsnr))) == NULL) { logerr("malloc failed\n"); YYABORT; } (*(struct _lsnr **)(&yyval))->type = T_LINEMODE; (*(struct _lsnr **)(&yyval))->transport = (*(struct _rcptr_trsp **)(&yyvsp[-1])); (*(struct _lsnr **)(&yyval))->rcptr = (*(struct _rcptr **)(&yyvsp[0])); if ((*(struct _rcptr_trsp **)(&yyvsp[-1]))->mode != W_PLAIN) { struct _rcptr *walk; for (walk = (*(struct _rcptr **)(&yyvsp[0])); walk != NULL; walk = walk->next) { if (walk->ctype == CON_UDP) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, "cannot use UDP transport for " "compressed/encrypted stream"); YYERROR; } } } } #line 2734 "conffile.tab.c" /* yacc.c:1646 */ break; case 106: #line 854 "conffile.y" /* yacc.c:1646 */ { if (((*(struct _rcptr_trsp **)(&yyval)) = ra_malloc(palloc, sizeof(struct _rcptr_trsp))) == NULL) { logerr("malloc failed\n"); YYABORT; } (*(struct _rcptr_trsp **)(&yyval))->mode = W_PLAIN; } #line 2748 "conffile.tab.c" /* yacc.c:1646 */ break; case 107: #line 863 "conffile.y" /* yacc.c:1646 */ { #ifdef HAVE_GZIP if (((*(struct _rcptr_trsp **)(&yyval)) = ra_malloc(palloc, sizeof(struct _rcptr_trsp))) == NULL) { logerr("malloc failed\n"); YYABORT; } (*(struct _rcptr_trsp **)(&yyval))->mode = W_GZIP; #else router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, "feature gzip not compiled in"); YYERROR; #endif } #line 2769 "conffile.tab.c" /* yacc.c:1646 */ break; case 108: #line 879 "conffile.y" /* yacc.c:1646 */ { #ifdef HAVE_LZ4 if (((*(struct _rcptr_trsp **)(&yyval)) = ra_malloc(palloc, sizeof(struct _rcptr_trsp))) == NULL) { logerr("malloc failed\n"); YYABORT; } (*(struct _rcptr_trsp **)(&yyval))->mode = W_LZ4; #else router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, "feature lz4 not compiled in"); YYERROR; #endif } #line 2790 "conffile.tab.c" /* yacc.c:1646 */ break; case 109: #line 895 "conffile.y" /* yacc.c:1646 */ { #ifdef HAVE_SSL if (((*(struct _rcptr_trsp **)(&yyval)) = ra_malloc(palloc, sizeof(struct _rcptr_trsp))) == NULL) { logerr("malloc failed\n"); YYABORT; } (*(struct _rcptr_trsp **)(&yyval))->mode = W_SSL; (*(struct _rcptr_trsp **)(&yyval))->pemcert = ra_strdup(ralloc, (*(char **)(&yyvsp[0]))); #else router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, "feature ssl not compiled in"); YYERROR; #endif } #line 2812 "conffile.tab.c" /* yacc.c:1646 */ break; case 110: #line 914 "conffile.y" /* yacc.c:1646 */ { (*(struct _rcptr **)(&yyvsp[-1]))->next = (*(struct _rcptr **)(&yyvsp[0])); (*(struct _rcptr **)(&yyval)) = (*(struct _rcptr **)(&yyvsp[-1])); } #line 2818 "conffile.tab.c" /* yacc.c:1646 */ break; case 111: #line 917 "conffile.y" /* yacc.c:1646 */ { (*(struct _rcptr **)(&yyval)) = NULL; } #line 2824 "conffile.tab.c" /* yacc.c:1646 */ break; case 112: #line 918 "conffile.y" /* yacc.c:1646 */ { (*(struct _rcptr **)(&yyval)) = (*(struct _rcptr **)(&yyvsp[0])); } #line 2830 "conffile.tab.c" /* yacc.c:1646 */ break; case 113: #line 922 "conffile.y" /* yacc.c:1646 */ { char *err; void *hint = NULL; char *w; char bcip[24]; if (((*(struct _rcptr **)(&yyval)) = ra_malloc(palloc, sizeof(struct _rcptr))) == NULL) { logerr("malloc failed\n"); YYABORT; } (*(struct _rcptr **)(&yyval))->ctype = (*(con_proto*)(&yyvsp[0])); /* find out if this is just a port */ for (w = (*(char **)(&yyvsp[-2])); *w != '\0'; w++) if (*w < '0' || *w > '9') break; if (*w == '\0') { snprintf(bcip, sizeof(bcip), ":%s", (*(char **)(&yyvsp[-2]))); (*(char **)(&yyvsp[-2])) = bcip; } err = router_validate_address( rtr, &((*(struct _rcptr **)(&yyval))->ip), &((*(struct _rcptr **)(&yyval))->port), &((*(struct _rcptr **)(&yyval))->saddr), &hint, (*(char **)(&yyvsp[-2])), (*(con_proto*)(&yyvsp[0]))); /* help some static analysis tools to see bcip isn't going * out of scope */ (*(char **)(&yyvsp[-2])) = NULL; if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } free(hint); (*(struct _rcptr **)(&yyval))->next = NULL; } #line 2871 "conffile.tab.c" /* yacc.c:1646 */ break; case 114: #line 959 "conffile.y" /* yacc.c:1646 */ { char *err; if (((*(struct _rcptr **)(&yyval)) = ra_malloc(palloc, sizeof(struct _rcptr))) == NULL) { logerr("malloc failed\n"); YYABORT; } (*(struct _rcptr **)(&yyval))->ctype = CON_UNIX; (*(struct _rcptr **)(&yyval))->ip = (*(char **)(&yyvsp[-2])); (*(struct _rcptr **)(&yyval))->port = 0; (*(struct _rcptr **)(&yyval))->saddr = NULL; err = router_validate_path(rtr, (*(char **)(&yyvsp[-2]))); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } (*(struct _rcptr **)(&yyval))->next = NULL; } #line 2895 "conffile.tab.c" /* yacc.c:1646 */ break; case 115: #line 980 "conffile.y" /* yacc.c:1646 */ { (*(con_proto*)(&yyval)) = CON_TCP; } #line 2901 "conffile.tab.c" /* yacc.c:1646 */ break; case 116: #line 981 "conffile.y" /* yacc.c:1646 */ { (*(con_proto*)(&yyval)) = CON_UDP; } #line 2907 "conffile.tab.c" /* yacc.c:1646 */ break; case 117: #line 987 "conffile.y" /* yacc.c:1646 */ { if (router_readconfig(rtr, (*(char **)(&yyvsp[0])), 0, 0, 0, 0, 0, 0, 0) == NULL) YYERROR; } #line 2916 "conffile.tab.c" /* yacc.c:1646 */ break; #line 2920 "conffile.tab.c" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires that yytoken be updated with the new translation. We take the approach of translating immediately before every use of yytoken. One alternative is translating here after every semantic action, but that translation would be missed if the semantic action invokes YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an incorrect destructor might then be invoked immediately. In the case of YYERROR or YYBACKUP, subsequent parser actions might lead to an incorrect destructor call or verbose syntax error message before the lookahead is translated. */ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; *++yylsp = yyloc; /* Now 'shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTOKENS]; goto yynewstate; /*--------------------------------------. | yyerrlab -- here on detecting error. | `--------------------------------------*/ yyerrlab: /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if ! YYERROR_VERBOSE yyerror (&yylloc, yyscanner, rtr, ralloc, palloc, YY_("syntax error")); #else # define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ yyssp, yytoken) { char const *yymsgp = YY_("syntax error"); int yysyntax_error_status; yysyntax_error_status = YYSYNTAX_ERROR; if (yysyntax_error_status == 0) yymsgp = yymsg; else if (yysyntax_error_status == 1) { if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); if (!yymsg) { yymsg = yymsgbuf; yymsg_alloc = sizeof yymsgbuf; yysyntax_error_status = 2; } else { yysyntax_error_status = YYSYNTAX_ERROR; yymsgp = yymsg; } } yyerror (&yylloc, yyscanner, rtr, ralloc, palloc, yymsgp); if (yysyntax_error_status == 2) goto yyexhaustedlab; } # undef YYSYNTAX_ERROR #endif } yyerror_range[1] = yylloc; if (yyerrstatus == 3) { /* If just tried and failed to reuse lookahead token after an error, discard it. */ if (yychar <= YYEOF) { /* Return failure if at end of input. */ if (yychar == YYEOF) YYABORT; } else { yydestruct ("Error: discarding", yytoken, &yylval, &yylloc, yyscanner, rtr, ralloc, palloc); yychar = YYEMPTY; } } /* Else will try to reuse lookahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: /* Pacify compilers like GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (/*CONSTCOND*/ 0) goto yyerrorlab; yyerror_range[1] = yylsp[1-yylen]; /* Do not reclaim the symbols of the rule whose action triggered this YYERROR. */ YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); yystate = *yyssp; goto yyerrlab1; /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; if (!yypact_value_is_default (yyn)) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) { yyn = yytable[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) YYABORT; yyerror_range[1] = *yylsp; yydestruct ("Error: popping", yystos[yystate], yyvsp, yylsp, yyscanner, rtr, ralloc, palloc); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; YY_IGNORE_MAYBE_UNINITIALIZED_END yyerror_range[2] = yylloc; /* Using YYLLOC is tempting, but would change the location of the lookahead. YYLOC is available though. */ YYLLOC_DEFAULT (yyloc, yyerror_range, 2); *++yylsp = yyloc; /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturn; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturn; #if !defined yyoverflow || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: yyerror (&yylloc, yyscanner, rtr, ralloc, palloc, YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: if (yychar != YYEMPTY) { /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ yytoken = YYTRANSLATE (yychar); yydestruct ("Cleanup: discarding lookahead", yytoken, &yylval, &yylloc, yyscanner, rtr, ralloc, palloc); } /* Do not reclaim the symbols of the rule whose action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", yystos[*yyssp], yyvsp, yylsp, yyscanner, rtr, ralloc, palloc); YYPOPSTACK (1); } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif #if YYERROR_VERBOSE if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); #endif return yyresult; } carbon-c-relay-3.2/conffile.tab.h000066400000000000000000000171051317265605500166750ustar00rootroot00000000000000/* A Bison parser, made by GNU Bison 3.0.4. */ /* Bison interface for Yacc-like parsers in C Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ #ifndef YY_ROUTER_YY_CONFFILE_TAB_H_INCLUDED # define YY_ROUTER_YY_CONFFILE_TAB_H_INCLUDED /* Debug traces. */ #ifndef ROUTER_YYDEBUG # if defined YYDEBUG #if YYDEBUG # define ROUTER_YYDEBUG 1 # else # define ROUTER_YYDEBUG 0 # endif # else /* ! defined YYDEBUG */ # define ROUTER_YYDEBUG 0 # endif /* ! defined YYDEBUG */ #endif /* ! defined ROUTER_YYDEBUG */ #if ROUTER_YYDEBUG extern int router_yydebug; #endif /* "%code requires" blocks. */ #line 11 "conffile.y" /* yacc.c:1909 */ struct _clust { enum clusttype t; int ival; }; struct _clhost { char *ip; int port; char *inst; int proto; con_trnsp trnsp; void *saddr; void *hint; struct _clhost *next; }; struct _maexpr { route *r; char drop; struct _maexpr *next; }; struct _agcomp { enum _aggr_compute_type ctype; unsigned char pctl; char *metric; struct _agcomp *next; }; struct _lsnr { con_type type; struct _rcptr_trsp *transport; struct _rcptr *rcptr; }; struct _rcptr { con_proto ctype; char *ip; int port; void *saddr; struct _rcptr *next; }; struct _rcptr_trsp { con_trnsp mode; char *pemcert; }; #line 96 "conffile.tab.h" /* yacc.c:1909 */ /* Token type. */ #ifndef ROUTER_YYTOKENTYPE # define ROUTER_YYTOKENTYPE enum router_yytokentype { crCLUSTER = 258, crFORWARD = 259, crANY_OF = 260, crFAILOVER = 261, crCARBON_CH = 262, crFNV1A_CH = 263, crJUMP_FNV1A_CH = 264, crFILE = 265, crIP = 266, crREPLICATION = 267, crPROTO = 268, crUSEALL = 269, crUDP = 270, crTCP = 271, crMATCH = 272, crVALIDATE = 273, crELSE = 274, crLOG = 275, crDROP = 276, crROUTE = 277, crUSING = 278, crSEND = 279, crTO = 280, crBLACKHOLE = 281, crSTOP = 282, crREWRITE = 283, crINTO = 284, crAGGREGATE = 285, crEVERY = 286, crSECONDS = 287, crEXPIRE = 288, crAFTER = 289, crTIMESTAMP = 290, crAT = 291, crSTART = 292, crMIDDLE = 293, crEND = 294, crOF = 295, crBUCKET = 296, crCOMPUTE = 297, crSUM = 298, crCOUNT = 299, crMAX = 300, crMIN = 301, crAVERAGE = 302, crMEDIAN = 303, crVARIANCE = 304, crSTDDEV = 305, crPERCENTILE = 306, crWRITE = 307, crSTATISTICS = 308, crSUBMIT = 309, crRESET = 310, crCOUNTERS = 311, crINTERVAL = 312, crPREFIX = 313, crWITH = 314, crLISTEN = 315, crTYPE = 316, crLINEMODE = 317, crTRANSPORT = 318, crGZIP = 319, crLZ4 = 320, crSSL = 321, crUNIX = 322, crINCLUDE = 323, crCOMMENT = 324, crSTRING = 325, crUNEXPECTED = 326, crINTVAL = 327 }; #endif /* Value type. */ #if ! defined ROUTER_YYSTYPE && ! defined ROUTER_YYSTYPE_IS_DECLARED union ROUTER_YYSTYPE { /* crCOMMENT */ char * crCOMMENT; /* crSTRING */ char * crSTRING; /* crUNEXPECTED */ char * crUNEXPECTED; /* cluster_opt_instance */ char * cluster_opt_instance; /* match_opt_route */ char * match_opt_route; /* statistics_opt_prefix */ char * statistics_opt_prefix; /* cluster */ cluster * cluster; /* statistics_opt_counters */ col_mode statistics_opt_counters; /* cluster_opt_proto */ con_proto cluster_opt_proto; /* rcptr_proto */ con_proto rcptr_proto; /* cluster_opt_transport */ con_trnsp cluster_opt_transport; /* match_opt_send_to */ destinations * match_opt_send_to; /* match_send_to */ destinations * match_send_to; /* match_dsts */ destinations * match_dsts; /* match_dsts2 */ destinations * match_dsts2; /* match_opt_dst */ destinations * match_opt_dst; /* match_dst */ destinations * match_dst; /* aggregate_opt_send_to */ destinations * aggregate_opt_send_to; /* aggregate_opt_timestamp */ enum _aggr_timestamp aggregate_opt_timestamp; /* aggregate_ts_when */ enum _aggr_timestamp aggregate_ts_when; /* cluster_useall */ enum clusttype cluster_useall; /* cluster_ch */ enum clusttype cluster_ch; /* crPERCENTILE */ int crPERCENTILE; /* crINTVAL */ int crINTVAL; /* cluster_opt_useall */ int cluster_opt_useall; /* cluster_opt_repl */ int cluster_opt_repl; /* match_log_or_drop */ int match_log_or_drop; /* match_opt_stop */ int match_opt_stop; /* statistics_opt_interval */ int statistics_opt_interval; /* aggregate_comp_type */ struct _agcomp aggregate_comp_type; /* aggregate_computes */ struct _agcomp * aggregate_computes; /* aggregate_opt_compute */ struct _agcomp * aggregate_opt_compute; /* aggregate_compute */ struct _agcomp * aggregate_compute; /* cluster_paths */ struct _clhost * cluster_paths; /* cluster_opt_path */ struct _clhost * cluster_opt_path; /* cluster_path */ struct _clhost * cluster_path; /* cluster_hosts */ struct _clhost * cluster_hosts; /* cluster_opt_host */ struct _clhost * cluster_opt_host; /* cluster_host */ struct _clhost * cluster_host; /* cluster_type */ struct _clust cluster_type; /* cluster_file */ struct _clust cluster_file; /* listener */ struct _lsnr * listener; /* match_exprs */ struct _maexpr * match_exprs; /* match_exprs2 */ struct _maexpr * match_exprs2; /* match_opt_expr */ struct _maexpr * match_opt_expr; /* match_expr */ struct _maexpr * match_expr; /* match_opt_validate */ struct _maexpr * match_opt_validate; /* receptors */ struct _rcptr * receptors; /* opt_receptor */ struct _rcptr * opt_receptor; /* receptor */ struct _rcptr * receptor; /* transport_mode */ struct _rcptr_trsp * transport_mode; #line 284 "conffile.tab.h" /* yacc.c:1909 */ }; typedef union ROUTER_YYSTYPE ROUTER_YYSTYPE; # define ROUTER_YYSTYPE_IS_TRIVIAL 1 # define ROUTER_YYSTYPE_IS_DECLARED 1 #endif /* Location type. */ #if ! defined ROUTER_YYLTYPE && ! defined ROUTER_YYLTYPE_IS_DECLARED typedef struct ROUTER_YYLTYPE ROUTER_YYLTYPE; struct ROUTER_YYLTYPE { int first_line; int first_column; int last_line; int last_column; }; # define ROUTER_YYLTYPE_IS_DECLARED 1 # define ROUTER_YYLTYPE_IS_TRIVIAL 1 #endif int router_yyparse (void *yyscanner, router *rtr, allocator *ralloc, allocator *palloc); #endif /* !YY_ROUTER_YY_CONFFILE_TAB_H_INCLUDED */ carbon-c-relay-3.2/conffile.y000066400000000000000000000571631317265605500161610ustar00rootroot00000000000000%{ #include "allocator.h" #include "conffile.h" #include "conffile.tab.h" #include "aggregator.h" #include "receptor.h" #include "config.h" int router_yylex(ROUTER_YYSTYPE *, ROUTER_YYLTYPE *, void *, router *, allocator *, allocator *); %} %code requires { struct _clust { enum clusttype t; int ival; }; struct _clhost { char *ip; int port; char *inst; int proto; con_trnsp trnsp; void *saddr; void *hint; struct _clhost *next; }; struct _maexpr { route *r; char drop; struct _maexpr *next; }; struct _agcomp { enum _aggr_compute_type ctype; unsigned char pctl; char *metric; struct _agcomp *next; }; struct _lsnr { con_type type; struct _rcptr_trsp *transport; struct _rcptr *rcptr; }; struct _rcptr { con_proto ctype; char *ip; int port; void *saddr; struct _rcptr *next; }; struct _rcptr_trsp { con_trnsp mode; char *pemcert; }; } %define api.prefix {router_yy} %define api.pure full %locations %define parse.error verbose %define api.value.type union %param {void *yyscanner} {router *rtr} {allocator *ralloc} {allocator *palloc} %token crCLUSTER %token crFORWARD crANY_OF crFAILOVER crCARBON_CH crFNV1A_CH crJUMP_FNV1A_CH crFILE crIP crREPLICATION crPROTO crUSEALL crUDP crTCP %type cluster_useall cluster_ch %type cluster_type cluster_file %type cluster_opt_repl cluster_opt_useall %type cluster_opt_proto %type cluster_opt_instance %type cluster %type cluster_host cluster_hosts cluster_opt_host cluster_path cluster_paths cluster_opt_path %type cluster_opt_transport %token crMATCH %token crVALIDATE crELSE crLOG crDROP crROUTE crUSING %token crSEND crTO crBLACKHOLE crSTOP %type match_dst match_opt_dst match_dsts match_dsts2 match_opt_send_to match_send_to aggregate_opt_send_to %type match_opt_stop match_log_or_drop %type match_opt_route %type match_opt_validate match_expr match_opt_expr match_exprs match_exprs2 %token crREWRITE %token crINTO %token crAGGREGATE %token crEVERY crSECONDS crEXPIRE crAFTER crTIMESTAMP crAT %token crSTART crMIDDLE crEND crOF crBUCKET %token crCOMPUTE crSUM crCOUNT crMAX crMIN crAVERAGE crMEDIAN %token crVARIANCE crSTDDEV %token crPERCENTILE %token crWRITE %type aggregate_ts_when aggregate_opt_timestamp %type aggregate_comp_type %type aggregate_compute aggregate_computes aggregate_opt_compute %token crSTATISTICS %token crSUBMIT crRESET crCOUNTERS crINTERVAL crPREFIX crWITH %type statistics_opt_interval %type statistics_opt_counters %type statistics_opt_prefix %token crLISTEN %token crTYPE crLINEMODE crTRANSPORT crGZIP crLZ4 crSSL crUNIX %type rcptr_proto %type receptor opt_receptor receptors %type transport_mode %type listener %token crINCLUDE %token crCOMMENT crSTRING crUNEXPECTED %token crINTVAL %% stmts: opt_stmt ; opt_stmt: | stmt opt_stmt ; stmt: command ';' ; command: cluster | match | rewrite | aggregate | send | statistics | listen | include ; /*** {{{ BEGIN cluster ***/ cluster: crCLUSTER crSTRING[name] cluster_type[type] cluster_hosts[servers] { struct _clhost *w; char *err; int srvcnt; /* count number of servers for ch_new */ for (srvcnt = 0, w = $servers; w != NULL; w = w->next, srvcnt++) ; if (($$ = ra_malloc(ralloc, sizeof(cluster))) == NULL) { logerr("malloc failed for cluster '%s'\n", $name); YYABORT; } $$->name = ra_strdup(ralloc, $name); $$->next = NULL; $$->type = $type.t; switch ($$->type) { case CARBON_CH: case FNV1A_CH: case JUMP_CH: $$->members.ch = ra_malloc(ralloc, sizeof(chashring)); if ($$->members.ch == NULL) { logerr("malloc failed for ch in cluster '%s'\n", $name); YYABORT; } if ($type.ival < 1 || $type.ival > 255) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, "replication count must be between 1 and 255"); YYERROR; } $$->members.ch->repl_factor = (unsigned char)$type.ival; $$->members.ch->ring = ch_new(ralloc, $$->type == CARBON_CH ? CARBON : $$->type == FNV1A_CH ? FNV1a : JUMP_FNV1a, srvcnt); $$->members.ch->servers = NULL; $type.ival = 0; /* hack, avoid triggering use_all */ break; case FORWARD: $$->members.forward = NULL; break; case ANYOF: case FAILOVER: $$->members.anyof = NULL; break; default: logerr("unknown cluster type %zd!\n", $$->type); YYABORT; } for (w = $servers; w != NULL; w = w->next) { err = router_add_server(rtr, w->ip, w->port, w->inst, T_LINEMODE, w->trnsp, w->proto, w->saddr, w->hint, $type.ival, $$); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } } err = router_add_cluster(rtr, $$); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } } | crCLUSTER crSTRING[name] cluster_file[type] cluster_paths[paths] { struct _clhost *w; char *err; if (($$ = ra_malloc(ralloc, sizeof(cluster))) == NULL) { logerr("malloc failed for cluster '%s'\n", $name); YYABORT; } $$->name = ra_strdup(ralloc, $name); $$->next = NULL; $$->type = $type.t; switch ($$->type) { case FILELOG: case FILELOGIP: $$->members.forward = NULL; break; default: logerr("unknown cluster type %zd!\n", $$->type); YYABORT; } for (w = $paths; w != NULL; w = w->next) { err = router_add_server(rtr, w->ip, w->port, w->inst, T_LINEMODE, W_PLAIN, w->proto, w->saddr, w->hint, $type.ival, $$); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } } err = router_add_cluster(rtr, $$); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } } ; cluster_type: cluster_useall[type] cluster_opt_useall[use] { $$.t = $type; $$.ival = $use; } | cluster_ch[type] cluster_opt_repl[repl] { $$.t = $type; $$.ival = $repl; } ; cluster_useall: crFORWARD { $$ = FORWARD; } | crANY_OF { $$ = ANYOF; } | crFAILOVER { $$ = FAILOVER; } ; cluster_opt_useall: { $$ = 0; } | crUSEALL { $$ = 1; } ; cluster_ch: crCARBON_CH { $$ = CARBON_CH; } | crFNV1A_CH { $$ = FNV1A_CH; } | crJUMP_FNV1A_CH { $$ = JUMP_CH; } ; cluster_opt_repl: { $$ = 1; } | crREPLICATION crINTVAL[cnt] { $$ = $cnt; } ; cluster_file: crFILE crIP { $$.t = FILELOGIP; $$.ival = 0; } | crFILE { $$.t = FILELOG; $$.ival = 0; } ; cluster_paths: cluster_path[l] cluster_opt_path[r] { $l->next = $r; $$ = $l; } ; cluster_opt_path: { $$ = NULL; } | cluster_path { $$ = $1; } ; cluster_path: crSTRING[path] { struct _clhost *ret = ra_malloc(palloc, sizeof(struct _clhost)); char *err = router_validate_path(rtr, $path); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } ret->ip = $path; ret->port = GRAPHITE_PORT; ret->saddr = NULL; ret->hint = NULL; ret->inst = NULL; ret->proto = CON_FILE; ret->next = NULL; $$ = ret; } ; cluster_hosts: cluster_host[l] cluster_opt_host[r] { $l->next = $r; $$ = $l; } ; cluster_opt_host: { $$ = NULL; } | cluster_hosts { $$ = $1; } ; cluster_host: crSTRING[ip] cluster_opt_instance[inst] cluster_opt_proto[prot] cluster_opt_type[type] cluster_opt_transport[trnsp] { struct _clhost *ret = ra_malloc(palloc, sizeof(struct _clhost)); char *err = router_validate_address( rtr, &(ret->ip), &(ret->port), &(ret->saddr), &(ret->hint), $ip, $prot); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } ret->inst = $inst; ret->proto = $prot; ret->trnsp = $trnsp; ret->next = NULL; $$ = ret; } ; cluster_opt_instance: { $$ = NULL; } | '=' crSTRING[inst] { $$ = $inst; } | '=' crINTVAL[inst] { $$ = ra_malloc(palloc, sizeof(char) * 12); if ($$ == NULL) { logerr("out of memory\n"); YYABORT; } snprintf($$, 12, "%d", $inst); } ; cluster_opt_proto: { $$ = CON_TCP; } | crPROTO crUDP { $$ = CON_UDP; } | crPROTO crTCP { $$ = CON_TCP; } ; cluster_opt_type: | crTYPE crLINEMODE ; cluster_opt_transport: { $$ = W_PLAIN; } | crTRANSPORT crGZIP { #ifdef HAVE_GZIP $$ = W_GZIP; #else router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, "feature gzip not compiled in"); YYERROR; #endif } | crTRANSPORT crLZ4 { #ifdef HAVE_LZ4 $$ = W_LZ4; #else router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, "feature lz4 not compiled in"); YYERROR; #endif } | crTRANSPORT crSSL { #ifdef HAVE_SSL $$ = W_SSL; #else router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, "feature ssl not compiled in"); YYERROR; #endif } ; /*** }}} END cluster ***/ /*** {{{ BEGIN match ***/ match: crMATCH match_exprs[exprs] match_opt_validate[val] match_opt_route[masq] match_opt_send_to[dsts] match_opt_stop[stop] { /* each expr comes with an allocated route, populate it */ struct _maexpr *we; destinations *d = NULL; char *err; if ($val != NULL) { /* optional validate clause */ if ((d = ra_malloc(ralloc, sizeof(destinations))) == NULL) { logerr("out of memory\n"); YYABORT; } d->next = NULL; if ((d->cl = ra_malloc(ralloc, sizeof(cluster))) == NULL) { logerr("out of memory\n"); YYABORT; } d->cl->name = NULL; d->cl->type = VALIDATION; d->cl->next = NULL; d->cl->members.validation = ra_malloc(ralloc, sizeof(validate)); if (d->cl->members.validation == NULL) { logerr("out of memory\n"); YYABORT; } d->cl->members.validation->rule = $val->r; d->cl->members.validation->action = $val->drop ? VAL_DROP : VAL_LOG; } /* add destinations to the chain */ if (d != NULL) { d->next = $dsts; } else { d = $dsts; } /* replace with copy on the router allocator */ if ($masq != NULL) $masq = ra_strdup(ralloc, $masq); for (we = $exprs; we != NULL; we = we->next) { we->r->next = NULL; we->r->dests = d; we->r->masq = $masq; we->r->stop = $dsts == NULL ? 0 : $dsts->cl->type == BLACKHOLE ? 1 : $stop; err = router_add_route(rtr, we->r); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } } } ; match_exprs: '*' { if (($$ = ra_malloc(palloc, sizeof(struct _maexpr))) == NULL) { logerr("out of memory\n"); YYABORT; } $$->r = NULL; if (router_validate_expression(rtr, &($$->r), "*") != NULL) YYABORT; $$->drop = 0; $$->next = NULL; } | match_exprs2 { $$ = $1; } ; match_exprs2: match_expr[l] match_opt_expr[r] { $l->next = $r; $$ = $l; } match_opt_expr: { $$ = NULL; } | match_exprs2 { $$ = $1; } ; match_expr: crSTRING[expr] { char *err; if (($$ = ra_malloc(palloc, sizeof(struct _maexpr))) == NULL) { logerr("out of memory\n"); YYABORT; } $$->r = NULL; err = router_validate_expression(rtr, &($$->r), $expr); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } $$->drop = 0; $$->next = NULL; } ; match_opt_validate: { $$ = NULL; } | crVALIDATE crSTRING[expr] crELSE match_log_or_drop[drop] { char *err; if (($$ = ra_malloc(palloc, sizeof(struct _maexpr))) == NULL) { logerr("out of memory\n"); YYABORT; } $$->r = NULL; err = router_validate_expression(rtr, &($$->r), $expr); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } $$->drop = $drop; $$->next = NULL; } ; match_log_or_drop: crLOG { $$ = 0; } | crDROP { $$ = 1; } ; match_opt_route: { $$ = NULL; } | crROUTE crUSING crSTRING[expr] { $$ = $expr; } ; match_opt_send_to: { $$ = NULL; } | match_send_to { $$ = $1; } ; match_send_to: crSEND crTO match_dsts[dsts] { $$ = $dsts; } ; match_dsts: crBLACKHOLE { if (($$ = ra_malloc(ralloc, sizeof(destinations))) == NULL) { logerr("out of memory\n"); YYABORT; } if (router_validate_cluster(rtr, &($$->cl), "blackhole") != NULL) YYABORT; $$->next = NULL; } | match_dsts2 { $$ = $1; } ; match_dsts2: match_dst[l] match_opt_dst[r] { $l->next = $r; $$ = $l; } match_opt_dst: { $$ = NULL; } | match_dsts2 { $$ = $1; } ; match_dst: crSTRING[cluster] { char *err; if (($$ = ra_malloc(ralloc, sizeof(destinations))) == NULL) { logerr("out of memory\n"); YYABORT; } err = router_validate_cluster(rtr, &($$->cl), $1); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } $$->next = NULL; } ; match_opt_stop: { $$ = 0; } | crSTOP { $$ = 1; } ; /*** }}} END match ***/ /*** {{{ BEGIN rewrite ***/ rewrite: crREWRITE crSTRING[expr] crINTO crSTRING[replacement] { char *err; route *r = NULL; cluster *cl; err = router_validate_expression(rtr, &r, $expr); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } cl = ra_malloc(ralloc, sizeof(cluster)); if (cl == NULL) { logerr("out of memory\n"); YYABORT; } cl->type = REWRITE; cl->name = NULL; cl->members.replacement = ra_strdup(ralloc, $replacement); cl->next = NULL; if (cl->members.replacement == NULL) { logerr("out of memory\n"); YYABORT; } r->dests = ra_malloc(ralloc, sizeof(destinations)); if (r->dests == NULL) { logerr("out of memory\n"); YYABORT; } r->dests->cl = cl; r->dests->next = NULL; r->stop = 0; r->next = NULL; err = router_add_route(rtr, r); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } } ; /*** }}} END rewrite ***/ /*** {{{ BEGIN aggregate ***/ aggregate: crAGGREGATE match_exprs2[exprs] crEVERY crINTVAL[intv] crSECONDS crEXPIRE crAFTER crINTVAL[expire] crSECONDS aggregate_opt_timestamp[tswhen] aggregate_computes[computes] aggregate_opt_send_to[dsts] match_opt_stop[stop] { cluster *w; aggregator *a; destinations *d; struct _agcomp *acw; struct _maexpr *we; char *err; if ($intv <= 0) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, "interval must be > 0"); YYERROR; } if ($expire <= 0) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, "expire must be > 0"); YYERROR; } if ($expire < $intv) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, "expire must be greater than interval"); YYERROR; } w = ra_malloc(ralloc, sizeof(cluster)); if (w == NULL) { logerr("malloc failed for aggregate\n"); YYABORT; } w->name = NULL; w->type = AGGREGATION; w->next = NULL; a = aggregator_new($intv, $expire, $tswhen); if (a == NULL) { logerr("out of memory\n"); YYABORT; } if ((err = router_add_aggregator(rtr, a)) != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } w->members.aggregation = a; for (acw = $computes; acw != NULL; acw = acw->next) { if (aggregator_add_compute(a, acw->metric, acw->ctype, acw->pctl) != 0) { logerr("out of memory\n"); YYABORT; } } err = router_add_cluster(rtr, w); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } d = ra_malloc(ralloc, sizeof(destinations)); if (d == NULL) { logerr("out of memory\n"); YYABORT; } d->cl = w; d->next = $dsts; for (we = $exprs; we != NULL; we = we->next) { we->r->next = NULL; we->r->dests = d; we->r->stop = $stop; err = router_add_route(rtr, we->r); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } } if ($dsts != NULL) router_add_stubroute(rtr, AGGRSTUB, w, $dsts); } ; aggregate_opt_timestamp: { $$ = TS_END; } | crTIMESTAMP crAT aggregate_ts_when[tswhen] crOF crBUCKET { $$ = $tswhen; } ; aggregate_ts_when: crSTART { $$ = TS_START; } | crMIDDLE { $$ = TS_MIDDLE; } | crEND { $$ = TS_END; } ; aggregate_computes: aggregate_compute[l] aggregate_opt_compute[r] { $l->next = $r; $$ = $l; } ; aggregate_opt_compute: { $$ = NULL; } | aggregate_computes { $$ = $1; } aggregate_compute: crCOMPUTE aggregate_comp_type[type] crWRITE crTO crSTRING[metric] { $$ = ra_malloc(palloc, sizeof(struct _agcomp)); if ($$ == NULL) { logerr("malloc failed\n"); YYABORT; } $$->ctype = $type.ctype; $$->pctl = $type.pctl; $$->metric = $metric; $$->next = NULL; } ; aggregate_comp_type: crSUM { $$.ctype = SUM; } | crCOUNT { $$.ctype = CNT; } | crMAX { $$.ctype = MAX; } | crMIN { $$.ctype = MIN; } | crAVERAGE { $$.ctype = AVG; } | crMEDIAN { $$.ctype = MEDN; } | crPERCENTILE { if ($1 < 1 || $1 > 99) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, "percentile: value x must be between 1 and 99"); YYERROR; } $$.ctype = PCTL; $$.pctl = (unsigned char)$1; } | crVARIANCE { $$.ctype = VAR; } | crSTDDEV { $$.ctype = SDEV; } ; aggregate_opt_send_to: { $$ = NULL; } | match_send_to { $$ = $1; } ; /*** }}} END aggregate ***/ /*** {{{ BEGIN send ***/ send: crSEND crSTATISTICS crTO match_dsts[dsts] match_opt_stop[stop] { char *err = router_set_statistics(rtr, $dsts); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } logerr("warning: 'send statistics to ...' is deprecated and will be " "removed in a future version, use 'statistics send to ...' " "instead\n"); } ; /*** }}} END send ***/ /*** {{{ BEGIN statistics ***/ statistics: crSTATISTICS statistics_opt_interval[interval] statistics_opt_counters[counters] statistics_opt_prefix[prefix] aggregate_opt_send_to[dsts] match_opt_stop[stop] { char *err; err = router_set_collectorvals(rtr, $interval, $prefix, $counters); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } if ($dsts != NULL) { err = router_set_statistics(rtr, $dsts); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } } } ; statistics_opt_interval: { $$ = -1; } | crSUBMIT crEVERY crINTVAL[intv] crSECONDS { if ($intv <= 0) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, "interval must be > 0"); YYERROR; } $$ = $intv; } ; statistics_opt_counters: { $$ = CUM; } | crRESET crCOUNTERS crAFTER crINTERVAL { $$ = SUB; } ; statistics_opt_prefix: { $$ = NULL; } | crPREFIX crWITH crSTRING[prefix] { $$ = $prefix; } ; /*** }}} END statistics ***/ /*** {{{ BEGIN listen ***/ listen: crLISTEN listener[lsnr] { struct _rcptr *walk; char *err; for (walk = $lsnr->rcptr; walk != NULL; walk = walk->next) { err = router_add_listener(rtr, $lsnr->type, $lsnr->transport->mode, $lsnr->transport->pemcert, walk->ctype, walk->ip, walk->port, walk->saddr); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } } } ; listener: crTYPE crLINEMODE transport_mode[mode] receptors[ifaces] { if (($$ = ra_malloc(palloc, sizeof(struct _lsnr))) == NULL) { logerr("malloc failed\n"); YYABORT; } $$->type = T_LINEMODE; $$->transport = $mode; $$->rcptr = $ifaces; if ($mode->mode != W_PLAIN) { struct _rcptr *walk; for (walk = $ifaces; walk != NULL; walk = walk->next) { if (walk->ctype == CON_UDP) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, "cannot use UDP transport for " "compressed/encrypted stream"); YYERROR; } } } } ; transport_mode: { if (($$ = ra_malloc(palloc, sizeof(struct _rcptr_trsp))) == NULL) { logerr("malloc failed\n"); YYABORT; } $$->mode = W_PLAIN; } | crTRANSPORT crGZIP { #ifdef HAVE_GZIP if (($$ = ra_malloc(palloc, sizeof(struct _rcptr_trsp))) == NULL) { logerr("malloc failed\n"); YYABORT; } $$->mode = W_GZIP; #else router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, "feature gzip not compiled in"); YYERROR; #endif } | crTRANSPORT crLZ4 { #ifdef HAVE_LZ4 if (($$ = ra_malloc(palloc, sizeof(struct _rcptr_trsp))) == NULL) { logerr("malloc failed\n"); YYABORT; } $$->mode = W_LZ4; #else router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, "feature lz4 not compiled in"); YYERROR; #endif } | crTRANSPORT crSSL crSTRING[pemcert] { #ifdef HAVE_SSL if (($$ = ra_malloc(palloc, sizeof(struct _rcptr_trsp))) == NULL) { logerr("malloc failed\n"); YYABORT; } $$->mode = W_SSL; $$->pemcert = ra_strdup(ralloc, $pemcert); #else router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, "feature ssl not compiled in"); YYERROR; #endif } ; receptors: receptor[l] opt_receptor[r] { $l->next = $r; $$ = $l; } ; opt_receptor: { $$ = NULL; } | receptors { $$ = $1; } ; receptor: crSTRING[ip] crPROTO rcptr_proto[prot] { char *err; void *hint = NULL; char *w; char bcip[24]; if (($$ = ra_malloc(palloc, sizeof(struct _rcptr))) == NULL) { logerr("malloc failed\n"); YYABORT; } $$->ctype = $prot; /* find out if this is just a port */ for (w = $ip; *w != '\0'; w++) if (*w < '0' || *w > '9') break; if (*w == '\0') { snprintf(bcip, sizeof(bcip), ":%s", $ip); $ip = bcip; } err = router_validate_address( rtr, &($$->ip), &($$->port), &($$->saddr), &hint, $ip, $prot); /* help some static analysis tools to see bcip isn't going * out of scope */ $ip = NULL; if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } free(hint); $$->next = NULL; } | crSTRING[path] crPROTO crUNIX { char *err; if (($$ = ra_malloc(palloc, sizeof(struct _rcptr))) == NULL) { logerr("malloc failed\n"); YYABORT; } $$->ctype = CON_UNIX; $$->ip = $path; $$->port = 0; $$->saddr = NULL; err = router_validate_path(rtr, $path); if (err != NULL) { router_yyerror(&yylloc, yyscanner, rtr, ralloc, palloc, err); YYERROR; } $$->next = NULL; } ; rcptr_proto: crTCP { $$ = CON_TCP; } | crUDP { $$ = CON_UDP; } ; /*** }}} END listen ***/ /*** {{{ BEGIN include ***/ include: crINCLUDE crSTRING[path] { if (router_readconfig(rtr, $path, 0, 0, 0, 0, 0, 0, 0) == NULL) YYERROR; } ; /*** }}} END include ***/ /* vim: set ts=4 sw=4 foldmethod=marker: */ carbon-c-relay-3.2/conffile.yy.c000066400000000000000000002637271317265605500166000ustar00rootroot00000000000000#line 1 "conffile.yy.c" #line 3 "conffile.yy.c" #define YY_INT_ALIGNED short int /* A lexical scanner generated by flex */ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 6 #define YY_FLEX_SUBMINOR_VERSION 4 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif #ifdef yy_create_buffer #define router_yy_create_buffer_ALREADY_DEFINED #else #define yy_create_buffer router_yy_create_buffer #endif #ifdef yy_delete_buffer #define router_yy_delete_buffer_ALREADY_DEFINED #else #define yy_delete_buffer router_yy_delete_buffer #endif #ifdef yy_scan_buffer #define router_yy_scan_buffer_ALREADY_DEFINED #else #define yy_scan_buffer router_yy_scan_buffer #endif #ifdef yy_scan_string #define router_yy_scan_string_ALREADY_DEFINED #else #define yy_scan_string router_yy_scan_string #endif #ifdef yy_scan_bytes #define router_yy_scan_bytes_ALREADY_DEFINED #else #define yy_scan_bytes router_yy_scan_bytes #endif #ifdef yy_init_buffer #define router_yy_init_buffer_ALREADY_DEFINED #else #define yy_init_buffer router_yy_init_buffer #endif #ifdef yy_flush_buffer #define router_yy_flush_buffer_ALREADY_DEFINED #else #define yy_flush_buffer router_yy_flush_buffer #endif #ifdef yy_load_buffer_state #define router_yy_load_buffer_state_ALREADY_DEFINED #else #define yy_load_buffer_state router_yy_load_buffer_state #endif #ifdef yy_switch_to_buffer #define router_yy_switch_to_buffer_ALREADY_DEFINED #else #define yy_switch_to_buffer router_yy_switch_to_buffer #endif #ifdef yypush_buffer_state #define router_yypush_buffer_state_ALREADY_DEFINED #else #define yypush_buffer_state router_yypush_buffer_state #endif #ifdef yypop_buffer_state #define router_yypop_buffer_state_ALREADY_DEFINED #else #define yypop_buffer_state router_yypop_buffer_state #endif #ifdef yyensure_buffer_stack #define router_yyensure_buffer_stack_ALREADY_DEFINED #else #define yyensure_buffer_stack router_yyensure_buffer_stack #endif #ifdef yylex #define router_yylex_ALREADY_DEFINED #else #define yylex router_yylex #endif #ifdef yyrestart #define router_yyrestart_ALREADY_DEFINED #else #define yyrestart router_yyrestart #endif #ifdef yylex_init #define router_yylex_init_ALREADY_DEFINED #else #define yylex_init router_yylex_init #endif #ifdef yylex_init_extra #define router_yylex_init_extra_ALREADY_DEFINED #else #define yylex_init_extra router_yylex_init_extra #endif #ifdef yylex_destroy #define router_yylex_destroy_ALREADY_DEFINED #else #define yylex_destroy router_yylex_destroy #endif #ifdef yyget_debug #define router_yyget_debug_ALREADY_DEFINED #else #define yyget_debug router_yyget_debug #endif #ifdef yyset_debug #define router_yyset_debug_ALREADY_DEFINED #else #define yyset_debug router_yyset_debug #endif #ifdef yyget_extra #define router_yyget_extra_ALREADY_DEFINED #else #define yyget_extra router_yyget_extra #endif #ifdef yyset_extra #define router_yyset_extra_ALREADY_DEFINED #else #define yyset_extra router_yyset_extra #endif #ifdef yyget_in #define router_yyget_in_ALREADY_DEFINED #else #define yyget_in router_yyget_in #endif #ifdef yyset_in #define router_yyset_in_ALREADY_DEFINED #else #define yyset_in router_yyset_in #endif #ifdef yyget_out #define router_yyget_out_ALREADY_DEFINED #else #define yyget_out router_yyget_out #endif #ifdef yyset_out #define router_yyset_out_ALREADY_DEFINED #else #define yyset_out router_yyset_out #endif #ifdef yyget_leng #define router_yyget_leng_ALREADY_DEFINED #else #define yyget_leng router_yyget_leng #endif #ifdef yyget_text #define router_yyget_text_ALREADY_DEFINED #else #define yyget_text router_yyget_text #endif #ifdef yyget_lineno #define router_yyget_lineno_ALREADY_DEFINED #else #define yyget_lineno router_yyget_lineno #endif #ifdef yyset_lineno #define router_yyset_lineno_ALREADY_DEFINED #else #define yyset_lineno router_yyset_lineno #endif #ifdef yyget_column #define router_yyget_column_ALREADY_DEFINED #else #define yyget_column router_yyget_column #endif #ifdef yyset_column #define router_yyset_column_ALREADY_DEFINED #else #define yyset_column router_yyset_column #endif #ifdef yywrap #define router_yywrap_ALREADY_DEFINED #else #define yywrap router_yywrap #endif #ifdef yyget_lval #define router_yyget_lval_ALREADY_DEFINED #else #define yyget_lval router_yyget_lval #endif #ifdef yyset_lval #define router_yyset_lval_ALREADY_DEFINED #else #define yyset_lval router_yyset_lval #endif #ifdef yyalloc #define router_yyalloc_ALREADY_DEFINED #else #define yyalloc router_yyalloc #endif #ifdef yyrealloc #define router_yyrealloc_ALREADY_DEFINED #else #define yyrealloc router_yyrealloc #endif #ifdef yyfree #define router_yyfree_ALREADY_DEFINED #else #define yyfree router_yyfree #endif /* First, we deal with platform-specific or compiler-specific issues. */ /* begin standard C headers. */ #include #include #include #include /* end standard C headers. */ /* flex integer type definitions */ #ifndef FLEXINT_H #define FLEXINT_H /* C99 systems have . Non-C99 systems may or may not. */ #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; /* Limits of integral types. */ #ifndef INT8_MIN #define INT8_MIN (-128) #endif #ifndef INT16_MIN #define INT16_MIN (-32767-1) #endif #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif #ifndef INT8_MAX #define INT8_MAX (127) #endif #ifndef INT16_MAX #define INT16_MAX (32767) #endif #ifndef INT32_MAX #define INT32_MAX (2147483647) #endif #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #ifndef SIZE_MAX #define SIZE_MAX (~(size_t)0) #endif #endif /* ! C99 */ #endif /* ! FLEXINT_H */ /* begin standard C++ headers. */ /* TODO: this is always defined, so inline it */ #define yyconst const #if defined(__GNUC__) && __GNUC__ >= 3 #define yynoreturn __attribute__((__noreturn__)) #else #define yynoreturn #endif /* Returned upon end-of-file. */ #define YY_NULL 0 /* Promotes a possibly negative, possibly signed char to an * integer in range [0..255] for use as an array index. */ #define YY_SC_TO_UI(c) ((YY_CHAR) (c)) /* An opaque pointer. */ #ifndef YY_TYPEDEF_YY_SCANNER_T #define YY_TYPEDEF_YY_SCANNER_T typedef void* yyscan_t; #endif /* For convenience, these vars (plus the bison vars far below) are macros in the reentrant scanner. */ #define yyin yyg->yyin_r #define yyout yyg->yyout_r #define yyextra yyg->yyextra_r #define yyleng yyg->yyleng_r #define yytext yyg->yytext_r #define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) #define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) #define yy_flex_debug yyg->yy_flex_debug_r /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN yyg->yy_start = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START ((yyg->yy_start - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE yyrestart( yyin , yyscanner ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #ifndef YY_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k. * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. * Ditto for the __ia64__ case accordingly. */ #define YY_BUF_SIZE 32768 #else #define YY_BUF_SIZE 16384 #endif /* __ia64__ */ #endif /* The state buf must be large enough to hold one state per character in the main buffer. */ #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif #ifndef YY_TYPEDEF_YY_SIZE_T #define YY_TYPEDEF_YY_SIZE_T typedef size_t yy_size_t; #endif #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires * access to the local variable yy_act. Since yyless() is a macro, it would break * existing scanners that call yyless() from OUTSIDE yylex. * One obvious solution it to make yy_act a global. I tried that, and saw * a 5% performance hit in a non-yylineno scanner, because yy_act is * normally declared as a register variable-- so it is not worth it. */ #define YY_LESS_LINENO(n) \ do { \ int yyl;\ for ( yyl = n; yyl < yyleng; ++yyl )\ if ( yytext[yyl] == '\n' )\ --yylineno;\ }while(0) #define YY_LINENO_REWIND_TO(dst) \ do {\ const char *p;\ for ( p = yy_cp-1; p >= (dst); --p)\ if ( *p == '\n' )\ --yylineno;\ }while(0) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ *yy_cp = yyg->yy_hold_char; \ YY_RESTORE_YY_MORE_OFFSET \ yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ int yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; #endif /* !YY_STRUCT_YY_BUFFER_STATE */ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". * * Returns the top of the stack, or NULL. */ #define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ : NULL) /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] void yyrestart ( FILE *input_file , yyscan_t yyscanner ); void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner ); void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); void yypop_buffer_state ( yyscan_t yyscanner ); static void yyensure_buffer_stack ( yyscan_t yyscanner ); static void yy_load_buffer_state ( yyscan_t yyscanner ); static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file , yyscan_t yyscanner ); #define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER , yyscanner) YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner ); YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner ); YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner ); void *yyalloc ( yy_size_t , yyscan_t yyscanner ); void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner ); void yyfree ( void * , yyscan_t yyscanner ); #define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ yyensure_buffer_stack (yyscanner); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ yyensure_buffer_stack (yyscanner); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) /* Begin user sect3 */ #define router_yywrap(yyscanner) (/*CONSTCOND*/1) #define YY_SKIP_YYWRAP typedef flex_uint8_t YY_CHAR; typedef int yy_state_type; #define yytext_ptr yytext_r static yy_state_type yy_get_previous_state ( yyscan_t yyscanner ); static yy_state_type yy_try_NUL_trans ( yy_state_type current_state , yyscan_t yyscanner); static int yy_get_next_buffer ( yyscan_t yyscanner ); static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner ); /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ yyg->yytext_ptr = yy_bp; \ yyleng = (int) (yy_cp - yy_bp); \ yyg->yy_hold_char = *yy_cp; \ *yy_cp = '\0'; \ yyg->yy_c_buf_p = yy_cp; #define YY_NUM_RULES 103 #define YY_END_OF_BUFFER 104 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info { flex_int32_t yy_verify; flex_int32_t yy_nxt; }; static const flex_int16_t yy_accept[529] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 102, 97, 98, 102, 101, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 99, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 95, 95, 93, 92, 95, 95, 102, 91, 100, 99, 21, 100, 100, 100, 100, 100, 100, 100, 100, 100, 23, 100, 100, 100, 100, 100, 100, 100, 100, 100, 97, 98, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 99, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 95, 95, 94, 100, 100, 99, 100, 100, 11, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 58, 0, 52, 0, 0, 45, 0, 54, 0, 0, 56, 0, 0, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 0, 87, 0, 0, 100, 100, 100, 19, 100, 100, 20, 100, 14, 100, 100, 13, 100, 100, 100, 100, 100, 100, 84, 100, 85, 100, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 10, 0, 0, 0, 27, 25, 0, 30, 33, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 0, 77, 0, 0, 80, 89, 100, 100, 18, 100, 100, 100, 33, 100, 15, 100, 100, 30, 100, 100, 83, 100, 100, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 28, 29, 40, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 0, 63, 0, 74, 0, 70, 0, 0, 72, 0, 0, 0, 86, 100, 100, 100, 12, 100, 100, 100, 28, 100, 37, 86, 100, 0, 0, 0, 79, 0, 0, 3, 0, 0, 0, 0, 0, 0, 47, 0, 39, 0, 59, 44, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 76, 0, 69, 0, 100, 100, 100, 100, 5, 100, 100, 0, 1, 90, 34, 0, 0, 0, 0, 2, 0, 57, 48, 53, 55, 0, 38, 49, 0, 0, 0, 0, 0, 71, 0, 100, 100, 100, 100, 100, 100, 0, 0, 0, 4, 7, 0, 0, 0, 61, 0, 73, 75, 81, 100, 16, 100, 100, 24, 100, 36, 0, 6, 0, 0, 41, 0, 32, 100, 17, 82, 68, 0, 60, 67, 100, 0, 60, 9, 0, 8, 0 } ; static const YY_CHAR yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 5, 6, 7, 7, 7, 1, 7, 7, 8, 7, 7, 7, 7, 7, 9, 10, 9, 9, 11, 9, 9, 9, 9, 9, 7, 12, 7, 13, 7, 7, 1, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 14, 7, 7, 15, 1, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 7, 32, 33, 34, 35, 36, 37, 38, 39, 40, 7, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static const YY_CHAR yy_meta[41] = { 0, 1, 1, 2, 1, 3, 1, 4, 4, 4, 4, 4, 1, 1, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 } ; static const flex_int16_t yy_base[537] = { 0, 0, 32, 64, 0, 74, 0, 1, 21, 101, 0, 36, 63, 130, 0, 152, 0, 186, 199, 213, 0, 246, 0, 139, 149, 39, 41, 275, 0, 795, 796, 3, 791, 790, 796, 770, 764, 761, 765, 772, 767, 9, 757, 769, 136, 749, 751, 755, 751, 750, 21, 749, 745, 748, 0, 66, 741, 1, 24, 100, 754, 754, 63, 103, 757, 740, 737, 749, 739, 732, 738, 734, 745, 43, 740, 739, 730, 86, 84, 0, 11, 758, 796, 139, 0, 0, 796, 746, 185, 796, 101, 0, 162, 247, 91, 116, 251, 278, 253, 745, 144, 129, 7, 142, 166, 170, 244, 131, 261, 205, 755, 754, 796, 734, 720, 736, 720, 718, 714, 721, 733, 709, 715, 722, 718, 708, 711, 714, 711, 707, 717, 703, 708, 706, 796, 711, 700, 279, 699, 796, 240, 714, 697, 23, 711, 698, 690, 708, 245, 796, 694, 179, 250, 697, 696, 796, 691, 698, 705, 686, 684, 698, 683, 696, 682, 276, 697, 679, 683, 681, 679, 678, 677, 683, 0, 296, 298, 796, 692, 300, 309, 299, 302, 691, 307, 311, 310, 313, 314, 315, 316, 317, 318, 320, 323, 321, 324, 325, 328, 336, 343, 332, 341, 345, 672, 670, 675, 667, 682, 667, 679, 663, 681, 678, 667, 673, 682, 654, 659, 658, 668, 796, 653, 667, 654, 655, 653, 662, 649, 796, 654, 796, 648, 649, 796, 653, 652, 651, 655, 649, 654, 641, 651, 637, 649, 639, 646, 641, 630, 629, 642, 632, 628, 639, 637, 637, 626, 636, 626, 630, 632, 617, 796, 630, 796, 611, 0, 277, 344, 349, 634, 350, 351, 633, 352, 632, 353, 356, 631, 357, 358, 72, 363, 365, 360, 630, 366, 629, 367, 622, 607, 605, 619, 615, 613, 796, 612, 605, 604, 603, 796, 616, 615, 615, 796, 796, 609, 796, 796, 606, 796, 595, 610, 605, 589, 589, 590, 593, 604, 592, 590, 597, 587, 796, 581, 594, 597, 579, 595, 590, 585, 576, 573, 567, 573, 580, 569, 573, 796, 577, 796, 572, 569, 796, 796, 584, 372, 583, 371, 374, 379, 582, 375, 581, 380, 381, 580, 391, 376, 579, 388, 392, 570, 571, 571, 560, 796, 554, 554, 565, 556, 548, 568, 550, 560, 796, 796, 796, 558, 545, 544, 796, 557, 541, 546, 554, 538, 543, 552, 796, 534, 537, 534, 538, 796, 533, 796, 545, 796, 528, 525, 796, 543, 527, 530, 796, 405, 397, 398, 545, 399, 400, 402, 544, 407, 543, 542, 408, 539, 522, 533, 796, 532, 517, 796, 535, 529, 530, 528, 517, 525, 796, 524, 796, 515, 796, 796, 514, 507, 507, 796, 500, 522, 519, 502, 503, 518, 796, 500, 796, 513, 410, 413, 419, 412, 517, 416, 422, 496, 796, 796, 796, 505, 510, 495, 503, 796, 489, 796, 796, 796, 796, 500, 796, 796, 495, 502, 497, 487, 492, 796, 498, 420, 423, 424, 427, 431, 430, 497, 498, 492, 796, 796, 504, 486, 481, 796, 493, 796, 796, 796, 434, 496, 432, 435, 495, 439, 796, 475, 796, 491, 479, 796, 458, 476, 441, 456, 447, 796, 445, 454, 796, 443, 281, 457, 198, 91, 796, 796, 473, 478, 483, 488, 492, 497, 499, 501 } ; static const flex_int16_t yy_def[537] = { 0, 529, 529, 529, 3, 3, 5, 3, 3, 3, 9, 3, 3, 3, 13, 3, 15, 530, 530, 528, 19, 19, 21, 21, 21, 21, 21, 21, 27, 528, 528, 528, 528, 531, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 532, 532, 528, 528, 533, 532, 534, 528, 535, 535, 528, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 528, 528, 531, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 532, 532, 533, 528, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 536, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 536, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 536, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 535, 535, 535, 535, 535, 535, 535, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 535, 535, 535, 535, 535, 535, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 535, 535, 535, 535, 535, 535, 528, 528, 528, 528, 528, 528, 528, 535, 535, 535, 535, 528, 528, 528, 528, 535, 528, 528, 535, 528, 528, 0, 528, 528, 528, 528, 528, 528, 528, 528 } ; static const flex_int16_t yy_nxt[837] = { 0, 528, 31, 32, 31, 109, 33, 109, 528, 137, 137, 137, 34, 175, 179, 175, 35, 30, 36, 30, 528, 179, 30, 197, 37, 53, 30, 38, 39, 119, 142, 143, 40, 41, 31, 32, 31, 30, 33, 30, 182, 132, 30, 120, 34, 53, 30, 87, 35, 87, 36, 232, 30, 144, 30, 133, 37, 30, 233, 38, 39, 30, 145, 165, 40, 41, 31, 32, 31, 66, 33, 87, 87, 87, 87, 87, 34, 87, 166, 30, 42, 30, 43, 151, 30, 44, 179, 138, 30, 45, 30, 356, 30, 46, 47, 30, 66, 152, 153, 30, 139, 48, 140, 172, 170, 179, 49, 50, 51, 52, 54, 54, 54, 173, 527, 179, 146, 55, 56, 57, 147, 58, 30, 186, 148, 171, 30, 154, 181, 59, 179, 60, 61, 155, 62, 63, 187, 64, 65, 54, 54, 54, 112, 179, 111, 179, 67, 87, 68, 196, 69, 30, 123, 111, 70, 30, 179, 87, 179, 103, 124, 71, 72, 73, 202, 125, 126, 74, 30, 103, 30, 87, 87, 30, 195, 87, 179, 30, 198, 75, 179, 87, 87, 76, 179, 87, 77, 78, 80, 81, 80, 82, 83, 183, 180, 180, 180, 241, 84, 179, 85, 80, 81, 80, 82, 83, 199, 109, 242, 109, 200, 84, 179, 85, 30, 31, 32, 31, 86, 33, 87, 87, 88, 88, 88, 34, 89, 87, 87, 87, 90, 87, 87, 87, 87, 91, 87, 92, 87, 87, 93, 87, 87, 87, 94, 95, 96, 97, 98, 87, 87, 87, 87, 87, 99, 87, 87, 87, 179, 30, 228, 179, 229, 87, 238, 179, 243, 179, 87, 244, 87, 184, 193, 87, 239, 179, 201, 87, 100, 101, 87, 87, 102, 87, 188, 189, 194, 185, 137, 137, 137, 179, 179, 203, 256, 346, 190, 104, 175, 526, 175, 112, 105, 111, 266, 257, 106, 87, 107, 108, 191, 87, 111, 179, 179, 267, 179, 192, 180, 180, 180, 179, 270, 179, 179, 179, 268, 179, 179, 179, 179, 179, 179, 276, 179, 179, 269, 179, 179, 179, 271, 273, 179, 279, 272, 274, 179, 275, 283, 277, 179, 278, 282, 281, 285, 179, 280, 179, 179, 179, 284, 288, 286, 179, 179, 179, 179, 179, 287, 348, 179, 179, 179, 354, 179, 347, 353, 179, 350, 179, 179, 179, 352, 351, 349, 179, 179, 357, 179, 179, 179, 359, 355, 179, 179, 179, 361, 358, 407, 408, 360, 413, 179, 410, 409, 179, 179, 412, 411, 266, 414, 179, 179, 179, 179, 415, 179, 453, 416, 406, 451, 179, 179, 456, 179, 417, 179, 179, 452, 455, 179, 454, 483, 179, 179, 484, 179, 179, 179, 457, 482, 179, 485, 502, 179, 179, 179, 501, 179, 179, 486, 505, 487, 179, 514, 179, 515, 179, 503, 504, 523, 179, 506, 524, 524, 524, 524, 524, 524, 516, 179, 522, 525, 517, 30, 30, 30, 30, 30, 79, 79, 79, 79, 79, 111, 111, 111, 111, 111, 174, 179, 521, 174, 176, 176, 176, 176, 176, 177, 520, 177, 177, 177, 178, 178, 345, 345, 519, 518, 179, 179, 513, 512, 511, 510, 509, 508, 507, 500, 499, 498, 497, 496, 495, 494, 493, 492, 491, 490, 489, 488, 179, 481, 480, 479, 478, 477, 476, 475, 474, 473, 472, 471, 470, 469, 468, 467, 466, 465, 464, 463, 462, 461, 460, 459, 458, 179, 179, 179, 179, 450, 449, 448, 447, 446, 445, 444, 443, 442, 441, 440, 439, 438, 437, 436, 435, 434, 433, 432, 431, 430, 429, 428, 427, 426, 425, 424, 423, 422, 421, 420, 419, 418, 179, 179, 179, 179, 179, 406, 405, 404, 403, 402, 401, 400, 399, 398, 397, 396, 395, 394, 393, 392, 391, 390, 389, 388, 387, 386, 385, 384, 383, 382, 381, 380, 379, 378, 377, 376, 375, 374, 373, 372, 371, 370, 369, 368, 367, 366, 365, 364, 363, 362, 179, 179, 179, 179, 179, 179, 344, 343, 342, 341, 340, 339, 338, 337, 336, 335, 334, 333, 332, 331, 330, 329, 328, 327, 326, 325, 324, 323, 322, 321, 320, 319, 318, 317, 316, 315, 314, 313, 312, 311, 310, 309, 308, 307, 306, 305, 304, 303, 302, 301, 300, 299, 298, 297, 296, 295, 294, 293, 292, 291, 290, 289, 179, 179, 265, 264, 263, 262, 261, 260, 259, 258, 255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 240, 237, 236, 235, 234, 231, 230, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 112, 110, 179, 179, 110, 169, 168, 167, 164, 163, 162, 161, 160, 159, 158, 157, 156, 150, 149, 141, 136, 135, 134, 131, 130, 129, 128, 127, 122, 121, 118, 117, 116, 115, 114, 113, 112, 110, 528, 29, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528 } ; static const flex_int16_t yy_chk[837] = { 0, 0, 1, 1, 1, 31, 1, 31, 0, 54, 54, 54, 1, 80, 91, 80, 1, 7, 1, 7, 0, 102, 7, 102, 1, 7, 7, 1, 1, 41, 57, 57, 1, 1, 2, 2, 2, 8, 2, 8, 91, 50, 8, 41, 2, 8, 8, 25, 2, 26, 2, 143, 11, 58, 11, 50, 2, 11, 143, 2, 2, 11, 58, 73, 2, 2, 3, 3, 3, 11, 3, 25, 25, 26, 26, 25, 3, 26, 73, 12, 3, 12, 3, 62, 12, 3, 281, 55, 12, 3, 5, 281, 5, 5, 5, 5, 12, 62, 62, 5, 55, 5, 55, 78, 77, 94, 5, 5, 5, 5, 9, 9, 9, 78, 526, 90, 59, 9, 9, 9, 59, 9, 9, 94, 59, 77, 9, 63, 90, 9, 95, 9, 9, 63, 9, 9, 95, 9, 9, 13, 13, 13, 83, 101, 83, 107, 13, 23, 13, 101, 13, 13, 44, 83, 13, 13, 103, 24, 100, 23, 44, 13, 13, 13, 107, 44, 44, 13, 15, 24, 15, 23, 23, 15, 100, 23, 92, 15, 103, 15, 104, 24, 24, 15, 105, 24, 15, 15, 17, 17, 17, 17, 17, 92, 88, 88, 88, 151, 17, 88, 17, 18, 18, 18, 18, 18, 104, 109, 151, 109, 105, 18, 525, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 21, 21, 21, 21, 106, 21, 140, 93, 140, 21, 148, 96, 152, 98, 21, 152, 21, 93, 98, 21, 148, 108, 106, 21, 21, 21, 21, 21, 21, 27, 96, 96, 98, 93, 137, 137, 137, 267, 97, 108, 165, 267, 97, 27, 175, 523, 175, 176, 27, 176, 179, 165, 27, 27, 27, 27, 97, 27, 176, 181, 179, 181, 182, 97, 180, 180, 180, 184, 185, 180, 186, 185, 182, 187, 188, 189, 190, 191, 192, 191, 193, 195, 184, 194, 196, 197, 186, 188, 198, 194, 187, 189, 201, 190, 198, 192, 199, 193, 197, 196, 200, 202, 195, 200, 268, 203, 199, 203, 201, 269, 271, 272, 274, 276, 202, 269, 277, 279, 280, 279, 284, 268, 277, 282, 272, 283, 286, 288, 276, 274, 271, 348, 346, 282, 349, 352, 358, 284, 280, 350, 354, 355, 288, 283, 346, 348, 286, 355, 360, 350, 349, 357, 361, 354, 352, 406, 357, 407, 408, 410, 411, 358, 412, 410, 360, 406, 407, 414, 417, 414, 451, 361, 454, 452, 408, 412, 456, 411, 452, 453, 482, 453, 457, 483, 484, 417, 451, 485, 454, 483, 487, 486, 503, 482, 501, 504, 456, 486, 457, 506, 501, 515, 503, 522, 484, 485, 519, 517, 487, 520, 520, 520, 524, 524, 524, 504, 516, 515, 522, 506, 529, 529, 529, 529, 529, 530, 530, 530, 530, 530, 531, 531, 531, 531, 531, 532, 514, 513, 532, 533, 533, 533, 533, 533, 534, 511, 534, 534, 534, 535, 535, 536, 536, 510, 508, 505, 502, 497, 495, 494, 493, 490, 489, 488, 481, 479, 478, 477, 476, 475, 472, 467, 465, 464, 463, 462, 458, 455, 450, 448, 446, 445, 444, 443, 442, 441, 439, 438, 437, 434, 432, 430, 429, 428, 427, 426, 425, 423, 422, 420, 419, 418, 416, 415, 413, 409, 404, 403, 402, 400, 399, 397, 395, 393, 392, 391, 390, 388, 387, 386, 385, 384, 383, 382, 380, 379, 378, 374, 373, 372, 371, 370, 369, 368, 367, 365, 364, 363, 362, 359, 356, 353, 351, 347, 345, 342, 341, 339, 337, 336, 335, 334, 333, 332, 331, 330, 329, 328, 327, 326, 325, 324, 322, 321, 320, 319, 318, 317, 316, 315, 314, 313, 312, 311, 309, 306, 303, 302, 301, 299, 298, 297, 296, 294, 293, 292, 291, 290, 289, 287, 285, 278, 275, 273, 270, 265, 263, 261, 260, 259, 258, 257, 256, 255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 233, 232, 230, 228, 227, 226, 225, 224, 223, 222, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 183, 178, 173, 172, 171, 170, 169, 168, 167, 166, 164, 163, 162, 161, 160, 159, 158, 157, 156, 154, 153, 150, 147, 146, 145, 144, 142, 141, 138, 136, 135, 133, 132, 131, 130, 129, 128, 127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 111, 110, 99, 87, 81, 76, 75, 74, 72, 71, 70, 69, 68, 67, 66, 65, 64, 61, 60, 56, 53, 52, 51, 49, 48, 47, 46, 45, 43, 42, 40, 39, 38, 37, 36, 35, 33, 32, 29, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528 } ; /* Table of booleans, true if rule could match eol. */ static const flex_int32_t yy_rule_can_match_eol[104] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, }; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET #line 1 "conffile.l" #line 2 "conffile.l" #include "allocator.h" #include "conffile.h" #include "conffile.tab.h" #define YYSTYPE ROUTER_YYSTYPE #define YY_DECL int router_yylex \ (YYSTYPE *yylval_param, ROUTER_YYLTYPE *llocp, yyscan_t yyscanner, router *rtr, allocator *ralloc, allocator *palloc) #define YY_USER_ACTION llocp->first_line = llocp->last_line = yylineno; \ llocp->first_column = yycolumn; llocp->last_column = yycolumn+yyleng-1; \ yycolumn += yyleng; #define YY_USER_INIT yycolumn = 0; yylineno = 0; int identstate = 0; #line 1044 "conffile.yy.c" #define YY_NO_INPUT 1 #line 1047 "conffile.yy.c" #define INITIAL 0 #define cl 1 #define ma 2 #define re 3 #define ag 4 #define se 5 #define st 6 #define li 7 #define qu 8 #define idcl 9 #define idma 10 #define idag 11 #define idin 12 #define idli 13 #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way * down here because we want the user's section 1 to have been scanned first. * The user has a chance to override it with an option. */ #include #endif #ifndef YY_EXTRA_TYPE #define YY_EXTRA_TYPE void * #endif /* Holds the entire state of the reentrant scanner. */ struct yyguts_t { /* User-defined. Not touched by flex. */ YY_EXTRA_TYPE yyextra_r; /* The rest are the same as the globals declared in the non-reentrant scanner. */ FILE *yyin_r, *yyout_r; size_t yy_buffer_stack_top; /**< index of top of stack. */ size_t yy_buffer_stack_max; /**< capacity of stack. */ YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ char yy_hold_char; int yy_n_chars; int yyleng_r; char *yy_c_buf_p; int yy_init; int yy_start; int yy_did_buffer_switch_on_eof; int yy_start_stack_ptr; int yy_start_stack_depth; int *yy_start_stack; yy_state_type yy_last_accepting_state; char* yy_last_accepting_cpos; int yylineno_r; int yy_flex_debug_r; char *yytext_r; int yy_more_flag; int yy_more_len; YYSTYPE * yylval_r; }; /* end struct yyguts_t */ static int yy_init_globals ( yyscan_t yyscanner ); /* This must go here because YYSTYPE and YYLTYPE are included * from bison output in section 1.*/ # define yylval yyg->yylval_r int yylex_init (yyscan_t* scanner); int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner); /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ int yylex_destroy ( yyscan_t yyscanner ); int yyget_debug ( yyscan_t yyscanner ); void yyset_debug ( int debug_flag , yyscan_t yyscanner ); YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner ); void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner ); FILE *yyget_in ( yyscan_t yyscanner ); void yyset_in ( FILE * _in_str , yyscan_t yyscanner ); FILE *yyget_out ( yyscan_t yyscanner ); void yyset_out ( FILE * _out_str , yyscan_t yyscanner ); int yyget_leng ( yyscan_t yyscanner ); char *yyget_text ( yyscan_t yyscanner ); int yyget_lineno ( yyscan_t yyscanner ); void yyset_lineno ( int _line_number , yyscan_t yyscanner ); int yyget_column ( yyscan_t yyscanner ); void yyset_column ( int _column_no , yyscan_t yyscanner ); YYSTYPE * yyget_lval ( yyscan_t yyscanner ); void yyset_lval ( YYSTYPE * yylval_param , yyscan_t yyscanner ); /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int yywrap ( yyscan_t yyscanner ); #else extern int yywrap ( yyscan_t yyscanner ); #endif #endif #ifndef YY_NO_UNPUT #endif #ifndef yytext_ptr static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen ( const char * , yyscan_t yyscanner); #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput ( yyscan_t yyscanner ); #else static int input ( yyscan_t yyscanner ); #endif #endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k */ #define YY_READ_BUF_SIZE 16384 #else #define YY_READ_BUF_SIZE 8192 #endif /* __ia64__ */ #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ int n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( yyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else \ { \ errno=0; \ while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \ { \ if( errno != EINTR) \ { \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ break; \ } \ errno=0; \ clearerr(yyin); \ } \ }\ \ #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner) #endif /* end tables serialization structures and prototypes */ /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL_IS_OURS 1 extern int yylex \ (YYSTYPE * yylval_param , yyscan_t yyscanner); #define YY_DECL int yylex \ (YYSTYPE * yylval_param , yyscan_t yyscanner) #endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK /*LINTED*/break; #endif #define YY_RULE_SETUP \ YY_USER_ACTION /** The main scanner function which does all the work. */ YY_DECL { yy_state_type yy_current_state; char *yy_cp, *yy_bp; int yy_act; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yylval = yylval_param; if ( !yyg->yy_init ) { yyg->yy_init = 1; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! yyg->yy_start ) yyg->yy_start = 1; /* first start state */ if ( ! yyin ) yyin = stdin; if ( ! yyout ) yyout = stdout; if ( ! YY_CURRENT_BUFFER ) { yyensure_buffer_stack (yyscanner); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); } yy_load_buffer_state( yyscanner ); } { #line 31 "conffile.l" #line 34 "conffile.l" char string_buf[1024]; char *strbuf = NULL; #line 1339 "conffile.yy.c" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { yy_cp = yyg->yy_c_buf_p; /* Support of yytext. */ *yy_cp = yyg->yy_hold_char; /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; yy_current_state = yyg->yy_start; yy_match: do { YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; yyg->yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 529 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; ++yy_cp; } while ( yy_base[yy_current_state] != 796 ); yy_find_action: yy_act = yy_accept[yy_current_state]; if ( yy_act == 0 ) { /* have to back up */ yy_cp = yyg->yy_last_accepting_cpos; yy_current_state = yyg->yy_last_accepting_state; yy_act = yy_accept[yy_current_state]; } YY_DO_BEFORE_ACTION; if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) { int yyl; for ( yyl = 0; yyl < yyleng; ++yyl ) if ( yytext[yyl] == '\n' ) do{ yylineno++; yycolumn=0; }while(0) ; } do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = yyg->yy_hold_char; yy_cp = yyg->yy_last_accepting_cpos; yy_current_state = yyg->yy_last_accepting_state; goto yy_find_action; case 1: YY_RULE_SETUP #line 37 "conffile.l" { identstate = cl; BEGIN(idcl); return crCLUSTER; } YY_BREAK case 2: YY_RULE_SETUP #line 42 "conffile.l" { identstate = idcl; BEGIN(idcl); return crFORWARD; } YY_BREAK case 3: YY_RULE_SETUP #line 47 "conffile.l" { identstate = idcl; BEGIN(idcl); return crANY_OF; } YY_BREAK case 4: YY_RULE_SETUP #line 52 "conffile.l" { identstate = idcl; BEGIN(idcl); return crFAILOVER; } YY_BREAK case 5: YY_RULE_SETUP #line 57 "conffile.l" return crUSEALL; YY_BREAK case 6: YY_RULE_SETUP #line 58 "conffile.l" { identstate = idcl; BEGIN(idcl); return crCARBON_CH; } YY_BREAK case 7: YY_RULE_SETUP #line 63 "conffile.l" { identstate = idcl; BEGIN(idcl); return crFNV1A_CH; } YY_BREAK case 8: YY_RULE_SETUP #line 68 "conffile.l" { identstate = idcl; BEGIN(idcl); return crJUMP_FNV1A_CH; } YY_BREAK case 9: YY_RULE_SETUP #line 73 "conffile.l" return crREPLICATION; YY_BREAK case 10: YY_RULE_SETUP #line 74 "conffile.l" { identstate = idcl; BEGIN(idcl); return crFILE; } YY_BREAK case 11: YY_RULE_SETUP #line 79 "conffile.l" return crIP; YY_BREAK case 12: YY_RULE_SETUP #line 80 "conffile.l" return crPROTO; YY_BREAK case 13: YY_RULE_SETUP #line 81 "conffile.l" return crUDP; YY_BREAK case 14: YY_RULE_SETUP #line 82 "conffile.l" return crTCP; YY_BREAK case 15: YY_RULE_SETUP #line 83 "conffile.l" return crTYPE; YY_BREAK case 16: YY_RULE_SETUP #line 84 "conffile.l" return crLINEMODE; YY_BREAK case 17: YY_RULE_SETUP #line 85 "conffile.l" return crTRANSPORT; YY_BREAK case 18: YY_RULE_SETUP #line 86 "conffile.l" return crGZIP; YY_BREAK case 19: YY_RULE_SETUP #line 87 "conffile.l" return crLZ4; YY_BREAK case 20: YY_RULE_SETUP #line 88 "conffile.l" return crSSL; YY_BREAK case 21: YY_RULE_SETUP #line 89 "conffile.l" return '='; YY_BREAK case 22: YY_RULE_SETUP #line 91 "conffile.l" { identstate = idma; BEGIN(idma); return crMATCH; } YY_BREAK case 23: YY_RULE_SETUP #line 96 "conffile.l" return '*'; YY_BREAK case 24: YY_RULE_SETUP #line 97 "conffile.l" { identstate = ma; BEGIN(idma); return crVALIDATE; } YY_BREAK case 25: YY_RULE_SETUP #line 102 "conffile.l" return crELSE; YY_BREAK case 26: YY_RULE_SETUP #line 103 "conffile.l" return crLOG; YY_BREAK case 27: YY_RULE_SETUP #line 104 "conffile.l" return crDROP; YY_BREAK case 28: YY_RULE_SETUP #line 105 "conffile.l" { BEGIN(ma); return crROUTE; } YY_BREAK case 29: YY_RULE_SETUP #line 109 "conffile.l" { identstate = ma; BEGIN(idma); return crUSING; } YY_BREAK case 30: YY_RULE_SETUP #line 114 "conffile.l" { BEGIN(ma); return crSEND; } YY_BREAK case 31: YY_RULE_SETUP #line 118 "conffile.l" { identstate = idcl; BEGIN(idcl); return crTO; } YY_BREAK case 32: YY_RULE_SETUP #line 123 "conffile.l" return crBLACKHOLE; YY_BREAK case 33: YY_RULE_SETUP #line 124 "conffile.l" return crSTOP; YY_BREAK case 34: YY_RULE_SETUP #line 126 "conffile.l" { identstate = re; BEGIN(idma); return crREWRITE; } YY_BREAK case 35: YY_RULE_SETUP #line 131 "conffile.l" { identstate = re; BEGIN(idma); return crINTO; } YY_BREAK case 36: YY_RULE_SETUP #line 137 "conffile.l" { identstate = idag; BEGIN(idag); return crAGGREGATE; } YY_BREAK case 37: YY_RULE_SETUP #line 142 "conffile.l" { BEGIN(ag); return crEVERY; } YY_BREAK case 38: YY_RULE_SETUP #line 146 "conffile.l" return crSECONDS; YY_BREAK case 39: YY_RULE_SETUP #line 147 "conffile.l" return crEXPIRE; YY_BREAK case 40: YY_RULE_SETUP #line 148 "conffile.l" return crAFTER; YY_BREAK case 41: YY_RULE_SETUP #line 149 "conffile.l" return crTIMESTAMP; YY_BREAK case 42: YY_RULE_SETUP #line 150 "conffile.l" return crAT; YY_BREAK case 43: YY_RULE_SETUP #line 151 "conffile.l" return crSTART; YY_BREAK case 44: YY_RULE_SETUP #line 152 "conffile.l" return crMIDDLE; YY_BREAK case 45: YY_RULE_SETUP #line 153 "conffile.l" return crEND; YY_BREAK case 46: YY_RULE_SETUP #line 154 "conffile.l" return crOF; YY_BREAK case 47: YY_RULE_SETUP #line 155 "conffile.l" return crBUCKET; YY_BREAK case 48: YY_RULE_SETUP #line 156 "conffile.l" return crCOMPUTE; YY_BREAK case 49: YY_RULE_SETUP #line 157 "conffile.l" return crSUM; YY_BREAK case 50: YY_RULE_SETUP #line 158 "conffile.l" return crSUM; YY_BREAK case 51: YY_RULE_SETUP #line 159 "conffile.l" return crCOUNT; YY_BREAK case 52: YY_RULE_SETUP #line 160 "conffile.l" return crCOUNT; YY_BREAK case 53: YY_RULE_SETUP #line 161 "conffile.l" return crMAX; YY_BREAK case 54: YY_RULE_SETUP #line 162 "conffile.l" return crMAX; YY_BREAK case 55: YY_RULE_SETUP #line 163 "conffile.l" return crMIN; YY_BREAK case 56: YY_RULE_SETUP #line 164 "conffile.l" return crMIN; YY_BREAK case 57: YY_RULE_SETUP #line 165 "conffile.l" return crAVERAGE; YY_BREAK case 58: YY_RULE_SETUP #line 166 "conffile.l" return crAVERAGE; YY_BREAK case 59: YY_RULE_SETUP #line 167 "conffile.l" return crMEDIAN; YY_BREAK case 60: YY_RULE_SETUP #line 168 "conffile.l" { yylval_param->crINTVAL = atoi(yytext + strlen("percentile")); return crPERCENTILE; } YY_BREAK case 61: YY_RULE_SETUP #line 173 "conffile.l" return crVARIANCE; YY_BREAK case 62: YY_RULE_SETUP #line 174 "conffile.l" return crSTDDEV; YY_BREAK case 63: YY_RULE_SETUP #line 175 "conffile.l" return crWRITE; YY_BREAK case 64: YY_RULE_SETUP #line 176 "conffile.l" { identstate = ag; BEGIN(idag); return crTO; } YY_BREAK case 65: YY_RULE_SETUP #line 181 "conffile.l" { /* reuse the match logic for send to ... stop */ BEGIN(ma); return crSEND; } YY_BREAK case 66: YY_RULE_SETUP #line 187 "conffile.l" { BEGIN(se); return crSEND; } YY_BREAK case 67: YY_RULE_SETUP #line 191 "conffile.l" { /* reuse the match logic for send to ... stop */ BEGIN(ma); return crSTATISTICS; } YY_BREAK case 68: YY_RULE_SETUP #line 197 "conffile.l" { BEGIN(st); return crSTATISTICS; } YY_BREAK case 69: YY_RULE_SETUP #line 201 "conffile.l" return crSUBMIT; YY_BREAK case 70: YY_RULE_SETUP #line 202 "conffile.l" return crEVERY; YY_BREAK case 71: YY_RULE_SETUP #line 203 "conffile.l" return crSECONDS; YY_BREAK case 72: YY_RULE_SETUP #line 204 "conffile.l" return crRESET; YY_BREAK case 73: YY_RULE_SETUP #line 205 "conffile.l" return crCOUNTERS; YY_BREAK case 74: YY_RULE_SETUP #line 206 "conffile.l" return crAFTER; YY_BREAK case 75: YY_RULE_SETUP #line 207 "conffile.l" return crINTERVAL; YY_BREAK case 76: YY_RULE_SETUP #line 208 "conffile.l" return crPREFIX; YY_BREAK case 77: YY_RULE_SETUP #line 209 "conffile.l" { identstate = st; BEGIN(idag); return crWITH; } YY_BREAK case 78: YY_RULE_SETUP #line 214 "conffile.l" { /* reuse the match logic for send to ... stop */ BEGIN(ma); return crSEND; } YY_BREAK case 79: YY_RULE_SETUP #line 220 "conffile.l" { BEGIN(li); return crLISTEN; } YY_BREAK case 80: YY_RULE_SETUP #line 224 "conffile.l" return crTYPE; YY_BREAK case 81: YY_RULE_SETUP #line 225 "conffile.l" { identstate = li; BEGIN(idli); return crLINEMODE; } YY_BREAK case 82: YY_RULE_SETUP #line 230 "conffile.l" return crTRANSPORT; YY_BREAK case 83: YY_RULE_SETUP #line 231 "conffile.l" { identstate = li; BEGIN(idli); return crGZIP; } YY_BREAK case 84: YY_RULE_SETUP #line 236 "conffile.l" { identstate = li; BEGIN(idli); return crLZ4; } YY_BREAK case 85: YY_RULE_SETUP #line 241 "conffile.l" { identstate = idli; BEGIN(idli); return crSSL; } YY_BREAK case 86: YY_RULE_SETUP #line 246 "conffile.l" { BEGIN(li); return crPROTO; } YY_BREAK case 87: YY_RULE_SETUP #line 250 "conffile.l" { identstate = li; BEGIN(idli); return crUDP; } YY_BREAK case 88: YY_RULE_SETUP #line 255 "conffile.l" { identstate = li; BEGIN(idli); return crTCP; } YY_BREAK case 89: YY_RULE_SETUP #line 260 "conffile.l" { identstate = li; BEGIN(idli); return crUNIX; } YY_BREAK case 90: YY_RULE_SETUP #line 266 "conffile.l" { identstate = INITIAL; BEGIN(idin); return crINCLUDE; } YY_BREAK /* handle quoted strings */ case 91: YY_RULE_SETUP #line 273 "conffile.l" { strbuf = string_buf; BEGIN(qu); } YY_BREAK case 92: YY_RULE_SETUP #line 278 "conffile.l" { if (strbuf == string_buf) { router_yyerror(llocp, NULL, rtr, ralloc, palloc, "empty string"); yyterminate(); } BEGIN(identstate); *strbuf = '\0'; yylval_param->crSTRING = ra_strdup(palloc, string_buf); return crSTRING; } YY_BREAK case 93: /* rule 93 can match eol */ YY_RULE_SETUP #line 289 "conffile.l" { router_yyerror(llocp, NULL, rtr, ralloc, palloc, "unterminated string"); yyterminate(); } YY_BREAK case YY_STATE_EOF(qu): #line 294 "conffile.l" { router_yyerror(llocp, NULL, rtr, ralloc, palloc, "unterminated string"); yyterminate(); } YY_BREAK case 94: YY_RULE_SETUP #line 299 "conffile.l" { *strbuf++ = yytext[1]; if (strbuf == string_buf + sizeof(string_buf)) { router_yyerror(llocp, NULL, rtr, ralloc, palloc, "string too large"); yyterminate(); } } YY_BREAK case 95: YY_RULE_SETUP #line 307 "conffile.l" { char *yptr = yytext; while (*yptr) { *strbuf++ = *yptr++; if (strbuf == string_buf + sizeof(string_buf)) { router_yyerror(llocp, NULL, rtr, ralloc, palloc, "string too large"); yyterminate(); } } } YY_BREAK case 96: /* rule 96 can match eol */ YY_RULE_SETUP #line 320 "conffile.l" { /* ignore for now yylval_param->crCOMMENT = ra_strdup(palloc, yytext); return crCOMMENT; */ yycolumn = 0; ; } YY_BREAK case 97: YY_RULE_SETUP #line 329 "conffile.l" ; /* whitespace */ YY_BREAK case 98: /* rule 98 can match eol */ YY_RULE_SETUP #line 330 "conffile.l" yycolumn = 0; YY_BREAK case 99: YY_RULE_SETUP #line 331 "conffile.l" { yylval_param->crINTVAL = atoi(yytext); return crINTVAL; } YY_BREAK case 100: YY_RULE_SETUP #line 335 "conffile.l" { yylval_param->crSTRING = ra_strdup(palloc, yytext); BEGIN(identstate); return crSTRING; } YY_BREAK case 101: YY_RULE_SETUP #line 340 "conffile.l" { BEGIN(INITIAL); return ';'; } YY_BREAK case 102: YY_RULE_SETUP #line 341 "conffile.l" { /* feed this back to the parser, it will give a * nice error message */ yylval_param->crSTRING = ra_strdup(palloc, yytext); return crUNEXPECTED; } YY_BREAK case 103: YY_RULE_SETUP #line 348 "conffile.l" ECHO; YY_BREAK #line 2127 "conffile.yy.c" case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(cl): case YY_STATE_EOF(ma): case YY_STATE_EOF(re): case YY_STATE_EOF(ag): case YY_STATE_EOF(se): case YY_STATE_EOF(st): case YY_STATE_EOF(li): case YY_STATE_EOF(idcl): case YY_STATE_EOF(idma): case YY_STATE_EOF(idag): case YY_STATE_EOF(idin): case YY_STATE_EOF(idli): yyterminate(); case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = yyg->yy_hold_char; YY_RESTORE_YY_MORE_OFFSET if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) { /* This was really a NUL. */ yy_state_type yy_next_state; yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( yyscanner ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner); yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++yyg->yy_c_buf_p; yy_current_state = yy_next_state; goto yy_match; } else { yy_cp = yyg->yy_c_buf_p; goto yy_find_action; } } else switch ( yy_get_next_buffer( yyscanner ) ) { case EOB_ACT_END_OF_FILE: { yyg->yy_did_buffer_switch_on_eof = 0; if ( yywrap( yyscanner ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * yytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! yyg->yy_did_buffer_switch_on_eof ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( yyscanner ); yy_cp = yyg->yy_c_buf_p; yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: yyg->yy_c_buf_p = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]; yy_current_state = yy_get_previous_state( yyscanner ); yy_cp = yyg->yy_c_buf_p; yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of user's declarations */ } /* end of yylex */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int yy_get_next_buffer (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; char *source = yyg->yytext_ptr; int number_to_move, i; int ret_val; if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr - 1); for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0; else { int num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; int yy_c_buf_p_offset = (int) (yyg->yy_c_buf_p - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { int new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ yyrealloc( (void *) b->yy_ch_buf, (yy_size_t) (b->yy_buf_size + 2) , yyscanner ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = NULL; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), yyg->yy_n_chars, num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; } if ( yyg->yy_n_chars == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; yyrestart( yyin , yyscanner); } else { ret_val = EOB_ACT_LAST_MATCH; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc( (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size , yyscanner ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); /* "- 2" to take care of EOB's */ YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2); } yyg->yy_n_chars += number_to_move; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ static yy_state_type yy_get_previous_state (yyscan_t yyscanner) { yy_state_type yy_current_state; char *yy_cp; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yy_current_state = yyg->yy_start; for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) { YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; yyg->yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 529 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner) { int yy_is_jam; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */ char *yy_cp = yyg->yy_c_buf_p; YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; yyg->yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 529 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; yy_is_jam = (yy_current_state == 528); (void)yyg; return yy_is_jam ? 0 : yy_current_state; } #ifndef YY_NO_UNPUT #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (yyscan_t yyscanner) #else static int input (yyscan_t yyscanner) #endif { int c; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; *yyg->yy_c_buf_p = yyg->yy_hold_char; if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) /* This was really a NUL. */ *yyg->yy_c_buf_p = '\0'; else { /* need more input */ int offset = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr); ++yyg->yy_c_buf_p; switch ( yy_get_next_buffer( yyscanner ) ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ yyrestart( yyin , yyscanner); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { if ( yywrap( yyscanner ) ) return 0; if ( ! yyg->yy_did_buffer_switch_on_eof ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(yyscanner); #else return input(yyscanner); #endif } case EOB_ACT_CONTINUE_SCAN: yyg->yy_c_buf_p = yyg->yytext_ptr + offset; break; } } } c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */ *yyg->yy_c_buf_p = '\0'; /* preserve yytext */ yyg->yy_hold_char = *++yyg->yy_c_buf_p; if ( c == '\n' ) do{ yylineno++; yycolumn=0; }while(0) ; return c; } #endif /* ifndef YY_NO_INPUT */ /** Immediately switch to a different input stream. * @param input_file A readable stream. * @param yyscanner The scanner object. * @note This function does not reset the start condition to @c INITIAL . */ void yyrestart (FILE * input_file , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if ( ! YY_CURRENT_BUFFER ){ yyensure_buffer_stack (yyscanner); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); } yy_init_buffer( YY_CURRENT_BUFFER, input_file , yyscanner); yy_load_buffer_state( yyscanner ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * @param yyscanner The scanner object. */ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* TODO. We should be able to replace this entire function body * with * yypop_buffer_state(); * yypush_buffer_state(new_buffer); */ yyensure_buffer_stack (yyscanner); if ( YY_CURRENT_BUFFER == new_buffer ) return; if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *yyg->yy_c_buf_p = yyg->yy_hold_char; YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; } YY_CURRENT_BUFFER_LVALUE = new_buffer; yy_load_buffer_state( yyscanner ); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ yyg->yy_did_buffer_switch_on_eof = 1; } static void yy_load_buffer_state (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; yyg->yy_hold_char = *yyg->yy_c_buf_p; } /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. * @param yyscanner The scanner object. * @return the allocated buffer state. */ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size , yyscan_t yyscanner) { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) , yyscanner ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; yy_init_buffer( b, file , yyscanner); return b; } /** Destroy the buffer. * @param b a buffer created with yy_create_buffer() * @param yyscanner The scanner object. */ void yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if ( ! b ) return; if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) yyfree( (void *) b->yy_ch_buf , yyscanner ); yyfree( (void *) b , yyscanner ); } /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a yyrestart() or at EOF. */ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) { int oerrno = errno; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yy_flush_buffer( b , yyscanner); b->yy_input_file = file; b->yy_fill_buffer = 1; /* If b is the current buffer, then yy_init_buffer was _probably_ * called from yyrestart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ b->yy_bs_lineno = 1; b->yy_bs_column = 0; } b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; errno = oerrno; } /** Discard all buffered characters. On the next scan, YY_INPUT will be called. * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * @param yyscanner The scanner object. */ void yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) yy_load_buffer_state( yyscanner ); } /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * @param yyscanner The scanner object. */ void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (new_buffer == NULL) return; yyensure_buffer_stack(yyscanner); /* This block is copied from yy_switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *yyg->yy_c_buf_p = yyg->yy_hold_char; YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; } /* Only push if top exists. Otherwise, replace top. */ if (YY_CURRENT_BUFFER) yyg->yy_buffer_stack_top++; YY_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from yy_switch_to_buffer. */ yy_load_buffer_state( yyscanner ); yyg->yy_did_buffer_switch_on_eof = 1; } /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * @param yyscanner The scanner object. */ void yypop_buffer_state (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (!YY_CURRENT_BUFFER) return; yy_delete_buffer(YY_CURRENT_BUFFER , yyscanner); YY_CURRENT_BUFFER_LVALUE = NULL; if (yyg->yy_buffer_stack_top > 0) --yyg->yy_buffer_stack_top; if (YY_CURRENT_BUFFER) { yy_load_buffer_state( yyscanner ); yyg->yy_did_buffer_switch_on_eof = 1; } } /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ static void yyensure_buffer_stack (yyscan_t yyscanner) { yy_size_t num_to_alloc; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (!yyg->yy_buffer_stack) { /* First allocation is just for 2 elements, since we don't know if this * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc (num_to_alloc * sizeof(struct yy_buffer_state*) , yyscanner); if ( ! yyg->yy_buffer_stack ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); yyg->yy_buffer_stack_max = num_to_alloc; yyg->yy_buffer_stack_top = 0; return; } if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){ /* Increase the buffer to prepare for a possible push. */ yy_size_t grow_size = 8 /* arbitrary grow size */; num_to_alloc = yyg->yy_buffer_stack_max + grow_size; yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc (yyg->yy_buffer_stack, num_to_alloc * sizeof(struct yy_buffer_state*) , yyscanner); if ( ! yyg->yy_buffer_stack ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); /* zero only the new slots.*/ memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); yyg->yy_buffer_stack_max = num_to_alloc; } } /** Setup the input buffer state to scan directly from a user-specified character buffer. * @param base the character buffer * @param size the size in bytes of the character buffer * @param yyscanner The scanner object. * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) { YY_BUFFER_STATE b; if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return NULL; b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = NULL; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; yy_switch_to_buffer( b , yyscanner ); return b; } /** Setup the input buffer state to scan a string. The next call to yylex() will * scan from a @e copy of @a str. * @param yystr a NUL-terminated string to scan * @param yyscanner The scanner object. * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use * yy_scan_bytes() instead. */ YY_BUFFER_STATE yy_scan_string (const char * yystr , yyscan_t yyscanner) { return yy_scan_bytes( yystr, (int) strlen(yystr) , yyscanner); } /** Setup the input buffer state to scan the given bytes. The next call to yylex() will * scan from a @e copy of @a bytes. * @param yybytes the byte buffer to scan * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. * @param yyscanner The scanner object. * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len , yyscan_t yyscanner) { YY_BUFFER_STATE b; char *buf; yy_size_t n; int i; /* Get memory for full buffer, including space for trailing EOB's. */ n = (yy_size_t) (_yybytes_len + 2); buf = (char *) yyalloc( n , yyscanner ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); for ( i = 0; i < _yybytes_len; ++i ) buf[i] = yybytes[i]; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; b = yy_scan_buffer( buf, n , yyscanner); if ( ! b ) YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->yy_is_our_buffer = 1; return b; } #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif static void yynoreturn yy_fatal_error (const char* msg , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; (void)yyg; fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ yytext[yyleng] = yyg->yy_hold_char; \ yyg->yy_c_buf_p = yytext + yyless_macro_arg; \ yyg->yy_hold_char = *yyg->yy_c_buf_p; \ *yyg->yy_c_buf_p = '\0'; \ yyleng = yyless_macro_arg; \ } \ while ( 0 ) /* Accessor methods (get/set functions) to struct members. */ /** Get the user-defined data for this scanner. * @param yyscanner The scanner object. */ YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyextra; } /** Get the current line number. * @param yyscanner The scanner object. */ int yyget_lineno (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (! YY_CURRENT_BUFFER) return 0; return yylineno; } /** Get the current column number. * @param yyscanner The scanner object. */ int yyget_column (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (! YY_CURRENT_BUFFER) return 0; return yycolumn; } /** Get the input stream. * @param yyscanner The scanner object. */ FILE *yyget_in (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyin; } /** Get the output stream. * @param yyscanner The scanner object. */ FILE *yyget_out (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyout; } /** Get the length of the current token. * @param yyscanner The scanner object. */ int yyget_leng (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyleng; } /** Get the current token. * @param yyscanner The scanner object. */ char *yyget_text (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yytext; } /** Set the user-defined data. This data is never touched by the scanner. * @param user_defined The data to be associated with this scanner. * @param yyscanner The scanner object. */ void yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyextra = user_defined ; } /** Set the current line number. * @param _line_number line number * @param yyscanner The scanner object. */ void yyset_lineno (int _line_number , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* lineno is only valid if an input buffer exists. */ if (! YY_CURRENT_BUFFER ) YY_FATAL_ERROR( "yyset_lineno called with no buffer" ); yylineno = _line_number; } /** Set the current column. * @param _column_no column number * @param yyscanner The scanner object. */ void yyset_column (int _column_no , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* column is only valid if an input buffer exists. */ if (! YY_CURRENT_BUFFER ) YY_FATAL_ERROR( "yyset_column called with no buffer" ); yycolumn = _column_no; } /** Set the input stream. This does not discard the current * input buffer. * @param _in_str A readable stream. * @param yyscanner The scanner object. * @see yy_switch_to_buffer */ void yyset_in (FILE * _in_str , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyin = _in_str ; } void yyset_out (FILE * _out_str , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyout = _out_str ; } int yyget_debug (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yy_flex_debug; } void yyset_debug (int _bdebug , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yy_flex_debug = _bdebug ; } /* Accessor methods for yylval and yylloc */ YYSTYPE * yyget_lval (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yylval; } void yyset_lval (YYSTYPE * yylval_param , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yylval = yylval_param; } /* User-visible API */ /* yylex_init is special because it creates the scanner itself, so it is * the ONLY reentrant function that doesn't take the scanner as the last argument. * That's why we explicitly handle the declaration, instead of using our macros. */ int yylex_init(yyscan_t* ptr_yy_globals) { if (ptr_yy_globals == NULL){ errno = EINVAL; return 1; } *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL ); if (*ptr_yy_globals == NULL){ errno = ENOMEM; return 1; } /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); return yy_init_globals ( *ptr_yy_globals ); } /* yylex_init_extra has the same functionality as yylex_init, but follows the * convention of taking the scanner as the last argument. Note however, that * this is a *pointer* to a scanner, as it will be allocated by this call (and * is the reason, too, why this function also must handle its own declaration). * The user defined value in the first argument will be available to yyalloc in * the yyextra field. */ int yylex_init_extra( YY_EXTRA_TYPE yy_user_defined, yyscan_t* ptr_yy_globals ) { struct yyguts_t dummy_yyguts; yyset_extra (yy_user_defined, &dummy_yyguts); if (ptr_yy_globals == NULL){ errno = EINVAL; return 1; } *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); if (*ptr_yy_globals == NULL){ errno = ENOMEM; return 1; } /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); yyset_extra (yy_user_defined, *ptr_yy_globals); return yy_init_globals ( *ptr_yy_globals ); } static int yy_init_globals (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* Initialization is the same as for the non-reentrant scanner. * This function is called from yylex_destroy(), so don't allocate here. */ yyg->yy_buffer_stack = NULL; yyg->yy_buffer_stack_top = 0; yyg->yy_buffer_stack_max = 0; yyg->yy_c_buf_p = NULL; yyg->yy_init = 0; yyg->yy_start = 0; yyg->yy_start_stack_ptr = 0; yyg->yy_start_stack_depth = 0; yyg->yy_start_stack = NULL; /* Defined in main.c */ #ifdef YY_STDINIT yyin = stdin; yyout = stdout; #else yyin = NULL; yyout = NULL; #endif /* For future reference: Set errno on error, since we are called by * yylex_init() */ return 0; } /* yylex_destroy is for both reentrant and non-reentrant scanners. */ int yylex_destroy (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ yy_delete_buffer( YY_CURRENT_BUFFER , yyscanner ); YY_CURRENT_BUFFER_LVALUE = NULL; yypop_buffer_state(yyscanner); } /* Destroy the stack itself. */ yyfree(yyg->yy_buffer_stack , yyscanner); yyg->yy_buffer_stack = NULL; /* Destroy the start condition stack. */ yyfree( yyg->yy_start_stack , yyscanner ); yyg->yy_start_stack = NULL; /* Reset the globals. This is important in a non-reentrant scanner so the next time * yylex() is called, initialization will occur. */ yy_init_globals( yyscanner); /* Destroy the main struct (reentrant only). */ yyfree ( yyscanner , yyscanner ); yyscanner = NULL; return 0; } /* * Internal utility routines. */ #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, const char * s2, int n , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; (void)yyg; int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (const char * s , yyscan_t yyscanner) { int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif void *yyalloc (yy_size_t size , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; (void)yyg; return malloc(size); } void *yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; (void)yyg; /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return realloc(ptr, size); } void yyfree (void * ptr , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; (void)yyg; free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ } #define YYTABLES_NAME "yytables" #line 348 "conffile.l" carbon-c-relay-3.2/config.h.in000066400000000000000000000131621317265605500162140ustar00rootroot00000000000000/* config.h.in. Generated from configure.ac by autoheader. */ /* Define to 1 if you have the header file. */ #undef HAVE_ARPA_INET_H /* Define to 1 if you have the header file. */ #undef HAVE_ASSERT_H /* Define to 1 if you have the header file. */ #undef HAVE_ERRNO_H /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Define to 1 if you have the `fork' function. */ #undef HAVE_FORK /* Define to 1 if you have the `gethostname' function. */ #undef HAVE_GETHOSTNAME /* Define to 1 if you have the `gettimeofday' function. */ #undef HAVE_GETTIMEOFDAY /* Define to 1 if you have the header file. */ #undef HAVE_GLOB_H /* Define if you have gzip */ #undef HAVE_GZIP /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `localtime_r' function. */ #undef HAVE_LOCALTIME_R /* Define if you have lz4 */ #undef HAVE_LZ4 /* Define to 1 if you have the header file. */ #undef HAVE_LZ4_H /* Define to 1 if your system has a GNU libc compatible `malloc' function, and to 0 otherwise. */ #undef HAVE_MALLOC /* Define to 1 if you have the header file. */ #undef HAVE_MATH_H /* Define to 1 if you have the `memmove' function. */ #undef HAVE_MEMMOVE /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `memset' function. */ #undef HAVE_MEMSET /* Define to 1 if you have the header file. */ #undef HAVE_NETDB_H /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IN_H /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_TCP_H /* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_ERR_H /* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_SSL_H /* Define to 1 if you have the header file. */ #undef HAVE_POLL_H /* Define to 1 if you have the `pow' function. */ #undef HAVE_POW /* Define to 1 if you have the header file. */ #undef HAVE_PTHREAD_H /* Define to 1 if your system has a GNU libc compatible `realloc' function, and to 0 otherwise. */ #undef HAVE_REALLOC /* Define to 1 if you have the `regcomp' function. */ #undef HAVE_REGCOMP /* Define to 1 if you have the header file. */ #undef HAVE_REGEX_H /* Define to 1 if you have the header file. */ #undef HAVE_SIGNAL_H /* Define to 1 if you have the `socket' function. */ #undef HAVE_SOCKET /* Define to 1 if you have the `sqrt' function. */ #undef HAVE_SQRT /* Define if you have ssl */ #undef HAVE_SSL /* Define to 1 if you have the header file. */ #undef HAVE_STDARG_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDIO_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strchr' function. */ #undef HAVE_STRCHR /* Define to 1 if you have the `strdup' function. */ #undef HAVE_STRDUP /* Define to 1 if you have the `strerror' function. */ #undef HAVE_STRERROR /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strstr' function. */ #undef HAVE_STRSTR /* Define to 1 if you have the `strtol' function. */ #undef HAVE_STRTOL /* Define to 1 if you have the header file. */ #undef HAVE_SYS_RESOURCE_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SOCKET_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TIME_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_UIO_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_UN_H /* Define to 1 if you have the header file. */ #undef HAVE_TIME_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the `vfork' function. */ #undef HAVE_VFORK /* Define to 1 if you have the header file. */ #undef HAVE_VFORK_H /* Define to 1 if `fork' works. */ #undef HAVE_WORKING_FORK /* Define to 1 if `vfork' works. */ #undef HAVE_WORKING_VFORK /* Define to 1 if you have the header file. */ #undef HAVE_ZLIB_H /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Version number of package */ #undef VERSION /* 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 #undef inline #endif /* Define to rpl_malloc if the replacement function should be used. */ #undef malloc /* Define to `int' if does not define. */ #undef pid_t /* Define to rpl_realloc if the replacement function should be used. */ #undef realloc /* Define as `fork' if `vfork' does not work. */ #undef vfork carbon-c-relay-3.2/configure000077500000000000000000005741611317265605500161130ustar00rootroot00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for carbon-c-relay 3.2. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='carbon-c-relay' PACKAGE_TARNAME='carbon-c-relay' PACKAGE_VERSION='3.2' PACKAGE_STRING='carbon-c-relay 3.2' PACKAGE_BUGREPORT='' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBSSL LIBLZ4 LIBGZIP LIBOBJS EGREP GREP CPP am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_silent_rules enable_dependency_tracking with_gzip with_lz4 with_ssl ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures carbon-c-relay 3.2 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/carbon-c-relay] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of carbon-c-relay 3.2:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) support gzip compression for sending/receiving support lz4 compression for sending/receiving support ssl encryption for sending/receiving Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF carbon-c-relay configure 3.2 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by carbon-c-relay $as_me 3.2, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers config.h" am__api_version='1.15' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='carbon-c-relay' VERSION='3.2' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar pax cpio none' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 fi fi # Checks for programs. ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 $as_echo_n "checking whether $CC understands -c and -o together... " >&6; } if ${am_cv_prog_cc_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 $as_echo "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi # Checks for libraries. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing sqrt" >&5 $as_echo_n "checking for library containing sqrt... " >&6; } if ${ac_cv_search_sqrt+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char sqrt (); int main () { return sqrt (); ; return 0; } _ACEOF for ac_lib in '' m; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_sqrt=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_sqrt+:} false; then : break fi done if ${ac_cv_search_sqrt+:} false; then : else ac_cv_search_sqrt=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_sqrt" >&5 $as_echo "$ac_cv_search_sqrt" >&6; } ac_res=$ac_cv_search_sqrt if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5 $as_echo_n "checking for library containing gethostbyname... " >&6; } if ${ac_cv_search_gethostbyname+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostbyname (); int main () { return gethostbyname (); ; return 0; } _ACEOF for ac_lib in '' nsl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_gethostbyname=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_gethostbyname+:} false; then : break fi done if ${ac_cv_search_gethostbyname+:} false; then : else ac_cv_search_gethostbyname=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5 $as_echo "$ac_cv_search_gethostbyname" >&6; } ac_res=$ac_cv_search_gethostbyname if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5 $as_echo_n "checking for library containing socket... " >&6; } if ${ac_cv_search_socket+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char socket (); int main () { return socket (); ; return 0; } _ACEOF for ac_lib in '' socket; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_socket=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_socket+:} false; then : break fi done if ${ac_cv_search_socket+:} false; then : else ac_cv_search_socket=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket" >&5 $as_echo "$ac_cv_search_socket" >&6; } ac_res=$ac_cv_search_socket if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi saveLIBS="$LIBS" LIBS= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_create" >&5 $as_echo_n "checking for library containing pthread_create... " >&6; } if ${ac_cv_search_pthread_create+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_create (); int main () { return pthread_create (); ; return 0; } _ACEOF for ac_lib in '' pthread; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_pthread_create=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_pthread_create+:} false; then : break fi done if ${ac_cv_search_pthread_create+:} false; then : else ac_cv_search_pthread_create=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pthread_create" >&5 $as_echo "$ac_cv_search_pthread_create" >&6; } ac_res=$ac_cv_search_pthread_create if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi if test "x$LIBS" != x ; then # compiler knows best, really LIBS="-pthread" fi LIBS="$saveLIBS $LIBS" # Checks for header files. ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in arpa/inet.h \ assert.h \ errno.h \ fcntl.h \ glob.h \ math.h \ netdb.h \ netinet/in.h \ netinet/tcp.h \ poll.h \ pthread.h \ regex.h \ signal.h \ stdarg.h \ stdio.h \ stdlib.h \ string.h \ sys/resource.h \ sys/socket.h \ sys/stat.h \ sys/time.h \ sys/types.h \ sys/uio.h \ sys/un.h \ time.h \ unistd.h \ do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF else as_fn_error $? "required header missing" "$LINENO" 5 fi done # Checks for typedefs, structures, and compiler characteristics. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 $as_echo_n "checking for inline... " >&6; } if ${ac_cv_c_inline+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } $ac_kw foo_t foo () {return 0; } #endif _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_inline=$ac_kw fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_inline" != no && break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 $as_echo "$ac_cv_c_inline" >&6; } case $ac_cv_c_inline in inline | yes) ;; *) case $ac_cv_c_inline in no) ac_val=;; *) ac_val=$ac_cv_c_inline;; esac cat >>confdefs.h <<_ACEOF #ifndef __cplusplus #define inline $ac_val #endif _ACEOF ;; esac # Checks for library functions. ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default" if test "x$ac_cv_type_pid_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define pid_t int _ACEOF fi for ac_header in vfork.h do : ac_fn_c_check_header_mongrel "$LINENO" "vfork.h" "ac_cv_header_vfork_h" "$ac_includes_default" if test "x$ac_cv_header_vfork_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_VFORK_H 1 _ACEOF fi done for ac_func in fork vfork do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done if test "x$ac_cv_func_fork" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fork" >&5 $as_echo_n "checking for working fork... " >&6; } if ${ac_cv_func_fork_works+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_fork_works=cross else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* By Ruediger Kuhlmann. */ return fork () < 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_fork_works=yes else ac_cv_func_fork_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fork_works" >&5 $as_echo "$ac_cv_func_fork_works" >&6; } else ac_cv_func_fork_works=$ac_cv_func_fork fi if test "x$ac_cv_func_fork_works" = xcross; then case $host in *-*-amigaos* | *-*-msdosdjgpp*) # Override, as these systems have only a dummy fork() stub ac_cv_func_fork_works=no ;; *) ac_cv_func_fork_works=yes ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5 $as_echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;} fi ac_cv_func_vfork_works=$ac_cv_func_vfork if test "x$ac_cv_func_vfork" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vfork" >&5 $as_echo_n "checking for working vfork... " >&6; } if ${ac_cv_func_vfork_works+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_vfork_works=cross else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Thanks to Paul Eggert for this test. */ $ac_includes_default #include #ifdef HAVE_VFORK_H # include #endif /* On some sparc systems, changes by the child to local and incoming argument registers are propagated back to the parent. The compiler is told about this with #include , but some compilers (e.g. gcc -O) don't grok . Test for this by using a static variable whose address is put into a register that is clobbered by the vfork. */ static void #ifdef __cplusplus sparc_address_test (int arg) # else sparc_address_test (arg) int arg; #endif { static pid_t child; if (!child) { child = vfork (); if (child < 0) { perror ("vfork"); _exit(2); } if (!child) { arg = getpid(); write(-1, "", 0); _exit (arg); } } } int main () { pid_t parent = getpid (); pid_t child; sparc_address_test (0); child = vfork (); if (child == 0) { /* Here is another test for sparc vfork register problems. This test uses lots of local variables, at least as many local variables as main has allocated so far including compiler temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should reuse the register of parent for one of the local variables, since it will think that parent can't possibly be used any more in this routine. Assigning to the local variable will thus munge parent in the parent process. */ pid_t p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(), p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid(); /* Convince the compiler that p..p7 are live; otherwise, it might use the same hardware register for all 8 local variables. */ if (p != p1 || p != p2 || p != p3 || p != p4 || p != p5 || p != p6 || p != p7) _exit(1); /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent from child file descriptors. If the child closes a descriptor before it execs or exits, this munges the parent's descriptor as well. Test for this by closing stdout in the child. */ _exit(close(fileno(stdout)) != 0); } else { int status; struct stat st; while (wait(&status) != child) ; return ( /* Was there some problem with vforking? */ child < 0 /* Did the child fail? (This shouldn't happen.) */ || status /* Did the vfork/compiler bug occur? */ || parent != getpid() /* Did the file descriptor bug occur? */ || fstat(fileno(stdout), &st) != 0 ); } } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_vfork_works=yes else ac_cv_func_vfork_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_vfork_works" >&5 $as_echo "$ac_cv_func_vfork_works" >&6; } fi; if test "x$ac_cv_func_fork_works" = xcross; then ac_cv_func_vfork_works=$ac_cv_func_vfork { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5 $as_echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;} fi if test "x$ac_cv_func_vfork_works" = xyes; then $as_echo "#define HAVE_WORKING_VFORK 1" >>confdefs.h else $as_echo "#define vfork fork" >>confdefs.h fi if test "x$ac_cv_func_fork_works" = xyes; then $as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h fi for ac_header in stdlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" if test "x$ac_cv_header_stdlib_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDLIB_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 $as_echo_n "checking for GNU libc compatible malloc... " >&6; } if ${ac_cv_func_malloc_0_nonnull+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_malloc_0_nonnull=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined STDC_HEADERS || defined HAVE_STDLIB_H # include #else char *malloc (); #endif int main () { return ! malloc (0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_malloc_0_nonnull=yes else ac_cv_func_malloc_0_nonnull=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5 $as_echo "$ac_cv_func_malloc_0_nonnull" >&6; } if test $ac_cv_func_malloc_0_nonnull = yes; then : $as_echo "#define HAVE_MALLOC 1" >>confdefs.h else $as_echo "#define HAVE_MALLOC 0" >>confdefs.h case " $LIBOBJS " in *" malloc.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS malloc.$ac_objext" ;; esac $as_echo "#define malloc rpl_malloc" >>confdefs.h fi for ac_header in stdlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" if test "x$ac_cv_header_stdlib_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDLIB_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible realloc" >&5 $as_echo_n "checking for GNU libc compatible realloc... " >&6; } if ${ac_cv_func_realloc_0_nonnull+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_realloc_0_nonnull=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined STDC_HEADERS || defined HAVE_STDLIB_H # include #else char *realloc (); #endif int main () { return ! realloc (0, 0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_realloc_0_nonnull=yes else ac_cv_func_realloc_0_nonnull=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_realloc_0_nonnull" >&5 $as_echo "$ac_cv_func_realloc_0_nonnull" >&6; } if test $ac_cv_func_realloc_0_nonnull = yes; then : $as_echo "#define HAVE_REALLOC 1" >>confdefs.h else $as_echo "#define HAVE_REALLOC 0" >>confdefs.h case " $LIBOBJS " in *" realloc.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS realloc.$ac_objext" ;; esac $as_echo "#define realloc rpl_realloc" >>confdefs.h fi for ac_func in gethostname \ gettimeofday \ localtime_r \ memmove \ memset \ pow \ regcomp \ socket \ sqrt \ strchr \ strdup \ strerror \ strstr \ strtol do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF else as_fn_error $? "required function missing" "$LINENO" 5 fi done # Check whether --with-gzip was given. if test "${with_gzip+set}" = set; then : withval=$with_gzip; else with_gzip=check fi LIBGZIP= if test "x$with_gzip" != xno; then : for ac_header in zlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" if test "x$ac_cv_header_zlib_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_ZLIB_H 1 _ACEOF else LIBGZIP=_missing_header fi done as_ac_Lib=`$as_echo "ac_cv_lib_z${LIBGZIP}''_gzopen" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gzopen in -lz${LIBGZIP}" >&5 $as_echo_n "checking for gzopen in -lz${LIBGZIP}... " >&6; } if eval \${$as_ac_Lib+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lz${LIBGZIP} $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gzopen (); int main () { return gzopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$as_ac_Lib=yes" else eval "$as_ac_Lib=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : LIBGZIP=-lz $as_echo "#define HAVE_GZIP 1" >>confdefs.h else if test "x$with_gzip" != xcheck; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "--with-gzip was given, but test for gzip failed See \`config.log' for more details" "$LINENO" 5; } fi LIBGZIP= fi fi # Check whether --with-lz4 was given. if test "${with_lz4+set}" = set; then : withval=$with_lz4; else with_lz4=check fi LIBLZ4= if test "x$with_lz4" != xno; then : for ac_header in lz4.h do : ac_fn_c_check_header_mongrel "$LINENO" "lz4.h" "ac_cv_header_lz4_h" "$ac_includes_default" if test "x$ac_cv_header_lz4_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LZ4_H 1 _ACEOF else LIBLZ4=_missing_header fi done as_ac_Lib=`$as_echo "ac_cv_lib_lz4${LIBLZ4}''_LZ4_createStream" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LZ4_createStream in -llz4${LIBLZ4}" >&5 $as_echo_n "checking for LZ4_createStream in -llz4${LIBLZ4}... " >&6; } if eval \${$as_ac_Lib+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-llz4${LIBLZ4} $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char LZ4_createStream (); int main () { return LZ4_createStream (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$as_ac_Lib=yes" else eval "$as_ac_Lib=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : LIBLZ4=-llz4 $as_echo "#define HAVE_LZ4 1" >>confdefs.h else if test "x$with_lz4" != xcheck; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "--with-lz4 was given, but test for lz4 failed See \`config.log' for more details" "$LINENO" 5; } fi LIBLZ4= fi fi # Check whether --with-ssl was given. if test "${with_ssl+set}" = set; then : withval=$with_ssl; else with_ssl=check fi LIBSSL= if test "x$with_ssl" != xno; then : for ac_header in openssl/err.h \ openssl/ssl.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF else LIBSSL=_missing_header fi done as_ac_Lib=`$as_echo "ac_cv_lib_ssl${LIBSSL}''_SSL_connect" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_connect in -lssl${LIBSSL}" >&5 $as_echo_n "checking for SSL_connect in -lssl${LIBSSL}... " >&6; } if eval \${$as_ac_Lib+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lssl${LIBSSL} $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char SSL_connect (); int main () { return SSL_connect (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$as_ac_Lib=yes" else eval "$as_ac_Lib=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : LIBSSL="-lssl" $as_echo "#define HAVE_SSL 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OPENSSL_add_all_algorithms_noconf in -lcrypto" >&5 $as_echo_n "checking for OPENSSL_add_all_algorithms_noconf in -lcrypto... " >&6; } if ${ac_cv_lib_crypto_OPENSSL_add_all_algorithms_noconf+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lcrypto $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char OPENSSL_add_all_algorithms_noconf (); int main () { return OPENSSL_add_all_algorithms_noconf (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_crypto_OPENSSL_add_all_algorithms_noconf=yes else ac_cv_lib_crypto_OPENSSL_add_all_algorithms_noconf=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_OPENSSL_add_all_algorithms_noconf" >&5 $as_echo "$ac_cv_lib_crypto_OPENSSL_add_all_algorithms_noconf" >&6; } if test "x$ac_cv_lib_crypto_OPENSSL_add_all_algorithms_noconf" = xyes; then : LIBSSL="${LIBSSL} -lcrypto" fi LIBSSL="${LIBSSL}" else if test "x$with_ssl" != xcheck; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "--with-ssl was given, but test for ssl failed See \`config.log' for more details" "$LINENO" 5; } fi LIBSSL= fi fi ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by carbon-c-relay $as_me 3.2, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ carbon-c-relay config.status 3.2 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi carbon-c-relay-3.2/configure.ac000066400000000000000000000063721317265605500164640ustar00rootroot00000000000000# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) AC_INIT([carbon-c-relay], [3.2], []) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE # Checks for programs. AC_PROG_CC AC_PROG_MAKE_SET # Checks for libraries. AC_SEARCH_LIBS([sqrt], [m]) AC_SEARCH_LIBS([gethostbyname], [nsl]) AC_SEARCH_LIBS([socket], [socket]) saveLIBS="$LIBS" LIBS= AC_SEARCH_LIBS([pthread_create], [pthread]) if test "x$LIBS" != x ; then # compiler knows best, really LIBS="-pthread" fi LIBS="$saveLIBS $LIBS" # Checks for header files. AC_CHECK_HEADERS([arpa/inet.h \ assert.h \ errno.h \ fcntl.h \ glob.h \ math.h \ netdb.h \ netinet/in.h \ netinet/tcp.h \ poll.h \ pthread.h \ regex.h \ signal.h \ stdarg.h \ stdio.h \ stdlib.h \ string.h \ sys/resource.h \ sys/socket.h \ sys/stat.h \ sys/time.h \ sys/types.h \ sys/uio.h \ sys/un.h \ time.h \ unistd.h \ ], [], [AC_MSG_ERROR([required header missing])]) # Checks for typedefs, structures, and compiler characteristics. AC_C_INLINE # Checks for library functions. AC_FUNC_FORK AC_FUNC_MALLOC AC_FUNC_REALLOC AC_CHECK_FUNCS([gethostname \ gettimeofday \ localtime_r \ memmove \ memset \ pow \ regcomp \ socket \ sqrt \ strchr \ strdup \ strerror \ strstr \ strtol], [], [AC_MSG_ERROR([required function missing])]) AC_ARG_WITH([gzip], [support gzip compression for sending/receiving], [], [with_gzip=check]) LIBGZIP= AS_IF([test "x$with_gzip" != xno], [AC_CHECK_HEADERS([zlib.h], [], [LIBGZIP=_missing_header]) AC_CHECK_LIB([z${LIBGZIP}], [gzopen], [AC_SUBST([LIBGZIP], [-lz]) AC_DEFINE([HAVE_GZIP], [1], [Define if you have gzip]) ], [if test "x$with_gzip" != xcheck; then AC_MSG_FAILURE( [--with-gzip was given, but test for gzip failed]) fi LIBGZIP= ] )]) AC_ARG_WITH([lz4], [support lz4 compression for sending/receiving], [], [with_lz4=check]) LIBLZ4= AS_IF([test "x$with_lz4" != xno], [AC_CHECK_HEADERS([lz4.h], [], [LIBLZ4=_missing_header]) AC_CHECK_LIB([lz4${LIBLZ4}], [LZ4_createStream], [AC_SUBST([LIBLZ4], [-llz4]) AC_DEFINE([HAVE_LZ4], [1], [Define if you have lz4]) ], [if test "x$with_lz4" != xcheck; then AC_MSG_FAILURE( [--with-lz4 was given, but test for lz4 failed]) fi LIBLZ4= ] )]) AC_ARG_WITH([ssl], [support ssl encryption for sending/receiving], [], [with_ssl=check]) LIBSSL= AS_IF([test "x$with_ssl" != xno], [AC_CHECK_HEADERS([openssl/err.h \ openssl/ssl.h], [], [LIBSSL=_missing_header]) AC_CHECK_LIB([ssl${LIBSSL}], [SSL_connect], [LIBSSL="-lssl" AC_DEFINE([HAVE_SSL], [1], [Define if you have ssl]) AC_CHECK_LIB([crypto], [OPENSSL_add_all_algorithms_noconf], [LIBSSL="${LIBSSL} -lcrypto"], []) AC_SUBST([LIBSSL], ["${LIBSSL}"]) ], [if test "x$with_ssl" != xcheck; then AC_MSG_FAILURE( [--with-ssl was given, but test for ssl failed]) fi LIBSSL= ] )]) AC_CONFIG_FILES([Makefile]) AC_OUTPUT carbon-c-relay-3.2/consistent-hash.c000066400000000000000000000272721317265605500174560ustar00rootroot00000000000000/* * Copyright 2013-2017 Fabian Groffen * * 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. */ #include #include #include #include #include "fnv1a.h" #include "md5.h" #include "server.h" #include "allocator.h" #define CH_RING struct _ch_ring #include "consistent-hash.h" /* This value is hardwired in the carbon sources, and necessary to get * fair (re)balancing of metrics in the hash ring. Because the value * seems reasonable, we use the same value for carbon and fnv1a hash * implementations. */ #define HASH_REPLICAS 100 typedef struct _ring_entry { unsigned short pos; server *server; } ch_ring_entry; struct _ch_ring { ch_type type; unsigned char hash_replicas; ch_ring_entry *entrylist; int entrysize; int entrycnt; }; /** * Computes the hash position for key in a 16-bit unsigned integer * space. Returns a number between 0 and 65535 based on the highest 2 * bytes of the MD5 sum of key. */ static unsigned short carbon_hashpos(const char *key, const char *end) { unsigned char md5[MD5_DIGEST_LENGTH]; MD5((unsigned char *)key, end - key, md5); return ((md5[0] << 8) + md5[1]); } /** * Computes the hash position for key in a 16-bit unsigned integer * space. Returns a number between 0 and 65535 based on the FNV1a hash * algorithm. */ static unsigned short fnv1a_hashpos(const char *key, const char *end) { unsigned int hash; fnv1a_32(hash, key, key, end); return (unsigned short)((hash >> 16) ^ (hash & (unsigned int)0xFFFF)); } /** * Computes the bucket number for key in the range [0, bckcnt). The * algorithm used is the jump consistent hash by Lamping and Veach. */ static unsigned int jump_bucketpos(unsigned long long int key, int bckcnt) { long long int b = -1, j = 0; assert(bckcnt > 0); /* help static code analysis */ while (j < bckcnt) { b = j; key = key * 2862933555777941757ULL + 1; j = (long long int)((double)(b + 1) * ((double)(1LL << 31) / (double)((key >> 33) + 1)) ); } /* b cannot exceed the range of bckcnt, see while condition */ return (unsigned int)b; } /** * Sort comparator for ch_ring_entry structs on pos, ip and instance. */ static int entrycmp_carbon(const void *l, const void *r) { ch_ring_entry *ch_l = (ch_ring_entry *)l; ch_ring_entry *ch_r = (ch_ring_entry *)r; if (ch_l->pos != ch_r->pos) return ch_l->pos - ch_r->pos; #ifndef CH_CMP_V40_BEHAVIOUR { int d = strcmp(server_ip(ch_l->server), server_ip(ch_r->server)); char *i_l, *i_r; if (d != 0) return d; i_l = server_instance(ch_l->server); i_r = server_instance(ch_r->server); if (i_l == NULL && i_r == NULL) return 0; if (i_l == NULL) return 1; if (i_r == NULL) return -1; return strcmp(i_l, i_r); } #endif return 0; } /** * Sort comparator for ch_ring_entry structs on pos, ip and port. */ static int entrycmp_fnv1a(const void *l, const void *r) { ch_ring_entry *ch_l = (ch_ring_entry *)l; ch_ring_entry *ch_r = (ch_ring_entry *)r; if (ch_l->pos != ch_r->pos) return ch_l->pos - ch_r->pos; #ifndef CH_CMP_V40_BEHAVIOUR { int d = strcmp(server_ip(ch_l->server), server_ip(ch_r->server)); if (d != 0) return d; return server_port(ch_l->server) - server_port(ch_r->server); } #endif return 0; } /** * Sort comparator for ch_ring_entry structs on instance only. */ static int entrycmp_jump_fnv1a(const void *l, const void *r) { ch_ring_entry *ch_l = (ch_ring_entry *)l; ch_ring_entry *ch_r = (ch_ring_entry *)r; char *si_l = server_instance(ch_l->server); char *si_r = server_instance(ch_r->server); char *endp; long val_l; long val_r; /* order such that servers with explicit instance come first * (sorted), all servers without instance follow in order of their * definition in the config file (as per documentation) */ if (si_l == NULL && si_r == NULL) return ch_l->pos - ch_r->pos; if (si_l == NULL) return 1; if (si_r == NULL) return -1; /* at this point we have two instances, try and see if both are * numbers, if so, compare as such, else fall back to string * comparison */ val_l = strtol(si_l, &endp, 10); if (*endp == '\0') { val_r = strtol(si_r, &endp, 10); if (*endp == '\0') return (int)(val_l - val_r); } return strcmp(si_l, si_r); } ch_ring * ch_new(allocator *a, ch_type type, int servercnt) { ch_ring *ret; if (servercnt > CONN_DESTS_SIZE) { logerr("ch_addnode: nodes in use exceeds CONN_DESTS_SIZE, " "increase CONN_DESTS_SIZE in router.h\n"); return NULL; } ret = ra_malloc(a, sizeof(ch_ring)); if (ret == NULL) return NULL; ret->type = type; switch (ret->type) { case CARBON: case FNV1a: ret->hash_replicas = HASH_REPLICAS; break; default: ret->hash_replicas = 1; break; } ret->entrycnt = 0; ret->entrysize = ret->hash_replicas * servercnt; ret->entrylist = ra_malloc(a, sizeof(ch_ring_entry) * ret->entrysize); if (ret->entrylist == NULL) { free(ret); return NULL; } return ret; } /** * Computes the hash positions for the server name given. This is based * on the hashpos function. The server name usually is the IPv4 * address. The port component is just stored and not used in the * carbon hash calculation in case of carbon_ch. The instance component * is used in the hash calculation of carbon_ch, it is ignored for * fnv1a_ch. Returns an updated ring once the last server is added. */ ch_ring * ch_addnode(ch_ring *ring, server *s) { int i; char buf[256]; ch_ring_entry *entries; char *instance = server_instance(s); int (*cmp)(const void *, const void *) = NULL; if (ring == NULL) return NULL; entries = &ring->entrylist[ring->entrycnt]; switch (ring->type) { case CARBON: for (i = 0; i < ring->hash_replicas; i++) { /* this format is actually Python's tuple format that is * used in serialised form as input for the hash */ snprintf(buf, sizeof(buf), "('%s', %s%s%s):%d", server_ip(s), instance == NULL ? "" : "'", instance == NULL ? "None" : instance, instance == NULL ? "" : "'", i); /* carbon upstream committed: * https://github.com/graphite-project/carbon/commit/024f9e67ca47619438951c59154c0dec0b0518c7 * this makes sure no collissions exist on pos, however, * at the expense of being agnostic to the input order, * therefore that change isn't implemented here, see * https://github.com/grobian/carbon-c-relay/issues/84 */ entries[i].pos = carbon_hashpos(buf, buf + strlen(buf)); entries[i].server = s; } cmp = *entrycmp_carbon; break; case FNV1a: for (i = 0; i < ring->hash_replicas; i++) { /* take all server info into account, such that * different port numbers for the same hosts will work * (unlike CARBON), unless we got a full overrride */ if (instance == NULL) { snprintf(buf, sizeof(buf), "%d-%s:%u", i, server_ip(s), server_port(s)); } else { snprintf(buf, sizeof(buf), "%d-%s", i, instance); } entries[i].pos = fnv1a_hashpos(buf, buf + strlen(buf)); entries[i].server = s; } cmp = *entrycmp_fnv1a; break; case JUMP_FNV1a: entries[0].pos = ring->entrycnt; entries[0].server = s; cmp = *entrycmp_jump_fnv1a; break; } ring->entrycnt += ring->hash_replicas; if (ring->entrycnt == ring->entrysize) { qsort(&ring->entrylist[0], ring->entrycnt, sizeof(ch_ring_entry), cmp); /* overwrite successive duplicates with the first entry to ensure * our binary search hits the "first" matching entry */ for (i = 0; i < ring->entrycnt - 1; i++) { if (ring->entrylist[i].pos == ring->entrylist[i + 1].pos) ring->entrylist[i + 1].server = ring->entrylist[i].server; } } return ring; } /** * Retrieve the nodes responsible for storing the given metric. The * replcnt argument specifies how many hosts should be retrieved. * Results are stored in ret, an array of ch_ring pointers. The * caller is responsible for ensuring that ret is large enough to store * replcnt pointers. */ void ch_get_nodes( destination ret[], ch_ring *ring, const char replcnt, const char *metric, const char *firstspace) { unsigned short pos = 0; int i, j, t; switch (ring->type) { case CARBON: pos = carbon_hashpos(metric, firstspace); break; case FNV1a: pos = fnv1a_hashpos(metric, firstspace); break; case JUMP_FNV1a: { /* this is really a short route, since the jump hash gives * us a bucket immediately */ unsigned long long int hash; server *bcklst[CONN_DESTS_SIZE]; const char *p; pos = replcnt; /* we know this fits, since ch_new checks i <= CONN_DESTS_SIZE */ for (i = 0; i < ring->entrycnt; i++) bcklst[i] = ring->entrylist[i].server; fnv1a_64(hash, p, metric, firstspace); while (i > 0) { j = jump_bucketpos(hash, i); (*ret).dest = bcklst[j]; ret++; if (--pos == 0) break; /* use xorshift to generate a different hash for input * in the jump hash again */ hash ^= hash >> 12; hash ^= hash << 25; hash ^= hash >> 27; hash *= 2685821657736338717ULL; /* remove the server we just selected, such that we can * be sure the next iteration will fetch another server */ bcklst[j] = bcklst[--i]; } } return; } assert(ring->entrylist); /* binary search for first entry.pos >= pos */ i = 0; j = ring->entrycnt; t = 0; /* 1 3 4 6 6 8 8 9 */ while (1) { t = (i + j) / 2; if (ring->entrylist[t].pos == pos) break; /* exact match */ if (ring->entrylist[t].pos < pos) { i = t; /* left is smaller, search right */ if (i == j - 1) { if (ring->entrylist[j].pos < pos) { t = j + 1; break; /* right pos is smaller than the value */ } else { t = j; break; /* right pos is the first bigger value */ } } } else { j = t; /* right is bigger, search left */ if (i == j - 1) { if (ring->entrylist[i].pos >= pos) { t = i; break; /* left pos is the first bigger than value */ } else { t = j; break; /* right pos is the first bigger value */ } } } } /* now fetch enough unique servers to match the requested count */ for (i = 0; i < replcnt; i++, t++) { if (t >= ring->entrycnt) t = 0; for (j = i - 1; j >= 0; j--) { if (ret[j].dest == ring->entrylist[t].server) { j = i; break; } } if (j == i) { i--; continue; } ret[i].dest = ring->entrylist[t].server; } } void ch_printhashring(ch_ring *ring, FILE *f) { ch_ring_entry *w; char column = 0; char srvbuf[21]; int i; for (i = 0; i < ring->entrycnt; i++) { w = &ring->entrylist[i]; snprintf(srvbuf, sizeof(srvbuf), "%s:%d%s%s", server_ip(w->server), server_port(w->server), server_instance(w->server) ? "=" : "", server_instance(w->server) ? server_instance(w->server) : ""); fprintf(f, "%5d@%-20s", w->pos, srvbuf); if (column < 2) { fprintf(f, " "); column++; } else { fprintf(f, "\n"); column = 0; } } if (column != 0) fprintf(f, "\n"); } unsigned short ch_gethashpos(ch_ring *ring, const char *key, const char *end) { switch (ring->type) { case CARBON: return carbon_hashpos(key, end); case FNV1a: return fnv1a_hashpos(key, end); case JUMP_FNV1a: { unsigned long long int hash; fnv1a_64(hash, key, key, end); return jump_bucketpos(hash, ring->entrycnt); } default: assert(0); /* this shouldn't happen */ } return 0; /* pacify compiler */ } carbon-c-relay-3.2/consistent-hash.h000066400000000000000000000023221317265605500174500ustar00rootroot00000000000000/* * Copyright 2013-2017 Fabian Groffen * * 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. */ #ifndef CONSISTENT_HASH_H #define CONSISTENT_HASH_H 1 #include #include "server.h" #include "router.h" #include "allocator.h" #ifndef CH_RING #define CH_RING void #endif typedef CH_RING ch_ring; typedef enum { CARBON, FNV1a, JUMP_FNV1a } ch_type; ch_ring *ch_new(allocator *a, ch_type type, int srvcnt); ch_ring *ch_addnode(ch_ring *ring, server *s); void ch_get_nodes( destination ret[], ch_ring *ring, const char replcnt, const char *metric, const char *firstspace); void ch_printhashring(ch_ring *ring, FILE *out); unsigned short ch_gethashpos(ch_ring *ring, const char *key, const char *end); #endif carbon-c-relay-3.2/contrib/000077500000000000000000000000001317265605500156265ustar00rootroot00000000000000carbon-c-relay-3.2/contrib/relay.logrotate000066400000000000000000000004341317265605500206650ustar00rootroot00000000000000# not installed by default as logrotate is used to manage all carbon log files. /var/log/%%NAME%%/%%NAME%%.log { sharedscripts missingok notifempty rotate 30 compress postrotate [ ! -f /var/run/%%NAME%%/%%NAME%%.pid ] || /etc/init.d/%%NAME%% restart endscript } carbon-c-relay-3.2/contrib/relay.monit000066400000000000000000000004621317265605500200140ustar00rootroot00000000000000# Monit script to ensure carbon c relay is always running check process %%NAME%% with pidfile /var/run/%%NAME%%/%%NAME%%.pid start program = "/etc/init.d/%%NAME%% start" stop program = "/etc/init.d/%%NAME%% stop" if failed port 2003 type tcp then restart if 5 restarts within 5 cycles then timeout carbon-c-relay-3.2/depcomp000077500000000000000000000560161317265605500155530ustar00rootroot00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2013-05-30.07; # UTC # Copyright (C) 1999-2014 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz digits=0123456789 alpha=${upper}${lower} if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interferences from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The second -e expression handles DOS-style file names with drive # letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E \ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: carbon-c-relay-3.2/dispatcher.c000066400000000000000000000761061317265605500164720ustar00rootroot00000000000000/* * Copyright 2013-2017 Fabian Groffen * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "relay.h" #include "router.h" #include "server.h" #include "collector.h" #include "dispatcher.h" #ifdef HAVE_GZIP #include #endif #ifdef HAVE_LZ4 #include #endif #ifdef HAVE_SSL #include #endif enum conntype { LISTENER, CONNECTION }; typedef struct _connection { int sock; void *strm; ssize_t (*strmread)(void *, void *, size_t); /* read func */ int (*strmclose)(void *); char takenby; /* -2: being setup, -1: free, 0: not taken, >0: tid */ char srcaddr[24]; /* string representation of source address */ char buf[METRIC_BUFSIZ]; int buflen; char needmore:1; char noexpire:1; char metric[METRIC_BUFSIZ]; destination dests[CONN_DESTS_SIZE]; size_t destlen; struct timeval lastwork; unsigned int maxsenddelay; char hadwork:1; char isaggr:1; char isudp:1; } connection; typedef struct _z_strm { int sock; union { #ifdef HAVE_GZIP z_stream z; #endif #ifdef HAVE_LZ4 LZ4_streamDecode_t *lz; #endif char dummy; } hdl; char ibuf[METRIC_BUFSIZ]; unsigned short ipos; } z_strm; struct _dispatcher { pthread_t tid; enum conntype type; char id; size_t metrics; size_t blackholes; size_t ticks; size_t sleeps; size_t prevmetrics; size_t prevblackholes; size_t prevticks; size_t prevsleeps; char keep_running; /* full byte for atomic access */ router *rtr; router *pending_rtr; char route_refresh_pending; /* full byte for atomic access */ char hold; /* full byte for atomic access */ char *allowed_chars; }; static listener **listeners = NULL; static connection *connections = NULL; static size_t connectionslen = 0; pthread_rwlock_t listenerslock = PTHREAD_RWLOCK_INITIALIZER; pthread_rwlock_t connectionslock = PTHREAD_RWLOCK_INITIALIZER; static size_t acceptedconnections = 0; static size_t closedconnections = 0; static unsigned int sockbufsize = 0; /* connection specific readers and closers */ /* ordinary socket */ static inline ssize_t sockread(void *strm, void *buf, size_t sze) { return read(*((int *)strm), buf, sze); } static inline int sockclose(void *strm) { int ret = close(*((int *)strm)); free(strm); return ret; } #ifdef HAVE_GZIP /* gzip wrapped socket */ static inline ssize_t gzipread(void *strm, void *buf, size_t sze) { z_stream *zstrm = &(((z_strm *)strm)->hdl.z); char *ibuf = ((z_strm *)strm)->ibuf; int ret; int iret; int err = 0; /* read any available data, if it fits */ ret = read(((z_strm *)strm)->sock, ibuf + ((z_strm *)strm)->ipos, METRIC_BUFSIZ - ((z_strm *)strm)->ipos); if (ret > 0) { ((z_strm *)strm)->ipos += ret; } else if (ret < 0) { err = errno; } zstrm->next_in = (Bytef *)ibuf; zstrm->avail_in = (uInt)(((z_strm *)strm)->ipos); zstrm->next_out = (Bytef *)buf; zstrm->avail_out = (uInt)sze; iret = inflate(zstrm, Z_SYNC_FLUSH); /* if deflate read something, update our ibuf */ if ((Bytef *)ibuf != zstrm->next_in) { memmove(ibuf, zstrm->next_in, zstrm->avail_in); ((z_strm *)strm)->ipos = zstrm->avail_in; } switch (iret) { case Z_OK: /* progress has been made */ /* calculate the "returned" bytes */ iret = sze - zstrm->avail_out; if (iret == 0) { /* something was done, so must have been reading input */ errno = EAGAIN; return -1; } break; case Z_STREAM_END: /* everything uncompressed, nothing pending */ iret = sze - zstrm->avail_out; break; case Z_DATA_ERROR: /* corrupt input */ inflateSync(zstrm); /* return isn't much of interest, we will call inflate next * time and sync again if it still fails */ errno = err ? err : EAGAIN; return -1; break; case Z_MEM_ERROR: /* out of memory */ logerr("out of memory during read of gzip stream\n"); errno = ENOMEM; return -1; case Z_BUF_ERROR: /* output buffer full or nothing to read */ /* if this happens, zlib still can't write even though last * call should have increased the buffer size by consuming * whatever was valid, so if we're stuck here, the situation * isn't going to improve, and we better bail out */ errno = err ? err : EMSGSIZE; return -1; } if (iret == 0 && ret != 0) { errno = EAGAIN; iret = -1; } return (ssize_t)iret; } static inline int gzipclose(void *strm) { int ret = close(((z_strm *)strm)->sock); inflateEnd(&(((z_strm *)strm)->hdl.z)); free(strm); return ret; } #endif #ifdef HAVE_LZ4 /* lz4 wrapped socket */ static inline ssize_t lzread(void *strm, void *buf, size_t sze) { char *ibuf = ((z_strm *)strm)->ibuf; int ret; /* read any available data, if it fits */ ret = read(((z_strm *)strm)->sock, ibuf + ((z_strm *)strm)->ipos, METRIC_BUFSIZ - ((z_strm *)strm)->ipos); if (ret > 0) { ((z_strm *)strm)->ipos += ret; } else if (ret < 0) { return -1; } ret = LZ4_decompress_safe_continue(((z_strm *)strm)->hdl.lz, ibuf, buf, ((z_strm *)strm)->ipos, sze); /* if we decompressed something, update our ibuf */ if (ret > 0) { ((z_strm *)strm)->ipos = ((z_strm *)strm)->ipos - ret; memmove(ibuf, ibuf + ret, ((z_strm *)strm)->ipos); } return (ssize_t)ret; } static inline int lzclose(void *strm) { int ret = LZ4_freeStreamDecode(((z_strm *)strm)->hdl.lz); free(strm); return ret; } #endif #ifdef HAVE_SSL /* (Open|Libre)SSL wrapped socket */ static inline ssize_t sslread(void *strm, void *buf, size_t sze) { return (ssize_t)SSL_read((SSL *)strm, buf, (int)sze); } static inline int sslclose(void *strm) { int sock = SSL_get_fd((SSL *)strm); SSL_free((SSL *)strm); return close(sock); } #endif /** * Helper function to try and be helpful to the user. If errno * indicates no new fds could be made, checks what the current max open * files limit is, and if it's close to what we have in use now, write * an informative message to stderr. */ void dispatch_check_rlimit_and_warn(void) { if (errno == EISCONN || errno == EMFILE) { struct rlimit ofiles; /* rlimit can be changed for the running process (at least on * Linux 2.6+) so refetch this value every time, should only * occur on errors anyway */ if (getrlimit(RLIMIT_NOFILE, &ofiles) < 0) ofiles.rlim_max = 0; if (ofiles.rlim_max != RLIM_INFINITY && ofiles.rlim_max > 0) logerr("process configured maximum connections = %d, " "consider raising max open files/max descriptor limit\n", (int)ofiles.rlim_max); } } #define MAX_LISTENERS 32 /* hopefully enough */ /** * Adds an (initial) listener socket to the chain of connections. * Listener sockets are those which need to be accept()-ed on. */ int dispatch_addlistener(listener *lsnr) { int c; int *socks; if (lsnr->ctype == CON_UDP) { /* Adds a pseudo-listener for datagram (UDP) sockets, which is * pseudo, for in fact it adds a new connection, but makes sure * that connection won't be closed after being idle, and won't * count that connection as an incoming connection either. */ for (socks = lsnr->socks; *socks != -1; socks++) { c = dispatch_addconnection(*socks, lsnr); if (c == -1) return 1; connections[c].noexpire = 1; connections[c].isudp = 1; acceptedconnections--; } return 0; } pthread_rwlock_wrlock(&listenerslock); for (c = 0; c < MAX_LISTENERS; c++) { if (listeners[c] == NULL) { listeners[c] = lsnr; for (socks = lsnr->socks; *socks != -1; socks++) (void) fcntl(*socks, F_SETFL, O_NONBLOCK); break; } } if (c == MAX_LISTENERS) { logerr("cannot add new listener: " "no more free listener slots (max = %zu)\n", MAX_LISTENERS); pthread_rwlock_unlock(&listenerslock); return 1; } pthread_rwlock_unlock(&listenerslock); return 0; } /** * Remove listener from the listeners list. Each removal will incur a * global lock. Frequent usage of this function is not anticipated. */ void dispatch_removelistener(listener *lsnr) { int c; int *socks; if (lsnr->ctype != CON_UDP) { pthread_rwlock_wrlock(&listenerslock); /* find connection */ for (c = 0; c < MAX_LISTENERS; c++) if (listeners[c] != NULL && listeners[c] == lsnr) break; if (c == MAX_LISTENERS) { /* not found?!? */ logerr("dispatch: cannot find listener to remove!\n"); pthread_rwlock_unlock(&listenerslock); return; } listeners[c] = NULL; pthread_rwlock_unlock(&listenerslock); } /* cleanup */ #ifdef HAVE_SSL if (lsnr->transport == W_SSL) SSL_CTX_free(lsnr->ctx); #endif /* acquire a write lock on connections, which is a bit wrong, but it * ensures all dispatchers are stopped while we close the sockets, * which avoids a race on the reading thereof if this is a UDP * connection */ pthread_rwlock_wrlock(&connectionslock); for (socks = lsnr->socks; *socks != -1; socks++) { close(*socks); *socks = -1; } pthread_rwlock_unlock(&connectionslock); if (lsnr->saddrs) freeaddrinfo(lsnr->saddrs); } /** * Copy over all state related things from olsnr to nlsnr and ensure * olsnr can be discarded (that is, thrown away without calling * dispatch_removelistener). */ void dispatch_transplantlistener(listener *olsnr, listener *nlsnr, router *r) { int c; pthread_rwlock_wrlock(&listenerslock); for (c = 0; c < MAX_LISTENERS; c++) { if (listeners[c] == olsnr) { router_transplant_listener_socks(r, olsnr, nlsnr); #ifdef HAVE_SSL if (nlsnr->transport == W_SSL) nlsnr->ctx = olsnr->ctx; #endif if (olsnr->saddrs) { freeaddrinfo(olsnr->saddrs); olsnr->saddrs = NULL; } listeners[c] = nlsnr; break; /* found and done */ } } } #define CONNGROWSZ 1024 /** * Adds a connection socket to the chain of connections. * Connection sockets are those which need to be read from. * Returns the connection id, or -1 if a failure occurred. */ int dispatch_addconnection(int sock, listener *lsnr) { size_t c; struct sockaddr_in6 saddr; socklen_t saddr_len = sizeof(saddr); pthread_rwlock_rdlock(&connectionslock); for (c = 0; c < connectionslen; c++) if (__sync_bool_compare_and_swap(&(connections[c].takenby), -1, -2)) break; pthread_rwlock_unlock(&connectionslock); if (c == connectionslen) { connection *newlst; pthread_rwlock_wrlock(&connectionslock); if (connectionslen > c) { /* another dispatcher just extended the list */ pthread_rwlock_unlock(&connectionslock); return dispatch_addconnection(sock, lsnr); } newlst = realloc(connections, sizeof(connection) * (connectionslen + CONNGROWSZ)); if (newlst == NULL) { logerr("cannot add new connection: " "out of memory allocating more slots (max = %zu)\n", connectionslen); pthread_rwlock_unlock(&connectionslock); return -1; } for (c = connectionslen; c < connectionslen + CONNGROWSZ; c++) { memset(&newlst[c], '\0', sizeof(connection)); newlst[c].takenby = -1; /* free */ } connections = newlst; c = connectionslen; /* for the setup code below */ newlst[c].takenby = -2; connectionslen += CONNGROWSZ; pthread_rwlock_unlock(&connectionslock); } /* figure out who's calling */ if (getpeername(sock, (struct sockaddr *)&saddr, &saddr_len) == 0) { snprintf(connections[c].srcaddr, sizeof(connections[c].srcaddr), "(unknown)"); switch (saddr.sin6_family) { case PF_INET: inet_ntop(saddr.sin6_family, &((struct sockaddr_in *)&saddr)->sin_addr, connections[c].srcaddr, sizeof(connections[c].srcaddr)); break; case PF_INET6: inet_ntop(saddr.sin6_family, &saddr.sin6_addr, connections[c].srcaddr, sizeof(connections[c].srcaddr)); break; } } (void) fcntl(sock, F_SETFL, O_NONBLOCK); if (sockbufsize > 0) { if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &sockbufsize, sizeof(sockbufsize)) != 0) ; } connections[c].sock = sock; if (lsnr == NULL || lsnr->transport == W_PLAIN) { int *strm = malloc(sizeof(connections[c].sock)); if (strm == NULL) { logerr("cannot add new connection: " "out of memory allocating stream\n"); __sync_bool_compare_and_swap(&(connections[c].takenby), -2, -1); return -1; } *strm = sock; connections[c].strm = strm; connections[c].strmread = &sockread; connections[c].strmclose = &sockclose; } #ifdef HAVE_GZIP else if (lsnr->transport == W_GZIP) { z_strm *zstrm = malloc(sizeof(z_strm)); if (zstrm == NULL) { logerr("cannot add new connection: " "out of memory allocating gzip stream\n"); __sync_bool_compare_and_swap(&(connections[c].takenby), -2, -1); return -1; } zstrm->hdl.z.zalloc = Z_NULL; zstrm->hdl.z.zfree = Z_NULL; zstrm->hdl.z.opaque = Z_NULL; zstrm->ipos = 0; zstrm->sock = sock; inflateInit2(&(zstrm->hdl.z), 15 + 16); connections[c].strm = zstrm; connections[c].strmread = &gzipread; connections[c].strmclose = &gzipclose; } #endif #ifdef HAVE_LZ4 else if (lsnr->transport == W_LZ4) { z_strm *lzstrm = malloc(sizeof(z_strm)); if (lzstrm == NULL) { logerr("cannot add new connection: " "out of memory allocating lz4 stream\n"); __sync_bool_compare_and_swap(&(connections[c].takenby), -2, -1); return -1; } lzstrm->sock = sock; lzstrm->hdl.lz = LZ4_createStreamDecode(); connections[c].strm = lzstrm; connections[c].strmread = &lzread; connections[c].strmclose = &lzclose; } #endif #ifdef HAVE_SSL else if (lsnr->transport == W_SSL) { connections[c].strm = SSL_new(lsnr->ctx); SSL_set_fd(connections[c].strm, sock); SSL_set_accept_state(connections[c].strm); connections[c].strmread = &sslread; connections[c].strmclose = &sslclose; } #endif connections[c].buflen = 0; connections[c].needmore = 0; connections[c].noexpire = 0; connections[c].isaggr = 0; connections[c].isudp = 0; connections[c].destlen = 0; gettimeofday(&connections[c].lastwork, NULL); connections[c].hadwork = 1; /* force first iteration before stalling */ /* after this dispatchers will pick this connection up */ __sync_bool_compare_and_swap(&(connections[c].takenby), -2, 0); __sync_add_and_fetch(&acceptedconnections, 1); return c; } /** * Adds a connection which we know is from an aggregator, so direct * pipe. This is different from normal connections that we don't want * to count them, never expire them, and want to recognise them when * we're doing reloads. */ int dispatch_addconnection_aggr(int sock) { int conn = dispatch_addconnection(sock, NULL); if (conn == -1) return 1; connections[conn].noexpire = 1; connections[conn].isaggr = 1; acceptedconnections--; return 0; } inline static char dispatch_process_dests(connection *conn, dispatcher *self, struct timeval now) { int i; char force; if (conn->destlen > 0) { if (conn->maxsenddelay == 0) conn->maxsenddelay = ((rand() % 750) + 250) * 1000; /* force when aggr (don't stall it) or after timeout */ force = conn->isaggr ? 1 : timediff(conn->lastwork, now) > conn->maxsenddelay; for (i = 0; i < conn->destlen; i++) { tracef("dispatcher %d, connfd %d, metric %s, queueing to %s:%d\n", self->id, conn->sock, conn->dests[i].metric, server_ip(conn->dests[i].dest), server_port(conn->dests[i].dest)); if (server_send(conn->dests[i].dest, conn->dests[i].metric, force) == 0) break; } if (i < conn->destlen) { conn->destlen -= i; memmove(&conn->dests[0], &conn->dests[i], (sizeof(destination) * conn->destlen)); return 0; } else { /* finally "complete" this metric */ conn->destlen = 0; conn->lastwork = now; conn->hadwork = 1; } } return 1; } #define IDLE_DISCONNECT_TIME (10 * 60 * 1000 * 1000) /* 10 minutes */ /** * Look at conn and see if works needs to be done. If so, do it. This * function operates on an (exclusive) lock on the connection it serves. * Schematically, what this function does is like this: * * read (partial) data <---- * | | * v | * split and clean metrics | * | | * v | * route metrics | feedback loop * | | (stall client) * v | * send 1st attempt | * \ | * v* | * this is optional, but if a server's * retry send (<1s) -------- queue is full, the client is stalled * block reads */ static int dispatch_connection(connection *conn, dispatcher *self, struct timeval start) { char *p, *q, *firstspace, *lastnl; int len; /* first try to resume any work being blocked */ if (dispatch_process_dests(conn, self, start) == 0) { __sync_bool_compare_and_swap(&(conn->takenby), self->id, 0); return 0; } /* don't poll (read) when the last time we ran nothing happened, * this is to avoid excessive CPU usage, issue #126 */ if (!conn->hadwork && timediff(conn->lastwork, start) < 100 * 1000) { __sync_bool_compare_and_swap(&(conn->takenby), self->id, 0); return 0; } conn->hadwork = 0; len = -2; /* try to read more data, if that succeeds, or we still have data * left in the buffer, try to process the buffer */ if ( (!conn->needmore && conn->buflen > 0) || (len = conn->strmread(conn->strm, conn->buf + conn->buflen, (sizeof(conn->buf) - 1) - conn->buflen)) > 0 ) { if (len > 0) { conn->buflen += len; tracef("dispatcher %d, connfd %d, read %d bytes from socket\n", self->id, conn->sock, len); #ifdef ENABLE_TRACE conn->buf[conn->buflen] = '\0'; #endif } /* metrics look like this: metric_path value timestamp\n * due to various messups we need to sanitise the * metrics_path here, to ensure we can calculate the metric * name off the filesystem path (and actually retrieve it in * the web interface). */ q = conn->metric; firstspace = NULL; lastnl = NULL; for (p = conn->buf; p - conn->buf < conn->buflen; p++) { if (*p == '\n' || *p == '\r') { /* end of metric */ lastnl = p; /* just a newline on it's own? some random garbage? skip */ if (q == conn->metric || firstspace == NULL) { q = conn->metric; firstspace = NULL; continue; } __sync_add_and_fetch(&(self->metrics), 1); /* add newline and terminate the string, we can do this * because we substract one from buf and we always store * a full metric in buf before we copy it to metric * (which is of the same size) */ *q++ = '\n'; *q = '\0'; /* perform routing of this metric */ tracef("dispatcher %d, connfd %d, metric %s", self->id, conn->sock, conn->metric); __sync_add_and_fetch(&(self->blackholes), router_route(self->rtr, conn->dests, &conn->destlen, CONN_DESTS_SIZE, conn->srcaddr, conn->metric, firstspace, self->id - 1)); tracef("dispatcher %d, connfd %d, destinations %zd\n", self->id, conn->sock, conn->destlen); /* restart building new one from the start */ q = conn->metric; firstspace = NULL; conn->hadwork = 1; gettimeofday(&conn->lastwork, NULL); conn->maxsenddelay = 0; /* send the metric to where it is supposed to go */ if (dispatch_process_dests(conn, self, conn->lastwork) == 0) break; } else if (*p == ' ' || *p == '\t' || *p == '.') { /* separator */ if (q == conn->metric) { /* make sure we skip this on next iteration to * avoid an infinite loop, issues #8 and #51 */ lastnl = p; continue; } if (*p == '\t') *p = ' '; if (*p == ' ' && firstspace == NULL) { if (*(q - 1) == '.') q--; /* strip trailing separator */ firstspace = q; *q++ = ' '; } else { /* metric_path separator or space, * - duplicate elimination * - don't start with separator/space */ if (*(q - 1) != *p && (q - 1) != firstspace) *q++ = *p; } } else if ( *p != '\0' && ( firstspace != NULL || (*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || strchr(self->allowed_chars, *p) ) ) { /* copy char */ *q++ = *p; } else { /* something barf, replace by underscore */ *q++ = '_'; } } conn->needmore = q != conn->metric; if (lastnl != NULL) { /* move remaining stuff to the front */ conn->buflen -= lastnl + 1 - conn->buf; tracef("dispatcher %d, conn->buf: %p, lastnl: %p, diff: %zd, " "conn->buflen: %d, sizeof(conn->buf): %lu, " "memmove(%d, %lu, %d)\n", self->id, conn->buf, lastnl, lastnl - conn->buf, conn->buflen, sizeof(conn->buf), 0, lastnl + 1 - conn->buf, conn->buflen + 1); tracef("dispatcher %d, pre conn->buf: %s\n", self->id, conn->buf); /* copy last NULL-byte for debug tracing */ memmove(conn->buf, lastnl + 1, conn->buflen + 1); tracef("dispatcher %d, post conn->buf: %s\n", self->id, conn->buf); lastnl = NULL; } } if (len == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) { /* nothing available/no work done */ struct timeval stop; gettimeofday(&stop, NULL); if (!conn->noexpire && timediff(conn->lastwork, stop) > IDLE_DISCONNECT_TIME) { /* force close connection below */ len = 0; } else { __sync_bool_compare_and_swap(&(conn->takenby), self->id, 0); return 0; } } if (len == -1 || len == 0 || conn->isudp) { /* error + EOF */ /* we also disconnect the client in this case if our reading * buffer is full, but we still need more (read returns 0 if the * size argument is 0) -> this is good, because we can't do much * with such client */ if (conn->noexpire) { /* reset buffer only (UDP/aggregations) and move on */ conn->needmore = 1; conn->buflen = 0; __sync_bool_compare_and_swap(&(conn->takenby), self->id, 0); return len > 0; } else if (conn->destlen == 0) { tracef("dispatcher: %d, connfd: %d, len: %d [%s], disconnecting\n", self->id, conn->sock, len, len < 0 ? strerror(errno) : ""); __sync_add_and_fetch(&closedconnections, 1); conn->strmclose(conn->strm); /* flag this connection as no longer in use, unless there is * pending metrics to send */ __sync_bool_compare_and_swap(&(conn->takenby), self->id, -1); return 0; } } /* "release" this connection again */ __sync_bool_compare_and_swap(&(conn->takenby), self->id, 0); return 1; } /** * pthread compatible routine that handles connections and processes * whatever comes in on those. */ static void * dispatch_runner(void *arg) { dispatcher *self = (dispatcher *)arg; connection *conn; int c; if (self->type == LISTENER) { struct pollfd ufds[MAX_LISTENERS]; int fds; int *sock; while (__sync_bool_compare_and_swap(&(self->keep_running), 1, 1)) { pthread_rwlock_rdlock(&listenerslock); fds = 0; for (c = 0; c < MAX_LISTENERS; c++) { if (listeners[c] == NULL) continue; for (sock = listeners[c]->socks; *sock != -1; sock++) { ufds[fds].fd = *sock; ufds[fds].events = POLLIN; fds++; } } pthread_rwlock_unlock(&listenerslock); if (poll(ufds, fds, 1000) > 0) { int f; for (f = fds - 1; f >= 0; f--) { if (ufds[f].revents & POLLIN) { int client; struct sockaddr addr; socklen_t addrlen = sizeof(addr); if ((client = accept(ufds[f].fd, &addr, &addrlen)) < 0) { logerr("dispatch: failed to " "accept() new connection: %s\n", strerror(errno)); dispatch_check_rlimit_and_warn(); continue; } pthread_rwlock_rdlock(&listenerslock); for (c = 0; c < MAX_LISTENERS; c++) { if (listeners[c] == NULL) continue; for (sock = listeners[c]->socks; *sock != -1; sock++) { if (ufds[f].fd == *sock) break; } if (*sock != -1) break; } pthread_rwlock_unlock(&listenerslock); if (c == MAX_LISTENERS) { logerr("dispatch: could not find listener for " "socket, rejecting connection\n"); close(client); continue; } if (dispatch_addconnection(client, listeners[c]) == -1) { close(client); continue; } } } } } } else if (self->type == CONNECTION) { int work; struct timeval start, stop; while (__sync_bool_compare_and_swap(&(self->keep_running), 1, 1)) { work = 0; if (__sync_bool_compare_and_swap(&(self->route_refresh_pending), 1, 1)) { self->rtr = self->pending_rtr; self->pending_rtr = NULL; __sync_bool_compare_and_swap(&(self->route_refresh_pending), 1, 0); __sync_and_and_fetch(&(self->hold), 0); } gettimeofday(&start, NULL); pthread_rwlock_rdlock(&connectionslock); for (c = 0; c < connectionslen; c++) { conn = &(connections[c]); /* atomically try to "claim" this connection */ if (!__sync_bool_compare_and_swap( &(conn->takenby), 0, self->id)) continue; if (__sync_bool_compare_and_swap( &(self->hold), 1, 1) && !conn->isaggr) { __sync_bool_compare_and_swap( &(conn->takenby), self->id, 0); continue; } work += dispatch_connection(conn, self, start); } pthread_rwlock_unlock(&connectionslock); gettimeofday(&stop, NULL); __sync_add_and_fetch(&(self->ticks), timediff(start, stop)); /* nothing done, avoid spinlocking */ if (__sync_bool_compare_and_swap(&(self->keep_running), 1, 1) && work == 0) { gettimeofday(&start, NULL); usleep((100 + (rand() % 200)) * 1000); /* 100ms - 300ms */ gettimeofday(&stop, NULL); __sync_add_and_fetch(&(self->sleeps), timediff(start, stop)); } } } else { logerr("huh? unknown self type!\n"); } return NULL; } /** * Starts a new dispatcher for the given type and with the given id. * Returns its handle. */ static dispatcher * dispatch_new( unsigned char id, enum conntype type, router *r, char *allowed_chars ) { dispatcher *ret = malloc(sizeof(dispatcher)); if (ret == NULL) return NULL; if (type == CONNECTION && r == NULL) { free(ret); return NULL; } ret->id = id + 1; /* ensure > 0 */ ret->type = type; ret->keep_running = 1; ret->rtr = r; ret->route_refresh_pending = 0; ret->hold = 0; ret->allowed_chars = allowed_chars; ret->metrics = 0; ret->blackholes = 0; ret->ticks = 0; ret->sleeps = 0; ret->prevmetrics = 0; ret->prevblackholes = 0; ret->prevticks = 0; ret->prevsleeps = 0; if (pthread_create(&ret->tid, NULL, dispatch_runner, ret) != 0) { free(ret); return NULL; } return ret; } void dispatch_set_bufsize(unsigned int nsockbufsize) { sockbufsize = nsockbufsize; } /** * Initialise the listeners array. This is a one-time allocation that * currently never is extended. This code does no locking, as it * assumes to be run before any access to listeners occur. */ char dispatch_init_listeners() { int i; /* once all-or-nothing allocation */ if ((listeners = malloc(sizeof(listener *) * MAX_LISTENERS)) == NULL) return 1; for (i = 0; i < MAX_LISTENERS; i++) listeners[i] = NULL; return 0; } /** * Starts a new dispatcher specialised in handling incoming connections * (and putting them on the queue for handling the connections). */ dispatcher * dispatch_new_listener(unsigned char id) { return dispatch_new(id, LISTENER, NULL, NULL); } /** * Starts a new dispatcher specialised in handling incoming data on * existing connections. */ dispatcher * dispatch_new_connection(unsigned char id, router *r, char *allowed_chars) { return dispatch_new(id, CONNECTION, r, allowed_chars); } /** * Signals this dispatcher to stop whatever it's doing. */ void dispatch_stop(dispatcher *d) { __sync_bool_compare_and_swap(&(d->keep_running), 1, 0); } /** * Shuts down dispatcher d. Returns when the dispatcher has terminated. */ void dispatch_shutdown(dispatcher *d) { dispatch_stop(d); pthread_join(d->tid, NULL); } /** * Free up resources taken by dispatcher d. The caller should make sure * the dispatcher has been shut down at this point. */ void dispatch_free(dispatcher *d) { free(d); } /** * Requests this dispatcher to stop processing connections. As soon as * schedulereload finishes reloading the routes, this dispatcher will * un-hold and continue processing connections. * Returns when the dispatcher is no longer doing work. */ inline void dispatch_hold(dispatcher *d) { __sync_bool_compare_and_swap(&(d->hold), 0, 1); } /** * Schedules routes r to be put in place for the current routes. The * replacement is performed at the next cycle of the dispatcher. */ inline void dispatch_schedulereload(dispatcher *d, router *r) { d->pending_rtr = r; __sync_bool_compare_and_swap(&(d->route_refresh_pending), 0, 1); } /** * Returns true if the routes scheduled to be reloaded by a call to * dispatch_schedulereload() have been activated. */ inline char dispatch_reloadcomplete(dispatcher *d) { return __sync_bool_compare_and_swap(&(d->route_refresh_pending), 0, 0); } /** * Returns the wall-clock time in milliseconds consumed by this dispatcher. */ inline size_t dispatch_get_ticks(dispatcher *self) { return __sync_add_and_fetch(&(self->ticks), 0); } /** * Returns the wall-clock time consumed since last call to this * function. */ inline size_t dispatch_get_ticks_sub(dispatcher *self) { size_t d = dispatch_get_ticks(self) - self->prevticks; self->prevticks += d; return d; } /** * Returns the wall-clock time in milliseconds consumed while sleeping * by this dispatcher. */ inline size_t dispatch_get_sleeps(dispatcher *self) { return __sync_add_and_fetch(&(self->sleeps), 0); } /** * Returns the wall-clock time consumed while sleeping since last call * to this function. */ inline size_t dispatch_get_sleeps_sub(dispatcher *self) { size_t d = dispatch_get_sleeps(self) - self->prevsleeps; self->prevsleeps += d; return d; } /** * Returns the number of metrics dispatched since start. */ inline size_t dispatch_get_metrics(dispatcher *self) { return __sync_add_and_fetch(&(self->metrics), 0); } /** * Returns the number of metrics dispatched since last call to this * function. */ inline size_t dispatch_get_metrics_sub(dispatcher *self) { size_t d = dispatch_get_metrics(self) - self->prevmetrics; self->prevmetrics += d; return d; } /** * Returns the number of metrics that were explicitly or implicitly * blackholed since start. */ inline size_t dispatch_get_blackholes(dispatcher *self) { return __sync_add_and_fetch(&(self->blackholes), 0); } /** * Returns the number of metrics that were blackholed since last call to * this function. */ inline size_t dispatch_get_blackholes_sub(dispatcher *self) { size_t d = dispatch_get_blackholes(self) - self->prevblackholes; self->prevblackholes += d; return d; } /** * Returns the number of accepted connections thusfar. */ inline size_t dispatch_get_accepted_connections(void) { return __sync_add_and_fetch(&(acceptedconnections), 0); } /** * Returns the number of closed connections thusfar. */ inline size_t dispatch_get_closed_connections(void) { return __sync_add_and_fetch(&(closedconnections), 0); } carbon-c-relay-3.2/dispatcher.h000066400000000000000000000037301317265605500164700ustar00rootroot00000000000000/* * Copyright 2013-2017 Fabian Groffen * * 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. */ #ifndef DISPATCHER_H #define DISPATCHER_H 1 #include #include "router.h" typedef struct _dispatcher dispatcher; void dispatch_check_rlimit_and_warn(void); int dispatch_addlistener(listener *lsnr); void dispatch_removelistener(listener *lsnr); void dispatch_transplantlistener(listener *olsnr, listener *nlsnr, router *r); int dispatch_addconnection(int sock, listener *lsnr); int dispatch_addconnection_aggr(int sock); void dispatch_set_bufsize(unsigned int sockbufsize); char dispatch_init_listeners(void); dispatcher *dispatch_new_listener(unsigned char id); dispatcher *dispatch_new_connection(unsigned char id, router *r, char *allowed_chars); void dispatch_stop(dispatcher *d); void dispatch_shutdown(dispatcher *d); void dispatch_free(dispatcher *d); size_t dispatch_get_ticks(dispatcher *self); size_t dispatch_get_metrics(dispatcher *self); size_t dispatch_get_blackholes(dispatcher *self); size_t dispatch_get_sleeps(dispatcher *self); size_t dispatch_get_ticks_sub(dispatcher *self); size_t dispatch_get_metrics_sub(dispatcher *self); size_t dispatch_get_blackholes_sub(dispatcher *self); size_t dispatch_get_sleeps_sub(dispatcher *self); size_t dispatch_get_accepted_connections(void); size_t dispatch_get_closed_connections(void); void dispatch_hold(dispatcher *d); void dispatch_schedulereload(dispatcher *d, router *r); char dispatch_reloadcomplete(dispatcher *d); #endif carbon-c-relay-3.2/fnv1a.h000066400000000000000000000025131317265605500153530ustar00rootroot00000000000000/* * Copyright 2013-2017 Fabian Groffen * * 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. */ #define FNV1A_32_OFFSET 2166136261UL #define FNV1A_32_PRIME 16777619 /** * 32-bits unsigned FNV1a returning into hash, using p to as variable to * walk over metric up to firstspace */ #define fnv1a_32(hash, p, metric, firstspace) \ hash = FNV1A_32_OFFSET; \ for (p = metric; p < firstspace; p++) \ hash = (hash ^ (unsigned int)*p) * FNV1A_32_PRIME; #define FNV1A_64_OFFSET 14695981039346656037ULL #define FNV1A_64_PRIME 1099511628211UL /** * 64-bits unsigned FNV1a returning into hash, using p to as variable to * walk over metric up to firstspace */ #define fnv1a_64(hash, p, metric, firstspace) \ hash = FNV1A_64_OFFSET; \ for (p = metric; p < firstspace; p++) \ hash = (hash ^ (unsigned long long int)*p) * FNV1A_64_PRIME; carbon-c-relay-3.2/install-sh000077500000000000000000000345231317265605500162010ustar00rootroot00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2013-12-25.23; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. tab=' ' nl=' ' IFS=" $tab$nl" # Set DOITPROG to "echo" to test this script. doit=${DOITPROG-} doit_exec=${doit:-exec} # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false is_target_a_directory=possibly usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) is_target_a_directory=always dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done # We allow the use of options -d and -T together, by making -d # take the precedence; this is for compatibility with GNU install. if test -n "$dir_arg"; then if test -n "$dst_arg"; then echo "$0: target directory not allowed when installing a directory." >&2 exit 1 fi fi if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then if test $# -gt 1 || test "$is_target_a_directory" = always; then if test ! -d "$dst_arg"; then echo "$0: $dst_arg: Is not a directory." >&2 exit 1 fi fi fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test "$is_target_a_directory" = never; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac oIFS=$IFS IFS=/ set -f set fnord $dstdir shift set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: carbon-c-relay-3.2/issues/000077500000000000000000000000001317265605500155015ustar00rootroot00000000000000carbon-c-relay-3.2/issues/distributiontest.c000066400000000000000000000074621317265605500212750ustar00rootroot00000000000000/* * Copyright 2013-2017 Fabian Groffen * * 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. */ /* This is a clumpsy program to test the distribution of a certain input * set of metrics. See also: * https://github.com/graphite-project/carbon/issues/485 * * compile using something like this: * clang -o distributiontest -I. issues/distributiontest.c consistent-hash.c \ * server.c queue.c md5.c dispatcher.c router.c aggregator.c -pthread -lm */ #include #include #include #include #include #include #include "consistent-hash.h" #include "router.h" #include "server.h" #include "relay.h" #include "md5.h" #define SRVCNT 8 #define REPLCNT 2 unsigned char mode = 0; int relaylog(enum logdst dest, const char *fmt, ...) { (void) dest; (void) fmt; return 0; } int main(int argc, char *argv[]) { FILE *f; int i, j; ch_ring *r; char buf[METRIC_BUFSIZ]; server *s[SRVCNT]; size_t scnt[SRVCNT]; size_t metrics; time_t start, stop; size_t min, max; double mean, stddev; if (argc < 2) { fprintf(stderr, "need file argument\n"); return 1; } if (strcmp(argv[1], "-") == 0) { f = stdin; } else { f = fopen(argv[1], "r"); } if (f == NULL) { fprintf(stderr, "failed to open '%s': %s\n", argv[1], strerror(errno)); return 1; } /* build hash-ring */ r = ch_new(JUMP_FNV1a); /* or CARBON, FNV1a */ for (i = 0; i < SRVCNT; i++) { char ip[24]; unsigned char md5[MD5_DIGEST_LENGTH]; char md5sum[MD5_DIGEST_LENGTH * 2 + 1]; snprintf(ip, sizeof(ip), "192.168.%d.%d", i, 10 + (i * 2)); s[i] = server_new( ip, 2003, T_LINEMODE, W_PLAIN, CON_TCP, NULL, 1024, 128, 4, 800 ); MD5((unsigned char *)ip, strlen(ip), md5); for (j = 0; j < MD5_DIGEST_LENGTH; j++) { snprintf(md5sum + (j * 2), 3, "%02x", md5[j]); } /* to use instance, enable this */ if (1 == 0) server_set_instance(s[i], md5sum); r = ch_addnode(r, s[i]); } /* process input */ memset(scnt, 0, sizeof(size_t) * SRVCNT); metrics = 0; start = time(NULL); while (fgets(buf, METRIC_BUFSIZ, f) != NULL) { destination dst[REPLCNT]; metrics++; ch_get_nodes( dst, r, REPLCNT, buf, buf + strlen(buf) - 1 ); for (i = 0; i < REPLCNT; i++) { free((void *)dst[i].metric); for (j = 0; j < SRVCNT; j++) { if (s[j] == dst[i].dest) { scnt[j]++; break; } } } } stop = time(NULL); mean = 0.0; stddev = 0.0; if (stop == start) { stop++; } printf("total metrics processed: %zd, time spent: ~%ds (~%d/s)\n", metrics, (int)(stop - start), (int)(metrics / (stop - start))); printf("replication count: %d, server count: %d\n", REPLCNT, SRVCNT); printf("server distribution:\n"); for (i = 0; i < SRVCNT; i++) { printf("- server %15s: %6zd (%.2f%%)\n", server_ip(s[i]), scnt[i], ((double)scnt[i] * 100.0) / (double)metrics); if (i == 0) { min = max = scnt[i]; } else { if (scnt[i] < min) min = scnt[i]; if (scnt[i] > max) max = scnt[i]; } mean += (double)scnt[i]; } mean /= (double)SRVCNT; for (i = 0; i < SRVCNT; i++) { stddev += pow((double)scnt[i] - mean, 2); } stddev = sqrt(stddev / (double)SRVCNT); printf("band: %zd - %zd (diff %zd, %.1f%%), mean: %.2f, stddev: %.2f\n", min, max, max - min, (double)(max-min) * 100.0 / (mean * SRVCNT), mean, stddev); } carbon-c-relay-3.2/issues/issue10.conf000066400000000000000000000020531317265605500176410ustar00rootroot00000000000000rewrite ^servers\.(cloud|bc|cwwtf|telhc)\.(int|test|stage|live|eng|green|mgmt)\.([a-zA-Z]+)([0-9]+) into servers.\1.\2.\3.\3\4 ; #remove derive, objects and gauges, etc. in keys (unless for applications (statsd)) # regex implementation doesn't understand this one #rewrite ^(.*)\.(? 1: arg = sys.argv[1] if arg.isdigit(): delay = int(arg) else: sys.stderr.write("Ignoring non-integer argument. Using default: %ss\n" % delay) sock = socket.socket() try: sock.connect( (CARBON_SERVER, CARBON_PORT) ) except socket.error: raise SystemExit("Couldn't connect to %(server)s on port %(port)d, is carbon-cache.py running?" % { 'server':CARBON_SERVER, 'port':CARBON_PORT }) try: run(sock, delay) except KeyboardInterrupt: sys.stderr.write("\nExiting on CTRL-c\n") sys.exit(0) if __name__ == "__main__": main() carbon-c-relay-3.2/issues/issue60.conf000066400000000000000000000007521317265605500176520ustar00rootroot00000000000000match ^metrics.all.* send to blackhole stop ; aggregate metrics.*.api.ac\.([^.]+)\.([^.]+)\.([^.]+)\.([^.]+)\.([^.]+)\.count every 10 seconds expire after 50 seconds compute sum write to metrics.all.api.ac.\1.\2.\3.\4.\5.count compute sum write to metrics.all.api.ac.\1.\2.all.\4.\5.count compute sum write to metrics.all.api.ac.\1.\2.\3.all.\5.count compute sum write to metrics.all.api.ac.\1.\2.all.all.\5.count ; carbon-c-relay-3.2/issues/issue82.conf000066400000000000000000000007751317265605500176630ustar00rootroot00000000000000cluster local_carbon carbon_ch 127.0.0.1:2013=a ; match * send to local_carbon stop ; aggregate ^sys\.dc[0-9].(somehost-[0-9]+)\.([^.]+)\.mysql\.replication_delay every 10 seconds expire after 35 seconds compute sum write to mysql.host.\1.replication_delay compute sum write to mysql.host.all.replication_delay compute sum write to mysql.cluster.\2.replication_delay compute sum write to mysql.cluster.all.replication_delay ; carbon-c-relay-3.2/issues/issue94-2.conf000066400000000000000000000004331317265605500200140ustar00rootroot00000000000000cluster graphite forward 127.0.0.1:2004 ; aggregate ^sys\.somemetric every 60 seconds expire after 75 seconds timestamp at end of bucket compute sum write to sys.somemetric send to graphite stop ; match * send to graphite ; carbon-c-relay-3.2/issues/issue94-3.conf000066400000000000000000000025301317265605500200150ustar00rootroot00000000000000############################################################################### # # Define clusters that we will manage. # ############################################################################### cluster local forward 127.0.0.1:2004 ; ############################################################################### # # Define any rewrite rules you might want. # ############################################################################### # carbon-c-relay metrics should go under system. rewrite ^carbon\.(.*) into system.carbon.\1 ; ############################################################################### # # Define Aggregations we want to use. # ############################################################################### #access-logs page counts aggregate ^app\.([^.]+)\.dc\.([^.]+)\.env\.([^.]+)\.store\.([^.]+)\.pages\.([^.]+)\.count every 60 seconds expire after 90 seconds compute sum write to aggregated_app.\1.dc.\2.env.\3.store.\4.pages.\5.count send to local ; ############################################################################### # # Send carbon metrics home. If you want another metric to be sent do it here. # ############################################################################### match ^system\.carbon\.(.*) send to local stop ; carbon-c-relay-3.2/issues/issue94-4.conf000066400000000000000000000004641317265605500200220ustar00rootroot00000000000000cluster reagg fnv1a_ch 127.0.0.1:2004=a 127.0.0.2:2004=b 127.0.0.3:2004=c 127.0.0.4:2004=d ; cluster b forward 127.0.0.1:2005; aggregate ^(.+).([^.]+).([^.]+)$ every 10 seconds expire after 30 seconds timestamp at end of bucket compute sum write to agg.\1.\2.sumall.hosts send to reagg b stop ; carbon-c-relay-3.2/issues/issue94.conf000066400000000000000000000011271317265605500176560ustar00rootroot00000000000000cluster aggregator-post failover 127.0.0.1:2004 127.0.0.1:2005 ; rewrite ^carbon\.(.*) into system.carbon.\1 ; aggregate ^app\.([^.]+)\.dc\.([^.]+)\.env\.([^.]+)\.store\.([^.]+)\.pages\.([^.]+)\.count every 60 seconds expire after 95 seconds timestamp at end of bucket compute sum write to aggregated_app.\1.dc.\2.env.\3.store.\4.pages.\5.count ; match ^system\.carbon\.(.*) send to aggregator-post stop ; match ^aggregated_(.*) send to aggregator-post stop ; match * send to blackhole stop ; carbon-c-relay-3.2/issues/routertest.c000066400000000000000000000032571317265605500200740ustar00rootroot00000000000000/* * Copyright 2013-2017 Fabian Groffen * * 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. */ /* Simple example of how to use the routing functionality of the relay * https://github.com/grobian/carbon-c-relay/issues/192 * * compile with something like: * gcc -o routertest routertest.c router.c server.c consistent-hash.c \ * md5.c queue.c dispatcher.c aggregator.c -lnsl -lsocket -lm */ #include #include #include #include "relay.h" #include "server.h" #include "router.h" unsigned char mode = 0; relaylog(enum logdst dest, const char *fmt, ...) { return 0; } #define DESTS_SIZE 32 int main() { size_t len = 0; size_t i; destination dests[DESTS_SIZE]; char *metric; char *firstspace; server *s; router *rtr; if ((rtr = router_readconfig(NULL, "test.conf", 100, 10, 1, 100)) == NULL) exit(1); metric = strdup("bla.bla.bla"); firstspace = metric + strlen(metric); (void)router_route(rtr, dests, &len, DESTS_SIZE, "127.0.0.1", metric, firstspace); for (i = 0; i < len; i++) { free((char *)dests[i].metric); s = dests[i].dest; printf("%zd: %s:%d=%s\n", i, server_ip(s), server_port(s), server_instance(s)); } return 0; } carbon-c-relay-3.2/md5.c000066400000000000000000000211111317265605500150130ustar00rootroot00000000000000/* * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. * MD5 Message-Digest Algorithm (RFC 1321). * * Homepage: * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 * * Author: * Alexander Peslyak, better known as Solar Designer * * This software was written by Alexander Peslyak in 2001. No copyright is * claimed, and the software is hereby placed in the public domain. * In case this attempt to disclaim copyright and place the software in the * public domain is deemed null and void, then the software is * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the * general public under the following terms: * * Redistribution and use in source and binary forms, with or without * modification, are permitted. * * There's ABSOLUTELY NO WARRANTY, express or implied. * * (This is a heavily cut-down "BSD license".) * * This differs from Colin Plumb's older public domain implementation in that * no exactly 32-bit integer data type is required (any 32-bit or wider * unsigned integer data type will do), there's no compile-time endianness * configuration, and the function prototypes match OpenSSL's. No code from * Colin Plumb's implementation has been reused; this comment merely compares * the properties of the two independent implementations. * * The primary goals of this implementation are portability and ease of use. * It is meant to be fast, but not as fast as possible. Some known * optimizations are not included to reduce source code size and avoid * compile-time configuration. */ #ifndef HAVE_OPENSSL #include #include "md5.h" /* * The basic MD5 functions. * * F and G are optimized compared to their RFC 1321 definitions for * architectures that lack an AND-NOT instruction, just like in Colin Plumb's * implementation. */ #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) #define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) #define H(x, y, z) (((x) ^ (y)) ^ (z)) #define H2(x, y, z) ((x) ^ ((y) ^ (z))) #define I(x, y, z) ((y) ^ ((x) | ~(z))) /* * The MD5 transformation for all four rounds. */ #define STEP(f, a, b, c, d, x, t, s) \ (a) += f((b), (c), (d)) + (x) + (t); \ (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ (a) += (b); /* * SET reads 4 input bytes in little-endian byte order and stores them * in a properly aligned word in host byte order. * * The check for little-endian architectures that tolerate unaligned * memory accesses is just an optimization. Nothing will break if it * doesn't work. */ #if defined(__i386__) || defined(__x86_64__) || defined(__vax__) #define SET(n) \ (*(MD5_u32plus *)&ptr[(n) * 4]) #define GET(n) \ SET(n) #else #define SET(n) \ (ctx->block[(n)] = \ (MD5_u32plus)ptr[(n) * 4] | \ ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \ ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \ ((MD5_u32plus)ptr[(n) * 4 + 3] << 24)) #define GET(n) \ (ctx->block[(n)]) #endif /* * This processes one or more 64-byte data blocks, but does NOT update * the bit counters. There are no alignment requirements. */ static const void *body(MD5_CTX *ctx, const void *data, unsigned long size) { const unsigned char *ptr; MD5_u32plus a, b, c, d; MD5_u32plus saved_a, saved_b, saved_c, saved_d; ptr = (const unsigned char *)data; a = ctx->a; b = ctx->b; c = ctx->c; d = ctx->d; do { saved_a = a; saved_b = b; saved_c = c; saved_d = d; /* Round 1 */ STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7) STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12) STEP(F, c, d, a, b, SET(2), 0x242070db, 17) STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22) STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7) STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12) STEP(F, c, d, a, b, SET(6), 0xa8304613, 17) STEP(F, b, c, d, a, SET(7), 0xfd469501, 22) STEP(F, a, b, c, d, SET(8), 0x698098d8, 7) STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12) STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17) STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22) STEP(F, a, b, c, d, SET(12), 0x6b901122, 7) STEP(F, d, a, b, c, SET(13), 0xfd987193, 12) STEP(F, c, d, a, b, SET(14), 0xa679438e, 17) STEP(F, b, c, d, a, SET(15), 0x49b40821, 22) /* Round 2 */ STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5) STEP(G, d, a, b, c, GET(6), 0xc040b340, 9) STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14) STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20) STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5) STEP(G, d, a, b, c, GET(10), 0x02441453, 9) STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14) STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20) STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5) STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9) STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14) STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20) STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5) STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9) STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14) STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20) /* Round 3 */ STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4) STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11) STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16) STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23) STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4) STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11) STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16) STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23) STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4) STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11) STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16) STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23) STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4) STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11) STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16) STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23) /* Round 4 */ STEP(I, a, b, c, d, GET(0), 0xf4292244, 6) STEP(I, d, a, b, c, GET(7), 0x432aff97, 10) STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15) STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21) STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6) STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10) STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15) STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21) STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6) STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10) STEP(I, c, d, a, b, GET(6), 0xa3014314, 15) STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21) STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6) STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10) STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15) STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21) a += saved_a; b += saved_b; c += saved_c; d += saved_d; ptr += 64; } while (size -= 64); ctx->a = a; ctx->b = b; ctx->c = c; ctx->d = d; return ptr; } void MD5_Init(MD5_CTX *ctx) { ctx->a = 0x67452301; ctx->b = 0xefcdab89; ctx->c = 0x98badcfe; ctx->d = 0x10325476; ctx->lo = 0; ctx->hi = 0; } void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size) { MD5_u32plus saved_lo; unsigned long used, available; saved_lo = ctx->lo; if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) ctx->hi++; ctx->hi += size >> 29; used = saved_lo & 0x3f; if (used) { available = 64 - used; if (size < available) { memcpy(&ctx->buffer[used], data, size); return; } memcpy(&ctx->buffer[used], data, available); data = (const unsigned char *)data + available; size -= available; body(ctx, ctx->buffer, 64); } if (size >= 64) { data = body(ctx, data, size & ~(unsigned long)0x3f); size &= 0x3f; } memcpy(ctx->buffer, data, size); } void MD5_Final(unsigned char *result, MD5_CTX *ctx) { unsigned long used, available; used = ctx->lo & 0x3f; ctx->buffer[used++] = 0x80; available = 64 - used; if (available < 8) { memset(&ctx->buffer[used], 0, available); body(ctx, ctx->buffer, 64); used = 0; available = 64; } memset(&ctx->buffer[used], 0, available - 8); ctx->lo <<= 3; ctx->buffer[56] = ctx->lo; ctx->buffer[57] = ctx->lo >> 8; ctx->buffer[58] = ctx->lo >> 16; ctx->buffer[59] = ctx->lo >> 24; ctx->buffer[60] = ctx->hi; ctx->buffer[61] = ctx->hi >> 8; ctx->buffer[62] = ctx->hi >> 16; ctx->buffer[63] = ctx->hi >> 24; body(ctx, ctx->buffer, 64); result[0] = ctx->a; result[1] = ctx->a >> 8; result[2] = ctx->a >> 16; result[3] = ctx->a >> 24; result[4] = ctx->b; result[5] = ctx->b >> 8; result[6] = ctx->b >> 16; result[7] = ctx->b >> 24; result[8] = ctx->c; result[9] = ctx->c >> 8; result[10] = ctx->c >> 16; result[11] = ctx->c >> 24; result[12] = ctx->d; result[13] = ctx->d >> 8; result[14] = ctx->d >> 16; result[15] = ctx->d >> 24; memset(ctx, 0, sizeof(*ctx)); } unsigned char *MD5(const void *data, unsigned long size, unsigned char *result) { MD5_CTX ctx; MD5_Init(&ctx); MD5_Update(&ctx, data, size); MD5_Final(result, &ctx); return result; } #endif carbon-c-relay-3.2/md5.h000066400000000000000000000027701317265605500150320ustar00rootroot00000000000000/* * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. * MD5 Message-Digest Algorithm (RFC 1321). * * Homepage: * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 * * Author: * Alexander Peslyak, better known as Solar Designer * * This software was written by Alexander Peslyak in 2001. No copyright is * claimed, and the software is hereby placed in the public domain. * In case this attempt to disclaim copyright and place the software in the * public domain is deemed null and void, then the software is * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the * general public under the following terms: * * Redistribution and use in source and binary forms, with or without * modification, are permitted. * * There's ABSOLUTELY NO WARRANTY, express or implied. * * See md5.c for more information. */ #ifdef HAVE_OPENSSL #include #elif !defined(_MD5_H) #define _MD5_H #define MD5_DIGEST_LENGTH 16 /* Any 32-bit or wider unsigned integer data type will do */ typedef unsigned int MD5_u32plus; typedef struct { MD5_u32plus lo, hi; MD5_u32plus a, b, c, d; unsigned char buffer[64]; MD5_u32plus block[16]; } MD5_CTX; extern void MD5_Init(MD5_CTX *ctx); extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size); extern void MD5_Final(unsigned char *result, MD5_CTX *ctx); extern unsigned char *MD5(const void *data, unsigned long size, unsigned char *result); #endif carbon-c-relay-3.2/missing000077500000000000000000000153301317265605500155670ustar00rootroot00000000000000#! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2013-10-28.13; # UTC # Copyright (C) 1996-2014 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=http://www.perl.org/ flex_URL=http://flex.sourceforge.net/ gnu_software_URL=http://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'autom4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: carbon-c-relay-3.2/queue.c000066400000000000000000000117031317265605500154600ustar00rootroot00000000000000/* * Copyright 2013-2017 Fabian Groffen * * 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. */ #include #include #include #include "queue.h" struct _queue { const char **queue; size_t end; size_t write; size_t read; size_t len; pthread_mutex_t lock; }; /** * Allocates a new queue structure with capacity to hold size elements. */ queue * queue_new(size_t size) { queue *ret = malloc(sizeof(queue)); if (ret == NULL) return NULL; ret->queue = malloc(sizeof(char *) * size); if (ret->queue == NULL) { free(ret); return NULL; } memset(ret->queue, 0, sizeof(char *) * size); ret->end = size; ret->read = ret->write = 0; ret->len = 0; pthread_mutex_init(&ret->lock, NULL); return ret; } /** * Frees up allocated resources in use by the queue. This doesn't take * into account any consumers at all. That is, the caller needs to * ensure noone is using the queue any more. */ void queue_destroy(queue *q) { const char *p; /* drain queue not to leak the memory consumed by pending metrics */ while ((p = queue_dequeue(q)) != NULL) free((char *)p); q->len = 0; pthread_mutex_destroy(&q->lock); free(q->queue); free(q); } /** * Enqueues the string pointed to by p at queue q. If the queue is * full, the oldest entry is dropped. For this reason, enqueuing will * never fail. This function assumes the pointer p is a copy for this * queue, that is returned on dequeue, or freed when dropped. */ void queue_enqueue(queue *q, const char *p) { /* queue normal: * |=====-----------------------------| 4 * ^ ^ * r w * queue wrap: * |===---------------------------====| 6 * ^ ^ * w r * queue full * |==================================| 23 * ^ * w+r */ pthread_mutex_lock(&q->lock); if (q->len == q->end) { if (q->read == q->end) q->read = 0; free((char *)(q->queue[q->read])); q->read++; q->len--; } if (q->write == q->end) q->write = 0; q->queue[q->write] = p; q->write++; q->len++; pthread_mutex_unlock(&q->lock); } /** * Returns the oldest entry in the queue. If there are no entries, NULL * is returned. The caller should free the returned string. */ const char * queue_dequeue(queue *q) { const char *ret; pthread_mutex_lock(&q->lock); if (q->len == 0) { pthread_mutex_unlock(&q->lock); return NULL; } if (q->read == q->end) q->read = 0; ret = q->queue[q->read++]; q->len--; pthread_mutex_unlock(&q->lock); return ret; } /** * Returns at most len elements from the queue. Attempts to use a * single lock to read a vector of elements from the queue to minimise * effects of locking. Returns the number of elements stored in ret. * The caller is responsible for freeing elements from ret, as well as * making sure it is large enough to store len elements. */ size_t queue_dequeue_vector(const char **ret, queue *q, size_t len) { size_t i; pthread_mutex_lock(&q->lock); if (q->len == 0) { pthread_mutex_unlock(&q->lock); return 0; } if (len > q->len) len = q->len; for (i = 0; i < len; i++) { if (q->read == q->end) q->read = 0; ret[i] = q->queue[q->read++]; } q->len -= len; pthread_mutex_unlock(&q->lock); return len; } /** * Puts the entry p at the front of the queue, instead of the end, if * there is space available in the queue. Returns 0 when no space is * available, non-zero otherwise. Like queue_enqueue, * queue_putback assumes pointer p points to a private copy for the * queue. */ char queue_putback(queue *q, const char *p) { pthread_mutex_lock(&q->lock); if (q->len == q->end) { pthread_mutex_unlock(&q->lock); return 0; } if (q->read == 0) q->read = q->end; q->read--; q->queue[q->read] = p; q->len++; pthread_mutex_unlock(&q->lock); return 1; } /** * Returns the (approximate) size of entries waiting to be read in the * queue. The returned value cannot be taken accurate with multiple * readers/writers concurrently in action. Hence it can only be seen as * mere hint about the state of the queue. */ inline size_t queue_len(queue *q) { size_t len; pthread_mutex_lock(&q->lock); len = q->len; pthread_mutex_unlock(&q->lock); return len; } /** * Returns the (approximate) size of free entries in the queue. The * same conditions as for queue_len apply. */ inline size_t queue_free(queue *q) { return q->end - queue_len(q); } /** * Returns the size of the queue. */ inline size_t queue_size(queue *q) { return q->end; } carbon-c-relay-3.2/queue.h000066400000000000000000000020221317265605500154570ustar00rootroot00000000000000/* * Copyright 2013-2017 Fabian Groffen * * 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. */ #ifndef QUEUE_H #define QUEUE_H 1 #include typedef struct _queue queue; queue* queue_new(size_t size); void queue_destroy(queue *q); void queue_enqueue(queue *q, const char *p); const char *queue_dequeue(queue *q); size_t queue_dequeue_vector(const char **ret, queue *q, size_t len); char queue_putback(queue *q, const char *p); size_t queue_len(queue *q); size_t queue_free(queue *q); size_t queue_size(queue *q); #endif carbon-c-relay-3.2/receptor.c000066400000000000000000000145451317265605500161660ustar00rootroot00000000000000/* * Copyright 2013-2017 Fabian Groffen * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include "relay.h" #include "router.h" #ifdef HAVE_SSL #include #include #endif static char bindlistenip(listener *lsnr, unsigned int backlog) { int sock; int optval; struct timeval tv; struct addrinfo *resw; char saddr[INET6_ADDRSTRLEN]; int binderr = 0; int sockcur = 0; #ifdef HAVE_SSL if (lsnr->transport == W_SSL) { /* create a auto-negotiate context */ const SSL_METHOD *m = SSLv23_server_method(); lsnr->ctx = SSL_CTX_new(m); if (lsnr->ctx == NULL) { char *err = ERR_error_string(ERR_get_error(), NULL); logerr("failed to create SSL context for listener on port %d: %s\n", lsnr->port, err); return 1; } /* load certificates */ if (SSL_CTX_use_certificate_file( lsnr->ctx, lsnr->pemcert, SSL_FILETYPE_PEM) <= 0) { char *err = ERR_error_string(ERR_get_error(), NULL); SSL_CTX_free(lsnr->ctx); logerr("cannot load certificate from %s: %s\n", lsnr->pemcert, err); return 1; } if (SSL_CTX_use_PrivateKey_file( lsnr->ctx, lsnr->pemcert, SSL_FILETYPE_PEM) <= 0) { char *err = ERR_error_string(ERR_get_error(), NULL); SSL_CTX_free(lsnr->ctx); logerr("cannot load private key from %s: %s\n", lsnr->pemcert, err); return 1; } if (!SSL_CTX_check_private_key(lsnr->ctx)) { char *err = ERR_error_string(ERR_get_error(), NULL); SSL_CTX_free(lsnr->ctx); logerr("private key does not match public certificate in %s: %s\n", lsnr->pemcert, err); return 1; } } #endif tv.tv_sec = 0; tv.tv_usec = 500 * 1000; for (resw = lsnr->saddrs; resw != NULL; resw = resw->ai_next) { if (resw->ai_family != PF_INET && resw->ai_family != PF_INET6) continue; if (resw->ai_protocol != IPPROTO_TCP && resw->ai_protocol != IPPROTO_UDP) continue; saddr_ntop(resw, saddr); if (saddr[0] == '\0') snprintf(saddr, sizeof(saddr), "(unknown)"); if ((sock = socket(resw->ai_family, resw->ai_socktype, resw->ai_protocol)) < 0) { if (errno == EAFNOSUPPORT && (sockcur > 0 || resw->ai_next != NULL)) { /* ignore "address family not supported by protocol" for * systems with ipv6 disabled, issue #296 */ continue; } logerr("failed to create socket for %s%s%s: %s\n", resw->ai_family == PF_INET ? "[" : "", saddr, resw->ai_family == PF_INET ? "]" : "", strerror(errno)); binderr = 1; break; } lsnr->socks[sockcur++] = sock; (void) setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); optval = 1; /* allow takeover */ (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); if (resw->ai_family == PF_INET6) { optval = 1; (void) setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)); } if (bind(sock, resw->ai_addr, resw->ai_addrlen) < 0) { logerr("failed to bind on %s%d %s port %u: %s\n", resw->ai_protocol == IPPROTO_TCP ? "tcp" : "udp", resw->ai_family == PF_INET6 ? 6 : 4, saddr, lsnr->port, strerror(errno)); binderr = 1; break; } if (resw->ai_protocol == IPPROTO_TCP) { if (listen(sock, backlog) < 0) { logerr("failed to listen on tcp%d %s port %u: %s\n", resw->ai_family == PF_INET6 ? 6 : 4, saddr, lsnr->port, strerror(errno)); binderr = 1; break; } logout("listening on tcp%d %s port %u\n", resw->ai_family == PF_INET6 ? 6 : 4, saddr, lsnr->port); } else { logout("listening on udp%d %s port %u\n", resw->ai_family == PF_INET6 ? 6 : 4, saddr, lsnr->port); } } if (binderr != 0) { /* close all opened sockets */ for (--sockcur; sockcur >= 0; sockcur--) close(lsnr->socks[sockcur]); return 1; } lsnr->socks[sockcur] = -1; return 0; } static char bindlistenunix(listener *lsnr, unsigned int backlog) { struct sockaddr_un srvr; int sock; #ifndef PF_LOCAL # define PF_LOCAL PF_UNIX #endif if ((sock = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) { logerr("failed to create socket for %s: %s\n", lsnr->ip, strerror(errno)); return 1; } lsnr->socks[0] = sock; lsnr->socks[1] = -1; memset(&srvr, 0, sizeof(struct sockaddr_un)); srvr.sun_family = PF_LOCAL; strncpy(srvr.sun_path, lsnr->ip, sizeof(srvr.sun_path) - 1); unlink(lsnr->ip); /* avoid address already in use */ if (bind(sock, (struct sockaddr *)&srvr, sizeof(struct sockaddr_un)) < 0) { logerr("failed to bind for %s: %s\n", lsnr->ip, strerror(errno)); close(sock); return 1; } if (listen(sock, backlog) < 0) { logerr("failed to listen on %s: %s\n", lsnr->ip, strerror(errno)); close(sock); return 1; } logout("listening on UNIX socket %s\n", lsnr->ip); return 0; } /** * Open up sockets associated with listener. Returns 0 when opening up * the listener succeeded, 1 otherwise. */ char bindlisten(listener *lsnr, unsigned int backlog) { switch (lsnr->ctype) { case CON_TCP: case CON_UDP: return bindlistenip(lsnr, backlog); case CON_UNIX: return bindlistenunix(lsnr, backlog); default: logerr("unsupported listener type"); return 1; } } static void close_socks(listener *lsnr) { int i; for (i = 0; lsnr->socks[i] != -1; i++) close(lsnr->socks[i]); logout("closed listener for %s %s:%u\n", lsnr->ctype == CON_UDP ? "udp" : "tcp", lsnr->ip == NULL ? "" : lsnr->ip, lsnr->port); } static void destroy_usock(listener *lsnr) { close(lsnr->socks[0]); unlink(lsnr->ip); logout("removed listener for %s\n", lsnr->ip); } void shutdownclose(listener *lsnr) { switch (lsnr->ctype) { case CON_TCP: case CON_UDP: close_socks(lsnr); break; case CON_UNIX: destroy_usock(lsnr); break; default: logerr("unsupported listener type"); break; } } carbon-c-relay-3.2/receptor.h000066400000000000000000000013751317265605500161700ustar00rootroot00000000000000/* * Copyright 2013-2017 Fabian Groffen * * 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. */ #ifndef RECEPTOR_H #define RECEPTOR_H 1 #include "router.h" int bindlisten(listener *lsnr, unsigned int backlog); void shutdownclose(listener *lsnr); #endif carbon-c-relay-3.2/relay.c000066400000000000000000000647131317265605500154610ustar00rootroot00000000000000/* * Copyright 2013-2017 Fabian Groffen * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__MACH__) || defined(BSD) # include # include #endif #include "relay.h" #include "server.h" #include "router.h" #include "receptor.h" #include "dispatcher.h" #include "aggregator.h" #include "collector.h" #include "conffile.h" unsigned char keep_running = 1; int pending_signal = -1; char relay_hostname[256]; unsigned char mode = 0; static char *config = NULL; static int batchsize = 2500; static int queuesize = 25000; static int maxstalls = 4; static unsigned short iotimeout = 600; static unsigned short listenport = GRAPHITE_PORT; static int optimiserthreshold = 50; static int sockbufsize = 0; static int collector_interval = 60; static unsigned int listenbacklog = 32; static col_mode smode = CUM; static dispatcher **workers = NULL; static char workercnt = 0; static router *rtr = NULL; static server *internal_submission = NULL; static char *relay_logfile = NULL; static FILE *relay_stdout = NULL; static FILE *relay_stderr = NULL; static char relay_can_log = 0; /** * Writes to the setup output stream, prefixed with a timestamp, and if * the stream is not going to stdout or stderr, prefixed with MSG or * ERR. */ int relaylog(enum logdst dest, const char *fmt, ...) { va_list ap; char prefix[64]; size_t len; time_t now; struct tm tm_now; FILE *dst = NULL; char console = 0; int ret; /* briefly stall if we're swapping fds */ while (!__sync_add_and_fetch(&relay_can_log, 0)) usleep((100 + (rand() % 200)) * 1000); /* 100ms - 300ms */ switch (dest) { case LOGOUT: dst = relay_stdout; if (dst == stdout) console = 1; break; case LOGERR: dst = relay_stderr; if (dst == stderr) console = 1; break; } /* NULL == /dev/null */ if (dst == NULL) return 0; time(&now); localtime_r(&now, &tm_now); len = strftime(prefix, sizeof(prefix), "[%Y-%m-%d %H:%M:%S]", &tm_now); if (!console) (void)snprintf(prefix + len, sizeof(prefix) - len, " (%s)", dest == LOGOUT ? "MSG" : "ERR"); fprintf(dst, "%s ", prefix); va_start(ap, fmt); ret = vfprintf(dst, fmt, ap); fflush(dst); va_end(ap); return ret; } static void sig_handler(int sig) { /* a thunder of signals will be ignored for as long as a pending * signal was set, I can live with that, feels like a bad practice * to bombard a process like that */ (void)__sync_bool_compare_and_swap(&pending_signal, -1, sig); } static void do_reload(void) { router *newrtr; aggregator *newaggrs; int id; FILE *newfd; size_t numaggregators; listener *lsnrs; if (relay_stderr != stderr) { /* try to re-open the file first, so we can still try and say * something if that fails */ if ((newfd = fopen(relay_logfile, "a")) == NULL) { logerr("not reopening logfiles: can't open '%s': %s\n", relay_logfile, strerror(errno)); } else { logout("closing logfile\n"); __sync_and_and_fetch(&relay_can_log, 0); /* lame race avoidance for relaylog() usage */ usleep((100 + (rand() % 200)) * 1000); /* 100ms - 300ms */ fclose(relay_stderr); relay_stdout = newfd; relay_stderr = newfd; __sync_bool_compare_and_swap(&relay_can_log, 0, 1); logout("reopening logfile\n"); } } logout("reloading config from '%s'\n", config); if ((newrtr = router_readconfig(NULL, config, workercnt, queuesize, batchsize, maxstalls, iotimeout, sockbufsize, listenport)) == NULL) { logerr("failed to read configuration '%s', aborting reload\n", config); return; } router_optimise(newrtr, optimiserthreshold); /* compare the configs first, if there is no diff, then * just refrain from reloading anything */ if (!router_printdiffs(rtr, newrtr, relay_stdout)) { /* no changes, shortcut */ logout("no config changes found\n"); router_free(newrtr); logout("SIGHUP handler complete\n"); return; } /* close connections that are not in the new config first */ lsnrs = router_get_listeners(rtr); for ( ; lsnrs != NULL; lsnrs = lsnrs->next) { if (router_contains_listener(newrtr, lsnrs) == NULL) { dispatch_removelistener(lsnrs); shutdownclose(lsnrs); } } logout("reloading collector\n"); collector_schedulereload(newrtr); while (!collector_reloadcomplete()) usleep((100 + (rand() % 200)) * 1000); /* 100ms - 300ms */ /* During aggregator final expiry, the dispatchers should not put * new metrics, so we have to temporarily stop them processing * connections. However, we still need to handle aggregations that * we will stop next, so this call results in the dispatchers only * dealing with connections from aggregators. Doing this, also * means that we can reload the config atomicly, which disrupts the * service seemingly for a bit, but results in less confusing output * in the end. */ logout("interrupting workers\n"); for (id = 1; id < 1 + workercnt; id++) dispatch_hold(workers[id]); numaggregators = aggregator_numaggregators(router_getaggregators(rtr)); if (numaggregators > 0) { logout("expiring aggregations\n"); aggregator_stop(); /* frees aggrs */ /* Now the aggregator has written everything to the * dispatchers, which will hand over to the servers with proper * metric adjustments (stubs). */ } newaggrs = router_getaggregators(newrtr); numaggregators = aggregator_numaggregators(newaggrs); if (numaggregators > 0) { if (!aggregator_start(newaggrs)) { logerr("failed to start aggregator, aggregations will no " "longer produce output!\n"); } } /* Transplant listeners so their open state won't get lost. Open up * connections for new listeners. */ lsnrs = router_get_listeners(newrtr); for ( ; lsnrs != NULL; lsnrs = lsnrs->next) { listener *olsnr; if ((olsnr = router_contains_listener(rtr, lsnrs)) != NULL) { /* ensure we copy over the opened sockets/state */ dispatch_transplantlistener(olsnr, lsnrs, newrtr); } else { if (bindlisten(lsnrs, listenbacklog) != 0) { logerr("failed to setup listener, " "this will impact the behaviour of the relay\n"); continue; } if (dispatch_addlistener(lsnrs) != 0) { logerr("failed to listen to socket, the " "listener will not be effective\n"); } } } /* Transplant the queues for the same servers, so we keep their * queues (potentially with data) around. To do so, we need to make * sure the servers aren't being operated on. */ router_shutdown(rtr); /* Because we know that ip:port:prot is unique in both sets, when we * find a match, we can just swap the queue. This comes with a * slight peculiarity, that if a server becomes part of an any_of * cluster (or failover), its pending queue can now be processed by * other servers. While this feels wrong, it can be extremely * useful in case existing data needs to be migrated to another * server, e.g. the config on purpose added a failover to offload a * known dead server before removing it. This is fairly specific * but in reality this happens to be desirable every once so often. */ router_transplant_queues(newrtr, rtr); /* Before we start the workers sending traffic, start up the * servers now queues are transplanted. */ router_start(newrtr); logout("reloading workers\n"); for (id = 1; id < 1 + workercnt; id++) dispatch_schedulereload(workers[id], newrtr); /* un-holds */ for (id = 1; id < 1 + workercnt; id++) { while (!dispatch_reloadcomplete(workers[id + 0])) usleep((100 + (rand() % 200)) * 1000); /* 100ms - 300ms */ } router_free(rtr); rtr = newrtr; logout("SIGHUP handler complete\n"); } static void handle_signal(int sig) { char *sign = "unknown signal"; switch (sig) { case SIGTERM: sign = "SIGTERM"; break; case SIGINT: sign = "SIGINT"; break; case SIGQUIT: sign = "SIGQUIT"; break; case SIGHUP: sign = "SIGHUP"; break; } if (keep_running) { logout("caught %s\n", sign); } else { /* also fine when SIGHUP */ logerr("caught %s while already shutting down, " "forcing exit!\n", sign); exit(1); } if (sig == SIGHUP) { do_reload(); } else { keep_running = 0; } } static int get_cores(void) { int cpus = 5; #if defined(__MACH__) || defined(BSD) size_t len = sizeof(cpus); sysctlbyname("hw.ncpu", &cpus, &len, NULL, 0); #else /* Linux and Solaris */ cpus = sysconf(_SC_NPROCESSORS_ONLN); #endif return cpus; } static void do_version(void) { printf("carbon-c-relay v" VERSION " (" GIT_VERSION ")\n"); exit(0); } static void do_usage(char *name, int exitcode) { printf("Usage: %s -f [opts]\n", name); printf("\n"); printf("Options:\n"); printf(" -v print version and exit\n"); printf(" -f read for clusters and routes\n"); printf(" -p listen on for connections, defaults to %u\n", GRAPHITE_PORT); printf(" -l write output to , defaults to stdout/stderr\n"); printf(" -w use worker threads, defaults to %d\n", get_cores()); printf(" -b server send batch size, defaults to %d\n", batchsize); printf(" -q server queue size, defaults to %d\n", queuesize); printf(" -L server max stalls, defaults to %d\n", maxstalls); printf(" -S statistics sending interval in seconds, defaults to 60\n"); printf(" -B connection listen backlog, defaults to 32\n"); printf(" -U socket receive buffer size, max/min/default values depend on OS\n"); printf(" -T IO timeout in milliseconds for server connections, defaults to %d\n", iotimeout); printf(" -m send statistics like carbon-cache.py, e.g. not cumulative\n"); printf(" -c characters to allow next to [A-Za-z0-9], defaults to -_:#\n"); printf(" -d debug mode: currently writes statistics to log, prints hash\n" " ring contents and matching position in test mode (-t)\n"); #ifdef ENABLE_TRACE printf(" add another -d to enable (very noisy) trace mode\n"); #endif printf(" -s submission mode: don't add any metrics to the stream like\n" " statistics, report drop counts and queue pressure to log\n"); printf(" -t config test mode: prints rule matches from input on stdin\n"); printf(" -H hostname: override hostname (used in statistics)\n"); printf(" -D daemonise: run in a background\n"); printf(" -P pidfile: write a pid to a specified pidfile\n"); printf(" -O minimum number of rules before optimising the ruleset, default: %d\n", optimiserthreshold); exit(exitcode); } int main(int argc, char * const argv[]) { char id; int ch; size_t numaggregators; char *allowed_chars = NULL; char *pidfile = NULL; FILE *pidfile_handle = NULL; aggregator *aggrs = NULL; int fds[2]; unsigned char startup_success = 0; listener *lsnrs; if (gethostname(relay_hostname, sizeof(relay_hostname)) < 0) snprintf(relay_hostname, sizeof(relay_hostname), "127.0.0.1"); while ((ch = getopt(argc, argv, ":hvdstf:l:p:w:b:q:L:T:c:H:B:U:DP:O:")) != -1) { switch (ch) { case 'v': do_version(); break; case 'd': /* secret support for -dd (just trace) and -ddd (debug * and trace) */ if (mode & MODE_DEBUG) { mode |= MODE_TRACE; mode &= ~MODE_DEBUG; } else { mode |= MODE_DEBUG; } break; case 's': mode |= MODE_SUBMISSION; break; case 't': /* -t: test interactively, -tt: test config and exit */ if (mode & MODE_TEST) { mode |= MODE_CONFIGTEST; } else { mode |= MODE_TEST; } break; case 'f': config = optarg; break; case 'l': relay_logfile = optarg; break; case 'p': listenport = (unsigned short)atoi(optarg); if (listenport == 0) { fprintf(stderr, "error: port needs to be a number >0\n"); do_usage(argv[0], 1); } break; case 'w': workercnt = (char)atoi(optarg); if (workercnt <= 0) { fprintf(stderr, "error: workers needs to be a number >0\n"); do_usage(argv[0], 1); } break; case 'b': batchsize = atoi(optarg); if (batchsize <= 0) { fprintf(stderr, "error: batch size needs to be a number >0\n"); do_usage(argv[0], 1); } break; case 'q': queuesize = atoi(optarg); if (queuesize <= 0) { fprintf(stderr, "error: queue size needs to be a number >0\n"); do_usage(argv[0], 1); } break; case 'L': maxstalls = atoi(optarg); if (maxstalls < 0 || maxstalls >= (1 << SERVER_STALL_BITS)) { fprintf(stderr, "error: maximum stalls needs to be a number " "between 0 and %d\n", (1 << SERVER_STALL_BITS) - 1); do_usage(argv[0], 1); } break; case 'T': { int val = atoi(optarg); if (val <= 0) { fprintf(stderr, "error: server IO timeout needs " "to be a number >0\n"); do_usage(argv[0], 1); } else if (val >= 60000) { fprintf(stderr, "error: server IO timeout needs " "to be less than one minute\n"); do_usage(argv[0], 1); } iotimeout = (unsigned short)val; } break; case 'c': allowed_chars = optarg; break; case 'H': snprintf(relay_hostname, sizeof(relay_hostname), "%s", optarg); break; case 'B': { int val = atoi(optarg); if (val <= 0) { fprintf(stderr, "error: backlog needs to be a number >0\n"); do_usage(argv[0], 1); } listenbacklog = (unsigned int)val; } break; case 'U': { int val = atoi(optarg); socklen_t len = sizeof(sockbufsize); int sock; if (val <= 0) { fprintf(stderr, "error: bufsize needs to be a number >0\n"); do_usage(argv[0], 1); } sockbufsize = (unsigned int)val; /* test the size to see if the value is valid, since * this is OS dependant, it's the only way */ sock = socket(PF_INET, SOCK_STREAM, 0); if (sock == -1 || setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &sockbufsize, sizeof(sockbufsize)) != 0) { fprintf(stderr, "failed to set socket bufsize: %s\n", strerror(errno)); } if (sock != -1 && getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &sockbufsize, &len) != 0) { fprintf(stderr, "failed to get socket bufsize: %s\n", strerror(errno)); } if (len != sizeof(sockbufsize)) { fprintf(stderr, "getsockopt returned unexpected size: %u, " "expected %zu\n", len, sizeof(sockbufsize)); exit(1); } if (sockbufsize > (unsigned int)val) fprintf(stderr, "warning: OS rejected socket bufsize\n"); if (sock != -1) close(sock); } break; case 'D': mode |= MODE_DAEMON; break; case 'P': pidfile = optarg; break; case 'O': { int val = atoi(optarg); optimiserthreshold = val < 0 ? -1 : val; } break; case '?': case ':': do_usage(argv[0], 1); break; case 'h': default: do_usage(argv[0], 0); break; } } if (optind == 1 || config == NULL) do_usage(argv[0], 1); /* seed randomiser for dispatcher and aggregator "splay" */ srand(time(NULL)); if (workercnt == 0) workercnt = mode & MODE_SUBMISSION ? 2 : get_cores(); /* disable collector for submission mode */ if (mode & MODE_SUBMISSION) collector_interval = 0; /* any_of failover maths need batchsize to be smaller than queuesize */ if (batchsize > queuesize) { fprintf(stderr, "error: batchsize must be smaller than queuesize\n"); exit(1); } if (relay_logfile != NULL && (mode & MODE_TEST) == 0) { FILE *f = fopen(relay_logfile, "a"); if (f == NULL) { fprintf(stderr, "error: failed to open logfile '%s': %s\n", relay_logfile, strerror(errno)); exit(1); } relay_stdout = f; relay_stderr = f; } else if (mode & MODE_CONFIGTEST) { /* suppress stdout, just show errors */ relay_stdout = NULL; relay_stderr = stderr; } else { relay_stdout = stdout; relay_stderr = stderr; } relay_can_log = 1; if (mode & MODE_DAEMON) { if (relay_logfile == NULL) { fprintf(stderr, "You must specify logfile if you want daemonisation!\n"); exit(1); } if (mode & MODE_TEST) { fprintf(stderr, "You cannot use test mode if you want daemonisation!\n"); exit(1); } } if (pidfile != NULL) { pidfile_handle = fopen(pidfile, "w"); if (pidfile_handle == NULL) { fprintf(stderr, "failed to open pidfile '%s': %s\n", pidfile, strerror(errno)); exit(1); } } if (mode & MODE_DAEMON) { pid_t p; if (pipe(fds) < 0) { fprintf(stderr, "failed to create pipe to talk to child process: %s\n", strerror(errno)); exit(1); } p = fork(); if (p < 0) { fprintf(stderr, "failed to fork intermediate process: %s\n", strerror(errno)); exit(1); } else if (p == 0) { char msg[1024]; /* child, fork again so our intermediate process can die and * its child becomes an orphan to init */ p = fork(); if (p < 0) { snprintf(msg, sizeof(msg), "failed to fork daemon process: %s\n", strerror(errno)); /* fool compiler */ if (write(fds[1], msg, strlen(msg) + 1) > -2) exit(1); /* not that retcode matters */ } else if (p == 0) { /* child, this is the final daemon process */ if (setsid() < 0) { snprintf(msg, sizeof(msg), "failed to setsid(): %s\n", strerror(errno)); /* fool compiler */ if (write(fds[1], msg, strlen(msg) + 1) > -2) exit(1); /* not that retcode matters */ } /* close descriptors, we won't need them ever since * we're detached from the controlling terminal */ close(0); close(1); close(2); } else { /* parent, die */ exit(0); } } else { /* parent: wait for child to report success */ char msg[1024]; int len = read(fds[0], msg, sizeof(msg)); if (len < 0) { fprintf(stderr, "unable to read from child, " "assuming daemonisation failed\n"); exit(1); } else if (len == 0) { fprintf(stderr, "got unexpected EOF from child, " "assuming daemonisation failed\n"); exit(1); } else if (strncmp(msg, "OK", len) == 0) { /* child is happy, so can we */ exit(0); } else { if (len == 1024) len--; msg[len] = '\0'; fprintf(stderr, "%s", msg); exit(1); } } } else { fds[0] = fds[1] = -1; } #define exit_err(...) { \ if (fds[0] != -1) { \ char msg[1024]; \ snprintf(msg, sizeof(msg), __VA_ARGS__); \ /* fool compiler */ \ if (write(fds[1], msg, strlen(msg) + 1) > -2) \ exit(1); /* not that retcode matters */ \ } else { \ logerr(__VA_ARGS__); \ exit(1); \ } \ } #define exit_ok { \ if (fds[0] != -1) { \ /* we're fine, flag our grandparent (= the original * process being called) it can terminate */ \ if (write(fds[1], "OK", 3) < -2) \ exit(1); /* if our grantparent died, we better do too */ \ close(fds[0]); \ close(fds[1]); \ } \ fds[0] = fds[1] = -1; \ startup_success = 1; \ } if (pidfile_handle) { fprintf(pidfile_handle, "%zu\n", (ssize_t)getpid()); fclose(pidfile_handle); } logout("starting carbon-c-relay v%s (%s), pid=%d\n", VERSION, GIT_VERSION, getpid()); if (relay_stdout != NULL) { fprintf(relay_stdout, "configuration:\n"); fprintf(relay_stdout, " relay hostname = %s\n", relay_hostname); fprintf(relay_stdout, " workers = %d\n", workercnt); fprintf(relay_stdout, " send batch size = %d\n", batchsize); fprintf(relay_stdout, " server queue size = %d\n", queuesize); fprintf(relay_stdout, " server max stalls = %d\n", maxstalls); fprintf(relay_stdout, " listen backlog = %u\n", listenbacklog); if (sockbufsize > 0) fprintf(relay_stdout, " socket bufsize = %u\n", sockbufsize); fprintf(relay_stdout, " server connection IO timeout = %dms\n", iotimeout); if (allowed_chars != NULL) fprintf(relay_stdout, " extra allowed characters = %s\n", allowed_chars); if (mode & MODE_DEBUG) fprintf(relay_stdout, " debug = true\n"); #ifdef ENABLE_TRACE if (mode & MODE_TRACE) fprintf(relay_stdout, " trace = true\n"); #endif else if (mode & MODE_SUBMISSION) fprintf(relay_stdout, " submission = true\n"); else if (mode & MODE_DAEMON) fprintf(relay_stdout, " daemon = true\n"); fprintf(relay_stdout, " configuration = %s\n", config); fprintf(relay_stdout, "\n"); } #ifdef HAVE_SSL /* this needs to happen once, globally */ SSL_library_init(); SSL_load_error_strings(); OpenSSL_add_all_algorithms(); #endif if ((rtr = router_readconfig(NULL, config, workercnt, queuesize, batchsize, maxstalls, iotimeout, sockbufsize, listenport)) == NULL) { exit_err("failed to read configuration '%s'\n", config); } router_optimise(rtr, optimiserthreshold); /* we're done if all we wanted was to test the config */ if (mode & MODE_CONFIGTEST) exit(0); aggrs = router_getaggregators(rtr); numaggregators = aggregator_numaggregators(aggrs); if (numaggregators > 10 && !(mode & MODE_DEBUG)) { fprintf(relay_stdout, "parsed configuration follows:\n" "(%zu aggregations with %zu computations omitted " "for brevity)\n", numaggregators, aggregator_numcomputes(aggrs)); router_printconfig(rtr, relay_stdout, PMODE_NORM); } else { fprintf(relay_stdout, "parsed configuration follows:\n"); router_printconfig(rtr, relay_stdout, PMODE_AGGR + (mode & MODE_DEBUG ? PMODE_DEBUG | PMODE_PEMT : PMODE_NORM)); } fprintf(relay_stdout, "\n"); /* shortcut for rule testing mode */ if (mode & MODE_TEST) { char metricbuf[METRIC_BUFSIZ]; char *p; fflush(relay_stdout); while (fgets(metricbuf, sizeof(metricbuf), stdin) != NULL) { if ((p = strchr(metricbuf, '\n')) != NULL) *p = '\0'; p = metricbuf; while (isspace(*p)) p++; if (*p == '\0') continue; router_test(rtr, metricbuf); } exit(0); } if (signal(SIGINT, sig_handler) == SIG_ERR) { exit_err("failed to create SIGINT handler: %s\n", strerror(errno)); } if (signal(SIGTERM, sig_handler) == SIG_ERR) { exit_err("failed to create SIGTERM handler: %s\n", strerror(errno)); } if (signal(SIGQUIT, sig_handler) == SIG_ERR) { exit_err("failed to create SIGQUIT handler: %s\n", strerror(errno)); } if (signal(SIGHUP, sig_handler) == SIG_ERR) { exit_err("failed to create SIGHUP handler: %s\n", strerror(errno)); } if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { exit_err("failed to ignore SIGPIPE: %s\n", strerror(errno)); } workers = malloc(sizeof(dispatcher *) * (1/*lsnr*/ + workercnt + 1/*sentinel*/)); if (workers == NULL) { exit_err("failed to allocate memory for workers\n"); } dispatch_set_bufsize(sockbufsize); if (dispatch_init_listeners() != 0) { exit_err("failed to allocate listeners\n"); } lsnrs = router_get_listeners(rtr); for ( ; lsnrs != NULL; lsnrs = lsnrs->next) { if (bindlisten(lsnrs, listenbacklog) != 0) { exit_err("failed to setup listener\n"); } if (dispatch_addlistener(lsnrs) != 0) { exit_err("failed to add listener\n"); } } /* ensure the listener id is at the end for regex_t array hack */ if ((workers[0] = dispatch_new_listener((unsigned char)workercnt)) == NULL) logerr("failed to add listener dispatcher\n"); if (allowed_chars == NULL) allowed_chars = "-_:#"; logout("starting %d workers\n", workercnt); for (id = 0; id < workercnt; id++) { workers[id + 1] = dispatch_new_connection( (unsigned char)id, rtr, allowed_chars); if (workers[id + 1] == NULL) { logerr("failed to add worker %d\n", id); break; } } workers[id + 1] = NULL; /* sentinel */ if (id < workercnt) { logerr("shutting down due to errors\n"); keep_running = 0; } /* server used for delivering metrics produced inside the relay, * that is, the collector (statistics) */ if ((internal_submission = server_new( "internal", listenport, T_LINEMODE, W_PLAIN, CON_PIPE, NULL, NULL, 3000, batchsize, maxstalls, iotimeout, sockbufsize)) == NULL) { logerr("failed to create internal submission queue, shutting down\n"); keep_running = 0; } if (internal_submission != NULL && server_start(internal_submission) != 0) { logerr("failed to start submission queue thread, shutting down\n"); server_free(internal_submission); internal_submission = NULL; keep_running = 0; } if (numaggregators > 0) { logout("starting aggregator\n"); if (!aggregator_start(aggrs)) { logerr("shutting down due to failure to start aggregator\n"); keep_running = 0; } } logout("starting statistics collector\n"); if (internal_submission != NULL) collector_start(&workers[1], rtr, internal_submission, smode == CUM); logout("starting servers\n"); if (router_start(rtr) != 0) { /* router_start logerrs itself */ keep_running = 0; } if (keep_running != 0) { logout("startup sequence complete\n"); exit_ok; } /* workers do the work, just wait */ while (keep_running) { sleep(1); if (pending_signal != -1) { handle_signal(pending_signal); pending_signal = -1; } } logout("shutting down...\n"); /* make sure we don't accept anything new anymore */ lsnrs = router_get_listeners(rtr); for ( ; lsnrs != NULL; lsnrs = lsnrs->next) { dispatch_removelistener(lsnrs); shutdownclose(lsnrs); } /* since workers will be freed, stop querying the structures */ collector_stop(); server_shutdown(internal_submission); server_free(internal_submission); logout("stopped collector\n"); if (numaggregators > 0) { aggregator_stop(); logout("stopped aggregator\n"); } /* give a little time for whatever the collector/aggregator wrote, * to be delivered by the dispatchers */ usleep(500 * 1000); /* 500ms */ /* make sure we don't write to our servers any more */ logout("stopped worker"); for (id = 0; id < 1 + workercnt; id++) dispatch_stop(workers[id + 0]); for (id = 0; id < 1 + workercnt; id++) { dispatch_shutdown(workers[id + 0]); dispatch_free(workers[id + 0]); fprintf(relay_stdout, " %d", id + 1); fflush(relay_stdout); } fprintf(relay_stdout, "\n"); fflush(relay_stdout); free(workers); router_shutdown(rtr); router_free(rtr); logout("stopped servers\n"); if (pidfile != NULL) unlink(pidfile); logout("stopped carbon-c-relay v%s (%s)\n", VERSION, GIT_VERSION); /* if we never called exit_ok before, it means we shut down due to * errors, so exit with an error */ if (startup_success == 0) { /* this message will never reach the log/screen when not * daemonised, because the logger already shut down */ exit_err("startup failed, review the logs for details\n"); } return 0; } carbon-c-relay-3.2/relay.h000066400000000000000000000036401317265605500154560ustar00rootroot00000000000000/* * Copyright 2013-2017 Fabian Groffen * * 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. */ #ifndef HAVE_RELAY_H #define HAVE_RELAY_H 1 #ifdef HAVE_CONFIG_H #include "config.h" #endif #define METRIC_BUFSIZ 8192 /* these are the various modes in which the relay runs */ #define MODE_DEBUG (1 << 0) #define MODE_SUBMISSION (1 << 1) #define MODE_TEST (1 << 2) #define MODE_DAEMON (1 << 3) #define MODE_TRACE (1 << 4) #define MODE_CONFIGTEST (1 << 5) extern unsigned char mode; #ifdef ENABLE_TRACE #define tracef(...) if (mode & MODE_TRACE) { fprintf(stdout, __VA_ARGS__); fflush(stdout); } #else #define tracef(...) /* noop */ #endif extern char relay_hostname[]; enum logdst { LOGOUT, LOGERR }; typedef enum { CON_TCP, CON_UDP, CON_PIPE, CON_FILE, CON_UNIX } con_proto; typedef enum { T_LINEMODE } con_type; typedef enum { W_PLAIN, W_GZIP, W_LZ4, W_SSL } con_trnsp; int relaylog(enum logdst dest, const char *fmt, ...); #define logout(args...) relaylog(LOGOUT, args) #define logerr(args...) relaylog(LOGERR, args) #define saddr_ntop(SADDR, BUF) { \ BUF[0] = '\0'; \ if ((SADDR)->ai_family == PF_INET) { \ inet_ntop((SADDR)->ai_family, \ &((struct sockaddr_in *)(SADDR)->ai_addr)->sin_addr, \ BUF, sizeof(BUF)); \ } else if ((SADDR)->ai_family == PF_INET6) { \ inet_ntop((SADDR)->ai_family, \ &((struct sockaddr_in6 *)(SADDR)->ai_addr)->sin6_addr, \ BUF, sizeof(BUF)); \ } \ } #endif carbon-c-relay-3.2/router.c000066400000000000000000002346261317265605500156670ustar00rootroot00000000000000/* * Copyright 2013-2017 Fabian Groffen * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "fnv1a.h" #include "consistent-hash.h" #include "server.h" #include "queue.h" #include "aggregator.h" #include "allocator.h" #include "relay.h" #include "router.h" #include "conffile.h" #include "conffile.tab.h" struct _router { cluster *clusters; route *routes; aggregator *aggregators; servers *srvrs; struct _router_collector { char *stub; int interval; char *prefix; col_mode mode; } collector; listener *listeners; struct _router_parser_err { const char *msg; size_t line; size_t start; size_t stop; } parser_err; struct _router_conf { char workercnt; size_t queuesize; size_t batchsize; int maxstalls; unsigned short iotimeout; unsigned int sockbufsize; } conf; allocator *a; }; /* declarations to avoid symbol/include hell when doing config.yy.h */ int router_yylex_init(void **); void router_yy_scan_string(char *, void *); int router_yylex_destroy(void *); /* catch string used for aggrgator destinations */ #define STUB_AGGR "_aggregator_stub_" /* catch string used for collector output */ #define STUB_STATS "_collector_stub_" /** * Frees regexes from routes. */ static void router_free_intern(route *routes, char workercnt) { /* the only thing that isn't allocated using the allocators are the * regexes */ while (routes != NULL) { if (routes->matchtype == REGEX) { int i; for(i = 0; i < workercnt; i++) regfree(&routes->rule[i]); } if (routes->next == NULL || routes->next->dests != routes->dests) { while (routes->dests != NULL) { if (routes->dests->cl->type == GROUP || routes->dests->cl->type == AGGRSTUB || routes->dests->cl->type == STATSTUB) router_free_intern(routes->dests->cl->members.routes, workercnt); if (routes->dests->cl->type == VALIDATION) router_free_intern( routes->dests->cl->members.validation->rule, workercnt); routes->dests = routes->dests->next; } } routes = routes->next; } } /** * Examines pattern and sets matchtype and rule or strmatch in route. */ static inline int determine_if_regex(allocator *a, char workercnt, route *r, char *pat) { /* try and see if we can avoid using a regex match, for * it is simply very slow/expensive to do so: most of * the time, people don't need fancy matching rules */ char patbuf[8192]; char *e = pat; char *pb = patbuf; char escape = 0; r->matchtype = CONTAINS; r->nmatch = 0; if (*e == '^' && r->matchtype == CONTAINS) { e++; r->matchtype = STARTS_WITH; } for (; *e != '\0'; e++) { switch (*e) { case '\\': if (escape) *pb++ = *e; escape = !escape; break; case '.': case '^': case '*': case '+': if (!escape) r->matchtype = REGEX; *pb++ = *e; escape = 0; break; case '$': if (!escape && e[1] == '\0') { if (r->matchtype == STARTS_WITH) { r->matchtype = MATCHES; } else { r->matchtype = ENDS_WITH; } } else { r->matchtype = REGEX; } escape = 0; break; default: if ( !escape && ( (*e == '_') || (*e == '-') || (*e >= '0' && *e <= '9') || (*e >= 'a' && *e <= 'z') || (*e >= 'A' && *e <= 'Z') ) ) { *pb++ = *e; } else { r->matchtype = REGEX; } escape = 0; break; } if (pb - patbuf == sizeof(patbuf)) r->matchtype = REGEX; if (r->matchtype == REGEX) break; } if (r->matchtype != REGEX) { *pb = '\0'; r->strmatch = ra_strdup(a, patbuf); r->pattern = ra_strdup(a, pat); } else { int i; int ret; r->rule = ra_malloc(a, sizeof(*r->rule) * workercnt); if (r->rule == NULL) { logerr("determine_if_regex: malloc failed for " "regular expressions\n"); return REG_ESPACE; /* lie closest to the truth */ } ret = regcomp(&r->rule[0], pat, REG_EXTENDED); if (ret != 0) return ret; /* allow use of regerror */ if (r->rule[0].re_nsub > 0) { /* we need +1 because position 0 contains the entire * expression */ r->nmatch = r->rule[0].re_nsub + 1; if (r->nmatch > RE_MAX_MATCHES) { logerr("determine_if_regex: too many match groups, " "please increase RE_MAX_MATCHES in router.h\n"); regfree(&r->rule[0]); return REG_ESPACE; /* lie closest to the truth */ } } for (i = 1; i < workercnt; i++) { if (regcomp(&r->rule[i], pat, REG_EXTENDED) != 0) { while (--i >= 0) regfree(&r->rule[i]); logerr("determine_if_regex: out of memory allocating " "regexes\n"); return REG_ESPACE; /* lie closest to the truth */ } } r->strmatch = NULL; r->pattern = ra_strdup(a, pat); } return 0; } static char serverip_server[256]; /* RFC1035 = 250 */ static const char * serverip(server *s) { const char *srvr = server_ip(s); if (strchr(srvr, ':') != NULL) { snprintf(serverip_server, sizeof(serverip_server), "[%s]", srvr); return serverip_server; } return srvr; } /** * Callback for the bison parser for yyerror */ void router_yyerror( void *locptr, void *s, router *r, allocator *ra, allocator *a, const char *msg) { (void)s; ROUTER_YYLTYPE *locp = (ROUTER_YYLTYPE *)locptr; regex_t re; size_t nmatch = 3; regmatch_t pmatch[3]; char buf1[METRIC_BUFSIZ]; char buf2[METRIC_BUFSIZ]; char *dummy; char (*sa)[METRIC_BUFSIZ]; char (*sb)[METRIC_BUFSIZ]; char (*st)[METRIC_BUFSIZ]; if (r->parser_err.msg != NULL) return; /* clean up the "value" types */ if (regcomp(&re, "cr(STRING|COMMENT|INTVAL)", REG_EXTENDED) != 0) { r->parser_err.msg = ra_strdup(a, msg); return; } snprintf(buf1, sizeof(buf1), "%s", msg); sa = &buf1; sb = &buf2; while (regexec(&re, *sa, nmatch, pmatch, 0) == 0) { dummy = *sa + strlen(*sa); if (router_rewrite_metric(sb, &dummy, *sa, dummy, "\\_1", nmatch, pmatch) == 0) { r->parser_err.msg = ra_strdup(a, msg); return; } st = sa; sa = sb; sb = st; } regfree(&re); /* clean up the keywords */ if (regcomp(&re, "cr([A-Z][A-Z0-9]*)", REG_EXTENDED) != 0) { r->parser_err.msg = ra_strdup(a, msg); return; } while (regexec(&re, *sa, nmatch, pmatch, 0) == 0) { dummy = *sa + strlen(*sa); if (router_rewrite_metric(sb, &dummy, *sa, dummy, "'\\_1'", nmatch, pmatch) == 0) { r->parser_err.msg = ra_strdup(a, msg); return; } st = sa; sa = sb; sb = st; } regfree(&re); /* remove an artificial phrase */ if (regcomp(&re, ", unexpected 'unexpected'", REG_EXTENDED) != 0) { r->parser_err.msg = ra_strdup(a, msg); return; } while (regexec(&re, *sa, nmatch, pmatch, 0) == 0) { dummy = *sa + strlen(*sa); if (router_rewrite_metric(sb, &dummy, *sa, dummy, "", nmatch, pmatch) == 0) { r->parser_err.msg = ra_strdup(a, msg); return; } st = sa; sa = sb; sb = st; } regfree(&re); /* clean up bison speak */ if (regcomp(&re, "\\$end", REG_EXTENDED) != 0) { r->parser_err.msg = ra_strdup(a, msg); return; } while (regexec(&re, *sa, nmatch, pmatch, 0) == 0) { dummy = *sa + strlen(*sa); if (router_rewrite_metric(sb, &dummy, *sa, dummy, "end of file", nmatch, pmatch) == 0) { r->parser_err.msg = ra_strdup(a, msg); return; } st = sa; sa = sb; sb = st; } regfree(&re); r->parser_err.msg = ra_strdup(a, *sa); if (locp != NULL) { r->parser_err.line = 1 + locp->first_line; r->parser_err.start = locp->first_column; if (locp->first_line == locp->last_line) { r->parser_err.stop = locp->last_column; } else { r->parser_err.stop = locp->first_column; } } else { r->parser_err.line = 0; } } /** * Parse ip string and validate it. When it is a numeric address, write * the cannonical version in retip. */ char * router_validate_address( router *rtr, char **retip, int *retport, void **retsaddr, void **rethint, char *ip, con_proto proto) { int port = GRAPHITE_PORT; struct addrinfo *saddr = NULL; struct addrinfo hint; char sport[8]; char *p; char *lastcolon = NULL; for (p = ip; *p != '\0'; p++) if (*p == ':') lastcolon = p; if (*(p - 1) == ']') lastcolon = NULL; if (lastcolon != NULL) { char *endp = NULL; *lastcolon = '\0'; port = (int)strtol(lastcolon + 1, &endp, 10); if (port < 1 || endp != p) return(ra_strdup(rtr->a, "invalid port number")); } if (*ip == '[') { ip++; if (lastcolon != NULL && *(lastcolon - 1) == ']') { *(lastcolon - 1) = '\0'; } else if (lastcolon == NULL && *(p - 1) == ']') { *(p - 1) = '\0'; } else { return(ra_strdup(rtr->a, "expected ']'")); } } if (lastcolon == ip) ip = NULL; /* only resolve port, e.g. any interface */ memset(&hint, 0, sizeof(hint)); saddr = NULL; /* try to see if this is a "numeric" IP address, which means * re-resolving lateron will make no difference */ hint.ai_family = PF_UNSPEC; hint.ai_socktype = proto == CON_UDP ? SOCK_DGRAM : SOCK_STREAM; hint.ai_protocol = proto == CON_UDP ? IPPROTO_UDP : IPPROTO_TCP; hint.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV | AI_PASSIVE; snprintf(sport, sizeof(sport), "%u", port); *rethint = NULL; if (getaddrinfo(ip, sport, &hint, &saddr) != 0) { int err; /* now resolve this the normal way to check validity */ hint.ai_flags = AI_NUMERICSERV; if ((err = getaddrinfo(ip, sport, &hint, &saddr)) != 0) { char errmsg[512]; snprintf(errmsg, sizeof(errmsg), "warning: failed to resolve " "%s, port %s, proto %s: %s", ip == NULL ? "" : ip, sport, proto == CON_UDP ? "udp" : "tcp", gai_strerror(err)); saddr = NULL; } /* no ra_malloc, it gets owned by server */ *rethint = malloc(sizeof(hint)); if (*rethint == NULL) { freeaddrinfo(saddr); return(ra_strdup(rtr->a, "out of memory copying hint structure")); } memcpy(*rethint, &hint, sizeof(hint)); } *retip = ip; *retport = port; *retsaddr = saddr; return NULL; } /** * Parse path string and validate it can be written to. */ char * router_validate_path(router *rtr, char *path) { struct stat st; char fileexists = 1; int probefd; /* if the file doesn't exist, remove it after trying to create it */ if (stat(path, &st) == -1) fileexists = 0; if ((probefd = open(path, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) { char errbuf[512]; if (errno == EOPNOTSUPP && st.st_mode & S_IFSOCK) { /* This is pretty lame, but I don't know a better way: we * can't open sockets in use, and as it stands we can't * check it is *us* who have the socket in use. So, we * assume we do, and ignore this silently. In the worst * case this yields an error when it opens up for real. */ return NULL; } snprintf(errbuf, sizeof(errbuf), "failed to open file '%s' for writing: %s", path, strerror(errno)); return ra_strdup(rtr->a, errbuf); } close(probefd); if (!fileexists) unlink(path); return NULL; } /** * Checks pat against regular expression syntax (or being '*') and * returns a route struct with the parsed info. If retr is NULL a route * struct is allocated. */ char * router_validate_expression(router *rtr, route **retr, char *pat) { route *r = *retr; if (r == NULL) { r = *retr = ra_malloc(rtr->a, sizeof(route)); if (r == NULL) return ra_strdup(rtr->a, "out of memory allocating route"); r->next = NULL; r->dests = NULL; } if (strcmp(pat, "*") == 0) { r->pattern = NULL; r->strmatch = NULL; r->matchtype = MATCHALL; } else { int err = determine_if_regex(rtr->a, rtr->conf.workercnt, r, pat); if (err != 0) { char ebuf[512]; size_t s = snprintf(ebuf, sizeof(ebuf), "invalid expression '%s': ", pat); regerror(err, &r->rule[0], ebuf + s, sizeof(ebuf) - s); return ra_strdup(rtr->a, ebuf); } } return NULL; } /** * Check if cluster is defined, and set the pointer to it. */ char * router_validate_cluster(router *rtr, cluster **clptr, char *cl) { cluster *w; /* lookup cluster */ for (w = rtr->clusters; w != NULL; w = w->next) { if (w->type != GROUP && w->type != AGGRSTUB && w->type != STATSTUB && w->type != AGGREGATION && w->type != REWRITE && w->type != VALIDATION && strcmp(w->name, cl) == 0) break; } if (w == NULL) return ra_strdup(rtr->a, "unknown cluster"); *clptr = w; return NULL; } /** * Adds a server to the chain in router, expands if necessary. */ char * router_add_server( router *ret, char *ip, int port, char *inst, con_type type, con_trnsp transport, con_proto proto, struct addrinfo *saddrs, struct addrinfo *hint, char useall, cluster *cl) { struct addrinfo *walk; struct addrinfo *lwalk; char hnbuf[INET6_ADDRSTRLEN]; char errbuf[512]; server *newserver; servers *w = NULL; walk = saddrs; /* NULL if file */ do { servers *s; lwalk = NULL; if (useall) { /* serialise the IP address, to make the targets explicit * (since we're expanding all A/AAAA records) */ saddr_ntop(walk, hnbuf); if (hnbuf[0] != '\0') ip = hnbuf; /* now we've expanded, don't trigger re-resolving */ if (hint) free(hint); hint = NULL; /* and turn this into a separate entry */ lwalk = walk->ai_next; walk->ai_next = NULL; } newserver = NULL; for (s = ret->srvrs; s != NULL; s = s->next) { if (server_cmp(s->server, walk, ip) == 0) { newserver = s->server; s->refcnt++; break; } } if (newserver == NULL) { newserver = server_new(ip, (unsigned short)port, type, transport, proto, walk, hint, ret->conf.queuesize, ret->conf.batchsize, ret->conf.maxstalls, ret->conf.iotimeout, ret->conf.sockbufsize); if (newserver == NULL) { freeaddrinfo(saddrs); if (hint) free(hint); snprintf(errbuf, sizeof(errbuf), "failed to add server %s:%d (%s) " "to cluster %s", ip, port, proto == CON_UDP ? "udp" : proto == CON_TCP ? "tcp" : proto == CON_FILE ? "file" : "???", cl->name); return ra_strdup(ret->a, errbuf); } if (ret->srvrs == NULL) { s = ret->srvrs = ra_malloc(ret->a, sizeof(servers)); } else { for (s = ret->srvrs; s->next != NULL; s = s->next) ; s = s->next = ra_malloc(ret->a, sizeof(servers)); } s->next = NULL; s->refcnt = 1; s->server = newserver; } /* check instance matches the existing server */ if (s->refcnt > 1) { char *sinst = server_instance(newserver); if (sinst == NULL && inst != NULL) { freeaddrinfo(saddrs); if (hint) free(hint); snprintf(errbuf, sizeof(errbuf), "cannot set instance '%s' for " "server %s:%d: server was previously " "defined without instance", inst, serverip(newserver), server_port(newserver)); return ra_strdup(ret->a, errbuf); } else if (sinst != NULL && inst == NULL) { freeaddrinfo(saddrs); if (hint) free(hint); snprintf(errbuf, sizeof(errbuf), "cannot define server %s:%d without " "instance: server was previously " "defined with instance '%s'", serverip(newserver), server_port(newserver), sinst); return ra_strdup(ret->a, errbuf); } else if (sinst != NULL && inst != NULL && strcmp(sinst, inst) != 0) { freeaddrinfo(saddrs); if (hint) free(hint); snprintf(errbuf, sizeof(errbuf), "cannot set instance '%s' for " "server %s:%d: server was previously " "defined with instance '%s'", inst, serverip(newserver), server_port(newserver), sinst); return ra_strdup(ret->a, errbuf); } /* else: sinst == inst == NULL */ } if (inst != NULL) server_set_instance(newserver, inst); if (cl->type == CARBON_CH || cl->type == FNV1A_CH || cl->type == JUMP_CH) { if (cl->members.ch->servers == NULL) { cl->members.ch->servers = w = ra_malloc(ret->a, sizeof(servers)); } else { for (w = cl->members.ch->servers; w->next != NULL; w = w->next) ; w = w->next = ra_malloc(ret->a, sizeof(servers)); } if (w == NULL) { snprintf(errbuf, sizeof(errbuf), "malloc failed for %s_ch %s", cl->type == CARBON_CH ? "carbon" : cl->type == FNV1A_CH ? "fnv1a" : "jump_fnv1a", ip); freeaddrinfo(saddrs); if (hint) free(hint); return ra_strdup(ret->a, errbuf); } w->next = NULL; w->server = newserver; cl->members.ch->ring = ch_addnode( cl->members.ch->ring, w->server); if (cl->members.ch->ring == NULL) { freeaddrinfo(saddrs); if (hint) free(hint); snprintf(errbuf, sizeof(errbuf), "failed to add server %s:%d " "to ring for cluster %s: out of memory", ip, port, cl->name); return ra_strdup(ret->a, errbuf); } } else if (cl->type == FORWARD || cl->type == FILELOG || cl->type == FILELOGIP) { if (cl->members.forward == NULL) { cl->members.forward = w = ra_malloc(ret->a, sizeof(servers)); } else { for (w = cl->members.forward; w->next != NULL; w = w->next) ; w = w->next = ra_malloc(ret->a, sizeof(servers)); } if (w == NULL) { snprintf(errbuf, sizeof(errbuf), "malloc failed for %s %s", cl->type == FORWARD ? "forward" : cl->type == FILELOG ? "file" : "file ip", ip); freeaddrinfo(saddrs); if (hint) free(hint); return ra_strdup(ret->a, errbuf); } w->next = NULL; w->server = newserver; } else if (cl->type == ANYOF || cl->type == FAILOVER) { if (cl->members.anyof == NULL) { cl->members.anyof = ra_malloc(ret->a, sizeof(serverlist)); if (cl->members.anyof != NULL) { cl->members.anyof->list = w = ra_malloc(ret->a, sizeof(servers)); cl->members.anyof->count = 1; cl->members.anyof->servers = NULL; } } else { for (w = cl->members.anyof->list; w->next != NULL; w = w->next) ; w = w->next = ra_malloc(ret->a, sizeof(servers)); cl->members.anyof->count++; } if (w == NULL) { snprintf(errbuf, sizeof(errbuf), "malloc failed for %s %s", cl->type == ANYOF ? "any_of" : "failover", ip); freeaddrinfo(saddrs); if (hint) free(hint); return ra_strdup(ret->a, errbuf); } w->next = NULL; w->server = newserver; if (s->refcnt > 1) { freeaddrinfo(saddrs); if (hint) free(hint); snprintf(errbuf, sizeof(errbuf), "cannot share server %s:%d with " "any_of/failover cluster '%s'", serverip(newserver), server_port(newserver), cl->name); return ra_strdup(ret->a, errbuf); } } walk = lwalk; } while (walk != NULL); return NULL; } char * router_add_cluster(router *r, cluster *cl) { cluster *cw; cluster *last = NULL; servers *w; for (cw = r->clusters; cw != NULL; last = cw, cw = cw->next) if (cw->name != NULL && cl->name != NULL && strcmp(cw->name, cl->name) == 0) return ra_strdup(r->a, "cluster with the same name already defined"); if (last == NULL) last = r->clusters; last->next = cl; /* post checks/fixups */ if (cl->type == ANYOF || cl->type == FAILOVER) { size_t i = 0; cl->members.anyof->servers = ra_malloc(r->a, sizeof(server *) * cl->members.anyof->count); if (cl->members.anyof->servers == NULL) return ra_strdup(r->a, "malloc failed for anyof servers"); for (w = cl->members.anyof->list; w != NULL; w = w->next) cl->members.anyof->servers[i++] = w->server; for (w = cl->members.anyof->list; w != NULL; w = w->next) { server_add_secondaries(w->server, cl->members.anyof->servers, cl->members.anyof->count); if (cl->type == FAILOVER) server_set_failover(w->server); } } else if (cl->type == CARBON_CH || cl->type == FNV1A_CH || cl->type == JUMP_CH) { /* check that replication count is actually <= the * number of servers */ size_t i = 0; char errbuf[512]; for (w = cl->members.ch->servers; w != NULL; w = w->next) i++; if (i < cl->members.ch->repl_factor) { snprintf(errbuf, sizeof(errbuf), "invalid cluster '%s': replication count (%u) is " "larger than the number of servers (%zu)\n", cl->name, cl->members.ch->repl_factor, i); return ra_strdup(r->a, errbuf); } } return NULL; } char * router_add_route(router *rtr, route *rte) { route *rw; route *last = NULL; route *matchallstop = NULL; for (rw = rtr->routes; rw != NULL; last = rw, rw = rw->next) if (rw->matchtype == MATCHALL && rw->stop) matchallstop = rw; if (last == NULL) { rtr->routes = rte; return NULL; } #define matchtype(r) \ r->dests->cl->type == AGGREGATION ? "aggregate" : \ r->dests->cl->type == REWRITE ? "rewrite" : \ "match" if (matchallstop != NULL) { logerr("warning: %s %s will never match " "due to preceding %s * ... stop\n", matchtype(rte), rte->pattern == NULL ? "*" : rte->pattern, matchtype(matchallstop)); } last->next = rte; return NULL; } char * router_add_aggregator(router *rtr, aggregator *a) { aggregator *aw; aggregator *last = NULL; for (aw = rtr->aggregators; aw != NULL; last = aw, aw = aw->next) ; if (last == NULL) { rtr->aggregators = a; return NULL; } last->next = a; return NULL; } char * router_add_stubroute( router *rtr, enum clusttype type, cluster *w, destinations *dw) { char stubname[48]; route *m; destinations *d; cluster *cl; char *err; m = ra_malloc(rtr->a, sizeof(route)); if (m == NULL) return ra_strdup(rtr->a, "malloc failed for stub route"); m->pattern = NULL; m->strmatch = NULL; m->dests = dw; m->stop = 1; m->matchtype = MATCHALL; m->next = NULL; /* inject stub route for dests */ d = ra_malloc(rtr->a, sizeof(destinations)); if (d == NULL) return ra_strdup(rtr->a, "malloc failed for stub destinations"); d->next = NULL; cl = d->cl = ra_malloc(rtr->a, sizeof(cluster)); if (cl == NULL) return ra_strdup(rtr->a, "malloc failed for stub cluster"); cl->name = NULL; cl->type = type; cl->members.routes = m; cl->next = NULL; err = router_add_cluster(rtr, cl); if (err != NULL) return err; if (type == AGGRSTUB) { snprintf(stubname, sizeof(stubname), STUB_AGGR "%p__", w->members.aggregation); } else if (type == STATSTUB) { snprintf(stubname, sizeof(stubname), STUB_STATS "%p__", rtr); } else { return ra_strdup(rtr->a, "unknown stub type"); } m = ra_malloc(rtr->a, sizeof(route)); if (m == NULL) return ra_strdup(rtr->a, "malloc failed for catch stub route"); m->pattern = ra_strdup(rtr->a, stubname); m->strmatch = ra_strdup(rtr->a, stubname); if (m->pattern == NULL || m->strmatch == NULL) ra_strdup(rtr->a, "malloc failed for catch stub pattern"); m->dests = d; m->stop = 1; m->matchtype = STARTS_WITH; /* enforce first match to avoid interference */ m->next = rtr->routes; rtr->routes = m; if (type == AGGRSTUB) { aggregator_set_stub(w->members.aggregation, stubname); } else if (type == STATSTUB) { rtr->collector.stub = m->pattern; } return NULL; } char * router_add_listener( router *rtr, con_type ltype, con_trnsp trnsp, char *pemcert, con_proto ctype, char *ip, int port, struct addrinfo *saddrs) { listener *lwalk; listener *prevl; struct addrinfo *swalk; struct addrinfo *lswalk; int addrcnt; #ifdef HAVE_SSL struct stat st; #endif if (saddrs == NULL && (ctype == CON_UDP || ctype == CON_TCP)) { char msg[256]; snprintf(msg, sizeof(msg), "invalid listener %s for port %d", ip, port); return ra_strdup(rtr->a, msg); } if (rtr->listeners == NULL) { lwalk = rtr->listeners = ra_malloc(rtr->a, sizeof(listener)); } else { char hnbufl[INET6_ADDRSTRLEN]; char hnbufr[INET6_ADDRSTRLEN]; prevl = NULL; for (lwalk = rtr->listeners; lwalk != NULL; lwalk = lwalk->next) { for (swalk = saddrs; swalk != NULL; swalk = swalk->ai_next) { saddr_ntop(swalk, hnbufl); if (lwalk->ctype == ctype && lwalk->port == port) { for (lswalk = lwalk->saddrs; lswalk != NULL; lswalk = lswalk->ai_next) { saddr_ntop(lswalk, hnbufr); /* ip is equal if: * - the address family is the same (ipv4/ipv6) * - at least one of the sides is 0.0.0.0 (ipv4 any) * - at least one of the sides is :: (ipv6 any) * - both sides are equal */ if (swalk->ai_family == lswalk->ai_family && ( strcmp(hnbufl, "0.0.0.0") == 0 || strcmp(hnbufr, "0.0.0.0") == 0 || strcmp(hnbufl, "::") == 0 || strcmp(hnbufr, "::") == 0 || strcmp(hnbufl, hnbufr) == 0)) { char msg[256]; snprintf(msg, sizeof(msg), "duplicate listener %s with %s for port %d", hnbufl, hnbufr, port); return ra_strdup(rtr->a, msg); } } } } if (saddrs == NULL) { /* UNIX */ if (lwalk->ctype == ctype && strcmp(lwalk->ip, ip) == 0) { char msg[256]; snprintf(msg, sizeof(msg), "duplicate listener %s", ip); return ra_strdup(rtr->a, msg); } } prevl = lwalk; } lwalk = prevl->next = ra_malloc(rtr->a, sizeof(listener)); } if (lwalk == NULL) return ra_strdup(rtr->a, "malloc failed for listener struct"); lwalk->lsnrtype = ltype; lwalk->transport = trnsp; lwalk->ctype = ctype; lwalk->ip = ip == NULL ? ip : ra_strdup(rtr->a, ip); lwalk->port = port; lwalk->socks = NULL; lwalk->saddrs = saddrs; #ifdef HAVE_SSL lwalk->ctx = NULL; lwalk->sslstrms = NULL; lwalk->pemcert = pemcert; if (stat(pemcert, &st) != -1) { memcpy(&(lwalk->pemmtimespec), &(st.st_mtime), sizeof(struct timespec)); } else { lwalk->pemmtimespec.tv_sec = 0; lwalk->pemmtimespec.tv_nsec = 0; } #else (void)pemcert; /* not used */ #endif lwalk->next = NULL; addrcnt = saddrs == NULL ? 1 : 0; for (swalk = saddrs; swalk != NULL; swalk = swalk->ai_next) addrcnt++; lwalk->socks = ra_malloc(rtr->a, sizeof(int) * (addrcnt + 1)); if (lwalk->socks == NULL) return ra_strdup(rtr->a, "malloc failed for sockets"); lwalk->socks[0] = -1; return NULL; } inline char * router_set_statistics(router *rtr, destinations *dsts) { if (rtr->collector.stub != NULL) return ra_strdup(rtr->a, "duplicate 'statistics send to' not allowed, " "use multiple destinations instead"); return router_add_stubroute(rtr, STATSTUB, NULL, dsts); } /** * Populates the routing tables by reading the config file. */ router * router_readconfig(router *orig, const char *path, char workercnt, size_t queuesize, size_t batchsize, int maxstalls, unsigned short iotimeout, unsigned int sockbufsize, unsigned short listenport) { FILE *cnf; char *buf; size_t len = 0; struct stat st; router *ret = NULL; void *lptr = NULL; allocator *palloc; if (strchr(path, '*') || strchr(path, '?') || (strchr(path, '[') && strchr(path, ']'))) { /* include path is a glob pattern */ glob_t globbuf; char *globpath; size_t i; if ((i = glob(path, 0, NULL, &globbuf)) != 0) { switch (i) { case GLOB_NOSPACE: /* since we don't set a limit, we won't * reach it either */ logerr("out of memory while globbing files for " "pattern '%s'\n", path); return NULL; case GLOB_ABORTED: /* we don't use a call-back, so this is * a real error of some sort */ logerr("unable to match any files from " "pattern '%s': %s\n", path, strerror(errno)); return NULL; case GLOB_NOMATCH: /* we don't want to abort on failing globs */ logout("warning: pattern '%s' did not match " "any files\n", path); return NULL; } } /* read all files matched by glob */ ret = orig; for (i = 0; i < globbuf.gl_pathc; i++) { globpath = globbuf.gl_pathv[i]; ret = router_readconfig(ret, globpath, workercnt, queuesize, batchsize, maxstalls, iotimeout, sockbufsize, listenport); if (ret == NULL) { /* readconfig will have freed when it found the error */ break; } } /* also after errors the globbuf structure is * initialised and might need free-ing */ globfree(&globbuf); return ret; } /* else: include path is a regular file path */ /* if there is no config, don't try anything */ if (stat(path, &st) == -1) { logerr("unable to stat file '%s': %s\n", path, strerror(errno)); return NULL; } if (orig == NULL) { cluster *cl; char *err; /* get a return structure (and allocator) in place */ if ((ret = malloc(sizeof(router))) == NULL) { logerr("malloc failed for router return struct\n"); return NULL; } ret->a = ra_new(); if (ret->a == NULL) { logerr("malloc failed for allocator\n"); free(ret); return NULL; } ret->routes = NULL; ret->aggregators = NULL; ret->srvrs = NULL; ret->clusters = NULL; err = router_set_collectorvals(ret, 60, "carbon.relays.\\.1", CUM); if (err != NULL) { logerr("setcollectorvals: %s\n"); router_free(ret); return NULL; } ret->collector.stub = NULL; ret->listeners = NULL; ret->conf.workercnt = workercnt; ret->conf.queuesize = queuesize; ret->conf.batchsize = batchsize; ret->conf.maxstalls = maxstalls; ret->conf.iotimeout = iotimeout; ret->conf.sockbufsize = sockbufsize; /* create virtual blackhole cluster */ cl = ra_malloc(ret->a, sizeof(cluster)); if (cl == NULL) { logerr("malloc failed for blackhole cluster\n"); router_free(ret); return NULL; } cl->name = ra_strdup(ret->a, "blackhole"); if (cl->name == NULL) { logerr("malloc failed for blackhole cluster name\n"); router_free(ret); return NULL; } cl->type = BLACKHOLE; cl->members.forward = NULL; cl->next = NULL; ret->clusters = cl; } else { ret = orig; } /* parser allocator for memory needs during parsing only */ palloc = ra_new(); if (palloc == NULL) { logerr("malloc failed for parse allocator\n"); router_free(ret); return NULL; } if ((buf = ra_malloc(palloc, st.st_size + 1)) == NULL) { logerr("malloc failed for config file buffer\n"); ra_free(palloc); router_free(ret); return NULL; } if ((cnf = fopen(path, "r")) == NULL) { logerr("failed to open config file '%s': %s\n", path, strerror(errno)); ra_free(palloc); router_free(ret); return NULL; } while ((len = fread(buf + len, 1, st.st_size - len, cnf)) != 0) ; buf[st.st_size] = '\0'; fclose(cnf); if (router_yylex_init(&lptr) != 0) { logerr("lex init failed\n"); ra_free(palloc); router_free(ret); return NULL; } /* copies buf due to modifications, we need orig for error reporting */ router_yy_scan_string(buf, lptr); ret->parser_err.msg = NULL; if (router_yyparse(lptr, ret, ret->a, palloc) != 0) { /* parser_err.msg can be NULL on cascading, see below */ if (ret->parser_err.line != 0) { char *line; char *p; char *carets; size_t carlen; fprintf(stderr, "%s:%zd:%zd: %s\n", path, ret->parser_err.line, ret->parser_err.start, ret->parser_err.msg); /* get some relevant context from buff and put ^^^^ below it * to point out the position of the error */ line = buf; while (ret->parser_err.line-- > 1 && line != NULL) { line = strchr(line, '\n'); if (line) line++; } if (line == NULL) line = buf; /* fallback, but will cause misplacement */ if ((p = strchr(line + ret->parser_err.stop, '\n')) != NULL) *p = '\0'; carlen = ret->parser_err.stop - ret->parser_err.start + 1; carets = ra_malloc(palloc, carlen + 1); memset(carets, '^', carlen); carets[carlen] = '\0'; fprintf(stderr, "%s\n", line); /* deal with tabs in the input */ for (p = line; p - line < ret->parser_err.start; p++) if (*p != '\t') *p = ' '; *p = '\0'; fprintf(stderr, "%s%s\n", line, carets); } else if (ret->parser_err.msg != NULL) { fprintf(stderr, "%s: %s\n", path, ret->parser_err.msg); } /* clear the message, so it isn't printed when this was an * included config */ ret->parser_err.msg = NULL; router_yylex_destroy(lptr); ra_free(palloc); router_free(ret); return NULL; } router_yylex_destroy(lptr); ra_free(palloc); if (orig == NULL) { /* set defaults if absent */ if (ret->listeners == NULL) { char sockbuf[128]; char *ip; int port; void *saddrs; void *hint; hint = NULL; snprintf(sockbuf, sizeof(sockbuf), ":%u", listenport); router_validate_address(ret, &ip, &port, &saddrs, &hint, sockbuf, CON_TCP); free(hint); router_add_listener(ret, T_LINEMODE, W_PLAIN, NULL, CON_TCP, ip, port, saddrs); hint = NULL; snprintf(sockbuf, sizeof(sockbuf), ":%u", listenport); router_validate_address(ret, &ip, &port, &saddrs, &hint, sockbuf, CON_UDP); free(hint); router_add_listener(ret, T_LINEMODE, W_PLAIN, NULL, CON_UDP, ip, port, saddrs); snprintf(sockbuf, sizeof(sockbuf), "%s/%s.%u", TMPDIR, SOCKFILE, listenport); router_add_listener(ret, T_LINEMODE, W_PLAIN, NULL, CON_UNIX, sockbuf, 0, NULL); } } return ret; } typedef struct _block { char *pattern; size_t hash; size_t refcnt; size_t seqnr; route *firstroute; route *lastroute; struct _block *prev; struct _block *next; } block; /** * Tries to optimise the match and aggregation rules in such a way that * the number of matches for non-matching metrics are reduced. The * problem is that with many metrics flowing in, the time to perform * lots of regex matches is high. This is not too bad if that time * spent actually results in a metric being counted (aggregation) or * sent further (match), but it is when the metric would be discarded * for it did not match anything. * Hence, we employ a simple strategy to try and reduce the incoming * stream of metrics as soon as possible before performing the more * specific and expensive matches to confirm fit. */ void router_optimise(router *r, int threshold) { char *p; char pblock[64]; char *b; route *rwalk; route *rnext; route *rlast; block *blocks; block *bwalk; block *bstart; block *blast; size_t bsum; size_t seq; /* avoid optimising anything if it won't pay off, note that threshold * can be negative, meaning it will never optimise */ seq = 0; for (rwalk = r->routes; rwalk != NULL && seq < threshold; rwalk = rwalk->next) seq++; if (seq < threshold) return; tracef("triggering optimiser, seq: %zd, threshold: %d\n", seq, threshold); /* Heuristic: the last part of the matching regex is the most * discriminating part of the metric. The last part is defined as a * block of characters matching [a-zA-Z_]+ at the end disregarding * any characters not matched by the previous expression. Then from * these last parts we create groups, that -- if having enough * members -- is used to reduce the amount of comparisons done * before determining that an input metric cannot match any * expression we have defined. */ seq = 0; blast = bstart = blocks = ra_malloc(r->a, sizeof(block)); if (blocks == NULL) { logerr("out of memory allocating blocks, skipping optimisation\n"); return; } blocks->refcnt = 0; blocks->pattern = NULL; blocks->hash = 0; blocks->seqnr = seq++; blocks->prev = NULL; blocks->next = NULL; rlast = NULL; for (rwalk = r->routes; rwalk != NULL; rwalk = rnext) { /* matchall and rewrite rules cannot be in a group (issue #218) */ if (rwalk->matchtype == MATCHALL || rwalk->dests->cl->type == REWRITE) { tracef("skipping %s\n", rwalk->pattern ? rwalk->pattern : "*"); blast->next = ra_malloc(r->a, sizeof(block)); if (blast->next == NULL) { logerr("out of memory allocating new block, " "skipping optimisation\n"); return; } blast->next->prev = blast; blast = blast->next; blast->pattern = NULL; blast->hash = 0; blast->refcnt = 1; blast->seqnr = seq++; blast->firstroute = rwalk; blast->lastroute = rwalk; blast->next = NULL; rnext = rwalk->next; rwalk->next = NULL; bstart = blast; rlast = NULL; continue; } p = rwalk->pattern + strlen(rwalk->pattern); /* strip off chars that won't belong to a block */ bsum = 0; while ( p > rwalk->pattern && ( bsum > 0 || ( (*p < 'a' || *p > 'z') && (*p < 'A' || *p > 'Z') && *p != '_' ) ) ) { if (*p == ')' || *p == '(') { char esc = 0; char oe = *p; /* trim escapes, need to figure out if this is escaped * or not, in order to find the a matching open or not */ for (--p; p > rwalk->pattern && *p == '\\'; p--) esc = !esc; if (!esc) /* not escaped */ bsum += oe == ')' ? 1 : -1; continue; /* skip p-- */ } p--; } if (p == rwalk->pattern) { /* nothing we can do with a pattern like this */ tracef("skipping unusable %s\n", p); blast->next = ra_malloc(r->a, sizeof(block)); if (blast->next == NULL) { logerr("out of memory allocating new block, " "skipping optimisation\n"); return; } blast->next->prev = blast; blast = blast->next; blast->pattern = NULL; blast->hash = 0; blast->refcnt = 1; blast->seqnr = seq++; blast->firstroute = rwalk; blast->lastroute = rwalk; blast->next = NULL; rnext = rwalk->next; rwalk->next = NULL; bstart = blast; rlast = NULL; continue; } /* find the block */ bsum = 0; b = pblock; while ( p >= rwalk->pattern && b - pblock < sizeof(pblock) && ( (*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || *p == '_' ) ) { bsum += *p; *b++ = *p--; } *b = '\0'; b = pblock; if (strlen(b) < 3) { /* this probably isn't selective enough, don't put in a group */ tracef("skipping too small pattern %s from %s\n", b, rwalk->pattern); blast->next = ra_malloc(r->a, sizeof(block)); if (blast->next == NULL) { logerr("out of memory allocating new block, " "skipping optimisation\n"); return; } blast->next->prev = blast; blast = blast->next; blast->pattern = NULL; blast->hash = 0; blast->refcnt = 1; blast->seqnr = seq++; blast->firstroute = rwalk; blast->lastroute = rwalk; blast->next = NULL; rnext = rwalk->next; rwalk->next = NULL; bstart = blast; rlast = NULL; continue; } tracef("found pattern %s from %s\n", b, rwalk->pattern); /* at this point, b points to the tail block in reverse, see if * we already had such tail in place */ for (bwalk = bstart; bwalk != NULL; bwalk = bwalk->next) { if (bwalk->hash != bsum || strcmp(bwalk->pattern, b) != 0) continue; break; } if (bwalk == NULL) { tracef("creating new group %s for %s\n", b, rwalk->pattern); blast->next = ra_malloc(r->a, sizeof(block)); if (blast->next == NULL) { logerr("out of memory allocating new block, " "skipping optimisation\n"); return; } blast->next->prev = blast; blast = blast->next; blast->pattern = ra_strdup(r->a, b); blast->hash = bsum; blast->refcnt = 1; blast->seqnr = seq; blast->firstroute = rwalk; blast->lastroute = rwalk; blast->next = NULL; rnext = rwalk->next; rwalk->next = NULL; if (rwalk->stop) { bstart = blast; rlast = NULL; seq++; } continue; } tracef("adding %s to existing group %s\n", rwalk->pattern, b); bwalk->refcnt++; bwalk->lastroute = bwalk->lastroute->next = rwalk; rnext = rwalk->next; rwalk->next = NULL; if (rlast == NULL || strcmp(rlast->pattern, b) == 0) { if (rwalk->stop) { /* move this one to the end */ if (bwalk->next != NULL) { bwalk->prev->next = bwalk->next; blast = blast->next = bwalk; bwalk->next = NULL; } rlast = rwalk; } } else { bstart = blast; rlast = NULL; seq++; } } /* make loop below easier by appending a dummy (reuse the one from * start) */ blast = blast->next = blocks; blocks = blocks->next; blast->next = NULL; blast->seqnr = seq; rwalk = r->routes = NULL; seq = 1; /* create groups, if feasible */ for (bwalk = blocks; bwalk != NULL; bwalk = blast) { if (bwalk->seqnr != seq) { seq++; blast = bwalk; continue; } if (bwalk->refcnt == 0) { blast = bwalk->next; continue; } else if (bwalk->refcnt < 3) { if (r->routes == NULL) { r->routes = bwalk->firstroute; } else { rwalk->next = bwalk->firstroute; } rwalk = bwalk->lastroute; blast = bwalk->next; } else { if (r->routes == NULL) { rwalk = r->routes = ra_malloc(r->a, sizeof(route)); } else { rwalk = rwalk->next = ra_malloc(r->a, sizeof(route)); } rwalk->pattern = NULL; rwalk->stop = 0; rwalk->matchtype = CONTAINS; rwalk->dests = ra_malloc(r->a, sizeof(destinations)); rwalk->dests->cl = ra_malloc(r->a, sizeof(cluster)); rwalk->dests->cl->name = bwalk->pattern; rwalk->dests->cl->type = GROUP; rwalk->dests->cl->members.routes = bwalk->firstroute; rwalk->dests->cl->next = NULL; rwalk->dests->next = NULL; rwalk->next = NULL; blast = bwalk->next; } } } /** * Returns all (unique) servers from the cluster-configuration. */ server ** router_getservers(router *r) { server **ret; servers *s; int i; i = 0; for (s = r->srvrs; s != NULL; s = s->next) i++; ret = malloc(sizeof(server *) * (i + 1)); if (ret == NULL) return NULL; i = 0; for (s = r->srvrs; s != NULL; s = s->next) ret[i++] = s->server; /* ensure NULL-termination */ ret[i] = NULL; return ret; } /** * Returns all aggregators from this router configuration */ inline aggregator * router_getaggregators(router *rtr) { return rtr->aggregators; } /** * Returns the stub prefix to use for collector stats, or NULL if no * such thing should be employed. */ inline char * router_getcollectorstub(router *rtr) { return rtr->collector.stub; } /** * Returns the interval in seconds for collector stats. */ inline int router_getcollectorinterval(router *rtr) { return rtr->collector.interval; } /** * Returns the interval in seconds for collector stats. */ inline char * router_getcollectorprefix(router *rtr) { return rtr->collector.prefix; } /** * Returns the mode (SUB or CUM) in which the collector should operate. */ inline col_mode router_getcollectormode(router *rtr) { return rtr->collector.mode; } /** * Sets the collector interval in seconds, the metric prefix string, and * the emission mode (cumulative or sum). */ inline char * router_set_collectorvals(router *rtr, int intv, char *prefix, col_mode smode) { if (intv >= 0) rtr->collector.interval = intv; if (prefix != NULL) { regex_t re; char cprefix[METRIC_BUFSIZ]; char *expr = "^(([^.]+)(\\..*)?)$"; char *dummy = relay_hostname + strlen(relay_hostname); size_t nmatch = 3; regmatch_t pmatch[3]; if (regcomp(&re, expr, REG_EXTENDED) != 0) return ra_strdup(rtr->a, "failed to compile hostname regexp"); if (regexec(&re, relay_hostname, nmatch, pmatch, 0) != 0) { regfree(&re); return ra_strdup(rtr->a, "failed to execute hostname regexp"); } if (router_rewrite_metric( &cprefix, &dummy, relay_hostname, dummy, prefix, nmatch, pmatch) == 0) { regfree(&re); return ra_strdup(rtr->a, "rewriting statistics prefix failed"); } regfree(&re); rtr->collector.prefix = ra_strdup(rtr->a, cprefix); if (rtr->collector.prefix == NULL) return ra_strdup(rtr->a, "out of memory"); } rtr->collector.mode = smode; return NULL; } /** * Mere debugging function to check if the configuration is picked up * alright. If all is set to false, aggregation rules won't be printed. * This comes in handy because aggregations usually come in the order of * thousands. */ void router_printconfig(router *rtr, FILE *f, char pmode) { cluster *c; route *r; servers *s; /* start with configuration wise standard components */ #define PPROTO \ server_ctype(s->server) == CON_UDP ? " proto udp" : "" #define PTYPE \ server_type(s->server) == T_LINEMODE ? "" : " type ???" #define PTRNSP \ server_transport(s->server) == W_PLAIN ? "" : \ server_transport(s->server) == W_GZIP ? " transport gzip" : \ server_transport(s->server) == W_LZ4 ? " transport lz4" : \ server_transport(s->server) == W_SSL ? " transport ssl" : " unknown" if (rtr->listeners != NULL) { listener *walk; fprintf(f, "listen\n"); for (walk = rtr->listeners; walk != NULL; walk = walk->next) { if (walk->lsnrtype == T_LINEMODE) { fprintf(f, " type linemode%s%s%s", walk->transport == W_PLAIN ? "" : walk->transport == W_GZIP ? " transport gzip" : walk->transport == W_LZ4 ? " transport lz4" : walk->transport == W_SSL ? " transport ssl" : " unknown", walk->transport == W_SSL ? " " : "", #ifdef HAVE_SSL walk->transport == W_SSL ? walk->pemcert : "" #else "" #endif ); #ifdef HAVE_SSL if (walk->transport == W_SSL && pmode & PMODE_PEMT) { fprintf(f, " # mtime %ld.%ld", walk->pemmtimespec.tv_sec, walk->pemmtimespec.tv_nsec); } #endif fprintf(f, "\n"); do { if (walk->ctype == CON_UNIX) { fprintf(f, " %s proto unix\n", walk->ip); } else { fprintf(f, " %s%s%u proto %s\n", walk->ip == NULL ? "" : walk->ip, walk->ip == NULL ? "" : ":", walk->port, walk->ctype == CON_UDP ? "udp" : "tcp"); } } while (walk->next != NULL && walk->lsnrtype == walk->next->lsnrtype && walk->transport == walk->next->transport && (walk = walk->next) != NULL); } } fprintf(f, " ;\n\n"); } if (rtr->collector.interval > 0) { fprintf(f, "statistics\n submit every %d seconds\n", rtr->collector.interval); if (rtr->collector.mode == SUB) fprintf(f, " reset counters after interval\n"); fprintf(f, " prefix with %s\n", rtr->collector.prefix); if (rtr->collector.stub != NULL) { fprintf(f, " send to"); for (r = rtr->routes; r != NULL; r = r->next) { if (r->dests->cl->type == STATSTUB) { destinations *d = r->dests->cl->members.routes->dests; if (d->next == NULL) { fprintf(f, " %s", d->cl->name); } else { for ( ; d != NULL; d = d->next) fprintf(f, "\n %s", d->cl->name); } fprintf(f, "\n stop\n"); break; } } } fprintf(f, " ;\n"); fprintf(f, "\n"); } for (c = rtr->clusters; c != NULL; c = c->next) { if (c->type == BLACKHOLE || c->type == REWRITE || c->type == GROUP || c->type == AGGREGATION || c->type == AGGRSTUB || c->type == STATSTUB) continue; fprintf(f, "cluster %s\n", c->name); if (c->type == FORWARD) { fprintf(f, " forward\n"); for (s = c->members.forward; s != NULL; s = s->next) fprintf(f, " %s:%d%s%s%s\n", serverip(s->server), server_port(s->server), PPROTO, PTYPE, PTRNSP); } else if (c->type == FILELOG || c->type == FILELOGIP) { fprintf(f, " file%s\n", c->type == FILELOGIP ? " ip" : ""); for (s = c->members.forward; s != NULL; s = s->next) fprintf(f, " %s\n", serverip(s->server)); } else if (c->type == ANYOF || c->type == FAILOVER) { fprintf(f, " %s\n", c->type == ANYOF ? "any_of" : "failover"); for (s = c->members.anyof->list; s != NULL; s = s->next) fprintf(f, " %s:%d%s%s%s\n", serverip(s->server), server_port(s->server), PPROTO, PTYPE, PTRNSP); } else if (c->type == CARBON_CH || c->type == FNV1A_CH || c->type == JUMP_CH) { fprintf(f, " %s_ch replication %d\n", c->type == CARBON_CH ? "carbon" : c->type == FNV1A_CH ? "fnv1a" : "jump_fnv1a", c->members.ch->repl_factor); for (s = c->members.ch->servers; s != NULL; s = s->next) fprintf(f, " %s:%d%s%s%s%s%s\n", serverip(s->server), server_port(s->server), server_instance(s->server) ? "=" : "", server_instance(s->server) ? server_instance(s->server) : "", PPROTO, PTYPE, PTRNSP); } fprintf(f, " ;\n"); if (pmode & PMODE_HASH) { if (c->type == CARBON_CH || c->type == FNV1A_CH || c->type == JUMP_CH) { fprintf(f, "# hash ring for %s follows\n", c->name); ch_printhashring(c->members.ch->ring, f); } } } fprintf(f, "\n"); for (r = rtr->routes; r != NULL; r = r->next) { if (r->dests->cl->type == AGGREGATION) { cluster *aggr = r->dests->cl; struct _aggr_computes *ac; char stubname[48]; char percentile[16]; if (!(pmode & PMODE_AGGR)) continue; if (pmode & PMODE_STUB || r->dests->next == NULL) { stubname[0] = '\0'; } else { snprintf(stubname, sizeof(stubname), STUB_AGGR "%p__", aggr->members.aggregation); } fprintf(f, "aggregate"); if (r->next == NULL || r->next->dests->cl != aggr) { fprintf(f, " %s\n", r->pattern); } else { fprintf(f, "\n"); do { fprintf(f, " %s\n", r->pattern); } while (r->next != NULL && r->next->dests->cl == aggr && (r = r->next) != NULL); } fprintf(f, " every %u seconds\n" " expire after %u seconds\n" " timestamp at %s of bucket\n", aggr->members.aggregation->interval, aggr->members.aggregation->expire, aggr->members.aggregation->tswhen == TS_START ? "start" : aggr->members.aggregation->tswhen == TS_MIDDLE ? "middle" : aggr->members.aggregation->tswhen == TS_END ? "end" : ""); for (ac = aggr->members.aggregation->computes; ac != NULL; ac = ac->next) { snprintf(percentile, sizeof(percentile), "percentile%d", ac->percentile); fprintf(f, " compute %s write to\n" " %s\n", ac->type == SUM ? "sum" : ac->type == CNT ? "count" : ac->type == MAX ? "max" : ac->type == MIN ? "min" : ac->type == AVG ? "average" : ac->type == MEDN ? "median" : ac->type == PCTL ? percentile : ac->type == VAR ? "variance" : ac->type == SDEV ? "stddev" : "", ac->metric + strlen(stubname)); } if (!(pmode & PMODE_STUB) && r->dests->next != NULL) { destinations *dn = r->dests->next; fprintf(f, " send to"); if (dn->next == NULL) { fprintf(f, " %s\n", dn->cl->name); } else { for (; dn != NULL; dn = dn->next) fprintf(f, "\n %s", dn->cl->name); fprintf(f, "\n"); } } fprintf(f, "%s ;\n", r->stop ? " stop\n" : ""); } else if (r->dests->cl->type == REWRITE) { fprintf(f, "rewrite %s\n into %s\n ;\n", r->pattern, r->dests->cl->members.replacement); } else if (r->dests->cl->type == GROUP) { size_t cnt = 0; route *rwalk; char blockname[64]; char *b = &blockname[sizeof(blockname) - 1]; char *p; for (rwalk = r->dests->cl->members.routes; rwalk != NULL; rwalk = rwalk->next) cnt++; /* reverse the name, to make it human consumable */ *b-- ='\0'; for (p = r->dests->cl->name; *p != '\0' && b > blockname; p++) *b-- = *p; fprintf(f, "# common pattern group '%s' " "contains %zu aggregations/matches\n", ++b, cnt); if (pmode & PMODE_AGGR) { router srtr; memset(&srtr, 0, sizeof(srtr)); srtr.routes = r->dests->cl->members.routes; /* recurse */ router_printconfig(&srtr, f, pmode); fprintf(f, "# end of group '%s'\n", b); } } else if (r->dests->cl->type == AGGRSTUB || r->dests->cl->type == STATSTUB) { if (pmode & PMODE_STUB) { fprintf(f, "# stub match for aggregate/statistics rule " "with send to\n"); fprintf(f, "match ^%s\n send to", r->pattern); if (r->dests->cl->members.routes->dests->next == NULL) { fprintf(f, " %s", r->dests->cl->members.routes->dests->cl->name); } else { destinations *d = r->dests->cl->members.routes->dests; for (; d != NULL; d = d->next) fprintf(f, "\n %s", d->cl->name); } fprintf(f, "%s\n ;\n", r->stop ? "\n stop" : ""); } } else { route *or = r; destinations *d; fprintf(f, "match"); if (r->next == NULL || r->next->dests != or->dests) { fprintf(f, " %s\n", r->matchtype == MATCHALL ? "*" : r->pattern); } else { fprintf(f, "\n"); do { fprintf(f, " %s\n", r->matchtype == MATCHALL ? "*" : r->pattern); } while (r->next != NULL && r->next->dests == or->dests && (r = r->next) != NULL); } d = or->dests; if (d->cl->type == VALIDATION) { validate *v = d->cl->members.validation; fprintf(f, " validate %s else %s\n", v->rule->pattern, v->action == VAL_LOG ? "log" : "drop"); /* hide this pseudo target */ d = d->next; } if (r->masq != NULL) fprintf(f, " route using %s\n", r->masq); if (d != NULL) { fprintf(f, " send to"); if (d->next == NULL) { fprintf(f, " %s", d->cl->name); } else { for ( ; d != NULL; d = d->next) fprintf(f, "\n %s", d->cl->name); } fprintf(f, "\n%s ;\n", or->stop ? " stop\n" : ""); } else { fprintf(f, " ;\n"); } } } fflush(f); } /** * Prints the differences between old and new at the highest level of * the change. (When a cluster is gone, its servers are not * considered.) Returns whether there were changes found. */ char router_printdiffs(router *old, router *new, FILE *out) { FILE *f; int fd; char *tmp = getenv("TMPDIR"); char patho[512]; char pathn[512]; char buf[1024]; size_t len; int ret; mode_t mask; /* First idea was to printconfig both old and new, and run diff -u * on them. Simple and effective. Does require diff and two files * though. For now, I guess we can live with that. */ if (tmp == NULL) tmp = "/tmp"; snprintf(patho, sizeof(patho), "%s/carbon-c-relay_route.XXXXXX", tmp); mask = umask(S_IWGRP | S_IWOTH); fd = mkstemp(patho); umask(mask); if (fd < 0) { logerr("failed to create temporary file: %s\n", strerror(errno)); return 1; } f = fdopen(fd, "r+"); if (f == NULL) { logerr("failed to open stream for file '%s': %s\n", patho, strerror(errno)); return 1; } router_printconfig(old, f, PMODE_AGGR | PMODE_PEMT); fclose(f); snprintf(pathn, sizeof(pathn), "%s/carbon-c-relay_route.XXXXXX", tmp); mask = umask(S_IWGRP | S_IWOTH); fd = mkstemp(pathn); umask(mask); if (fd < 0) { logerr("failed to create temporary file: %s\n", strerror(errno)); return 1; } f = fdopen(fd, "r+"); if (f == NULL) { logerr("failed to open stream for file '%s': %s\n", pathn, strerror(errno)); return 1; } router_printconfig(new, f, PMODE_AGGR | PMODE_PEMT); fclose(f); /* diff and print its output */ snprintf(buf, sizeof(buf), "diff -u %s %s", patho, pathn); f = popen(buf, "r"); while ((len = fread(buf, 1, sizeof(buf) - 1, f)) > 0) { if (fwrite(buf, len, 1, out) == 0) /* ignore */ ; } ret = pclose(f); unlink(patho); unlink(pathn); /* ret: * 0 - no diffs * 1 - diffs * 2 - some error (file not found?) * let's say that an error means potential difference */ return ret != 0; } /** * Evaluates all servers in new and if an identical server exists in * old, swaps their queues. */ void router_transplant_queues(router *new, router *old) { servers *os; servers *ns; for (ns = new->srvrs; ns != NULL; ns = ns->next) { for (os = old->srvrs; os != NULL; os = os->next) { if (strcmp(server_ip(ns->server), server_ip(os->server)) == 0 && server_port(ns->server) == server_port(os->server) && server_ctype(ns->server) == server_ctype(os->server)) { server_swap_queue(ns->server, os->server); continue; } } } } inline listener * router_get_listeners(router *rtr) { return rtr->listeners; } /** * Returns whether a comparible listener to lsnr exists in router rtr. * Comparible means they are the same hostname, or have canonical ip * representation that matches. */ listener * router_contains_listener(router *rtr, listener *lsnr) { listener *rwalk; char hnbufl[INET6_ADDRSTRLEN]; char hnbufr[INET6_ADDRSTRLEN]; char match; match = 0; if (lsnr->saddrs) { saddr_ntop(lsnr->saddrs, hnbufl); } else { snprintf(hnbufl, sizeof(hnbufl), "unknown left"); } for (rwalk = rtr->listeners; rwalk != NULL; rwalk = rwalk->next) { if (rwalk->saddrs) { saddr_ntop(rwalk->saddrs, hnbufr); } else { snprintf(hnbufr, sizeof(hnbufr), "unknown right"); } if (lsnr->transport == rwalk->transport && lsnr->ctype == rwalk->ctype) { if (lsnr->ctype == CON_UNIX) { if (strcmp(lsnr->ip, rwalk->ip) == 0) { match = 1; break; } } else { char *p; char *l, *r; /* compare against user input, but try to cannonicalise * IP addresses in order to get correct matches */ if (lsnr->ip != NULL) { for (p = lsnr->ip ; strchr("0123456789.:", *p) != 0; p++) ; if (*p != '\0') { l = lsnr->ip; } else { l = hnbufl; } } else { l = hnbufl; } if (rwalk->ip != NULL) { for (p = rwalk->ip ; strchr("0123456789.:", *p) != 0; p++) ; if (*p != '\0') { r = rwalk->ip; } else { r = hnbufr; } } else { r = hnbufr; } if (lsnr->port == rwalk->port && strcmp(l, r) == 0) { #ifdef HAVE_SSL /* check pemmtimespec */ if (lsnr->transport == W_SSL && lsnr->pemmtimespec.tv_sec == rwalk->pemmtimespec.tv_sec && lsnr->pemmtimespec.tv_nsec == rwalk->pemmtimespec.tv_nsec) #endif { match = 1; break; } } } } } return match ? rwalk : NULL; } void router_transplant_listener_socks(router *rtr, listener *olsnr, listener *nlsnr) { int cnt; for (cnt = 0; olsnr->socks[cnt] != -1; cnt++) ; cnt++; nlsnr->socks = ra_malloc(rtr->a, sizeof(int) * (cnt)); memmove(nlsnr->socks, olsnr->socks, sizeof(int) * (cnt)); } /** * Starts all resources (servers) associated to this router. */ char router_start(router *rtr) { servers *s; char ret = 0; int err; for (s = rtr->srvrs; s != NULL; s = s->next) { if ((err = server_start(s->server)) != 0) { logerr("failed to start server %s:%u: %s\n", serverip(s->server), server_port(s->server), strerror(err)); ret = 1; } } return ret; } /** * Shuts down all resources (servers) associated to this router. */ void router_shutdown(router *rtr) { servers *s; for (s = rtr->srvrs; s != NULL; s = s->next) server_shutdown(s->server); } /** * Free the routes and all associated resources. */ void router_free(router *rtr) { servers *s; router_free_intern(rtr->routes, rtr->conf.workercnt); /* free all servers from the pool, in case of secondaries, the * previous call to router_shutdown made sure nothing references the * servers anymore */ for (s = rtr->srvrs; s != NULL; s = s->next) server_free(s->server); ra_free(rtr->a); free(rtr); } inline static char router_metric_matches( const route *r, char *metric, char *firstspace, regmatch_t *pmatch, int dispatcher_id) { char ret = 0; char firstspc = *firstspace; union { char *c; size_t i; } t; switch (r->matchtype) { case MATCHALL: ret = 1; break; case REGEX: *firstspace = '\0'; ret = regexec(&r->rule[dispatcher_id], metric, r->nmatch, pmatch, 0) == 0; *firstspace = firstspc; break; case CONTAINS: *firstspace = '\0'; ret = (t.c = strstr(metric, r->strmatch)) != NULL; if (ret) { pmatch[0].rm_so = t.c - metric; pmatch[0].rm_eo = pmatch[0].rm_so + strlen(r->strmatch); } *firstspace = firstspc; break; case STARTS_WITH: t.i = strlen(r->strmatch); ret = strncmp(metric, r->strmatch, t.i) == 0; if (ret) { pmatch[0].rm_so = 0; pmatch[0].rm_eo = t.i; } break; case ENDS_WITH: *firstspace = '\0'; t.i = strlen(r->strmatch); ret = strcmp(firstspace - t.i, r->strmatch) == 0; if (ret) { pmatch[0].rm_so = firstspace - t.i - metric; pmatch[0].rm_eo = pmatch[0].rm_so + t.i; } *firstspace = firstspc; break; case MATCHES: *firstspace = '\0'; ret = strcmp(metric, r->strmatch) == 0; if (ret) { pmatch[0].rm_so = 0; pmatch[0].rm_eo = strlen(r->strmatch); } *firstspace = firstspc; break; default: ret = 0; break; } return ret; } inline size_t router_rewrite_metric( char (*newmetric)[METRIC_BUFSIZ], char **newfirstspace, const char *metric, const char *firstspace, const char *replacement, const size_t nmatch, const regmatch_t *pmatch) { char escape = 0; int ref = 0; char *s = *newmetric; const char *p; const char *q; const char *t; enum rewrite_case { RETAIN, LOWER, UPPER, RETAIN_DOT, LOWER_DOT, UPPER_DOT } rcase = RETAIN; assert(pmatch != NULL); /* insert leading part */ q = metric; t = metric + pmatch[0].rm_so; if (s - *newmetric + t - q < sizeof(*newmetric)) { while (q < t) *s++ = *q++; } else { return 0; /* won't fit, don't try further */ } for (p = replacement; ; p++) { switch (*p) { case '\\': if (!escape) { escape = 1; rcase = RETAIN; break; } /* fall through so we handle \1\2 */ default: if (escape == 1 && rcase == RETAIN && *p == '_') { rcase = LOWER; } else if (escape == 1 && rcase == RETAIN && *p == '^') { rcase = UPPER; } else if (escape == 1 && *p == '.') { if (rcase == LOWER) { rcase = LOWER_DOT; } else if (rcase == UPPER) { rcase = UPPER_DOT; } else { rcase = RETAIN_DOT; } } else if (escape && *p >= '0' && *p <= '9') { escape = 2; ref *= 10; ref += *p - '0'; } else { if (escape) { if (ref > 0 && ref <= nmatch && pmatch[ref].rm_so >= 0) { /* insert match part */ q = metric + pmatch[ref].rm_so; t = metric + pmatch[ref].rm_eo; if (s - *newmetric + t - q < sizeof(*newmetric)) { switch (rcase) { case RETAIN: while (q < t) *s++ = *q++; break; case LOWER: while (q < t) *s++ = (char)tolower(*q++); break; case UPPER: while (q < t) *s++ = (char)toupper(*q++); break; case RETAIN_DOT: while (q < t) { if (*q == '.') *s++ = '_'; else *s++ = *q; q++; } break; case LOWER_DOT: while (q < t) { if (*q == '.') *s++ = '_'; else *s++ = (char)tolower(*q); q++; } break; case UPPER_DOT: while (q < t) { if (*q == '.') *s++ = '_'; else *s++ = (char)toupper(*q); q++; } break; } } } ref = 0; } if (*p != '\\') { /* \1\2 case */ escape = 0; rcase = RETAIN; if (s - *newmetric + 1 < sizeof(*newmetric)) *s++ = *p; } } break; } if (*p == '\0') break; } /* undo trailing \0 */ s--; /* insert remaining part */ q = metric + pmatch[0].rm_eo; t = firstspace; if (s - *newmetric + t - q < sizeof(*newmetric)) { while (q < t) *s++ = *q++; } else { return 0; /* won't fit, don't try further */ } /* record new position of firstspace */ *newfirstspace = s; /* copy data part */ if (s - *newmetric + strlen(firstspace) < sizeof(*newmetric)) { for (p = firstspace; *p != '\0'; p++) *s++ = *p; *s++ = '\0'; return s - *newmetric; } return 0; /* we couldn't copy everything */ } static char router_route_intern( char *blackholed, destination ret[], size_t *curlen, size_t retsize, char *srcaddr, char *metric, char *firstspace, const route *r, int dispatcher_id) { const route *w; destinations *d; char stop = 0; char wassent = 0; const char *p; const char *q = NULL; /* pacify compiler, won't happen in reality */ const char *t; char newmetric[METRIC_BUFSIZ]; char *newfirstspace = NULL; size_t len; regmatch_t pmatch[RE_MAX_MATCHES]; #define failif(RETLEN, WANTLEN) \ if (WANTLEN > RETLEN) { \ logerr("router_route: out of destination slots, " \ "increase CONN_DESTS_SIZE in router.h\n"); \ return 1; \ } for (w = r; w != NULL; w = w->next) { if (w->dests->cl->type == GROUP) { /* strrstr doesn't exist, grrr * therefore the pattern in the group is stored in reverse, * such that we can start matching the tail easily without * having to calculate the end of the pattern string all the * time */ for (p = firstspace - 1; p >= metric; p--) { for (q = w->dests->cl->name, t = p; *q != '\0' && t >= metric; q++, t--) { if (*q != *t) break; } if (*q == '\0') break; } /* indirection */ assert(q != NULL); if (*q == '\0') stop = router_route_intern( blackholed, ret, curlen, retsize, srcaddr, metric, firstspace, w->dests->cl->members.routes, dispatcher_id); } else if (router_metric_matches(w, metric, firstspace, pmatch, dispatcher_id)) { stop = w->stop; /* rule matches, send to destination(s) */ for (d = w->dests; d != NULL; d = d->next) { switch (d->cl->type) { case BLACKHOLE: *blackholed = 1; break; case FILELOGIP: { servers *s; snprintf(newmetric, sizeof(newmetric), "%s %s", srcaddr, metric); for (s = d->cl->members.forward; s != NULL; s = s->next) { failif(retsize, *curlen + 1); ret[*curlen].dest = s->server; ret[(*curlen)++].metric = strdup(newmetric); } wassent = 1; } break; case FILELOG: case FORWARD: { /* simple case, no logic necessary */ servers *s; for (s = d->cl->members.forward; s != NULL; s = s->next) { failif(retsize, *curlen + 1); ret[*curlen].dest = s->server; ret[(*curlen)++].metric = strdup(metric); } wassent = 1; } break; case ANYOF: { /* we queue the same metrics at the same server */ unsigned int hash; fnv1a_32(hash, p, metric, firstspace); /* We could use the retry approach here, but since * our c is very small compared to MAX_INT, the bias * we introduce for the last few of the range * (MAX_INT % c) can be considered neglicible given * the number of occurances of c in the range of * MAX_INT, therefore we stick with a simple mod. */ hash %= d->cl->members.anyof->count; failif(retsize, *curlen + 1); ret[*curlen].dest = d->cl->members.anyof->servers[hash]; ret[(*curlen)++].metric = strdup(metric); wassent = 1; } break; case FAILOVER: { /* queue at the first non-failing server */ unsigned short i; failif(retsize, *curlen + 1); ret[*curlen].dest = NULL; for (i = 0; i < d->cl->members.anyof->count; i++) { server *s = d->cl->members.anyof->servers[i]; if (server_failed(s)) continue; ret[*curlen].dest = s; break; } if (ret[*curlen].dest == NULL) /* all failed, take first server */ ret[*curlen].dest = d->cl->members.anyof->servers[0]; ret[(*curlen)++].metric = strdup(metric); wassent = 1; } break; case CARBON_CH: case FNV1A_CH: case JUMP_CH: { size_t i; /* let the ring(bearer) decide */ failif(retsize, *curlen + d->cl->members.ch->repl_factor); if (w->masq != NULL) { if ((len = router_rewrite_metric( &newmetric, &newfirstspace, metric, firstspace, w->masq, w->nmatch, pmatch)) == 0) { logerr("router_route: failed to route using: " "newmetric size too small to hold " "replacement (%s -> %s)\n", metric, w->masq); break; } } ch_get_nodes( &ret[*curlen], d->cl->members.ch->ring, d->cl->members.ch->repl_factor, w->masq ? newmetric : metric, w->masq ? newfirstspace : firstspace); for (i = 0; i < d->cl->members.ch->repl_factor; i++) ret[(*curlen)++].metric = strdup(metric); wassent = 1; } break; case AGGREGATION: { /* aggregation rule */ aggregator_putmetric( d->cl->members.aggregation, metric, firstspace, w->nmatch, pmatch); wassent = 1; /* we need to break out of the inner loop. since * the rest of dests are meant for the stub, and * we should certainly not process it now */ while (d->next != NULL) d = d->next; } break; case REWRITE: { /* rewrite metric name */ if ((len = router_rewrite_metric( &newmetric, &newfirstspace, metric, firstspace, d->cl->members.replacement, w->nmatch, pmatch)) == 0) { logerr("router_route: failed to rewrite " "metric: newmetric size too small to hold " "replacement (%s -> %s)\n", metric, d->cl->members.replacement); break; }; /* scary! write back the rewritten metric */ memcpy(metric, newmetric, len); firstspace = metric + (newfirstspace - newmetric); } break; case AGGRSTUB: case STATSTUB: { /* strip off the stub pattern, and reroute this * thing */ router_route_intern( blackholed, ret, curlen, retsize, srcaddr, metric + strlen(w->pattern), firstspace, w->dests->cl->members.routes, dispatcher_id); } break; case VALIDATION: { /* test whether data matches, if not, either log * or drop and stop */ char *lastchr = firstspace + strlen(firstspace) - 1; if (router_metric_matches( w->dests->cl->members.validation->rule, firstspace + 1, lastchr, pmatch, dispatcher_id)) break; if (w->dests->cl->members.validation->action == VAL_LOG) { logerr("dropping metric due to validation error: " "%s", metric); wassent = 1; } /* only stop if this is a validate without * destinations */ stop |= d->next == NULL; /* break out of the dests loop */ while (d->next != NULL) d = d->next; break; } case GROUP: { /* this should not happen */ } break; } } } /* stop processing further rules if requested */ if (stop) break; } if (!wassent) *blackholed = 1; return stop; } /** * Looks up the locations the given metric_path should be sent to, and * returns the list of servers in ret, the number of servers is * returned in retcnt. * Returns whether the metric was blackholed (e.g. not routed anywhere). */ inline char router_route( router *rtr, destination ret[], size_t *retcnt, size_t retsize, char *srcaddr, char *metric, char *firstspace, int dispatcher_id) { size_t curlen = 0; char blackholed = 0; (void)router_route_intern(&blackholed, ret, &curlen, retsize, srcaddr, metric, firstspace, rtr->routes, dispatcher_id); *retcnt = curlen; return blackholed; } /** * Prints for metric_path which rules and/or aggregations would be * triggered. Useful for testing regular expressions. */ static char router_test_intern(char *metric, char *firstspace, route *routes) { route *w; destinations *d; char stop = 0; char gotmatch = 0; char newmetric[METRIC_BUFSIZ]; char *newfirstspace = NULL; size_t len; regmatch_t pmatch[RE_MAX_MATCHES]; for (w = routes; w != NULL; w = w->next) { if (w->dests->cl->type == GROUP) { /* just recurse, in test mode performance shouldn't be an * issue at all */ gotmatch |= router_test_intern( metric, firstspace, w->dests->cl->members.routes); if (gotmatch & 2) break; } else if (router_metric_matches(w, metric, firstspace, pmatch, 0)) { gotmatch = 1; switch (w->dests->cl->type) { case AGGREGATION: fprintf(stdout, "aggregation\n"); break; case REWRITE: fprintf(stdout, "rewrite\n"); break; case AGGRSTUB: case STATSTUB: { gotmatch |= router_test_intern( metric + strlen(w->pattern), firstspace, w->dests->cl->members.routes); return gotmatch; } break; default: fprintf(stdout, "match\n"); break; } *firstspace = '\0'; switch (w->matchtype) { case MATCHALL: fprintf(stdout, " * -> %s\n", metric); break; case REGEX: fprintf(stdout, " %s (regex) -> %s\n", w->pattern, metric); break; default: { char *x; switch (w->matchtype) { case CONTAINS: x = "strstr"; break; case STARTS_WITH: x = "strncmp"; break; case ENDS_WITH: x = "tailcmp"; break; case MATCHES: x = "strcmp"; break; default: x = "!impossible?"; break; } fprintf(stdout, " %s [%s: %s]\n -> %s\n", w->pattern, x, w->strmatch, metric); } break; } *firstspace = ' '; stop = w->stop; for (d = w->dests; d != NULL; d = d->next) { switch (d->cl->type) { case AGGREGATION: { struct _aggr_computes *ac; int stublen = 0; char percentile[16]; if (mode & MODE_DEBUG || d->next == NULL) { stublen = 0; } else { char x; stublen = snprintf(&x, 1, STUB_AGGR "%p__", d->cl->members.aggregation); } for (ac = d->cl->members.aggregation->computes; ac != NULL; ac = ac->next) { if (w->nmatch == 0 || (len = router_rewrite_metric( &newmetric, &newfirstspace, metric, firstspace, ac->metric, w->nmatch, pmatch)) == 0) { if (w->nmatch > 0) { fprintf(stderr, "router_test: failed to " "rewrite metric: newmetric size too " "small to hold replacement " "(%s -> %s)\n", metric, ac->metric); break; } len = snprintf(newmetric, sizeof(newmetric), "%s", ac->metric); if (len >= sizeof(newmetric)) len = sizeof(newmetric) - 1; newfirstspace = newmetric + len; } snprintf(percentile, sizeof(percentile), "percentile%d", ac->percentile); fprintf(stdout, " %s%s%s%s -> %s\n", ac->type == SUM ? "sum" : ac->type == CNT ? "count" : ac->type == MAX ? "max" : ac->type == MIN ? "min" : ac->type == AVG ? "average" : ac->type == MEDN ? "median" : ac->type == PCTL ? percentile : ac->type == VAR ? "variance" : ac->type == SDEV ? "stddev" : "", w->nmatch > 0 ? "(" : "", w->nmatch > 0 ? ac->metric + stublen : "", w->nmatch > 0 ? ")" : "", newmetric + stublen); if (mode & MODE_DEBUG && d->next != NULL) { gotmatch |= router_test_intern( newmetric, newfirstspace, routes); } } if (mode & MODE_DEBUG) { return gotmatch; } else { gotmatch |= 4; } } break; case BLACKHOLE: { fprintf(stdout, " blackholed\n"); } break; case REWRITE: { /* rewrite metric name */ if ((len = router_rewrite_metric( &newmetric, &newfirstspace, metric, firstspace, d->cl->members.replacement, w->nmatch, pmatch)) == 0) { fprintf(stderr, "router_test: failed to rewrite " "metric: newmetric size too small to hold " "replacement (%s -> %s)\n", metric, d->cl->members.replacement); break; }; /* scary! write back the rewritten metric */ memcpy(metric, newmetric, len); firstspace = metric + (newfirstspace - newmetric); *firstspace = '\0'; fprintf(stdout, " into(%s) -> %s\n", d->cl->members.replacement, metric); *firstspace = ' '; } break; case FORWARD: { servers *s; fprintf(stdout, " forward(%s)\n", d->cl->name); for (s = d->cl->members.forward; s != NULL; s = s->next) fprintf(stdout, " %s:%d\n", serverip(s->server), server_port(s->server)); } break; case FILELOG: case FILELOGIP: { servers *s; fprintf(stdout, " file%s(%s)\n", d->cl->type == FILELOGIP ? " ip" : "", d->cl->name); for (s = d->cl->members.forward; s != NULL; s = s->next) fprintf(stdout, " %s\n", serverip(s->server)); } break; case CARBON_CH: case FNV1A_CH: case JUMP_CH: { destination dst[CONN_DESTS_SIZE]; int i; fprintf(stdout, " %s_ch(%s)\n", d->cl->type == CARBON_CH ? "carbon" : d->cl->type == FNV1A_CH ? "fnv1a" : "jump_fnv1a", d->cl->name); if (gotmatch & 4) break; if (w->masq != NULL) { if ((len = router_rewrite_metric( &newmetric, &newfirstspace, metric, firstspace, w->masq, w->nmatch, pmatch)) == 0) { fprintf(stderr, "router_test: failed to " "route using: " "newmetric size too small to hold " "replacement (%s -> %s)\n", metric, w->masq); break; } fprintf(stdout, " using(%s) -> %s\n", w->masq, newmetric); } if (mode & MODE_DEBUG) { fprintf(stdout, " hash_pos(%d)\n", ch_gethashpos(d->cl->members.ch->ring, w->masq ? newmetric : metric, w->masq ? newfirstspace : firstspace)); } ch_get_nodes(dst, d->cl->members.ch->ring, d->cl->members.ch->repl_factor, w->masq ? newmetric : metric, w->masq ? newfirstspace : firstspace); for (i = 0; i < d->cl->members.ch->repl_factor; i++) { fprintf(stdout, " %s:%d\n", serverip(dst[i].dest), server_port(dst[i].dest)); } } break; case FAILOVER: case ANYOF: { unsigned int hash; fprintf(stdout, " %s(%s)\n", d->cl->type == ANYOF ? "any_of" : "failover", d->cl->name); if (gotmatch & 4) break; if (d->cl->type == ANYOF) { const char *p; fnv1a_32(hash, p, metric, firstspace); hash %= d->cl->members.anyof->count; } else { hash = 0; } fprintf(stdout, " %s:%d\n", serverip(d->cl->members.anyof->servers[hash]), server_port(d->cl->members.anyof->servers[hash])); } break; case VALIDATION: { char *lastspc = firstspace + strlen(firstspace); fprintf(stdout, " validate\n %s -> %s\n", d->cl->members.validation->rule->pattern, firstspace + 1); if (router_metric_matches( d->cl->members.validation->rule, firstspace + 1, lastspc, pmatch, 0)) { fprintf(stdout, " match\n"); } else { fprintf(stdout, " fail -> %s\n", d->cl->members.validation->action == VAL_LOG ? "log" : "drop"); stop |= d->next == NULL; while (d->next != NULL) d = d->next; } } break; default: { fprintf(stdout, " cluster(%s)\n", d->cl->name); } break; } } if (stop) { gotmatch = 3; fprintf(stdout, " stop\n"); break; } } } return gotmatch; } void router_test(router *rtr, char *metric) { char *firstspace; for (firstspace = metric; *firstspace != '\0'; firstspace++) if (*firstspace == ' ') break; if (!router_test_intern(metric, firstspace, rtr->routes)) { *firstspace = '\0'; fprintf(stdout, "nothing matched %s\n", metric); } fflush(stdout); } carbon-c-relay-3.2/router.h000066400000000000000000000056351317265605500156700ustar00rootroot00000000000000/* * Copyright 2013-2017 Fabian Groffen * * 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. */ #ifndef ROUTER_H #define ROUTER_H 1 #include #include #include #include "relay.h" #include "server.h" #include "aggregator.h" #ifdef HAVE_SSL #include #endif #define PMODE_NORM (1 << 0) #define PMODE_AGGR (1 << 1) #define PMODE_HASH (1 << 2) #define PMODE_STUB (1 << 3) #define PMODE_PEMT (1 << 4) #define PMODE_DEBUG (PMODE_HASH | PMODE_STUB) #define CONN_DESTS_SIZE 64 #ifndef TMPDIR # define TMPDIR "/tmp" #endif #define SOCKFILE ".s.carbon-c-relay" typedef struct { const char *metric; server *dest; } destination; typedef struct _router_listener { con_type lsnrtype; con_trnsp transport; con_proto ctype; char *ip; int port; int *socks; #ifdef HAVE_SSL SSL_CTX *ctx; SSL **sslstrms; char *pemcert; struct timespec pemmtimespec; #endif struct addrinfo *saddrs; struct _router_listener *next; } listener; typedef struct _router router; typedef enum { SUB, CUM } col_mode; #define RE_MAX_MATCHES 64 router *router_readconfig(router *orig, const char *path, char workercnt, size_t queuesize, size_t batchsize, int maxstalls, unsigned short iotimeout, unsigned int sockbufsize, unsigned short port); void router_optimise(router *r, int threshold); char router_printdiffs(router *old, router *new, FILE *out); listener *router_contains_listener(router *rtr, listener *lsnr); void router_transplant_queues(router *new, router *old); void router_transplant_listener_socks(router *rtr, listener *olsnr, listener *nlsnr); char router_start(router *r); size_t router_rewrite_metric(char (*newmetric)[METRIC_BUFSIZ], char **newfirstspace, const char *metric, const char *firstspace, const char *replacement, const size_t nmatch, const regmatch_t *pmatch); void router_printconfig(router *r, FILE *f, char mode); char router_route(router *r, destination ret[], size_t *retcnt, size_t retsize, char *srcaddr, char *metric, char *firstspace, int dispatcher_id); void router_test(router *r, char *metric_path); listener *router_get_listeners(router *r); server **router_getservers(router *r); aggregator *router_getaggregators(router *r); char *router_getcollectorstub(router *r); int router_getcollectorinterval(router *r); char *router_getcollectorprefix(router *r); col_mode router_getcollectormode(router *r); void router_shutdown(router *r); void router_free(router *r); #endif carbon-c-relay-3.2/server.c000066400000000000000000001034751317265605500156520ustar00rootroot00000000000000/* * Copyright 2013-2017 Fabian Groffen * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "relay.h" #include "queue.h" #include "dispatcher.h" #include "collector.h" #include "server.h" #ifdef HAVE_GZIP #include #endif #ifdef HAVE_LZ4 #include #endif #ifdef HAVE_SSL #include #include #endif struct _server { const char *ip; unsigned short port; char *instance; struct addrinfo *saddr; struct addrinfo *hint; char reresolve:1; int fd; void *strm; ssize_t (*strmwrite)(void *, const void *, size_t); /* write impl */ int (*strmflush)(void *); /* flush impl */ int (*strmclose)(void *); /* close impl */ const char *(*strmerror)(void *, int); /* get last err str */ #ifdef HAVE_SSL SSL_CTX *ctx; #endif queue *queue; size_t bsize; short iotimeout; unsigned int sockbufsize; unsigned char maxstalls:SERVER_STALL_BITS; const char **batch; con_type type; con_trnsp transport; con_proto ctype; pthread_t tid; struct _server **secondaries; size_t secondariescnt; char failover:1; char failure; /* full byte for atomic access */ char running; /* full byte for atomic access */ char keep_running; /* full byte for atomic access */ unsigned char stallseq; /* full byte for atomic access */ size_t metrics; size_t dropped; size_t stalls; size_t ticks; size_t prevmetrics; size_t prevdropped; size_t prevstalls; size_t prevticks; }; /* connection specific writers and closers */ typedef struct _z_strm { char obuf[METRIC_BUFSIZ]; int sock; union { #ifdef HAVE_LZ4 LZ4_stream_t *lz; #endif void *dummy; } hdl; } z_strm; /* ordinary socket */ static inline ssize_t sockwrite(void *strm, const void *buf, size_t sze) { return write(*((int *)strm), buf, sze); } static inline int sockflush(void *strm) { /* noop, we don't use a stream in the normal case */ return 0; } static inline int sockclose(void *strm) { return close(*((int *)strm)); } static inline const char * sockerror(void *strm, int rval) { (void)strm; (void)rval; return strerror(errno); } #ifdef HAVE_GZIP /* gzip wrapped socket */ static inline ssize_t gzipwrite(void *strm, const void *buf, size_t sze) { return (ssize_t)gzwrite((gzFile)strm, buf, (unsigned)sze); } static inline int gzipflush(void *strm) { return gzflush((gzFile)strm, Z_SYNC_FLUSH); } static inline int gzipclose(void *strm) { return gzclose((gzFile)strm); } #endif #ifdef HAVE_LZ4 /* lz4 wrapped socket */ static inline ssize_t lzwrite(void *strm, const void *buf, size_t sze) { int oret; char *obuf = ((z_strm *)strm)->obuf; int cret; cret = LZ4_compress_fast_continue(((z_strm *)strm)->hdl.lz, buf, obuf, sze, METRIC_BUFSIZ, 0); if (cret == 0) return -1; /* we must reset/free lz */ while (cret > 0) { oret = write(((z_strm *)strm)->sock, obuf, cret); if (oret < 0) return -1; /* failure is failure */ /* update counters to possibly retry the remaining bit */ obuf += oret; cret -= oret; } return sze; } static inline int lzflush(void *strm) { return 0; } static inline int lzclose(void *strm) { int ret = close(((z_strm *)strm)->sock); LZ4_freeStream(((z_strm *)strm)->hdl.lz); free(strm); return ret; } #endif #ifdef HAVE_SSL /* (Open|Libre)SSL wrapped socket */ static inline ssize_t sslwrite(void *strm, const void *buf, size_t sze) { return (ssize_t)SSL_write((SSL *)strm, buf, (int)sze); } static inline int sslflush(void *strm) { /* noop */ return 0; } static inline int sslclose(void *strm) { int sock = SSL_get_fd((SSL *)strm); SSL_free((SSL *)strm); return close(sock); } static inline const char * sslerror(void *strm, int rval) { int err = SSL_get_error((SSL *)strm, rval); return ERR_reason_error_string(err); } #endif /** * Reads from the queue and sends items to the remote server. This * function is designed to be a thread. Data sending is attempted to be * batched, but sent one by one to reduce loss on sending failure. * A connection with the server is maintained for as long as there is * data to be written. As soon as there is none, the connection is * dropped if a timeout of DISCONNECT_WAIT_TIME exceeds. */ static void * server_queuereader(void *d) { server *self = (server *)d; size_t len; ssize_t slen; const char **metric = self->batch; struct timeval start, stop; struct timeval timeout; queue *squeue; char idle = 0; size_t *secpos = NULL; unsigned char cnt; const char *p; *metric = NULL; #define FAIL_WAIT_TIME 6 /* 6 * 250ms = 1.5s */ #define DISCONNECT_WAIT_TIME 12 /* 12 * 250ms = 3s */ #define LEN_CRITICAL(Q) (queue_free(Q) < self->bsize) self->running = 1; while (1) { if (queue_len(self->queue) == 0) { /* if we're idling, close the TCP connection, this allows us * to reduce connections, while keeping the connection alive * if we're writing a lot */ gettimeofday(&start, NULL); if (self->ctype == CON_TCP && self->fd >= 0 && idle++ > DISCONNECT_WAIT_TIME) { self->strmclose(self->strm); self->fd = -1; } if (idle == 1) /* ensure blocks are pushed out as soon as we're idling, * this allows compressors to benefit from a larger * stream of data to gain better compresion */ self->strmflush(self->strm); gettimeofday(&stop, NULL); __sync_add_and_fetch(&(self->ticks), timediff(start, stop)); if (__sync_bool_compare_and_swap(&(self->keep_running), 0, 0)) break; /* nothing to do, so slow down for a bit */ usleep((200 + (rand() % 100)) * 1000); /* 200ms - 300ms */ /* if we are in failure mode, keep checking if we can * connect, this avoids unnecessary queue moves */ if (__sync_bool_compare_and_swap(&(self->failure), 0, 0)) /* it makes no sense to try and do something, so skip */ continue; } else if (self->secondariescnt > 0 && (__sync_add_and_fetch(&(self->failure), 0) >= FAIL_WAIT_TIME || (!self->failover && LEN_CRITICAL(self->queue)))) { size_t i; gettimeofday(&start, NULL); if (self->secondariescnt > 0) { if (secpos == NULL) { secpos = malloc(sizeof(size_t) * self->secondariescnt); if (secpos == NULL) { logerr("server: failed to allocate memory " "for secpos\n"); gettimeofday(&stop, NULL); __sync_add_and_fetch(&(self->ticks), timediff(start, stop)); continue; } for (i = 0; i < self->secondariescnt; i++) secpos[i] = i; } if (!self->failover) { /* randomise the failover list such that in the * grand scheme of things we don't punish the first * working server in the list to deal with all * traffic meant for a now failing server */ for (i = 0; i < self->secondariescnt; i++) { size_t n = rand() % (self->secondariescnt - i); if (n != i) { size_t t = secpos[n]; secpos[n] = secpos[i]; secpos[i] = t; } } } } /* offload data from our queue to our secondaries * when doing so, observe the following: * - avoid nodes that are in failure mode * - avoid nodes which queues are >= critical_len * when no nodes remain given the above * - send to nodes which queue size < critical_len * where there are no such nodes * - do nothing (we will overflow, since we can't send * anywhere) */ *metric = NULL; squeue = NULL; for (i = 0; i < self->secondariescnt; i++) { /* both conditions below make sure we skip ourself */ if (__sync_add_and_fetch( &(self->secondaries[secpos[i]]->failure), 0)) continue; squeue = self->secondaries[secpos[i]]->queue; if (!self->failover && LEN_CRITICAL(squeue)) { squeue = NULL; continue; } if (*metric == NULL) { /* send up to batch size of our queue to this queue */ len = queue_dequeue_vector( self->batch, self->queue, self->bsize); self->batch[len] = NULL; metric = self->batch; } for (; *metric != NULL; metric++) if (!queue_putback(squeue, *metric)) break; /* try to put back stuff that didn't fit */ for (; *metric != NULL; metric++) if (!queue_putback(self->queue, *metric)) break; } for (; *metric != NULL; metric++) { if (mode & MODE_DEBUG) logerr("dropping metric: %s", *metric); free((char *)*metric); __sync_add_and_fetch(&(self->dropped), 1); } gettimeofday(&stop, NULL); self->ticks += timediff(start, stop); if (squeue == NULL) { /* we couldn't do anything, take it easy for a bit */ if (__sync_add_and_fetch(&(self->failure), 0) > 1) { /* This is a compound because I can't seem to figure * out how to atomically just "set" a variable. * It's not bad when in the middle there is a ++, * all that counts is that afterwards its > 0. */ __sync_and_and_fetch(&(self->failure), 0); __sync_add_and_fetch(&(self->failure), 1); } if (__sync_bool_compare_and_swap(&(self->keep_running), 0, 0)) break; usleep((200 + (rand() % 100)) * 1000); /* 200ms - 300ms */ } } else if (__sync_add_and_fetch(&(self->failure), 0) > 0) { if (__sync_bool_compare_and_swap(&(self->keep_running), 0, 0)) break; usleep((200 + (rand() % 100)) * 1000); /* 200ms - 300ms */ /* avoid overflowing */ if (__sync_add_and_fetch(&(self->failure), 0) > FAIL_WAIT_TIME) __sync_sub_and_fetch(&(self->failure), 1); } /* at this point we've got work to do, if we're instructed to * shut down, however, try to get everything out of the door * (until we fail, see top of this loop) */ gettimeofday(&start, NULL); /* try to connect */ if (self->fd < 0) { if (self->reresolve) { /* can only be CON_UDP/CON_TCP */ struct addrinfo *saddr; char sport[8]; /* re-lookup the address info, if it fails, stay with * whatever we have such that resolution errors incurred * after starting the relay won't make it fail */ freeaddrinfo(self->saddr); snprintf(sport, sizeof(sport), "%u", self->port); if (getaddrinfo(self->ip, sport, self->hint, &saddr) == 0) { self->saddr = saddr; } else { if (__sync_fetch_and_add(&(self->failure), 1) == 0) logerr("failed to resolve %s:%u, server unavailable\n", self->ip, self->port); self->saddr = NULL; /* this will break out below */ } } if (self->ctype == CON_PIPE) { int intconn[2]; if (pipe(intconn) < 0) { if (__sync_fetch_and_add(&(self->failure), 1) == 0) logerr("failed to create pipe: %s\n", strerror(errno)); continue; } dispatch_addconnection(intconn[0], NULL); self->fd = intconn[1]; } else if (self->ctype == CON_FILE) { if ((self->fd = open(self->ip, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) { if (__sync_fetch_and_add(&(self->failure), 1) == 0) logerr("failed to open file '%s': %s\n", self->ip, strerror(errno)); continue; } } else if (self->ctype == CON_UDP) { struct addrinfo *walk; for (walk = self->saddr; walk != NULL; walk = walk->ai_next) { if ((self->fd = socket(walk->ai_family, walk->ai_socktype, walk->ai_protocol)) < 0) { if (walk->ai_next == NULL && __sync_fetch_and_add(&(self->failure), 1) == 0) logerr("failed to create udp socket: %s\n", strerror(errno)); continue; } if (connect(self->fd, walk->ai_addr, walk->ai_addrlen) < 0) { if (walk->ai_next == NULL && __sync_fetch_and_add(&(self->failure), 1) == 0) logerr("failed to connect udp socket: %s\n", strerror(errno)); close(self->fd); self->fd = -1; continue; } /* we made it up here, so this connection is usable */ break; } /* if this didn't resolve to anything, treat as failure */ if (self->saddr == NULL) __sync_add_and_fetch(&(self->failure), 1); /* if all addrinfos failed, try again later */ if (self->fd < 0) continue; } else { /* CON_TCP */ int ret; int args; struct addrinfo *walk; for (walk = self->saddr; walk != NULL; walk = walk->ai_next) { if ((self->fd = socket(walk->ai_family, walk->ai_socktype, walk->ai_protocol)) < 0) { if (walk->ai_next == NULL && __sync_fetch_and_add(&(self->failure), 1) == 0) logerr("failed to create socket: %s\n", strerror(errno)); continue; } /* put socket in non-blocking mode such that we can * poll() (time-out) on the connect() call */ args = fcntl(self->fd, F_GETFL, NULL); if (fcntl(self->fd, F_SETFL, args | O_NONBLOCK) < 0) { logerr("failed to set socket non-blocking mode: %s\n", strerror(errno)); close(self->fd); self->fd = -1; continue; } ret = connect(self->fd, walk->ai_addr, walk->ai_addrlen); if (ret < 0 && errno == EINPROGRESS) { /* wait for connection to succeed if the OS thinks * it can succeed */ struct pollfd ufds[1]; ufds[0].fd = self->fd; ufds[0].events = POLLIN | POLLOUT; ret = poll(ufds, 1, self->iotimeout + (rand() % 100)); if (ret == 0) { /* time limit expired */ if (walk->ai_next == NULL && __sync_fetch_and_add( &(self->failure), 1) == 0) logerr("failed to connect() to " "%s:%u: Operation timed out\n", self->ip, self->port); close(self->fd); self->fd = -1; continue; } else if (ret < 0) { /* some select error occurred */ if (walk->ai_next && __sync_fetch_and_add( &(self->failure), 1) == 0) logerr("failed to poll() for %s:%u: %s\n", self->ip, self->port, strerror(errno)); close(self->fd); self->fd = -1; continue; } else { if (ufds[0].revents & POLLHUP) { if (walk->ai_next == NULL && __sync_fetch_and_add( &(self->failure), 1) == 0) logerr("failed to connect() for %s:%u: " "Connection refused\n", self->ip, self->port); close(self->fd); self->fd = -1; continue; } } } else if (ret < 0) { if (walk->ai_next == NULL && __sync_fetch_and_add(&(self->failure), 1) == 0) { logerr("failed to connect() to %s:%u: %s\n", self->ip, self->port, strerror(errno)); dispatch_check_rlimit_and_warn(); } close(self->fd); self->fd = -1; continue; } /* make socket blocking again */ if (fcntl(self->fd, F_SETFL, args) < 0) { logerr("failed to remove socket non-blocking " "mode: %s\n", strerror(errno)); close(self->fd); self->fd = -1; continue; } /* disable Nagle's algorithm, issue #208 */ args = 1; if (setsockopt(self->fd, IPPROTO_TCP, TCP_NODELAY, &args, sizeof(args)) != 0) ; /* ignore */ #ifdef TCP_USER_TIMEOUT /* break out of connections when no ACK is being * received for +- 10 seconds instead of * retransmitting for +- 15 minutes available on * linux >= 2.6.37 * the 10 seconds is in line with the SO_SNDTIMEO * set on the socket below */ args = 10000 + (rand() % 300); if (setsockopt(self->fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &args, sizeof(args)) != 0) ; /* ignore */ #endif /* if we reached up here, we're good to go, so don't * continue with the other addrinfos */ break; } /* if this didn't resolve to anything, treat as failure */ if (self->saddr == NULL) __sync_add_and_fetch(&(self->failure), 1); /* all available addrinfos failed on us */ if (self->fd < 0) continue; } /* ensure we will break out of connections being stuck more * quickly than the kernel would give up */ timeout.tv_sec = 10; timeout.tv_usec = (rand() % 300) * 1000; if (setsockopt(self->fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) != 0) ; /* ignore */ if (self->sockbufsize > 0) if (setsockopt(self->fd, SOL_SOCKET, SO_SNDBUF, &self->sockbufsize, sizeof(self->sockbufsize)) != 0) ; /* ignore */ #ifdef SO_NOSIGPIPE if (self->ctype == CON_TCP || self->ctype == CON_UDP) { int enable = 1; if (setsockopt(self->fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&enable, sizeof(enable)) != 0) logout("warning: failed to ignore SIGPIPE on socket: %s\n", strerror(errno)); } #endif #ifdef HAVE_GZIP if (self->transport == W_GZIP) { self->strm = gzdopen(self->fd, "w"); if (self->strm == Z_NULL) { logerr("failed to open gzip stream: %s\n", strerror(errno)); close(self->fd); self->fd = -1; continue; } } #endif #ifdef HAVE_LZ4 if (self->transport == W_LZ4) { z_strm *s = (z_strm *)malloc(sizeof(z_strm)); if (s == NULL) { logerr("failed to allocate lz4 stream: %s\n", strerror(errno)); close(self->fd); self->fd = -1; continue; } s->sock = self->fd; s->hdl.lz = LZ4_createStream(); if (s->hdl.lz == NULL) { logerr("failed to create lz4 stream: out of memory\n"); free(s); close(self->fd); self->fd = -1; continue; } self->strm = s; } #endif #ifdef HAVE_SSL if (self->transport == W_SSL) { int rv; self->strm = SSL_new(self->ctx); if (SSL_set_fd(self->strm, self->fd) == 0) { logerr("failed to SSL_set_fd: %s\n", ERR_reason_error_string(ERR_get_error())); self->strmclose(self->strm); self->fd = -1; continue; } if ((rv = SSL_connect(self->strm)) != 1) { logerr("failed to connect ssl stream: %s\n", ERR_reason_error_string( SSL_get_error(self->strm, rv))); self->strmclose(self->strm); self->fd = -1; continue; } } #endif } /* send up to batch size */ len = queue_dequeue_vector(self->batch, self->queue, self->bsize); self->batch[len] = NULL; metric = self->batch; if (len != 0 && __sync_bool_compare_and_swap(&(self->keep_running), 0, 0)) { /* be noisy during shutdown so we can track any slowing down * servers, possibly preventing us to shut down */ logerr("shutting down %s:%u: waiting for %zu metrics\n", self->ip, self->port, len + queue_len(self->queue)); } if (len == 0 && __sync_add_and_fetch(&(self->failure), 0)) { /* if we don't have anything to send, we have at least a * connection succeed, so assume the server is up again, * this is in particular important for recovering this * node by probes, to avoid starvation of this server since * its queue is possibly being offloaded to secondaries */ if (self->ctype != CON_UDP) logerr("server %s:%u: OK after probe\n", self->ip, self->port); __sync_and_and_fetch(&(self->failure), 0); } for (; *metric != NULL; metric++) { len = strlen(*metric); /* Write to the stream, this may not succeed completely due * to flow control and whatnot, which the docs suggest need * resuming to complete. So, use a loop, but to avoid * getting endlessly stuck on this, only try a limited * number of times for a single metric. */ for (cnt = 0, p = *metric; cnt < 10; cnt++) { if ((slen = self->strmwrite(self->strm, p, len)) != len) { if (slen >= 0) { p += slen; len -= slen; } else if (errno != EINTR) { break; } /* allow the remote to catch up */ usleep((50 + (rand() % 150)) * 1000); /* 50ms - 200ms */ } else { break; } } if (slen != len) { /* not fully sent (after tries), or failure * close connection regardless so we don't get * synchonisation problems */ if (self->ctype != CON_UDP && __sync_fetch_and_add(&(self->failure), 1) == 0) logerr("failed to write() to %s:%u: %s\n", self->ip, self->port, (slen < 0 ? self->strmerror(self->strm, slen) : "incomplete write")); self->strmclose(self->strm); self->fd = -1; /* put back stuff we couldn't process */ for (; *metric != NULL; metric++) { if (!queue_putback(self->queue, *metric)) { if (mode & MODE_DEBUG) logerr("server %s:%u: dropping metric: %s", self->ip, self->port, *metric); free((char *)*metric); __sync_add_and_fetch(&(self->dropped), 1); } } break; } else if (!__sync_bool_compare_and_swap(&(self->failure), 0, 0)) { if (self->ctype != CON_UDP) logerr("server %s:%u: OK\n", self->ip, self->port); __sync_and_and_fetch(&(self->failure), 0); } free((char *)*metric); __sync_add_and_fetch(&(self->metrics), 1); } gettimeofday(&stop, NULL); __sync_add_and_fetch(&(self->ticks), timediff(start, stop)); idle = 0; } __sync_and_and_fetch(&(self->running), 0); if (self->fd >= 0) self->strmclose(self->strm); if (secpos != NULL) free(secpos); return NULL; } /** * Allocate a new (outbound) server. Effectively this means a thread * that reads from the queue and sends this as good as it can to the ip * address and port associated. */ server * server_new( const char *ip, unsigned short port, con_type type, con_trnsp transport, con_proto ctype, struct addrinfo *saddr, struct addrinfo *hint, size_t qsize, size_t bsize, int maxstalls, unsigned short iotimeout, unsigned int sockbufsize) { server *ret; if ((ret = malloc(sizeof(server))) == NULL) return NULL; ret->type = type; ret->transport = transport; ret->ctype = ctype; ret->tid = 0; ret->secondaries = NULL; ret->secondariescnt = 0; ret->ip = strdup(ip); if (ret->ip == NULL) { free(ret); return NULL; } ret->port = port; ret->instance = NULL; ret->bsize = bsize; ret->iotimeout = iotimeout < 250 ? 600 : iotimeout; ret->sockbufsize = sockbufsize; ret->maxstalls = maxstalls; if ((ret->batch = malloc(sizeof(char *) * (bsize + 1))) == NULL) { free((char *)ret->ip); free(ret); return NULL; } ret->fd = -1; if (transport == W_PLAIN) { ret->strm = &(ret->fd); ret->strmwrite = &sockwrite; ret->strmflush = &sockflush; ret->strmclose = &sockclose; ret->strmerror = &sockerror; } #ifdef HAVE_GZIP else if (transport == W_GZIP) { ret->strmwrite = &gzipwrite; ret->strmflush = &gzipflush; ret->strmclose = &gzipclose; ret->strmerror = &sockerror; } #endif #ifdef HAVE_LZ4 else if (transport == W_LZ4) { ret->strmwrite = &lzwrite; ret->strmflush = &lzflush; ret->strmclose = &lzclose; ret->strmerror = &sockerror; } #endif #ifdef HAVE_SSL else if (transport == W_SSL) { /* create a auto-negotiate context */ const SSL_METHOD *m = SSLv23_client_method(); ret->ctx = SSL_CTX_new(m); if (ret->ctx == NULL) { char *err = ERR_error_string(ERR_get_error(), NULL); logerr("failed to create SSL context for server " "%s:%d: %s\n", ret->ip, ret->port, err); free((char *)ret->ip); free(ret); return NULL; } ret->strmwrite = &sslwrite; ret->strmflush = &sslflush; ret->strmclose = &sslclose; ret->strmerror = &sslerror; } #endif else { logerr("no transport type defined for server!!! (this is a BUG)\n"); assert(0); } ret->saddr = saddr; ret->reresolve = 0; ret->hint = NULL; if (hint != NULL) { ret->reresolve = 1; ret->hint = hint; } ret->queue = queue_new(qsize); if (ret->queue == NULL) { if (ret->hint) free(ret->hint); free(ret->batch); free((char *)ret->ip); free(ret); return NULL; } ret->failover = 0; ret->failure = 0; ret->running = 0; ret->keep_running = 1; ret->stallseq = 0; ret->metrics = 0; ret->dropped = 0; ret->stalls = 0; ret->ticks = 0; ret->prevmetrics = 0; ret->prevdropped = 0; ret->prevstalls = 0; ret->prevticks = 0; ret->tid = 0; return ret; } /** * Compare server s against the address info in saddr. A server is * considered to be equal is it is of the same socket family, type and * protocol, and if the target address and port are the same. When * saddr is NULL, a match against the given ip is attempted, e.g. for * file destinations. */ char server_cmp(server *s, struct addrinfo *saddr, const char *ip) { if ((saddr == NULL || s->saddr == NULL)) { if (strcmp(s->ip, ip) == 0) return 0; } else if ( s->saddr->ai_family == saddr->ai_family && s->saddr->ai_socktype == saddr->ai_socktype && s->saddr->ai_protocol == saddr->ai_protocol ) { if (saddr->ai_family == AF_INET) { struct sockaddr_in *l = ((struct sockaddr_in *)s->saddr->ai_addr); struct sockaddr_in *r = ((struct sockaddr_in *)saddr->ai_addr); if (l->sin_port == r->sin_port && l->sin_addr.s_addr == r->sin_addr.s_addr) return 0; } else if (saddr->ai_family == AF_INET6) { struct sockaddr_in6 *l = ((struct sockaddr_in6 *)s->saddr->ai_addr); struct sockaddr_in6 *r = ((struct sockaddr_in6 *)saddr->ai_addr); if (l->sin6_port == r->sin6_port && memcmp(l->sin6_addr.s6_addr, r->sin6_addr.s6_addr, sizeof(l->sin6_addr.s6_addr)) == 0) return 0; } } return 1; /* not equal */ } /** * Starts a previously created server using server_new(). Returns * errno if starting a thread failed, after which the caller should * server_free() the given s pointer. */ char server_start(server *s) { return pthread_create(&s->tid, NULL, &server_queuereader, s); } /** * Adds a list of secondary servers to this server. A secondary server * is a server which' queue will be checked when this server has nothing * to do. */ void server_add_secondaries(server *self, server **secondaries, size_t count) { self->secondaries = secondaries; self->secondariescnt = count; } /** * Flags this server as part of a failover cluster, which means the * secondaries are used only to offload on failure, not on queue stress. */ void server_set_failover(server *self) { self->failover = 1; } /** * Sets instance name only used for carbon_ch cluster type. */ void server_set_instance(server *self, char *instance) { if (self->instance != NULL) free(self->instance); self->instance = strdup(instance); } /** * Thin wrapper around the associated queue with the server object. * Returns true if the metric could be queued for sending, or the metric * was dropped because the associated server is down. Returns false * otherwise (when a retry seems like it could succeed shortly). */ inline char server_send(server *s, const char *d, char force) { if (queue_free(s->queue) == 0) { char failure = __sync_add_and_fetch(&(s->failure), 0); if (!force && s->secondariescnt > 0) { size_t i; /* don't immediately drop if we know there are others that * back us up */ for (i = 0; i < s->secondariescnt; i++) { if (!__sync_add_and_fetch(&(s->secondaries[i]->failure), 0)) { failure = 0; break; } } } if (failure || force || __sync_add_and_fetch(&(s->stallseq), 0) == s->maxstalls) { __sync_add_and_fetch(&(s->dropped), 1); /* excess event will be dropped by the enqueue below */ } else { __sync_add_and_fetch(&(s->stallseq), 1); __sync_add_and_fetch(&(s->stalls), 1); return 0; } } else { __sync_and_and_fetch(&(s->stallseq), 0); } queue_enqueue(s->queue, d); return 1; } /** * Tells this server to finish sending pending items from its queue. */ void server_shutdown(server *s) { int i; size_t failures; size_t inqueue; /* this function should only be called on a running server */ if (__sync_bool_compare_and_swap(&(s->keep_running), 0, 0)) return; if (s->secondariescnt > 0) { /* if we have a working connection, or we still have stuff in * our queue, wait for our secondaries, as they might need us, * or we need them */ do { failures = 0; inqueue = 0; for (i = 0; i < s->secondariescnt; i++) { if (__sync_add_and_fetch(&(s->secondaries[i]->failure), 0)) failures++; if (__sync_add_and_fetch(&(s->secondaries[i]->running), 0)) inqueue += queue_len(s->secondaries[i]->queue); } /* loop until we all failed, or nothing is in the queues */ } while (failures != s->secondariescnt && inqueue != 0 && logout("any_of cluster pending %zu metrics " "(with %zu failed nodes)\n", inqueue, failures) >= -1 && usleep((200 + (rand() % 100)) * 1000) <= 0); /* shut down entire cluster */ for (i = 0; i < s->secondariescnt; i++) __sync_bool_compare_and_swap( &(s->secondaries[i]->keep_running), 1, 0); /* to pretend to be dead for above loop (just in case) */ if (inqueue != 0) for (i = 0; i < s->secondariescnt; i++) __sync_add_and_fetch(&(s->secondaries[i]->failure), 1); /* wait for the secondaries to be stopped so we surely don't get * invalid reads when server_free is called */ for (i = 0; i < s->secondariescnt; i++) { while (__sync_add_and_fetch(&(s->secondaries[i]->running), 0)) usleep((200 + (rand() % 100)) * 1000); } } __sync_bool_compare_and_swap(&(s->keep_running), 1, 0); } /** * Frees this server and associated resources. This includes joining * the server thread. */ void server_free(server *s) { int err; if (s->tid != 0 && (err = pthread_join(s->tid, NULL)) != 0) logerr("%s:%u: failed to join server thread: %s\n", s->ip, s->port, strerror(err)); s->tid = 0; if (s->ctype == CON_TCP) { size_t qlen = queue_len(s->queue); if (qlen > 0) logerr("dropping %zu metrics for %s:%u\n", qlen, s->ip, s->port); } queue_destroy(s->queue); free(s->batch); if (s->instance) free(s->instance); if (s->saddr != NULL) freeaddrinfo(s->saddr); if (s->hint) free(s->hint); free((char *)s->ip); s->ip = NULL; free(s); } /** * Swaps the queue between server l to r. This is assumes both l and r * are not running. */ void server_swap_queue(server *l, server *r) { queue *t; assert(l->keep_running == 0 || l->tid == 0); assert(r->keep_running == 0 || r->tid == 0); t = l->queue; l->queue = r->queue; r->queue = t; /* swap associated statistics as well */ l->metrics = r->metrics; l->dropped = r->dropped; l->stalls = r->stalls; l->ticks = r->ticks; l->prevmetrics = r->prevmetrics; l->prevdropped = r->prevdropped; l->prevstalls = r->prevstalls; l->prevticks = r->prevticks; } /** * Returns the ip address this server points to. */ inline const char * server_ip(server *s) { if (s == NULL) return NULL; return s->ip; } /** * Returns the port this server connects at. */ inline unsigned short server_port(server *s) { if (s == NULL) return 0; return s->port; } /** * Returns the instance associated with this server. */ inline char * server_instance(server *s) { return s->instance; } /** * Returns the connection protocol of this server. */ inline con_proto server_ctype(server *s) { if (s == NULL) return CON_PIPE; return s->ctype; } /** * Returns the connection transport of this server. */ inline con_trnsp server_transport(server *s) { if (s == NULL) return W_PLAIN; return s->transport; } /** * Returns the connection type of this server. */ inline con_type server_type(server *s) { if (s == NULL) return T_LINEMODE; return s->type; } /** * Returns whether the last action on this server caused a failure. */ inline char server_failed(server *s) { if (s == NULL) return 0; return __sync_add_and_fetch(&(s->failure), 0); } /** * Returns the wall-clock time in microseconds (us) consumed sending metrics. */ inline size_t server_get_ticks(server *s) { if (s == NULL) return 0; return __sync_add_and_fetch(&(s->ticks), 0); } /** * Returns the wall-clock time in microseconds (us) consumed since last * call to this function. */ inline size_t server_get_ticks_sub(server *s) { size_t d; if (s == NULL) return 0; d = __sync_add_and_fetch(&(s->ticks), 0) - s->prevticks; s->prevticks += d; return d; } /** * Returns the number of metrics sent since start. */ inline size_t server_get_metrics(server *s) { if (s == NULL) return 0; return __sync_add_and_fetch(&(s->metrics), 0); } /** * Returns the number of metrics sent since last call to this function. */ inline size_t server_get_metrics_sub(server *s) { size_t d; if (s == NULL) return 0; d = __sync_add_and_fetch(&(s->metrics), 0) - s->prevmetrics; s->prevmetrics += d; return d; } /** * Returns the number of metrics dropped since start. */ inline size_t server_get_dropped(server *s) { if (s == NULL) return 0; return __sync_add_and_fetch(&(s->dropped), 0); } /** * Returns the number of metrics dropped since last call to this function. */ inline size_t server_get_dropped_sub(server *s) { size_t d; if (s == NULL) return 0; d = __sync_add_and_fetch(&(s->dropped), 0) - s->prevdropped; s->prevdropped += d; return d; } /** * Returns the number of stalls since start. A stall happens when the * queue is full, but it appears as if it would be a good idea to wait * for a brief period and retry. */ inline size_t server_get_stalls(server *s) { if (s == NULL) return 0; return __sync_add_and_fetch(&(s->stalls), 0); } /** * Returns the number of stalls since last call to this function. */ inline size_t server_get_stalls_sub(server *s) { size_t d; if (s == NULL) return 0; d = __sync_add_and_fetch(&(s->stalls), 0) - s->prevstalls; s->prevstalls += d; return d; } /** * Returns the (approximate) number of metrics waiting to be sent. */ inline size_t server_get_queue_len(server *s) { if (s == NULL) return 0; return queue_len(s->queue); } /** * Returns the allocated size of the queue backing metrics waiting to be * sent. */ inline size_t server_get_queue_size(server *s) { if (s == NULL) return 0; return queue_size(s->queue); } carbon-c-relay-3.2/server.h000066400000000000000000000040751317265605500156530ustar00rootroot00000000000000/* * Copyright 2013-2017 Fabian Groffen * * 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. */ #ifndef SERVER_H #define SERVER_H 1 #include #include "relay.h" #define SERVER_STALL_BITS 4 /* 0 up to 15 */ typedef struct _server server; server *server_new( const char *ip, unsigned short port, con_type type, con_trnsp transport, con_proto ctype, struct addrinfo *saddr, struct addrinfo *hint, size_t queuesize, size_t batchsize, int maxstalls, unsigned short iotimeout, unsigned int sockbufsize); char server_cmp(server *s, struct addrinfo *saddr, const char *ip); char server_start(server *s); void server_add_secondaries(server *d, server **sec, size_t cnt); void server_set_failover(server *d); void server_set_instance(server *d, char *inst); char server_send(server *s, const char *d, char force); void server_shutdown(server *s); void server_free(server *s); void server_swap_queue(server *l, server *r); const char *server_ip(server *s); unsigned short server_port(server *s); char *server_instance(server *s); con_proto server_ctype(server *s); con_type server_type(server *s); con_trnsp server_transport(server *s); char server_failed(server *s); size_t server_get_ticks(server *s); size_t server_get_metrics(server *s); size_t server_get_stalls(server *s); size_t server_get_dropped(server *s); size_t server_get_ticks_sub(server *s); size_t server_get_metrics_sub(server *s); size_t server_get_stalls_sub(server *s); size_t server_get_dropped_sub(server *s); size_t server_get_queue_len(server *s); size_t server_get_queue_size(server *s); #endif carbon-c-relay-3.2/test/000077500000000000000000000000001317265605500151455ustar00rootroot00000000000000carbon-c-relay-3.2/test/issue10.out000066400000000000000000000040011317265605500171620ustar00rootroot00000000000000listen type linemode 2003 proto tcp 2003 proto udp /tmp/.s.carbon-c-relay.2003 proto unix ; statistics submit every 60 seconds prefix with carbon.relays.test_hostname ; rewrite ^servers\.(cloud|bc|cwwtf|telhc)\.(int|test|stage|live|eng|green|mgmt)\.([a-zA-Z]+)([0-9]+) into servers.\1.\2.\3.\3\4 ; rewrite ^(.*)\.protocol_counter\.(.*)$ into \1.\2 ; rewrite ^(.*)\.tcp_connections\.(.*)$ into \1.\2 ; rewrite ^(.*)\.vmpage_action\.(.*)$ into \1.\2 ; rewrite tcpconns\.([0-9]+)-remote\.(.*)$ into tcpconns.outbound.\1.\2 ; rewrite tcpconns\.([0-9]+)-local\.(.*)$ into tcpconns.inbound.\1.\2 ; rewrite ^servers\.(cloud|bc|cwwtf|telhc)\.(int|test|stage|live|eng|green|mgmt)\.(.*)\.(.*)\.apps\.events\.(.*) into events.\1.\2.\3.\4.\5 ; rewrite -(average|percentile-90|p9[95]|sum_sq|sum|mean|lower|upper|count|stdev|median)$ into .\1 ; rewrite ^(a.*) into \_1_ ; rewrite ^(b.*) into \^1^ ; rewrite ^servers\.(cloud|bc|cwwtf|telhc)\.(int|test|stage|live|eng|green|mgmt)\.([a-zA-Z]+)([0-9]+) (regex) -> servers.cloud.int.foo42 into(servers.\1.\2.\3.\3\4) -> servers.cloud.int.foo.foo42 rewrite ^(.*)\.protocol_counter\.(.*)$ (regex) -> bla.protocol_counter.foo into(\1.\2) -> bla.foo rewrite ^(b.*) (regex) -> bla.foo into(\^1^) -> BLA.FOO^ rewrite tcpconns\.([0-9]+)-remote\.(.*)$ (regex) -> tcpconns.42-remote.foo into(tcpconns.outbound.\1.\2) -> tcpconns.outbound.42.foo rewrite ^servers\.(cloud|bc|cwwtf|telhc)\.(int|test|stage|live|eng|green|mgmt)\.(.*)\.(.*)\.apps\.events\.(.*) (regex) -> servers.cloud.int.foo.bar.apps.events.meh into(events.\1.\2.\3.\4.\5) -> events.cloud.int.foo.bar.meh rewrite -(average|percentile-90|p9[95]|sum_sq|sum|mean|lower|upper|count|stdev|median)$ (regex) -> foo.bar.whatever-average into(.\1) -> foo.bar.whatever.average rewrite ^(a.*) (regex) -> abLaH into(\_1_) -> ablah_ rewrite ^(b.*) (regex) -> bFoO into(\^1^) -> BFOO^ carbon-c-relay-3.2/test/issue10.tst000066400000000000000000000002341317265605500171710ustar00rootroot00000000000000servers.cloud.int.foo42 bla.protocol_counter.foo tcpconns.42-remote.foo servers.cloud.int.foo.bar.apps.events.meh foo.bar.whatever-average abLaH bFoO carbon-c-relay-3.2/test/issue117.out000066400000000000000000000003101317265605500172510ustar00rootroot00000000000000../issues/issue117.conf:20:1: invalid cluster 'really-doesnt-make-sense': replication count (10) is larger than the number of servers (3) ; ^ failed to read configuration '../issues/issue117.conf' carbon-c-relay-3.2/test/issue117.tst000066400000000000000000000000001317265605500172500ustar00rootroot00000000000000carbon-c-relay-3.2/test/issue156.out000066400000000000000000000002751317265605500172660ustar00rootroot00000000000000../issues/issue156.conf:8:1: cannot set instance 'c' for server 127.0.0.1:2003: server was previously defined with instance 'a' ; ^ failed to read configuration '../issues/issue156.conf' carbon-c-relay-3.2/test/issue156.tst000066400000000000000000000000001317265605500172530ustar00rootroot00000000000000carbon-c-relay-3.2/test/issue157.out000066400000000000000000000002401317265605500172570ustar00rootroot00000000000000../issues/issue157.conf:8:1: cannot share server 127.0.0.1:2003 with any_of/failover cluster 'two' ; ^ failed to read configuration '../issues/issue157.conf' carbon-c-relay-3.2/test/issue157.tst000066400000000000000000000000001317265605500172540ustar00rootroot00000000000000carbon-c-relay-3.2/test/issue163.out000066400000000000000000000007341317265605500172640ustar00rootroot00000000000000warning: 'send statistics to ...' is deprecated and will be removed in a future version, use 'statistics send to ...' instead listen type linemode 2003 proto tcp 2003 proto udp /tmp/.s.carbon-c-relay.2003 proto unix ; statistics submit every 60 seconds prefix with carbon.relays.test_hostname send to upstream stop ; cluster upstream forward 127.0.0.1:2003 ; match * send to blackhole stop ; carbon-c-relay-3.2/test/issue163.tst000066400000000000000000000000001317265605500172510ustar00rootroot00000000000000carbon-c-relay-3.2/test/issue165.out000066400000000000000000000022651317265605500172670ustar00rootroot00000000000000listen type linemode 2003 proto tcp 2003 proto udp /tmp/.s.carbon-c-relay.2003 proto unix ; statistics submit every 60 seconds prefix with carbon.relays.test_hostname ; cluster one any_of localhost:5000 localhost:6000 localhost:7000 ; rewrite ^servers\.(cloud|bc|cwwtf|telhc)\.(int|test|stage|live|eng|green|mgmt)\.([a-zA-Z]+)([0-9]+) into servers.\1.\2.\3.\3\4 ; rewrite ^(.*)\.protocol_counter\.(.*)$ into \1.\2 ; rewrite ^(.*)\.tcp_connections\.(.*)$ into \1.\2 ; rewrite ^(.*)\.vmpage_action\.(.*)$ into \1.\2 ; rewrite tcpconns\.([0-9]+)-remote\.(.*)$ into tcpconns.outbound.\1.\2 ; rewrite tcpconns\.([0-9]+)-local\.(.*)$ into tcpconns.inbound.\1.\2 ; rewrite ^servers\.(cloud|bc|cwwtf|telhc)\.(int|test|stage|live|eng|green|mgmt)\.(.*)\.(.*)\.apps\.events\.(.*) into events.\1.\2.\3.\4.\5 ; rewrite -(average|percentile-90|p9[95]|sum_sq|sum|mean|lower|upper|count|stdev|median)$ into .\1 ; rewrite ^(a.*) into \_1_ ; rewrite ^(b.*) into \^1^ ; match ^carbon\.relays\..*$ send to blackhole stop ; match * send to one ; carbon-c-relay-3.2/test/issue165.tst000066400000000000000000000000001317265605500172530ustar00rootroot00000000000000carbon-c-relay-3.2/test/issue180.out000066400000000000000000000005461317265605500172640ustar00rootroot00000000000000listen type linemode 2003 proto tcp 2003 proto udp /tmp/.s.carbon-c-relay.2003 proto unix ; statistics submit every 60 seconds prefix with carbon.relays.test_hostname ; match foo send to blackhole stop ; match baz send to blackhole stop ; match bar send to blackhole stop ; carbon-c-relay-3.2/test/issue180.tst000066400000000000000000000000001317265605500172500ustar00rootroot00000000000000carbon-c-relay-3.2/test/issue184.out000066400000000000000000000040401317265605500172610ustar00rootroot00000000000000listen type linemode 2003 proto tcp 2003 proto udp /tmp/.s.carbon-c-relay.2003 proto unix ; statistics submit every 60 seconds prefix with carbon.relays.test_hostname ; aggregate (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) (foo|bar)\.(.+) every 1 seconds expire after 2 seconds timestamp at end of bucket compute sum write to \1 ; # common pattern group 'dothework' contains 4 aggregations/matches aggregate dothework.(foo|bar)\.(.+) somethingelse.dothework\.(.+) more.dothework.(yo.) whatever.dothework.(yo.) every 1 seconds expire after 2 seconds timestamp at end of bucket compute sum write to \1 ; # end of group 'dothework' aggregate a.nonmatching.thing every 1 seconds expire after 2 seconds timestamp at end of bucket compute sum write to \1 ; carbon-c-relay-3.2/test/issue184.tst000066400000000000000000000000001317265605500172540ustar00rootroot00000000000000carbon-c-relay-3.2/test/issue202.out000066400000000000000000000006631317265605500172570ustar00rootroot00000000000000listen type linemode 2003 proto tcp 2003 proto udp /tmp/.s.carbon-c-relay.2003 proto unix ; statistics submit every 60 seconds prefix with carbon.relays.test_hostname ; cluster my_cluster forward 127.0.0.1:2003 ; cluster my_homie_cluster forward 127.0.0.1:2004 ; match ^awesome\.(.+) send to my_cluster my_homie_cluster stop ; carbon-c-relay-3.2/test/issue202.tst000066400000000000000000000000001317265605500172430ustar00rootroot00000000000000carbon-c-relay-3.2/test/issue213.dbg000066400000000000000000000000001317265605500171670ustar00rootroot00000000000000carbon-c-relay-3.2/test/issue213.out000066400000000000000000000100111317265605500172450ustar00rootroot00000000000000listen type linemode 2003 proto tcp 2003 proto udp /tmp/.s.carbon-c-relay.2003 proto unix ; statistics submit every 60 seconds prefix with carbon.relays.test_hostname ; cluster graphite forward 127.0.0.1:2004 ; # stub match for aggregate/statistics rule with send to match ^_aggregator_stub_0xc0d3__ send to graphite stop ; # stub match for aggregate/statistics rule with send to match ^_aggregator_stub_0xc0d3__ send to graphite stop ; # stub match for aggregate/statistics rule with send to match ^_aggregator_stub_0xc0d3__ send to graphite stop ; # stub match for aggregate/statistics rule with send to match ^_aggregator_stub_0xc0d3__ send to graphite stop ; # stub match for aggregate/statistics rule with send to match ^_aggregator_stub_0xc0d3__ send to graphite stop ; # stub match for aggregate/statistics rule with send to match ^_aggregator_stub_0xc0d3__ send to graphite stop ; # stub match for aggregate/statistics rule with send to match ^_aggregator_stub_0xc0d3__ send to graphite stop ; # stub match for aggregate/statistics rule with send to match ^_aggregator_stub_0xc0d3__ send to graphite stop ; # stub match for aggregate/statistics rule with send to match ^_aggregator_stub_0xc0d3__ send to graphite stop ; # stub match for aggregate/statistics rule with send to match ^_aggregator_stub_0xc0d3__ send to graphite stop ; # stub match for aggregate/statistics rule with send to match ^_aggregator_stub_0xc0d3__ send to graphite stop ; aggregate ^1\.(foo|bar)\.some_instance\.([^.]+)\.(.+) every 30 seconds expire after 90 seconds timestamp at end of bucket compute sum write to _aggregator_stub_0xc0d3__sums.some_instance.\2.\3 ; aggregate ^2\.(foo|bar)\.some_instance\.([^.]+)\.(.+) every 30 seconds expire after 90 seconds timestamp at end of bucket compute sum write to _aggregator_stub_0xc0d3__sums.some_instance.\2.\3 ; aggregate ^3\.(foo|bar)\.some_instance\.([^.]+)\.(.+) every 30 seconds expire after 90 seconds timestamp at end of bucket compute sum write to _aggregator_stub_0xc0d3__sums.some_instance.\2.\3 ; aggregate ^4\.(foo|bar)\.some_instance\.([^.]+)\.(.+) every 30 seconds expire after 90 seconds timestamp at end of bucket compute sum write to _aggregator_stub_0xc0d3__sums.some_instance.\2.\3 ; aggregate ^5\.(foo|bar)\.some_instance\.([^.]+)\.(.+) every 30 seconds expire after 90 seconds timestamp at end of bucket compute sum write to _aggregator_stub_0xc0d3__sums.some_instance.\2.\3 ; aggregate ^6\.(foo|bar)\.some_instance\.([^.]+)\.(.+) every 30 seconds expire after 90 seconds timestamp at end of bucket compute sum write to _aggregator_stub_0xc0d3__sums.some_instance.\2.\3 ; aggregate ^7\.(foo|bar)\.some_instance\.([^.]+)\.(.+) every 30 seconds expire after 90 seconds timestamp at end of bucket compute sum write to _aggregator_stub_0xc0d3__sums.some_instance.\2.\3 ; aggregate ^8\.(foo|bar)\.some_instance\.([^.]+)\.(.+) every 30 seconds expire after 90 seconds timestamp at end of bucket compute sum write to _aggregator_stub_0xc0d3__sums.some_instance.\2.\3 ; aggregate ^9\.(foo|bar)\.some_instance\.([^.]+)\.(.+) every 30 seconds expire after 90 seconds timestamp at end of bucket compute sum write to _aggregator_stub_0xc0d3__sums.some_instance.\2.\3 ; aggregate ^10\.(foo|bar)\.some_instance\.([^.]+)\.(.+) every 30 seconds expire after 90 seconds timestamp at end of bucket compute sum write to _aggregator_stub_0xc0d3__sums.some_instance.\2.\3 ; aggregate ^11\.(foo|bar)\.some_instance\.([^.]+)\.(.+) every 30 seconds expire after 90 seconds timestamp at end of bucket compute sum write to _aggregator_stub_0xc0d3__sums.some_instance.\2.\3 ; carbon-c-relay-3.2/test/issue218.out000066400000000000000000000044031317265605500172620ustar00rootroot00000000000000listen type linemode 2003 proto tcp 2003 proto udp /tmp/.s.carbon-c-relay.2003 proto unix ; statistics submit every 60 seconds prefix with carbon.relays.test_hostname ; rewrite abcdefg0 into b ; rewrite abcdefg1 into b ; rewrite abcdefg2 into b ; rewrite abcdefg3 into b ; rewrite abcdefg4 into b ; rewrite abcdefg5 into b ; rewrite abcdefg6 into b ; rewrite abcdefg7 into b ; rewrite abcdefg8 into b ; rewrite abcdefg9 into b ; rewrite abcdefg10 into b ; rewrite abcdefg11 into b ; rewrite abcdefg12 into b ; rewrite abcdefg13 into b ; rewrite abcdefg14 into b ; rewrite abcdefg15 into b ; rewrite abcdefg16 into b ; rewrite abcdefg17 into b ; rewrite abcdefg18 into b ; rewrite abcdefg19 into b ; rewrite abcdefg20 into b ; rewrite abcdefg21 into b ; rewrite abcdefg22 into b ; rewrite abcdefg23 into b ; rewrite abcdefg24 into b ; rewrite abcdefg25 into b ; rewrite abcdefg26 into b ; rewrite abcdefg27 into b ; rewrite abcdefg28 into b ; rewrite abcdefg29 into b ; rewrite abcdefg30 into b ; rewrite abcdefg31 into b ; rewrite abcdefg32 into b ; rewrite abcdefg33 into b ; rewrite abcdefg34 into b ; rewrite abcdefg35 into b ; rewrite abcdefg36 into b ; rewrite abcdefg37 into b ; rewrite abcdefg38 into b ; rewrite abcdefg39 into b ; rewrite abcdefg40 into b ; rewrite abcdefg41 into b ; rewrite abcdefg42 into b ; rewrite abcdefg43 into b ; rewrite abcdefg44 into b ; rewrite abcdefg45 into b ; rewrite abcdefg46 into b ; rewrite abcdefg47 into b ; rewrite abcdefg48 into b ; rewrite abcdefg49 into b ; rewrite abcdefg50 into b ; rewrite abcdefg51 into b ; rewrite abcdefg52 into b ; rewrite abcdefg53 into b ; rewrite abcdefg54 into b ; rewrite abcdefg55 into b ; rewrite abcdefg56 into b ; rewrite abcdefg57 into b ; rewrite abcdefg58 into b ; rewrite abcdefg59 into b ; carbon-c-relay-3.2/test/issue218.tst000066400000000000000000000000001317265605500172520ustar00rootroot00000000000000carbon-c-relay-3.2/test/issue228.out000066400000000000000000000031101317265605500172550ustar00rootroot00000000000000listen type linemode 2003 proto tcp 2003 proto udp /tmp/.s.carbon-c-relay.2003 proto unix ; statistics submit every 60 seconds prefix with carbon.relays.test_hostname ; cluster foo file ip /dev/stdout ; match foo.bar validate ^[0-9.e+-]+\ [0-9.e+-]+$ else drop send to foo ; match foo.bar validate ^[0-9]+\ [0-9]+$ else drop send to foo stop ; match * validate ^[0-9]+\ [0-9]+$ else drop ; match * validate ^unknown+\ [0-9]+$ else log ; match foo.bar (regex) -> foo.bar validate ^[0-9.e+-]+\ [0-9.e+-]+$ -> this wrong fail -> drop match foo.bar (regex) -> foo.bar validate ^[0-9]+\ [0-9]+$ -> this wrong fail -> drop stop match foo.bar (regex) -> foo.bar validate ^[0-9.e+-]+\ [0-9.e+-]+$ -> 42 42 match file ip(foo) /dev/stdout match foo.bar (regex) -> foo.bar validate ^[0-9]+\ [0-9]+$ -> 42 42 match file ip(foo) /dev/stdout stop match foo.bar (regex) -> foo.bar validate ^[0-9.e+-]+\ [0-9.e+-]+$ -> 4.2 4.2 match file ip(foo) /dev/stdout match foo.bar (regex) -> foo.bar validate ^[0-9]+\ [0-9]+$ -> 4.2 4.2 fail -> drop stop match * -> blah validate ^[0-9]+\ [0-9]+$ -> 4.2 4.2 fail -> drop stop match * -> blah validate ^[0-9]+\ [0-9]+$ -> 42 42 match match * -> blah validate ^unknown+\ [0-9]+$ -> 42 42 fail -> log stop carbon-c-relay-3.2/test/issue228.tst000066400000000000000000000001131317265605500172600ustar00rootroot00000000000000foo.bar this wrong foo.bar 42 42 foo.bar 4.2 4.2 blah 4.2 4.2 blah 42 42 carbon-c-relay-3.2/test/issue235.out000066400000000000000000000014451317265605500172640ustar00rootroot00000000000000listen type linemode 2003 proto tcp 2003 proto udp /tmp/.s.carbon-c-relay.2003 proto unix ; statistics submit every 60 seconds prefix with carbon.relays.test_hostname ; cluster aggrs fnv1a_ch replication 1 127.0.0.1:2003=a 127.0.0.1:2004=b 127.0.0.1:2005=c 127.0.0.1:2006=d 127.0.0.2:2003=a 127.0.0.2:2004=b 127.0.0.2:2005=c 127.0.0.2:2006=d ; match ^collection.([^.]+).([^.]+).([^.]+).[^.]+.(.+) route using collection.\1.\2.\3.\4 send to aggrs ; match ^collection.([^.]+).([^.]+).([^.]+).[^.]+.(.+) (regex) -> collection.fo.bar.x.y.blakwklsa.skla fnv1a_ch(aggrs) using(collection.\1.\2.\3.\4) -> collection.fo.bar.x.blakwklsa.skla 127.0.0.1:2004 carbon-c-relay-3.2/test/issue235.tst000066400000000000000000000000451317265605500172620ustar00rootroot00000000000000collection.fo.bar.x.y.blakwklsa.skla carbon-c-relay-3.2/test/issue236.dbg000066400000000000000000000042421317265605500172100ustar00rootroot00000000000000cd85d26b19018dec78e33d44e1477993130267ec79f92abd25ece33fa029bf56 f802b190bb63b02c2b933fd017b3764f9bceafb351ffaa92f06fed6fa0f9017c df7c8a8cd0ab1e68b72555ee8cd297e8853bed3190554b32a09faa0d722b59bb 45f2add911716502327e88d43d0bc6316507f95212bb16a604b6dc04a851cee8 2a96380d6b4df489d14a5b01426d9c21d9f4f16551bae7bccabc24ee0af4dd8d 07058ac7da6ed9fb9aeb00da1ec32336a295349343f19ce9452552e311829ec2 6225da61cb0f8872e74e16db799acddf09c1b13c9bfa263d45418081440999e1 2136e0d19c8a1b557df0daa81646a1c7c96d5f3522f5484e2e641859d093c2dd 8f811b2ce741185954408bd6ef95b7317d8f68b2d66ae5b095e6960308cc7ed3 d681fa62dd8cd4ff60c44ae2647914fc41c13b0fc269f7560071a7a3ad410907 23363a396895571de9b529708fe6a0f6a74302963011aff0331dedd97e73afb0 85dd0943b0e24c67e0e6307f5e3ade9d244077576c7d401702d4cfbdecd62ee6 8b03cb452953a78dc9a647dca3b8b28f390f6ca3205597105a77c3453b59cb53 16ec4868740a3961379ce0df077ace28e81e0200767ed2ead50fdb654a10c4e3 0bb3a449bf2fc9eb3fc906261ecaa62970d4a03d5f70575fa4b60aac97529cd8 79d16b180742149eca6e504085e22d4f2b3bc354e6ad16beb09ab69bce41146e e0d8eaf81773c01d856d986a0c87e6e34582290f7da7eb0b910b1fb8a809ebf0 40fa7bde092cfdde97be93469dfc7d28073ff4221a1c8008a137107a0f63abbc 48a10f8ef3512208b85a50546f0dd4cb6dda8531ac2ce5cf3a093e3189764167 67546909eeb4e6ea1059fde6d075b19f5d2b18afddb6027594b6544bc7e34313 foo4lohf4AepooJoh3CaiNuyaich5to4raawei6elohfohf8Fiet0Uosheem Obainoh5vuleiDai2iu3wae8iem5faisoh1Aeg4jaijais4aex3puhieM6gi jai2sus3xiex4eunomi4Ne9eRoveecah8suebeiha0Eer1raijaa4Fai1boh taequei9uL4eicoo5eu0ua7daiyihishahch4chuac0eibetahFieghahYie uu7Ov0ahC5cheiT4lieQuahba1Di8ahjei3ec8aezaloh0eihahgh9johro9 pha4thoiSheedaewoo3RieSoC9iquaish2eica8ahsheodeiveihia6eemie dier5xighoch1kaishaa4waifenai1of8dieshuQu3tohshaiphepet8oaBe aiRohr4fi6eim1mee0phah8taiwoiTi0wieh5Shahpe5xaicoo4eesah8ein shei2aed4thaiL1chooch8baewoh2ikuphubie6nooreiGuvah8meithoode ood7ia6goh5aab8ukei1Oa8zeeg4bohheitheiT6WeeTh2az4ku4vaegh3Sh aeg6ajiePheeQuau9ash ureiphahJuichue3vohW uodahf9auXeef3iechee ooy2rah2Wahmohvuutee xu7ooXohduotaht1quie ohth8Shei7Yei1aewala XoChoh7iecee0ahg3fu5 Iecee6izeig2oshieChe zoi4wah2Ooh4Laeveiro nahw4tugh5emaeJ6quo3 # before lowest carbon iiZeik7oongohdohgane # before lowest fnv1a Heak8dahph1is7eaghah carbon-c-relay-3.2/test/issue236.out000066400000000000000000001515501317265605500172700ustar00rootroot00000000000000listen type linemode 2003 proto tcp 2003 proto udp /tmp/.s.carbon-c-relay.2003 proto unix ; statistics submit every 60 seconds prefix with carbon.relays.test_hostname ; cluster carbon carbon_ch replication 2 127.0.0.1:2003 127.0.0.2:2004 127.0.0.3:2005 127.0.0.4:2006 127.0.0.5:2007 127.0.0.6:2008 127.0.0.7:2009 ; # hash ring for carbon follows 372@127.0.0.7:2009 461@127.0.0.5:2007 508@127.0.0.4:2006 704@127.0.0.6:2008 708@127.0.0.6:2008 724@127.0.0.1:2003 743@127.0.0.7:2009 872@127.0.0.2:2004 1004@127.0.0.3:2005 1054@127.0.0.1:2003 1055@127.0.0.3:2005 1247@127.0.0.5:2007 1331@127.0.0.2:2004 1489@127.0.0.5:2007 1557@127.0.0.3:2005 1672@127.0.0.5:2007 1812@127.0.0.5:2007 1834@127.0.0.3:2005 2261@127.0.0.6:2008 2286@127.0.0.3:2005 2379@127.0.0.4:2006 2535@127.0.0.7:2009 2770@127.0.0.4:2006 2772@127.0.0.4:2006 2832@127.0.0.7:2009 2862@127.0.0.7:2009 2935@127.0.0.5:2007 3033@127.0.0.3:2005 3254@127.0.0.2:2004 3393@127.0.0.6:2008 3486@127.0.0.7:2009 3676@127.0.0.7:2009 3708@127.0.0.5:2007 3835@127.0.0.3:2005 3979@127.0.0.5:2007 3989@127.0.0.2:2004 4113@127.0.0.7:2009 4125@127.0.0.4:2006 4126@127.0.0.6:2008 4273@127.0.0.5:2007 4379@127.0.0.6:2008 4555@127.0.0.3:2005 4620@127.0.0.4:2006 4659@127.0.0.3:2005 4971@127.0.0.3:2005 5053@127.0.0.3:2005 5182@127.0.0.5:2007 5227@127.0.0.6:2008 5240@127.0.0.3:2005 5566@127.0.0.3:2005 5987@127.0.0.7:2009 6056@127.0.0.7:2009 6103@127.0.0.6:2008 6180@127.0.0.2:2004 6316@127.0.0.1:2003 6330@127.0.0.4:2006 6335@127.0.0.1:2003 6546@127.0.0.4:2006 6676@127.0.0.7:2009 6803@127.0.0.5:2007 6851@127.0.0.3:2005 6943@127.0.0.6:2008 7144@127.0.0.3:2005 7159@127.0.0.7:2009 7278@127.0.0.1:2003 7840@127.0.0.1:2003 7896@127.0.0.3:2005 8135@127.0.0.4:2006 8137@127.0.0.7:2009 8256@127.0.0.6:2008 8341@127.0.0.4:2006 8369@127.0.0.4:2006 8371@127.0.0.1:2003 8373@127.0.0.3:2005 8390@127.0.0.2:2004 8483@127.0.0.2:2004 8525@127.0.0.1:2003 8670@127.0.0.3:2005 8716@127.0.0.7:2009 8845@127.0.0.6:2008 8909@127.0.0.1:2003 9152@127.0.0.3:2005 9213@127.0.0.4:2006 9230@127.0.0.2:2004 9272@127.0.0.4:2006 9393@127.0.0.3:2005 9575@127.0.0.7:2009 9600@127.0.0.2:2004 9968@127.0.0.7:2009 10153@127.0.0.2:2004 10228@127.0.0.3:2005 10246@127.0.0.1:2003 10310@127.0.0.3:2005 10379@127.0.0.6:2008 10477@127.0.0.7:2009 10678@127.0.0.2:2004 10771@127.0.0.4:2006 10843@127.0.0.2:2004 10848@127.0.0.5:2007 10878@127.0.0.3:2005 10906@127.0.0.5:2007 10908@127.0.0.3:2005 10981@127.0.0.3:2005 11211@127.0.0.7:2009 11294@127.0.0.2:2004 11319@127.0.0.5:2007 11330@127.0.0.4:2006 11341@127.0.0.2:2004 11354@127.0.0.5:2007 11426@127.0.0.1:2003 11433@127.0.0.5:2007 11493@127.0.0.2:2004 11519@127.0.0.6:2008 11660@127.0.0.4:2006 11713@127.0.0.1:2003 11906@127.0.0.3:2005 11929@127.0.0.5:2007 11938@127.0.0.3:2005 11942@127.0.0.2:2004 12148@127.0.0.2:2004 12196@127.0.0.6:2008 12305@127.0.0.4:2006 12333@127.0.0.7:2009 12436@127.0.0.2:2004 12491@127.0.0.7:2009 12745@127.0.0.5:2007 12759@127.0.0.3:2005 13167@127.0.0.6:2008 13213@127.0.0.5:2007 13282@127.0.0.5:2007 13503@127.0.0.7:2009 13580@127.0.0.5:2007 13924@127.0.0.6:2008 13979@127.0.0.4:2006 14059@127.0.0.7:2009 14061@127.0.0.7:2009 14076@127.0.0.2:2004 14216@127.0.0.5:2007 14278@127.0.0.4:2006 14301@127.0.0.6:2008 14383@127.0.0.4:2006 14456@127.0.0.6:2008 14505@127.0.0.4:2006 14596@127.0.0.3:2005 14637@127.0.0.1:2003 14639@127.0.0.7:2009 14711@127.0.0.1:2003 14841@127.0.0.2:2004 15052@127.0.0.5:2007 15302@127.0.0.4:2006 15503@127.0.0.3:2005 15873@127.0.0.2:2004 15922@127.0.0.7:2009 16069@127.0.0.4:2006 16091@127.0.0.6:2008 16142@127.0.0.2:2004 16328@127.0.0.2:2004 16645@127.0.0.4:2006 16671@127.0.0.4:2006 16814@127.0.0.5:2007 16824@127.0.0.1:2003 16864@127.0.0.6:2008 16971@127.0.0.5:2007 16991@127.0.0.1:2003 17075@127.0.0.3:2005 17115@127.0.0.3:2005 17121@127.0.0.6:2008 17190@127.0.0.1:2003 17193@127.0.0.6:2008 17326@127.0.0.2:2004 17396@127.0.0.3:2005 17408@127.0.0.4:2006 17410@127.0.0.5:2007 17414@127.0.0.1:2003 18024@127.0.0.6:2008 18050@127.0.0.5:2007 18103@127.0.0.1:2003 18319@127.0.0.7:2009 18320@127.0.0.6:2008 18541@127.0.0.7:2009 18841@127.0.0.5:2007 18912@127.0.0.7:2009 18935@127.0.0.5:2007 18947@127.0.0.1:2003 18981@127.0.0.2:2004 18996@127.0.0.7:2009 19227@127.0.0.2:2004 19238@127.0.0.4:2006 19404@127.0.0.3:2005 19487@127.0.0.4:2006 19533@127.0.0.5:2007 19650@127.0.0.7:2009 19656@127.0.0.7:2009 19907@127.0.0.2:2004 19981@127.0.0.5:2007 20122@127.0.0.7:2009 20284@127.0.0.5:2007 20377@127.0.0.3:2005 20593@127.0.0.1:2003 20650@127.0.0.5:2007 20712@127.0.0.5:2007 20719@127.0.0.7:2009 20778@127.0.0.4:2006 20869@127.0.0.5:2007 20872@127.0.0.5:2007 21148@127.0.0.7:2009 21176@127.0.0.4:2006 21308@127.0.0.6:2008 21360@127.0.0.1:2003 21402@127.0.0.7:2009 21499@127.0.0.6:2008 21510@127.0.0.5:2007 21569@127.0.0.3:2005 21795@127.0.0.2:2004 21995@127.0.0.5:2007 21998@127.0.0.2:2004 22045@127.0.0.2:2004 22073@127.0.0.5:2007 22224@127.0.0.6:2008 22273@127.0.0.6:2008 22419@127.0.0.4:2006 22540@127.0.0.7:2009 22546@127.0.0.4:2006 22683@127.0.0.2:2004 22702@127.0.0.5:2007 22746@127.0.0.2:2004 22753@127.0.0.3:2005 22753@127.0.0.3:2005 22912@127.0.0.2:2004 22933@127.0.0.4:2006 22990@127.0.0.7:2009 23128@127.0.0.7:2009 23166@127.0.0.7:2009 23232@127.0.0.6:2008 23376@127.0.0.6:2008 23412@127.0.0.1:2003 23503@127.0.0.4:2006 23556@127.0.0.6:2008 23787@127.0.0.1:2003 23794@127.0.0.7:2009 23814@127.0.0.7:2009 23886@127.0.0.2:2004 24036@127.0.0.7:2009 24331@127.0.0.1:2003 24338@127.0.0.6:2008 24412@127.0.0.2:2004 24419@127.0.0.7:2009 24444@127.0.0.2:2004 24485@127.0.0.6:2008 24498@127.0.0.6:2008 24520@127.0.0.7:2009 24723@127.0.0.5:2007 24790@127.0.0.5:2007 24802@127.0.0.6:2008 24808@127.0.0.1:2003 24809@127.0.0.7:2009 24859@127.0.0.2:2004 24942@127.0.0.1:2003 24958@127.0.0.2:2004 25064@127.0.0.2:2004 25064@127.0.0.2:2004 25077@127.0.0.6:2008 25334@127.0.0.1:2003 25470@127.0.0.6:2008 25480@127.0.0.3:2005 25503@127.0.0.1:2003 25578@127.0.0.7:2009 25678@127.0.0.5:2007 25690@127.0.0.7:2009 25707@127.0.0.6:2008 25918@127.0.0.3:2005 26005@127.0.0.1:2003 26107@127.0.0.7:2009 26171@127.0.0.5:2007 26268@127.0.0.6:2008 26535@127.0.0.7:2009 26681@127.0.0.7:2009 26739@127.0.0.6:2008 26862@127.0.0.3:2005 26998@127.0.0.4:2006 27205@127.0.0.7:2009 27448@127.0.0.3:2005 27541@127.0.0.4:2006 27771@127.0.0.5:2007 27909@127.0.0.1:2003 27941@127.0.0.7:2009 28008@127.0.0.2:2004 28343@127.0.0.6:2008 28382@127.0.0.7:2009 28589@127.0.0.5:2007 28628@127.0.0.6:2008 28738@127.0.0.7:2009 28785@127.0.0.5:2007 28976@127.0.0.5:2007 28978@127.0.0.3:2005 29123@127.0.0.3:2005 29160@127.0.0.1:2003 29409@127.0.0.1:2003 29438@127.0.0.7:2009 29504@127.0.0.4:2006 29524@127.0.0.2:2004 29556@127.0.0.6:2008 29588@127.0.0.5:2007 29704@127.0.0.4:2006 29794@127.0.0.5:2007 29810@127.0.0.3:2005 29851@127.0.0.7:2009 30015@127.0.0.3:2005 30056@127.0.0.1:2003 30080@127.0.0.2:2004 30143@127.0.0.5:2007 30174@127.0.0.6:2008 30181@127.0.0.2:2004 30311@127.0.0.2:2004 30402@127.0.0.3:2005 30422@127.0.0.1:2003 30557@127.0.0.6:2008 30699@127.0.0.6:2008 30722@127.0.0.3:2005 30727@127.0.0.1:2003 30740@127.0.0.6:2008 30810@127.0.0.5:2007 30883@127.0.0.2:2004 30968@127.0.0.7:2009 30997@127.0.0.2:2004 31020@127.0.0.2:2004 31249@127.0.0.3:2005 31271@127.0.0.6:2008 31389@127.0.0.6:2008 31393@127.0.0.5:2007 31715@127.0.0.5:2007 31729@127.0.0.6:2008 31753@127.0.0.7:2009 31960@127.0.0.2:2004 31981@127.0.0.1:2003 32097@127.0.0.6:2008 32098@127.0.0.4:2006 32099@127.0.0.2:2004 32154@127.0.0.3:2005 32207@127.0.0.6:2008 32267@127.0.0.5:2007 32332@127.0.0.2:2004 32338@127.0.0.1:2003 32341@127.0.0.3:2005 32754@127.0.0.6:2008 32764@127.0.0.5:2007 32928@127.0.0.4:2006 32982@127.0.0.2:2004 33013@127.0.0.3:2005 33144@127.0.0.1:2003 33261@127.0.0.1:2003 33321@127.0.0.7:2009 33433@127.0.0.4:2006 33565@127.0.0.3:2005 33579@127.0.0.7:2009 33606@127.0.0.4:2006 33674@127.0.0.4:2006 33698@127.0.0.3:2005 33773@127.0.0.2:2004 34190@127.0.0.5:2007 34215@127.0.0.4:2006 34281@127.0.0.5:2007 34304@127.0.0.6:2008 34320@127.0.0.1:2003 34333@127.0.0.6:2008 34429@127.0.0.3:2005 34449@127.0.0.7:2009 34482@127.0.0.2:2004 34524@127.0.0.4:2006 34537@127.0.0.2:2004 34546@127.0.0.3:2005 34670@127.0.0.2:2004 35531@127.0.0.2:2004 35557@127.0.0.4:2006 35569@127.0.0.4:2006 35809@127.0.0.5:2007 36036@127.0.0.3:2005 36114@127.0.0.1:2003 36149@127.0.0.5:2007 36341@127.0.0.5:2007 36431@127.0.0.4:2006 36630@127.0.0.7:2009 36704@127.0.0.4:2006 36757@127.0.0.6:2008 36899@127.0.0.6:2008 36966@127.0.0.6:2008 37082@127.0.0.7:2009 37278@127.0.0.2:2004 37538@127.0.0.7:2009 37548@127.0.0.1:2003 37717@127.0.0.2:2004 37783@127.0.0.4:2006 37888@127.0.0.1:2003 38144@127.0.0.6:2008 38208@127.0.0.5:2007 38305@127.0.0.3:2005 38434@127.0.0.6:2008 38436@127.0.0.3:2005 38540@127.0.0.2:2004 38602@127.0.0.6:2008 38638@127.0.0.3:2005 38689@127.0.0.1:2003 38761@127.0.0.3:2005 39098@127.0.0.6:2008 39190@127.0.0.2:2004 39265@127.0.0.1:2003 39698@127.0.0.6:2008 39969@127.0.0.1:2003 40124@127.0.0.6:2008 40183@127.0.0.2:2004 40297@127.0.0.6:2008 40382@127.0.0.1:2003 40494@127.0.0.4:2006 40528@127.0.0.4:2006 40590@127.0.0.3:2005 40762@127.0.0.4:2006 40893@127.0.0.7:2009 40960@127.0.0.3:2005 40964@127.0.0.1:2003 41389@127.0.0.1:2003 41406@127.0.0.5:2007 41508@127.0.0.4:2006 41558@127.0.0.7:2009 41560@127.0.0.3:2005 41572@127.0.0.6:2008 41689@127.0.0.5:2007 41806@127.0.0.1:2003 41887@127.0.0.7:2009 42005@127.0.0.5:2007 42075@127.0.0.3:2005 42123@127.0.0.4:2006 42263@127.0.0.4:2006 42264@127.0.0.7:2009 42308@127.0.0.1:2003 42363@127.0.0.6:2008 42557@127.0.0.1:2003 42633@127.0.0.1:2003 42701@127.0.0.7:2009 42882@127.0.0.6:2008 42886@127.0.0.4:2006 42951@127.0.0.6:2008 42989@127.0.0.3:2005 43103@127.0.0.7:2009 43216@127.0.0.7:2009 43269@127.0.0.2:2004 43329@127.0.0.5:2007 43357@127.0.0.6:2008 43425@127.0.0.4:2006 43505@127.0.0.5:2007 43526@127.0.0.4:2006 43554@127.0.0.3:2005 43742@127.0.0.5:2007 44082@127.0.0.6:2008 44165@127.0.0.1:2003 44198@127.0.0.4:2006 44206@127.0.0.4:2006 44220@127.0.0.4:2006 44229@127.0.0.4:2006 44315@127.0.0.4:2006 44316@127.0.0.7:2009 44423@127.0.0.3:2005 44439@127.0.0.4:2006 44506@127.0.0.1:2003 44532@127.0.0.1:2003 44534@127.0.0.1:2003 44800@127.0.0.7:2009 44835@127.0.0.2:2004 44929@127.0.0.6:2008 45051@127.0.0.1:2003 45093@127.0.0.1:2003 45122@127.0.0.4:2006 45286@127.0.0.7:2009 45577@127.0.0.7:2009 45633@127.0.0.2:2004 45733@127.0.0.1:2003 45770@127.0.0.3:2005 45777@127.0.0.2:2004 45998@127.0.0.3:2005 46016@127.0.0.3:2005 46017@127.0.0.6:2008 46030@127.0.0.6:2008 46038@127.0.0.3:2005 46043@127.0.0.2:2004 46122@127.0.0.2:2004 46252@127.0.0.3:2005 46324@127.0.0.1:2003 46403@127.0.0.3:2005 46514@127.0.0.2:2004 46571@127.0.0.7:2009 46746@127.0.0.2:2004 46764@127.0.0.4:2006 46778@127.0.0.4:2006 46851@127.0.0.2:2004 46971@127.0.0.5:2007 47104@127.0.0.2:2004 47106@127.0.0.7:2009 47127@127.0.0.4:2006 47198@127.0.0.1:2003 47292@127.0.0.3:2005 47365@127.0.0.6:2008 47684@127.0.0.1:2003 47710@127.0.0.7:2009 47812@127.0.0.2:2004 47936@127.0.0.4:2006 48116@127.0.0.4:2006 48126@127.0.0.2:2004 48219@127.0.0.1:2003 48248@127.0.0.5:2007 48578@127.0.0.3:2005 48623@127.0.0.2:2004 48668@127.0.0.2:2004 48814@127.0.0.5:2007 48967@127.0.0.7:2009 48974@127.0.0.4:2006 49035@127.0.0.4:2006 49046@127.0.0.7:2009 49111@127.0.0.6:2008 49187@127.0.0.6:2008 49341@127.0.0.7:2009 49523@127.0.0.6:2008 49666@127.0.0.1:2003 49705@127.0.0.5:2007 49817@127.0.0.5:2007 49842@127.0.0.3:2005 49947@127.0.0.5:2007 49953@127.0.0.1:2003 50006@127.0.0.1:2003 50149@127.0.0.4:2006 50174@127.0.0.3:2005 50415@127.0.0.2:2004 50484@127.0.0.3:2005 50516@127.0.0.1:2003 50690@127.0.0.7:2009 50974@127.0.0.4:2006 51020@127.0.0.2:2004 51110@127.0.0.6:2008 51605@127.0.0.1:2003 51667@127.0.0.1:2003 51724@127.0.0.5:2007 51802@127.0.0.2:2004 51988@127.0.0.2:2004 52243@127.0.0.4:2006 52384@127.0.0.4:2006 52396@127.0.0.5:2007 52470@127.0.0.3:2005 52570@127.0.0.3:2005 52629@127.0.0.5:2007 52758@127.0.0.7:2009 52941@127.0.0.1:2003 52981@127.0.0.2:2004 53070@127.0.0.2:2004 53162@127.0.0.2:2004 53234@127.0.0.2:2004 53267@127.0.0.7:2009 53291@127.0.0.7:2009 53360@127.0.0.5:2007 53497@127.0.0.1:2003 53696@127.0.0.5:2007 53851@127.0.0.2:2004 53920@127.0.0.1:2003 54023@127.0.0.4:2006 54181@127.0.0.6:2008 54192@127.0.0.3:2005 54380@127.0.0.6:2008 54454@127.0.0.1:2003 54486@127.0.0.1:2003 54737@127.0.0.1:2003 54786@127.0.0.3:2005 54811@127.0.0.7:2009 55236@127.0.0.3:2005 55246@127.0.0.2:2004 55398@127.0.0.3:2005 55404@127.0.0.2:2004 55475@127.0.0.5:2007 55488@127.0.0.7:2009 55663@127.0.0.5:2007 55663@127.0.0.5:2007 55699@127.0.0.4:2006 55704@127.0.0.3:2005 55886@127.0.0.6:2008 56311@127.0.0.7:2009 56430@127.0.0.6:2008 56435@127.0.0.5:2007 56468@127.0.0.7:2009 56503@127.0.0.2:2004 56569@127.0.0.2:2004 56629@127.0.0.7:2009 56679@127.0.0.4:2006 56753@127.0.0.5:2007 56773@127.0.0.3:2005 56805@127.0.0.4:2006 56811@127.0.0.5:2007 56982@127.0.0.4:2006 57052@127.0.0.6:2008 57103@127.0.0.1:2003 57147@127.0.0.6:2008 57243@127.0.0.3:2005 57351@127.0.0.1:2003 57598@127.0.0.6:2008 57631@127.0.0.1:2003 57888@127.0.0.3:2005 57940@127.0.0.1:2003 58215@127.0.0.7:2009 58280@127.0.0.2:2004 58441@127.0.0.2:2004 58525@127.0.0.1:2003 58609@127.0.0.5:2007 58622@127.0.0.7:2009 58643@127.0.0.3:2005 58685@127.0.0.6:2008 58860@127.0.0.4:2006 58906@127.0.0.4:2006 58942@127.0.0.3:2005 58995@127.0.0.2:2004 58999@127.0.0.5:2007 59060@127.0.0.2:2004 59068@127.0.0.4:2006 59370@127.0.0.5:2007 59415@127.0.0.5:2007 59430@127.0.0.7:2009 59482@127.0.0.7:2009 59502@127.0.0.1:2003 59568@127.0.0.5:2007 59615@127.0.0.6:2008 59616@127.0.0.5:2007 59822@127.0.0.2:2004 59878@127.0.0.4:2006 60015@127.0.0.6:2008 60113@127.0.0.5:2007 60127@127.0.0.4:2006 60171@127.0.0.7:2009 60177@127.0.0.2:2004 60198@127.0.0.5:2007 60211@127.0.0.4:2006 60246@127.0.0.7:2009 60303@127.0.0.1:2003 60369@127.0.0.3:2005 60449@127.0.0.3:2005 60544@127.0.0.1:2003 60746@127.0.0.3:2005 60777@127.0.0.6:2008 60970@127.0.0.4:2006 61007@127.0.0.4:2006 61084@127.0.0.3:2005 61137@127.0.0.3:2005 61266@127.0.0.7:2009 61339@127.0.0.1:2003 61365@127.0.0.2:2004 61552@127.0.0.1:2003 61806@127.0.0.1:2003 61875@127.0.0.1:2003 61900@127.0.0.1:2003 61912@127.0.0.2:2004 61933@127.0.0.2:2004 61984@127.0.0.5:2007 62040@127.0.0.1:2003 62137@127.0.0.4:2006 62227@127.0.0.5:2007 62349@127.0.0.3:2005 62364@127.0.0.4:2006 62439@127.0.0.2:2004 62593@127.0.0.1:2003 62633@127.0.0.1:2003 62685@127.0.0.1:2003 62689@127.0.0.3:2005 62691@127.0.0.4:2006 62734@127.0.0.1:2003 62750@127.0.0.1:2003 62804@127.0.0.6:2008 62822@127.0.0.1:2003 62926@127.0.0.5:2007 62948@127.0.0.6:2008 62977@127.0.0.7:2009 63093@127.0.0.2:2004 63146@127.0.0.5:2007 63209@127.0.0.7:2009 63400@127.0.0.1:2003 63483@127.0.0.4:2006 63546@127.0.0.2:2004 63605@127.0.0.6:2008 63688@127.0.0.1:2003 63690@127.0.0.4:2006 63735@127.0.0.5:2007 63986@127.0.0.4:2006 64031@127.0.0.6:2008 64314@127.0.0.5:2007 64314@127.0.0.5:2007 64324@127.0.0.6:2008 64519@127.0.0.3:2005 64659@127.0.0.6:2008 64723@127.0.0.4:2006 64819@127.0.0.4:2006 64938@127.0.0.3:2005 64944@127.0.0.6:2008 65046@127.0.0.6:2008 65129@127.0.0.6:2008 65153@127.0.0.6:2008 65159@127.0.0.1:2003 65401@127.0.0.4:2006 65519@127.0.0.5:2007 cluster fnv fnv1a_ch replication 2 127.0.0.1:2003 127.0.0.2:2004 127.0.0.3:2005 127.0.0.4:2006 127.0.0.5:2007 127.0.0.6:2008 127.0.0.7:2009 ; # hash ring for fnv follows 144@127.0.0.6:2008 271@127.0.0.4:2006 413@127.0.0.2:2004 453@127.0.0.7:2009 596@127.0.0.4:2006 745@127.0.0.5:2007 753@127.0.0.2:2004 896@127.0.0.4:2006 990@127.0.0.2:2004 1019@127.0.0.5:2007 1052@127.0.0.5:2007 1129@127.0.0.2:2004 1166@127.0.0.5:2007 1216@127.0.0.5:2007 1288@127.0.0.7:2009 1362@127.0.0.5:2007 1467@127.0.0.4:2006 1555@127.0.0.7:2009 1841@127.0.0.4:2006 2083@127.0.0.7:2009 2093@127.0.0.4:2006 2195@127.0.0.4:2006 2302@127.0.0.7:2009 2484@127.0.0.1:2003 2533@127.0.0.2:2004 2566@127.0.0.6:2008 2596@127.0.0.4:2006 2608@127.0.0.6:2008 2826@127.0.0.4:2006 2893@127.0.0.2:2004 2909@127.0.0.7:2009 3522@127.0.0.5:2007 3541@127.0.0.1:2003 3639@127.0.0.5:2007 3805@127.0.0.5:2007 3870@127.0.0.1:2003 3979@127.0.0.6:2008 3984@127.0.0.3:2005 4034@127.0.0.4:2006 4066@127.0.0.7:2009 4167@127.0.0.1:2003 4572@127.0.0.6:2008 4597@127.0.0.1:2003 4759@127.0.0.1:2003 4919@127.0.0.2:2004 4958@127.0.0.5:2007 5130@127.0.0.2:2004 5220@127.0.0.7:2009 5282@127.0.0.5:2007 5292@127.0.0.3:2005 5312@127.0.0.6:2008 5412@127.0.0.4:2006 5417@127.0.0.2:2004 5493@127.0.0.1:2003 5501@127.0.0.4:2006 5675@127.0.0.2:2004 5949@127.0.0.1:2003 5976@127.0.0.1:2003 6111@127.0.0.1:2003 6118@127.0.0.2:2004 6184@127.0.0.7:2009 6303@127.0.0.5:2007 6311@127.0.0.7:2009 6368@127.0.0.5:2007 6379@127.0.0.3:2005 6404@127.0.0.3:2005 6602@127.0.0.5:2007 6884@127.0.0.4:2006 6910@127.0.0.6:2008 6928@127.0.0.1:2003 6976@127.0.0.5:2007 7068@127.0.0.1:2003 7177@127.0.0.6:2008 7272@127.0.0.4:2006 7292@127.0.0.2:2004 7341@127.0.0.3:2005 7451@127.0.0.6:2008 7624@127.0.0.6:2008 7729@127.0.0.6:2008 7753@127.0.0.3:2005 7965@127.0.0.6:2008 8081@127.0.0.3:2005 8081@127.0.0.3:2005 8086@127.0.0.3:2005 8166@127.0.0.5:2007 8169@127.0.0.5:2007 8217@127.0.0.3:2005 8421@127.0.0.4:2006 8577@127.0.0.7:2009 8851@127.0.0.4:2006 8903@127.0.0.4:2006 9032@127.0.0.4:2006 9227@127.0.0.3:2005 9520@127.0.0.5:2007 9548@127.0.0.6:2008 9617@127.0.0.7:2009 9649@127.0.0.6:2008 9769@127.0.0.5:2007 9894@127.0.0.4:2006 9980@127.0.0.2:2004 9984@127.0.0.7:2009 10027@127.0.0.4:2006 10035@127.0.0.5:2007 10044@127.0.0.6:2008 10165@127.0.0.6:2008 10209@127.0.0.5:2007 10261@127.0.0.6:2008 10380@127.0.0.5:2007 10445@127.0.0.4:2006 10452@127.0.0.7:2009 10643@127.0.0.6:2008 10765@127.0.0.1:2003 10796@127.0.0.7:2009 11075@127.0.0.7:2009 11212@127.0.0.4:2006 11216@127.0.0.4:2006 11329@127.0.0.4:2006 11367@127.0.0.7:2009 11743@127.0.0.4:2006 11883@127.0.0.6:2008 11962@127.0.0.4:2006 12013@127.0.0.6:2008 12055@127.0.0.7:2009 12118@127.0.0.4:2006 12194@127.0.0.1:2003 12200@127.0.0.5:2007 12373@127.0.0.4:2006 12465@127.0.0.1:2003 12475@127.0.0.2:2004 12492@127.0.0.1:2003 12496@127.0.0.2:2004 12545@127.0.0.7:2009 12816@127.0.0.5:2007 13035@127.0.0.6:2008 13062@127.0.0.7:2009 13263@127.0.0.1:2003 13406@127.0.0.7:2009 13520@127.0.0.4:2006 13894@127.0.0.3:2005 13966@127.0.0.6:2008 14027@127.0.0.7:2009 14216@127.0.0.4:2006 14222@127.0.0.6:2008 14296@127.0.0.1:2003 14610@127.0.0.6:2008 14664@127.0.0.4:2006 15129@127.0.0.1:2003 15256@127.0.0.4:2006 15306@127.0.0.1:2003 15377@127.0.0.1:2003 15429@127.0.0.3:2005 15841@127.0.0.4:2006 15885@127.0.0.1:2003 16081@127.0.0.3:2005 16117@127.0.0.5:2007 16150@127.0.0.7:2009 16298@127.0.0.1:2003 16371@127.0.0.4:2006 16419@127.0.0.3:2005 16481@127.0.0.1:2003 16494@127.0.0.5:2007 16548@127.0.0.3:2005 16669@127.0.0.4:2006 16760@127.0.0.5:2007 16760@127.0.0.5:2007 16815@127.0.0.2:2004 16919@127.0.0.6:2008 17383@127.0.0.5:2007 17390@127.0.0.6:2008 17425@127.0.0.3:2005 17451@127.0.0.6:2008 17527@127.0.0.3:2005 17749@127.0.0.5:2007 17771@127.0.0.7:2009 17779@127.0.0.6:2008 17784@127.0.0.4:2006 17897@127.0.0.6:2008 17902@127.0.0.5:2007 17932@127.0.0.7:2009 17962@127.0.0.7:2009 18228@127.0.0.7:2009 18262@127.0.0.1:2003 18442@127.0.0.5:2007 18540@127.0.0.6:2008 18566@127.0.0.6:2008 18621@127.0.0.1:2003 18814@127.0.0.7:2009 18855@127.0.0.6:2008 18956@127.0.0.2:2004 18961@127.0.0.6:2008 18989@127.0.0.7:2009 19000@127.0.0.4:2006 19039@127.0.0.4:2006 19069@127.0.0.6:2008 19209@127.0.0.5:2007 19241@127.0.0.4:2006 19256@127.0.0.4:2006 19316@127.0.0.4:2006 19324@127.0.0.7:2009 19430@127.0.0.2:2004 19456@127.0.0.6:2008 19514@127.0.0.1:2003 19541@127.0.0.3:2005 19587@127.0.0.3:2005 19647@127.0.0.3:2005 19663@127.0.0.2:2004 19899@127.0.0.3:2005 20117@127.0.0.6:2008 20129@127.0.0.5:2007 20309@127.0.0.6:2008 20467@127.0.0.2:2004 20831@127.0.0.7:2009 20853@127.0.0.7:2009 20914@127.0.0.5:2007 21015@127.0.0.1:2003 21054@127.0.0.1:2003 21080@127.0.0.7:2009 21136@127.0.0.4:2006 21177@127.0.0.3:2005 21342@127.0.0.3:2005 21520@127.0.0.7:2009 21522@127.0.0.6:2008 21554@127.0.0.2:2004 21594@127.0.0.3:2005 21868@127.0.0.5:2007 22058@127.0.0.1:2003 22207@127.0.0.5:2007 22235@127.0.0.3:2005 22239@127.0.0.2:2004 22358@127.0.0.2:2004 22488@127.0.0.1:2003 22623@127.0.0.5:2007 22675@127.0.0.7:2009 22705@127.0.0.1:2003 22798@127.0.0.1:2003 23227@127.0.0.4:2006 23332@127.0.0.5:2007 23457@127.0.0.3:2005 23479@127.0.0.7:2009 23528@127.0.0.4:2006 23749@127.0.0.1:2003 23771@127.0.0.5:2007 23865@127.0.0.7:2009 24064@127.0.0.4:2006 24274@127.0.0.4:2006 24390@127.0.0.1:2003 24474@127.0.0.6:2008 24838@127.0.0.6:2008 24932@127.0.0.3:2005 24939@127.0.0.2:2004 24961@127.0.0.5:2007 25004@127.0.0.4:2006 25131@127.0.0.2:2004 25153@127.0.0.3:2005 25268@127.0.0.2:2004 25489@127.0.0.7:2009 25572@127.0.0.2:2004 25719@127.0.0.4:2006 25739@127.0.0.7:2009 25759@127.0.0.3:2005 25765@127.0.0.1:2003 25765@127.0.0.1:2003 25863@127.0.0.1:2003 26036@127.0.0.2:2004 26064@127.0.0.1:2003 26136@127.0.0.3:2005 26161@127.0.0.2:2004 26167@127.0.0.3:2005 26177@127.0.0.2:2004 26189@127.0.0.6:2008 26255@127.0.0.6:2008 26347@127.0.0.6:2008 26449@127.0.0.1:2003 26502@127.0.0.2:2004 26520@127.0.0.1:2003 26595@127.0.0.2:2004 26896@127.0.0.2:2004 26943@127.0.0.1:2003 26977@127.0.0.6:2008 27269@127.0.0.6:2008 27471@127.0.0.4:2006 27582@127.0.0.3:2005 27642@127.0.0.3:2005 27780@127.0.0.1:2003 27844@127.0.0.4:2006 27899@127.0.0.2:2004 28144@127.0.0.2:2004 28173@127.0.0.2:2004 28191@127.0.0.2:2004 28194@127.0.0.4:2006 28245@127.0.0.7:2009 28343@127.0.0.3:2005 28447@127.0.0.4:2006 28487@127.0.0.3:2005 28493@127.0.0.1:2003 28512@127.0.0.2:2004 28515@127.0.0.3:2005 28662@127.0.0.1:2003 28673@127.0.0.4:2006 28856@127.0.0.4:2006 28939@127.0.0.5:2007 28943@127.0.0.7:2009 29026@127.0.0.2:2004 29078@127.0.0.7:2009 29170@127.0.0.3:2005 29172@127.0.0.6:2008 29223@127.0.0.5:2007 29229@127.0.0.7:2009 29317@127.0.0.3:2005 29491@127.0.0.3:2005 29568@127.0.0.2:2004 29579@127.0.0.2:2004 29636@127.0.0.7:2009 29673@127.0.0.4:2006 29797@127.0.0.4:2006 29798@127.0.0.2:2004 29964@127.0.0.2:2004 30008@127.0.0.1:2003 30049@127.0.0.3:2005 30247@127.0.0.4:2006 30494@127.0.0.7:2009 30538@127.0.0.3:2005 30672@127.0.0.7:2009 30689@127.0.0.1:2003 30743@127.0.0.5:2007 30947@127.0.0.2:2004 31075@127.0.0.2:2004 31149@127.0.0.7:2009 31220@127.0.0.6:2008 31224@127.0.0.2:2004 31226@127.0.0.2:2004 31232@127.0.0.7:2009 31290@127.0.0.3:2005 31322@127.0.0.7:2009 31342@127.0.0.5:2007 31385@127.0.0.1:2003 31597@127.0.0.4:2006 31645@127.0.0.7:2009 31801@127.0.0.4:2006 32150@127.0.0.4:2006 32170@127.0.0.7:2009 32245@127.0.0.7:2009 32287@127.0.0.1:2003 32468@127.0.0.4:2006 32568@127.0.0.5:2007 32598@127.0.0.7:2009 32669@127.0.0.7:2009 32909@127.0.0.1:2003 33080@127.0.0.6:2008 33182@127.0.0.6:2008 33208@127.0.0.4:2006 33238@127.0.0.1:2003 33355@127.0.0.4:2006 33363@127.0.0.2:2004 33440@127.0.0.7:2009 33461@127.0.0.7:2009 33549@127.0.0.4:2006 33554@127.0.0.3:2005 33608@127.0.0.2:2004 33664@127.0.0.3:2005 33733@127.0.0.3:2005 33784@127.0.0.3:2005 33794@127.0.0.6:2008 33925@127.0.0.4:2006 34214@127.0.0.1:2003 34228@127.0.0.7:2009 34313@127.0.0.5:2007 34316@127.0.0.1:2003 34455@127.0.0.3:2005 34464@127.0.0.2:2004 34506@127.0.0.6:2008 34607@127.0.0.5:2007 34611@127.0.0.1:2003 35138@127.0.0.5:2007 35224@127.0.0.4:2006 35452@127.0.0.1:2003 35480@127.0.0.5:2007 35755@127.0.0.7:2009 35828@127.0.0.2:2004 36126@127.0.0.2:2004 36149@127.0.0.7:2009 36159@127.0.0.2:2004 36209@127.0.0.4:2006 36238@127.0.0.6:2008 36259@127.0.0.6:2008 36337@127.0.0.2:2004 36401@127.0.0.3:2005 36517@127.0.0.6:2008 36527@127.0.0.6:2008 36632@127.0.0.7:2009 36697@127.0.0.3:2005 36742@127.0.0.4:2006 36861@127.0.0.3:2005 36901@127.0.0.1:2003 36934@127.0.0.2:2004 36939@127.0.0.2:2004 36944@127.0.0.5:2007 37018@127.0.0.5:2007 37169@127.0.0.3:2005 37185@127.0.0.3:2005 37256@127.0.0.7:2009 37281@127.0.0.7:2009 37288@127.0.0.2:2004 37307@127.0.0.2:2004 37311@127.0.0.6:2008 37324@127.0.0.5:2007 37599@127.0.0.5:2007 37700@127.0.0.2:2004 37728@127.0.0.3:2005 37777@127.0.0.6:2008 37869@127.0.0.3:2005 37890@127.0.0.5:2007 38007@127.0.0.2:2004 38038@127.0.0.5:2007 38053@127.0.0.5:2007 38094@127.0.0.5:2007 38183@127.0.0.7:2009 38415@127.0.0.1:2003 38439@127.0.0.5:2007 38498@127.0.0.3:2005 38517@127.0.0.6:2008 38565@127.0.0.7:2009 38627@127.0.0.7:2009 38628@127.0.0.5:2007 38715@127.0.0.2:2004 38750@127.0.0.2:2004 38765@127.0.0.7:2009 38794@127.0.0.7:2009 38923@127.0.0.3:2005 39091@127.0.0.1:2003 39184@127.0.0.6:2008 39253@127.0.0.3:2005 39450@127.0.0.3:2005 39465@127.0.0.1:2003 39481@127.0.0.6:2008 39556@127.0.0.2:2004 39642@127.0.0.3:2005 39878@127.0.0.5:2007 39923@127.0.0.1:2003 39984@127.0.0.1:2003 40143@127.0.0.2:2004 40251@127.0.0.6:2008 40587@127.0.0.1:2003 40696@127.0.0.7:2009 40942@127.0.0.6:2008 40968@127.0.0.2:2004 41068@127.0.0.4:2006 41351@127.0.0.1:2003 41416@127.0.0.1:2003 41487@127.0.0.6:2008 41673@127.0.0.3:2005 41748@127.0.0.3:2005 41866@127.0.0.1:2003 42030@127.0.0.3:2005 42059@127.0.0.7:2009 42197@127.0.0.5:2007 42287@127.0.0.4:2006 42410@127.0.0.5:2007 42684@127.0.0.4:2006 42833@127.0.0.5:2007 43004@127.0.0.1:2003 43311@127.0.0.5:2007 43452@127.0.0.1:2003 43594@127.0.0.4:2006 43629@127.0.0.3:2005 43903@127.0.0.1:2003 43932@127.0.0.3:2005 43985@127.0.0.6:2008 43987@127.0.0.4:2006 44004@127.0.0.7:2009 44194@127.0.0.6:2008 44426@127.0.0.3:2005 44515@127.0.0.5:2007 44548@127.0.0.5:2007 44695@127.0.0.7:2009 44842@127.0.0.1:2003 44866@127.0.0.5:2007 44887@127.0.0.4:2006 44912@127.0.0.1:2003 45005@127.0.0.6:2008 45046@127.0.0.5:2007 45169@127.0.0.5:2007 45191@127.0.0.5:2007 45203@127.0.0.7:2009 45476@127.0.0.2:2004 45485@127.0.0.2:2004 45531@127.0.0.5:2007 45640@127.0.0.7:2009 45684@127.0.0.4:2006 45704@127.0.0.6:2008 45847@127.0.0.3:2005 45866@127.0.0.6:2008 45928@127.0.0.7:2009 46136@127.0.0.3:2005 46306@127.0.0.5:2007 46376@127.0.0.2:2004 46489@127.0.0.4:2006 46624@127.0.0.2:2004 46657@127.0.0.7:2009 46737@127.0.0.3:2005 46889@127.0.0.1:2003 47183@127.0.0.4:2006 47201@127.0.0.7:2009 47240@127.0.0.7:2009 47294@127.0.0.6:2008 47523@127.0.0.3:2005 47576@127.0.0.3:2005 47663@127.0.0.1:2003 47697@127.0.0.6:2008 47711@127.0.0.6:2008 47830@127.0.0.1:2003 47980@127.0.0.3:2005 48054@127.0.0.5:2007 48201@127.0.0.6:2008 48205@127.0.0.6:2008 48387@127.0.0.1:2003 48423@127.0.0.7:2009 48581@127.0.0.4:2006 48934@127.0.0.5:2007 48957@127.0.0.3:2005 49024@127.0.0.4:2006 49435@127.0.0.4:2006 49439@127.0.0.5:2007 49612@127.0.0.2:2004 49663@127.0.0.2:2004 49802@127.0.0.3:2005 49981@127.0.0.3:2005 50092@127.0.0.3:2005 50218@127.0.0.6:2008 50242@127.0.0.2:2004 50267@127.0.0.3:2005 50413@127.0.0.5:2007 50449@127.0.0.5:2007 50500@127.0.0.5:2007 50834@127.0.0.5:2007 51211@127.0.0.5:2007 51218@127.0.0.3:2005 51335@127.0.0.7:2009 51501@127.0.0.7:2009 51524@127.0.0.3:2005 51569@127.0.0.1:2003 51596@127.0.0.7:2009 51732@127.0.0.1:2003 51876@127.0.0.7:2009 52118@127.0.0.1:2003 52287@127.0.0.5:2007 52492@127.0.0.2:2004 52652@127.0.0.5:2007 52723@127.0.0.3:2005 52780@127.0.0.6:2008 52839@127.0.0.5:2007 52848@127.0.0.7:2009 52879@127.0.0.1:2003 53011@127.0.0.4:2006 53016@127.0.0.5:2007 53089@127.0.0.4:2006 53115@127.0.0.6:2008 53176@127.0.0.2:2004 53335@127.0.0.6:2008 53420@127.0.0.5:2007 53463@127.0.0.6:2008 53504@127.0.0.5:2007 53562@127.0.0.5:2007 53581@127.0.0.6:2008 53732@127.0.0.6:2008 53752@127.0.0.1:2003 53763@127.0.0.6:2008 53940@127.0.0.5:2007 54007@127.0.0.2:2004 54056@127.0.0.6:2008 54108@127.0.0.1:2003 54338@127.0.0.4:2006 54343@127.0.0.2:2004 54383@127.0.0.2:2004 54414@127.0.0.4:2006 54450@127.0.0.3:2005 54463@127.0.0.4:2006 54541@127.0.0.4:2006 54692@127.0.0.6:2008 55021@127.0.0.2:2004 55245@127.0.0.7:2009 55271@127.0.0.7:2009 55586@127.0.0.7:2009 55829@127.0.0.5:2007 55952@127.0.0.2:2004 55986@127.0.0.4:2006 56038@127.0.0.1:2003 56521@127.0.0.2:2004 56662@127.0.0.3:2005 56727@127.0.0.1:2003 56826@127.0.0.7:2009 57000@127.0.0.6:2008 57131@127.0.0.7:2009 57157@127.0.0.3:2005 57220@127.0.0.6:2008 57327@127.0.0.3:2005 57339@127.0.0.4:2006 57383@127.0.0.5:2007 57391@127.0.0.2:2004 57425@127.0.0.6:2008 57694@127.0.0.3:2005 57820@127.0.0.2:2004 57957@127.0.0.2:2004 58001@127.0.0.6:2008 58066@127.0.0.1:2003 58138@127.0.0.1:2003 58223@127.0.0.2:2004 58282@127.0.0.7:2009 58313@127.0.0.7:2009 58463@127.0.0.2:2004 58524@127.0.0.7:2009 58687@127.0.0.2:2004 58724@127.0.0.1:2003 58775@127.0.0.7:2009 58832@127.0.0.1:2003 58989@127.0.0.6:2008 59016@127.0.0.1:2003 59259@127.0.0.1:2003 59304@127.0.0.4:2006 59312@127.0.0.3:2005 59390@127.0.0.2:2004 59572@127.0.0.4:2006 59573@127.0.0.2:2004 59577@127.0.0.7:2009 59631@127.0.0.4:2006 59669@127.0.0.4:2006 59738@127.0.0.1:2003 59758@127.0.0.6:2008 59915@127.0.0.3:2005 59925@127.0.0.3:2005 60042@127.0.0.1:2003 60096@127.0.0.2:2004 60199@127.0.0.5:2007 60228@127.0.0.3:2005 60313@127.0.0.2:2004 60326@127.0.0.7:2009 60344@127.0.0.1:2003 60390@127.0.0.5:2007 60428@127.0.0.5:2007 60430@127.0.0.1:2003 60480@127.0.0.4:2006 60603@127.0.0.4:2006 60793@127.0.0.3:2005 61083@127.0.0.6:2008 61098@127.0.0.7:2009 61321@127.0.0.1:2003 61479@127.0.0.6:2008 61538@127.0.0.6:2008 61586@127.0.0.2:2004 61648@127.0.0.2:2004 61822@127.0.0.5:2007 61871@127.0.0.6:2008 61890@127.0.0.2:2004 61910@127.0.0.4:2006 61972@127.0.0.3:2005 61992@127.0.0.1:2003 61992@127.0.0.1:2003 62085@127.0.0.2:2004 62089@127.0.0.3:2005 62355@127.0.0.3:2005 62448@127.0.0.1:2003 62461@127.0.0.1:2003 62609@127.0.0.1:2003 62713@127.0.0.7:2009 62809@127.0.0.3:2005 62822@127.0.0.5:2007 62944@127.0.0.5:2007 63229@127.0.0.2:2004 63248@127.0.0.3:2005 63310@127.0.0.2:2004 63436@127.0.0.4:2006 63447@127.0.0.4:2006 63523@127.0.0.6:2008 63677@127.0.0.4:2006 63721@127.0.0.3:2005 63775@127.0.0.4:2006 63784@127.0.0.5:2007 63870@127.0.0.7:2009 63874@127.0.0.3:2005 63921@127.0.0.3:2005 64047@127.0.0.2:2004 64143@127.0.0.3:2005 64157@127.0.0.6:2008 64250@127.0.0.1:2003 64251@127.0.0.2:2004 64292@127.0.0.7:2009 64473@127.0.0.2:2004 64588@127.0.0.6:2008 64604@127.0.0.3:2005 64630@127.0.0.6:2008 64809@127.0.0.5:2007 64918@127.0.0.3:2005 64927@127.0.0.1:2003 65117@127.0.0.1:2003 65121@127.0.0.2:2004 65156@127.0.0.4:2006 65199@127.0.0.7:2009 65279@127.0.0.5:2007 65286@127.0.0.1:2003 65293@127.0.0.6:2008 cluster jump jump_fnv1a_ch replication 2 127.0.0.1:2003 127.0.0.2:2004 127.0.0.3:2005 127.0.0.4:2006 127.0.0.5:2007 127.0.0.6:2008 127.0.0.7:2009 ; # hash ring for jump follows 0@127.0.0.1:2003 1@127.0.0.2:2004 2@127.0.0.3:2005 3@127.0.0.4:2006 4@127.0.0.5:2007 5@127.0.0.6:2008 6@127.0.0.7:2009 cluster jump2 jump_fnv1a_ch replication 2 127.0.0.11:2003 127.0.0.12:2004=1 127.0.0.13:2005 127.0.0.14:2006=2 127.0.0.15:2007 127.0.0.16:2008=foo 127.0.0.17:2009 ; # hash ring for jump2 follows 1@127.0.0.12:2004=1 3@127.0.0.14:2006=2 5@127.0.0.16:2008=foo 0@127.0.0.11:2003 2@127.0.0.13:2005 4@127.0.0.15:2007 6@127.0.0.17:2009 match * send to carbon fnv jump ; match * -> cd85d26b19018dec78e33d44e1477993130267ec79f92abd25ece33fa029bf56 carbon_ch(carbon) hash_pos(31587) 127.0.0.5:2007 127.0.0.6:2008 fnv1a_ch(fnv) hash_pos(27369) 127.0.0.4:2006 127.0.0.3:2005 jump_fnv1a_ch(jump) hash_pos(3) 127.0.0.4:2006 127.0.0.5:2007 match * -> f802b190bb63b02c2b933fd017b3764f9bceafb351ffaa92f06fed6fa0f9017c carbon_ch(carbon) hash_pos(43312) 127.0.0.5:2007 127.0.0.6:2008 fnv1a_ch(fnv) hash_pos(29168) 127.0.0.3:2005 127.0.0.6:2008 jump_fnv1a_ch(jump) hash_pos(2) 127.0.0.3:2005 127.0.0.2:2004 match * -> df7c8a8cd0ab1e68b72555ee8cd297e8853bed3190554b32a09faa0d722b59bb carbon_ch(carbon) hash_pos(42160) 127.0.0.4:2006 127.0.0.7:2009 fnv1a_ch(fnv) hash_pos(46461) 127.0.0.4:2006 127.0.0.2:2004 jump_fnv1a_ch(jump) hash_pos(2) 127.0.0.3:2005 127.0.0.1:2003 match * -> 45f2add911716502327e88d43d0bc6316507f95212bb16a604b6dc04a851cee8 carbon_ch(carbon) hash_pos(10005) 127.0.0.2:2004 127.0.0.3:2005 fnv1a_ch(fnv) hash_pos(5668) 127.0.0.2:2004 127.0.0.1:2003 jump_fnv1a_ch(jump) hash_pos(4) 127.0.0.5:2007 127.0.0.2:2004 match * -> 2a96380d6b4df489d14a5b01426d9c21d9f4f16551bae7bccabc24ee0af4dd8d carbon_ch(carbon) hash_pos(6690) 127.0.0.5:2007 127.0.0.3:2005 fnv1a_ch(fnv) hash_pos(63134) 127.0.0.2:2004 127.0.0.3:2005 jump_fnv1a_ch(jump) hash_pos(6) 127.0.0.7:2009 127.0.0.4:2006 match * -> 07058ac7da6ed9fb9aeb00da1ec32336a295349343f19ce9452552e311829ec2 carbon_ch(carbon) hash_pos(19325) 127.0.0.3:2005 127.0.0.4:2006 fnv1a_ch(fnv) hash_pos(64475) 127.0.0.6:2008 127.0.0.3:2005 jump_fnv1a_ch(jump) hash_pos(6) 127.0.0.7:2009 127.0.0.6:2008 match * -> 6225da61cb0f8872e74e16db799acddf09c1b13c9bfa263d45418081440999e1 carbon_ch(carbon) hash_pos(1696) 127.0.0.5:2007 127.0.0.3:2005 fnv1a_ch(fnv) hash_pos(6992) 127.0.0.1:2003 127.0.0.6:2008 jump_fnv1a_ch(jump) hash_pos(4) 127.0.0.5:2007 127.0.0.6:2008 match * -> 2136e0d19c8a1b557df0daa81646a1c7c96d5f3522f5484e2e641859d093c2dd carbon_ch(carbon) hash_pos(34559) 127.0.0.2:2004 127.0.0.4:2006 fnv1a_ch(fnv) hash_pos(41271) 127.0.0.1:2003 127.0.0.6:2008 jump_fnv1a_ch(jump) hash_pos(4) 127.0.0.5:2007 127.0.0.1:2003 match * -> 8f811b2ce741185954408bd6ef95b7317d8f68b2d66ae5b095e6960308cc7ed3 carbon_ch(carbon) hash_pos(26992) 127.0.0.4:2006 127.0.0.7:2009 fnv1a_ch(fnv) hash_pos(3652) 127.0.0.5:2007 127.0.0.1:2003 jump_fnv1a_ch(jump) hash_pos(6) 127.0.0.7:2009 127.0.0.6:2008 match * -> d681fa62dd8cd4ff60c44ae2647914fc41c13b0fc269f7560071a7a3ad410907 carbon_ch(carbon) hash_pos(58783) 127.0.0.4:2006 127.0.0.3:2005 fnv1a_ch(fnv) hash_pos(23193) 127.0.0.4:2006 127.0.0.5:2007 jump_fnv1a_ch(jump) hash_pos(6) 127.0.0.7:2009 127.0.0.5:2007 match * -> 23363a396895571de9b529708fe6a0f6a74302963011aff0331dedd97e73afb0 carbon_ch(carbon) hash_pos(21392) 127.0.0.7:2009 127.0.0.6:2008 fnv1a_ch(fnv) hash_pos(20148) 127.0.0.6:2008 127.0.0.2:2004 jump_fnv1a_ch(jump) hash_pos(3) 127.0.0.4:2006 127.0.0.7:2009 match * -> 85dd0943b0e24c67e0e6307f5e3ade9d244077576c7d401702d4cfbdecd62ee6 carbon_ch(carbon) hash_pos(39809) 127.0.0.1:2003 127.0.0.6:2008 fnv1a_ch(fnv) hash_pos(3540) 127.0.0.1:2003 127.0.0.5:2007 jump_fnv1a_ch(jump) hash_pos(1) 127.0.0.2:2004 127.0.0.7:2009 match * -> 8b03cb452953a78dc9a647dca3b8b28f390f6ca3205597105a77c3453b59cb53 carbon_ch(carbon) hash_pos(24199) 127.0.0.1:2003 127.0.0.6:2008 fnv1a_ch(fnv) hash_pos(16745) 127.0.0.5:2007 127.0.0.2:2004 jump_fnv1a_ch(jump) hash_pos(2) 127.0.0.3:2005 127.0.0.7:2009 match * -> 16ec4868740a3961379ce0df077ace28e81e0200767ed2ead50fdb654a10c4e3 carbon_ch(carbon) hash_pos(43051) 127.0.0.7:2009 127.0.0.2:2004 fnv1a_ch(fnv) hash_pos(15832) 127.0.0.4:2006 127.0.0.1:2003 jump_fnv1a_ch(jump) hash_pos(3) 127.0.0.4:2006 127.0.0.6:2008 match * -> 0bb3a449bf2fc9eb3fc906261ecaa62970d4a03d5f70575fa4b60aac97529cd8 carbon_ch(carbon) hash_pos(46257) 127.0.0.1:2003 127.0.0.3:2005 fnv1a_ch(fnv) hash_pos(7981) 127.0.0.3:2005 127.0.0.5:2007 jump_fnv1a_ch(jump) hash_pos(3) 127.0.0.4:2006 127.0.0.1:2003 match * -> 79d16b180742149eca6e504085e22d4f2b3bc354e6ad16beb09ab69bce41146e carbon_ch(carbon) hash_pos(51724) 127.0.0.5:2007 127.0.0.2:2004 fnv1a_ch(fnv) hash_pos(59468) 127.0.0.4:2006 127.0.0.2:2004 jump_fnv1a_ch(jump) hash_pos(6) 127.0.0.7:2009 127.0.0.1:2003 match * -> e0d8eaf81773c01d856d986a0c87e6e34582290f7da7eb0b910b1fb8a809ebf0 carbon_ch(carbon) hash_pos(38156) 127.0.0.5:2007 127.0.0.3:2005 fnv1a_ch(fnv) hash_pos(42198) 127.0.0.4:2006 127.0.0.5:2007 jump_fnv1a_ch(jump) hash_pos(3) 127.0.0.4:2006 127.0.0.7:2009 match * -> 40fa7bde092cfdde97be93469dfc7d28073ff4221a1c8008a137107a0f63abbc carbon_ch(carbon) hash_pos(37429) 127.0.0.7:2009 127.0.0.1:2003 fnv1a_ch(fnv) hash_pos(52947) 127.0.0.4:2006 127.0.0.5:2007 jump_fnv1a_ch(jump) hash_pos(6) 127.0.0.7:2009 127.0.0.6:2008 match * -> 48a10f8ef3512208b85a50546f0dd4cb6dda8531ac2ce5cf3a093e3189764167 carbon_ch(carbon) hash_pos(44963) 127.0.0.1:2003 127.0.0.4:2006 fnv1a_ch(fnv) hash_pos(26264) 127.0.0.6:2008 127.0.0.1:2003 jump_fnv1a_ch(jump) hash_pos(6) 127.0.0.7:2009 127.0.0.6:2008 match * -> 67546909eeb4e6ea1059fde6d075b19f5d2b18afddb6027594b6544bc7e34313 carbon_ch(carbon) hash_pos(42623) 127.0.0.1:2003 127.0.0.7:2009 fnv1a_ch(fnv) hash_pos(51939) 127.0.0.1:2003 127.0.0.5:2007 jump_fnv1a_ch(jump) hash_pos(1) 127.0.0.2:2004 127.0.0.4:2006 match * -> foo4lohf4AepooJoh3CaiNuyaich5to4raawei6elohfohf8Fiet0Uosheem carbon_ch(carbon) hash_pos(41422) 127.0.0.4:2006 127.0.0.7:2009 fnv1a_ch(fnv) hash_pos(52199) 127.0.0.5:2007 127.0.0.2:2004 jump_fnv1a_ch(jump) hash_pos(0) 127.0.0.1:2003 127.0.0.6:2008 match * -> Obainoh5vuleiDai2iu3wae8iem5faisoh1Aeg4jaijais4aex3puhieM6gi carbon_ch(carbon) hash_pos(956) 127.0.0.3:2005 127.0.0.1:2003 fnv1a_ch(fnv) hash_pos(12076) 127.0.0.4:2006 127.0.0.1:2003 jump_fnv1a_ch(jump) hash_pos(2) 127.0.0.3:2005 127.0.0.7:2009 match * -> jai2sus3xiex4eunomi4Ne9eRoveecah8suebeiha0Eer1raijaa4Fai1boh carbon_ch(carbon) hash_pos(6964) 127.0.0.3:2005 127.0.0.7:2009 fnv1a_ch(fnv) hash_pos(25943) 127.0.0.2:2004 127.0.0.1:2003 jump_fnv1a_ch(jump) hash_pos(0) 127.0.0.1:2003 127.0.0.2:2004 match * -> taequei9uL4eicoo5eu0ua7daiyihishahch4chuac0eibetahFieghahYie carbon_ch(carbon) hash_pos(50008) 127.0.0.4:2006 127.0.0.3:2005 fnv1a_ch(fnv) hash_pos(28057) 127.0.0.2:2004 127.0.0.4:2006 jump_fnv1a_ch(jump) hash_pos(5) 127.0.0.6:2008 127.0.0.2:2004 match * -> uu7Ov0ahC5cheiT4lieQuahba1Di8ahjei3ec8aezaloh0eihahgh9johro9 carbon_ch(carbon) hash_pos(43406) 127.0.0.4:2006 127.0.0.5:2007 fnv1a_ch(fnv) hash_pos(42121) 127.0.0.5:2007 127.0.0.4:2006 jump_fnv1a_ch(jump) hash_pos(0) 127.0.0.1:2003 127.0.0.5:2007 match * -> pha4thoiSheedaewoo3RieSoC9iquaish2eica8ahsheodeiveihia6eemie carbon_ch(carbon) hash_pos(1015) 127.0.0.1:2003 127.0.0.3:2005 fnv1a_ch(fnv) hash_pos(45673) 127.0.0.4:2006 127.0.0.6:2008 jump_fnv1a_ch(jump) hash_pos(1) 127.0.0.2:2004 127.0.0.1:2003 match * -> dier5xighoch1kaishaa4waifenai1of8dieshuQu3tohshaiphepet8oaBe carbon_ch(carbon) hash_pos(6624) 127.0.0.7:2009 127.0.0.5:2007 fnv1a_ch(fnv) hash_pos(22001) 127.0.0.1:2003 127.0.0.5:2007 jump_fnv1a_ch(jump) hash_pos(6) 127.0.0.7:2009 127.0.0.6:2008 match * -> aiRohr4fi6eim1mee0phah8taiwoiTi0wieh5Shahpe5xaicoo4eesah8ein carbon_ch(carbon) hash_pos(56408) 127.0.0.6:2008 127.0.0.5:2007 fnv1a_ch(fnv) hash_pos(4823) 127.0.0.2:2004 127.0.0.5:2007 jump_fnv1a_ch(jump) hash_pos(2) 127.0.0.3:2005 127.0.0.6:2008 match * -> shei2aed4thaiL1chooch8baewoh2ikuphubie6nooreiGuvah8meithoode carbon_ch(carbon) hash_pos(52076) 127.0.0.4:2006 127.0.0.5:2007 fnv1a_ch(fnv) hash_pos(39788) 127.0.0.5:2007 127.0.0.1:2003 jump_fnv1a_ch(jump) hash_pos(3) 127.0.0.4:2006 127.0.0.7:2009 match * -> ood7ia6goh5aab8ukei1Oa8zeeg4bohheitheiT6WeeTh2az4ku4vaegh3Sh carbon_ch(carbon) hash_pos(4000) 127.0.0.7:2009 127.0.0.4:2006 fnv1a_ch(fnv) hash_pos(13998) 127.0.0.7:2009 127.0.0.4:2006 jump_fnv1a_ch(jump) hash_pos(1) 127.0.0.2:2004 127.0.0.6:2008 match * -> aeg6ajiePheeQuau9ash carbon_ch(carbon) hash_pos(59804) 127.0.0.2:2004 127.0.0.4:2006 fnv1a_ch(fnv) hash_pos(2057) 127.0.0.7:2009 127.0.0.4:2006 jump_fnv1a_ch(jump) hash_pos(3) 127.0.0.4:2006 127.0.0.3:2005 match * -> ureiphahJuichue3vohW carbon_ch(carbon) hash_pos(16814) 127.0.0.5:2007 127.0.0.1:2003 fnv1a_ch(fnv) hash_pos(27574) 127.0.0.3:2005 127.0.0.1:2003 jump_fnv1a_ch(jump) hash_pos(3) 127.0.0.4:2006 127.0.0.1:2003 match * -> uodahf9auXeef3iechee carbon_ch(carbon) hash_pos(9470) 127.0.0.7:2009 127.0.0.2:2004 fnv1a_ch(fnv) hash_pos(22075) 127.0.0.5:2007 127.0.0.3:2005 jump_fnv1a_ch(jump) hash_pos(4) 127.0.0.5:2007 127.0.0.2:2004 match * -> ooy2rah2Wahmohvuutee carbon_ch(carbon) hash_pos(59066) 127.0.0.4:2006 127.0.0.5:2007 fnv1a_ch(fnv) hash_pos(60856) 127.0.0.6:2008 127.0.0.7:2009 jump_fnv1a_ch(jump) hash_pos(1) 127.0.0.2:2004 127.0.0.5:2007 match * -> xu7ooXohduotaht1quie carbon_ch(carbon) hash_pos(29314) 127.0.0.1:2003 127.0.0.7:2009 fnv1a_ch(fnv) hash_pos(42712) 127.0.0.5:2007 127.0.0.1:2003 jump_fnv1a_ch(jump) hash_pos(5) 127.0.0.6:2008 127.0.0.7:2009 match * -> ohth8Shei7Yei1aewala carbon_ch(carbon) hash_pos(24415) 127.0.0.7:2009 127.0.0.2:2004 fnv1a_ch(fnv) hash_pos(11765) 127.0.0.6:2008 127.0.0.4:2006 jump_fnv1a_ch(jump) hash_pos(3) 127.0.0.4:2006 127.0.0.1:2003 match * -> XoChoh7iecee0ahg3fu5 carbon_ch(carbon) hash_pos(53904) 127.0.0.1:2003 127.0.0.4:2006 fnv1a_ch(fnv) hash_pos(29824) 127.0.0.2:2004 127.0.0.1:2003 jump_fnv1a_ch(jump) hash_pos(2) 127.0.0.3:2005 127.0.0.7:2009 match * -> Iecee6izeig2oshieChe carbon_ch(carbon) hash_pos(26732) 127.0.0.6:2008 127.0.0.3:2005 fnv1a_ch(fnv) hash_pos(28018) 127.0.0.2:2004 127.0.0.4:2006 jump_fnv1a_ch(jump) hash_pos(1) 127.0.0.2:2004 127.0.0.6:2008 match * -> zoi4wah2Ooh4Laeveiro carbon_ch(carbon) hash_pos(11599) 127.0.0.4:2006 127.0.0.1:2003 fnv1a_ch(fnv) hash_pos(65339) 127.0.0.6:2008 127.0.0.4:2006 jump_fnv1a_ch(jump) hash_pos(0) 127.0.0.1:2003 127.0.0.4:2006 match * -> nahw4tugh5emaeJ6quo3 carbon_ch(carbon) hash_pos(20553) 127.0.0.1:2003 127.0.0.5:2007 fnv1a_ch(fnv) hash_pos(22407) 127.0.0.1:2003 127.0.0.5:2007 jump_fnv1a_ch(jump) hash_pos(4) 127.0.0.5:2007 127.0.0.2:2004 match * -> # carbon_ch(carbon) hash_pos(427) 127.0.0.5:2007 127.0.0.4:2006 fnv1a_ch(fnv) hash_pos(46878) 127.0.0.1:2003 127.0.0.4:2006 jump_fnv1a_ch(jump) hash_pos(0) 127.0.0.1:2003 127.0.0.7:2009 match * -> iiZeik7oongohdohgane carbon_ch(carbon) hash_pos(363) 127.0.0.7:2009 127.0.0.5:2007 fnv1a_ch(fnv) hash_pos(36956) 127.0.0.5:2007 127.0.0.3:2005 jump_fnv1a_ch(jump) hash_pos(1) 127.0.0.2:2004 127.0.0.7:2009 match * -> # carbon_ch(carbon) hash_pos(427) 127.0.0.5:2007 127.0.0.4:2006 fnv1a_ch(fnv) hash_pos(46878) 127.0.0.1:2003 127.0.0.4:2006 jump_fnv1a_ch(jump) hash_pos(0) 127.0.0.1:2003 127.0.0.7:2009 match * -> Heak8dahph1is7eaghah carbon_ch(carbon) hash_pos(23781) 127.0.0.1:2003 127.0.0.7:2009 fnv1a_ch(fnv) hash_pos(62) 127.0.0.6:2008 127.0.0.4:2006 jump_fnv1a_ch(jump) hash_pos(5) 127.0.0.6:2008 127.0.0.2:2004 carbon-c-relay-3.2/test/issue238.out000066400000000000000000000020421317265605500172610ustar00rootroot00000000000000statistics submit every 60 seconds prefix with carbon.relays.test_hostname ; cluster zone1 carbon_ch replication 1 127.0.0.1:2101 ; cluster zone2 carbon_ch replication 1 127.0.0.1:2102 ; cluster zone3 carbon_ch replication 1 127.0.0.1:2103 ; match * validate ^[-+]?[0-9]*.?[0-9]+([eE][-+]?[0-9]+)?\ [0-9.]+$ else drop send to zone1 ; match * validate ^[-+]?[0-9]*.?[0-9]+([eE][-+]?[0-9]+)?\s[0-9.]+$ else drop send to zone2 ; match * validate ^[-+]?[0-9]*.?[0-9]+([eE][-+]?[0-9]+)?[:space:][0-9.]+$ else drop send to zone3 stop ; match * -> foo validate ^[-+]?[0-9]*.?[0-9]+([eE][-+]?[0-9]+)?\ [0-9.]+$ -> 4.2e-10 42 match carbon_ch(zone1) 127.0.0.1:2101 match * -> foo validate ^[-+]?[0-9]*.?[0-9]+([eE][-+]?[0-9]+)?\s[0-9.]+$ -> 4.2e-10 42 fail -> drop match * -> foo validate ^[-+]?[0-9]*.?[0-9]+([eE][-+]?[0-9]+)?[:space:][0-9.]+$ -> 4.2e-10 42 fail -> drop stop carbon-c-relay-3.2/test/issue238.tst000066400000000000000000000000171317265605500172640ustar00rootroot00000000000000foo 4.2e-10 42 carbon-c-relay-3.2/test/issue246.out000066400000000000000000000016561317265605500172720ustar00rootroot00000000000000listen type linemode 2003 proto tcp 2003 proto udp /tmp/.s.carbon-c-relay.2003 proto unix ; statistics submit every 60 seconds prefix with carbon.relays.test_hostname ; cluster foo file /dev/stdout ; match ^sin\.foobar\.sin_1a_host0[0-4][0-9]\..+ send to foo stop ; match ^sin\.foobar\.sin_1a_host0[5-9][0-9]\..+ send to foo stop ; match ^sin\.foobar\.sin_1a_host1[0-4][0-9]\..+ send to foo stop ; match * send to foo stop ; match ^sin\.foobar\.sin_1a_host0[0-4][0-9]\..+ (regex) -> sin.foobar.sin_1a_host000.foo file(foo) /dev/stdout stop match ^sin\.foobar\.sin_1a_host0[5-9][0-9]\..+ (regex) -> sin.foobar.sin_1a_host050.foo file(foo) /dev/stdout stop match ^sin\.foobar\.sin_1a_host1[0-4][0-9]\..+ (regex) -> sin.foobar.sin_1a_host100.foo file(foo) /dev/stdout stop carbon-c-relay-3.2/test/issue246.tst000066400000000000000000000001321317265605500172610ustar00rootroot00000000000000sin.foobar.sin_1a_host000.foo sin.foobar.sin_1a_host050.foo sin.foobar.sin_1a_host100.foo carbon-c-relay-3.2/test/issue252.out000066400000000000000000000023601317265605500172600ustar00rootroot00000000000000listen type linemode 2003 proto tcp 2003 proto udp /tmp/.s.carbon-c-relay.2003 proto unix ; statistics submit every 60 seconds prefix with carbon.relays.test_hostname ; cluster default fnv1a_ch replication 1 127.0.0.1:2103 ; aggregate ^collectd\.(.+)\.cpu\.([0-9]+)\.percent\.idle ^collectd\.(ABC-.+)\.cpu\.([0-9]+)\.percent\.idle ^collectd\.ABC-(.+)\.cpu\.([0-9]+)\.percent\.idle ^collectd\.([^.]+)\.cpu\.([0-9]+)\.percent\.idle every 10 seconds expire after 15 seconds timestamp at end of bucket compute count write to collectd.\1.aggregated.cpu.total_cores ; match * send to default stop ; aggregation ^collectd\.(.+)\.cpu\.([0-9]+)\.percent\.idle (regex) -> collectd.test_host.cpu.42.percent.idle count(collectd.\1.aggregated.cpu.total_cores) -> collectd.test_host.aggregated.cpu.total_cores aggregation ^collectd\.([^.]+)\.cpu\.([0-9]+)\.percent\.idle (regex) -> collectd.test_host.cpu.42.percent.idle count(collectd.\1.aggregated.cpu.total_cores) -> collectd.test_host.aggregated.cpu.total_cores match * -> collectd.test_host.cpu.42.percent.idle fnv1a_ch(default) 127.0.0.1:2103 stop carbon-c-relay-3.2/test/issue252.tst000066400000000000000000000000471317265605500172630ustar00rootroot00000000000000collectd.test_host.cpu.42.percent.idle carbon-c-relay-3.2/test/issue253.out000066400000000000000000000007471317265605500172700ustar00rootroot00000000000000warning: 'send statistics to ...' is deprecated and will be removed in a future version, use 'statistics send to ...' instead listen type linemode 2003 proto tcp 2003 proto udp /tmp/.s.carbon-c-relay.2003 proto unix ; statistics submit every 60 seconds prefix with carbon.relays.test_hostname send to default stop ; cluster default fnv1a_ch replication 1 127.0.0.1:2103 ; match * send to default stop ; carbon-c-relay-3.2/test/issue253.tst000066400000000000000000000000001317265605500172510ustar00rootroot00000000000000carbon-c-relay-3.2/test/issue263-c0.out000066400000000000000000000004301317265605500175560ustar00rootroot00000000000000../issues/issue263-c1.conf:1:0: syntax error, unexpected string, expecting end of file produce a syntax error here ^ relay(68680,0x7fffa8e9c3c0) malloc: *** error for object 0x7fd7c4c02ab0: pointer being freed was not allocated *** set a breakpoint in malloc_error_break to debug carbon-c-relay-3.2/test/issue263-c0.tst000066400000000000000000000000001317265605500175520ustar00rootroot00000000000000carbon-c-relay-3.2/test/issue263.out000066400000000000000000000004521317265605500172620ustar00rootroot00000000000000listen type linemode 2003 proto tcp 2003 proto udp /tmp/.s.carbon-c-relay.2003 proto unix ; statistics submit every 60 seconds prefix with carbon.relays.test_hostname ; rewrite ^(.+)\.win_([^.]+)\.(.+)\.\%_(.+) into \1.win_\2.\3.Percent_\4 ; carbon-c-relay-3.2/test/issue263.tst000066400000000000000000000000001317265605500172520ustar00rootroot00000000000000carbon-c-relay-3.2/test/issue267.out000066400000000000000000000006521317265605500172700ustar00rootroot00000000000000listen type linemode 2003 proto tcp 2003 proto udp /tmp/.s.carbon-c-relay.2003 proto unix ; statistics submit every 60 seconds prefix with carbon.relays.test_hostname ; cluster log-file file /tmp/carbon-c-relay-metrics.log ; cluster next-hop forward 127.0.0.1:2013 ; match * send to log-file ; match * send to next-hop stop ; carbon-c-relay-3.2/test/issue267.tst000066400000000000000000000000001317265605500172560ustar00rootroot00000000000000carbon-c-relay-3.2/test/issue27.out000066400000000000000000000005461317265605500172040ustar00rootroot00000000000000listen type linemode 2003 proto tcp 2003 proto udp /tmp/.s.carbon-c-relay.2003 proto unix ; statistics submit every 60 seconds prefix with carbon.relays.test_hostname ; rewrite env\.app\.POS.\.yadda\.count into env.app.POS ; rewrite env\.app\.POS.\.yadda\.count into env.app.POS#.yadda.count ; carbon-c-relay-3.2/test/issue27.tst000066400000000000000000000000001317265605500171700ustar00rootroot00000000000000carbon-c-relay-3.2/test/issue288.out000066400000000000000000000015271317265605500172750ustar00rootroot00000000000000listen type linemode 2003 proto tcp 2003 proto udp /tmp/.s.carbon-c-relay.2003 proto unix ; statistics submit every 60 seconds prefix with carbon.relays.test_hostname ; cluster crash fnv1a_ch replication 1 127.0.0.1:2003 127.0.0.2:2003 127.0.0.3:2003 127.0.0.4:2003 127.0.0.5:2003 127.0.0.6:2003 127.0.0.7:2003 127.0.0.8:2003 127.0.0.9:2003 127.0.0.10:2003 127.0.0.11:2003 127.0.0.12:2003 127.0.0.13:2003 127.0.0.14:2003 127.0.0.15:2003 127.0.0.16:2003 127.0.0.17:2003 127.0.0.18:2003 127.0.0.19:2003 127.0.0.20:2003 127.0.0.21:2003 127.0.0.22:2003 127.0.0.23:2003 127.0.0.24:2003 127.0.0.25:2003 ; carbon-c-relay-3.2/test/issue288.tst000066400000000000000000000000001317265605500172610ustar00rootroot00000000000000carbon-c-relay-3.2/test/issue293.out000066400000000000000000000005301317265605500172620ustar00rootroot00000000000000listen type linemode 2003 proto tcp 2003 proto udp /tmp/.s.carbon-c-relay.2003 proto unix ; statistics submit every 60 seconds prefix with carbon.relays.test_hostname ; cluster ignore_nonexistent any_of 127.0.0.1:2003 127.0.0.2:2003 nonexistent.example.com:2003 ; carbon-c-relay-3.2/test/issue293.tst000066400000000000000000000000001317265605500172550ustar00rootroot00000000000000carbon-c-relay-3.2/test/issue310.dbg000066400000000000000000000000001317265605500171650ustar00rootroot00000000000000carbon-c-relay-3.2/test/issue310.out000066400000000000000000000017011317265605500172510ustar00rootroot00000000000000listen type linemode 2003 proto tcp 2003 proto udp /tmp/.s.carbon-c-relay.2003 proto unix ; statistics submit every 60 seconds prefix with carbon.relays.test_hostname ; cluster blabla-1 jump_fnv1a_ch replication 1 10.1.1.45:2003=9 10.1.1.40:2003=11 10.1.1.24:2003=8 10.1.2.26:2003=2 10.1.2.33:2003=1 10.1.2.7:2003=5 10.1.2.9:2003=6 10.1.2.3:2003=3 10.1.2.4:2003=4 10.1.2.21:2003=7 10.1.2.1:2003=0 10.1.2.39:2003=10 ; # hash ring for blabla-1 follows 10@10.1.2.1:2003=0 4@10.1.2.33:2003=1 3@10.1.2.26:2003=2 7@10.1.2.3:2003=3 8@10.1.2.4:2003=4 5@10.1.2.7:2003=5 6@10.1.2.9:2003=6 9@10.1.2.21:2003=7 2@10.1.1.24:2003=8 0@10.1.1.45:2003=9 11@10.1.2.39:2003=10 1@10.1.1.40:2003=11 match * send to blabla-1 ; carbon-c-relay-3.2/test/listen-duplicates01.conf000066400000000000000000000001011317265605500215760ustar00rootroot00000000000000 listen linemode 2013 proto tcp 127.0.0.1:2013 proto tcp ; carbon-c-relay-3.2/test/listen-duplicates01.out000066400000000000000000000002261317265605500214700ustar00rootroot00000000000000listen-duplicates01.conf:6:1: duplicate listener 127.0.0.1 with 127.0.0.1 for port 2013 ; ^ failed to read configuration 'listen-duplicates01.conf' carbon-c-relay-3.2/test/listen-duplicates01.tst000066400000000000000000000000001317265605500214610ustar00rootroot00000000000000carbon-c-relay-3.2/test/listen-duplicates02.conf000066400000000000000000000001661317265605500216120ustar00rootroot00000000000000 listen linemode [::]:2013 proto tcp 0.0.0.0:2013 proto tcp [::1]:2013 proto tcp 127.0.0.1:2013 proto tcp ; carbon-c-relay-3.2/test/listen-duplicates02.out000066400000000000000000000002111317265605500214630ustar00rootroot00000000000000listen-duplicates02.conf:8:1: duplicate listener ::1 with :: for port 2013 ; ^ failed to read configuration 'listen-duplicates02.conf' carbon-c-relay-3.2/test/listen-duplicates02.tst000066400000000000000000000000001317265605500214620ustar00rootroot00000000000000carbon-c-relay-3.2/test/listen.conf000066400000000000000000000010021317265605500173030ustar00rootroot00000000000000# listen syntax incarnations # # # listen # type linemode [transport >] # < proto > ... # ... # ; listen type linemode 2013 proto tcp 0.0.0.0:2013 proto udp /var/tmp/tstlisten.sock proto unix ; listen type linemode 0.0.0.0:2014 proto tcp ; listen type linemode transport gzip 0.0.0.0:2015 proto tcp ; listen type linemode transport ssl mycert.pem 127.0.0.1:2913 proto tcp ; carbon-c-relay-3.2/test/listen.out000066400000000000000000000006101317265605500171710ustar00rootroot00000000000000listen type linemode 2013 proto tcp 0.0.0.0:2013 proto udp /var/tmp/tstlisten.sock proto unix 0.0.0.0:2014 proto tcp type linemode transport gzip 0.0.0.0:2015 proto tcp type linemode transport ssl mycert.pem 127.0.0.1:2913 proto tcp ; statistics submit every 60 seconds prefix with carbon.relays.test_hostname ; carbon-c-relay-3.2/test/listen.tst000066400000000000000000000000001317265605500171650ustar00rootroot00000000000000carbon-c-relay-3.2/test/run-test.sh000077500000000000000000000035171317265605500172730ustar00rootroot00000000000000#!/usr/bin/env bash # Copyright 2013-2017 Fabian Groffen # # 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. EXEC=../relay EFLAGS="-Htest.hostname -t" DIFF="diff -Nu" POST="cat" CNFCLN=( sed -e '/^configuration:/,/^parsed configuration follows:/d' -e '/starting carbon-c-relay v/d' -e 's/^\[[0-9][0-9\-]* [0-9][0-9:]*\] //' -e 's/_stub_[0-9a-fx][0-9a-fx]*__/_stub_0xc0d3__/') run_test() { local eflags="$1" local test=${2%.*} local conf="${test}.conf" local tdiff [[ -e ${conf} ]] || conf="../issues/${conf}" echo -n "${test}: " tdiff=$(cat ${2} \ | ( ${EXEC} ${eflags} -f "${conf}" ; trigger_bash_segv_print=$?) 2>&1 \ | "${CNFCLN[@]}" \ | ${DIFF} "${test}.out" - --label "${test}.out" --label "${test}.out" \ | ${POST} \ ; exit ${PIPESTATUS[3]}) if [[ $? == 0 ]] ; then echo "PASS" return 0 else echo "FAIL" echo "${tdiff}" return 1 fi } while [[ -n $1 ]] ; do case "$1" in --approve|-a) POST="patch" ;; --) shift break ;; *) break ;; esac shift done tstcnt=0 tstfail=0 for t in $* ; do if [[ -e ${t}.tst ]] ; then : $((tstcnt++)) run_test "${EFLAGS}" "${t}.tst" || : $((tstfail++)) elif [[ -e ${t}.dbg ]] ; then : $((tstcnt++)) run_test "${EFLAGS} -d" "${t}.dbg" || : $((tstfail++)) fi done echo "Ran ${tstcnt} tests with ${tstfail} failing" exit ${tstfail}