diff --git a/.gitignore b/.gitignore index 1d2e9fce5..0ce9eb7e2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ +*.trace pprof.txt +.dsn *.svg *.profile *.key @@ -28,6 +30,7 @@ bin/ *.test bin/* test/log/ +test/covenantsql* # Output of the go coverage tool, specifically when used with LiteIDE *.out diff --git a/.travis.yml b/.travis.yml index 9b787d406..676511089 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ env: - secure: "CNZXODvXHMB0z6Z+Jd8MjzP+RYgRzkykRNpZdCDCo6AC57BpV5U20Mn9o2MGhTA9lMgtyNXXEaQxeIGZMFp3iB2UHiPif1UD4C0uDttytTuCcmHMlBIVP8GiNcAexi1Zv2SchM1k8z3tw5zDhkYMwjs/4ZsGVXHa1ip/UzpZaJBPl9D64wedJxZGBjS/Kn9IZTrMkL2otr8rKk0ZFMtwDkHKdjfikZ+PAlkYpX2a2Dp69HTLbEtx+ugocNj02hzgVYNpFXA1K0CulyCYJq7oqdx0UFbtKEd3urYFWfmxEZSg6SoHcIujC+/BKfZELFyA3uomp+cLpGaRlEp/iAlj/ixTo4iFtu6XdDOim4J9ZVtNSg6DdDstL9uhxCu+vca/ntViGfyw6CF0hKcHTZvlH2awiV1njmHFdRvoaMy/1fdw1JAV9O7ylU3bV5GrF6fMQ1CpweYCnF3IMpvvwdeUnGR6NPvqjybcnyXoTXZ139PxfWzbUzSG8KbOvzt1aVhWF5184b8fqhN3768Y1stke+FjFpARqlPVsfzS7fnn5kx8zZ5nfmwZjnL/WFob24mvm+/9e7IsfWmeEQdFspD+spBE4WOta7tegqh5ANNfM2owd9evtH5kqlCLeAVD3LMs69ZQW45KS0rDJpY8+ffMWRJRmoM/pweW3CmbHPeb468=" # https://codecov.io/gh/CovenantSQL/CovenantSQL - secure: "iJVHTJ8NNzb3UKgh8VRXZg+XVXxcnH10dPDyg44Osp67bkwB46nIDAgDvPRZCX4Kr2Q7FCip1DT1DzkcxCBqCD7XgSsvtoP05kckWZf5dUp2qdaaBgFBR5F2ijhTgpqSG2/MZyY/9DRZhfd/DTywo4K4cGRGpjUYm7BSmR/5ou1Dk6CksoPFMwkE0zHVdRBkRoMaqqVGl9uxFyU6ssZ9IFsLbbSiJ+/iFZDbfBMuzhpxziJ4Oli1LrveEMCCnwKFgVURD3bVUtHrpdQ1RNJQzjkM8tvtilrh3Sf5X9+sJ8K+N1NnzDJiPnEZfkd69vDSh5gEivgIg3j9zIgQGfreDoKCOTfEgzGxRaPusokLQUyDGcU0ZMtLV3mzikeWJ1nUv7jOR8RF97KoJL/ZEgK5Owh5w3WhA+EcvuWC5gggi5Lx2mf7AK6zbm5JiOomBZLINKnygT+tHOKbuglDgP2UL7OBDE3xCI+WT4q3Zz6VKuNdwEFv81Qg925QFr9ifZlCPSzaNHkepEGji++3yFaEPTEtS3TzM+DTqOefU/I1q4IFvgHRMh4M7AbYQPx1m6H/2kk9xwycMD6HtHHwA9Yk2jnMUM085lL1W3A2gEn3V73lm99jQuECW8AgYQ3o9J8BpuVuZnH9n5uXjyFPrhc2tCUPDrBes/phFfJycSrGq0Y=" - - REVIEWDOG_VERSION=0.9.9 + - REVIEWDOG_VERSION=0.9.11 language: go go: - '1.11' @@ -34,15 +34,17 @@ before_script: - echo $TRAVIS_SECURE_ENV_VARS script: - bash build.sh - - go test -v -race $(go list ./... | grep -v "/vendor/") -coverprofile cover.out + - go test -v -race -failfast -parallel 16 $(go list ./... | grep -v "/vendor/") -coverprofile cover.out + - cd rpc && go test -test.bench ^BenchmarkPersistentCaller_Call$ -test.run ^$ && cd - - gocovmerge cover.out $(find cmd -name "*.cover.out") > coverage.txt && rm -f cover.out - bash <(curl -s https://codecov.io/bash) - >- golint ./... | grep -v 'vendor/' | grep -v 'server/' | grep -v 'utils/' | reviewdog -f=golint -reporter=github-pr-review || true before_deploy: + - bash build.sh - mkdir -p build - - tar czvf build/CovenantSQL-$TRAVIS_TAG.$TRAVIS_OS_NAME-amd64.tar.gz bin/cql* + - tar czvf build/CovenantSQL-$TRAVIS_TAG.$TRAVIS_OS_NAME-amd64.tar.gz $(ls bin/cql* | grep -v test) deploy: provider: releases diff --git a/CHANGELOG.md b/CHANGELOG.md index 28274c80e..bcca8da03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,31 @@ # Changelog +## [v0.0.3](https://github.com/CovenantSQL/CovenantSQL/tree/v0.0.3) (2018-11-04) + +[Full Changelog](https://github.com/CovenantSQL/CovenantSQL/compare/v0.0.2...v0.0.3) + +**Fixed bugs:** + +- Cannot receive tokens from testnet [\#84](https://github.com/CovenantSQL/CovenantSQL/issues/84) +- Potential deadlock in testing [\#93](https://github.com/CovenantSQL/CovenantSQL/issues/93) + +**Closed issues:** + +- Command cqld -version failed without -config parameter [\#99](https://github.com/CovenantSQL/CovenantSQL/issues/99) + +**Merged pull requests:** + +- Add call stack print for Error, Fatal and Panic [\#108](https://github.com/CovenantSQL/CovenantSQL/pull/108) ([auxten](https://github.com/auxten)) +- Update GNTE submodule to it's newest master [\#105](https://github.com/CovenantSQL/CovenantSQL/pull/105) ([laodouya](https://github.com/laodouya)) +- Add GNTE bench test [\#102](https://github.com/CovenantSQL/CovenantSQL/pull/102) ([laodouya](https://github.com/laodouya)) +- Use leveldb to instead boltdb on sqlchain [\#101](https://github.com/CovenantSQL/CovenantSQL/pull/101) ([zeqing-guo](https://github.com/zeqing-guo)) +- Update Dockerfile, using go1.11 instead [\#100](https://github.com/CovenantSQL/CovenantSQL/pull/100) ([laodouya](https://github.com/laodouya)) +- Replace hashicorp/yamux with xtaci/smux [\#98](https://github.com/CovenantSQL/CovenantSQL/pull/98) ([auxten](https://github.com/auxten)) +- Update MySQL Adapter to support mysql-java-connector/SequelPro/Navicat [\#96](https://github.com/CovenantSQL/CovenantSQL/pull/96) ([xq262144](https://github.com/xq262144)) +- Minerd performance tuning [\#95](https://github.com/CovenantSQL/CovenantSQL/pull/95) ([auxten](https://github.com/auxten)) +- Update README [\#91](https://github.com/CovenantSQL/CovenantSQL/pull/91) ([foreseaz](https://github.com/foreseaz)) +- Blockproducer Explorer feature including Transaction type encode/decode improvements [\#90](https://github.com/CovenantSQL/CovenantSQL/pull/90) ([xq262144](https://github.com/xq262144)) + ## [v0.0.2](https://github.com/CovenantSQL/CovenantSQL/tree/v0.0.2) (2018-10-17) [Full Changelog](https://github.com/CovenantSQL/CovenantSQL/compare/v0.0.1...v0.0.2) @@ -51,12 +77,13 @@ **Merged pull requests:** -- Make cql-utils and README.md less ambiguous [\#77](https://github.com/CovenantSQL/CovenantSQL/pull/77) ([auxten](https://github.com/auxten)) +- Make idminer and README.md less ambiguous [\#77](https://github.com/CovenantSQL/CovenantSQL/pull/77) ([auxten](https://github.com/auxten)) - Make all path config in adapter relative to working root configuration [\#76](https://github.com/CovenantSQL/CovenantSQL/pull/76) ([auxten](https://github.com/auxten)) +- TestNet faucet for CovenantSQL API demo [\#75](https://github.com/CovenantSQL/CovenantSQL/pull/75) ([auxten](https://github.com/auxten)) - HTTPS RESTful API for CovenantSQL [\#74](https://github.com/CovenantSQL/CovenantSQL/pull/74) ([xq262144](https://github.com/xq262144)) - Unify the nonce increment, BaseAccount also increases account nonce. [\#73](https://github.com/CovenantSQL/CovenantSQL/pull/73) ([leventeliu](https://github.com/leventeliu)) - Fix a nonce checking issue and add more specific test cases. [\#72](https://github.com/CovenantSQL/CovenantSQL/pull/72) ([leventeliu](https://github.com/leventeliu)) -- Add an cql-utils readme for generating key pair and testnet address [\#71](https://github.com/CovenantSQL/CovenantSQL/pull/71) ([zeqing-guo](https://github.com/zeqing-guo)) +- Add an idminer readme for generating key pair and testnet address [\#71](https://github.com/CovenantSQL/CovenantSQL/pull/71) ([zeqing-guo](https://github.com/zeqing-guo)) - Add BenchmarkSingleMiner, use rpc.NewPersistentCaller for client conn [\#70](https://github.com/CovenantSQL/CovenantSQL/pull/70) ([auxten](https://github.com/auxten)) - Add RPC methods for balance query. [\#69](https://github.com/CovenantSQL/CovenantSQL/pull/69) ([leventeliu](https://github.com/leventeliu)) - Addrgen to generate testnet address [\#68](https://github.com/CovenantSQL/CovenantSQL/pull/68) ([zeqing-guo](https://github.com/zeqing-guo)) @@ -65,7 +92,7 @@ - Add auto config generator [\#65](https://github.com/CovenantSQL/CovenantSQL/pull/65) ([zeqing-guo](https://github.com/zeqing-guo)) - Use a well-defined interface to process transactions on block producers. [\#64](https://github.com/CovenantSQL/CovenantSQL/pull/64) ([leventeliu](https://github.com/leventeliu)) - Add an explanation for non-deterministic authenticated encryption input vector [\#63](https://github.com/CovenantSQL/CovenantSQL/pull/63) ([auxten](https://github.com/auxten)) -- Add nonce generator in cql-utils [\#61](https://github.com/CovenantSQL/CovenantSQL/pull/61) ([zeqing-guo](https://github.com/zeqing-guo)) +- Add nonce generator in idminer [\#61](https://github.com/CovenantSQL/CovenantSQL/pull/61) ([zeqing-guo](https://github.com/zeqing-guo)) - Optional database encryption support on database creation. [\#60](https://github.com/CovenantSQL/CovenantSQL/pull/60) ([xq262144](https://github.com/xq262144)) - Clarify README.md for project and DH-RPC [\#59](https://github.com/CovenantSQL/CovenantSQL/pull/59) ([auxten](https://github.com/auxten)) - Rename ThunderDB to CovenantSQL [\#57](https://github.com/CovenantSQL/CovenantSQL/pull/57) ([zeqing-guo](https://github.com/zeqing-guo)) @@ -75,8 +102,6 @@ - Fix/issue-50: use major version tag in docker file [\#51](https://github.com/CovenantSQL/CovenantSQL/pull/51) ([leventeliu](https://github.com/leventeliu)) - Add DH-RPC example [\#49](https://github.com/CovenantSQL/CovenantSQL/pull/49) ([auxten](https://github.com/auxten)) - Merge cli tool to core code base [\#48](https://github.com/CovenantSQL/CovenantSQL/pull/48) ([xq262144](https://github.com/xq262144)) -- Add observer helper functions and binaries and hotfix binary for dht database migrations. [\#47](https://github.com/CovenantSQL/CovenantSQL/pull/47) ([xq262144](https://github.com/xq262144)) -- [More...](https://github.com/CovenantSQL/CovenantSQL/pulls?q=is%3Apr+is%3Aclosed) diff --git a/Dockerfile b/Dockerfile index 866681942..2f046e8a4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Stage: builder -FROM golang:1.10-stretch as builder +FROM golang:1.11-stretch as builder WORKDIR /go/src/github.com/CovenantSQL/CovenantSQL COPY . . diff --git a/Gopkg.lock b/Gopkg.lock index 4fdec7120..563485179 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -19,7 +19,7 @@ [[projects]] branch = "master" - digest = "1:8d21b4d359da7c7e49800d2e6e186997bae08ea6f814b7ca20bbd76e72e0338d" + digest = "1:599cc68328d92a329d9ec7fd516ed5ac2abfaaafd5f824001adafcb0cf10fe49" name = "github.com/CovenantSQL/sqlparser" packages = [ ".", @@ -29,7 +29,7 @@ "dependency/sqltypes", ] pruneopts = "UT" - revision = "fe86852c12c8b9055d4d0731940014487dca1f12" + revision = "fb543cee920387ed5e85a2f098eba2dcc12b13c7" [[projects]] branch = "master" @@ -119,6 +119,14 @@ revision = "583e8937c61f1af6513608ccc75c97b6abdf4ff9" version = "v1.3.0" +[[projects]] + branch = "master" + digest = "1:7b274cc72af687fe6eb618acd83b9601c4317fbe5ac1dfb41cc116e3495f68b0" + name = "github.com/cyberdelia/go-metrics-graphite" + packages = ["."] + pruneopts = "UT" + revision = "39f87cc3b432bbb898d7c643c0e93cac2bc865ad" + [[projects]] branch = "master" digest = "1:710109527a119c813d4fac773712dd92f449ed7c2f7b81f49822f94d290c8f72" @@ -192,7 +200,7 @@ name = "github.com/gopherjs/gopherjs" packages = ["js"] pruneopts = "UT" - revision = "1babbf986f6fcb1156d0646cdba5c4f81bc32849" + revision = "0766667cb4d1cfb8d5fde1fe210ae41ead3cf589" [[projects]] digest = "1:c79fb010be38a59d657c48c6ba1d003a8aa651fa56b579d959d74573b7dff8e1" @@ -218,14 +226,6 @@ revision = "e3702bed27f0d39777b0b37b664b6280e8ef8fbf" version = "v1.6.2" -[[projects]] - branch = "master" - digest = "1:a4826c308e84f5f161b90b54a814f0be7d112b80164b9b884698a6903ea47ab3" - name = "github.com/hashicorp/yamux" - packages = ["."] - pruneopts = "UT" - revision = "2f1d1f20f75d5404f53b9edf6b53ed5505508675" - [[projects]] branch = "master" digest = "1:438016f7d4af8e5a7010b6d0705b267a7607ddc0decad051e83a9458c6b9a523" @@ -307,12 +307,12 @@ version = "v1.0.1" [[projects]] - digest = "1:57689550840d285f2da9e85356a66e626592a8b6f1170d7f2482438e64fe82e3" + digest = "1:c22d250c583ec1136ecad8b74a43f408c08ddbbcbae715341ec4a49f332628e0" name = "github.com/miekg/dns" packages = ["."] pruneopts = "UT" - revision = "d74956db7b5b20451796774572d0f5a0222e377a" - version = "v1.0.13" + revision = "915ca3d5ffd945235828a097c917311a9d86ebb4" + version = "v1.0.14" [[projects]] branch = "master" @@ -348,14 +348,14 @@ [[projects]] branch = "master" - digest = "1:f43f7e80e273179b98af510dd453d184c7860920d6f9aa5c89e06aed0494a7a8" + digest = "1:f696f304d2a14745859a153f1041b66e0e2cf150eff731beb6431e93e27ddc5c" name = "github.com/prometheus/client_golang" packages = [ "prometheus", "prometheus/internal", ] pruneopts = "UT" - revision = "1cafe34db7fdec6022e17e00e1c1ea501022f3e4" + revision = "f30f428035633da15d00d3dfefb0128c5e569ef4" [[projects]] branch = "master" @@ -367,7 +367,7 @@ [[projects]] branch = "master" - digest = "1:95ed48ec01b571d453b17ed631c7b65be39ced2b5082f1426a2fa6991799846f" + digest = "1:6366b518dc6e520027f67ad03792b99e370468aac47c4102bddd56ae6ce780e5" name = "github.com/prometheus/common" packages = [ "expfmt", @@ -376,7 +376,7 @@ "version", ] pruneopts = "UT" - revision = "bcb74de08d37a417cb6789eec1d6c810040f0470" + revision = "7e9e6cabbd393fc208072eedef99188d0ce788b6" [[projects]] branch = "master" @@ -393,11 +393,19 @@ [[projects]] branch = "master" - digest = "1:ff6b0586c0621a76832cf783eee58cbb9d9795d2ce8acbc199a4131db11c42a9" + digest = "1:d38f81081a389f1466ec98192cf9115a82158854d6f01e1c23e2e7554b97db71" + name = "github.com/rcrowley/go-metrics" + packages = ["."] + pruneopts = "UT" + revision = "3113b8401b8a98917cde58f8bbd42a1b1c03b1fd" + +[[projects]] + branch = "master" + digest = "1:a3b8912deeef29007fab9a13a9f21b9e9b59c621a2ed61e2fe7b37320a71fbd5" name = "github.com/satori/go.uuid" packages = ["."] pruneopts = "UT" - revision = "36e9d2ebbde5e3f13ab2e25625fd453271d6522e" + revision = "b2ce2384e17bbe0c6d34077efa39dbab3e09123b" [[projects]] branch = "master" @@ -423,7 +431,7 @@ [[projects]] branch = "master" - digest = "1:a730590f80ebe31a7c88a072500766c6094a14b03e0c6931e4a63a13f227edc4" + digest = "1:d3384958d1ace51e2187c9747d806eee27d1aebdb1a4df798058a8cacc19b379" name = "github.com/siddontang/go-mysql" packages = [ "mysql", @@ -431,7 +439,8 @@ "server", ] pruneopts = "UT" - revision = "c8bed9e1e90b2121165ad80fe85a34ceff169999" + revision = "7f644882a1f315e77bfda60b4f689a45a2eec228" + source = "github.com/CovenantSQL/go-mysql" [[projects]] digest = "1:3f53e9e4dfbb664cd62940c9c4b65a2171c66acd0b7621a1a6b8e78513525a52" @@ -539,11 +548,11 @@ [[projects]] branch = "master" - digest = "1:8a6b9b1c86f610eb347e6e5e42af0fc9aff52427c619dd70e9e61a79c6114106" + digest = "1:3863946ace74cbd518a33a2e8dd145a13aba1fc37a0e89788154083f183fca11" name = "github.com/xo/tblfmt" packages = ["."] pruneopts = "UT" - revision = "3ae3311c5ac954b9ec8a89eed14e395abbb069e4" + revision = "e82d5611beb24993cc6afc59cdacf6e598891d12" [[projects]] branch = "master" @@ -555,7 +564,7 @@ [[projects]] branch = "master" - digest = "1:6162124bb1bdabe76e3da4a734a5109e8979e8cf4ddcc5c0efeb0a50bd3c1ef5" + digest = "1:70492e57eb4abe45c86ff3855b87a6681f15bcf7e12666596c1e826a9c95d99f" name = "github.com/xo/usql" packages = [ "drivers", @@ -568,7 +577,16 @@ "text", ] pruneopts = "UT" - revision = "ee0ef60c5b0883dcb5caa67d5317c56d6389e779" + revision = "885ff880d8520d74c227a9d1a310aa473209d155" + source = "github.com/CovenantSQL/usql" + +[[projects]] + digest = "1:07aaea55c778d9f0461a429eb19a134f17e9ac3232a5a28b16dfe57c637889bc" + name = "github.com/xtaci/smux" + packages = ["."] + pruneopts = "UT" + revision = "545ecee9d2a96ef4cf3c420c6b4095ac313fe870" + version = "v1.09" [[projects]] digest = "1:4619abe2e9ceabced45ff40a4826866c48f264bb58384efe799a8fb83c2256e0" @@ -588,7 +606,7 @@ "ssh/terminal", ] pruneopts = "UT" - revision = "0c41d7ab0a0ee717d4590a44bcb987dfd9e183eb" + revision = "45a5f77698d342a8c2ef8423abdf0ba6880b008a" [[projects]] branch = "master" @@ -604,18 +622,18 @@ "ipv6", ] pruneopts = "UT" - revision = "49bb7cea24b1df9410e1712aa6433dae904ff66a" + revision = "c44066c5c816ec500d459a2a324a753f78531ae0" [[projects]] branch = "master" - digest = "1:f5aa274a0377f85735edc7fedfb0811d3cbc20af91633797cb359e29c3272271" + digest = "1:d2605ed96ca0244a457fa8e6c37d5c370ce98ea09dcc21e5e07d967bfcb78878" name = "golang.org/x/sys" packages = [ "unix", "windows", ] pruneopts = "UT" - revision = "fa43e7bc11baaae89f3f902b2b4d832b68234844" + revision = "95b1ffbd15a57cc5abb3f04402b9e8ec0016a52c" [[projects]] digest = "1:342378ac4dcb378a5448dd723f0784ae519383532f5e70ade24132c4c8693202" @@ -637,11 +655,11 @@ "github.com/btcsuite/btcd/btcec", "github.com/btcsuite/btcutil/base58", "github.com/coreos/bbolt", + "github.com/cyberdelia/go-metrics-graphite", "github.com/dyatlov/go-opengraph/opengraph", "github.com/fortytw2/leaktest", "github.com/gorilla/handlers", "github.com/gorilla/mux", - "github.com/hashicorp/yamux", "github.com/jmoiron/jsonq", "github.com/jordwest/mock-conn", "github.com/lufia/iostat", @@ -653,6 +671,7 @@ "github.com/prometheus/common/expfmt", "github.com/prometheus/common/version", "github.com/prometheus/procfs", + "github.com/rcrowley/go-metrics", "github.com/satori/go.uuid", "github.com/siddontang/go-mysql/mysql", "github.com/siddontang/go-mysql/server", @@ -671,6 +690,7 @@ "github.com/xo/usql/handler", "github.com/xo/usql/rline", "github.com/xo/usql/text", + "github.com/xtaci/smux", "golang.org/x/crypto/ed25519", "golang.org/x/crypto/ssh/terminal", "golang.org/x/sys/unix", diff --git a/Gopkg.toml b/Gopkg.toml index 6c483cb82..89678703c 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -50,6 +50,7 @@ [[override]] name = "github.com/xo/usql" + source = "github.com/CovenantSQL/usql" branch = "master" [[override]] @@ -60,11 +61,15 @@ name = "github.com/CovenantSQL/xurls" branch = "master" +[[override]] + name = "github.com/siddontang/go-mysql" + source = "github.com/CovenantSQL/go-mysql" + branch = "master" + [prune] go-tests = true unused-packages = true - [[constraint]] branch = "master" name = "github.com/btcsuite/btcutil" diff --git a/README.md b/README.md index c4788fba3..b54cc285d 100644 --- a/README.md +++ b/README.md @@ -69,17 +69,17 @@ that inspired us: ## Libs ### Network Stack -

- -

- - [DH-RPC](rpc/) := TLS - Cert + DHT - - RPC Layer: compatible with golang `net/rpc` - - Naming Layer: [**C**onsistent **S**ecure **DHT**](https://godoc.org/github.com/CovenantSQL/CovenantSQL/consistent) - - Pooling Layer: session pool built on Yamux - - Multiplex Layer: Yamux by Hashicorp - - Transport Security Layer: [**E**nhanced **TLS**](https://github.com/CovenantSQL/research/wiki/ETLS(Enhanced-Transport-Layer-Security)) - - Network Layer: TCP or KCP for optional later +[DH-RPC](rpc/) := TLS - Cert + DHT + +| Layer | Implementation | +|:-------------------|:--------------:| +| RPC | `net/rpc` | +| Naming | [**C**onsistent **S**ecure **DHT**](https://godoc.org/github.com/CovenantSQL/CovenantSQL/consistent) | +| Pooling | Session Pool | +| Multiplex | Yamux | +| Transport Security | [**E**nhanced **TLS**](https://github.com/CovenantSQL/research/wiki/ETLS(Enhanced-Transport-Layer-Security)) | +| Network | TCP or KCP for optional later | #### Test Tools @@ -89,14 +89,17 @@ that inspired us: #### Connector -CovenantSQL is Still Under Construction(U know..). Test net will be released till Oct. +CovenantSQL is still under construction and Testnet is already released, [have a try](https://testnet.covenantsql.io/). -Watch us or [![follow on Twitter](https://img.shields.io/twitter/url/https/twitter.com/fold_left.svg?style=social&label=Follow%20%40CovenantLabs)](https://twitter.com/intent/follow?screen_name=CovenantLabs) for updates. - [Golang](client/) - [Java](https://github.com/CovenantSQL/covenant-connector) +- [NodeJS](https://github.com/CovenantSQL/node-covenantsql) +- [Python](https://github.com/CovenantSQL/python-driver) - Coding for more…… +Watch us or [![follow on Twitter](https://img.shields.io/twitter/url/https/twitter.com/fold_left.svg?style=social&label=Follow%20%40CovenantLabs)](https://twitter.com/intent/follow?screen_name=CovenantLabs) for updates. + ## TestNet - [Quick Start](https://testnet.covenantsql.io/quickstart) diff --git a/bin/docker-entry.sh b/bin/docker-entry.sh index 8726f5b77..fd5348d4a 100755 --- a/bin/docker-entry.sh +++ b/bin/docker-entry.sh @@ -24,5 +24,8 @@ cli) faucet) exec /app/cql-faucet -config ${COVENANT_CONF} "${@}" ;; +explorer) + exec /app/cql-explorer -config ${COVENANT_CONF} "${@}" + ;; esac diff --git a/blockproducer/blockindex.go b/blockproducer/blockindex.go index 02891bcae..a916b5902 100644 --- a/blockproducer/blockindex.go +++ b/blockproducer/blockindex.go @@ -35,12 +35,12 @@ func newBlockNode(h uint32, block *types.Block, parent *blockNode) *blockNode { var count uint32 if parent != nil { - count = parent.height + 1 + count = parent.count + 1 } else { count = 0 } bn := &blockNode{ - hash: block.SignedHeader.BlockHash, + hash: *block.BlockHash(), parent: parent, height: h, count: count, @@ -79,6 +79,18 @@ func (bn *blockNode) ancestor(h uint32) *blockNode { return ancestor } +func (bn *blockNode) ancestorByCount(c uint32) *blockNode { + if c > bn.count { + return nil + } + + ancestor := bn + for ancestor != nil && ancestor.count != c { + ancestor = ancestor.parent + } + return ancestor +} + type blockIndex struct { mu sync.RWMutex index map[hash.Hash]*blockNode @@ -107,9 +119,9 @@ func (bi *blockIndex) hasBlock(h hash.Hash) bool { return has } -func (bi *blockIndex) lookupBlock(h hash.Hash) *blockNode { +func (bi *blockIndex) lookupNode(h *hash.Hash) *blockNode { bi.mu.RLock() defer bi.mu.RUnlock() - return bi.index[h] + return bi.index[*h] } diff --git a/blockproducer/blockindex_test.go b/blockproducer/blockindex_test.go index 4a244e993..67b08e32a 100644 --- a/blockproducer/blockindex_test.go +++ b/blockproducer/blockindex_test.go @@ -31,7 +31,7 @@ func TestNewBlockNodeAndIndexKey(t *testing.T) { } parent := newBlockNode(0, block, nil) if parent == nil { - t.Fatalf("unexpected result: nil") + t.Fatal("unexpected result: nil") } else if parent.parent != nil { t.Fatalf("unexpected parent: %v", parent.parent) } else if parent.height != 0 { @@ -44,7 +44,7 @@ func TestNewBlockNodeAndIndexKey(t *testing.T) { } child := newBlockNode(1, block2, parent) if child == nil { - t.Fatalf("unexpected result: nil") + t.Fatal("unexpected result: nil") } else if child.parent != parent { t.Fatalf("unexpected parent: %v", parent.parent) } else if child.height != parent.height+1 { @@ -69,7 +69,7 @@ func TestAncestor(t *testing.T) { } parent := newBlockNode(0, block, nil) if parent == nil { - t.Fatalf("unexpected result: nil") + t.Fatal("unexpected result: nil") } else if parent.parent != nil { t.Fatalf("unexpected parent: %v", parent.parent) } else if parent.height != 0 { @@ -82,7 +82,7 @@ func TestAncestor(t *testing.T) { } child := newBlockNode(1, block2, parent) if child == nil { - t.Fatalf("unexpected result: nil") + t.Fatal("unexpected result: nil") } else if child.parent != parent { t.Fatalf("unexpected parent: %v", parent.parent) } else if child.height != parent.height+1 { @@ -107,7 +107,7 @@ func TestIndexBlock(t *testing.T) { bi := newBlockIndex() if bi == nil { - t.Fatalf("unexpected result: nil") + t.Fatal("unexpected result: nil") } block0, err := generateRandomBlock(hash.Hash{}, true) @@ -138,7 +138,7 @@ func TestIndexBlock(t *testing.T) { t.Fatalf("lack of block index: %v", bn1) } - bn3 := bi.lookupBlock(bn0.hash) + bn3 := bi.lookupNode(&bn0.hash) if !reflect.DeepEqual(bn0, bn3) { t.Fatalf("two values should be equal: \n\tv0=%+v\n\tv1=%+v", bn0, bn3) } diff --git a/blockproducer/chain.go b/blockproducer/chain.go index 330cdb187..59904afbd 100644 --- a/blockproducer/chain.go +++ b/blockproducer/chain.go @@ -18,15 +18,19 @@ package blockproducer import ( "fmt" + "os" "sync" "time" pi "github.com/CovenantSQL/CovenantSQL/blockproducer/interfaces" - "github.com/CovenantSQL/CovenantSQL/blockproducer/types" + pt "github.com/CovenantSQL/CovenantSQL/blockproducer/types" + "github.com/CovenantSQL/CovenantSQL/crypto" + "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" "github.com/CovenantSQL/CovenantSQL/crypto/hash" "github.com/CovenantSQL/CovenantSQL/crypto/kms" "github.com/CovenantSQL/CovenantSQL/merkle" "github.com/CovenantSQL/CovenantSQL/proto" + "github.com/CovenantSQL/CovenantSQL/route" "github.com/CovenantSQL/CovenantSQL/rpc" "github.com/CovenantSQL/CovenantSQL/utils" "github.com/CovenantSQL/CovenantSQL/utils/log" @@ -34,16 +38,14 @@ import ( ) var ( - metaBucket = [4]byte{0x0, 0x0, 0x0, 0x0} - metaStateKey = []byte("covenantsql-state") - metaBlockIndexBucket = []byte("covenantsql-block-index-bucket") - metaTransactionBucket = []byte("covenantsql-tx-index-bucket") - metaTxBillingIndexBucket = []byte("covenantsql-tx-billing-index-bucket") - metaLastTxBillingIndexBucket = []byte("covenantsql-last-tx-billing-index-bucket") - metaAccountIndexBucket = []byte("covenantsql-account-index-bucket") - metaSQLChainIndexBucket = []byte("covenantsql-sqlchain-index-bucket") - gasprice uint32 = 1 - accountAddress proto.AccountAddress + metaBucket = [4]byte{0x0, 0x0, 0x0, 0x0} + metaStateKey = []byte("covenantsql-state") + metaBlockIndexBucket = []byte("covenantsql-block-index-bucket") + metaTransactionBucket = []byte("covenantsql-tx-index-bucket") + metaAccountIndexBucket = []byte("covenantsql-account-index-bucket") + metaSQLChainIndexBucket = []byte("covenantsql-sqlchain-index-bucket") + gasPrice uint32 = 1 + accountAddress proto.AccountAddress ) // Chain defines the main chain. @@ -51,18 +53,21 @@ type Chain struct { db *bolt.DB ms *metaState bi *blockIndex - ti *txIndex rt *rt cl *rpc.Caller - blocksFromSelf chan *types.Block - blocksFromRPC chan *types.Block + blocksFromSelf chan *pt.Block + blocksFromRPC chan *pt.Block pendingTxs chan pi.Transaction stopCh chan struct{} } // NewChain creates a new blockchain. func NewChain(cfg *Config) (*Chain, error) { + if fi, err := os.Stat(cfg.DataFile); err == nil && fi.Mode().IsRegular() { + return LoadChain(cfg) + } + // open db file db, err := bolt.Open(cfg.DataFile, 0600, nil) if err != nil { @@ -74,11 +79,10 @@ func NewChain(cfg *Config) (*Chain, error) { if err != nil { return nil, err } - enc, err := pubKey.MarshalHash() + accountAddress, err := crypto.PubKeyHash(pubKey) if err != nil { return nil, err } - accountAddress = proto.AccountAddress(hash.THashH(enc[:])) // create bucket for meta data err = db.Update(func(tx *bolt.Tx) (err error) { @@ -103,16 +107,6 @@ func NewChain(cfg *Config) (*Chain, error) { } } - _, err = bucket.CreateBucketIfNotExists(metaTxBillingIndexBucket) - if err != nil { - return - } - - _, err = bucket.CreateBucketIfNotExists(metaLastTxBillingIndexBucket) - if err != nil { - return - } - _, err = bucket.CreateBucketIfNotExists(metaAccountIndexBucket) if err != nil { return @@ -130,16 +124,15 @@ func NewChain(cfg *Config) (*Chain, error) { db: db, ms: newMetaState(), bi: newBlockIndex(), - ti: newTxIndex(), rt: newRuntime(cfg, accountAddress), cl: rpc.NewCaller(), - blocksFromSelf: make(chan *types.Block), - blocksFromRPC: make(chan *types.Block), + blocksFromSelf: make(chan *pt.Block), + blocksFromRPC: make(chan *pt.Block), pendingTxs: make(chan pi.Transaction), stopCh: make(chan struct{}), } - log.Debugf("pushing genesis block: %v", cfg.Genesis) + log.WithField("genesis", cfg.Genesis).Debug("pushing genesis block") if err = chain.pushGenesisBlock(cfg.Genesis); err != nil { return nil, err @@ -170,29 +163,32 @@ func LoadChain(cfg *Config) (chain *Chain, err error) { if err != nil { return nil, err } - enc, err := pubKey.MarshalHash() + accountAddress, err = crypto.PubKeyHash(pubKey) if err != nil { return nil, err } - accountAddress = proto.AccountAddress(hash.THashH(enc[:])) chain = &Chain{ db: db, ms: newMetaState(), bi: newBlockIndex(), - ti: newTxIndex(), rt: newRuntime(cfg, accountAddress), cl: rpc.NewCaller(), - blocksFromSelf: make(chan *types.Block), - blocksFromRPC: make(chan *types.Block), + blocksFromSelf: make(chan *pt.Block), + blocksFromRPC: make(chan *pt.Block), pendingTxs: make(chan pi.Transaction), stopCh: make(chan struct{}), } err = chain.db.View(func(tx *bolt.Tx) (err error) { meta := tx.Bucket(metaBucket[:]) + metaEnc := meta.Get(metaStateKey) + if metaEnc == nil { + return ErrMetaStateNotFound + } + state := &State{} - if err = state.deserialize(meta.Get(metaStateKey)); err != nil { + if err = utils.DecodeMsgPack(metaEnc, state); err != nil { return } chain.rt.setHead(state) @@ -203,10 +199,9 @@ func LoadChain(cfg *Config) (chain *Chain, err error) { nodes := make([]blockNode, blocks.Stats().KeyN) if err = blocks.ForEach(func(k, v []byte) (err error) { - block := &types.Block{} - - if err = block.Deserialize(v); err != nil { - log.Errorf("loadeing block: %v", err) + block := &pt.Block{} + if err = utils.DecodeMsgPack(v, block); err != nil { + log.WithError(err).Error("load block failed") return err } @@ -214,14 +209,14 @@ func LoadChain(cfg *Config) (chain *Chain, err error) { if last == nil { // TODO(lambda): check genesis block - } else if block.SignedHeader.ParentHash.IsEqual(&last.hash) { + } else if block.ParentHash().IsEqual(&last.hash) { if err = block.SignedHeader.Verify(); err != nil { return err } parent = last } else { - parent = chain.bi.lookupBlock(block.SignedHeader.BlockHash) + parent = chain.bi.lookupNode(block.ParentHash()) if parent == nil { return ErrParentNotFound @@ -229,6 +224,7 @@ func LoadChain(cfg *Config) (chain *Chain, err error) { } nodes[index].initBlockNode(block, parent) + chain.bi.addBlock(&nodes[index]) last = &nodes[index] index++ return err @@ -236,39 +232,6 @@ func LoadChain(cfg *Config) (chain *Chain, err error) { return err } - txbillings := meta.Bucket(metaTxBillingIndexBucket) - if err = txbillings.ForEach(func(k, v []byte) (err error) { - txbilling := types.TxBilling{} - err = txbilling.Deserialize(v) - if err != nil { - return - } - chain.ti.addTxBilling(&txbilling) - return - }); err != nil { - return - } - - lastTxBillings := meta.Bucket(metaLastTxBillingIndexBucket) - if err = lastTxBillings.ForEach(func(k, v []byte) (err error) { - var databaseID proto.DatabaseID - err = utils.DecodeMsgPack(k, &databaseID) - if err != nil { - return - } - - var sequenceID uint32 - err = utils.DecodeMsgPack(v, &sequenceID) - if err != nil { - return - } - - chain.ti.updateLastTxBilling(&databaseID, sequenceID) - return - }); err != nil { - return - } - // Reload state if err = chain.ms.reloadProcedure()(tx); err != nil { return @@ -283,70 +246,18 @@ func LoadChain(cfg *Config) (chain *Chain, err error) { return chain, nil } -// checkTxBilling has two steps: 1. Hash 2. Signature 3. existed tx 4. SequenceID. -func (c *Chain) checkTxBilling(tb *types.TxBilling) (err error) { - err = tb.Verify() - if err != nil { - return err - } - - if val := c.ti.getTxBilling(tb.TxHash); val == nil { - err = c.db.View(func(tx *bolt.Tx) error { - meta := tx.Bucket(metaBucket[:]) - dec := meta.Bucket(metaTxBillingIndexBucket).Get(tb.TxHash[:]) - if len(dec) != 0 { - decTx := &types.TxBilling{} - err = decTx.Deserialize(dec) - if err != nil { - return err - } - - if decTx != nil && (!decTx.SignedBlock.IsEqual(tb.SignedBlock)) { - return ErrExistedTx - } - } - return nil - }) - if err != nil { - return err - } - } else { - if val.SignedBlock != nil && (!val.SignedBlock.IsEqual(tb.SignedBlock)) { - return ErrExistedTx - } - } - - // check sequence ID to avoid double rewards and fees - databaseID := tb.GetDatabaseID() - sequenceID, err := c.ti.lastSequenceID(databaseID) - if err == nil { - if sequenceID >= tb.GetSequenceID() { - return ErrSmallerSequenceID - } - } - - return nil -} - // checkBlock has following steps: 1. check parent block 2. checkTx 2. merkle tree 3. Hash 4. Signature. -func (c *Chain) checkBlock(b *types.Block) (err error) { +func (c *Chain) checkBlock(b *pt.Block) (err error) { // TODO(lambda): process block fork - if !b.SignedHeader.ParentHash.IsEqual(c.rt.getHead().getHeader()) { + if !b.ParentHash().IsEqual(c.rt.getHead().getHeader()) { log.WithFields(log.Fields{ "head": c.rt.getHead().getHeader().String(), "height": c.rt.getHead().getHeight(), - "received_parent": b.SignedHeader.ParentHash, + "received_parent": b.ParentHash(), }).Debug("invalid parent") return ErrParentNotMatch } - // TODO(leventeliu): merge transactions checking. - for i := range b.TxBillings { - if err = c.checkTxBilling(b.TxBillings[i]); err != nil { - return err - } - } - rootHash := merkle.NewMerkle(b.GetTxHashes()).GetRoot() if !b.SignedHeader.MerkleRoot.IsEqual(rootHash) { return ErrInvalidMerkleTreeRoot @@ -357,14 +268,14 @@ func (c *Chain) checkBlock(b *types.Block) (err error) { return err } h := hash.THashH(enc) - if !b.SignedHeader.BlockHash.IsEqual(&h) { + if !b.BlockHash().IsEqual(&h) { return ErrInvalidHash } return nil } -func (c *Chain) pushBlockWithoutCheck(b *types.Block) error { +func (c *Chain) pushBlockWithoutCheck(b *pt.Block) error { h := c.rt.getHeightFromTime(b.Timestamp()) node := newBlockNode(h, b, c.rt.getHead().getNode()) state := &State{ @@ -373,22 +284,22 @@ func (c *Chain) pushBlockWithoutCheck(b *types.Block) error { Height: node.height, } - encBlock, err := b.Serialize() + encBlock, err := utils.EncodeMsgPack(b) if err != nil { return err } - encState, err := c.rt.getHead().serialize() + encState, err := utils.EncodeMsgPack(c.rt.getHead()) if err != nil { return err } err = c.db.Update(func(tx *bolt.Tx) (err error) { - err = tx.Bucket(metaBucket[:]).Put(metaStateKey, encState) + err = tx.Bucket(metaBucket[:]).Put(metaStateKey, encState.Bytes()) if err != nil { return err } - err = tx.Bucket(metaBucket[:]).Bucket(metaBlockIndexBucket).Put(node.indexKey(), encBlock) + err = tx.Bucket(metaBucket[:]).Bucket(metaBlockIndexBucket).Put(node.indexKey(), encBlock.Bytes()) if err != nil { return err } @@ -408,15 +319,15 @@ func (c *Chain) pushBlockWithoutCheck(b *types.Block) error { return nil } -func (c *Chain) pushGenesisBlock(b *types.Block) (err error) { +func (c *Chain) pushGenesisBlock(b *pt.Block) (err error) { err = c.pushBlockWithoutCheck(b) if err != nil { - log.Errorf("push genesis block failed: %v", err) + log.WithError(err).Error("push genesis block failed") } return } -func (c *Chain) pushBlock(b *types.Block) error { +func (c *Chain) pushBlock(b *pt.Block) error { err := c.checkBlock(b) if err != nil { return err @@ -427,81 +338,25 @@ func (c *Chain) pushBlock(b *types.Block) error { return err } - for i := range b.TxBillings { - err = c.pushTxBillingWithoutCheck(b.TxBillings[i]) - if err != nil { - return err - } - } - - return nil -} - -func (c *Chain) pushTxBillingWithoutCheck(tb *types.TxBilling) error { - encTx, err := tb.Serialize() - if err != nil { - return err - } - - err = c.db.Update(func(tx *bolt.Tx) error { - meta := tx.Bucket(metaBucket[:]) - err = meta.Bucket(metaTxBillingIndexBucket).Put(tb.TxHash[:], encTx) - if err != nil { - return err - } - - // if the tx is packed in some block, its nonce should be stored to ensure nonce is monotone increasing - if tb.SignedBlock != nil { - databaseID, err := utils.EncodeMsgPack(tb.GetDatabaseID()) - if err != nil { - return err - } - - sequenceID, err := utils.EncodeMsgPack(tb.GetSequenceID()) - if err != nil { - return err - } - err = meta.Bucket(metaLastTxBillingIndexBucket).Put(databaseID.Bytes(), sequenceID.Bytes()) - return err - } - return nil - }) - if err != nil { - return err - } - c.ti.addTxBilling(tb) - if tb.IsSigned() { - c.ti.updateLastTxBilling(tb.GetDatabaseID(), tb.GetSequenceID()) - } return nil } -func (c *Chain) pushTxBilling(tb *types.TxBilling) error { - err := c.checkTxBilling(tb) - if err != nil { - return err - } - - err = c.pushTxBillingWithoutCheck(tb) - return err -} - func (c *Chain) produceBlock(now time.Time) error { priv, err := kms.GetLocalPrivateKey() if err != nil { return err } - b := &types.Block{ - SignedHeader: types.SignedHeader{ - Header: types.Header{ + b := &pt.Block{ + SignedHeader: pt.SignedHeader{ + Header: pt.Header{ Version: blockVersion, Producer: c.rt.accountAddress, ParentHash: *c.rt.getHead().getHeader(), Timestamp: now, }, }, - TxBillings: c.ti.fetchUnpackedTxBillings(), + Transactions: c.ms.pullTxs(), } err = b.PackAndSignBlock(priv) @@ -509,11 +364,7 @@ func (c *Chain) produceBlock(now time.Time) error { return err } - for i := range b.TxBillings { - b.TxBillings[i].SetSignedBlock(&b.SignedHeader.BlockHash) - } - - log.Debugf("generate new block: %v", b) + log.WithField("block", b).Debug("produced new block") err = c.pushBlockWithoutCheck(b) if err != nil { @@ -527,7 +378,6 @@ func (c *Chain) produceBlock(now time.Time) error { wg.Add(1) go func(id proto.NodeID) { defer wg.Done() - method := fmt.Sprintf("%s.%s", MainChainRPCName, "AdviseNewBlock") blockReq := &AdviseNewBlockReq{ Envelope: proto.Envelope{ // TODO(lambda): Add fields. @@ -535,16 +385,19 @@ func (c *Chain) produceBlock(now time.Time) error { Block: b, } blockResp := &AdviseNewBlockResp{} - if err := c.cl.CallNode(id, method, blockReq, blockResp); err != nil { + if err := c.cl.CallNode(id, route.MCCAdviseNewBlock.String(), blockReq, blockResp); err != nil { log.WithFields(log.Fields{ "peer": c.rt.getPeerInfoString(), "curr_turn": c.rt.getNextTurn(), "now_time": time.Now().UTC().Format(time.RFC3339Nano), - "block_hash": b.SignedHeader.BlockHash, + "block_hash": b.BlockHash(), }).WithError(err).Error( - "Failed to advise new block") + "failed to advise new block") } else { - log.Debugf("Success to advising #%d height block to %s", c.rt.getHead().getHeight(), id) + log.WithFields(log.Fields{ + "height": c.rt.getHead().getHeight(), + "node": id, + }).Debug("success advising block") } }(s.ID) } @@ -553,7 +406,7 @@ func (c *Chain) produceBlock(now time.Time) error { return err } -func (c *Chain) produceTxBilling(br *types.BillingRequest) (_ *types.BillingResponse, err error) { +func (c *Chain) produceBilling(br *pt.BillingRequest) (_ *pt.BillingRequest, err error) { // TODO(lambda): simplify the function if err = c.checkBillingRequest(br); err != nil { return @@ -563,7 +416,6 @@ func (c *Chain) produceTxBilling(br *types.BillingRequest) (_ *types.BillingResp // TODO(lambda): because there is no token distribution, // we only increase miners' balance but not decrease customer's balance var ( - enc []byte accountNumber = len(br.Header.GasAmounts) receivers = make([]*proto.AccountAddress, accountNumber) fees = make([]uint64, accountNumber) @@ -572,30 +424,20 @@ func (c *Chain) produceTxBilling(br *types.BillingRequest) (_ *types.BillingResp for i, addrAndGas := range br.Header.GasAmounts { receivers[i] = &addrAndGas.AccountAddress - fees[i] = addrAndGas.GasAmount * uint64(gasprice) + fees[i] = addrAndGas.GasAmount * uint64(gasPrice) rewards[i] = 0 } - if enc, err = br.MarshalHash(); err != nil { - return - } - h := hash.THashH(enc) - - // generate response - privKey, err := kms.GetLocalPrivateKey() + // add block producer signature + var privKey *asymmetric.PrivateKey + privKey, err = kms.GetLocalPrivateKey() if err != nil { return } - sign, err := privKey.Sign(h[:]) - if err != nil { + + if _, _, err = br.SignRequestHeader(privKey, false); err != nil { return } - resp := &types.BillingResponse{ - AccountAddress: accountAddress, - RequestHash: h, - Signee: privKey.PubKey(), - Signature: sign, - } // generate and push the txbilling // 1. generate txbilling @@ -604,98 +446,70 @@ func (c *Chain) produceTxBilling(br *types.BillingRequest) (_ *types.BillingResp return } var ( - tc = types.NewTxContent(uint32(nc), br, receivers, fees, rewards, resp) - tb = types.NewTxBilling(tc, types.TxTypeBilling, &c.rt.accountAddress) + tc = pt.NewBillingHeader(nc, br, accountAddress, receivers, fees, rewards) + tb = pt.NewBilling(tc) ) if err = tb.Sign(privKey); err != nil { return } - log.Debugf("response is %s", resp.RequestHash) + log.WithField("billingRequestHash", br.RequestHash).Debug("generated billing transaction") // 2. push tx c.pendingTxs <- tb - tbReq := &AdviseTxBillingReq{ - Envelope: proto.Envelope{ - // TODO(lambda): Add fields. - }, - TxBilling: tb, - } - method := fmt.Sprintf("%s.%s", MainChainRPCName, "AdviseTxBilling") - peers := c.rt.getPeers() - wg := &sync.WaitGroup{} - for _, s := range peers.Servers { - if !s.ID.IsEqual(&c.rt.nodeID) { - wg.Add(1) - go func(id proto.NodeID) { - defer wg.Done() - tbResp := &AdviseTxBillingResp{} - if err := c.cl.CallNode(id, method, tbReq, tbResp); err != nil { - log.WithFields(log.Fields{ - "peer": c.rt.getPeerInfoString(), - "curr_turn": c.rt.getNextTurn(), - "now_time": time.Now().UTC().Format(time.RFC3339Nano), - "tx_hash": tb.TxHash, - }).WithError(err).Error( - "Failed to advise new block") - } - }(s.ID) - } - } - wg.Wait() - return resp, nil + return br, nil } // checkBillingRequest checks followings by order: // 1. period of sqlchain; // 2. request's hash // 3. miners' signatures. -func (c *Chain) checkBillingRequest(br *types.BillingRequest) error { +func (c *Chain) checkBillingRequest(br *pt.BillingRequest) (err error) { // period of sqlchain; // TODO(lambda): get and check period and miner list of specific sqlchain - // request's hash - enc, err := br.Header.MarshalHash() - if err != nil { - return err - } - h := hash.THashH(enc[:]) - if !h.IsEqual(&br.RequestHash) { - return ErrInvalidHash - } + err = br.VerifySignatures() + return +} - // miners' signatures - sLen := len(br.Signees) - if sLen != len(br.Signatures) { - return ErrInvalidBillingRequest +func (c *Chain) fetchBlockByHeight(h uint32) (b *pt.Block, count uint32, err error) { + node := c.rt.getHead().getNode().ancestor(h) + if node == nil { + return nil, 0, ErrNoSuchBlock } - for i := range br.Signees { - if !br.Signatures[i].Verify(h[:], br.Signees[i]) { - return ErrSignVerification - } + + b = &pt.Block{} + k := node.indexKey() + + err = c.db.View(func(tx *bolt.Tx) error { + v := tx.Bucket(metaBucket[:]).Bucket(metaBlockIndexBucket).Get(k) + return utils.DecodeMsgPack(v, b) + }) + if err != nil { + return nil, 0, err } - return nil + return b, node.count, nil } -func (c *Chain) fetchBlockByHeight(h uint32) (*types.Block, error) { - node := c.rt.getHead().getNode().ancestor(h) +func (c *Chain) fetchBlockByCount(count uint32) (b *pt.Block, height uint32, err error) { + node := c.rt.getHead().getNode().ancestorByCount(count) if node == nil { - return nil, ErrNoSuchBlock + return nil, 0, ErrNoSuchBlock } - b := &types.Block{} + b = &pt.Block{} k := node.indexKey() - err := c.db.View(func(tx *bolt.Tx) error { + err = c.db.View(func(tx *bolt.Tx) error { v := tx.Bucket(metaBucket[:]).Bucket(metaBlockIndexBucket).Get(k) - return b.Deserialize(v) + return utils.DecodeMsgPack(v, b) }) if err != nil { - return nil, err + return nil, 0, err } - return b, nil + return b, node.height, nil } // runCurrentTurn does the check and runs block producing if its my turn. @@ -711,10 +525,10 @@ func (c *Chain) runCurrentTurn(now time.Time) { return } - log.Infof("produce a new block with height %d", c.rt.getNextTurn()) + log.WithField("height", c.rt.getNextTurn()).Info("producing a new block") if err := c.produceBlock(now); err != nil { log.WithField("now", now.Format(time.RFC3339Nano)).WithError(err).Errorln( - "Failed to produce block") + "failed to produce block") } } @@ -722,15 +536,21 @@ func (c *Chain) runCurrentTurn(now time.Time) { func (c *Chain) sync() error { log.WithFields(log.Fields{ "peer": c.rt.getPeerInfoString(), - }).Debug("Synchronizing chain state") + }).Debug("synchronizing chain state") for { now := c.rt.now() height := c.rt.getHeightFromTime(now) - log.Infof("current height is %d, next turn is %d", height, c.rt.getNextTurn()) + log.WithFields(log.Fields{ + "height": height, + "nextTurn": c.rt.getNextTurn(), + }).Info("try sync heights") if c.rt.getNextTurn() >= height { - log.Infof("return with height %d, next turn is %d", height, c.rt.getNextTurn()) + log.WithFields(log.Fields{ + "height": height, + "nextTurn": c.rt.getNextTurn(), + }).Info("return heights") break } @@ -769,7 +589,7 @@ func (c *Chain) Start() error { func (c *Chain) processBlocks() { rsCh := make(chan struct{}) rsWG := &sync.WaitGroup{} - returnStash := func(stash []*types.Block) { + returnStash := func(stash []*pt.Block) { defer rsWG.Done() for _, block := range stash { select { @@ -786,7 +606,7 @@ func (c *Chain) processBlocks() { c.rt.wg.Done() }() - var stash []*types.Block + var stash []*pt.Block for { select { case block := <-c.blocksFromSelf: @@ -801,7 +621,7 @@ func (c *Chain) processBlocks() { if h := c.rt.getHeightFromTime(block.Timestamp()); h > c.rt.getNextTurn()-1 { // Stash newer blocks for later check if stash == nil { - stash = make([]*types.Block, 0) + stash = make([]*pt.Block, 0) } stash = append(stash, block) } else { @@ -885,12 +705,11 @@ func (c *Chain) mainCycle() { func (c *Chain) syncHead() { // Try to fetch if the the block of the current turn is not advised yet - log.WithFields(log.Fields{ - "index": c.rt.index, - "next_turn": c.rt.getNextTurn(), - "height": c.rt.getHead().getHeight(), - "count": c.rt.getHead().getNode().count, - }).Debugf("sync header") + //log.WithFields(log.Fields{ + // "index": c.rt.index, + // "next_turn": c.rt.getNextTurn(), + // "height": c.rt.getHead().getHeight(), + //}).Debug("sync header") if h := c.rt.getNextTurn() - 1; c.rt.getHead().getHeight() < h { var err error req := &FetchBlockReq{ @@ -900,13 +719,12 @@ func (c *Chain) syncHead() { Height: h, } resp := &FetchBlockResp{} - method := fmt.Sprintf("%s.%s", MainChainRPCName, "FetchBlock") peers := c.rt.getPeers() succ := false for i, s := range peers.Servers { if !s.ID.IsEqual(&c.rt.nodeID) { - err = c.cl.CallNode(s.ID, method, req, resp) + err = c.cl.CallNode(s.ID, route.MCCFetchBlock.String(), req, resp) if err != nil || resp.Block == nil { log.WithFields(log.Fields{ "peer": c.rt.getPeerInfoString(), diff --git a/blockproducer/chain_test.go b/blockproducer/chain_test.go index 307518889..450a4f4cd 100644 --- a/blockproducer/chain_test.go +++ b/blockproducer/chain_test.go @@ -17,18 +17,20 @@ package blockproducer import ( - "fmt" "io/ioutil" + "os" "sync" "testing" "time" - "github.com/CovenantSQL/CovenantSQL/blockproducer/types" - "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" + pi "github.com/CovenantSQL/CovenantSQL/blockproducer/interfaces" + pt "github.com/CovenantSQL/CovenantSQL/blockproducer/types" "github.com/CovenantSQL/CovenantSQL/crypto/kms" "github.com/CovenantSQL/CovenantSQL/kayak" "github.com/CovenantSQL/CovenantSQL/pow/cpuminer" "github.com/CovenantSQL/CovenantSQL/proto" + "github.com/CovenantSQL/CovenantSQL/route" + ct "github.com/CovenantSQL/CovenantSQL/sqlchain/types" "github.com/CovenantSQL/CovenantSQL/utils/log" . "github.com/smartystreets/goconvey/convey" ) @@ -41,14 +43,9 @@ var ( testClientNumberPerChain = 10 ) -type nodeProfile struct { - NodeID proto.NodeID - PrivateKey *asymmetric.PrivateKey - PublicKey *asymmetric.PublicKey -} - func TestChain(t *testing.T) { Convey("test main chain", t, func() { + log.SetLevel(log.InfoLevel) confDir := "../test/mainchain/node_standalone/config.yaml" privDir := "../test/mainchain/node_standalone/private.key" cleanup, _, _, rpcServer, err := initNode( @@ -62,6 +59,7 @@ func TestChain(t *testing.T) { So(err, ShouldBeNil) fl.Close() + os.Remove(fl.Name()) // create genesis block genesis, err := generateRandomBlock(genesisHash, true) @@ -77,7 +75,7 @@ func TestChain(t *testing.T) { ao, ok := chain.ms.readonly.accounts[testAddress1] So(ok, ShouldBeTrue) So(ao, ShouldNotBeNil) - So(chain.ms.pool.entries[testAddress1].transacions, ShouldBeEmpty) + So(chain.ms.pool.entries[testAddress1].transactions, ShouldBeEmpty) So(chain.ms.pool.entries[testAddress1].baseNonce, ShouldEqual, 1) var ( bl uint64 @@ -96,7 +94,7 @@ func TestChain(t *testing.T) { So(loaded, ShouldBeTrue) So(bl, ShouldEqual, testInitBalance) - // Hack for signle instance test + // Hack for single instance test chain.rt.bpNum = 5 for { @@ -108,46 +106,56 @@ func TestChain(t *testing.T) { chain.rt.isMyTurn()) // chain will receive blocks and tx - // receive block // generate valid txbillings - tbs := make([]*types.TxBilling, 10) - for i := range tbs { - tb, err := generateRandomTxBillingWithSeqID(0) + tbs := make([]pi.Transaction, 0, 20) + + // pull previous processed transactions + tbs = append(tbs, chain.ms.pullTxs()...) + + for i := 0; i != 10; i++ { + tb, err := generateRandomAccountBilling() So(err, ShouldBeNil) - tbs[i] = tb + tbs = append(tbs, tb) } // generate block - block, err := generateRandomBlockWithTxBillings(*chain.rt.getHead().getHeader(), tbs) + block, err := generateRandomBlockWithTransactions(*chain.rt.getHead().getHeader(), tbs) So(err, ShouldBeNil) err = chain.pushBlock(block) So(err, ShouldBeNil) + nextNonce, err := chain.ms.nextNonce(testAddress1) + So(err, ShouldBeNil) for _, val := range tbs { - So(chain.ti.hasTxBilling(val.TxHash), ShouldBeTrue) + // should be packed + So(nextNonce >= val.GetAccountNonce(), ShouldBeTrue) } So(chain.bi.hasBlock(block.SignedHeader.BlockHash), ShouldBeTrue) // So(chain.rt.getHead().Height, ShouldEqual, height) height := chain.rt.getHead().getHeight() - specificHeightBlock1, err := chain.fetchBlockByHeight(height) + specificHeightBlock1, _, err := chain.fetchBlockByHeight(height) So(err, ShouldBeNil) So(block.SignedHeader.BlockHash, ShouldResemble, specificHeightBlock1.SignedHeader.BlockHash) - specificHeightBlock2, err := chain.fetchBlockByHeight(height + 1000) + specificHeightBlock2, _, err := chain.fetchBlockByHeight(height + 1000) So(specificHeightBlock2, ShouldBeNil) So(err, ShouldNotBeNil) - // receive txes - receivedTbs := make([]*types.TxBilling, 9) + // receive txs + receivedTbs := make([]*pt.Billing, 9) for i := range receivedTbs { - tb, err := generateRandomTxBillingWithSeqID(0) + tb, err := generateRandomAccountBilling() So(err, ShouldBeNil) receivedTbs[i] = tb - chain.pushTxBilling(tb) + err = chain.processTx(tb) + So(err, ShouldBeNil) } + nextNonce, err = chain.ms.nextNonce(testAddress1) + for _, val := range receivedTbs { - So(chain.ti.hasTxBilling(val.TxHash), ShouldBeTrue) + // should be packed or unpacked + So(chain.ms.pool.hasTx(val), ShouldBeTrue) } // So(height, ShouldEqual, chain.rt.getHead().Height) @@ -155,8 +163,8 @@ func TestChain(t *testing.T) { t.Logf("Pushed new block: height = %d, %s <- %s", chain.rt.getHead().getHeight(), - block.SignedHeader.ParentHash, - block.SignedHeader.BlockHash) + block.ParentHash(), + block.BlockHash()) if chain.rt.getHead().getHeight() >= testPeriodNumber { break @@ -197,6 +205,8 @@ func TestMultiNode(t *testing.T) { // create tmp file fl, err := ioutil.TempFile("", "mainchain") So(err, ShouldBeNil) + fl.Close() + os.Remove(fl.Name()) // init config cleanup, dht, _, server, err := initNode(configs[i], privateKeys[i]) @@ -237,7 +247,7 @@ func TestMultiNode(t *testing.T) { } var resp proto.PingResp dht.Ping(&req, &resp) - log.Debugf("ping response: %v", resp) + log.WithField("resp", resp).Debug("got ping response") err = chains[i].Start() So(err, ShouldBeNil) @@ -264,16 +274,18 @@ func TestMultiNode(t *testing.T) { br, err := generateRandomBillingRequest() c.So(err, ShouldBeNil) - bReq := &AdviseBillingReq{ + bReq := &ct.AdviseBillingReq{ Envelope: proto.Envelope{ // TODO(lambda): Add fields. }, Req: br, } - bResp := &AdviseBillingResp{} - method := fmt.Sprintf("%s.%s", MainChainRPCName, "AdviseBillingRequest") - log.Debugf("CallNode %d hash is %s", val, br.RequestHash) - err = chains[i].cl.CallNode(chains[i].rt.nodeID, method, bReq, bResp) + bResp := &ct.AdviseBillingResp{} + log.WithFields(log.Fields{ + "node": val, + "requestHash": br.RequestHash, + }).Debug("advising billing request") + err = chains[i].cl.CallNode(chains[i].rt.nodeID, route.MCCAdviseBillingRequest.String(), bReq, bResp) if err != nil { log.WithFields(log.Fields{ "peer": chains[i].rt.getPeerInfoString(), diff --git a/blockproducer/db_service.go b/blockproducer/db_service.go index feadfc058..511227bc3 100644 --- a/blockproducer/db_service.go +++ b/blockproducer/db_service.go @@ -40,8 +40,6 @@ import ( const ( // DefaultAllocationRounds defines max rounds to try allocate peers for database creation. DefaultAllocationRounds = 3 - // DBServiceName for block producer to provide database management related logic. - DBServiceName = "BPDB" ) var ( @@ -78,24 +76,37 @@ func (s *DBService) CreateDatabase(req *CreateDatabaseRequest, resp *CreateDatab // TODO(xq262144): verify identity // verify identity + defer func() { + log.WithFields(log.Fields{ + "meta": req.Header.ResourceMeta, + "node": req.GetNodeID().String(), + }).WithError(err).Debug("create database") + }() + // create random DatabaseID var dbID proto.DatabaseID if dbID, err = s.generateDatabaseID(req.GetNodeID()); err != nil { return } + log.WithField("db", dbID).Debug("generated database id") + // allocate nodes var peers *kayak.Peers if peers, err = s.allocateNodes(0, dbID, req.Header.ResourceMeta); err != nil { return } + log.WithField("peers", peers).Debug("generated peers info") + // TODO(lambda): call accounting features, top up deposit var genesisBlock *ct.Block if genesisBlock, err = s.generateGenesisBlock(dbID, req.Header.ResourceMeta); err != nil { return } + log.WithField("block", genesisBlock).Debug("generated genesis block") + defer func() { if err != nil { // TODO(lambda): release deposit on error @@ -104,11 +115,6 @@ func (s *DBService) CreateDatabase(req *CreateDatabaseRequest, resp *CreateDatab // call miner nodes to provide service var privateKey *asymmetric.PrivateKey - var pubKey *asymmetric.PublicKey - - if pubKey, err = kms.GetLocalPublicKey(); err != nil { - return - } if privateKey, err = kms.GetLocalPrivateKey(); err != nil { return } @@ -120,7 +126,6 @@ func (s *DBService) CreateDatabase(req *CreateDatabaseRequest, resp *CreateDatab Peers: peers, GenesisBlock: genesisBlock, } - initSvcReq.Header.Signee = pubKey if err = initSvcReq.Sign(privateKey); err != nil { return } @@ -130,7 +135,6 @@ func (s *DBService) CreateDatabase(req *CreateDatabaseRequest, resp *CreateDatab rollbackReq.Header.Instance = wt.ServiceInstance{ DatabaseID: dbID, } - rollbackReq.Header.Signee = pubKey if err = rollbackReq.Sign(privateKey); err != nil { return } @@ -147,7 +151,7 @@ func (s *DBService) CreateDatabase(req *CreateDatabaseRequest, resp *CreateDatab GenesisBlock: genesisBlock, } - log.Debugf("generated instance meta: %v", instanceMeta) + log.WithField("meta", instanceMeta).Debug("generated instance meta") if err = s.ServiceMap.Set(instanceMeta); err != nil { // critical error @@ -157,7 +161,6 @@ func (s *DBService) CreateDatabase(req *CreateDatabaseRequest, resp *CreateDatab // send response to client resp.Header.InstanceMeta = instanceMeta - resp.Header.Signee = pubKey // sign the response err = resp.Sign(privateKey) @@ -175,6 +178,13 @@ func (s *DBService) DropDatabase(req *DropDatabaseRequest, resp *DropDatabaseRes // TODO(xq262144): verify identity // verify identity and database belonging + defer func() { + log.WithFields(log.Fields{ + "db": req.Header.DatabaseID, + "node": req.GetNodeID().String(), + }).Debug("drop database") + }() + // get database peers var instanceMeta wt.ServiceInstance if instanceMeta, err = s.ServiceMap.Get(req.Header.DatabaseID); err != nil { @@ -228,6 +238,13 @@ func (s *DBService) GetDatabase(req *GetDatabaseRequest, resp *GetDatabaseRespon // TODO(xq262144): verify identity // verify identity and database belonging + defer func() { + log.WithFields(log.Fields{ + "db": req.Header.DatabaseID, + "node": req.GetNodeID().String(), + }).Debug("get database") + }() + // fetch from meta var instanceMeta wt.ServiceInstance if instanceMeta, err = s.ServiceMap.Get(req.Header.DatabaseID); err != nil { @@ -259,13 +276,13 @@ func (s *DBService) GetNodeDatabases(req *wt.InitService, resp *wt.InitServiceRe return } - log.Debugf("current instance for node %v: %v", req.GetNodeID().ToNodeID(), instances) + log.WithFields(log.Fields{ + "node": req.GetNodeID().String(), + "databases": instances, + }).Debug("get node databases") // send response to client resp.Header.Instances = instances - if resp.Header.Signee, err = kms.GetLocalPublicKey(); err != nil { - return - } var privateKey *asymmetric.PrivateKey if privateKey, err = kms.GetLocalPrivateKey(); err != nil { return @@ -297,7 +314,7 @@ func (s *DBService) generateDatabaseID(reqNodeID *proto.RawNodeID) (dbID proto.D startNonce.Inc() dbID = proto.DatabaseID(nonce.Hash.String()) - log.Debugf("try generated database id %v", dbID) + log.WithField("db", dbID).Debug("try generate database id") // check existence if _, err = s.ServiceMap.Get(dbID); err == ErrNoSuchDatabase { @@ -312,6 +329,14 @@ func (s *DBService) allocateNodes(lastTerm uint64, dbID proto.DatabaseID, resour excludeNodes := make(map[proto.NodeID]bool) var allocated []allocatedNode + defer func() { + log.WithFields(log.Fields{ + "db": dbID, + "meta": resourceMeta, + "peers": peers, + }).WithError(err).Debug("try allocated nodes") + }() + if resourceMeta.Node <= 0 { err = ErrDatabaseAllocation return @@ -325,7 +350,7 @@ func (s *DBService) allocateNodes(lastTerm uint64, dbID proto.DatabaseID, resour } for i := 0; i != s.AllocationRounds; i++ { - log.Debugf("node allocation round %d", i+1) + log.WithField("round", i).Debug("try allocation node") var nodes []proto.Node @@ -341,7 +366,7 @@ func (s *DBService) allocateNodes(lastTerm uint64, dbID proto.DatabaseID, resour nodes, err = s.Consistent.GetNeighborsEx(string(dbID), curRange, proto.ServerRoles(rolesFilter)) - log.Debugf("found %d neighbor nodes", len(nodes)) + log.WithField("nodeCount", len(nodes)).Debug("found nodes to try dispatch") // TODO(xq262144): brute force implementation to be optimized var nodeIDs []proto.NodeID @@ -352,7 +377,11 @@ func (s *DBService) allocateNodes(lastTerm uint64, dbID proto.DatabaseID, resour } } - log.Debugf("found %d suitable nodes: %v", len(nodeIDs), nodeIDs) + log.WithFields(log.Fields{ + "nodeCount": len(nodeIDs), + "totalCount": len(nodes), + "nodes": nodeIDs, + }).Debug("found nodes to dispatch") if len(nodeIDs) < int(resourceMeta.Node) { continue @@ -361,15 +390,19 @@ func (s *DBService) allocateNodes(lastTerm uint64, dbID proto.DatabaseID, resour // check node resource status metrics := s.NodeMetrics.GetMetrics(nodeIDs) - log.Debugf("get %d metric records for %d nodes", len(metrics), len(nodeIDs)) + log.WithFields(log.Fields{ + "recordCount": len(metrics), + "nodeCount": len(nodeIDs), + }).Debug("found metric records to dispatch") for nodeID, nodeMetric := range metrics { - log.Debugf("parse metric of node %v", nodeID) + log.WithField("node", nodeID).Debug("parse metric") + var metricValue uint64 // get metric if metricValue, err = s.getMetric(nodeMetric, MetricKeyFreeMemory); err != nil { - log.Debugf("get node %s memory metric failed", nodeID) + log.WithField("node", nodeID).Debug("get memory metric failed") // add to excludes excludeNodes[nodeID] = true @@ -386,7 +419,11 @@ func (s *DBService) allocateNodes(lastTerm uint64, dbID proto.DatabaseID, resour MemoryMetric: metricValue, }) } else { - log.Debugf("node %s memory metric does not meet requirements", nodeID) + log.WithFields(log.Fields{ + "actual": metricValue, + "expected": resourceMeta.Memory, + "node": nodeID, + }).Debug("node memory node meets requirement") excludeNodes[nodeID] = true } } @@ -443,7 +480,11 @@ func (s *DBService) getMetric(metric metric.MetricMap, keys []string) (value uin } func (s *DBService) buildPeers(term uint64, nodes []proto.Node, allocated []proto.NodeID) (peers *kayak.Peers, err error) { - log.Debugf("build peers for allocated nodes with term: %v, allocated nodes: %v", term, allocated) + log.WithFields(log.Fields{ + "term": term, + "nodes": allocated, + }).Debug("build peers for term/nodes") + // get local private key var pubKey *asymmetric.PublicKey if pubKey, err = kms.GetLocalPublicKey(); err != nil { @@ -498,10 +539,6 @@ func (s *DBService) generateGenesisBlock(dbID proto.DatabaseID, resourceMeta wt. // TODO(xq262144): following is stub code, real logic should be implemented in the future emptyHash := hash.Hash{} - var pubKey *asymmetric.PublicKey - if pubKey, err = kms.GetLocalPublicKey(); err != nil { - return - } var privKey *asymmetric.PrivateKey if privKey, err = kms.GetLocalPrivateKey(); err != nil { return @@ -520,8 +557,6 @@ func (s *DBService) generateGenesisBlock(dbID proto.DatabaseID, resourceMeta wt. ParentHash: emptyHash, Timestamp: time.Now().UTC(), }, - Signee: pubKey, - Signature: nil, }, } err = genesisBlock.PackAndSignBlock(privKey) diff --git a/blockproducer/db_service_test.go b/blockproducer/db_service_test.go index a06ed73bc..da00e68ba 100644 --- a/blockproducer/db_service_test.go +++ b/blockproducer/db_service_test.go @@ -46,10 +46,6 @@ func TestService(t *testing.T) { defer cleanup() // get keys - var pubKey *asymmetric.PublicKey - pubKey, err = kms.GetLocalPublicKey() - So(err, ShouldBeNil) - var privateKey *asymmetric.PrivateKey privateKey, err = kms.GetLocalPrivateKey() So(err, ShouldBeNil) @@ -66,7 +62,7 @@ func TestService(t *testing.T) { } // register BPDB service to rpc - err = server.RegisterService(DBServiceName, dbService) + err = server.RegisterService(route.BPDBRPCName, dbService) So(err, ShouldBeNil) // get database @@ -77,7 +73,6 @@ func TestService(t *testing.T) { // test get database getReq := new(GetDatabaseRequest) getReq.Header.DatabaseID = proto.DatabaseID("db") - getReq.Header.Signee = pubKey err = getReq.Sign(privateKey) So(err, ShouldBeNil) @@ -101,7 +96,6 @@ func TestService(t *testing.T) { createDBReq.Header.ResourceMeta = wt.ResourceMeta{ Node: 1, } - createDBReq.Header.Signee = pubKey err = createDBReq.Sign(privateKey) So(err, ShouldBeNil) createDBRes := new(CreateDatabaseResponse) @@ -166,7 +160,6 @@ func TestService(t *testing.T) { // drop database dropDBReq := new(DropDatabaseRequest) dropDBReq.Header.DatabaseID = createDBRes.Header.InstanceMeta.DatabaseID - dropDBReq.Header.Signee = pubKey err = dropDBReq.Sign(privateKey) So(err, ShouldBeNil) dropDBRes := new(DropDatabaseResponse) @@ -176,7 +169,6 @@ func TestService(t *testing.T) { // get this database again to test if it is dropped getReq = new(GetDatabaseRequest) getReq.Header.DatabaseID = createDBRes.Header.InstanceMeta.DatabaseID - getReq.Header.Signee = pubKey err = getReq.Sign(privateKey) So(err, ShouldBeNil) err = rpc.NewCaller().CallNode(nodeID, route.BPDBGetDatabase.String(), getReq, getRes) @@ -191,12 +183,8 @@ func buildQuery(queryType wt.QueryType, connID uint64, seqNo uint64, databaseID return } - // get private/public key - var pubKey *asymmetric.PublicKey + // get private key var privateKey *asymmetric.PrivateKey - if pubKey, err = kms.GetLocalPublicKey(); err != nil { - return - } if privateKey, err = kms.GetLocalPrivateKey(); err != nil { return } @@ -220,7 +208,6 @@ func buildQuery(queryType wt.QueryType, connID uint64, seqNo uint64, databaseID SeqNo: seqNo, Timestamp: tm, }, - Signee: pubKey, }, Payload: wt.RequestPayload{ Queries: realQueries, diff --git a/blockproducer/db_service_types.go b/blockproducer/db_service_types.go index 7797dff6c..6edac9581 100644 --- a/blockproducer/db_service_types.go +++ b/blockproducer/db_service_types.go @@ -65,6 +65,7 @@ func (sh *SignedCreateDatabaseRequestHeader) Sign(signer *asymmetric.PrivateKey) // sign sh.Signature, err = signer.Sign(sh.HeaderHash[:]) + sh.Signee = signer.PubKey() return } @@ -128,6 +129,7 @@ func (sh *SignedCreateDatabaseResponseHeader) Sign(signer *asymmetric.PrivateKey // sign sh.Signature, err = signer.Sign(sh.HeaderHash[:]) + sh.Signee = signer.PubKey() return } @@ -191,6 +193,7 @@ func (sh *SignedDropDatabaseRequestHeader) Sign(signer *asymmetric.PrivateKey) ( // sign sh.Signature, err = signer.Sign(sh.HeaderHash[:]) + sh.Signee = signer.PubKey() return } @@ -256,6 +259,7 @@ func (sh *SignedGetDatabaseRequestHeader) Sign(signer *asymmetric.PrivateKey) (e // sign sh.Signature, err = signer.Sign(sh.HeaderHash[:]) + sh.Signee = signer.PubKey() return } @@ -318,6 +322,7 @@ func (sh *SignedGetDatabaseResponseHeader) Sign(signer *asymmetric.PrivateKey) ( // sign sh.Signature, err = signer.Sign(sh.HeaderHash[:]) + sh.Signee = signer.PubKey() return } diff --git a/blockproducer/errors.go b/blockproducer/errors.go index 507ebf263..53e845bab 100644 --- a/blockproducer/errors.go +++ b/blockproducer/errors.go @@ -74,4 +74,6 @@ var ( ErrUnknownTransactionType = errors.New("unknown transaction type") // ErrTransactionMismatch indicates that transactions to be committed mismatch the pool. ErrTransactionMismatch = errors.New("transaction mismatch") + // ErrMetaStateNotFound indicates that meta state not found in db. + ErrMetaStateNotFound = errors.New("meta state not found in db") ) diff --git a/blockproducer/helper_test.go b/blockproducer/helper_test.go index 2a8d42fb8..ccc5d7efa 100644 --- a/blockproducer/helper_test.go +++ b/blockproducer/helper_test.go @@ -29,7 +29,6 @@ import ( "time" "github.com/CovenantSQL/CovenantSQL/conf" - "github.com/CovenantSQL/CovenantSQL/consistent" "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" "github.com/CovenantSQL/CovenantSQL/crypto/hash" @@ -76,8 +75,6 @@ func createRandomBlock(parent hash.Hash, isGenesis bool) (b *ct.Block, err error ParentHash: parent, Timestamp: time.Now().UTC(), }, - Signee: pub, - Signature: nil, }, Queries: make([]*hash.Hash, rand.Intn(10)+10), } @@ -187,7 +184,7 @@ func initNode(confRP, privateKeyRP string) (cleanupFunc func(), dht *route.DHTSe if d, err = ioutil.TempDir("", "db_test_"); err != nil { return } - log.Debugf("temp dir: %s", d) + log.WithField("d", d).Debug("created temp dir") // init conf _, testFile, _, _ := runtime.Caller(0) @@ -215,14 +212,14 @@ func initNode(confRP, privateKeyRP string) (cleanupFunc func(), dht *route.DHTSe } // init rpc - if server, err = rpc.NewServerWithService(rpc.ServiceMap{"DHT": dht}); err != nil { + if server, err = rpc.NewServerWithService(rpc.ServiceMap{route.DHTRPCName: dht}); err != nil { return } // register metric service metricService = metric.NewCollectServer() if err = server.RegisterService(metric.MetricServiceName, metricService); err != nil { - log.Errorf("init metric service failed: %v", err) + log.WithError(err).Error("init metric service failed") return } diff --git a/blockproducer/interfaces/mixins.go b/blockproducer/interfaces/mixins.go new file mode 100644 index 000000000..26cce6346 --- /dev/null +++ b/blockproducer/interfaces/mixins.go @@ -0,0 +1,46 @@ +/* + * Copyright 2018 The CovenantSQL Authors. + * + * 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. + */ + +package interfaces + +//go:generate hsp + +// TransactionTypeMixin provide type heuristic features to transaction wrapper. +type TransactionTypeMixin struct { + TxType TransactionType +} + +// ContainsTransactionTypeMixin interface defines interface to detect transaction type mixin. +type ContainsTransactionTypeMixin interface { + SetTransactionType(TransactionType) +} + +// GetTransactionType implements Transaction.GetTransactionType. +func (m *TransactionTypeMixin) GetTransactionType() TransactionType { + return m.TxType +} + +// SetTransactionType is a helper function for derived types. +func (m *TransactionTypeMixin) SetTransactionType(t TransactionType) { + m.TxType = t +} + +// NewTransactionTypeMixin returns new instance. +func NewTransactionTypeMixin(txType TransactionType) *TransactionTypeMixin { + return &TransactionTypeMixin{ + TxType: txType, + } +} diff --git a/blockproducer/types/tx_gen.go b/blockproducer/interfaces/mixins_gen.go similarity index 50% rename from blockproducer/types/tx_gen.go rename to blockproducer/interfaces/mixins_gen.go index 46dfae05c..a3fb205a9 100644 --- a/blockproducer/types/tx_gen.go +++ b/blockproducer/interfaces/mixins_gen.go @@ -1,4 +1,4 @@ -package types +package interfaces // Code generated by github.com/CovenantSQL/HashStablePack DO NOT EDIT. @@ -7,15 +7,21 @@ import ( ) // MarshalHash marshals for hash -func (z TxType) MarshalHash() (o []byte, err error) { +func (z *TransactionTypeMixin) MarshalHash() (o []byte, err error) { var b []byte o = hsp.Require(b, z.Msgsize()) - o = hsp.AppendByte(o, byte(z)) + // map header, size 1 + o = append(o, 0x81, 0x81) + if oTemp, err := z.TxType.MarshalHash(); err != nil { + return nil, err + } else { + o = hsp.AppendBytes(o, oTemp) + } return } // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message -func (z TxType) Msgsize() (s int) { - s = hsp.ByteSize +func (z *TransactionTypeMixin) Msgsize() (s int) { + s = 1 + 7 + z.TxType.Msgsize() return } diff --git a/blockproducer/interfaces/mixins_gen_test.go b/blockproducer/interfaces/mixins_gen_test.go new file mode 100644 index 000000000..eb3a35968 --- /dev/null +++ b/blockproducer/interfaces/mixins_gen_test.go @@ -0,0 +1,47 @@ +package interfaces + +// Code generated by github.com/CovenantSQL/HashStablePack DO NOT EDIT. + +import ( + "bytes" + "crypto/rand" + "encoding/binary" + "testing" +) + +func TestMarshalHashTransactionTypeMixin(t *testing.T) { + v := TransactionTypeMixin{} + binary.Read(rand.Reader, binary.BigEndian, &v) + bts1, err := v.MarshalHash() + if err != nil { + t.Fatal(err) + } + bts2, err := v.MarshalHash() + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(bts1, bts2) { + t.Fatal("hash not stable") + } +} + +func BenchmarkMarshalHashTransactionTypeMixin(b *testing.B) { + v := TransactionTypeMixin{} + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + v.MarshalHash() + } +} + +func BenchmarkAppendMsgTransactionTypeMixin(b *testing.B) { + v := TransactionTypeMixin{} + bts := make([]byte, 0, v.Msgsize()) + bts, _ = v.MarshalHash() + b.SetBytes(int64(len(bts))) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + bts, _ = v.MarshalHash() + } +} diff --git a/blockproducer/interfaces/transaction.go b/blockproducer/interfaces/transaction.go index df2497378..f4916ac80 100644 --- a/blockproducer/interfaces/transaction.go +++ b/blockproducer/interfaces/transaction.go @@ -61,32 +61,46 @@ const ( TransactionTypeDeleteDatabaseUser // TransactionTypeBaseAccount defines base account transaction type. TransactionTypeBaseAccount - // TransactionTypeCreataDatabase defines database creation transaction type. - TransactionTypeCreataDatabase + // TransactionTypeCreateDatabase defines database creation transaction type. + TransactionTypeCreateDatabase // TransactionTypeNumber defines transaction types number. TransactionTypeNumber ) -// Serializer is the interface implemented by an object that can serialize itself into binary form. -type Serializer interface { - Serialize() ([]byte, error) -} - -// Deserializer is the interface implemented by an object that can deserialize a binary -// representation of itself. -type Deserializer interface { - Deserialize(enc []byte) error +func (t TransactionType) String() string { + switch t { + case TransactionTypeBilling: + return "Billing" + case TransactionTypeTransfer: + return "Transfer" + case TransactionTypeCreateAccount: + return "CreateAccount" + case TransactionTypeDeleteAccount: + return "DeleteAccount" + case TransactionTypeAddDatabaseUser: + return "AddDatabaseUser" + case TransactionTypeAlterDatabaseUser: + return "AlterDatabaseUser" + case TransactionTypeDeleteDatabaseUser: + return "DeleteDatabaseUser" + case TransactionTypeBaseAccount: + return "BaseAccount" + case TransactionTypeCreateDatabase: + return "CreateDatabase" + default: + return "Unknown" + } } // Transaction is the interface implemented by an object that can be verified and processed by // block producers. type Transaction interface { - Serializer - Deserializer GetAccountAddress() proto.AccountAddress GetAccountNonce() AccountNonce GetHash() hash.Hash GetTransactionType() TransactionType Sign(signer *asymmetric.PrivateKey) error Verify() error + MarshalHash() ([]byte, error) + Msgsize() int } diff --git a/blockproducer/interfaces/transaction_wrapper.go b/blockproducer/interfaces/transaction_wrapper.go new file mode 100644 index 000000000..37948aa38 --- /dev/null +++ b/blockproducer/interfaces/transaction_wrapper.go @@ -0,0 +1,244 @@ +/* + * Copyright 2018 The CovenantSQL Authors. + * + * 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. + */ + +package interfaces + +import ( + "reflect" + "sync" + + "github.com/CovenantSQL/CovenantSQL/utils" + "github.com/pkg/errors" + "github.com/ugorji/go/codec" +) + +const ( + // msgpack constants, copied from go/codec/msgpack.go + valueTypeMap = 9 + valueTypeArray = 10 +) + +var ( + txTypeMapping sync.Map + txType = reflect.TypeOf((*Transaction)(nil)).Elem() + txWrapperType = reflect.TypeOf((*TransactionWrapper)(nil)) + + // ErrInvalidContainerType represents invalid container type read from msgpack bytes. + ErrInvalidContainerType = errors.New("invalid container type for TransactionWrapper") + // ErrInvalidTransactionType represents invalid transaction type read from msgpack bytes. + ErrInvalidTransactionType = errors.New("invalid transaction type, can not instantiate transaction") + // ErrTransactionRegistration represents invalid transaction object type being registered. + ErrTransactionRegistration = errors.New("transaction register failed") + // ErrMsgPackVersionMismatch represents the msgpack library abi has changed. + ErrMsgPackVersionMismatch = errors.New("msgpack library version mismatch") +) + +func init() { + // detect msgpack version + if codec.GenVersion != 8 { + panic(ErrMsgPackVersionMismatch) + } + + // register transaction wrapper to msgpack handler + if err := utils.RegisterInterfaceToMsgPack(txType, txWrapperType); err != nil { + panic(err) + } +} + +// TransactionWrapper is the wrapper for Transaction interface for serialization/deserialization purpose. +type TransactionWrapper struct { + Transaction +} + +// Unwrap returns transaction within wrapper. +func (w *TransactionWrapper) Unwrap() Transaction { + return w.Transaction +} + +// CodecEncodeSelf implements codec.Selfer interface. +func (w *TransactionWrapper) CodecEncodeSelf(e *codec.Encoder) { + helperEncoder, encDriver := codec.GenHelperEncoder(e) + + if w == nil || w.Transaction == nil { + encDriver.EncodeNil() + return + } + + // if the transaction is supports type transaction mixin + var rawTx interface{} = w.Transaction + if _, ok := rawTx.(ContainsTransactionTypeMixin); ok { + // encode directly + helperEncoder.EncFallback(w.Transaction) + return + } + + // translate wrapper to two fields array wrapped by map + encDriver.WriteArrayStart(2) + encDriver.WriteArrayElem() + encDriver.EncodeUint(uint64(w.GetTransactionType())) + encDriver.WriteArrayElem() + helperEncoder.EncFallback(w.Transaction) + encDriver.WriteArrayEnd() +} + +// CodecDecodeSelf implements codec.Selfer interface. +func (w *TransactionWrapper) CodecDecodeSelf(d *codec.Decoder) { + _, decodeDriver := codec.GenHelperDecoder(d) + + // clear fields + w.Transaction = nil + ct := decodeDriver.ContainerType() + + switch ct { + case valueTypeArray: + w.decodeFromWrapper(d) + case valueTypeMap: + w.decodeFromRaw(d) + default: + panic(errors.Wrapf(ErrInvalidContainerType, "type %v applied", ct)) + } +} + +func (w *TransactionWrapper) decodeFromWrapper(d *codec.Decoder) { + helperDecoder, decodeDriver := codec.GenHelperDecoder(d) + containerLen := decodeDriver.ReadArrayStart() + + for i := 0; i < containerLen; i++ { + if decodeDriver.CheckBreak() { + break + } + + decodeDriver.ReadArrayElem() + + if i == 0 { + if decodeDriver.TryDecodeAsNil() { + // invalid type, can not instantiate transaction + panic(ErrInvalidTransactionType) + } else { + var txType TransactionType + helperDecoder.DecFallback(&txType, true) + + var err error + if w.Transaction, err = NewTransaction(txType); err != nil { + panic(err) + } + } + } else if i == 1 { + if ct := decodeDriver.ContainerType(); ct != valueTypeMap { + panic(errors.Wrapf(ErrInvalidContainerType, "type %v applied", ct)) + } + + if !decodeDriver.TryDecodeAsNil() { + // the container type should be struct + helperDecoder.DecFallback(&w.Transaction, true) + } + } else { + helperDecoder.DecSwallow() + helperDecoder.DecStructFieldNotFound(i, "") + } + } + + decodeDriver.ReadArrayEnd() + + if containerLen < 2 { + panic(ErrInvalidTransactionType) + } +} + +func (w *TransactionWrapper) decodeFromRaw(d *codec.Decoder) { + helperDecoder, _ := codec.GenHelperDecoder(d) + + // read all container as raw + rawBytes := helperDecoder.DecRaw() + + var typeDetector TransactionTypeMixin + typeDetector.SetTransactionType(TransactionTypeNumber) + + var err error + if err = utils.DecodeMsgPack(rawBytes, &typeDetector); err != nil { + panic(err) + } + + txType := typeDetector.GetTransactionType() + + if txType == TransactionTypeNumber { + panic(ErrInvalidTransactionType) + } + + if w.Transaction, err = NewTransaction(txType); err != nil { + panic(err) + } + + if err = utils.DecodeMsgPack(rawBytes, w.Transaction); err != nil { + panic(err) + } +} + +// RegisterTransaction registers transaction type to wrapper. +func RegisterTransaction(t TransactionType, tx Transaction) { + if tx == nil { + panic(ErrTransactionRegistration) + } + rt := reflect.TypeOf(tx) + + if rt == txWrapperType { + panic(ErrTransactionRegistration) + } + + txTypeMapping.Store(t, rt) +} + +// NewTransaction instantiates new transaction object. +func NewTransaction(t TransactionType) (tx Transaction, err error) { + var d interface{} + var ok bool + var rt reflect.Type + + if d, ok = txTypeMapping.Load(t); !ok { + err = errors.Wrapf(ErrInvalidTransactionType, "transaction not registered") + return + } + rt = d.(reflect.Type) + + if !rt.Implements(txType) || rt == txWrapperType { + err = errors.Wrap(ErrInvalidTransactionType, "invalid transaction registered") + return + } + + var rv reflect.Value + + if rt.Kind() == reflect.Ptr { + rv = reflect.New(rt.Elem()) + } else { + rv = reflect.New(rt).Elem() + } + + rawTx := rv.Interface() + tx = rawTx.(Transaction) + + if txTypeAwareness, ok := rawTx.(ContainsTransactionTypeMixin); ok { + txTypeAwareness.SetTransactionType(t) + } + + return +} + +// WrapTransaction wraps transaction in wrapper. +func WrapTransaction(tx Transaction) *TransactionWrapper { + return &TransactionWrapper{ + Transaction: tx, + } +} diff --git a/blockproducer/metastate.go b/blockproducer/metastate.go index b1bbe6a7d..b4d1ae675 100644 --- a/blockproducer/metastate.go +++ b/blockproducer/metastate.go @@ -81,7 +81,11 @@ func (s *metaState) loadAccountStableBalance(addr proto.AccountAddress) (b uint6 defer s.Unlock() defer func() { - log.Debugf("query stable account: %v, result: %v, %v", addr.String(), b, loaded) + log.WithFields(log.Fields{ + "account": addr.String(), + "balance": b, + "loaded": loaded, + }).Debug("queried stable account") }() if o, loaded = s.dirty.accounts[addr]; loaded && o != nil { @@ -101,7 +105,11 @@ func (s *metaState) loadAccountCovenantBalance(addr proto.AccountAddress) (b uin defer s.Unlock() defer func() { - log.Debugf("query covenant account: %v, result: %v, %v", addr.String(), b, loaded) + log.WithFields(log.Fields{ + "account": addr.String(), + "balance": b, + "loaded": loaded, + }).Debug("queried covenant account") }() if o, loaded = s.dirty.accounts[addr]; loaded && o != nil { @@ -116,7 +124,10 @@ func (s *metaState) loadAccountCovenantBalance(addr proto.AccountAddress) (b uin } func (s *metaState) storeBaseAccount(k proto.AccountAddress, v *accountObject) (err error) { - log.Debugf("store account %v to %v", k.String(), v) + log.WithFields(log.Fields{ + "addr": k.String(), + "account": v, + }).Debug("store account") // Since a transfer tx may create an empty receiver account, this method should try to cover // the side effect. if ao, ok := s.loadOrStoreAccountObject(k, v); ok { @@ -310,7 +321,7 @@ func (s *metaState) partialCommitProcedure(txs []pi.Transaction) (_ func(*bolt.T // Rebuild dirty map cm.dirty = newMetaIndex() for _, v := range cp.entries { - for _, tx := range v.transacions { + for _, tx := range v.transactions { if err = cm.applyTransaction(tx); err != nil { return } @@ -649,15 +660,15 @@ func (s *metaState) increaseNonce(addr proto.AccountAddress) (err error) { return } -func (s *metaState) applyBilling(tx *pt.TxBilling) (err error) { - for i, v := range tx.TxContent.Receivers { +func (s *metaState) applyBilling(tx *pt.Billing) (err error) { + for i, v := range tx.Receivers { // Create empty receiver account if not found s.loadOrStoreAccountObject(*v, &accountObject{Account: pt.Account{Address: *v}}) - if err = s.increaseAccountCovenantBalance(*v, tx.TxContent.Fees[i]); err != nil { + if err = s.increaseAccountCovenantBalance(*v, tx.Fees[i]); err != nil { return } - if err = s.increaseAccountStableBalance(*v, tx.TxContent.Rewards[i]); err != nil { + if err = s.increaseAccountStableBalance(*v, tx.Rewards[i]); err != nil { return } } @@ -668,10 +679,13 @@ func (s *metaState) applyTransaction(tx pi.Transaction) (err error) { switch t := tx.(type) { case *pt.Transfer: err = s.transferAccountStableBalance(t.Sender, t.Receiver, t.Amount) - case *pt.TxBilling: + case *pt.Billing: err = s.applyBilling(t) case *pt.BaseAccount: err = s.storeBaseAccount(t.Address, &accountObject{Account: t.Account}) + case *pi.TransactionWrapper: + // call again using unwrapped transaction + err = s.applyTransaction(t.Unwrap()) default: err = ErrUnknownTransactionType } @@ -688,7 +702,7 @@ func (s *metaState) applyTransactionProcedure(t pi.Transaction) (_ func(*bolt.Tx } ) - log.Debugf("try applying transaction: %v", t) + log.WithField("tx", t).Debug("try applying transaction") // Static checks, which have no relation with metaState if err = t.Verify(); err != nil { @@ -696,20 +710,20 @@ func (s *metaState) applyTransactionProcedure(t pi.Transaction) (_ func(*bolt.Tx } var ( - enc []byte + enc *bytes.Buffer hash = t.GetHash() addr = t.GetAccountAddress() nonce = t.GetAccountNonce() ttype = t.GetTransactionType() ) - if enc, err = t.Serialize(); err != nil { - log.Debugf("encode failed on applying transaction: %v", err) + if enc, err = utils.EncodeMsgPack(t); err != nil { + log.WithField("tx", t).WithError(err).Debug("encode failed on applying transaction") return errPass } // metaState-related checks will be performed within bolt.Tx to guarantee consistency return func(tx *bolt.Tx) (err error) { - log.Debugf("processing transaction: %v", t) + log.WithField("tx", t).Debug("processing transaction") // Check tx existense // TODO(leventeliu): maybe move outside? @@ -728,19 +742,22 @@ func (s *metaState) applyTransactionProcedure(t pi.Transaction) (_ func(*bolt.Tx } if nextNonce != nonce { err = ErrInvalidAccountNonce - log.Debugf("nonce not match during transaction apply: %v", err) + log.WithFields(log.Fields{ + "actual": nonce, + "expected": nextNonce, + }).WithError(err).Debug("nonce not match during transaction apply") return } // Try to put transaction before any state change, will be rolled back later // if transaction doesn't apply tb := tx.Bucket(metaBucket[:]).Bucket(metaTransactionBucket).Bucket(ttype.Bytes()) - if err = tb.Put(hash[:], enc); err != nil { - log.Debugf("store transaction to bucket failed: %v", err) + if err = tb.Put(hash[:], enc.Bytes()); err != nil { + log.WithError(err).Debug("store transaction to bucket failed") return } // Try to apply transaction to metaState if err = s.applyTransaction(t); err != nil { - log.Debugf("apply transaction failed: %v", err) + log.WithError(err).Debug("apply transaction failed") return } if err = s.increaseNonce(addr); err != nil { @@ -758,7 +775,7 @@ func (s *metaState) pullTxs() (txs []pi.Transaction) { defer s.Unlock() for _, v := range s.pool.entries { // TODO(leventeliu): check race condition. - txs = append(txs, v.transacions...) + txs = append(txs, v.transactions...) } return } diff --git a/blockproducer/metastate_test.go b/blockproducer/metastate_test.go index f8296b45a..e27cc13af 100644 --- a/blockproducer/metastate_test.go +++ b/blockproducer/metastate_test.go @@ -568,31 +568,29 @@ func TestMetaState(t *testing.T) { }) }) }) - Convey("When transacions are added", func() { + Convey("When transactions are added", func() { var ( n pi.AccountNonce - t0 = &pt.BaseAccount{ - Account: pt.Account{ - Address: addr1, - }, - } - t1 = &pt.Transfer{ - TransferHeader: pt.TransferHeader{ + t0 = pt.NewBaseAccount(&pt.Account{ + Address: addr1, + }) + t1 = pt.NewTransfer( + &pt.TransferHeader{ Sender: addr1, Receiver: addr2, Nonce: 1, Amount: 0, }, - } - t2 = &pt.TxBilling{ - TxContent: pt.TxContent{ - SequenceID: 2, - Receivers: []*proto.AccountAddress{&addr2}, - Fees: []uint64{1}, - Rewards: []uint64{1}, + ) + t2 = pt.NewBilling( + &pt.BillingHeader{ + Nonce: 2, + Producer: addr1, + Receivers: []*proto.AccountAddress{&addr2}, + Fees: []uint64{1}, + Rewards: []uint64{1}, }, - AccountAddress: &addr1, - } + ) ) err = t1.Sign(testPrivKey) So(err, ShouldBeNil) @@ -600,20 +598,20 @@ func TestMetaState(t *testing.T) { So(err, ShouldBeNil) err = db.Update(ms.applyTransactionProcedure(t0)) So(err, ShouldBeNil) - So(len(ms.pool.entries[addr1].transacions), ShouldEqual, 1) + So(len(ms.pool.entries[addr1].transactions), ShouldEqual, 1) err = db.Update(ms.applyTransactionProcedure(t1)) So(err, ShouldBeNil) _, loaded = ms.pool.entries[t1.GetAccountAddress()] So(loaded, ShouldBeTrue) So(ms.pool.hasTx(t0), ShouldBeTrue) - So(len(ms.pool.entries[addr1].transacions), ShouldEqual, 2) + So(len(ms.pool.entries[addr1].transactions), ShouldEqual, 2) _, loaded = ms.pool.entries[t1.GetAccountAddress()] So(loaded, ShouldBeTrue) So(ms.pool.hasTx(t0), ShouldBeTrue) So(ms.pool.hasTx(t1), ShouldBeTrue) err = db.Update(ms.applyTransactionProcedure(t2)) So(err, ShouldBeNil) - So(len(ms.pool.entries[addr1].transacions), ShouldEqual, 3) + So(len(ms.pool.entries[addr1].transactions), ShouldEqual, 3) _, loaded = ms.pool.entries[t1.GetAccountAddress()] So(loaded, ShouldBeTrue) _, loaded = ms.pool.entries[t2.GetAccountAddress()] @@ -658,25 +656,25 @@ func TestMetaState(t *testing.T) { err = db.Update(ms.partialCommitProcedure([]pi.Transaction{})) So(err, ShouldBeNil) So(ms.pool.entries[addr1].baseNonce, ShouldEqual, 0) - So(len(ms.pool.entries[addr1].transacions), ShouldEqual, 3) + So(len(ms.pool.entries[addr1].transactions), ShouldEqual, 3) }) Convey("The partial commit procedure should be appliable for tx0", func() { err = db.Update(ms.partialCommitProcedure([]pi.Transaction{t0})) So(err, ShouldBeNil) So(ms.pool.entries[addr1].baseNonce, ShouldEqual, 1) - So(len(ms.pool.entries[addr1].transacions), ShouldEqual, 2) + So(len(ms.pool.entries[addr1].transactions), ShouldEqual, 2) }) Convey("The partial commit procedure should be appliable for tx0-1", func() { err = db.Update(ms.partialCommitProcedure([]pi.Transaction{t0, t1})) So(err, ShouldBeNil) So(ms.pool.entries[addr1].baseNonce, ShouldEqual, 2) - So(len(ms.pool.entries[addr1].transacions), ShouldEqual, 1) + So(len(ms.pool.entries[addr1].transactions), ShouldEqual, 1) }) Convey("The partial commit procedure should be appliable for all tx", func() { err = db.Update(ms.partialCommitProcedure([]pi.Transaction{t0, t1, t2})) So(err, ShouldBeNil) So(ms.pool.entries[addr1].baseNonce, ShouldEqual, 3) - So(len(ms.pool.entries[addr1].transacions), ShouldEqual, 0) + So(len(ms.pool.entries[addr1].transactions), ShouldEqual, 0) }) Convey( "The partial commit procedure should not be appliable for modified tx", @@ -686,7 +684,7 @@ func TestMetaState(t *testing.T) { So(err, ShouldBeNil) err = db.Update(ms.partialCommitProcedure([]pi.Transaction{t0, t1, t2})) So(err, ShouldEqual, ErrTransactionMismatch) - So(len(ms.pool.entries[addr1].transacions), ShouldEqual, 3) + So(len(ms.pool.entries[addr1].transactions), ShouldEqual, 3) }, ) }) @@ -694,78 +692,78 @@ func TestMetaState(t *testing.T) { Convey("When base account txs are added", func() { var ( txs = []pi.Transaction{ - &pt.BaseAccount{ - Account: pt.Account{ + pt.NewBaseAccount( + &pt.Account{ Address: addr1, StableCoinBalance: 100, CovenantCoinBalance: 100, }, - }, - &pt.BaseAccount{ - Account: pt.Account{ + ), + pt.NewBaseAccount( + &pt.Account{ Address: addr2, StableCoinBalance: 100, CovenantCoinBalance: 100, }, - }, - &pt.Transfer{ - TransferHeader: pt.TransferHeader{ + ), + pt.NewTransfer( + &pt.TransferHeader{ Sender: addr1, Receiver: addr2, Nonce: 1, Amount: 10, }, - }, - &pt.TxBilling{ - TxContent: pt.TxContent{ - SequenceID: 2, - Receivers: []*proto.AccountAddress{&addr2}, - Fees: []uint64{1}, - Rewards: []uint64{1}, + ), + pt.NewBilling( + &pt.BillingHeader{ + Nonce: 2, + Producer: addr1, + Receivers: []*proto.AccountAddress{&addr2}, + Fees: []uint64{1}, + Rewards: []uint64{1}, }, - AccountAddress: &addr1, - }, - &pt.TxBilling{ - TxContent: pt.TxContent{ - SequenceID: 1, - Receivers: []*proto.AccountAddress{&addr1}, - Fees: []uint64{1}, - Rewards: []uint64{1}, + ), + pt.NewBilling( + &pt.BillingHeader{ + Nonce: 1, + Producer: addr2, + Receivers: []*proto.AccountAddress{&addr1}, + Fees: []uint64{1}, + Rewards: []uint64{1}, }, - AccountAddress: &addr2, - }, - &pt.Transfer{ - TransferHeader: pt.TransferHeader{ + ), + pt.NewTransfer( + &pt.TransferHeader{ Sender: addr2, Receiver: addr1, Nonce: 2, Amount: 1, }, - }, - &pt.Transfer{ - TransferHeader: pt.TransferHeader{ + ), + pt.NewTransfer( + &pt.TransferHeader{ Sender: addr1, Receiver: addr2, Nonce: 3, Amount: 10, }, - }, - &pt.Transfer{ - TransferHeader: pt.TransferHeader{ + ), + pt.NewTransfer( + &pt.TransferHeader{ Sender: addr2, Receiver: addr1, Nonce: 3, Amount: 1, }, - }, - &pt.Transfer{ - TransferHeader: pt.TransferHeader{ + ), + pt.NewTransfer( + &pt.TransferHeader{ Sender: addr2, Receiver: addr1, Nonce: 4, Amount: 1, }, - }, + ), } ) for _, tx := range txs { diff --git a/blockproducer/rpc.go b/blockproducer/rpc.go index 22322558d..358e5bad0 100644 --- a/blockproducer/rpc.go +++ b/blockproducer/rpc.go @@ -20,11 +20,7 @@ import ( pi "github.com/CovenantSQL/CovenantSQL/blockproducer/interfaces" "github.com/CovenantSQL/CovenantSQL/blockproducer/types" "github.com/CovenantSQL/CovenantSQL/proto" -) - -const ( - // MainChainRPCName defines rpc service name of main chain internal consensus. - MainChainRPCName = "MCC" + ct "github.com/CovenantSQL/CovenantSQL/sqlchain/types" ) // ChainRPCService defines a main chain RPC server. @@ -46,7 +42,7 @@ type AdviseNewBlockResp struct { // AdviseTxBillingReq defines a request of the AdviseTxBilling RPC method. type AdviseTxBillingReq struct { proto.Envelope - TxBilling *types.TxBilling + TxBilling *types.Billing } // AdviseTxBillingResp defines a response of the AdviseTxBilling RPC method. @@ -54,18 +50,6 @@ type AdviseTxBillingResp struct { proto.Envelope } -// AdviseBillingReq defines a request of the AdviseBillingRequest RPC method. -type AdviseBillingReq struct { - proto.Envelope - Req *types.BillingRequest -} - -// AdviseBillingResp defines a request of the AdviseBillingRequest RPC method. -type AdviseBillingResp struct { - proto.Envelope - Resp *types.BillingResponse -} - // FetchBlockReq defines a request of the FetchBlock RPC method. type FetchBlockReq struct { proto.Envelope @@ -76,9 +60,16 @@ type FetchBlockReq struct { type FetchBlockResp struct { proto.Envelope Height uint32 + Count uint32 Block *types.Block } +// FetchBlockByCountReq define a request of the FetchBlockByCount RPC method. +type FetchBlockByCountReq struct { + proto.Envelope + Count uint32 +} + // FetchTxBillingReq defines a request of the FetchTxBilling RPC method. type FetchTxBillingReq struct { proto.Envelope @@ -113,12 +104,6 @@ type AddTxResp struct { proto.Envelope } -// AddTxTransferReq defines a request of AddTxTransfer RPC method. -type AddTxTransferReq struct { - proto.Envelope - Tx *types.Transfer -} - // QueryAccountStableBalanceReq defines a request of the QueryAccountStableBalance RPC method. type QueryAccountStableBalanceReq struct { proto.Envelope @@ -153,14 +138,9 @@ func (s *ChainRPCService) AdviseNewBlock(req *AdviseNewBlockReq, resp *AdviseNew return s.chain.pushBlock(req.Block) } -// AdviseTxBilling is the RPC method to advise a new billing tx to target server. -func (s *ChainRPCService) AdviseTxBilling(req *AdviseTxBillingReq, resp *AdviseTxBillingResp) error { - return s.chain.pushTxBilling(req.TxBilling) -} - // AdviseBillingRequest is the RPC method to advise a new billing request to main chain. -func (s *ChainRPCService) AdviseBillingRequest(req *AdviseBillingReq, resp *AdviseBillingResp) error { - response, err := s.chain.produceTxBilling(req.Req) +func (s *ChainRPCService) AdviseBillingRequest(req *ct.AdviseBillingReq, resp *ct.AdviseBillingResp) error { + response, err := s.chain.produceBilling(req.Req) if err != nil { return err } @@ -168,15 +148,31 @@ func (s *ChainRPCService) AdviseBillingRequest(req *AdviseBillingReq, resp *Advi return nil } -// FetchBlock is the RPC method to fetch a known block form the target server. +// FetchBlock is the RPC method to fetch a known block from the target server. func (s *ChainRPCService) FetchBlock(req *FetchBlockReq, resp *FetchBlockResp) error { resp.Height = req.Height - block, err := s.chain.fetchBlockByHeight(req.Height) + block, count, err := s.chain.fetchBlockByHeight(req.Height) + if err != nil { + return err + } resp.Block = block + resp.Count = count return err } -// FetchTxBilling is the RPC method to fetch a known billing tx form the target server. +// FetchBlockByCount is the RPC method to fetch a known block from the target server. +func (s *ChainRPCService) FetchBlockByCount(req *FetchBlockByCountReq, resp *FetchBlockResp) error { + resp.Count = req.Count + block, height, err := s.chain.fetchBlockByCount(req.Count) + if err != nil { + return err + } + resp.Block = block + resp.Height = height + return err +} + +// FetchTxBilling is the RPC method to fetch a known billing tx from the target server. func (s *ChainRPCService) FetchTxBilling(req *FetchTxBillingReq, resp *FetchTxBillingResp) error { return nil } @@ -203,17 +199,6 @@ func (s *ChainRPCService) AddTx(req *AddTxReq, resp *AddTxResp) (err error) { return } -// AddTxTransfer is the RPC method to add a transfer transaction. -func (s *ChainRPCService) AddTxTransfer(req *AddTxTransferReq, resp *AddTxResp) (err error) { - if req.Tx == nil { - return ErrUnknownTransactionType - } - - s.chain.pendingTxs <- req.Tx - - return -} - // QueryAccountStableBalance is the RPC method to query acccount stable coin balance. func (s *ChainRPCService) QueryAccountStableBalance( req *QueryAccountStableBalanceReq, resp *QueryAccountStableBalanceResp) (err error, diff --git a/blockproducer/runtime.go b/blockproducer/runtime.go index f282a6cda..b1e376f0d 100644 --- a/blockproducer/runtime.go +++ b/blockproducer/runtime.go @@ -23,6 +23,7 @@ import ( "github.com/CovenantSQL/CovenantSQL/kayak" "github.com/CovenantSQL/CovenantSQL/proto" + "github.com/CovenantSQL/CovenantSQL/route" "github.com/CovenantSQL/CovenantSQL/rpc" ) @@ -99,7 +100,7 @@ func newRuntime(cfg *Config, accountAddress proto.AccountAddress) *rt { } func (r *rt) startService(chain *Chain) { - r.server.RegisterService(MainChainRPCName, &ChainRPCService{chain: chain}) + r.server.RegisterService(route.BlockProducerRPCName, &ChainRPCService{chain: chain}) } // nextTick returns the current clock reading and the duration till the next turn. If duration diff --git a/blockproducer/state.go b/blockproducer/state.go index 3875c9004..c82fc3618 100644 --- a/blockproducer/state.go +++ b/blockproducer/state.go @@ -20,7 +20,6 @@ import ( "sync" "github.com/CovenantSQL/CovenantSQL/crypto/hash" - "github.com/CovenantSQL/CovenantSQL/utils" ) // State store the node info of chain. @@ -31,22 +30,6 @@ type State struct { Height uint32 } -// serialize serializes the state. -func (s *State) serialize() ([]byte, error) { - buffer, err := utils.EncodeMsgPack(s) - if err != nil { - return nil, err - } - - return buffer.Bytes(), nil -} - -// deserialize deserializes the state. -func (s *State) deserialize(b []byte) error { - err := utils.DecodeMsgPack(b, s) - return err -} - func (s *State) getNode() *blockNode { s.Lock() defer s.Unlock() diff --git a/blockproducer/txindex.go b/blockproducer/txindex.go deleted file mode 100644 index d17eebd21..000000000 --- a/blockproducer/txindex.go +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2018 The CovenantSQL Authors. - * - * 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. - */ - -package blockproducer - -import ( - "sync" - - "github.com/CovenantSQL/CovenantSQL/blockproducer/types" - "github.com/CovenantSQL/CovenantSQL/crypto/hash" - "github.com/CovenantSQL/CovenantSQL/proto" -) - -// txIndex indexes the tx blockchain receive. -type txIndex struct { - mu sync.Mutex - - billingHashIndex map[hash.Hash]*types.TxBilling - // lastBillingIndex indexes last appearing txBilling of DatabaseID - // to ensure the nonce of txbilling monotone increasing - lastBillingIndex map[*proto.DatabaseID]uint32 -} - -// newTxIndex creates a new TxIndex. -func newTxIndex() *txIndex { - ti := txIndex{ - billingHashIndex: make(map[hash.Hash]*types.TxBilling), - lastBillingIndex: make(map[*proto.DatabaseID]uint32), - } - return &ti -} - -// addTxBilling adds a checked TxBilling in the TxIndex. -func (ti *txIndex) addTxBilling(tb *types.TxBilling) error { - ti.mu.Lock() - defer ti.mu.Unlock() - - if v, ok := ti.billingHashIndex[*tb.TxHash]; ok { - // TODO(lambda): ensure whether the situation will happen - if v == nil { - return ErrCorruptedIndex - } - } - - ti.billingHashIndex[*tb.TxHash] = tb - - return nil -} - -// updateLatTxBilling updates the last billing index of specific databaseID. -func (ti *txIndex) updateLastTxBilling(databaseID *proto.DatabaseID, sequenceID uint32) (err error) { - ti.mu.Lock() - defer ti.mu.Unlock() - - if v, ok := ti.lastBillingIndex[databaseID]; ok { - if v >= sequenceID { - return ErrSmallerSequenceID - } - ti.lastBillingIndex[databaseID] = sequenceID - } - ti.lastBillingIndex[databaseID] = sequenceID - return -} - -// fetchUnpackedTxBillings fetch all txbillings in index. -func (ti *txIndex) fetchUnpackedTxBillings() []*types.TxBilling { - ti.mu.Lock() - defer ti.mu.Unlock() - - txes := make([]*types.TxBilling, 0, 1024) - - for _, t := range ti.billingHashIndex { - if t != nil && t.SignedBlock == nil { - txes = append(txes, t) - } - } - return txes -} - -// hasTxBilling look up the specific txbilling in index. -func (ti *txIndex) hasTxBilling(h *hash.Hash) bool { - _, ok := ti.billingHashIndex[*h] - return ok -} - -// getTxBilling look up the specific txbilling in index. -func (ti *txIndex) getTxBilling(h *hash.Hash) *types.TxBilling { - val := ti.billingHashIndex[*h] - return val -} - -// lastSequenceID look up the last sequenceID of specific databaseID. -func (ti *txIndex) lastSequenceID(databaseID *proto.DatabaseID) (uint32, error) { - if seqID, ok := ti.lastBillingIndex[databaseID]; ok { - return seqID, nil - } - return 0, ErrNoSuchTxBilling -} diff --git a/blockproducer/txindex_test.go b/blockproducer/txindex_test.go deleted file mode 100644 index 784c7808f..000000000 --- a/blockproducer/txindex_test.go +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2018 The CovenantSQL Authors. - * - * 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. - */ - -package blockproducer - -import ( - "math/rand" - "reflect" - "testing" - - "github.com/CovenantSQL/CovenantSQL/blockproducer/types" -) - -func Test_AddAndHasTxBilling(t *testing.T) { - ti := newTxIndex() - maxLen := 100 - mlen := rand.Intn(maxLen) - tbs := make([]*types.TxBilling, mlen) - for i := range tbs { - tb, err := generateRandomTxBilling() - if err != nil { - t.Fatalf("unexpect error: %v", err) - } - tbs[i] = tb - err = ti.addTxBilling(tb) - if err != nil { - t.Fatalf("unexpect error: %v", err) - } - } - - for i := range tbs { - if !ti.hasTxBilling(tbs[i].TxHash) { - t.Fatalf("tx (%v) should be included in tx index", tbs[i]) - } - if val := ti.getTxBilling(tbs[i].TxHash); !reflect.DeepEqual(tbs[i], val) { - t.Fatalf("tx (%v) should be included in tx index", tbs[i]) - } - tb, err := generateRandomTxBilling() - if err != nil { - t.Fatalf("unexpect error: %v", err) - } - if ti.hasTxBilling(tb.TxHash) { - t.Fatalf("tx (%v) should be excluded in tx index", tb) - } - } - - fetchedTbs := ti.fetchUnpackedTxBillings() - for i := range fetchedTbs { - if !reflect.DeepEqual(tbs[i], fetchedTbs[i]) { - t.Fatalf("two values should be equal: \n\tv1=%v\n\tv2=%v", tbs[i], fetchedTbs[i]) - } - } -} diff --git a/blockproducer/txpool.go b/blockproducer/txpool.go index 8a17156c8..4fd46f683 100644 --- a/blockproducer/txpool.go +++ b/blockproducer/txpool.go @@ -23,34 +23,34 @@ import ( ) type accountTxEntries struct { - account proto.AccountAddress - baseNonce pi.AccountNonce - transacions []pi.Transaction + account proto.AccountAddress + baseNonce pi.AccountNonce + transactions []pi.Transaction } func newAccountTxEntries( addr proto.AccountAddress, baseNonce pi.AccountNonce) (_ *accountTxEntries, ) { return &accountTxEntries{ - account: addr, - baseNonce: baseNonce, - transacions: nil, + account: addr, + baseNonce: baseNonce, + transactions: nil, } } func (e *accountTxEntries) nextNonce() pi.AccountNonce { - return e.baseNonce + pi.AccountNonce(len(e.transacions)) + return e.baseNonce + pi.AccountNonce(len(e.transactions)) } func (e *accountTxEntries) addTx(tx pi.Transaction) { - e.transacions = append(e.transacions, tx) + e.transactions = append(e.transactions, tx) } func (e *accountTxEntries) halfDeepCopy() (cpy *accountTxEntries) { return &accountTxEntries{ - account: e.account, - baseNonce: e.baseNonce, - transacions: e.transacions[:], + account: e.account, + baseNonce: e.baseNonce, + transactions: e.transactions[:], } } @@ -89,12 +89,12 @@ func (p *txPool) hasTx(tx pi.Transaction) (ok bool) { nonce = tx.GetAccountNonce() index = int(nonce - te.baseNonce) ) - if ok = (nonce >= te.baseNonce && index < len(te.transacions)); !ok { + if ok = (nonce >= te.baseNonce && index < len(te.transactions)); !ok { log.Debug("transaction nonce or index already exists") return } // Check transaction hash - if ok = (tx.GetHash() == te.transacions[index].GetHash()); !ok { + if ok = (tx.GetHash() == te.transactions[index].GetHash()); !ok { log.Debug("transaction hash already exists") return } @@ -108,15 +108,15 @@ func (p *txPool) cmpAndMoveNextTx(tx pi.Transaction) (ok bool) { return } // Out of range - if ok = (tx.GetAccountNonce() == te.baseNonce && len(te.transacions) > 0); !ok { + if ok = (tx.GetAccountNonce() == te.baseNonce && len(te.transactions) > 0); !ok { return } // Check transaction hash - if ok = (tx.GetHash() == te.transacions[0].GetHash()); !ok { + if ok = (tx.GetHash() == te.transactions[0].GetHash()); !ok { return } // Move forward - te.transacions = te.transacions[1:] + te.transactions = te.transactions[1:] te.baseNonce++ return } diff --git a/blockproducer/types/account_gen.go b/blockproducer/types/account_gen.go index 1b7ea56b4..031082942 100644 --- a/blockproducer/types/account_gen.go +++ b/blockproducer/types/account_gen.go @@ -12,14 +12,14 @@ func (z *Account) MarshalHash() (o []byte, err error) { o = hsp.Require(b, z.Msgsize()) // map header, size 5 o = append(o, 0x85, 0x85) + o = hsp.AppendFloat64(o, z.Rating) + o = append(o, 0x85) if oTemp, err := z.NextNonce.MarshalHash(); err != nil { return nil, err } else { o = hsp.AppendBytes(o, oTemp) } o = append(o, 0x85) - o = hsp.AppendFloat64(o, z.Rating) - o = append(o, 0x85) if oTemp, err := z.Address.MarshalHash(); err != nil { return nil, err } else { @@ -34,7 +34,7 @@ func (z *Account) MarshalHash() (o []byte, err error) { // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message func (z *Account) Msgsize() (s int) { - s = 1 + 10 + z.NextNonce.Msgsize() + 7 + hsp.Float64Size + 8 + z.Address.Msgsize() + 18 + hsp.Uint64Size + 20 + hsp.Uint64Size + s = 1 + 7 + hsp.Float64Size + 10 + z.NextNonce.Msgsize() + 8 + z.Address.Msgsize() + 18 + hsp.Uint64Size + 20 + hsp.Uint64Size return } diff --git a/blockproducer/types/baseaccount.go b/blockproducer/types/baseaccount.go index af93be2ec..ce4facda1 100644 --- a/blockproducer/types/baseaccount.go +++ b/blockproducer/types/baseaccount.go @@ -17,13 +17,10 @@ package types import ( - "bytes" - pi "github.com/CovenantSQL/CovenantSQL/blockproducer/interfaces" "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" "github.com/CovenantSQL/CovenantSQL/crypto/hash" "github.com/CovenantSQL/CovenantSQL/proto" - "github.com/CovenantSQL/CovenantSQL/utils" ) //go:generate hsp @@ -31,22 +28,15 @@ import ( // BaseAccount defines the base account type header. type BaseAccount struct { Account - AccountHash hash.Hash + pi.TransactionTypeMixin } -// Serialize implements interfaces/Transaction.Serialize. -func (b *BaseAccount) Serialize() (s []byte, err error) { - var enc *bytes.Buffer - if enc, err = utils.EncodeMsgPack(b); err != nil { - return +// NewBaseAccount returns new instance. +func NewBaseAccount(account *Account) *BaseAccount { + return &BaseAccount{ + Account: *account, + TransactionTypeMixin: *pi.NewTransactionTypeMixin(pi.TransactionTypeBaseAccount), } - s = enc.Bytes() - return -} - -// Deserialize implements interfaces/Transaction.Deserialize. -func (b *BaseAccount) Deserialize(enc []byte) error { - return utils.DecodeMsgPack(enc, b) } // GetAccountAddress implements interfaces/Transaction.GetAccountAddress. @@ -61,13 +51,8 @@ func (b *BaseAccount) GetAccountNonce() pi.AccountNonce { } // GetHash implements interfaces/Transaction.GetHash. -func (b *BaseAccount) GetHash() hash.Hash { - return b.AccountHash -} - -// GetTransactionType implements interfaces/Transaction.GetTransactionType. -func (b *BaseAccount) GetTransactionType() pi.TransactionType { - return pi.TransactionTypeBaseAccount +func (b *BaseAccount) GetHash() (h hash.Hash) { + return } // Sign implements interfaces/Transaction.Sign. @@ -79,3 +64,7 @@ func (b *BaseAccount) Sign(signer *asymmetric.PrivateKey) (err error) { func (b *BaseAccount) Verify() (err error) { return } + +func init() { + pi.RegisterTransaction(pi.TransactionTypeBaseAccount, (*BaseAccount)(nil)) +} diff --git a/blockproducer/types/baseaccount_gen.go b/blockproducer/types/baseaccount_gen.go index 6f8c8f40f..857c98fd1 100644 --- a/blockproducer/types/baseaccount_gen.go +++ b/blockproducer/types/baseaccount_gen.go @@ -18,7 +18,7 @@ func (z *BaseAccount) MarshalHash() (o []byte, err error) { o = hsp.AppendBytes(o, oTemp) } o = append(o, 0x82) - if oTemp, err := z.AccountHash.MarshalHash(); err != nil { + if oTemp, err := z.TransactionTypeMixin.MarshalHash(); err != nil { return nil, err } else { o = hsp.AppendBytes(o, oTemp) @@ -28,6 +28,6 @@ func (z *BaseAccount) MarshalHash() (o []byte, err error) { // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message func (z *BaseAccount) Msgsize() (s int) { - s = 1 + 8 + z.Account.Msgsize() + 12 + z.AccountHash.Msgsize() + s = 1 + 8 + z.Account.Msgsize() + 21 + z.TransactionTypeMixin.Msgsize() return } diff --git a/blockproducer/types/billing.go b/blockproducer/types/billing.go index 3e4f80502..0beeb86f7 100644 --- a/blockproducer/types/billing.go +++ b/blockproducer/types/billing.go @@ -17,94 +17,81 @@ package types import ( + pi "github.com/CovenantSQL/CovenantSQL/blockproducer/interfaces" "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" - "github.com/CovenantSQL/CovenantSQL/crypto/hash" "github.com/CovenantSQL/CovenantSQL/proto" ) //go:generate hsp -// BillingRequestHeader includes contents that need to be signed. Billing blocks should be within -// height range [low, high] (inclusive). -type BillingRequestHeader struct { - DatabaseID proto.DatabaseID - // sqlchain block hash and its height - LowBlock hash.Hash - LowHeight int32 - HighBlock hash.Hash - HighHeight int32 - GasAmounts []*proto.AddrAndGas +// BillingHeader defines the customer's billing and block rewards in transaction. +type BillingHeader struct { + // Transaction nonce + Nonce pi.AccountNonce + BillingRequest BillingRequest + // Bill producer + Producer proto.AccountAddress + // Bill receivers + Receivers []*proto.AccountAddress + // Fee paid by stable coin + Fees []uint64 + // Reward is share coin + Rewards []uint64 } -// -//// MarshalHash marshals for hash -//func (bh *BillingRequestHeader) MarshalHash() ([]byte, error) { -// buffer := bytes.NewBuffer(nil) -// -// err := utils.WriteElements(buffer, binary.BigEndian, -// &bh.DatabaseID, -// &bh.LowBlock, -// &bh.LowHeight, -// &bh.HighBlock, -// &bh.HighHeight, -// &bh.GasAmounts, -// ) -// -// if err != nil { -// return nil, err -// } -// return buffer.Bytes(), nil -//} - -// BillingRequest defines periodically Billing sync. -type BillingRequest struct { - Header BillingRequestHeader - RequestHash hash.Hash - Signees []*asymmetric.PublicKey - Signatures []*asymmetric.Signature +// NewBillingHeader generates new BillingHeader. +func NewBillingHeader(nonce pi.AccountNonce, bReq *BillingRequest, producer proto.AccountAddress, receivers []*proto.AccountAddress, + fees []uint64, rewards []uint64) *BillingHeader { + return &BillingHeader{ + Nonce: nonce, + BillingRequest: *bReq, + Producer: producer, + Receivers: receivers, + Fees: fees, + Rewards: rewards, + } } -//// MarshalHash marshals for hash -//func (br *BillingRequest) MarshalHash() ([]byte, error) { -// buffer := bytes.NewBuffer(nil) -// -// err := utils.WriteElements(buffer, binary.BigEndian, -// &br.Header, -// &br.RequestHash, -// &br.Signees, -// &br.Signatures, -// ) -// -// if err != nil { -// return nil, err -// } -// return buffer.Bytes(), nil -//} +// Billing is a type of tx, that is used to record sql chain billing and block rewards. +type Billing struct { + BillingHeader + pi.TransactionTypeMixin + DefaultHashSignVerifierImpl +} -// PackRequestHeader computes the hash of header. -func (br *BillingRequest) PackRequestHeader() (*hash.Hash, error) { - b, err := br.Header.MarshalHash() - if err != nil { - return nil, err +// NewBilling generates a new Billing. +func NewBilling(header *BillingHeader) *Billing { + return &Billing{ + BillingHeader: *header, + TransactionTypeMixin: *pi.NewTransactionTypeMixin(pi.TransactionTypeBilling), } +} - h := hash.THashH(b) - return &h, nil +// Sign implements interfaces/Transaction.Sign. +func (tb *Billing) Sign(signer *asymmetric.PrivateKey) (err error) { + return tb.DefaultHashSignVerifierImpl.Sign(&tb.BillingHeader, signer) } -// SignRequestHeader first computes the hash of BillingRequestHeader, then signs the request. -func (br *BillingRequest) SignRequestHeader(signee *asymmetric.PrivateKey) (*asymmetric.Signature, error) { - signature, err := signee.Sign(br.RequestHash[:]) - if err != nil { - return nil, err - } - return signature, nil +// Verify implements interfaces/Transaction.Verify. +func (tb *Billing) Verify() error { + return tb.DefaultHashSignVerifierImpl.Verify(&tb.BillingHeader) +} + +// GetAccountAddress implements interfaces/Transaction.GetAccountAddress. +func (tb *Billing) GetAccountAddress() proto.AccountAddress { + return tb.Producer +} + +// GetAccountNonce implements interfaces/Transaction.GetAccountNonce. +func (tb *Billing) GetAccountNonce() pi.AccountNonce { + return tb.Nonce +} + +// GetDatabaseID gets the database ID. +func (tb *Billing) GetDatabaseID() *proto.DatabaseID { + return &tb.BillingRequest.Header.DatabaseID } -// BillingResponse defines the the response for BillingRequest. -type BillingResponse struct { - AccountAddress proto.AccountAddress - RequestHash hash.Hash - Signee *asymmetric.PublicKey - Signature *asymmetric.Signature +func init() { + pi.RegisterTransaction(pi.TransactionTypeBilling, (*Billing)(nil)) } diff --git a/blockproducer/types/billing_gen.go b/blockproducer/types/billing_gen.go index 6e2efb4ab..5260f1a35 100644 --- a/blockproducer/types/billing_gen.go +++ b/blockproducer/types/billing_gen.go @@ -7,44 +7,24 @@ import ( ) // MarshalHash marshals for hash -func (z *BillingRequest) MarshalHash() (o []byte, err error) { +func (z *Billing) MarshalHash() (o []byte, err error) { var b []byte o = hsp.Require(b, z.Msgsize()) - // map header, size 4 - o = append(o, 0x84, 0x84) - if oTemp, err := z.Header.MarshalHash(); err != nil { + // map header, size 3 + o = append(o, 0x83, 0x83) + if oTemp, err := z.BillingHeader.MarshalHash(); err != nil { return nil, err } else { o = hsp.AppendBytes(o, oTemp) } - o = append(o, 0x84) - o = hsp.AppendArrayHeader(o, uint32(len(z.Signees))) - for za0001 := range z.Signees { - if z.Signees[za0001] == nil { - o = hsp.AppendNil(o) - } else { - if oTemp, err := z.Signees[za0001].MarshalHash(); err != nil { - return nil, err - } else { - o = hsp.AppendBytes(o, oTemp) - } - } - } - o = append(o, 0x84) - o = hsp.AppendArrayHeader(o, uint32(len(z.Signatures))) - for za0002 := range z.Signatures { - if z.Signatures[za0002] == nil { - o = hsp.AppendNil(o) - } else { - if oTemp, err := z.Signatures[za0002].MarshalHash(); err != nil { - return nil, err - } else { - o = hsp.AppendBytes(o, oTemp) - } - } + o = append(o, 0x83) + if oTemp, err := z.DefaultHashSignVerifierImpl.MarshalHash(); err != nil { + return nil, err + } else { + o = hsp.AppendBytes(o, oTemp) } - o = append(o, 0x84) - if oTemp, err := z.RequestHash.MarshalHash(); err != nil { + o = append(o, 0x83) + if oTemp, err := z.TransactionTypeMixin.MarshalHash(); err != nil { return nil, err } else { o = hsp.AppendBytes(o, oTemp) @@ -53,39 +33,29 @@ func (z *BillingRequest) MarshalHash() (o []byte, err error) { } // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message -func (z *BillingRequest) Msgsize() (s int) { - s = 1 + 7 + z.Header.Msgsize() + 8 + hsp.ArrayHeaderSize - for za0001 := range z.Signees { - if z.Signees[za0001] == nil { - s += hsp.NilSize - } else { - s += z.Signees[za0001].Msgsize() - } - } - s += 11 + hsp.ArrayHeaderSize - for za0002 := range z.Signatures { - if z.Signatures[za0002] == nil { - s += hsp.NilSize - } else { - s += z.Signatures[za0002].Msgsize() - } - } - s += 12 + z.RequestHash.Msgsize() +func (z *Billing) Msgsize() (s int) { + s = 1 + 14 + z.BillingHeader.Msgsize() + 28 + z.DefaultHashSignVerifierImpl.Msgsize() + 21 + z.TransactionTypeMixin.Msgsize() return } // MarshalHash marshals for hash -func (z *BillingRequestHeader) MarshalHash() (o []byte, err error) { +func (z *BillingHeader) MarshalHash() (o []byte, err error) { var b []byte o = hsp.Require(b, z.Msgsize()) // map header, size 6 o = append(o, 0x86, 0x86) - o = hsp.AppendArrayHeader(o, uint32(len(z.GasAmounts))) - for za0001 := range z.GasAmounts { - if z.GasAmounts[za0001] == nil { + if oTemp, err := z.BillingRequest.MarshalHash(); err != nil { + return nil, err + } else { + o = hsp.AppendBytes(o, oTemp) + } + o = append(o, 0x86) + o = hsp.AppendArrayHeader(o, uint32(len(z.Receivers))) + for za0001 := range z.Receivers { + if z.Receivers[za0001] == nil { o = hsp.AppendNil(o) } else { - if oTemp, err := z.GasAmounts[za0001].MarshalHash(); err != nil { + if oTemp, err := z.Receivers[za0001].MarshalHash(); err != nil { return nil, err } else { o = hsp.AppendBytes(o, oTemp) @@ -93,23 +63,23 @@ func (z *BillingRequestHeader) MarshalHash() (o []byte, err error) { } } o = append(o, 0x86) - if oTemp, err := z.LowBlock.MarshalHash(); err != nil { - return nil, err - } else { - o = hsp.AppendBytes(o, oTemp) + o = hsp.AppendArrayHeader(o, uint32(len(z.Fees))) + for za0002 := range z.Fees { + o = hsp.AppendUint64(o, z.Fees[za0002]) } o = append(o, 0x86) - if oTemp, err := z.HighBlock.MarshalHash(); err != nil { + o = hsp.AppendArrayHeader(o, uint32(len(z.Rewards))) + for za0003 := range z.Rewards { + o = hsp.AppendUint64(o, z.Rewards[za0003]) + } + o = append(o, 0x86) + if oTemp, err := z.Nonce.MarshalHash(); err != nil { return nil, err } else { o = hsp.AppendBytes(o, oTemp) } o = append(o, 0x86) - o = hsp.AppendInt32(o, z.LowHeight) - o = append(o, 0x86) - o = hsp.AppendInt32(o, z.HighHeight) - o = append(o, 0x86) - if oTemp, err := z.DatabaseID.MarshalHash(); err != nil { + if oTemp, err := z.Producer.MarshalHash(); err != nil { return nil, err } else { o = hsp.AppendBytes(o, oTemp) @@ -118,73 +88,15 @@ func (z *BillingRequestHeader) MarshalHash() (o []byte, err error) { } // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message -func (z *BillingRequestHeader) Msgsize() (s int) { - s = 1 + 11 + hsp.ArrayHeaderSize - for za0001 := range z.GasAmounts { - if z.GasAmounts[za0001] == nil { +func (z *BillingHeader) Msgsize() (s int) { + s = 1 + 15 + z.BillingRequest.Msgsize() + 10 + hsp.ArrayHeaderSize + for za0001 := range z.Receivers { + if z.Receivers[za0001] == nil { s += hsp.NilSize } else { - s += z.GasAmounts[za0001].Msgsize() - } - } - s += 9 + z.LowBlock.Msgsize() + 10 + z.HighBlock.Msgsize() + 10 + hsp.Int32Size + 11 + hsp.Int32Size + 11 + z.DatabaseID.Msgsize() - return -} - -// MarshalHash marshals for hash -func (z *BillingResponse) MarshalHash() (o []byte, err error) { - var b []byte - o = hsp.Require(b, z.Msgsize()) - // map header, size 4 - o = append(o, 0x84, 0x84) - if z.Signee == nil { - o = hsp.AppendNil(o) - } else { - if oTemp, err := z.Signee.MarshalHash(); err != nil { - return nil, err - } else { - o = hsp.AppendBytes(o, oTemp) - } - } - o = append(o, 0x84) - if z.Signature == nil { - o = hsp.AppendNil(o) - } else { - if oTemp, err := z.Signature.MarshalHash(); err != nil { - return nil, err - } else { - o = hsp.AppendBytes(o, oTemp) + s += z.Receivers[za0001].Msgsize() } } - o = append(o, 0x84) - if oTemp, err := z.RequestHash.MarshalHash(); err != nil { - return nil, err - } else { - o = hsp.AppendBytes(o, oTemp) - } - o = append(o, 0x84) - if oTemp, err := z.AccountAddress.MarshalHash(); err != nil { - return nil, err - } else { - o = hsp.AppendBytes(o, oTemp) - } - return -} - -// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message -func (z *BillingResponse) Msgsize() (s int) { - s = 1 + 7 - if z.Signee == nil { - s += hsp.NilSize - } else { - s += z.Signee.Msgsize() - } - s += 10 - if z.Signature == nil { - s += hsp.NilSize - } else { - s += z.Signature.Msgsize() - } - s += 12 + z.RequestHash.Msgsize() + 15 + z.AccountAddress.Msgsize() + s += 5 + hsp.ArrayHeaderSize + (len(z.Fees) * (hsp.Uint64Size)) + 8 + hsp.ArrayHeaderSize + (len(z.Rewards) * (hsp.Uint64Size)) + 6 + z.Nonce.Msgsize() + 9 + z.Producer.Msgsize() return } diff --git a/blockproducer/types/billing_gen_test.go b/blockproducer/types/billing_gen_test.go index 1ad0c1426..845a15213 100644 --- a/blockproducer/types/billing_gen_test.go +++ b/blockproducer/types/billing_gen_test.go @@ -9,8 +9,8 @@ import ( "testing" ) -func TestMarshalHashBillingRequest(t *testing.T) { - v := BillingRequest{} +func TestMarshalHashBilling(t *testing.T) { + v := Billing{} binary.Read(rand.Reader, binary.BigEndian, &v) bts1, err := v.MarshalHash() if err != nil { @@ -25,8 +25,8 @@ func TestMarshalHashBillingRequest(t *testing.T) { } } -func BenchmarkMarshalHashBillingRequest(b *testing.B) { - v := BillingRequest{} +func BenchmarkMarshalHashBilling(b *testing.B) { + v := Billing{} b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { @@ -34,8 +34,8 @@ func BenchmarkMarshalHashBillingRequest(b *testing.B) { } } -func BenchmarkAppendMsgBillingRequest(b *testing.B) { - v := BillingRequest{} +func BenchmarkAppendMsgBilling(b *testing.B) { + v := Billing{} bts := make([]byte, 0, v.Msgsize()) bts, _ = v.MarshalHash() b.SetBytes(int64(len(bts))) @@ -46,8 +46,8 @@ func BenchmarkAppendMsgBillingRequest(b *testing.B) { } } -func TestMarshalHashBillingRequestHeader(t *testing.T) { - v := BillingRequestHeader{} +func TestMarshalHashBillingHeader(t *testing.T) { + v := BillingHeader{} binary.Read(rand.Reader, binary.BigEndian, &v) bts1, err := v.MarshalHash() if err != nil { @@ -62,8 +62,8 @@ func TestMarshalHashBillingRequestHeader(t *testing.T) { } } -func BenchmarkMarshalHashBillingRequestHeader(b *testing.B) { - v := BillingRequestHeader{} +func BenchmarkMarshalHashBillingHeader(b *testing.B) { + v := BillingHeader{} b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { @@ -71,45 +71,8 @@ func BenchmarkMarshalHashBillingRequestHeader(b *testing.B) { } } -func BenchmarkAppendMsgBillingRequestHeader(b *testing.B) { - v := BillingRequestHeader{} - bts := make([]byte, 0, v.Msgsize()) - bts, _ = v.MarshalHash() - b.SetBytes(int64(len(bts))) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - bts, _ = v.MarshalHash() - } -} - -func TestMarshalHashBillingResponse(t *testing.T) { - v := BillingResponse{} - binary.Read(rand.Reader, binary.BigEndian, &v) - bts1, err := v.MarshalHash() - if err != nil { - t.Fatal(err) - } - bts2, err := v.MarshalHash() - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(bts1, bts2) { - t.Fatal("hash not stable") - } -} - -func BenchmarkMarshalHashBillingResponse(b *testing.B) { - v := BillingResponse{} - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - v.MarshalHash() - } -} - -func BenchmarkAppendMsgBillingResponse(b *testing.B) { - v := BillingResponse{} +func BenchmarkAppendMsgBillingHeader(b *testing.B) { + v := BillingHeader{} bts := make([]byte, 0, v.Msgsize()) bts, _ = v.MarshalHash() b.SetBytes(int64(len(bts))) diff --git a/blockproducer/types/billing_request.go b/blockproducer/types/billing_request.go new file mode 100644 index 000000000..14d96c1b9 --- /dev/null +++ b/blockproducer/types/billing_request.go @@ -0,0 +1,155 @@ +/* + * Copyright 2018 The CovenantSQL Authors. + * + * 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. + */ + +package types + +import ( + "reflect" + + "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" + "github.com/CovenantSQL/CovenantSQL/crypto/hash" + "github.com/CovenantSQL/CovenantSQL/proto" +) + +//go:generate hsp + +// BillingRequestHeader includes contents that need to be signed. Billing blocks should be within +// height range [low, high] (inclusive). +type BillingRequestHeader struct { + DatabaseID proto.DatabaseID + // sqlchain block hash and its height + LowBlock hash.Hash + LowHeight int32 + HighBlock hash.Hash + HighHeight int32 + GasAmounts []*proto.AddrAndGas +} + +// BillingRequest defines periodically Billing sync. +type BillingRequest struct { + Header BillingRequestHeader + RequestHash hash.Hash + Signees []*asymmetric.PublicKey + Signatures []*asymmetric.Signature +} + +// PackRequestHeader computes the hash of header. +func (br *BillingRequest) PackRequestHeader() (h *hash.Hash, err error) { + var enc []byte + if enc, err = br.Header.MarshalHash(); err != nil { + return + } + + br.RequestHash = hash.THashH(enc) + h = &br.RequestHash + return +} + +// SignRequestHeader first computes the hash of BillingRequestHeader, then signs the request. +func (br *BillingRequest) SignRequestHeader(signer *asymmetric.PrivateKey, calcHash bool) ( + signee *asymmetric.PublicKey, signature *asymmetric.Signature, err error) { + if calcHash { + if _, err = br.PackRequestHeader(); err != nil { + return + } + } + + if signature, err = signer.Sign(br.RequestHash[:]); err == nil { + // append to current signatures + signee = signer.PubKey() + br.Signees = append(br.Signees, signee) + br.Signatures = append(br.Signatures, signature) + } + + return +} + +// AddSignature add existing signature to BillingRequest, requires the structure to be packed first. +func (br *BillingRequest) AddSignature( + signee *asymmetric.PublicKey, signature *asymmetric.Signature, calcHash bool) (err error) { + if calcHash { + if _, err = br.PackRequestHeader(); err != nil { + return + } + } + + if !signature.Verify(br.RequestHash[:], signee) { + err = ErrSignVerification + return + } + + // append + br.Signees = append(br.Signees, signee) + br.Signatures = append(br.Signatures, signature) + + return +} + +// VerifySignatures verify existing signatures. +func (br *BillingRequest) VerifySignatures() (err error) { + if len(br.Signees) != len(br.Signatures) { + return ErrSignVerification + } + + var enc []byte + if enc, err = br.Header.MarshalHash(); err != nil { + return + } + + h := hash.THashH(enc) + if !br.RequestHash.IsEqual(&h) { + return ErrSignVerification + } + + if len(br.Signees) == 0 { + return + } + + for idx, signee := range br.Signees { + if !br.Signatures[idx].Verify(br.RequestHash[:], signee) { + return ErrSignVerification + } + } + + return +} + +// Compare returns if two billing records are identical. +func (br *BillingRequest) Compare(r *BillingRequest) (err error) { + if !br.Header.LowBlock.IsEqual(&r.Header.LowBlock) || + !br.Header.HighBlock.IsEqual(&br.Header.HighBlock) { + err = ErrBillingNotMatch + return + } + + reqMap := make(map[proto.AccountAddress]*proto.AddrAndGas) + locMap := make(map[proto.AccountAddress]*proto.AddrAndGas) + + for _, v := range br.Header.GasAmounts { + reqMap[v.AccountAddress] = v + } + + for _, v := range r.Header.GasAmounts { + locMap[v.AccountAddress] = v + } + + if !reflect.DeepEqual(reqMap, locMap) { + err = ErrBillingNotMatch + return + } + + return +} diff --git a/blockproducer/types/billing_request_gen.go b/blockproducer/types/billing_request_gen.go new file mode 100644 index 000000000..48da8b034 --- /dev/null +++ b/blockproducer/types/billing_request_gen.go @@ -0,0 +1,132 @@ +package types + +// Code generated by github.com/CovenantSQL/HashStablePack DO NOT EDIT. + +import ( + hsp "github.com/CovenantSQL/HashStablePack/marshalhash" +) + +// MarshalHash marshals for hash +func (z *BillingRequest) MarshalHash() (o []byte, err error) { + var b []byte + o = hsp.Require(b, z.Msgsize()) + // map header, size 4 + o = append(o, 0x84, 0x84) + if oTemp, err := z.Header.MarshalHash(); err != nil { + return nil, err + } else { + o = hsp.AppendBytes(o, oTemp) + } + o = append(o, 0x84) + o = hsp.AppendArrayHeader(o, uint32(len(z.Signees))) + for za0001 := range z.Signees { + if z.Signees[za0001] == nil { + o = hsp.AppendNil(o) + } else { + if oTemp, err := z.Signees[za0001].MarshalHash(); err != nil { + return nil, err + } else { + o = hsp.AppendBytes(o, oTemp) + } + } + } + o = append(o, 0x84) + o = hsp.AppendArrayHeader(o, uint32(len(z.Signatures))) + for za0002 := range z.Signatures { + if z.Signatures[za0002] == nil { + o = hsp.AppendNil(o) + } else { + if oTemp, err := z.Signatures[za0002].MarshalHash(); err != nil { + return nil, err + } else { + o = hsp.AppendBytes(o, oTemp) + } + } + } + o = append(o, 0x84) + if oTemp, err := z.RequestHash.MarshalHash(); err != nil { + return nil, err + } else { + o = hsp.AppendBytes(o, oTemp) + } + return +} + +// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message +func (z *BillingRequest) Msgsize() (s int) { + s = 1 + 7 + z.Header.Msgsize() + 8 + hsp.ArrayHeaderSize + for za0001 := range z.Signees { + if z.Signees[za0001] == nil { + s += hsp.NilSize + } else { + s += z.Signees[za0001].Msgsize() + } + } + s += 11 + hsp.ArrayHeaderSize + for za0002 := range z.Signatures { + if z.Signatures[za0002] == nil { + s += hsp.NilSize + } else { + s += z.Signatures[za0002].Msgsize() + } + } + s += 12 + z.RequestHash.Msgsize() + return +} + +// MarshalHash marshals for hash +func (z *BillingRequestHeader) MarshalHash() (o []byte, err error) { + var b []byte + o = hsp.Require(b, z.Msgsize()) + // map header, size 6 + o = append(o, 0x86, 0x86) + o = hsp.AppendArrayHeader(o, uint32(len(z.GasAmounts))) + for za0001 := range z.GasAmounts { + if z.GasAmounts[za0001] == nil { + o = hsp.AppendNil(o) + } else { + if oTemp, err := z.GasAmounts[za0001].MarshalHash(); err != nil { + return nil, err + } else { + o = hsp.AppendBytes(o, oTemp) + } + } + } + o = append(o, 0x86) + if oTemp, err := z.LowBlock.MarshalHash(); err != nil { + return nil, err + } else { + o = hsp.AppendBytes(o, oTemp) + } + o = append(o, 0x86) + if oTemp, err := z.HighBlock.MarshalHash(); err != nil { + return nil, err + } else { + o = hsp.AppendBytes(o, oTemp) + } + o = append(o, 0x86) + o = hsp.AppendInt32(o, z.LowHeight) + o = append(o, 0x86) + o = hsp.AppendInt32(o, z.HighHeight) + o = append(o, 0x86) + if oTemp, err := z.DatabaseID.MarshalHash(); err != nil { + return nil, err + } else { + o = hsp.AppendBytes(o, oTemp) + } + return +} + +// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message +func (z *BillingRequestHeader) Msgsize() (s int) { + s = 1 + 11 + hsp.ArrayHeaderSize + for za0001 := range z.GasAmounts { + if z.GasAmounts[za0001] == nil { + s += hsp.NilSize + } else { + s += z.GasAmounts[za0001].Msgsize() + } + } + s += 9 + z.LowBlock.Msgsize() + 10 + z.HighBlock.Msgsize() + 10 + hsp.Int32Size + 11 + hsp.Int32Size + 11 + z.DatabaseID.Msgsize() + return +} diff --git a/blockproducer/types/txsqlchainbilling_gen_test.go b/blockproducer/types/billing_request_gen_test.go similarity index 70% rename from blockproducer/types/txsqlchainbilling_gen_test.go rename to blockproducer/types/billing_request_gen_test.go index add50d6f9..d46613c46 100644 --- a/blockproducer/types/txsqlchainbilling_gen_test.go +++ b/blockproducer/types/billing_request_gen_test.go @@ -9,8 +9,8 @@ import ( "testing" ) -func TestMarshalHashTxBilling(t *testing.T) { - v := TxBilling{} +func TestMarshalHashBillingRequest(t *testing.T) { + v := BillingRequest{} binary.Read(rand.Reader, binary.BigEndian, &v) bts1, err := v.MarshalHash() if err != nil { @@ -25,8 +25,8 @@ func TestMarshalHashTxBilling(t *testing.T) { } } -func BenchmarkMarshalHashTxBilling(b *testing.B) { - v := TxBilling{} +func BenchmarkMarshalHashBillingRequest(b *testing.B) { + v := BillingRequest{} b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { @@ -34,8 +34,8 @@ func BenchmarkMarshalHashTxBilling(b *testing.B) { } } -func BenchmarkAppendMsgTxBilling(b *testing.B) { - v := TxBilling{} +func BenchmarkAppendMsgBillingRequest(b *testing.B) { + v := BillingRequest{} bts := make([]byte, 0, v.Msgsize()) bts, _ = v.MarshalHash() b.SetBytes(int64(len(bts))) @@ -46,8 +46,8 @@ func BenchmarkAppendMsgTxBilling(b *testing.B) { } } -func TestMarshalHashTxContent(t *testing.T) { - v := TxContent{} +func TestMarshalHashBillingRequestHeader(t *testing.T) { + v := BillingRequestHeader{} binary.Read(rand.Reader, binary.BigEndian, &v) bts1, err := v.MarshalHash() if err != nil { @@ -62,8 +62,8 @@ func TestMarshalHashTxContent(t *testing.T) { } } -func BenchmarkMarshalHashTxContent(b *testing.B) { - v := TxContent{} +func BenchmarkMarshalHashBillingRequestHeader(b *testing.B) { + v := BillingRequestHeader{} b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { @@ -71,8 +71,8 @@ func BenchmarkMarshalHashTxContent(b *testing.B) { } } -func BenchmarkAppendMsgTxContent(b *testing.B) { - v := TxContent{} +func BenchmarkAppendMsgBillingRequestHeader(b *testing.B) { + v := BillingRequestHeader{} bts := make([]byte, 0, v.Msgsize()) bts, _ = v.MarshalHash() b.SetBytes(int64(len(bts))) diff --git a/blockproducer/types/billing_request_test.go b/blockproducer/types/billing_request_test.go new file mode 100644 index 000000000..c6d7ee998 --- /dev/null +++ b/blockproducer/types/billing_request_test.go @@ -0,0 +1,339 @@ +/* + * Copyright 2018 The CovenantSQL Authors. + * + * 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. + */ + +package types + +import ( + "reflect" + "testing" + + "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" + "github.com/CovenantSQL/CovenantSQL/crypto/hash" + "github.com/CovenantSQL/CovenantSQL/proto" + "github.com/CovenantSQL/CovenantSQL/utils" + "github.com/CovenantSQL/CovenantSQL/utils/log" +) + +var ( + peerNum = 32 +) + +func TestBillingRequestHeader_MarshalUnmarshalBinary(t *testing.T) { + reqHeader := generateRandomBillingRequestHeader() + b, err := utils.EncodeMsgPack(reqHeader) + if err != nil { + t.Fatalf("unexpect error when marshal request header: %v", err) + } + + newReqHeader := &BillingRequestHeader{} + err = utils.DecodeMsgPack(b.Bytes(), newReqHeader) + if err != nil { + t.Fatalf("unexpect error when unmashll request header: %v", err) + } + + if !reflect.DeepEqual(reqHeader, newReqHeader) { + t.Fatalf("values not match:\n\tv0=%+v\n\tv1=%+v", reqHeader, newReqHeader) + } +} + +func TestBillingRequest_MarshalUnmarshalBinary(t *testing.T) { + req, err := generateRandomBillingRequest() + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + enc, err := utils.EncodeMsgPack(req) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + dec := &BillingRequest{} + err = utils.DecodeMsgPack(enc.Bytes(), dec) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if !reflect.DeepEqual(req, dec) { + log.Debug(req) + log.Debug(dec) + t.Fatal("values not match") + } +} + +func TestBillingRequest_PackRequestHeader(t *testing.T) { + req, err := generateRandomBillingRequest() + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + enc, err := req.Header.MarshalHash() + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + h := hash.THashH(enc) + if !h.IsEqual(&req.RequestHash) { + t.Fatalf("hash not matched: \n\tv1=%v\n\tv2=%v", req.RequestHash, h) + } +} + +func TestBillingRequest_SignRequestHeader(t *testing.T) { + req, err := generateRandomBillingRequest() + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + enc, err := req.Header.MarshalHash() + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + h := hash.THashH(enc) + if !h.IsEqual(&req.RequestHash) { + t.Fatalf("hash not matched: \n\tv1=%v\n\tv2=%v", req.RequestHash, h) + } + + for i, sign := range req.Signatures { + if !sign.Verify(req.RequestHash[:], req.Signees[i]) { + + t.Fatalf("signature cannot match the hash and public key: %v", req) + } + } + + priv, pub, err := asymmetric.GenSecp256k1KeyPair() + _, sign, err := req.SignRequestHeader(priv, false) + if err != nil || !sign.Verify(req.RequestHash[:], pub) { + t.Fatalf("signature cannot match the hash and public key: %v", req) + } +} + +func TestBillingRequest_SignRequestHeader2(t *testing.T) { + header := generateRandomBillingRequestHeader() + req := &BillingRequest{ + Header: *header, + } + + priv, _, err := asymmetric.GenSecp256k1KeyPair() + signee, sign, err := req.SignRequestHeader(priv, true) + if err != nil || !sign.Verify(req.RequestHash[:], signee) { + t.Fatalf("signature cannot match the hash and public key: %v", req) + } +} + +func TestBillingRequest_AddSignature(t *testing.T) { + header := generateRandomBillingRequestHeader() + req := &BillingRequest{ + Header: *header, + } + + priv, _, err := asymmetric.GenSecp256k1KeyPair() + signee, sign, err := req.SignRequestHeader(priv, true) + if err != nil || !sign.Verify(req.RequestHash[:], signee) { + t.Fatalf("signature cannot match the hash and public key, req: %v, err: %v", req, err) + } + + // clear previous signees and signatures + req.Signees = req.Signees[:0] + req.Signatures = req.Signatures[:0] + + if err := req.AddSignature(signee, sign, false); err != nil { + t.Fatalf("add signature failed, req: %v, err: %v", req, err) + } +} + +func TestBillingRequest_AddSignature2(t *testing.T) { + header := generateRandomBillingRequestHeader() + req := &BillingRequest{ + Header: *header, + } + + priv, _, err := asymmetric.GenSecp256k1KeyPair() + signee, sign, err := req.SignRequestHeader(priv, true) + if err != nil || !sign.Verify(req.RequestHash[:], signee) { + t.Fatalf("signature cannot match the hash and public key, req: %v, err: %v", req, err) + } + + // clear previous signees and signatures + req.RequestHash = hash.Hash{} + req.Signees = req.Signees[:0] + req.Signatures = req.Signatures[:0] + + if err := req.AddSignature(signee, sign, true); err != nil { + t.Fatalf("add signature failed, req: %v, err: %v", req, err) + } +} + +func TestBillingRequest_AddSignature3(t *testing.T) { + header := generateRandomBillingRequestHeader() + req := &BillingRequest{ + Header: *header, + } + + priv, _, err := asymmetric.GenSecp256k1KeyPair() + signee, sign, err := req.SignRequestHeader(priv, true) + if err != nil || !sign.Verify(req.RequestHash[:], signee) { + t.Fatalf("signature cannot match the hash and public key, req: %v, err: %v", req, err) + } + + // clear previous signees and signatures + req.RequestHash = hash.Hash{} + req.Signees = req.Signees[:0] + req.Signatures = req.Signatures[:0] + + _, signee, _ = asymmetric.GenSecp256k1KeyPair() + if err := req.AddSignature(signee, sign, true); err != ErrSignVerification { + t.Fatalf("add signature should failed, req: %v, err: %v", req, err) + } +} + +func TestBillingRequest_VerifySignatures(t *testing.T) { + header := generateRandomBillingRequestHeader() + req := &BillingRequest{ + Header: *header, + } + + addSignature := func(calcHash bool) { + priv, _, err := asymmetric.GenSecp256k1KeyPair() + _, _, err = req.SignRequestHeader(priv, calcHash) + if err != nil { + t.Fatalf("sign request failed, req: %v, err: %v", req, err) + } + } + + // add 3 signatures + addSignature(true) + addSignature(false) + addSignature(false) + + if err := req.VerifySignatures(); err != nil { + t.Fatalf("verify signature failed, req: %v, err: %v", req, err) + } +} + +func TestBillingRequest_VerifySignatures2(t *testing.T) { + header := generateRandomBillingRequestHeader() + req := &BillingRequest{ + Header: *header, + } + + addSignature := func(calcHash bool) { + priv, _, err := asymmetric.GenSecp256k1KeyPair() + _, _, err = req.SignRequestHeader(priv, calcHash) + if err != nil { + t.Fatalf("sign request failed, req: %v, err: %v", req, err) + } + } + + // add 3 signatures + addSignature(true) + addSignature(false) + addSignature(false) + + // length invalidation + req.Signees = req.Signees[:0] + + if err := req.VerifySignatures(); err != ErrSignVerification { + t.Fatalf("verify should be failed, req: %v, err: %v", req, err) + } +} + +func TestBillingRequest_VerifySignatures3(t *testing.T) { + header := generateRandomBillingRequestHeader() + req := &BillingRequest{ + Header: *header, + } + + addSignature := func(calcHash bool) { + priv, _, err := asymmetric.GenSecp256k1KeyPair() + _, _, err = req.SignRequestHeader(priv, calcHash) + if err != nil { + t.Fatalf("sign request failed, req: %v, err: %v", req, err) + } + } + + // add 3 signatures + addSignature(true) + addSignature(false) + addSignature(false) + + // length invalidation + req.RequestHash = hash.Hash{} + + if err := req.VerifySignatures(); err != ErrSignVerification { + t.Fatalf("verify should be failed, req: %v, err: %v", req, err) + } +} + +func TestBillingRequest_VerifySignatures4(t *testing.T) { + header := generateRandomBillingRequestHeader() + req := &BillingRequest{ + Header: *header, + } + + addSignature := func(calcHash bool) { + priv, _, err := asymmetric.GenSecp256k1KeyPair() + _, _, err = req.SignRequestHeader(priv, calcHash) + if err != nil { + t.Fatalf("sign request failed, req: %v, err: %v", req, err) + } + } + + // add 3 signatures + addSignature(true) + addSignature(false) + addSignature(false) + + // length invalidation + _, req.Signees[0], _ = asymmetric.GenSecp256k1KeyPair() + + if err := req.VerifySignatures(); err == nil || err != ErrSignVerification { + t.Fatalf("verify should be failed, req: %v, err: %v", req, err) + } +} + +func TestBillingRequest_Compare(t *testing.T) { + req, _ := generateRandomBillingRequest() + + if err := req.Compare(req); err != nil { + t.Fatalf("compare failed, req: %v, err: %v", req, err) + } + + var req2 BillingRequest + req2 = *req + + req2.Header.LowBlock = hash.Hash{} + + if err := req.Compare(&req2); err != ErrBillingNotMatch { + t.Fatalf("compare should be failed, req: %v, req2: %v, err: %v", req, req2, err) + } +} + +func TestBillingRequest_Compare2(t *testing.T) { + req, _ := generateRandomBillingRequest() + var req2 BillingRequest + req2 = *req + + var gasAmount proto.AddrAndGas + gasAmount = *req.Header.GasAmounts[0] + gasAmount.GasAmount += 10 + req2.Header.GasAmounts = nil + req2.Header.GasAmounts = append(req2.Header.GasAmounts, &gasAmount) + req2.Header.GasAmounts = append(req2.Header.GasAmounts, req.Header.GasAmounts[1:]...) + + if err := req.Compare(&req2); err != ErrBillingNotMatch { + t.Fatalf("compare should be failed, req: %v, req2: %v, err: %v", req, req2, err) + } +} diff --git a/blockproducer/types/billing_test.go b/blockproducer/types/billing_test.go index 9f3f49446..bafa32c10 100644 --- a/blockproducer/types/billing_test.go +++ b/blockproducer/types/billing_test.go @@ -20,124 +20,104 @@ import ( "reflect" "testing" - "github.com/CovenantSQL/CovenantSQL/utils" - "github.com/CovenantSQL/CovenantSQL/utils/log" - "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" "github.com/CovenantSQL/CovenantSQL/crypto/hash" + "github.com/CovenantSQL/CovenantSQL/utils" ) -var ( - peerNum uint32 = 32 -) - -func TestBillingRequestHeader_MarshalUnmarshalBinary(t *testing.T) { - reqHeader := generateRandomBillingRequestHeader() - b, err := utils.EncodeMsgPack(reqHeader) +func TestBillingHeader_MarshalUnmarshalBinary(t *testing.T) { + tc, err := generateRandomBillingHeader() if err != nil { - t.Fatalf("unexpect error when marshal request header: %v", err) + t.Fatalf("Unexpeted error: %v", err) } - newReqHeader := &BillingRequestHeader{} - err = utils.DecodeMsgPack(b.Bytes(), newReqHeader) + enc, err := utils.EncodeMsgPack(tc) if err != nil { - t.Fatalf("unexpect error when unmashll request header: %v", err) + t.Fatalf("Unexpeted error: %v", err) } - if !reflect.DeepEqual(reqHeader, newReqHeader) { - t.Fatalf("values not match:\n\tv0=%+v\n\tv1=%+v", reqHeader, newReqHeader) - } -} - -func TestBillingRequest_MarshalUnmarshalBinary(t *testing.T) { - req, err := generateRandomBillingRequest() - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - enc, err := utils.EncodeMsgPack(req) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - dec := &BillingRequest{} + dec := &BillingHeader{} err = utils.DecodeMsgPack(enc.Bytes(), dec) if err != nil { - t.Fatalf("unexpected error: %v", err) + t.Fatalf("Unexpeted error: %v", err) } - if !reflect.DeepEqual(req, dec) { - log.Debug(req) - log.Debug(dec) - t.Fatal("values not match") + if tc.Nonce != dec.Nonce { + t.Fatalf("Value not match: \n\tv1=%v\n\tv2=%v", tc.Nonce, tc.Nonce) } -} - -func TestBillingRequest_PackRequestHeader(t *testing.T) { - req, err := generateRandomBillingRequest() - if err != nil { - t.Fatalf("unexpected error: %v", err) + if tc.BillingRequest.RequestHash != dec.BillingRequest.RequestHash { + t.Fatalf("Value not match: \n\tv1=%v\n\tv2=%v", tc.BillingRequest.RequestHash, tc.BillingRequest.RequestHash) } - - enc, err := req.Header.MarshalHash() - if err != nil { - t.Fatalf("unexpected error: %v", err) + if !tc.BillingRequest.Signatures[0].IsEqual(dec.BillingRequest.Signatures[0]) { + t.Fatalf("Value not match: \n\tv1=%v\n\tv2=%v", tc.BillingRequest.Signatures[0], dec.BillingRequest.Signatures[0]) } - - h := hash.THashH(enc) - if !h.IsEqual(&req.RequestHash) { - t.Fatalf("hash not matched: \n\tv1=%v\n\tv2=%v", req.RequestHash, h) + for i := range tc.Receivers { + if !reflect.DeepEqual(tc.Receivers[i], dec.Receivers[i]) { + t.Fatalf("Value not match: \n\ttc.Receivers[%d]=%v\n\tReceive[%d]=%v", i, i, tc.Receivers[i], tc.Receivers[0]) + } + if tc.Rewards[i] != dec.Rewards[i] { + t.Fatalf("Value not match: \n\ttc.Rewards[%d]=%v\n\tRewards[%d]=%v", i, i, tc.Rewards[i], tc.Rewards[0]) + } + if tc.Fees[i] != dec.Fees[i] { + t.Fatalf("Value not match: \n\ttc.Fees[%d]=%v\n\tFees[%d]=%v", i, i, tc.Fees[i], tc.Fees[0]) + } } } -func TestBillingRequest_SignRequestHeader(t *testing.T) { - req, err := generateRandomBillingRequest() +func TestBilling_SerializeDeserialize(t *testing.T) { + tb, err := generateRandomBilling() if err != nil { - t.Fatalf("unexpected error: %v", err) + t.Fatalf("Unexpeted error: %v", err) } - enc, err := req.Header.MarshalHash() + enc, err := utils.EncodeMsgPack(tb) if err != nil { - t.Fatalf("unexpected error: %v", err) + t.Fatalf("Unexpeted error: %v", err) } - h := hash.THashH(enc) - if !h.IsEqual(&req.RequestHash) { - t.Fatalf("hash not matched: \n\tv1=%v\n\tv2=%v", req.RequestHash, h) + dec := Billing{} + err = utils.DecodeMsgPack(enc.Bytes(), &dec) + if err != nil { + t.Fatalf("Unexpeted error: %v", err) } - for i, sign := range req.Signatures { - if !sign.Verify(req.RequestHash[:], req.Signees[i]) { - - t.Fatalf("signature cannot match the hash and public key: %v", req) - } + if !tb.Signature.IsEqual(dec.Signature) { + t.Fatalf("Value not match: \n\tv1=%v\n\tv2=%v", tb.Signature, tb.Signature) } - - priv, pub, err := asymmetric.GenSecp256k1KeyPair() - sign, err := req.SignRequestHeader(priv) - if !sign.Verify(req.RequestHash[:], pub) { - t.Fatalf("signature cannot match the hash and public key: %v", req) + if !tb.Signee.IsEqual(dec.Signee) { + t.Fatalf("Value not match: \n\tv1=%v\n\tv2=%v", tb.Signee, tb.Signee) } - sign, err = req.SignRequestHeader(priv) - if !sign.Verify(req.RequestHash[:], pub) { - t.Fatalf("signature cannot match the hash and public key: %v", req) + if !tb.Hash.IsEqual(&dec.Hash) { + t.Fatalf("Value not match: \n\tv1=%v\n\tv2=%v", tb.Hash, tb.Hash) } } -func TestBillingResponse_MarshalUnmarshalBinary(t *testing.T) { - resp, err := generateRandomBillingResponse() +func TestBilling_PackAndSignTx(t *testing.T) { + tb, err := generateRandomBilling() if err != nil { - t.Fatalf("unexpected error: %v", err) + t.Fatalf("Unexpeted error: %v", err) } - enc, err := utils.EncodeMsgPack(resp) + priv, _, err := asymmetric.GenSecp256k1KeyPair() + if err != nil { + t.Fatalf("Unexpeted error: %v", err) + } + tb.Sign(priv) + enc, err := tb.BillingHeader.MarshalHash() if err != nil { - t.Fatalf("unexpected error: %v", err) + t.Fatalf("Unexpeted error: %v", err) + } + h := hash.THashH(enc[:]) + sign, err := priv.Sign(h[:]) + if err != nil { + t.Fatalf("Unexpeted error: %v", err) + } + if !sign.IsEqual(tb.Signature) { + t.Fatalf("Value not match: \n\tv1=%v\n\tv2=%v", sign, tb.Signature) } - dec := &BillingResponse{} - err = utils.DecodeMsgPack(enc.Bytes(), dec) + err = tb.Verify() if err != nil { - t.Fatalf("unexpected error: %v", err) + t.Fatalf("Verify signature failed: %v", err) } } diff --git a/blockproducer/types/block.go b/blockproducer/types/block.go index 515f6c595..a2f88d642 100644 --- a/blockproducer/types/block.go +++ b/blockproducer/types/block.go @@ -17,8 +17,6 @@ package types import ( - "bytes" - "reflect" "time" pi "github.com/CovenantSQL/CovenantSQL/blockproducer/interfaces" @@ -26,7 +24,6 @@ import ( "github.com/CovenantSQL/CovenantSQL/crypto/hash" "github.com/CovenantSQL/CovenantSQL/merkle" "github.com/CovenantSQL/CovenantSQL/proto" - "github.com/ugorji/go/codec" ) //go:generate hsp @@ -60,22 +57,18 @@ func (s *SignedHeader) Verify() error { // Block defines the main chain block. type Block struct { SignedHeader SignedHeader - TxBillings []*TxBilling Transactions []pi.Transaction } -// GetTxHashes returns all hashes of tx in block.{TxBillings, ...} +// GetTxHashes returns all hashes of tx in block.{Billings, ...} func (b *Block) GetTxHashes() []*hash.Hash { // TODO(lambda): when you add new tx type, you need to put new tx's hash in the slice - // get hashes in block.TxBillings - bl := len(b.TxBillings) - hs := make([]*hash.Hash, len(b.TxBillings)+len(b.Transactions)) - for i, v := range b.TxBillings { - hs[i] = v.TxHash - } + // get hashes in block.Transactions + hs := make([]*hash.Hash, len(b.Transactions)) + for i, v := range b.Transactions { h := v.GetHash() - hs[bl+i] = &h + hs[i] = &h } return hs } @@ -102,64 +95,6 @@ func (b *Block) PackAndSignBlock(signer *asymmetric.PrivateKey) error { return nil } -func enumType(t pi.TransactionType) (i pi.Transaction) { - switch t { - case pi.TransactionTypeBilling: - i = (*TxBilling)(nil) - case pi.TransactionTypeTransfer: - i = (*Transfer)(nil) - case pi.TransactionTypeBaseAccount: - i = (*BaseAccount)(nil) - case pi.TransactionTypeCreataDatabase: - i = (*CreateDatabase)(nil) - } - return -} - -// Serialize converts block to bytes. -func (b *Block) Serialize() ([]byte, error) { - buf := bytes.NewBuffer(nil) - hd := codec.MsgpackHandle{ - WriteExt: true, - RawToString: true, - } - enc := codec.NewEncoder(buf, &hd) - err := enc.Encode(b) - return buf.Bytes(), err -} - -// Deserialize converts bytes to block. -func (b *Block) Deserialize(buf []byte) error { - r := bytes.NewBuffer(buf) - hd := codec.MsgpackHandle{ - WriteExt: true, - RawToString: true, - } - - for i := pi.TransactionType(0); i < pi.TransactionTypeNumber; i++ { - err := hd.Intf2Impl( - reflect.TypeOf((*pi.Transaction)(nil)).Elem(), - reflect.TypeOf(enumType(i)), - ) - if err != nil { - return err - } - } - - dec := codec.NewDecoder(r, &hd) - return dec.Decode(b) -} - -// PushTx pushes txes into block. -func (b *Block) PushTx(tx *TxBilling) { - if b.TxBillings != nil { - // TODO(lambda): set appropriate capacity. - b.TxBillings = make([]*TxBilling, 0, 100) - } - - b.TxBillings = append(b.TxBillings, tx) -} - // Verify verifies whether the block is valid. func (b *Block) Verify() error { hs := b.GetTxHashes() @@ -190,3 +125,13 @@ func (b *Block) Timestamp() time.Time { func (b *Block) Producer() proto.AccountAddress { return b.SignedHeader.Producer } + +// ParentHash returns the parent hash field of the block header. +func (b *Block) ParentHash() *hash.Hash { + return &b.SignedHeader.ParentHash +} + +// BlockHash returns the parent hash field of the block header. +func (b *Block) BlockHash() *hash.Hash { + return &b.SignedHeader.BlockHash +} diff --git a/blockproducer/types/block_gen.go b/blockproducer/types/block_gen.go index 5398974ce..1a0814c1c 100644 --- a/blockproducer/types/block_gen.go +++ b/blockproducer/types/block_gen.go @@ -18,16 +18,12 @@ func (z *Block) MarshalHash() (o []byte, err error) { o = hsp.AppendBytes(o, oTemp) } o = append(o, 0x82) - o = hsp.AppendArrayHeader(o, uint32(len(z.TxBillings))) - for za0001 := range z.TxBillings { - if z.TxBillings[za0001] == nil { - o = hsp.AppendNil(o) + o = hsp.AppendArrayHeader(o, uint32(len(z.Transactions))) + for za0001 := range z.Transactions { + if oTemp, err := z.Transactions[za0001].MarshalHash(); err != nil { + return nil, err } else { - if oTemp, err := z.TxBillings[za0001].MarshalHash(); err != nil { - return nil, err - } else { - o = hsp.AppendBytes(o, oTemp) - } + o = hsp.AppendBytes(o, oTemp) } } return @@ -35,13 +31,9 @@ func (z *Block) MarshalHash() (o []byte, err error) { // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message func (z *Block) Msgsize() (s int) { - s = 1 + 13 + z.SignedHeader.Msgsize() + 11 + hsp.ArrayHeaderSize - for za0001 := range z.TxBillings { - if z.TxBillings[za0001] == nil { - s += hsp.NilSize - } else { - s += z.TxBillings[za0001].Msgsize() - } + s = 1 + 13 + z.SignedHeader.Msgsize() + 13 + hsp.ArrayHeaderSize + for za0001 := range z.Transactions { + s += z.Transactions[za0001].Msgsize() } return } diff --git a/blockproducer/types/block_test.go b/blockproducer/types/block_test.go index e2c42bf0d..403123ea6 100644 --- a/blockproducer/types/block_test.go +++ b/blockproducer/types/block_test.go @@ -17,14 +17,12 @@ package types import ( + "bytes" "encoding" "reflect" "testing" - "bytes" - "github.com/CovenantSQL/CovenantSQL/utils" - . "github.com/smartystreets/goconvey/convey" ) func TestHeader_MarshalUnmarshalBinary(t *testing.T) { @@ -86,14 +84,13 @@ func TestBlock_MarshalUnmarshalBinary(t *testing.T) { t.Log("dec hash BinaryMashaler interface") } - enc, err := block.Serialize() + enc, err := utils.EncodeMsgPack(block) if err != nil { t.Fatalf("Failed to mashal binary: %v", err) } dec := &Block{} - - err = dec.Deserialize(enc) + err = utils.DecodeMsgPack(enc.Bytes(), dec) if err != nil { t.Fatalf("Failed to unmashal binary: %v", err) } @@ -109,10 +106,6 @@ func TestBlock_MarshalUnmarshalBinary(t *testing.T) { if !bytes.Equal(bts1, bts2) { t.Fatal("hash not stable") } - - if !reflect.DeepEqual(block, dec) { - t.Fatalf("value not match") - } } func TestBlock_PackAndSignBlock(t *testing.T) { @@ -132,27 +125,13 @@ func TestBlock_PackAndSignBlock(t *testing.T) { t.Fatalf("Unexpected error: %v", err) } - tb, err := generateRandomTxBilling() + tb, err := generateRandomBilling() if err != nil { t.Fatalf("Unexpected error: %v", err) } - block.PushTx(tb) + block.Transactions = append(block.Transactions, tb) err = block.Verify() if err != ErrMerkleRootVerification { t.Fatalf("Unexpected error: %v", err) } } - -func TestOther_MarshalHash(t *testing.T) { - Convey("marshal hash", t, func() { - tm := TxType(1) - s, err := tm.MarshalHash() - So(err, ShouldBeNil) - So(s, ShouldNotBeEmpty) - - So(tm.String(), ShouldResemble, "TxUnknown") - - tm = TxType(0) - So(tm.String(), ShouldResemble, "TxBilling") - }) -} diff --git a/blockproducer/types/common.go b/blockproducer/types/common.go index c865cd63f..024cc9646 100644 --- a/blockproducer/types/common.go +++ b/blockproducer/types/common.go @@ -17,26 +17,10 @@ package types import ( - "bytes" - "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" "github.com/CovenantSQL/CovenantSQL/crypto/hash" - "github.com/CovenantSQL/CovenantSQL/utils" ) -func serialize(i interface{}) (s []byte, err error) { - var enc *bytes.Buffer - if enc, err = utils.EncodeMsgPack(i); err != nil { - return - } - s = enc.Bytes() - return -} - -func deserialize(enc []byte, o interface{}) error { - return utils.DecodeMsgPack(enc, o) -} - type marshalHasher interface { MarshalHash() ([]byte, error) } diff --git a/blockproducer/types/createdb.go b/blockproducer/types/createdb.go index 41e105421..2d5aa00fa 100644 --- a/blockproducer/types/createdb.go +++ b/blockproducer/types/createdb.go @@ -43,22 +43,16 @@ func (h *CreateDatabaseHeader) GetAccountNonce() pi.AccountNonce { // CreateDatabase defines the database creation transaction. type CreateDatabase struct { CreateDatabaseHeader + pi.TransactionTypeMixin DefaultHashSignVerifierImpl } -// Serialize implements interfaces/Transaction.Serialize. -func (cd *CreateDatabase) Serialize() ([]byte, error) { - return serialize(cd) -} - -// Deserialize implements interfaces/Transaction.Deserialize. -func (cd *CreateDatabase) Deserialize(enc []byte) error { - return deserialize(enc, cd) -} - -// GetTransactionType implements interfaces/Transaction.GetTransactionType. -func (cd *CreateDatabase) GetTransactionType() pi.TransactionType { - return pi.TransactionTypeCreataDatabase +// NewCreateDatabase returns new instance. +func NewCreateDatabase(header *CreateDatabaseHeader) *CreateDatabase { + return &CreateDatabase{ + CreateDatabaseHeader: *header, + TransactionTypeMixin: *pi.NewTransactionTypeMixin(pi.TransactionTypeCreateDatabase), + } } // Sign implements interfaces/Transaction.Sign. @@ -70,3 +64,7 @@ func (cd *CreateDatabase) Sign(signer *asymmetric.PrivateKey) (err error) { func (cd *CreateDatabase) Verify() error { return cd.DefaultHashSignVerifierImpl.Verify(&cd.CreateDatabaseHeader) } + +func init() { + pi.RegisterTransaction(pi.TransactionTypeCreateDatabase, (*CreateDatabase)(nil)) +} diff --git a/blockproducer/types/createdb_gen.go b/blockproducer/types/createdb_gen.go index 368a8c99a..0b3e6b862 100644 --- a/blockproducer/types/createdb_gen.go +++ b/blockproducer/types/createdb_gen.go @@ -10,9 +10,9 @@ import ( func (z *CreateDatabase) MarshalHash() (o []byte, err error) { var b []byte o = hsp.Require(b, z.Msgsize()) + // map header, size 3 // map header, size 2 - // map header, size 2 - o = append(o, 0x82, 0x82, 0x82, 0x82) + o = append(o, 0x83, 0x83, 0x82, 0x82) if oTemp, err := z.CreateDatabaseHeader.Owner.MarshalHash(); err != nil { return nil, err } else { @@ -24,18 +24,24 @@ func (z *CreateDatabase) MarshalHash() (o []byte, err error) { } else { o = hsp.AppendBytes(o, oTemp) } - o = append(o, 0x82) + o = append(o, 0x83) if oTemp, err := z.DefaultHashSignVerifierImpl.MarshalHash(); err != nil { return nil, err } else { o = hsp.AppendBytes(o, oTemp) } + o = append(o, 0x83) + if oTemp, err := z.TransactionTypeMixin.MarshalHash(); err != nil { + return nil, err + } else { + o = hsp.AppendBytes(o, oTemp) + } return } // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message func (z *CreateDatabase) Msgsize() (s int) { - s = 1 + 21 + 1 + 6 + z.CreateDatabaseHeader.Owner.Msgsize() + 6 + z.CreateDatabaseHeader.Nonce.Msgsize() + 28 + z.DefaultHashSignVerifierImpl.Msgsize() + s = 1 + 21 + 1 + 6 + z.CreateDatabaseHeader.Owner.Msgsize() + 6 + z.CreateDatabaseHeader.Nonce.Msgsize() + 28 + z.DefaultHashSignVerifierImpl.Msgsize() + 21 + z.TransactionTypeMixin.Msgsize() return } diff --git a/blockproducer/types/errors.go b/blockproducer/types/errors.go index 7d856cb81..13d135db1 100644 --- a/blockproducer/types/errors.go +++ b/blockproducer/types/errors.go @@ -33,4 +33,7 @@ var ( // ErrNodePublicKeyNotMatch indicates that the public key given with a node does not match the // one in the key store. ErrNodePublicKeyNotMatch = errors.New("node publick key doesn't match") + + // ErrBillingNotMatch indicates that the billing request doesn't match the local result. + ErrBillingNotMatch = errors.New("billing request doesn't match") ) diff --git a/blockproducer/types/msgpack_test.go b/blockproducer/types/msgpack_test.go new file mode 100644 index 000000000..c448c3af6 --- /dev/null +++ b/blockproducer/types/msgpack_test.go @@ -0,0 +1,158 @@ +/* + * Copyright 2018 The CovenantSQL Authors. + * + * 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. + */ + +package types + +import ( + "reflect" + "testing" + + pi "github.com/CovenantSQL/CovenantSQL/blockproducer/interfaces" + "github.com/CovenantSQL/CovenantSQL/utils" + . "github.com/smartystreets/goconvey/convey" +) + +type complexStructure struct { + Tx pi.Transaction + Txs []pi.Transaction + Maps map[string]pi.Transaction +} + +func TestEncodeDecodeTransactions(t *testing.T) { + Convey("test encode/decode single transaction", t, func() { + var t pi.Transaction + t = NewBaseAccount(&Account{}) + buf, err := utils.EncodeMsgPack(t) + So(err, ShouldBeNil) + + var out pi.Transaction + err = utils.DecodeMsgPack(buf.Bytes(), &out) + So(err, ShouldBeNil) + So(out, ShouldNotBeNil) + So(reflect.TypeOf(out).String(), ShouldContainSubstring, "TransactionWrapper") + So(out.GetTransactionType(), ShouldEqual, t.GetTransactionType()) + }) + Convey("test encode/decode series of transactions", t, func() { + var t []pi.Transaction + t = append(t, NewBaseAccount(&Account{})) + t = append(t, NewTransfer(&TransferHeader{})) + t = append(t, NewBilling(&BillingHeader{})) + t = append(t, NewCreateDatabase(&CreateDatabaseHeader{})) + + buf, err := utils.EncodeMsgPack(t) + So(err, ShouldBeNil) + + var out []pi.Transaction + err = utils.DecodeMsgPack(buf.Bytes(), &out) + So(err, ShouldBeNil) + So(out, ShouldNotBeNil) + So(out, ShouldHaveLength, len(t)) + + for i := range t { + So(out[i], ShouldNotBeNil) + So(out[i].GetTransactionType(), ShouldEqual, t[i].GetTransactionType()) + So(reflect.TypeOf(out[i]).String(), ShouldContainSubstring, "TransactionWrapper") + } + }) + Convey("test encode/decode complex structure containing transactions", t, func() { + var t complexStructure + t.Tx = NewBaseAccount(&Account{}) + t.Txs = append(t.Txs, NewBaseAccount(&Account{})) + t.Txs = append(t.Txs, NewTransfer(&TransferHeader{})) + t.Txs = append(t.Txs, NewBilling(&BillingHeader{})) + t.Txs = append(t.Txs, NewCreateDatabase(&CreateDatabaseHeader{})) + t.Maps = make(map[string]pi.Transaction) + t.Maps["BaseAccount"] = NewBaseAccount(&Account{}) + t.Maps["Transfer"] = NewTransfer(&TransferHeader{}) + t.Maps["Billing"] = NewBilling(&BillingHeader{}) + t.Maps["CreateDatabase"] = NewCreateDatabase(&CreateDatabaseHeader{}) + buf, err := utils.EncodeMsgPack(t) + So(err, ShouldBeNil) + + var out complexStructure + err = utils.DecodeMsgPack(buf.Bytes(), &out) + So(err, ShouldBeNil) + So(out.Tx, ShouldNotBeNil) + So(out.Txs, ShouldNotBeNil) + So(out.Txs, ShouldHaveLength, len(t.Txs)) + So(out.Maps, ShouldNotBeNil) + So(out.Maps, ShouldHaveLength, len(t.Maps)) + + So(out.Tx.GetTransactionType(), ShouldEqual, pi.TransactionTypeBaseAccount) + So(reflect.TypeOf(out.Tx).String(), ShouldContainSubstring, "TransactionWrapper") + + for i := range out.Txs { + So(out.Txs[i], ShouldNotBeNil) + So(out.Txs[i].GetTransactionType(), ShouldEqual, t.Txs[i].GetTransactionType()) + So(reflect.TypeOf(out.Txs[i]).String(), ShouldContainSubstring, "TransactionWrapper") + } + + for k, v := range out.Maps { + So(v, ShouldNotBeNil) + So(out.Maps[k].GetTransactionType(), ShouldEqual, t.Maps[k].GetTransactionType()) + So(reflect.TypeOf(out.Maps[k]).String(), ShouldContainSubstring, "TransactionWrapper") + } + }) + Convey("test encode wrapper, decode using real type", t, func() { + var t pi.Transaction + t = pi.WrapTransaction(NewBaseAccount(&Account{})) + So(reflect.TypeOf(t).String(), ShouldContainSubstring, "TransactionWrapper") + So(t.GetTransactionType(), ShouldEqual, pi.TransactionTypeBaseAccount) + buf, err := utils.EncodeMsgPack(t) + So(err, ShouldBeNil) + + var out *BaseAccount + err = utils.DecodeMsgPack(buf.Bytes(), &out) + So(err, ShouldBeNil) + So(out, ShouldNotBeNil) + So(out.GetTransactionType(), ShouldEqual, pi.TransactionTypeBaseAccount) + So(reflect.TypeOf(out).String(), ShouldContainSubstring, "BaseAccount") + }) + Convey("decode invalid data", t, func() { + var testTypes = []interface{}{ + "1", + 1, + 0.1, + []int{}, + []int{1, 2}, + []int{1, 2, 3}, + struct{ A int }{A: 1}, + struct{ TxType int }{TxType: int(pi.TransactionTypeNumber) + 1}, + struct{ TxType struct{} }{}, + struct{}{}, + } + + for _, val := range testTypes { + buf, err := utils.EncodeMsgPack(val) + So(err, ShouldBeNil) + + var out pi.Transaction + err = utils.DecodeMsgPack(buf.Bytes(), &out) + So(err, ShouldNotBeNil) + } + }) + Convey("decode wrapper with nil transaction", t, func() { + var t pi.Transaction + t = pi.WrapTransaction(nil) + buf, err := utils.EncodeMsgPack(t) + So(err, ShouldBeNil) + + var out pi.Transaction + err = utils.DecodeMsgPack(buf.Bytes(), &out) + So(err, ShouldBeNil) + So(out, ShouldBeNil) + }) +} diff --git a/blockproducer/types/transfer.go b/blockproducer/types/transfer.go index 62f84b5e9..e9a170fa0 100644 --- a/blockproducer/types/transfer.go +++ b/blockproducer/types/transfer.go @@ -17,13 +17,9 @@ package types import ( - "bytes" - pi "github.com/CovenantSQL/CovenantSQL/blockproducer/interfaces" "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" - "github.com/CovenantSQL/CovenantSQL/crypto/hash" "github.com/CovenantSQL/CovenantSQL/proto" - "github.com/CovenantSQL/CovenantSQL/utils" ) //go:generate hsp @@ -38,24 +34,16 @@ type TransferHeader struct { // Transfer defines the transfer transaction. type Transfer struct { TransferHeader - HeaderHash hash.Hash - Signee *asymmetric.PublicKey - Signature *asymmetric.Signature + pi.TransactionTypeMixin + DefaultHashSignVerifierImpl } -// Serialize serializes TxBilling using msgpack. -func (t *Transfer) Serialize() (b []byte, err error) { - var enc *bytes.Buffer - if enc, err = utils.EncodeMsgPack(t); err != nil { - return +// NewTransfer returns new instance. +func NewTransfer(header *TransferHeader) *Transfer { + return &Transfer{ + TransferHeader: *header, + TransactionTypeMixin: *pi.NewTransactionTypeMixin(pi.TransactionTypeTransfer), } - b = enc.Bytes() - return -} - -// Deserialize desrializes TxBilling using msgpack. -func (t *Transfer) Deserialize(enc []byte) error { - return utils.DecodeMsgPack(enc, t) } // GetAccountAddress implements interfaces/Transaction.GetAccountAddress. @@ -68,42 +56,16 @@ func (t *Transfer) GetAccountNonce() pi.AccountNonce { return t.Nonce } -// GetHash implements interfaces/Transaction.GetHash. -func (t *Transfer) GetHash() hash.Hash { - return t.HeaderHash -} - -// GetTransactionType implements interfaces/Transaction.GetTransactionType. -func (t *Transfer) GetTransactionType() pi.TransactionType { - return pi.TransactionTypeTransfer -} - // Sign implements interfaces/Transaction.Sign. func (t *Transfer) Sign(signer *asymmetric.PrivateKey) (err error) { - var enc []byte - if enc, err = t.TransferHeader.MarshalHash(); err != nil { - return - } - var h = hash.THashH(enc) - if t.Signature, err = signer.Sign(h[:]); err != nil { - return - } - t.HeaderHash = h - t.Signee = signer.PubKey() - return + return t.DefaultHashSignVerifierImpl.Sign(&t.TransferHeader, signer) } // Verify implements interfaces/Transaction.Verify. func (t *Transfer) Verify() (err error) { - var enc []byte - if enc, err = t.TransferHeader.MarshalHash(); err != nil { - return - } else if h := hash.THashH(enc); !t.HeaderHash.IsEqual(&h) { - err = ErrSignVerification - return - } else if !t.Signature.Verify(h[:], t.Signee) { - err = ErrSignVerification - return - } - return + return t.DefaultHashSignVerifierImpl.Verify(&t.TransferHeader) +} + +func init() { + pi.RegisterTransaction(pi.TransactionTypeTransfer, (*Transfer)(nil)) } diff --git a/blockproducer/types/transfer_gen.go b/blockproducer/types/transfer_gen.go index 9091a1e62..6d910fa70 100644 --- a/blockproducer/types/transfer_gen.go +++ b/blockproducer/types/transfer_gen.go @@ -10,35 +10,21 @@ import ( func (z *Transfer) MarshalHash() (o []byte, err error) { var b []byte o = hsp.Require(b, z.Msgsize()) - // map header, size 4 - o = append(o, 0x84, 0x84) - if z.Signee == nil { - o = hsp.AppendNil(o) - } else { - if oTemp, err := z.Signee.MarshalHash(); err != nil { - return nil, err - } else { - o = hsp.AppendBytes(o, oTemp) - } - } - o = append(o, 0x84) - if z.Signature == nil { - o = hsp.AppendNil(o) + // map header, size 3 + o = append(o, 0x83, 0x83) + if oTemp, err := z.DefaultHashSignVerifierImpl.MarshalHash(); err != nil { + return nil, err } else { - if oTemp, err := z.Signature.MarshalHash(); err != nil { - return nil, err - } else { - o = hsp.AppendBytes(o, oTemp) - } + o = hsp.AppendBytes(o, oTemp) } - o = append(o, 0x84) + o = append(o, 0x83) if oTemp, err := z.TransferHeader.MarshalHash(); err != nil { return nil, err } else { o = hsp.AppendBytes(o, oTemp) } - o = append(o, 0x84) - if oTemp, err := z.HeaderHash.MarshalHash(); err != nil { + o = append(o, 0x83) + if oTemp, err := z.TransactionTypeMixin.MarshalHash(); err != nil { return nil, err } else { o = hsp.AppendBytes(o, oTemp) @@ -48,19 +34,7 @@ func (z *Transfer) MarshalHash() (o []byte, err error) { // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message func (z *Transfer) Msgsize() (s int) { - s = 1 + 7 - if z.Signee == nil { - s += hsp.NilSize - } else { - s += z.Signee.Msgsize() - } - s += 10 - if z.Signature == nil { - s += hsp.NilSize - } else { - s += z.Signature.Msgsize() - } - s += 15 + z.TransferHeader.Msgsize() + 11 + z.HeaderHash.Msgsize() + s = 1 + 28 + z.DefaultHashSignVerifierImpl.Msgsize() + 15 + z.TransferHeader.Msgsize() + 21 + z.TransactionTypeMixin.Msgsize() return } diff --git a/blockproducer/types/tx_gen_test.go b/blockproducer/types/tx_gen_test.go deleted file mode 100644 index 76e7feeed..000000000 --- a/blockproducer/types/tx_gen_test.go +++ /dev/null @@ -1,3 +0,0 @@ -package types - -// Code generated by github.com/CovenantSQL/HashStablePack DO NOT EDIT. diff --git a/blockproducer/types/txsqlchainbilling.go b/blockproducer/types/txsqlchainbilling.go deleted file mode 100644 index fcb680ded..000000000 --- a/blockproducer/types/txsqlchainbilling.go +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright 2018 The CovenantSQL Authors. - * - * 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. - */ - -package types - -import ( - "bytes" - "sync" - - pi "github.com/CovenantSQL/CovenantSQL/blockproducer/interfaces" - "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" - "github.com/CovenantSQL/CovenantSQL/crypto/hash" - "github.com/CovenantSQL/CovenantSQL/proto" - "github.com/CovenantSQL/CovenantSQL/utils" -) - -//go:generate hsp -//hsp:ignore sync.Mutex Mutex - -// TxContent defines the customer's billing and block rewards in transaction. -type TxContent struct { - SequenceID uint32 - BillingRequest BillingRequest - Receivers []*proto.AccountAddress - // Fee paid by stable coin - Fees []uint64 - // Reward is share coin - Rewards []uint64 - BillingResponse BillingResponse -} - -// NewTxContent generates new TxContent. -func NewTxContent(seqID uint32, - bReq *BillingRequest, - receivers []*proto.AccountAddress, - fees []uint64, - rewards []uint64, - bResp *BillingResponse) *TxContent { - return &TxContent{ - SequenceID: seqID, - BillingRequest: *bReq, - Receivers: receivers, - Fees: fees, - Rewards: rewards, - BillingResponse: *bResp, - } -} - -// GetHash returns the hash of transaction. -func (tb *TxContent) GetHash() (*hash.Hash, error) { - b, err := tb.MarshalHash() - if err != nil { - return nil, err - } - h := hash.THashH(b) - return &h, nil -} - -// TxBilling is a type of tx, that is used to record sql chain billing and block rewards. -type TxBilling struct { - mutex sync.Mutex - TxContent TxContent - TxType byte - AccountAddress *proto.AccountAddress - TxHash *hash.Hash - Signee *asymmetric.PublicKey - Signature *asymmetric.Signature - SignedBlock *hash.Hash -} - -// NewTxBilling generates a new TxBilling. -func NewTxBilling(txContent *TxContent, txType TxType, addr *proto.AccountAddress) *TxBilling { - return &TxBilling{ - TxContent: *txContent, - TxType: txType.ToByte(), - AccountAddress: addr, - } -} - -// Serialize serializes TxBilling using msgpack. -func (tb *TxBilling) Serialize() (b []byte, err error) { - var enc *bytes.Buffer - if enc, err = utils.EncodeMsgPack(tb); err != nil { - return - } - b = enc.Bytes() - return -} - -// Deserialize desrializes TxBilling using msgpack. -func (tb *TxBilling) Deserialize(enc []byte) error { - return utils.DecodeMsgPack(enc, tb) -} - -// GetAccountAddress implements interfaces/Transaction.GetAccountAddress. -func (tb *TxBilling) GetAccountAddress() proto.AccountAddress { - return *tb.AccountAddress -} - -// GetAccountNonce implements interfaces/Transaction.GetAccountNonce. -func (tb *TxBilling) GetAccountNonce() pi.AccountNonce { - return pi.AccountNonce(tb.TxContent.SequenceID) -} - -// GetHash implements interfaces/Transaction.GetHash. -func (tb *TxBilling) GetHash() hash.Hash { - return *tb.TxHash -} - -// GetTransactionType implements interfaces/Transaction.GetTransactionType. -func (tb *TxBilling) GetTransactionType() pi.TransactionType { - return pi.TransactionTypeBilling -} - -// Sign computes tx of TxContent and signs it. -func (tb *TxBilling) Sign(signer *asymmetric.PrivateKey) error { - enc, err := tb.TxContent.MarshalHash() - if err != nil { - return err - } - h := hash.THashH(enc) - tb.TxHash = &h - - pub := asymmetric.PublicKey(signer.PublicKey) - tb.Signee = &pub - - signature, err := signer.Sign(h[:]) - if err != nil { - return err - } - tb.Signature = signature - - return nil -} - -// Verify verifies the signature of TxBilling. -func (tb *TxBilling) Verify() (err error) { - var enc []byte - if enc, err = tb.TxContent.MarshalHash(); err != nil { - return - } else if h := hash.THashH(enc); !tb.TxHash.IsEqual(&h) { - err = ErrSignVerification - return - } else if !tb.Signature.Verify(h[:], tb.Signee) { - err = ErrSignVerification - return - } - return -} - -// GetDatabaseID gets the database ID. -func (tb *TxBilling) GetDatabaseID() *proto.DatabaseID { - return &tb.TxContent.BillingRequest.Header.DatabaseID -} - -// GetSequenceID gets the sequence ID. -func (tb *TxBilling) GetSequenceID() uint32 { - return tb.TxContent.SequenceID -} - -// IsSigned shows whether the tx billing is signed. -func (tb *TxBilling) IsSigned() bool { - tb.mutex.Lock() - defer tb.mutex.Unlock() - return tb.SignedBlock != nil -} - -// SetSignedBlock sets the tx billing with block hash. -func (tb *TxBilling) SetSignedBlock(h *hash.Hash) { - tb.mutex.Lock() - defer tb.mutex.Unlock() - tb.SignedBlock = h -} - -// GetSignedBlock gets the block hash. -func (tb *TxBilling) GetSignedBlock() *hash.Hash { - tb.mutex.Lock() - defer tb.mutex.Unlock() - return tb.SignedBlock -} diff --git a/blockproducer/types/txsqlchainbilling_gen.go b/blockproducer/types/txsqlchainbilling_gen.go deleted file mode 100644 index 3cdd961e8..000000000 --- a/blockproducer/types/txsqlchainbilling_gen.go +++ /dev/null @@ -1,168 +0,0 @@ -package types - -// Code generated by github.com/CovenantSQL/HashStablePack DO NOT EDIT. - -import ( - hsp "github.com/CovenantSQL/HashStablePack/marshalhash" -) - -// MarshalHash marshals for hash -func (z *TxBilling) MarshalHash() (o []byte, err error) { - var b []byte - o = hsp.Require(b, z.Msgsize()) - // map header, size 7 - o = append(o, 0x87, 0x87) - if z.Signee == nil { - o = hsp.AppendNil(o) - } else { - if oTemp, err := z.Signee.MarshalHash(); err != nil { - return nil, err - } else { - o = hsp.AppendBytes(o, oTemp) - } - } - o = append(o, 0x87) - if z.Signature == nil { - o = hsp.AppendNil(o) - } else { - if oTemp, err := z.Signature.MarshalHash(); err != nil { - return nil, err - } else { - o = hsp.AppendBytes(o, oTemp) - } - } - o = append(o, 0x87) - if z.SignedBlock == nil { - o = hsp.AppendNil(o) - } else { - if oTemp, err := z.SignedBlock.MarshalHash(); err != nil { - return nil, err - } else { - o = hsp.AppendBytes(o, oTemp) - } - } - o = append(o, 0x87) - if z.TxHash == nil { - o = hsp.AppendNil(o) - } else { - if oTemp, err := z.TxHash.MarshalHash(); err != nil { - return nil, err - } else { - o = hsp.AppendBytes(o, oTemp) - } - } - o = append(o, 0x87) - if z.AccountAddress == nil { - o = hsp.AppendNil(o) - } else { - if oTemp, err := z.AccountAddress.MarshalHash(); err != nil { - return nil, err - } else { - o = hsp.AppendBytes(o, oTemp) - } - } - o = append(o, 0x87) - if oTemp, err := z.TxContent.MarshalHash(); err != nil { - return nil, err - } else { - o = hsp.AppendBytes(o, oTemp) - } - o = append(o, 0x87) - o = hsp.AppendByte(o, z.TxType) - return -} - -// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message -func (z *TxBilling) Msgsize() (s int) { - s = 1 + 7 - if z.Signee == nil { - s += hsp.NilSize - } else { - s += z.Signee.Msgsize() - } - s += 10 - if z.Signature == nil { - s += hsp.NilSize - } else { - s += z.Signature.Msgsize() - } - s += 12 - if z.SignedBlock == nil { - s += hsp.NilSize - } else { - s += z.SignedBlock.Msgsize() - } - s += 7 - if z.TxHash == nil { - s += hsp.NilSize - } else { - s += z.TxHash.Msgsize() - } - s += 15 - if z.AccountAddress == nil { - s += hsp.NilSize - } else { - s += z.AccountAddress.Msgsize() - } - s += 10 + z.TxContent.Msgsize() + 7 + hsp.ByteSize - return -} - -// MarshalHash marshals for hash -func (z *TxContent) MarshalHash() (o []byte, err error) { - var b []byte - o = hsp.Require(b, z.Msgsize()) - // map header, size 6 - o = append(o, 0x86, 0x86) - if oTemp, err := z.BillingRequest.MarshalHash(); err != nil { - return nil, err - } else { - o = hsp.AppendBytes(o, oTemp) - } - o = append(o, 0x86) - if oTemp, err := z.BillingResponse.MarshalHash(); err != nil { - return nil, err - } else { - o = hsp.AppendBytes(o, oTemp) - } - o = append(o, 0x86) - o = hsp.AppendArrayHeader(o, uint32(len(z.Receivers))) - for za0001 := range z.Receivers { - if z.Receivers[za0001] == nil { - o = hsp.AppendNil(o) - } else { - if oTemp, err := z.Receivers[za0001].MarshalHash(); err != nil { - return nil, err - } else { - o = hsp.AppendBytes(o, oTemp) - } - } - } - o = append(o, 0x86) - o = hsp.AppendArrayHeader(o, uint32(len(z.Fees))) - for za0002 := range z.Fees { - o = hsp.AppendUint64(o, z.Fees[za0002]) - } - o = append(o, 0x86) - o = hsp.AppendArrayHeader(o, uint32(len(z.Rewards))) - for za0003 := range z.Rewards { - o = hsp.AppendUint64(o, z.Rewards[za0003]) - } - o = append(o, 0x86) - o = hsp.AppendUint32(o, z.SequenceID) - return -} - -// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message -func (z *TxContent) Msgsize() (s int) { - s = 1 + 15 + z.BillingRequest.Msgsize() + 16 + z.BillingResponse.Msgsize() + 10 + hsp.ArrayHeaderSize - for za0001 := range z.Receivers { - if z.Receivers[za0001] == nil { - s += hsp.NilSize - } else { - s += z.Receivers[za0001].Msgsize() - } - } - s += 5 + hsp.ArrayHeaderSize + (len(z.Fees) * (hsp.Uint64Size)) + 8 + hsp.ArrayHeaderSize + (len(z.Rewards) * (hsp.Uint64Size)) + 11 + hsp.Uint32Size - return -} diff --git a/blockproducer/types/txsqlchainbilling_test.go b/blockproducer/types/txsqlchainbilling_test.go deleted file mode 100644 index dc004a11b..000000000 --- a/blockproducer/types/txsqlchainbilling_test.go +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2018 The CovenantSQL Authors. - * - * 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. - */ - -package types - -import ( - "reflect" - "testing" - - "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" - "github.com/CovenantSQL/CovenantSQL/crypto/hash" - "github.com/CovenantSQL/CovenantSQL/utils" -) - -func TestTxContent_GetHashAndGetType(t *testing.T) { - tc, err := generateRandomTxContent() - if err != nil { - t.Fatalf("Unexpeted error: %v", err) - } - - h, err := tc.GetHash() - if err != nil { - t.Fatalf("Unexpeted error: %v", err) - } - - enc, err := tc.MarshalHash() - encHash := hash.THashH(enc) - if !h.IsEqual(&encHash) { - t.Fatalf("Hash not match: \n\tv1=%v,\n\tv2=%v", h, encHash) - } -} - -func TestTxContent_MarshalUnmarshalBinary(t *testing.T) { - tc, err := generateRandomTxContent() - if err != nil { - t.Fatalf("Unexpeted error: %v", err) - } - - enc, err := utils.EncodeMsgPack(tc) - if err != nil { - t.Fatalf("Unexpeted error: %v", err) - } - - dec := &TxContent{} - err = utils.DecodeMsgPack(enc.Bytes(), dec) - if err != nil { - t.Fatalf("Unexpeted error: %v", err) - } - - if tc.SequenceID != dec.SequenceID { - t.Fatalf("Value not match: \n\tv1=%v\n\tv2=%v", tc.SequenceID, tc.SequenceID) - } - if tc.BillingRequest.RequestHash != dec.BillingRequest.RequestHash { - t.Fatalf("Value not match: \n\tv1=%v\n\tv2=%v", tc.BillingRequest.RequestHash, tc.BillingRequest.RequestHash) - } - if !tc.BillingRequest.Signatures[0].IsEqual(dec.BillingRequest.Signatures[0]) { - t.Fatalf("Value not match: \n\tv1=%v\n\tv2=%v", tc.BillingRequest.Signatures[0], dec.BillingRequest.Signatures[0]) - } - for i := range tc.Receivers { - if !reflect.DeepEqual(tc.Receivers[i], dec.Receivers[i]) { - t.Fatalf("Value not match: \n\ttc.Receivers[%d]=%v\n\tReceive[%d]=%v", i, i, tc.Receivers[i], tc.Receivers[0]) - } - if tc.Rewards[i] != dec.Rewards[i] { - t.Fatalf("Value not match: \n\ttc.Rewards[%d]=%v\n\tRewards[%d]=%v", i, i, tc.Rewards[i], tc.Rewards[0]) - } - if tc.Fees[i] != dec.Fees[i] { - t.Fatalf("Value not match: \n\ttc.Fees[%d]=%v\n\tFees[%d]=%v", i, i, tc.Fees[i], tc.Fees[0]) - } - } -} - -func TestTxBilling_SerializeDeserialize(t *testing.T) { - tb, err := generateRandomTxBilling() - if err != nil { - t.Fatalf("Unexpeted error: %v", err) - } - - enc, err := tb.Serialize() - if err != nil { - t.Fatalf("Unexpeted error: %v", err) - } - - dec := TxBilling{} - err = dec.Deserialize(enc) - if err != nil { - t.Fatalf("Unexpeted error: %v", err) - } - - if !tb.SignedBlock.IsEqual(dec.SignedBlock) { - t.Fatalf("Value not match: \n\tv1=%v\n\tv2=%v", tb.SignedBlock, tb.SignedBlock) - } - if !tb.Signature.IsEqual(dec.Signature) { - t.Fatalf("Value not match: \n\tv1=%v\n\tv2=%v", tb.Signature, tb.Signature) - } - if !tb.Signee.IsEqual(dec.Signee) { - t.Fatalf("Value not match: \n\tv1=%v\n\tv2=%v", tb.Signee, tb.Signee) - } - if !tb.TxHash.IsEqual(dec.TxHash) { - t.Fatalf("Value not match: \n\tv1=%v\n\tv2=%v", tb.TxHash, tb.TxHash) - } - if !reflect.DeepEqual(tb.TxContent.BillingResponse, dec.TxContent.BillingResponse) { - t.Fatalf("Value not match: \n\tv1=%v\n\tv2=%v", tb.TxContent.BillingResponse, tb.TxContent.BillingResponse) - } -} - -func TestTxBilling_GetSet(t *testing.T) { - tb, err := generateRandomTxBilling() - if err != nil { - t.Fatalf("Unexpeted error: %v", err) - } - - tb.GetSequenceID() - if tb.GetDatabaseID() == nil { - t.Fatalf("String should not be nil: %v", tb) - } - - if !tb.IsSigned() { - t.Fatalf("BlockHash should not be nil: %v", tb) - } - h := generateRandomHash() - tb.SetSignedBlock(&h) - if !h.IsEqual(tb.GetSignedBlock()) { - t.Fatalf("BlockHash should be the same: v1=%s, v2=%s", h.String(), tb.GetSignedBlock().String()) - } -} - -func TestTxBilling_PackAndSignTx(t *testing.T) { - tb, err := generateRandomTxBilling() - if err != nil { - t.Fatalf("Unexpeted error: %v", err) - } - - priv, _, err := asymmetric.GenSecp256k1KeyPair() - if err != nil { - t.Fatalf("Unexpeted error: %v", err) - } - tb.Sign(priv) - enc, err := tb.TxContent.MarshalHash() - if err != nil { - t.Fatalf("Unexpeted error: %v", err) - } - h := hash.THashH(enc[:]) - sign, err := priv.Sign(h[:]) - if err != nil { - t.Fatalf("Unexpeted error: %v", err) - } - if !sign.IsEqual(tb.Signature) { - t.Fatalf("Value not match: \n\tv1=%v\n\tv2=%v", sign, tb.Signature) - } - - err = tb.Verify() - if err != nil { - t.Fatalf("Verify signature failed: %v", err) - } -} diff --git a/blockproducer/types/xxx_test.go b/blockproducer/types/xxx_test.go index f5a0efe10..31bd5a7ae 100644 --- a/blockproducer/types/xxx_test.go +++ b/blockproducer/types/xxx_test.go @@ -23,6 +23,7 @@ import ( "testing" "time" + pi "github.com/CovenantSQL/CovenantSQL/blockproducer/interfaces" "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" "github.com/CovenantSQL/CovenantSQL/crypto/hash" "github.com/CovenantSQL/CovenantSQL/crypto/kms" @@ -116,17 +117,9 @@ func randStringBytes(n int) string { return string(b) } -func generateRandomUint32s(n int32) []uint32 { - s := make([]uint32, n) - for i := range s { - s[i] = (uint32)(rand.Int31()) - } - return s -} - func generateRandomBlock(parent hash.Hash, isGenesis bool) (b *Block, err error) { // Generate key pair - priv, pub, err := asymmetric.GenSecp256k1KeyPair() + priv, _, err := asymmetric.GenSecp256k1KeyPair() if err != nil { return @@ -143,16 +136,15 @@ func generateRandomBlock(parent hash.Hash, isGenesis bool) (b *Block, err error) ParentHash: parent, Timestamp: time.Now().UTC(), }, - Signee: pub, }, } for i, n := 0, rand.Intn(10)+10; i < n; i++ { - tb, err := generateRandomTxBilling() + tb, err := generateRandomBilling() if err != nil { return nil, err } - b.PushTx(tb) + b.Transactions = append(b.Transactions, tb) } err = b.PackAndSignBlock(priv) @@ -170,72 +162,44 @@ func generateRandomBillingRequestHeader() *BillingRequestHeader { } } -func generateRandomBillingRequest() (*BillingRequest, error) { +func generateRandomBillingRequest() (req *BillingRequest, err error) { reqHeader := generateRandomBillingRequestHeader() - req := BillingRequest{ + req = &BillingRequest{ Header: *reqHeader, } - h, err := req.PackRequestHeader() - if err != nil { + if _, err = req.PackRequestHeader(); err != nil { return nil, err } - signees := make([]*asymmetric.PublicKey, peerNum) - signatures := make([]*asymmetric.Signature, peerNum) - - for i := range signees { + for i := 0; i < peerNum; i++ { // Generate key pair - priv, pub, err := asymmetric.GenSecp256k1KeyPair() - if err != nil { - return nil, err + var priv *asymmetric.PrivateKey + + if priv, _, err = asymmetric.GenSecp256k1KeyPair(); err != nil { + return } - signees[i] = pub - signatures[i], err = priv.Sign(h[:]) - if err != nil { - return nil, err + + if _, _, err = req.SignRequestHeader(priv, false); err != nil { + return } } - req.RequestHash = *h - req.Signatures = signatures - req.Signees = signees - return &req, nil + return } -func generateRandomBillingResponse() (*BillingResponse, error) { - priv, pub, err := asymmetric.GenSecp256k1KeyPair() - if err != nil { - return nil, err - } - h := generateRandomHash() - sign, err := priv.Sign(h[:]) - if err != nil { - return nil, err - } - resp := BillingResponse{ - AccountAddress: proto.AccountAddress(generateRandomHash()), - RequestHash: h, - Signee: pub, - Signature: sign, +func generateRandomBillingHeader() (tc *BillingHeader, err error) { + var req *BillingRequest + if req, err = generateRandomBillingRequest(); err != nil { + return } - return &resp, nil -} -func generateRandomTxContent() (*TxContent, error) { - req, err := generateRandomBillingRequest() - if err != nil { - return nil, err - } - priv, pub, err := asymmetric.GenSecp256k1KeyPair() - sign, err := priv.Sign(req.RequestHash[:]) - if err != nil { - return nil, err + var priv *asymmetric.PrivateKey + if priv, _, err = asymmetric.GenSecp256k1KeyPair(); err != nil { + return } - resp := &BillingResponse{ - AccountAddress: proto.AccountAddress(generateRandomHash()), - RequestHash: req.RequestHash, - Signee: pub, - Signature: sign, + + if _, _, err = req.SignRequestHeader(priv, false); err != nil { + return } receivers := make([]*proto.AccountAddress, peerNum) @@ -249,33 +213,28 @@ func generateRandomTxContent() (*TxContent, error) { rewards[i] = rand.Uint64() } - tc := NewTxContent(rand.Uint32(), req, receivers, fees, rewards, resp) + producer := proto.AccountAddress(generateRandomHash()) + tc = NewBillingHeader(pi.AccountNonce(rand.Uint32()), req, producer, receivers, fees, rewards) return tc, nil } -func generateRandomTxBilling() (*TxBilling, error) { - txContent, err := generateRandomTxContent() +func generateRandomBilling() (*Billing, error) { + header, err := generateRandomBillingHeader() if err != nil { return nil, err } - accountAddress := proto.AccountAddress(generateRandomHash()) - txHash := generateRandomHash() - priv, pub, err := asymmetric.GenSecp256k1KeyPair() - sign, err := priv.Sign(txHash[:]) + priv, _, err := asymmetric.GenSecp256k1KeyPair() if err != nil { return nil, err } - blockHash := generateRandomHash() - - txBilling := NewTxBilling(txContent, TxTypeBilling, &accountAddress) - txBilling.TxHash = &txHash - txBilling.Signee = pub - txBilling.Signature = sign - txBilling.SignedBlock = &blockHash + txBilling := NewBilling(header) + if err := txBilling.Sign(priv); err != nil { + return nil, err + } return txBilling, nil } -func generateRandomGasAmount(n uint32) []*proto.AddrAndGas { +func generateRandomGasAmount(n int) []*proto.AddrAndGas { gasAmount := make([]*proto.AddrAndGas, n) for i := range gasAmount { diff --git a/blockproducer/xxx_test.go b/blockproducer/xxx_test.go index 4429f206b..8361b0eeb 100644 --- a/blockproducer/xxx_test.go +++ b/blockproducer/xxx_test.go @@ -25,8 +25,8 @@ import ( "time" pi "github.com/CovenantSQL/CovenantSQL/blockproducer/interfaces" - "github.com/CovenantSQL/CovenantSQL/blockproducer/types" pt "github.com/CovenantSQL/CovenantSQL/blockproducer/types" + "github.com/CovenantSQL/CovenantSQL/crypto" "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" "github.com/CovenantSQL/CovenantSQL/crypto/hash" "github.com/CovenantSQL/CovenantSQL/crypto/kms" @@ -41,17 +41,13 @@ var ( uuidLen = 32 peerNum uint32 = 32 - testAddress1 = proto.AccountAddress{0x0, 0x0, 0x0, 0x1} - testAddress2 = proto.AccountAddress{0x0, 0x0, 0x0, 0x2} - testInitBalance = uint64(10000) - testMasterKey = []byte(".9K.sgch!3;C>w0v") - testDifficulty = 4 - testDataDir string - testPrivKeyFile string - testPubKeysFile string - testNonce pi.AccountNonce - testPrivKey *asymmetric.PrivateKey - testPubKey *asymmetric.PublicKey + testAddress1 = proto.AccountAddress{0x0, 0x0, 0x0, 0x1} + testAddress2 = proto.AccountAddress{0x0, 0x0, 0x0, 0x2} + testInitBalance = uint64(10000) + testDifficulty = 4 + testDataDir string + testAddress1Nonce pi.AccountNonce + testPrivKey *asymmetric.PrivateKey ) const ( @@ -87,9 +83,9 @@ func randStringBytes(n int) string { return string(b) } -func generateRandomBlock(parent hash.Hash, isGenesis bool) (b *types.Block, err error) { +func generateRandomBlock(parent hash.Hash, isGenesis bool) (b *pt.Block, err error) { // Generate key pair - priv, pub, err := asymmetric.GenSecp256k1KeyPair() + priv, _, err := asymmetric.GenSecp256k1KeyPair() if err != nil { return @@ -98,43 +94,42 @@ func generateRandomBlock(parent hash.Hash, isGenesis bool) (b *types.Block, err h := hash.Hash{} rand.Read(h[:]) - b = &types.Block{ - SignedHeader: types.SignedHeader{ - Header: types.Header{ + b = &pt.Block{ + SignedHeader: pt.SignedHeader{ + Header: pt.Header{ Version: 0x01000000, Producer: proto.AccountAddress(h), ParentHash: parent, Timestamp: time.Now().UTC(), }, - Signee: pub, }, } if !isGenesis { for i, n := 0, rand.Intn(10)+10; i < n; i++ { - tb, err := generateRandomTxBilling() + ba, tb, err := generateRandomBillingAndBaseAccount() if err != nil { return nil, err } - b.PushTx(tb) + b.Transactions = append(b.Transactions, ba, tb) } } else { // Create base accounts var ( - ba1 = &pt.BaseAccount{ - Account: pt.Account{ + ba1 = pt.NewBaseAccount( + &pt.Account{ Address: testAddress1, StableCoinBalance: testInitBalance, CovenantCoinBalance: testInitBalance, }, - } - ba2 = &pt.BaseAccount{ - Account: pt.Account{ + ) + ba2 = pt.NewBaseAccount( + &pt.Account{ Address: testAddress2, StableCoinBalance: testInitBalance, CovenantCoinBalance: testInitBalance, }, - } + ) ) if err = ba1.Sign(testPrivKey); err != nil { return @@ -142,17 +137,16 @@ func generateRandomBlock(parent hash.Hash, isGenesis bool) (b *types.Block, err if err = ba2.Sign(testPrivKey); err != nil { return } - b.Transactions = append(b.Transactions, ba1) - b.Transactions = append(b.Transactions, ba2) + b.Transactions = append(b.Transactions, ba1, ba2) } err = b.PackAndSignBlock(priv) return } -func generateRandomBlockWithTxBillings(parent hash.Hash, tbs []*types.TxBilling) (b *types.Block, err error) { +func generateRandomBlockWithTransactions(parent hash.Hash, tbs []pi.Transaction) (b *pt.Block, err error) { // Generate key pair - priv, pub, err := asymmetric.GenSecp256k1KeyPair() + priv, _, err := asymmetric.GenSecp256k1KeyPair() if err != nil { return @@ -161,44 +155,42 @@ func generateRandomBlockWithTxBillings(parent hash.Hash, tbs []*types.TxBilling) h := hash.Hash{} rand.Read(h[:]) - b = &types.Block{ - SignedHeader: types.SignedHeader{ - Header: types.Header{ + b = &pt.Block{ + SignedHeader: pt.SignedHeader{ + Header: pt.Header{ Version: 0x01000000, Producer: proto.AccountAddress(h), ParentHash: parent, Timestamp: time.Now().UTC(), }, - Signee: pub, }, } - b.TxBillings = tbs + for _, tb := range tbs { + b.Transactions = append(b.Transactions, tb) + } - testNonce++ - var tr = &pt.Transfer{ - TransferHeader: pt.TransferHeader{ + testAddress1Nonce++ + var tr = pt.NewTransfer( + &pt.TransferHeader{ Sender: testAddress1, Receiver: testAddress2, - Nonce: testNonce, + Nonce: testAddress1Nonce, Amount: 1, }, - } + ) if err = tr.Sign(priv); err != nil { return } b.Transactions = append(b.Transactions, tr) err = b.PackAndSignBlock(priv) - for i := range b.TxBillings { - b.TxBillings[i].SignedBlock = &b.SignedHeader.BlockHash - } return } -func generateRandomBillingRequestHeader() *types.BillingRequestHeader { - return &types.BillingRequestHeader{ +func generateRandomBillingRequestHeader() *pt.BillingRequestHeader { + return &pt.BillingRequestHeader{ DatabaseID: *generateRandomDatabaseID(), LowBlock: generateRandomHash(), LowHeight: rand.Int31(), @@ -208,9 +200,9 @@ func generateRandomBillingRequestHeader() *types.BillingRequestHeader { } } -func generateRandomBillingRequest() (*types.BillingRequest, error) { +func generateRandomBillingRequest() (*pt.BillingRequest, error) { reqHeader := generateRandomBillingRequestHeader() - req := types.BillingRequest{ + req := pt.BillingRequest{ Header: *reqHeader, } h, err := req.PackRequestHeader() @@ -240,40 +232,19 @@ func generateRandomBillingRequest() (*types.BillingRequest, error) { return &req, nil } -func generateRandomBillingResponse() (*types.BillingResponse, error) { - priv, pub, err := asymmetric.GenSecp256k1KeyPair() - if err != nil { - return nil, err - } - h := generateRandomHash() - sign, err := priv.Sign(h[:]) - if err != nil { - return nil, err - } - resp := types.BillingResponse{ - AccountAddress: proto.AccountAddress(generateRandomHash()), - RequestHash: h, - Signee: pub, - Signature: sign, +func generateRandomBillingHeader() (tc *pt.BillingHeader, err error) { + var req *pt.BillingRequest + if req, err = generateRandomBillingRequest(); err != nil { + return } - return &resp, nil -} -func generateRandomTxContent() (*types.TxContent, error) { - req, err := generateRandomBillingRequest() - if err != nil { - return nil, err - } - priv, pub, err := asymmetric.GenSecp256k1KeyPair() - sign, err := priv.Sign(req.RequestHash[:]) - if err != nil { - return nil, err + var priv *asymmetric.PrivateKey + if priv, _, err = asymmetric.GenSecp256k1KeyPair(); err != nil { + return } - resp := &types.BillingResponse{ - AccountAddress: proto.AccountAddress(generateRandomHash()), - RequestHash: req.RequestHash, - Signee: pub, - Signature: sign, + + if _, _, err = req.SignRequestHeader(priv, false); err != nil { + return } receivers := make([]*proto.AccountAddress, peerNum) @@ -286,69 +257,55 @@ func generateRandomTxContent() (*types.TxContent, error) { fees[i] = rand.Uint64() rewards[i] = rand.Uint64() } + producer := proto.AccountAddress(generateRandomHash()) - tc := &types.TxContent{ - SequenceID: rand.Uint32(), - BillingRequest: *req, - BillingResponse: *resp, - Receivers: receivers, - Fees: fees, - Rewards: rewards, - } + tc = pt.NewBillingHeader(pi.AccountNonce(rand.Uint32()), req, producer, receivers, fees, rewards) return tc, nil } -func generateRandomTxBilling() (*types.TxBilling, error) { - txContent, err := generateRandomTxContent() +func generateRandomBillingAndBaseAccount() (*pt.BaseAccount, *pt.Billing, error) { + header, err := generateRandomBillingHeader() if err != nil { - return nil, err + return nil, nil, err } - accountAddress := proto.AccountAddress(generateRandomHash()) - txHash := generateRandomHash() - priv, pub, err := asymmetric.GenSecp256k1KeyPair() - sign, err := priv.Sign(txHash[:]) - if err != nil { - return nil, err + priv, _, err := asymmetric.GenSecp256k1KeyPair() + header.Producer, _ = crypto.PubKeyHash(priv.PubKey()) + + txBilling := pt.NewBilling(header) + + if err := txBilling.Sign(priv); err != nil { + return nil, nil, err } - blockHash := generateRandomHash() - txBilling := &types.TxBilling{ - TxContent: *txContent, - AccountAddress: &accountAddress, - TxHash: &txHash, - Signee: pub, - Signature: sign, - SignedBlock: &blockHash, + txBaseAccount := pt.NewBaseAccount( + &pt.Account{ + Address: header.Producer, + StableCoinBalance: testInitBalance, + CovenantCoinBalance: testInitBalance, + }, + ) + + if err := txBaseAccount.Sign(priv); err != nil { + return nil, nil, err } - return txBilling, nil + + return txBaseAccount, txBilling, nil } -func generateRandomTxBillingWithSeqID(seqID uint32) (*types.TxBilling, error) { - txContent, err := generateRandomTxContent() - txContent.SequenceID = seqID +func generateRandomAccountBilling() (*pt.Billing, error) { + header, err := generateRandomBillingHeader() if err != nil { return nil, err } - accountAddress := testAddress1 - enc, err := txContent.MarshalHash() - if err != nil { - return nil, err - } - txHash := hash.THashH(enc) - priv, pub, err := asymmetric.GenSecp256k1KeyPair() - sign, err := priv.Sign(txHash[:]) - if err != nil { + header.Producer = testAddress1 + testAddress1Nonce++ + header.Nonce = testAddress1Nonce + txBilling := pt.NewBilling(header) + + if err := txBilling.Sign(testPrivKey); err != nil { return nil, err } - txBilling := &types.TxBilling{ - TxContent: *txContent, - AccountAddress: &accountAddress, - TxHash: &txHash, - Signee: pub, - Signature: sign, - SignedBlock: nil, - } return txBilling, nil } @@ -372,22 +329,6 @@ func generateRandomHash() hash.Hash { return h } -func generateRandomNode() (node *nodeProfile, err error) { - priv, pub, err := asymmetric.GenSecp256k1KeyPair() - - if err != nil { - return - } - - node = &nodeProfile{ - PrivateKey: priv, - PublicKey: pub, - } - - createRandomString(10, 10, (*string)(&node.NodeID)) - return -} - func registerNodesWithPublicKey(pub *asymmetric.PublicKey, diff int, num int) ( nis []cpuminer.NonceInfo, err error) { nis = make([]cpuminer.NonceInfo, num) @@ -432,17 +373,6 @@ func createRandomString(offset, length int, s *string) { *s = string(buff) } -// createNodes assign Node asymmetric key pair and generate Node.NonceInfo -// Node.ID = Node.NonceInfo.Hash. -func createNodes(pubKey *asymmetric.PublicKey, timeThreshold time.Duration) *proto.Node { - node := proto.NewNode() - nonce := asymmetric.GetPubKeyNonce(pubKey, proto.NewNodeIDDifficulty, timeThreshold, nil) - node.ID = proto.NodeID(nonce.Hash.String()) - node.Nonce = nonce.Nonce - log.Debugf("Node: %v", node) - return node -} - func createTestPeersWithPrivKeys(priv *asymmetric.PrivateKey, num int) (nis []cpuminer.NonceInfo, p *kayak.Peers, err error) { if num <= 0 { return @@ -552,7 +482,7 @@ func setup() { rand.Read(genesisHash[:]) // Create key paire for test - if testPrivKey, testPubKey, err = asymmetric.GenSecp256k1KeyPair(); err != nil { + if testPrivKey, _, err = asymmetric.GenSecp256k1KeyPair(); err != nil { panic(err) } diff --git a/build.sh b/build.sh index cb5211048..f856edc00 100755 --- a/build.sh +++ b/build.sh @@ -34,9 +34,6 @@ cql_observer_pkgpath="github.com/CovenantSQL/CovenantSQL/cmd/cql-observer" go build -ldflags "-X main.version=${version} -X github.com/CovenantSQL/CovenantSQL/conf.RoleTag=C ${GOLDFLAGS}" -o bin/cql-observer ${cql_observer_pkgpath} go test -coverpkg github.com/CovenantSQL/CovenantSQL/... -cover -race -c -tags 'testbinary' -ldflags "-X main.version=${version} -X github.com/CovenantSQL/CovenantSQL/conf.RoleTag=C ${GOLDFLAGS}" -o bin/cql-observer.test ${cql_observer_pkgpath} -# hotfix_pkgpath="github.com/CovenantSQL/CovenantSQL/cmd/hotfix/msgpack-20180824" -# CGO_ENABLED=1 go build -ldflags "${GOLDFLAGS}" -o bin/hotfix_msgpack_20180824 ${hotfix_pkgpath} - cli_pkgpath="github.com/CovenantSQL/CovenantSQL/cmd/cql" CGO_ENABLED=1 go build -ldflags "-X main.version=${version} -X github.com/CovenantSQL/CovenantSQL/conf.RoleTag=C ${GOLDFLAGS}" --tags ${platform}" sqlite_omit_load_extension" -o bin/cql ${cli_pkgpath} @@ -47,7 +44,10 @@ cql_faucet_pkgpath="github.com/CovenantSQL/CovenantSQL/cmd/cql-faucet" CGO_ENABLED=1 go build -ldflags "-X main.version=${version} -X github.com/CovenantSQL/CovenantSQL/conf.RoleTag=C ${GOLDFLAGS}" --tags ${platform}" sqlite_omit_load_extension" -o bin/cql-faucet ${cql_faucet_pkgpath} cql_mysql_adapter_pkgpath="github.com/CovenantSQL/CovenantSQL/cmd/cql-mysql-adapter" -CGO_ENABLED=1 go build -ldflags "-X github.com/CovenantSQL/CovenantSQL/conf.RoleTag=C ${GOLDFLAGS}" --tags ${platform}" sqlite_omit_load_extension" -o bin/cql-mysql-adapter ${cql_mysql_adapter_pkgpath} +CGO_ENABLED=1 go build -ldflags "-X main.version=${version} -X github.com/CovenantSQL/CovenantSQL/conf.RoleTag=C ${GOLDFLAGS}" --tags ${platform}" sqlite_omit_load_extension" -o bin/cql-mysql-adapter ${cql_mysql_adapter_pkgpath} + +cql_explorer_pkgpath="github.com/CovenantSQL/CovenantSQL/cmd/cql-explorer" +CGO_ENABLED=1 go build -ldflags "-X main.version=${version} -X github.com/CovenantSQL/CovenantSQL/conf.RoleTag=C ${GOLDFLAGS}" --tags ${platform}" sqlite_omit_load_extension" -o bin/cql-explorer ${cql_explorer_pkgpath} echo "done" diff --git a/cleanupDB.sh b/cleanupDB.sh index a14cbd9bd..caf5dc037 100755 --- a/cleanupDB.sh +++ b/cleanupDB.sh @@ -7,4 +7,5 @@ cd ${PROJECT_DIR} && find . -name '*.db-shm' -exec rm -f {} \; cd ${PROJECT_DIR} && find . -name '*.db-wal' -exec rm -f {} \; cd ${PROJECT_DIR} && find . -name 'db.meta' -exec rm -f {} \; cd ${PROJECT_DIR} && find . -name 'public.keystore' -exec rm -f {} \; -cd ${PROJECT_DIR} && find . -name '*.public.keystore' -exec rm -f {} \; \ No newline at end of file +cd ${PROJECT_DIR} && find . -name '*.public.keystore' -exec rm -f {} \; +cd ${PROJECT_DIR} && find . -type d -name '*.ldb' -prune -exec rm -rf {} \; diff --git a/client/_example/simple.go b/client/_example/simple.go index 1bbd2e420..1dd270aab 100644 --- a/client/_example/simple.go +++ b/client/_example/simple.go @@ -19,7 +19,6 @@ package main import ( "database/sql" "flag" - "fmt" "github.com/CovenantSQL/CovenantSQL/client" diff --git a/client/clientbench_test.go b/client/clientbench_test.go index af6e68738..b19fb2c85 100644 --- a/client/clientbench_test.go +++ b/client/clientbench_test.go @@ -41,7 +41,7 @@ func BenchmarkCovenantSQLDriver(b *testing.B) { log.SetLevel(log.DebugLevel) err = os.Chdir(testWorkingDir) if err != nil { - log.Errorf("change working dir failed: %s", err) + log.WithError(err).Error("change working dir failed") return } @@ -59,7 +59,7 @@ func BenchmarkCovenantSQLDriver(b *testing.B) { b.Fatal(err) } - log.Infof("the created database dsn is %v", dsn) + log.WithField("dsn", dsn).Info("created database") db, err := sql.Open("covenantsql", dsn) if err != nil { @@ -90,7 +90,7 @@ func BenchmarkCovenantSQLDriver(b *testing.B) { if err != nil || result < 0 { b.Fatal(err) } - log.Debugf("result %d", result) + log.WithField("result", result).Debug("collected result") } }) err = db.Close() diff --git a/client/config.go b/client/config.go index 8b7a498eb..9f18a6861 100644 --- a/client/config.go +++ b/client/config.go @@ -18,26 +18,13 @@ package client import ( "net/url" - "time" -) - -const ( - paramKeyDebug = "debug" - paramKeyUpdateInterval = "update_interval" -) - -var ( - // DefaultPeersUpdateInterval set client update peers config every 15 seconds. - DefaultPeersUpdateInterval = time.Second * 15 + "strings" ) // Config is a configuration parsed from a DSN string. type Config struct { DatabaseID string - Debug bool - PeersUpdateInterval time.Duration - // additional configs should be filled // such as read/write/exec timeout // currently no timeout is supported. @@ -45,10 +32,7 @@ type Config struct { // NewConfig creates a new config with default value. func NewConfig() *Config { - return &Config{ - Debug: false, - PeersUpdateInterval: DefaultPeersUpdateInterval, - } + return &Config{} } // FormatDSN formats the given Config into a DSN string which can be passed to the driver. @@ -56,20 +40,11 @@ func (cfg *Config) FormatDSN() string { // build query from arguments u := &url.URL{ - Scheme: "covenantsql", + Scheme: DBScheme, Host: cfg.DatabaseID, } newQuery := u.Query() - - if cfg.Debug { - newQuery.Set(paramKeyDebug, "true") - } - - if cfg.PeersUpdateInterval != DefaultPeersUpdateInterval { - newQuery.Set(paramKeyUpdateInterval, cfg.PeersUpdateInterval.String()) - } - u.RawQuery = newQuery.Encode() return u.String() @@ -77,6 +52,10 @@ func (cfg *Config) FormatDSN() string { // ParseDSN parse the DSN string to a Config. func ParseDSN(dsn string) (cfg *Config, err error) { + if !strings.HasPrefix(dsn, DBScheme) && !strings.HasPrefix(dsn, DBSchemeAlias) { + dsn = DBScheme + "://" + dsn + } + var u *url.URL if u, err = url.Parse(dsn); err != nil { return @@ -85,17 +64,5 @@ func ParseDSN(dsn string) (cfg *Config, err error) { cfg = NewConfig() cfg.DatabaseID = u.Host - urlQuery := u.Query() - - if urlQuery.Get(paramKeyDebug) == "true" { - cfg.Debug = true - } - if updateInterval := urlQuery.Get(paramKeyUpdateInterval); updateInterval != "" { - // parse update interval - if cfg.PeersUpdateInterval, err = time.ParseDuration(updateInterval); err != nil { - return - } - } - return } diff --git a/client/config_test.go b/client/config_test.go index a59a42595..f7a3d501b 100644 --- a/client/config_test.go +++ b/client/config_test.go @@ -18,7 +18,6 @@ package client import ( "testing" - "time" "github.com/CovenantSQL/CovenantSQL/proto" . "github.com/smartystreets/goconvey/convey" @@ -33,19 +32,15 @@ func TestConfig(t *testing.T) { So(err, ShouldBeNil) So(cfg.DatabaseID, ShouldEqual, proto.DatabaseID("db")) So(cfg.FormatDSN(), ShouldEqual, "covenantsql://db") - - // test with parameters - cfg, err = ParseDSN("covenantsql://db?debug=true&update_interval=1s") + }) + Convey("test invalid config", t, func() { + _, err := ParseDSN("invalid dsn") + So(err, ShouldNotBeNil) + }) + Convey("test dsn with only database id", t, func() { + dbIDStr := "00000bef611d346c0cbe1beaa76e7f0ed705a194fdf9ac3a248ec70e9c198bf9" + cfg, err := ParseDSN(dbIDStr) So(err, ShouldBeNil) - So(cfg.DatabaseID, ShouldEqual, proto.DatabaseID("db")) - So(cfg.Debug, ShouldBeTrue) - So(cfg.PeersUpdateInterval, ShouldEqual, time.Second) - - cfg.Debug = false - So(cfg.FormatDSN(), ShouldEqual, "covenantsql://db?update_interval=1s") - - cfg.Debug = true - cfg.PeersUpdateInterval = DefaultPeersUpdateInterval - So(cfg.FormatDSN(), ShouldEqual, "covenantsql://db?debug=true") + So(cfg.DatabaseID, ShouldEqual, dbIDStr) }) } diff --git a/client/conn.go b/client/conn.go index 60c8371ed..a91de5258 100644 --- a/client/conn.go +++ b/client/conn.go @@ -20,13 +20,10 @@ import ( "context" "database/sql" "database/sql/driver" - "math/rand" - "strings" "sync" "sync/atomic" "time" - bp "github.com/CovenantSQL/CovenantSQL/blockproducer" "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" "github.com/CovenantSQL/CovenantSQL/crypto/kms" "github.com/CovenantSQL/CovenantSQL/kayak" @@ -37,39 +34,24 @@ import ( wt "github.com/CovenantSQL/CovenantSQL/worker/types" ) -var ( - connectionID uint64 - seqNo uint64 - randSource = rand.New(rand.NewSource(time.Now().UnixNano())) -) - // conn implements an interface sql.Conn. type conn struct { dbID proto.DatabaseID - queries []wt.Query - peers *kayak.Peers - peersLock sync.RWMutex - nodeID proto.NodeID - privKey *asymmetric.PrivateKey - pubKey *asymmetric.PublicKey + queries []wt.Query + localNodeID proto.NodeID + privKey *asymmetric.PrivateKey + ackCh chan *wt.Ack inTransaction bool closed int32 - closeCh chan struct{} + pCaller *rpc.PersistentCaller } func newConn(cfg *Config) (c *conn, err error) { - if cfg.Debug { - log.SetLevel(log.DebugLevel) - } - - // init connectionID to random id - atomic.CompareAndSwapUint64(&connectionID, 0, randSource.Uint64()) - // get local node id - var nodeID proto.NodeID - if nodeID, err = kms.GetLocalNodeID(); err != nil { + var localNodeID proto.NodeID + if localNodeID, err = kms.GetLocalNodeID(); err != nil { return } @@ -79,53 +61,85 @@ func newConn(cfg *Config) (c *conn, err error) { return } - // get local public key - var pubKey *asymmetric.PublicKey - if pubKey, err = kms.GetLocalPublicKey(); err != nil { + c = &conn{ + dbID: proto.DatabaseID(cfg.DatabaseID), + localNodeID: localNodeID, + privKey: privKey, + queries: make([]wt.Query, 0), + } + + // get peers from BP + if _, err = cacheGetPeers(c.dbID, c.privKey); err != nil { + log.WithError(err).Error("cacheGetPeers failed") + c = nil return } - c = &conn{ - dbID: proto.DatabaseID(cfg.DatabaseID), - nodeID: nodeID, - privKey: privKey, - pubKey: pubKey, - queries: make([]wt.Query, 0), - closeCh: make(chan struct{}), + err = c.startAckWorkers(2) + if err != nil { + log.WithError(err).Error("startAckWorkers failed") + c = nil + return } + log.WithField("db", c.dbID).Debug("new connection to database") - c.log("new conn database ", c.dbID) + return +} - // get peers from BP - if err = c.getPeers(); err != nil { - return +func (c *conn) startAckWorkers(workerCount int) (err error) { + c.ackCh = make(chan *wt.Ack, workerCount*4) + for i := 0; i < workerCount; i++ { + go c.ackWorker() } + return +} - // start peers update routine - go func() { - ticker := time.NewTicker(cfg.PeersUpdateInterval) - defer ticker.Stop() +func (c *conn) stopAckWorkers() { + close(c.ackCh) +} - for { - select { - case <-c.closeCh: - return - case <-ticker.C: +func (c *conn) ackWorker() { + if rawPeers, ok := peerList.Load(c.dbID); ok { + if peers, ok := rawPeers.(*kayak.Peers); ok { + var ( + oneTime sync.Once + pc *rpc.PersistentCaller + err error + ) + + ackWorkerLoop: + for { + ack, got := <-c.ackCh + if !got { //closed and empty + break ackWorkerLoop + } + oneTime.Do(func() { + pc = rpc.NewPersistentCaller(peers.Leader.ID) + }) + if err = ack.Sign(c.privKey, false); err != nil { + log.WithField("target", pc.TargetID).WithError(err).Error("failed to sign ack") + continue + } + + var ackRes wt.AckResponse + // send ack back + if err = pc.Call(route.DBSAck.String(), ack, &ackRes); err != nil { + log.WithError(err).Warning("send ack failed") + continue + } } - - if err = c.getPeers(); err != nil { - c.log("update peers failed ", err.Error()) + if pc != nil { + pc.CloseStream() } + log.Debug("ack worker quiting") + return } - }() + } + log.Fatal("must GetPeers first") return } -func (c *conn) log(msg ...interface{}) { - log.Debug(msg...) -} - // Prepare implements the driver.Conn.Prepare method. func (c *conn) Prepare(query string) (driver.Stmt, error) { return c.PrepareContext(context.Background(), query) @@ -135,15 +149,10 @@ func (c *conn) Prepare(query string) (driver.Stmt, error) { func (c *conn) Close() error { // close the meta connection if atomic.CompareAndSwapInt32(&c.closed, 0, 1) { - c.log("closed connection") - } - - select { - case <-c.closeCh: - default: - close(c.closeCh) + log.WithField("db", c.dbID).Debug("closed connection") } - + c.stopAckWorkers() + c.pCaller.CloseStream() return nil } @@ -159,7 +168,7 @@ func (c *conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, e } // start transaction - c.log("begin transaction tx=", c.inTransaction) + log.WithField("inTx", c.inTransaction).Debug("begin transaction") if c.inTransaction { return nil, sql.ErrTxDone @@ -178,6 +187,8 @@ func (c *conn) PrepareContext(ctx context.Context, query string) (driver.Stmt, e return nil, driver.ErrBadConn } + log.WithField("query", query).Debug("prepared statement") + // prepare the statement return newStmt(c, query), nil } @@ -270,29 +281,55 @@ func (c *conn) addQuery(queryType wt.QueryType, query *wt.Query) (rows driver.Ro // append queries c.queries = append(c.queries, *query) + + log.WithFields(log.Fields{ + "pattern": query.Pattern, + "args": query.Args, + }).Debug("add query to tx") + return } + log.WithFields(log.Fields{ + "pattern": query.Pattern, + "args": query.Args, + }).Debug("execute query") + return c.sendQuery(queryType, []wt.Query{*query}) } func (c *conn) sendQuery(queryType wt.QueryType, queries []wt.Query) (rows driver.Rows, err error) { - c.peersLock.RLock() - defer c.peersLock.RUnlock() + var peers *kayak.Peers + if peers, err = cacheGetPeers(c.dbID, c.privKey); err != nil { + return + } + + // allocate sequence + connID, seqNo := allocateConnAndSeq() + defer putBackConn(connID) + + defer func() { + log.WithFields(log.Fields{ + "count": len(queries), + "type": queryType.String(), + "connID": connID, + "seqNo": seqNo, + "target": peers.Leader.ID, + "source": c.localNodeID, + }).WithError(err).Debug("send query") + }() // build request - seqNo := atomic.AddUint64(&seqNo, 1) req := &wt.Request{ Header: wt.SignedRequestHeader{ RequestHeader: wt.RequestHeader{ QueryType: queryType, - NodeID: c.nodeID, + NodeID: c.localNodeID, DatabaseID: c.dbID, - ConnectionID: atomic.LoadUint64(&connectionID), + ConnectionID: connID, SeqNo: seqNo, Timestamp: getLocalTime(), }, - Signee: c.pubKey, }, Payload: wt.RequestPayload{ Queries: queries, @@ -303,87 +340,29 @@ func (c *conn) sendQuery(queryType wt.QueryType, queries []wt.Query) (rows drive return } - pCaller := rpc.NewPersistentCaller(c.peers.Leader.ID) - defer pCaller.Close() + c.pCaller = rpc.NewPersistentCaller(peers.Leader.ID) var response wt.Response - if err = pCaller.Call(route.DBSQuery.String(), req, &response); err != nil { - if strings.Contains(err.Error(), "invalid request sequence") { - // request sequence failure, try again - atomic.StoreUint64(&connectionID, randSource.Uint64()) - req.Header.ConnectionID = atomic.LoadUint64(&connectionID) - req.Header.SeqNo = atomic.AddUint64(&seqNo, 1) - - if err = req.Sign(c.privKey); err != nil { - return - } - - // send request again - if err = pCaller.Call(route.DBSQuery.String(), req, &response); err != nil { - return - } - } else { - return - } + if err = c.pCaller.Call(route.DBSQuery.String(), req, &response); err != nil { + return } // verify response if err = response.Verify(); err != nil { return } + rows = newRows(&response) // build ack - ack := &wt.Ack{ + c.ackCh <- &wt.Ack{ Header: wt.SignedAckHeader{ AckHeader: wt.AckHeader{ Response: response.Header, - NodeID: c.nodeID, + NodeID: c.localNodeID, Timestamp: getLocalTime(), }, - Signee: c.pubKey, }, } - if err = ack.Sign(c.privKey); err != nil { - return - } - - var ackRes wt.AckResponse - - // send ack back - if err = pCaller.Call(route.DBSAck.String(), ack, &ackRes); err != nil { - log.Warningf("ack query failed: %v", err) - err = nil - } - - rows = newRows(&response) - - return -} - -func (c *conn) getPeers() (err error) { - c.peersLock.Lock() - defer c.peersLock.Unlock() - - req := new(bp.GetDatabaseRequest) - req.Header.DatabaseID = c.dbID - req.Header.Signee = c.pubKey - - if err = req.Sign(c.privKey); err != nil { - return - } - - res := new(bp.GetDatabaseResponse) - if err = requestBP(route.BPDBGetDatabase, req, res); err != nil { - return - } - - // verify response - if err = res.Verify(); err != nil { - return - } - - c.peers = res.Header.InstanceMeta.Peers - return } diff --git a/client/conn_test.go b/client/conn_test.go index 70e714f9a..29022e9e4 100644 --- a/client/conn_test.go +++ b/client/conn_test.go @@ -18,6 +18,7 @@ package client import ( "database/sql" + "sync" "testing" "github.com/CovenantSQL/CovenantSQL/utils/log" @@ -250,3 +251,40 @@ func TestTransaction(t *testing.T) { So(err, ShouldNotBeNil) }) } + +func TestConnAndSeqAllocation(t *testing.T) { + Convey("conn id and seq no allocation test", t, func() { + var wg sync.WaitGroup + var seqMap sync.Map + testFunc := func(c, s uint64) { + v, l := seqMap.LoadOrStore(c, s) + if l { + vi := v.(uint64) + if vi >= s { + // invalid + t.Fatalf(ErrInvalidRequestSeq.Error()) + } + } else { + seqMap.Store(c, s) + } + } + f := func() { + wg.Add(1) + go func() { + defer wg.Done() + for i := 0; i != 100; i++ { + connID, seqNo := allocateConnAndSeq() + t.Logf("connID: %v, seqNo: %v", connID, seqNo) + testFunc(connID, seqNo) + putBackConn(connID) + } + }() + } + + f() + f() + f() + f() + wg.Wait() + }) +} diff --git a/client/driver.go b/client/driver.go index 0f9a9e2d9..4522fac11 100644 --- a/client/driver.go +++ b/client/driver.go @@ -19,27 +19,51 @@ package client import ( "database/sql" "database/sql/driver" + "math/rand" + "strings" + "sync" + "sync/atomic" + "time" + + "github.com/pkg/errors" bp "github.com/CovenantSQL/CovenantSQL/blockproducer" "github.com/CovenantSQL/CovenantSQL/conf" "github.com/CovenantSQL/CovenantSQL/crypto" "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" "github.com/CovenantSQL/CovenantSQL/crypto/kms" + "github.com/CovenantSQL/CovenantSQL/kayak" "github.com/CovenantSQL/CovenantSQL/proto" "github.com/CovenantSQL/CovenantSQL/route" "github.com/CovenantSQL/CovenantSQL/rpc" + "github.com/CovenantSQL/CovenantSQL/utils/log" wt "github.com/CovenantSQL/CovenantSQL/worker/types" ) const ( - // PubKeyStorePath defines public cache store. - PubKeyStorePath = "./public.keystore" + // DBScheme defines the dsn scheme. + DBScheme = "covenantsql" + // DBSchemeAlias defines the alias dsn scheme. + DBSchemeAlias = "cql" +) + +var ( + // PeersUpdateInterval defines peers list refresh interval for client. + PeersUpdateInterval = time.Second * 5 + + driverInitialized uint32 + peersUpdaterRunning uint32 + peerList sync.Map // map[proto.DatabaseID]*kayak.Peers + connIDLock sync.Mutex + connIDAvail []uint64 + globalSeqNo uint64 + randSource = rand.New(rand.NewSource(time.Now().UnixNano())) ) func init() { - driver := new(covenantSQLDriver) - sql.Register("covenantsql", driver) - sql.Register("cql", driver) + d := new(covenantSQLDriver) + sql.Register(DBScheme, d) + sql.Register(DBSchemeAlias, d) } // covenantSQLDriver implements sql.Driver interface. @@ -53,6 +77,11 @@ func (d *covenantSQLDriver) Open(dsn string) (conn driver.Conn, err error) { return } + if atomic.LoadUint32(&driverInitialized) == 0 { + err = ErrNotInitialized + return + } + return newConn(cfg) } @@ -61,6 +90,11 @@ type ResourceMeta wt.ResourceMeta // Init defines init process for client. func Init(configFile string, masterKey []byte) (err error) { + if !atomic.CompareAndSwapUint32(&driverInitialized, 0, 1) { + err = ErrAlreadyInitialized + return + } + // load config if conf.GConf, err = conf.LoadConfig(configFile); err != nil { return @@ -71,31 +105,48 @@ func Init(configFile string, masterKey []byte) (err error) { } // ping block producer to register node - err = registerNode() + if err = registerNode(); err != nil { + return + } + + // run peers updater + if err = runPeerListUpdater(); err != nil { + return + } return } // Create send create database operation to block producer. func Create(meta ResourceMeta) (dsn string, err error) { + if atomic.LoadUint32(&driverInitialized) == 0 { + err = ErrNotInitialized + return + } + req := new(bp.CreateDatabaseRequest) req.Header.ResourceMeta = wt.ResourceMeta(meta) if req.Header.Signee, err = kms.GetLocalPublicKey(); err != nil { + err = errors.Wrap(err, "get local public key failed") return } var privateKey *asymmetric.PrivateKey if privateKey, err = kms.GetLocalPrivateKey(); err != nil { + err = errors.Wrap(err, "get local private key failed") return } if err = req.Sign(privateKey); err != nil { + err = errors.Wrap(err, "sign request failed") return } res := new(bp.CreateDatabaseResponse) if err = requestBP(route.BPDBCreateDatabase, req, res); err != nil { + err = errors.Wrap(err, "call BPDB.CreateDatabase failed") return } if err = res.Verify(); err != nil { + err = errors.Wrap(err, "response verify failed") return } @@ -108,6 +159,11 @@ func Create(meta ResourceMeta) (dsn string, err error) { // Drop send drop database operation to block producer. func Drop(dsn string) (err error) { + if atomic.LoadUint32(&driverInitialized) == 0 { + err = ErrNotInitialized + return + } + var cfg *Config if cfg, err = ParseDSN(dsn); err != nil { return @@ -133,6 +189,11 @@ func Drop(dsn string) (err error) { // GetStableCoinBalance get the stable coin balance of current account. func GetStableCoinBalance() (balance uint64, err error) { + if atomic.LoadUint32(&driverInitialized) == 0 { + err = ErrNotInitialized + return + } + req := new(bp.QueryAccountStableBalanceReq) resp := new(bp.QueryAccountStableBalanceResp) @@ -154,6 +215,11 @@ func GetStableCoinBalance() (balance uint64, err error) { // GetCovenantCoinBalance get the covenant coin balance of current account. func GetCovenantCoinBalance() (balance uint64, err error) { + if atomic.LoadUint32(&driverInitialized) == 0 { + err = ErrNotInitialized + return + } + req := new(bp.QueryAccountCovenantBalanceReq) resp := new(bp.QueryAccountCovenantBalanceResp) @@ -198,3 +264,141 @@ func registerNode() (err error) { return } + +func runPeerListUpdater() (err error) { + var privKey *asymmetric.PrivateKey + if privKey, err = kms.GetLocalPrivateKey(); err != nil { + return + } + + if !atomic.CompareAndSwapUint32(&peersUpdaterRunning, 0, 1) { + return + } + + go func() { + for { + if atomic.LoadUint32(&peersUpdaterRunning) == 0 { + return + } + + var wg sync.WaitGroup + + peerList.Range(func(rawDBID, _ interface{}) bool { + dbID := rawDBID.(proto.DatabaseID) + + wg.Add(1) + go func(dbID proto.DatabaseID) { + defer wg.Done() + var err error + + if _, err = getPeers(dbID, privKey); err != nil { + log.WithField("db", dbID). + WithError(err). + Warning("update peers failed") + + // TODO(xq262144), better rpc remote error judgement + if strings.Contains(err.Error(), bp.ErrNoSuchDatabase.Error()) { + log.WithField("db", dbID). + Warning("database no longer exists, stopped peers update") + peerList.Delete(dbID) + } + } + }(dbID) + + return true + }) + + wg.Wait() + + time.Sleep(PeersUpdateInterval) + } + }() + + return +} + +func stopPeersUpdater() { + atomic.StoreUint32(&peersUpdaterRunning, 0) +} + +func cacheGetPeers(dbID proto.DatabaseID, privKey *asymmetric.PrivateKey) (peers *kayak.Peers, err error) { + var ok bool + var rawPeers interface{} + var cacheHit bool + + defer func() { + log.WithFields(log.Fields{ + "db": dbID, + "hit": cacheHit, + }).WithError(err).Debug("cache get peers for database") + }() + + if rawPeers, ok = peerList.Load(dbID); ok { + if peers, ok = rawPeers.(*kayak.Peers); ok { + cacheHit = true + return + } + } + + // get peers using non-cache method + return getPeers(dbID, privKey) +} + +func getPeers(dbID proto.DatabaseID, privKey *asymmetric.PrivateKey) (peers *kayak.Peers, err error) { + req := new(bp.GetDatabaseRequest) + req.Header.DatabaseID = dbID + + defer func() { + log.WithFields(log.Fields{ + "db": dbID, + "peers": peers, + }).WithError(err).Debug("get peers for database") + }() + + if err = req.Sign(privKey); err != nil { + return + } + + res := new(bp.GetDatabaseResponse) + if err = requestBP(route.BPDBGetDatabase, req, res); err != nil { + return + } + + // verify response + if err = res.Verify(); err != nil { + return + } + + peers = res.Header.InstanceMeta.Peers + + // set peers in the updater cache + peerList.Store(dbID, peers) + + return +} + +func allocateConnAndSeq() (connID uint64, seqNo uint64) { + connIDLock.Lock() + defer connIDLock.Unlock() + + if len(connIDAvail) == 0 { + // generate one + connID = randSource.Uint64() + seqNo = atomic.AddUint64(&globalSeqNo, 1) + return + } + + // pop one conn + connID = connIDAvail[0] + connIDAvail = connIDAvail[1:] + seqNo = atomic.AddUint64(&globalSeqNo, 1) + + return +} + +func putBackConn(connID uint64) { + connIDLock.Lock() + defer connIDLock.Unlock() + + connIDAvail = append(connIDAvail, connID) +} diff --git a/client/driver_test.go b/client/driver_test.go index 162bb2ad2..f412b19f7 100644 --- a/client/driver_test.go +++ b/client/driver_test.go @@ -18,6 +18,7 @@ package client import ( "path/filepath" + "sync/atomic" "testing" "github.com/CovenantSQL/CovenantSQL/route" @@ -35,12 +36,15 @@ func TestInit(t *testing.T) { stopTestService, confDir, err = startTestService() So(err, ShouldBeNil) defer stopTestService() + // fake driver not initialized + atomic.StoreUint32(&driverInitialized, 0) err = Init(filepath.Join(confDir, "config.yaml"), []byte("")) So(err, ShouldBeNil) // test loaded block producer nodes bps := route.GetBPs() So(len(bps), ShouldBeGreaterThanOrEqualTo, 1) //So(bps[0].ToRawNodeID().ToNodeID(), ShouldResemble, (*conf.GConf.KnownNodes)[0].ID) + stopPeersUpdater() }) } diff --git a/client/errors.go b/client/errors.go index 28043ca20..ca89de944 100644 --- a/client/errors.go +++ b/client/errors.go @@ -16,9 +16,16 @@ package client -import "errors" +import "github.com/pkg/errors" // Various errors the driver might returns. var ( + // ErrQueryInTransaction represents a read query is presented during user transaction. ErrQueryInTransaction = errors.New("only write is supported during transaction") + // ErrNotInitialized represents the driver is not initialized yet. + ErrNotInitialized = errors.New("driver not initialized") + // ErrAlreadyInitialized represents the driver is already initialized. + ErrAlreadyInitialized = errors.New("driver already initialized") + // ErrInvalidRequestSeq defines invalid sequence no of request. + ErrInvalidRequestSeq = errors.New("invalid request sequence applied") ) diff --git a/client/helper_test.go b/client/helper_test.go index 59aafa303..ed267535a 100644 --- a/client/helper_test.go +++ b/client/helper_test.go @@ -25,6 +25,7 @@ import ( "path/filepath" "runtime" "sync" + "sync/atomic" "time" bp "github.com/CovenantSQL/CovenantSQL/blockproducer" @@ -45,6 +46,11 @@ import ( wt "github.com/CovenantSQL/CovenantSQL/worker/types" ) +const ( + // PubKeyStorePath defines public cache store. + PubKeyStorePath = "./public.keystore" +) + var ( rootHash = hash.Hash{} ) @@ -207,7 +213,7 @@ func startTestService() (stopTestService func(), tempDir string, err error) { block, err = createRandomBlock(rootHash, true) // get database peers - if peers, err = getPeers(1); err != nil { + if peers, err = genPeers(1); err != nil { return } @@ -242,7 +248,7 @@ func initNode() (cleanupFunc func(), tempDir string, server *rpc.Server, err err if tempDir, err = ioutil.TempDir("", "db_test_"); err != nil { return } - log.Debugf("temp dir: %s", tempDir) + log.WithField("d", tempDir).Debug("created temp dir") // init conf _, testFile, _, _ := runtime.Caller(0) @@ -260,7 +266,10 @@ func initNode() (cleanupFunc func(), tempDir string, server *rpc.Server, err err log.Debugf("GConf: %#v", conf.GConf) _, err = utils.CopyFile(privateKeyPath, conf.GConf.PrivateKeyFile) if err != nil { - log.Fatalf("Copy %s to %s failed: %v", privateKeyPath, conf.GConf.PrivateKeyFile, err) + log.WithFields(log.Fields{ + "from": privateKeyPath, + "to": conf.GConf.PrivateKeyFile, + }).WithError(err).Fatal("copy private key failed") return } // reset the once @@ -276,17 +285,17 @@ func initNode() (cleanupFunc func(), tempDir string, server *rpc.Server, err err } // init rpc - if server, err = rpc.NewServerWithService(rpc.ServiceMap{"DHT": dht}); err != nil { + if server, err = rpc.NewServerWithService(rpc.ServiceMap{route.DHTRPCName: dht}); err != nil { return } // register bpdb service - if err = server.RegisterService(bp.DBServiceName, &stubBPDBService{}); err != nil { + if err = server.RegisterService(route.BPDBRPCName, &stubBPDBService{}); err != nil { return } // register fake chain service - if err = server.RegisterService(bp.MainChainRPCName, &stubBPDBService{}); err != nil { + if err = server.RegisterService(route.BlockProducerRPCName, &stubBPDBService{}); err != nil { return } @@ -305,6 +314,9 @@ func initNode() (cleanupFunc func(), tempDir string, server *rpc.Server, err err server.Stop() } + // fake database init already processed + atomic.StoreUint32(&driverInitialized, 1) + return } @@ -329,8 +341,6 @@ func createRandomBlock(parent hash.Hash, isGenesis bool) (b *ct.Block, err error ParentHash: parent, Timestamp: time.Now().UTC(), }, - Signee: pub, - Signature: nil, }, Queries: make([]*hash.Hash, rand.Intn(10)+10), } @@ -391,7 +401,7 @@ func getKeys() (privKey *asymmetric.PrivateKey, pubKey *asymmetric.PublicKey, er return } -func getPeers(term uint64) (peers *kayak.Peers, err error) { +func genPeers(term uint64) (peers *kayak.Peers, err error) { // get node id var nodeID proto.NodeID if nodeID, err = kms.GetLocalNodeID(); err != nil { diff --git a/cmd/cql-adapter/README.md b/cmd/cql-adapter/README.md index 38194e2a7..dbc4a3b2e 100644 --- a/cmd/cql-adapter/README.md +++ b/cmd/cql-adapter/README.md @@ -51,7 +51,7 @@ $ cql-utils -tool adapterconfgen -config config.yaml ListenAddr (default: 0.0.0.0:4661): ⏎ CertificatePath (default: server.pem): ⏎ PrivateKeyPath (default: server-key.pem): ⏎ -VerifyCertificate (default: false): ⏎ +VerifyCertificate (default: true) (y/n): ⏎ ClientCAPath (default:): ⏎ AdminCerts (default:): ⏎ WriteCerts (default:): ⏎ @@ -120,8 +120,8 @@ $ cql-adapter -config config.yaml ```bash // send query (linux) curl -v https://127.0.0.1:4661/v1/query --insecure \ - --cert read.data.thunderdb.io.pem \ - --key read.data.thunderdb.io.key \ + --cert read.data.covenantsql.io.pem \ + --key read.data.covenantsql.io.key \ --form database=kucoin.GO.BTC \ --form query='select * from trades limit 10' @@ -244,7 +244,7 @@ curl -v https://e.morenodes.com:11108/v1/query --insecure \ ###### Parameters -**node:** node count requirement for ThunderDB +**node:** node count requirement for CovenantSQL ###### Response diff --git a/cmd/cql-adapter/api/account.go b/cmd/cql-adapter/api/account.go index 21dc3c35a..d06e49389 100644 --- a/cmd/cql-adapter/api/account.go +++ b/cmd/cql-adapter/api/account.go @@ -20,6 +20,7 @@ import ( "net/http" "github.com/CovenantSQL/CovenantSQL/client" + "github.com/CovenantSQL/CovenantSQL/utils/log" ) func init() { @@ -35,7 +36,10 @@ type accountAPI struct{} // StableCoinBalance defines query for stable coin balance. func (a *accountAPI) StableCoinBalance(rw http.ResponseWriter, r *http.Request) { - if balance, err := client.GetStableCoinBalance(); err != nil { + var balance uint64 + var err error + + if balance, err = client.GetStableCoinBalance(); err != nil { sendResponse(http.StatusInternalServerError, false, err, nil, rw) } else { sendResponse(http.StatusOK, true, nil, map[string]interface{}{ @@ -43,12 +47,17 @@ func (a *accountAPI) StableCoinBalance(rw http.ResponseWriter, r *http.Request) }, rw) } + log.WithField("stableBalance", balance).WithError(err).Debug("get stable coin balance") + return } // CovenantCoinBalance defines query for covenant coin balance. func (a *accountAPI) CovenantCoinBalance(rw http.ResponseWriter, r *http.Request) { - if balance, err := client.GetCovenantCoinBalance(); err != nil { + var balance uint64 + var err error + + if balance, err = client.GetCovenantCoinBalance(); err != nil { sendResponse(http.StatusInternalServerError, false, err, nil, rw) } else { sendResponse(http.StatusOK, true, nil, map[string]interface{}{ @@ -56,5 +65,7 @@ func (a *accountAPI) CovenantCoinBalance(rw http.ResponseWriter, r *http.Request }, rw) } + log.WithField("covenantBalance", balance).WithError(err).Debug("get covenant coin balance") + return } diff --git a/cmd/cql-adapter/api/admin.go b/cmd/cql-adapter/api/admin.go index 2abd04d61..6ee4c2fe6 100644 --- a/cmd/cql-adapter/api/admin.go +++ b/cmd/cql-adapter/api/admin.go @@ -23,6 +23,7 @@ import ( "strconv" "github.com/CovenantSQL/CovenantSQL/cmd/cql-adapter/config" + "github.com/CovenantSQL/CovenantSQL/utils/log" ) func init() { @@ -61,12 +62,20 @@ func (a *adminAPI) CreateDatabase(rw http.ResponseWriter, r *http.Request) { nodeCntStr := r.FormValue("node") nodeCnt, err := strconv.Atoi(nodeCntStr) + var dbID string + + defer func() { + log.WithFields(log.Fields{ + "nodeCnt": nodeCnt, + "db": dbID, + }).WithError(err).Debug("create database") + }() + if err != nil || nodeCnt <= 0 || nodeCnt >= math.MaxUint16 { sendResponse(http.StatusBadRequest, false, "Invalid node count supplied", nil, rw) return } - var dbID string if dbID, err = config.GetConfig().StorageInstance.Create(nodeCnt); err != nil { sendResponse(http.StatusInternalServerError, false, err, nil, rw) return @@ -80,11 +89,16 @@ func (a *adminAPI) CreateDatabase(rw http.ResponseWriter, r *http.Request) { // DropDatabase defines drop database admin API. func (a *adminAPI) DropDatabase(rw http.ResponseWriter, r *http.Request) { var dbID string + var err error + + defer func() { + log.WithField("db", dbID).WithError(err).Debug("drop database") + }() + if dbID = getDatabaseID(rw, r); dbID == "" { return } - var err error if err = config.GetConfig().StorageInstance.Drop(dbID); err != nil { sendResponse(http.StatusInternalServerError, false, err, nil, rw) return diff --git a/cmd/cql-adapter/api/query.go b/cmd/cql-adapter/api/query.go index 3cc5078f5..aed0b15de 100644 --- a/cmd/cql-adapter/api/query.go +++ b/cmd/cql-adapter/api/query.go @@ -47,7 +47,7 @@ func (a *queryAPI) Query(rw http.ResponseWriter, r *http.Request) { return } - log.WithField("db", dbID).WithField("query", query).Infof("got query") + log.WithField("db", dbID).WithField("query", query).Info("got query") assoc := r.FormValue("assoc") @@ -136,7 +136,7 @@ func (a *queryAPI) Write(rw http.ResponseWriter, r *http.Request) { return } - log.WithField("db", dbID).WithField("query", query).Infof("got exec") + log.WithField("db", dbID).WithField("query", query).Info("got exec") var err error if err = config.GetConfig().StorageInstance.Exec(dbID, query); err != nil { diff --git a/cmd/cql-adapter/config/config.go b/cmd/cql-adapter/config/config.go index 15b56a55c..debf4f5e7 100644 --- a/cmd/cql-adapter/config/config.go +++ b/cmd/cql-adapter/config/config.go @@ -59,7 +59,7 @@ type Config struct { WriteCertificates []*x509.Certificate `yaml:"-"` // storage config - StorageDriver string `yaml:"StorageDriver"` // sqlite3 or ThunderDB + StorageDriver string `yaml:"StorageDriver"` // sqlite3 or covenantsql StorageRoot string `yaml:"StorageRoot"` StorageInstance storage.Storage `yaml:"-"` } @@ -73,17 +73,17 @@ func LoadConfig(configPath string, password string) (config *Config, err error) var workingRoot string var configBytes []byte if configBytes, err = ioutil.ReadFile(configPath); err != nil { - log.Errorf("read config file failed: %v", err) + log.WithError(err).Error("read config file failed") } configWrapper := &confWrapper{} if err = yaml.Unmarshal(configBytes, configWrapper); err != nil { - log.Errorf("unmarshal config file failed: %v", err) + log.WithError(err).Error("unmarshal config file failed") return } if configWrapper.Adapter == nil { err = ErrEmptyAdapterConfig - log.Errorf("could not read adapter config: %v", err) + log.WithError(err).Error("could not read adapter config") return } @@ -103,7 +103,7 @@ func LoadConfig(configPath string, password string) (config *Config, err error) if config.CertificatePath == "" || config.PrivateKeyPath == "" { err = ErrRequireServerCertificate - log.Errorf("invalid adapter config: %v", err) + log.WithError(err).Error("invalid adapter config") return } diff --git a/cmd/cql-adapter/main.go b/cmd/cql-adapter/main.go index 1b356b7b0..570937371 100644 --- a/cmd/cql-adapter/main.go +++ b/cmd/cql-adapter/main.go @@ -19,8 +19,10 @@ package main import ( "context" "flag" + "fmt" "os" "os/signal" + "runtime" "time" "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" @@ -28,9 +30,13 @@ import ( "golang.org/x/sys/unix" ) +const name = "cql-adapeter" + var ( - configFile string - password string + version = "unknown" + configFile string + password string + showVersion bool ) func init() { @@ -38,26 +44,33 @@ func init() { flag.StringVar(&password, "password", "", "master key password") flag.BoolVar(&asymmetric.BypassSignature, "bypassSignature", false, "Disable signature sign and verify, for testing") + flag.BoolVar(&showVersion, "version", false, "Show version information and exit") } func main() { flag.Parse() + if showVersion { + fmt.Printf("%v %v %v %v %v\n", + name, version, runtime.GOOS, runtime.GOARCH, runtime.Version()) + os.Exit(0) + } + flag.Visit(func(f *flag.Flag) { - log.Infof("Args %s : %v", f.Name, f.Value) + log.Infof("Args %#v : %s", f.Name, f.Value) }) server, err := NewHTTPAdapter(configFile, password) if err != nil { - log.Fatalf("init adapter failed: %v", err) + log.WithError(err).Fatal("init adapter failed") return } stop := make(chan os.Signal, 1) signal.Notify(stop, os.Interrupt, unix.SIGTERM) - log.Infof("start adapter") + log.Info("start adapter") if err = server.Serve(); err != nil { - log.Fatalf("start adapter failed: %v", err) + log.WithError(err).Fatal("start adapter failed") return } @@ -66,5 +79,5 @@ func main() { ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) defer cancel() server.Shutdown(ctx) - log.Infof("stopped adapter") + log.Info("stopped adapter") } diff --git a/cmd/cql-adapter/server.go b/cmd/cql-adapter/server.go index 93090ab86..e8cc0c204 100644 --- a/cmd/cql-adapter/server.go +++ b/cmd/cql-adapter/server.go @@ -27,7 +27,7 @@ import ( "github.com/gorilla/handlers" ) -// HTTPAdapter is a adapter for ThunderDB/alternative sqlite3 service. +// HTTPAdapter is a adapter for covenantsql/alternative sqlite3 service. type HTTPAdapter struct { tlsConfig *tls.Config server *http.Server diff --git a/cmd/cql-adapter/storage/covenantsql.go b/cmd/cql-adapter/storage/covenantsql.go index 14149d378..f5847d7b8 100644 --- a/cmd/cql-adapter/storage/covenantsql.go +++ b/cmd/cql-adapter/storage/covenantsql.go @@ -22,17 +22,17 @@ import ( "github.com/CovenantSQL/CovenantSQL/client" ) -// ThunderDBStorage defines the thunderdb database abstraction. -type ThunderDBStorage struct{} +// CovenantSQLStorage defines the covenantsql database abstraction. +type CovenantSQLStorage struct{} -// NewCovenantSQLStorage returns new thunderdb storage handler. -func NewCovenantSQLStorage() (s *ThunderDBStorage) { - s = &ThunderDBStorage{} +// NewCovenantSQLStorage returns new covenantsql storage handler. +func NewCovenantSQLStorage() (s *CovenantSQLStorage) { + s = &CovenantSQLStorage{} return } // Create implements the Storage abstraction interface. -func (s *ThunderDBStorage) Create(nodeCnt int) (dbID string, err error) { +func (s *CovenantSQLStorage) Create(nodeCnt int) (dbID string, err error) { var dsn string if dsn, err = client.Create(client.ResourceMeta{Node: uint16(nodeCnt)}); err != nil { return @@ -48,7 +48,7 @@ func (s *ThunderDBStorage) Create(nodeCnt int) (dbID string, err error) { } // Drop implements the Storage abstraction interface. -func (s *ThunderDBStorage) Drop(dbID string) (err error) { +func (s *CovenantSQLStorage) Drop(dbID string) (err error) { cfg := client.NewConfig() cfg.DatabaseID = dbID err = client.Drop(cfg.FormatDSN()) @@ -56,7 +56,7 @@ func (s *ThunderDBStorage) Drop(dbID string) (err error) { } // Query implements the Storage abstraction interface. -func (s *ThunderDBStorage) Query(dbID string, query string) (columns []string, types []string, result [][]interface{}, err error) { +func (s *CovenantSQLStorage) Query(dbID string, query string) (columns []string, types []string, result [][]interface{}, err error) { var conn *sql.DB if conn, err = s.getConn(dbID); err != nil { return @@ -92,7 +92,7 @@ func (s *ThunderDBStorage) Query(dbID string, query string) (columns []string, t } // Exec implements the Storage abstraction interface. -func (s *ThunderDBStorage) Exec(dbID string, query string) (err error) { +func (s *CovenantSQLStorage) Exec(dbID string, query string) (err error) { var conn *sql.DB if conn, err = s.getConn(dbID); err != nil { return @@ -104,7 +104,7 @@ func (s *ThunderDBStorage) Exec(dbID string, query string) (err error) { return } -func (s *ThunderDBStorage) getConn(dbID string) (db *sql.DB, err error) { +func (s *CovenantSQLStorage) getConn(dbID string) (db *sql.DB, err error) { cfg := client.NewConfig() cfg.DatabaseID = dbID diff --git a/cmd/cql-adapter/storage/sqlite3.go b/cmd/cql-adapter/storage/sqlite3.go index e1311838c..f3a80f1af 100644 --- a/cmd/cql-adapter/storage/sqlite3.go +++ b/cmd/cql-adapter/storage/sqlite3.go @@ -24,7 +24,6 @@ import ( "math/rand" "os" "path/filepath" - // Import sqlite3 manually. _ "github.com/CovenantSQL/go-sqlite3-encrypt" ) @@ -130,7 +129,7 @@ func (s *SQLite3Storage) Exec(dbID string, query string) (err error) { func (s *SQLite3Storage) getConn(dbID string, readonly bool) (db *sql.DB, err error) { dbFile := filepath.Join(s.rootDir, dbID+".db3") - dbDSN := fmt.Sprintf("file:%s?_journal_mode=WAL&_synchronous=FULL", dbFile) + dbDSN := fmt.Sprintf("file:%s?_journal_mode=WAL&_synchronous=NORMAL", dbFile) if readonly { dbDSN += "&mode=ro" } diff --git a/cmd/cql-explorer/README.md b/cmd/cql-explorer/README.md new file mode 100644 index 000000000..6bce4872e --- /dev/null +++ b/cmd/cql-explorer/README.md @@ -0,0 +1,182 @@ +This doc introduce the usage of CovenantSQL block producer chain explorer server. + +## Prerequisites + +Make sure the ```$GOPATH/bin``` is in your ```$PATH```, download/build the explorer binary. + +```shell +$ go get github.com/CovenantSQL/CovenantSQL/cmd/cql-explorer +``` + +Adapter requires a CovenantSQL ```config.yaml``` which can by generated by configuration generator. + +### Generating Default Config File + +Generate the main configuration file. Same as [Generating Default Config File in Golang Client Doc](https://github.com/CovenantSQL/CovenantSQL/tree/develop/client#generating-default-config-file). An existing configuration file can also be used. + +## Explorer Usage + +### Start + +Start the explorer by following commands: + +```shell +$ cql-explorer -config config.yaml +``` + +The available options are: + +```shell +$ cql-explorer --help +Usage of cql-explorer: + -config string + config file path (default "./config.yaml") + -interval duration + new block check interval for explorer (default 2s) + -listen string + listen address for http explorer api (default "127.0.0.1:4665") + -password string + master key password for covenantsql +``` + +### API + +#### Query Synced Head Block + +**GET** /v1/head + +##### Request + +##### Response + +```json +{ + "success" : true, + "status" : "ok", + "data" : { + "block" : { + "txs" : [], + "hash" : "20ba21af54da3e17252fb4b6b7331fb6f36aca1b9b793597af6ef46faad34dea", + "timestamp" : 1540278575120.34, + "version" : 1, + "count" : 561, + "producer" : "8d7604acfdb391891a4c795f0939425b6d58bd50a81e579d15f06ecd381ad549", + "height" : 3040488, + "parent" : "f9c4f9c7a1dcbcf14a13eb91a007b33672f1f8a261738f5a25fee27c3ccaa584" + } + } +} +``` + +#### Query Block by _COUNT_ + +**GET** /v1/count/{count} + +##### Request + +__count__: count of specified block, 0 for genesis block + +##### Response + +```json +{ + "success" : true, + "status" : "ok", + "data" : { + "block" : { + "version" : 1, + "height" : 0, + "count" : 0, + "timestamp" : 1534197599120, + "hash" : "f745ca6427237aac858dd3c7f2df8e6f3c18d0f1c164e07a1c6b8eebeba6b154", + "txs" : [], + "parent" : "0000000000000000000000000000000000000000000000000000000000000001", + "producer" : "0000000000000000000000000000000000000000000000000000000000000001" + } + } +} +``` + +#### Query Block by _HASH_ + +**GET** /v1/block/{hash} + +##### Request + +__hash__: hash of specified block + +##### Response + +```json +{ + "success" : true, + "status" : "ok", + "data" : { + "block" : { + "version" : 1, + "height" : 0, + "count" : 0, + "timestamp" : 1534197599120, + "hash" : "f745ca6427237aac858dd3c7f2df8e6f3c18d0f1c164e07a1c6b8eebeba6b154", + "txs" : [], + "parent" : "0000000000000000000000000000000000000000000000000000000000000001", + "producer" : "0000000000000000000000000000000000000000000000000000000000000001" + } + } +} +``` + +#### Query Block by _HEIGHT_ + +**GET** /v1/height/{height} + +##### Request + +__height__: height of specified block, 0 for genesis block (height is related to block produce time and interval) + +##### Response + +```json +{ + "success" : true, + "status" : "ok", + "data" : { + "block" : { + "version" : 1, + "height" : 0, + "count" : 0, + "timestamp" : 1534197599120, + "hash" : "f745ca6427237aac858dd3c7f2df8e6f3c18d0f1c164e07a1c6b8eebeba6b154", + "txs" : [], + "parent" : "0000000000000000000000000000000000000000000000000000000000000001", + "producer" : "0000000000000000000000000000000000000000000000000000000000000001" + } + } +} +``` + +#### Query Transaction by _HASH_ + +**GET** /v1/tx/{hash} + +##### Request + +__hash__: hash of specified tx + +##### Response + +```json +{ + "success": true, + "status": "ok", + "data": { + "tx": { + "nonce": 11616, + "amount": 1225, + "sender": "00000bef611d346c0cbe1beaa76e7f0ed705a194fdf9ac3a248ec70e9c198bf9", + "receiver": "676b12fef8732ac78a97ea5dba0977bbbabc48f64eee66f09be89a589297e567", + "type": "Transfer" + } + } +} +``` \ No newline at end of file diff --git a/cmd/cql-explorer/api.go b/cmd/cql-explorer/api.go new file mode 100644 index 000000000..fb55c3366 --- /dev/null +++ b/cmd/cql-explorer/api.go @@ -0,0 +1,327 @@ +/* + * Copyright 2018 The CovenantSQL Authors. + * + * 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. + */ + +package main + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "strconv" + "time" + + pi "github.com/CovenantSQL/CovenantSQL/blockproducer/interfaces" + pt "github.com/CovenantSQL/CovenantSQL/blockproducer/types" + "github.com/CovenantSQL/CovenantSQL/crypto/hash" + "github.com/CovenantSQL/CovenantSQL/proto" + "github.com/CovenantSQL/CovenantSQL/utils/log" + "github.com/gorilla/mux" +) + +var ( + apiTimeout = time.Second * 10 +) + +func sendResponse(code int, success bool, msg interface{}, data interface{}, rw http.ResponseWriter) { + msgStr := "ok" + if msg != nil { + msgStr = fmt.Sprint(msg) + } + rw.WriteHeader(code) + json.NewEncoder(rw).Encode(map[string]interface{}{ + "status": msgStr, + "success": success, + "data": data, + }) +} + +func sendError(err error, rw http.ResponseWriter) { + if err == ErrNotFound { + sendResponse(404, false, err, nil, rw) + } else if err == ErrBadRequest { + sendResponse(400, false, err, nil, rw) + } else if err != nil { + sendResponse(500, false, err, nil, rw) + } else { + sendResponse(200, true, nil, nil, rw) + } +} + +func getUintFromVars(field string, r *http.Request) (value uint32, err error) { + vars := mux.Vars(r) + valueStr := vars[field] + if valueStr == "" { + err = ErrBadRequest + return + } + + valueUint, err := strconv.ParseUint(valueStr, 10, 32) + if err != nil { + return + } + + value = uint32(valueUint) + + return +} + +type explorerAPI struct { + service *Service +} + +func (a *explorerAPI) GetHighestBlock(rw http.ResponseWriter, r *http.Request) { + count, err := a.service.getHighestCount() + if err != nil { + sendError(err, rw) + return + } + + block, _, height, err := a.service.getBlockByCount(count) + if err != nil { + sendError(err, rw) + return + } + + sendResponse(200, true, nil, a.formatBlock(count, height, block), rw) +} + +func (a *explorerAPI) GetBlockByCount(rw http.ResponseWriter, r *http.Request) { + count, err := getUintFromVars("count", r) + if err != nil { + sendError(err, rw) + return + } + + block, _, height, err := a.service.getBlockByCount(count) + if err != nil { + sendError(err, rw) + return + } + + sendResponse(200, true, nil, a.formatBlock(count, height, block), rw) +} + +func (a *explorerAPI) GetBlockByHeight(rw http.ResponseWriter, r *http.Request) { + height, err := getUintFromVars("height", r) + if err != nil { + sendError(err, rw) + return + } + + block, count, _, err := a.service.getBlockByHeight(height) + if err != nil { + sendError(err, rw) + return + } + + sendResponse(200, true, nil, a.formatBlock(count, height, block), rw) +} + +func (a *explorerAPI) GetBlockByHash(rw http.ResponseWriter, r *http.Request) { + h, err := a.getHash(r) + if err != nil { + sendError(err, rw) + return + } + + block, count, height, err := a.service.getBlockByHash(h) + if err != nil { + sendError(err, rw) + return + } + + sendResponse(200, true, nil, a.formatBlock(count, height, block), rw) +} + +func (a *explorerAPI) GetTxByHash(rw http.ResponseWriter, r *http.Request) { + h, err := a.getHash(r) + if err != nil { + sendError(err, rw) + return + } + + tx, count, height, err := a.service.getTxByHash(h) + if err != nil { + sendError(err, rw) + return + } + + sendResponse(200, true, nil, a.formatTx(count, height, tx), rw) +} + +func (a *explorerAPI) formatTime(t time.Time) float64 { + return float64(t.UnixNano()) / 1e6 +} + +func (a *explorerAPI) formatBlock(count uint32, height uint32, b *pt.Block) map[string]interface{} { + txs := make([]map[string]interface{}, 0, len(b.Transactions)) + + for _, tx := range b.Transactions { + txs = append(txs, a.formatRawTx(tx)) + } + + return map[string]interface{}{ + "block": map[string]interface{}{ + "height": height, + "count": count, + "hash": b.BlockHash().String(), + "parent": b.ParentHash().String(), + "timestamp": a.formatTime(b.Timestamp()), + "version": b.SignedHeader.Version, + "producer": b.SignedHeader.Producer.String(), + "txs": txs, + }, + } +} + +func (a *explorerAPI) formatRawTx(t pi.Transaction) (res map[string]interface{}) { + if t == nil { + return nil + } + + switch tx := t.(type) { + case *pt.Transfer: + res = map[string]interface{}{ + "nonce": tx.Nonce, + "sender": tx.Sender.String(), + "receiver": tx.Receiver.String(), + "amount": tx.Amount, + } + case *pt.Billing: + res = a.formatTxBilling(tx) + case *pt.BaseAccount: + res = map[string]interface{}{ + "next_nonce": tx.NextNonce, + "address": tx.Address, + "stable_balance": tx.StableCoinBalance, + "covenant_balance": tx.CovenantCoinBalance, + "rating": tx.Rating, + } + case *pi.TransactionWrapper: + res = a.formatRawTx(tx.Unwrap()) + return + default: + // for unknown transactions + if txBytes, err := json.Marshal(tx); err != nil { + res = map[string]interface{}{ + "error": err.Error(), + } + } else if err = json.Unmarshal(txBytes, &res); err != nil { + res = map[string]interface{}{ + "error": err.Error(), + } + } + } + + res["type"] = t.GetTransactionType().String() + + return +} + +func (a *explorerAPI) formatTxBilling(tx *pt.Billing) (res map[string]interface{}) { + if tx == nil { + return + } + + return map[string]interface{}{ + "nonce": tx.Nonce, + "producer": tx.Producer.String(), + "billing_request": func(br pt.BillingRequest) map[string]interface{} { + return map[string]interface{}{ + "database_id": br.Header.DatabaseID, + "low_block": br.Header.LowBlock.String(), + "low_height": br.Header.LowHeight, + "high_block": br.Header.HighBlock.String(), + "high_height": br.Header.HighHeight, + "gas_amounts": func(gasAmounts []*proto.AddrAndGas) (d []map[string]interface{}) { + for _, g := range gasAmounts { + d = append(d, map[string]interface{}{ + "address": g.AccountAddress.String(), + "node": g.RawNodeID.String(), + "amount": g.GasAmount, + }) + } + return + }(br.Header.GasAmounts), + } + }(tx.BillingRequest), + "receivers": func(receivers []*proto.AccountAddress) (s []string) { + for _, r := range receivers { + s = append(s, r.String()) + } + return + }(tx.Receivers), + "fees": tx.Fees, + "rewards": tx.Rewards, + } +} + +func (a *explorerAPI) formatTx(count uint32, height uint32, tx pi.Transaction) map[string]interface{} { + var res map[string]interface{} + + if res = a.formatRawTx(tx); res != nil { + res["height"] = height + res["count"] = count + } + + return map[string]interface{}{ + "tx": res, + } +} + +func (a *explorerAPI) getHash(r *http.Request) (h *hash.Hash, err error) { + vars := mux.Vars(r) + hStr := vars["hash"] + return hash.NewHashFromStr(hStr) +} + +func startAPI(service *Service, listenAddr string) (server *http.Server, err error) { + router := mux.NewRouter() + router.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) { + sendResponse(http.StatusOK, true, nil, nil, rw) + }).Methods("GET") + + api := &explorerAPI{ + service: service, + } + v1Router := router.PathPrefix("/v1").Subrouter() + v1Router.HandleFunc("/tx/{hash}", api.GetTxByHash).Methods("GET") + v1Router.HandleFunc("/height/{height:[0-9]+}", api.GetBlockByHeight).Methods("GET") + v1Router.HandleFunc("/block/{hash}", api.GetBlockByHash).Methods("GET") + v1Router.HandleFunc("/count/{count:[0-9]+}", api.GetBlockByCount).Methods("GET") + v1Router.HandleFunc("/head", api.GetHighestBlock).Methods("GET") + + server = &http.Server{ + Addr: listenAddr, + WriteTimeout: apiTimeout, + ReadTimeout: apiTimeout, + IdleTimeout: apiTimeout, + Handler: router, + } + + go func() { + if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { + log.WithError(err).Fatal("start api server failed") + } + }() + + return server, err +} + +func stopAPI(server *http.Server) (err error) { + return server.Shutdown(context.Background()) +} diff --git a/cmd/cql-explorer/errors.go b/cmd/cql-explorer/errors.go new file mode 100644 index 000000000..22937dac8 --- /dev/null +++ b/cmd/cql-explorer/errors.go @@ -0,0 +1,32 @@ +/* + * Copyright 2018 The CovenantSQL Authors. + * + * 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. + */ + +package main + +import "github.com/pkg/errors" + +var ( + // ErrNilBlock represents nil block received. + ErrNilBlock = errors.New("nil block received") + // ErrNilTransaction represents nil transaction received. + ErrNilTransaction = errors.New("nil transaction received") + // ErrStopped defines error on explorer service has already stopped + ErrStopped = errors.New("explorer service has stopped") + // ErrNotFound defines error on failed to found specified resource + ErrNotFound = errors.New("resource not found") + // ErrBadRequest defines errors on error input field. + ErrBadRequest = errors.New("request field not fulfilled") +) diff --git a/cmd/cql-explorer/main.go b/cmd/cql-explorer/main.go new file mode 100644 index 000000000..171138d40 --- /dev/null +++ b/cmd/cql-explorer/main.go @@ -0,0 +1,122 @@ +/* + * Copyright 2018 The CovenantSQL Authors. + * + * 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. + */ + +package main + +import ( + "flag" + "fmt" + "math/rand" + "net/http" + "os" + "os/signal" + "runtime" + "syscall" + "time" + + "github.com/CovenantSQL/CovenantSQL/client" + "github.com/CovenantSQL/CovenantSQL/utils/log" +) + +const name = "cql-explorer" + +var ( + version = "unknown" +) + +var ( + // config + configFile string + password string + listenAddr string + checkInterval time.Duration + showVersion bool +) + +func init() { + flag.StringVar(&configFile, "config", "./config.yaml", "config file path") + flag.StringVar(&listenAddr, "listen", "127.0.0.1:4665", "listen address for http explorer api") + flag.DurationVar(&checkInterval, "interval", time.Second*2, "new block check interval for explorer") + flag.StringVar(&password, "password", "", "master key password for covenantsql") + flag.BoolVar(&showVersion, "version", false, "Show version information and exit") +} + +func main() { + // set random + rand.Seed(time.Now().UnixNano()) + log.SetLevel(log.DebugLevel) + flag.Parse() + if showVersion { + fmt.Printf("%v %v %v %v %v\n", + name, version, runtime.GOOS, runtime.GOARCH, runtime.Version()) + os.Exit(0) + } + + flag.Visit(func(f *flag.Flag) { + log.Infof("Args %#v : %s", f.Name, f.Value) + }) + + // init client + var err error + if err = client.Init(configFile, []byte(password)); err != nil { + log.WithError(err).Fatal("init node failed") + return + } + + // start service + var service *Service + if service, err = NewService(checkInterval); err != nil { + log.WithError(err).Fatal("init service failed") + return + } + + // start api + var httpServer *http.Server + if httpServer, err = startAPI(service, listenAddr); err != nil { + log.WithError(err).Fatal("start explorer api failed") + return + } + + // start subscription + if err = service.start(); err != nil { + log.WithError(err).Fatal("start service failed") + return + } + + signalCh := make(chan os.Signal, 1) + signal.Notify( + signalCh, + syscall.SIGINT, + syscall.SIGTERM, + ) + signal.Ignore(syscall.SIGHUP, syscall.SIGTTIN, syscall.SIGTTOU) + + <-signalCh + + // stop explorer api + if err = stopAPI(httpServer); err != nil { + log.WithError(err).Fatal("stop explorer api failed") + return + } + + // stop subscription + if err = service.stop(); err != nil { + log.WithError(err).Fatal("stop service failed") + return + } + + log.Info("explorer stopped") +} diff --git a/cmd/cql-explorer/service.go b/cmd/cql-explorer/service.go new file mode 100644 index 000000000..0ccda7ff3 --- /dev/null +++ b/cmd/cql-explorer/service.go @@ -0,0 +1,460 @@ +/* + * Copyright 2018 The CovenantSQL Authors. + * + * 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. + */ + +package main + +import ( + "bytes" + "encoding/binary" + "path/filepath" + "sync" + "sync/atomic" + "time" + + bp "github.com/CovenantSQL/CovenantSQL/blockproducer" + pi "github.com/CovenantSQL/CovenantSQL/blockproducer/interfaces" + pt "github.com/CovenantSQL/CovenantSQL/blockproducer/types" + "github.com/CovenantSQL/CovenantSQL/conf" + "github.com/CovenantSQL/CovenantSQL/crypto/hash" + "github.com/CovenantSQL/CovenantSQL/proto" + "github.com/CovenantSQL/CovenantSQL/route" + "github.com/CovenantSQL/CovenantSQL/rpc" + "github.com/CovenantSQL/CovenantSQL/utils" + "github.com/CovenantSQL/CovenantSQL/utils/log" + "github.com/syndtr/goleveldb/leveldb" + "github.com/syndtr/goleveldb/leveldb/util" +) + +const ( + dbFileName = "explorer.db" +) + +var ( + // storage keys + blockKeyPrefix = []byte("BLOCK_") + blockHashPrefix = []byte("HASH_") + blockHeightPrefix = []byte("HEIGHT_") + txKeyPrefix = []byte("TX_") +) + +// Service defines the main chain explorer service structure. +type Service struct { + db *leveldb.DB + + caller *rpc.Caller + stopped int32 + stopCh chan struct{} + triggerCh chan struct{} + wg sync.WaitGroup + + // new block check interval + checkInterval time.Duration + + // next block to fetch + nextBlockToFetch uint32 +} + +// NewService creates new explorer service handler. +func NewService(checkInterval time.Duration) (service *Service, err error) { + // open explorer database + dbFile := filepath.Join(conf.GConf.WorkingRoot, dbFileName) + db, err := leveldb.OpenFile(dbFile, nil) + if err != nil { + return + } + + defer func() { + if err != nil { + db.Close() + } + }() + + // init service + service = &Service{ + db: db, + caller: rpc.NewCaller(), + stopCh: make(chan struct{}), + triggerCh: make(chan struct{}, 1), + checkInterval: checkInterval, + } + + return +} + +func (s *Service) start() (err error) { + if atomic.LoadInt32(&s.stopped) == 1 { + // stopped + return ErrStopped + } + + if err = s.getSubscriptionCheckpoint(); err != nil { + return + } + + // start subscription worker + s.wg.Add(1) + go s.subscriptionWorker() + + return +} + +func (s *Service) getBlockByCount(c uint32) (b *pt.Block, count uint32, height uint32, err error) { + var bKey []byte + bKey = append(bKey, blockKeyPrefix...) + bKey = append(bKey, uint32ToBytes(c)...) + + it := s.db.NewIterator(util.BytesPrefix(bKey), nil) + if it.First() { + // decode + bKeyLen := len(bKey) + hBytes := it.Key()[bKeyLen : bKeyLen+4] + height = bytesToUint32(hBytes) + count = c + err = utils.DecodeMsgPack(it.Value(), &b) + } else { + // not found + err = ErrNotFound + } + it.Release() + + if err != nil { + // ignore iterator error + it.Error() + return + } + + err = it.Error() + + return +} + +func (s *Service) getBlockByHash(h *hash.Hash) (b *pt.Block, count uint32, height uint32, err error) { + if h == nil { + err = ErrNotFound + return + } + + var bKey []byte + bKey = append(bKey, blockHashPrefix...) + bKey = append(bKey, h[:]...) + + var bCountData []byte + if bCountData, err = s.db.Get(bKey, nil); err != nil { + if err == leveldb.ErrNotFound { + err = ErrNotFound + } + return + } + + count = bytesToUint32(bCountData) + return s.getBlockByCount(count) +} + +func (s *Service) getBlockByHeight(h uint32) (b *pt.Block, count uint32, height uint32, err error) { + var bKey []byte + bKey = append(bKey, blockHeightPrefix...) + bKey = append(bKey, uint32ToBytes(h)...) + + var bCountData []byte + if bCountData, err = s.db.Get(bKey, nil); err != nil { + if err == leveldb.ErrNotFound { + err = ErrNotFound + } + return + } + + count = bytesToUint32(bCountData) + return s.getBlockByCount(count) +} + +func (s *Service) getTxByHash(h *hash.Hash) (tx pi.Transaction, c uint32, height uint32, err error) { + if h == nil { + err = ErrNotFound + return + } + + var txKey []byte + txKey = append(txKey, txKeyPrefix...) + txKey = append(txKey, h[:]...) + + var bCountData []byte + if bCountData, err = s.db.Get(txKeyPrefix, nil); err != nil { + if err == leveldb.ErrNotFound { + err = ErrNotFound + } + return + } + + c = bytesToUint32(bCountData) + + var b *pt.Block + if b, _, height, err = s.getBlockByCount(c); err != nil { + return + } + + if b == nil || b.Transactions == nil { + err = ErrNotFound + return + } + + for _, curTx := range b.Transactions { + if curTx == nil { + continue + } + + if curH := curTx.GetHash(); h.IsEqual(&curH) { + tx = curTx + break + } + } + + if tx == nil { + err = ErrNotFound + return + } + + return +} + +func (s *Service) getHighestCount() (c uint32, err error) { + // load previous committed counts + it := s.db.NewIterator(util.BytesPrefix(blockKeyPrefix), nil) + if it.Last() { + // decode block count from key + blockKey := it.Key() + prefixLen := len(blockKeyPrefix) + c = bytesToUint32(blockKey[prefixLen : prefixLen+4]) + } else { + err = ErrNotFound + } + it.Release() + + if err != nil { + it.Error() + return + } + + err = it.Error() + + return +} + +func (s *Service) getSubscriptionCheckpoint() (err error) { + var lastBlockCount uint32 + if lastBlockCount, err = s.getHighestCount(); err != nil { + log.WithError(err).Warning("get last block failed") + + if err == ErrNotFound { + // not found, set last block count to 0 + log.Info("set current block count fetch head to 0") + err = nil + atomic.StoreUint32(&s.nextBlockToFetch, 0) + } + + return + } + + log.WithFields(log.Fields{ + "count": lastBlockCount, + }).Info("fetched last block count") + + atomic.StoreUint32(&s.nextBlockToFetch, lastBlockCount+1) + + return +} + +func (s *Service) subscriptionWorker() { + defer s.wg.Done() + + log.Info("started subscription worker") + for { + select { + case <-s.stopCh: + log.Info("exited subscription worker") + return + case <-s.triggerCh: + case <-time.After(s.checkInterval): + } + + // request block producer for next block + s.requestBlock() + } +} + +func (s *Service) requestBlock() { + if atomic.LoadInt32(&s.stopped) == 1 { + return + } + + blockCount := atomic.LoadUint32(&s.nextBlockToFetch) + log.WithFields(log.Fields{"count": blockCount}).Info("try fetch next block") + + req := &bp.FetchBlockByCountReq{Count: blockCount} + resp := &bp.FetchBlockResp{} + + if err := s.requestBP(route.MCCFetchBlockByCount.String(), req, resp); err != nil { + // fetch block failed + log.WithError(err).Warning("fetch block failed,wait for next round") + return + } + + // process block + if err := s.processBlock(blockCount, resp.Height, resp.Block); err != nil { + log.WithError(err).Warning("process block failed, try fetch/process again") + return + } + + atomic.AddUint32(&s.nextBlockToFetch, 1) + + // last fetch success, trigger next fetch for fast sync + select { + case s.triggerCh <- struct{}{}: + default: + } +} + +func (s *Service) processBlock(c uint32, h uint32, b *pt.Block) (err error) { + if b == nil { + log.WithField("count", c).Warning("processed nil block") + return ErrNilBlock + } + + log.WithFields(log.Fields{ + "hash": b.BlockHash(), + "parent": b.ParentHash(), + "height": h, + "count": c, + }).Info("process new block") + + if err = s.saveTransactions(c, b.Transactions); err != nil { + return + } + + err = s.saveBlock(c, h, b) + + return +} + +func (s *Service) saveTransactions(c uint32, txs []pi.Transaction) (err error) { + if txs == nil || len(txs) == 0 { + return + } + + for _, t := range txs { + if err = s.saveTransaction(c, t); err != nil { + return + } + } + + return +} + +func (s *Service) saveTransaction(c uint32, tx pi.Transaction) (err error) { + if tx == nil { + return ErrNilTransaction + } + + txHash := tx.GetHash() + + var txKey []byte + + txKey = append(txKey, txKeyPrefix...) + txKey = append(txKey, txHash[:]...) + txData := uint32ToBytes(c) + + err = s.db.Put(txKey, txData, nil) + + return +} + +func (s *Service) saveBlock(c uint32, h uint32, b *pt.Block) (err error) { + if b == nil { + return ErrNilBlock + } + + bHash := b.BlockHash() + + var buf *bytes.Buffer + + if buf, err = utils.EncodeMsgPack(b); err != nil { + return + } + + cBytes := uint32ToBytes(c) + hBytes := uint32ToBytes(h) + + var bKey, bHashKey, bHeightKey []byte + + bKey = append(bKey, blockKeyPrefix...) + bKey = append(bKey, cBytes...) + bKey = append(bKey, hBytes...) + + bHashKey = append(bHashKey, blockHashPrefix...) + bHashKey = append(bHashKey, bHash[:]...) + + bHeightKey = append(bHeightKey, blockHeightPrefix...) + bHeightKey = append(bHeightKey, hBytes...) + + if err = s.db.Put(bKey, buf.Bytes(), nil); err != nil { + return + } + + if err = s.db.Put(bHashKey, cBytes, nil); err != nil { + return + } + + err = s.db.Put(bHeightKey, cBytes, nil) + + return +} + +func (s *Service) requestBP(method string, request interface{}, response interface{}) (err error) { + var bpNodeID proto.NodeID + if bpNodeID, err = rpc.GetCurrentBP(); err != nil { + return + } + return s.caller.CallNode(bpNodeID, method, request, response) +} + +func (s *Service) stop() (err error) { + if !atomic.CompareAndSwapInt32(&s.stopped, 0, 1) { + // stopped + return ErrStopped + } + + log.Info("stop subscription") + + select { + case <-s.stopCh: + default: + close(s.stopCh) + } + + s.wg.Wait() + s.db.Close() + + return +} + +func uint32ToBytes(h uint32) (data []byte) { + data = make([]byte, 4) + binary.BigEndian.PutUint32(data, h) + return +} + +func bytesToUint32(data []byte) uint32 { + return binary.BigEndian.Uint32(data) +} diff --git a/cmd/cql-faucet/api.go b/cmd/cql-faucet/api.go index 4025590c1..631a54598 100644 --- a/cmd/cql-faucet/api.go +++ b/cmd/cql-faucet/api.go @@ -159,7 +159,7 @@ func startAPI(v *Verifier, p *Persistence, listenAddr string) (server *http.Serv go func() { if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { - log.Fatalf("start api server failed: %v", err) + log.WithError(err).Fatal("start api server failed") } }() diff --git a/cmd/cql-faucet/config.go b/cmd/cql-faucet/config.go index 7b2839cb3..7f30ba25b 100644 --- a/cmd/cql-faucet/config.go +++ b/cmd/cql-faucet/config.go @@ -46,19 +46,19 @@ type confWrapper struct { func LoadConfig(configPath string) (config *Config, err error) { var configBytes []byte if configBytes, err = ioutil.ReadFile(configPath); err != nil { - log.Errorf("read config file failed: %v", err) + log.WithError(err).Error("read config file failed") return } configWrapper := &confWrapper{} if err = yaml.Unmarshal(configBytes, configWrapper); err != nil { - log.Errorf("unmarshal config file failed: %v", err) + log.WithError(err).Error("unmarshal config file failed") return } if configWrapper.Faucet == nil { err = ErrInvalidFaucetConfig - log.Errorf("could not read faucet config: %v", err) + log.WithError(err).Error("could not read faucet config") return } @@ -90,7 +90,7 @@ func LoadConfig(configPath string) (config *Config, err error) { } if config.AddressDailyQuota == 0 || config.AccountDailyQuota == 0 { - log.Warningf("AddressDailyQuota & AccountDailyQuota should be valid positive number, 1 assumed") + log.Warning("AddressDailyQuota & AccountDailyQuota should be valid positive number, 1 assumed") if config.AddressDailyQuota == 0 { config.AddressDailyQuota = 1 @@ -103,7 +103,7 @@ func LoadConfig(configPath string) (config *Config, err error) { } if config.VerificationInterval.Nanoseconds() <= 0 { - log.Warningf("a valid VerificationInterval is required, 30 seconds assumed") + log.Warning("a valid VerificationInterval is required, 30 seconds assumed") config.VerificationInterval = 30 * time.Second } diff --git a/cmd/cql-faucet/main.go b/cmd/cql-faucet/main.go index e9064c871..7f580285f 100644 --- a/cmd/cql-faucet/main.go +++ b/cmd/cql-faucet/main.go @@ -19,9 +19,11 @@ package main import ( "context" "flag" + "fmt" "net/http" "os" "os/signal" + "runtime" "time" "github.com/CovenantSQL/CovenantSQL/client" @@ -30,9 +32,13 @@ import ( "golang.org/x/sys/unix" ) +const name = "cql-faucet" + var ( - configFile string - password string + version = "unknown" + configFile string + password string + showVersion bool ) func init() { @@ -40,18 +46,25 @@ func init() { flag.StringVar(&password, "password", "", "master key password for covenantsql") flag.BoolVar(&asymmetric.BypassSignature, "bypassSignature", false, "Disable signature sign and verify, for testing") + flag.BoolVar(&showVersion, "version", false, "Show version information and exit") } func main() { flag.Parse() + if showVersion { + fmt.Printf("%v %v %v %v %v\n", + name, version, runtime.GOOS, runtime.GOARCH, runtime.Version()) + os.Exit(0) + } + flag.Visit(func(f *flag.Flag) { - log.Infof("Args %s : %v", f.Name, f.Value) + log.Infof("Args %#v : %s", f.Name, f.Value) }) // init client var err error if err = client.Init(configFile, []byte(password)); err != nil { - log.Errorf("init covenantsql client failed: %v", err) + log.WithError(err).Error("init covenantsql client failed") os.Exit(-1) return } @@ -60,7 +73,7 @@ func main() { var cfg *Config if cfg, err = LoadConfig(configFile); err != nil { - log.Errorf("read faucet config failed: %v", err) + log.WithError(err).Error("read faucet config failed") os.Exit(-1) return } diff --git a/cmd/cql-faucet/persistence.go b/cmd/cql-faucet/persistence.go index 961ece8e2..91a009030 100644 --- a/cmd/cql-faucet/persistence.go +++ b/cmd/cql-faucet/persistence.go @@ -26,7 +26,6 @@ import ( "github.com/CovenantSQL/CovenantSQL/conf" "github.com/CovenantSQL/CovenantSQL/utils/log" "github.com/satori/go.uuid" - // Load sqlite3 database driver. _ "github.com/CovenantSQL/go-sqlite3-encrypt" ) @@ -169,7 +168,7 @@ func (p *Persistence) checkAccountLimit(platform string, account string) (err er log.WithFields(log.Fields{ "account": account, "platform": platform, - }).Errorf("daily account quota exceeded") + }).Error("daily account quota exceeded") return ErrAccountQuotaExceeded } @@ -197,7 +196,7 @@ func (p *Persistence) checkAddressLimit(address string) (err error) { // quota exceeded log.WithFields(log.Fields{ "address": address, - }).Errorf("daily address quota exceeded") + }).Error("daily address quota exceeded") return ErrAddressQuotaExceeded } diff --git a/cmd/cql-faucet/verifier.go b/cmd/cql-faucet/verifier.go index e3d53503e..aaefa1c30 100644 --- a/cmd/cql-faucet/verifier.go +++ b/cmd/cql-faucet/verifier.go @@ -31,7 +31,6 @@ import ( pt "github.com/CovenantSQL/CovenantSQL/blockproducer/types" "github.com/CovenantSQL/CovenantSQL/crypto" "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" - "github.com/CovenantSQL/CovenantSQL/crypto/hash" "github.com/CovenantSQL/CovenantSQL/crypto/kms" "github.com/CovenantSQL/CovenantSQL/proto" "github.com/CovenantSQL/CovenantSQL/route" @@ -103,14 +102,14 @@ func NewVerifier(cfg *Config, p *Persistence) (v *Verifier, err error) { return } - log.Infof("vault address is: %v", hash.Hash(v.vaultAddress).String()) + log.WithField("vault", v.vaultAddress.String()).Info("init verifier") return } func (v *Verifier) run() { for { - log.Infof("begin verification iteration") + log.Info("begin verification iteration") // fetch records v.verify() @@ -118,7 +117,7 @@ func (v *Verifier) run() { // dispense v.dispense() - log.Infof("end verification iteration") + log.Info("end verification iteration") select { case <-time.After(v.interval): @@ -143,7 +142,7 @@ func (v *Verifier) verify() { defer wg.Done() verified, err := f() if err != nil { - log.Warningf("verify applications failed: %v", err) + log.WithError(err).Warning("verify application failed") ch <- verified } } @@ -218,9 +217,9 @@ func (v *Verifier) dispenseOne(r *applicationRecord) (err error) { // get current balance if err = requestBP(route.MCCQueryAccountStableBalance.String(), balanceReq, balanceRes); err != nil { - log.Warningf("get account balance failed: %v", err) + log.WithError(err).Warning("get account balance failed") } else { - log.Infof("get account balance success, balance: %v", balanceRes.Balance) + log.WithField("balance", balanceRes.Balance).Info("get account balance") } // allocate nonce @@ -230,7 +229,7 @@ func (v *Verifier) dispenseOne(r *applicationRecord) (err error) { if err = requestBP(route.MCCNextAccountNonce.String(), nonceReq, nonceResp); err != nil { // allocate nonce failed - log.Warningf("allocate nonce for transaction failed: %v", err) + log.WithError(err).Warning("allocate nonce for transaction failed") return } @@ -243,7 +242,7 @@ func (v *Verifier) dispenseOne(r *applicationRecord) (err error) { } // log error - log.Warningf("decode transfer target address failed: %v", err) + log.WithError(err).Warning("decode transfer target address failed") // mark failed r.failReason = err.Error() @@ -252,32 +251,31 @@ func (v *Verifier) dispenseOne(r *applicationRecord) (err error) { return } - log.WithFields(log.Fields(r.asMap())).Infof("dispensed application record failed") + log.WithFields(log.Fields(r.asMap())).Info("dispensed application record failed") // skip invalid address faucet application err = nil return } - req := &bp.AddTxTransferReq{} + req := &bp.AddTxReq{} resp := &bp.AddTxResp{} - req.Tx = &pt.Transfer{ - TransferHeader: pt.TransferHeader{ + req.Tx = pt.NewTransfer( + &pt.TransferHeader{ Sender: v.vaultAddress, Receiver: targetAddress, Nonce: nonceResp.Nonce, Amount: uint64(r.tokenAmount), }, - Signee: v.publicKey, - } + ) if err = req.Tx.Sign(v.privateKey); err != nil { // sign failed? return } - if err = requestBP(route.MCCAddTxTransfer.String(), req, resp); err != nil { + if err = requestBP(route.MCCAddTx.String(), req, resp); err != nil { // add transaction failed, try again - log.Warningf("send transaction failed: %v", err) + log.WithError(err).Warning("send transaction failed") return } @@ -290,7 +288,7 @@ func (v *Verifier) dispenseOne(r *applicationRecord) (err error) { return } - log.WithFields(log.Fields(r.asMap())).Infof("dispensed application record") + log.WithFields(log.Fields(r.asMap())).Info("dispensed application record") return } @@ -309,7 +307,7 @@ func (v *Verifier) doVerify(records []*applicationRecord, verifyFunc func(string return } - log.WithFields(log.Fields(r.asMap())).Infof("verified application record") + log.WithFields(log.Fields(r.asMap())).Info("verified application record") verified = r.rowID } diff --git a/cmd/cql-minerd/benchGNTE.sh b/cmd/cql-minerd/benchGNTE.sh new file mode 100755 index 000000000..b26b2d207 --- /dev/null +++ b/cmd/cql-minerd/benchGNTE.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +../../build.sh && \ +go test -bench=^BenchmarkMinerGNTE1$ -benchtime=10s -run ^$ && \ +go test -bench=^BenchmarkMinerGNTE2$ -benchtime=10s -run ^$ && \ +go test -bench=^BenchmarkMinerGNTE3$ -benchtime=10s -run ^$ && \ +go test -bench=^BenchmarkMinerGNTE4$ -benchtime=10s -run ^$ && \ +go test -bench=^BenchmarkMinerGNTE8$ -benchtime=10s -run ^$ diff --git a/cmd/cql-minerd/dbms.go b/cmd/cql-minerd/dbms.go index 8616cf3d6..c2b712304 100644 --- a/cmd/cql-minerd/dbms.go +++ b/cmd/cql-minerd/dbms.go @@ -18,7 +18,6 @@ package main import ( "bytes" - "errors" "io/ioutil" "math/rand" "os" @@ -36,6 +35,7 @@ import ( "github.com/CovenantSQL/CovenantSQL/utils" "github.com/CovenantSQL/CovenantSQL/worker" wt "github.com/CovenantSQL/CovenantSQL/worker/types" + "github.com/pkg/errors" ) var rootHash = hash.Hash{} @@ -53,10 +53,12 @@ func startDBMS(server *rpc.Server) (dbms *worker.DBMS, err error) { } if dbms, err = worker.NewDBMS(cfg); err != nil { + err = errors.Wrap(err, "create new DBMS failed") return } if err = dbms.Init(); err != nil { + err = errors.Wrap(err, "init DBMS failed") return } @@ -68,9 +70,11 @@ func startDBMS(server *rpc.Server) (dbms *worker.DBMS, err error) { var privKey *asymmetric.PrivateKey if pubKey, err = kms.GetLocalPublicKey(); err != nil { + err = errors.Wrap(err, "get local public key failed") return } if privKey, err = kms.GetLocalPrivateKey(); err != nil { + err = errors.Wrap(err, "get local private key failed") return } @@ -102,12 +106,14 @@ func startDBMS(server *rpc.Server) (dbms *worker.DBMS, err error) { } if err = dbPeers.Sign(privKey); err != nil { + err = errors.Wrap(err, "sign peers failed") return } // load genesis block var block *ct.Block if block, err = loadGenesisBlock(testFixture); err != nil { + err = errors.Wrap(err, "load genesis block failed") return } @@ -118,6 +124,7 @@ func startDBMS(server *rpc.Server) (dbms *worker.DBMS, err error) { GenesisBlock: block, } if err = dbms.Create(instance, false); err != nil { + err = errors.Wrap(err, "add new DBMS failed") return } } @@ -134,18 +141,21 @@ func loadGenesisBlock(fixture *conf.MinerDatabaseFixture) (block *ct.Block, err var blockBytes []byte if blockBytes, err = ioutil.ReadFile(fixture.GenesisBlockFile); err == nil { + err = errors.Wrap(err, "read block failed") return } if os.IsNotExist(err) && fixture.AutoGenerateGenesisBlock { // generate if block, err = createRandomBlock(rootHash, true); err != nil { + err = errors.Wrap(err, "create random block failed") return } // encode block var bytesBuffer *bytes.Buffer if bytesBuffer, err = utils.EncodeMsgPack(block); err != nil { + err = errors.Wrap(err, "encode block failed") return } @@ -181,8 +191,6 @@ func createRandomBlock(parent hash.Hash, isGenesis bool) (b *ct.Block, err error ParentHash: parent, Timestamp: time.Now().UTC(), }, - Signee: pub, - Signature: nil, }, Queries: make([]*hash.Hash, rand.Intn(10)+10), } diff --git a/cmd/cql-minerd/integration_test.go b/cmd/cql-minerd/integration_test.go index 86b2a068c..60024948c 100644 --- a/cmd/cql-minerd/integration_test.go +++ b/cmd/cql-minerd/integration_test.go @@ -21,15 +21,17 @@ package main import ( "context" "database/sql" + "io/ioutil" + "math/rand" "os" + "os/exec" "path/filepath" "sync" + "sync/atomic" "syscall" "testing" "time" - "os/exec" - "github.com/CovenantSQL/CovenantSQL/client" "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" "github.com/CovenantSQL/CovenantSQL/utils" @@ -47,27 +49,11 @@ var nodeCmds []*utils.CMD var FJ = filepath.Join -func TestBuild(t *testing.T) { - Convey("build", t, func() { - log.SetLevel(log.DebugLevel) - So(utils.Build(), ShouldBeNil) - }) -} - func startNodes() { ctx := context.Background() // wait for ports to be available var err error - err = utils.WaitForPorts(ctx, "127.0.0.1", []int{ - 2144, - 2145, - 2146, - }, time.Millisecond*200) - - if err != nil { - log.Fatalf("wait for port ready timeout: %v", err) - } err = utils.WaitForPorts(ctx, "127.0.0.1", []int{ 3122, @@ -86,7 +72,7 @@ func startNodes() { []string{"-config", FJ(testWorkingDir, "./integration/node_0/config.yaml"), "-test.coverprofile", FJ(baseDir, "./cmd/cql-minerd/leader.cover.out"), }, - "leader", testWorkingDir, logDir, false, + "leader", testWorkingDir, logDir, true, ); err == nil { nodeCmds = append(nodeCmds, cmd) } else { @@ -115,7 +101,31 @@ func startNodes() { log.Errorf("start node failed: %v", err) } - time.Sleep(time.Second * 3) + ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) + defer cancel() + err = utils.WaitToConnect(ctx, "127.0.0.1", []int{ + 3122, + 3121, + 3120, + }, time.Second) + + if err != nil { + log.Fatalf("wait for port ready timeout: %v", err) + } + + ctx, cancel = context.WithTimeout(context.Background(), time.Second*30) + defer cancel() + err = utils.WaitForPorts(ctx, "127.0.0.1", []int{ + 2144, + 2145, + 2146, + }, time.Millisecond*200) + + if err != nil { + log.Fatalf("wait for port ready timeout: %v", err) + } + + time.Sleep(10 * time.Second) // start 3miners os.RemoveAll(FJ(testWorkingDir, "./integration/node_miner_0/data")) @@ -124,7 +134,7 @@ func startNodes() { []string{"-config", FJ(testWorkingDir, "./integration/node_miner_0/config.yaml"), "-test.coverprofile", FJ(baseDir, "./cmd/cql-minerd/miner0.cover.out"), }, - "miner0", testWorkingDir, logDir, false, + "miner0", testWorkingDir, logDir, true, ); err == nil { nodeCmds = append(nodeCmds, cmd) } else { @@ -230,6 +240,10 @@ func startNodesProfile(bypassSign bool) { FJ(baseDir, "./bin/cql-minerd"), []string{"-config", FJ(testWorkingDir, "./integration/node_miner_0/config.yaml"), "-cpu-profile", FJ(baseDir, "./cmd/cql-minerd/miner0.profile"), + "-traceFile", FJ(baseDir, "./cmd/cql-minerd/miner0.trace"), + "-metricGraphiteServer", "192.168.2.100:2003", + "-profileServer", "0.0.0.0:8080", + "-metricLog", bypassArg, }, "miner0", testWorkingDir, logDir, false, @@ -244,6 +258,10 @@ func startNodesProfile(bypassSign bool) { FJ(baseDir, "./bin/cql-minerd"), []string{"-config", FJ(testWorkingDir, "./integration/node_miner_1/config.yaml"), "-cpu-profile", FJ(baseDir, "./cmd/cql-minerd/miner1.profile"), + "-traceFile", FJ(baseDir, "./cmd/cql-minerd/miner1.trace"), + "-metricGraphiteServer", "192.168.2.100:2003", + "-profileServer", "0.0.0.0:8081", + "-metricLog", bypassArg, }, "miner1", testWorkingDir, logDir, false, @@ -258,6 +276,10 @@ func startNodesProfile(bypassSign bool) { FJ(baseDir, "./bin/cql-minerd"), []string{"-config", FJ(testWorkingDir, "./integration/node_miner_2/config.yaml"), "-cpu-profile", FJ(baseDir, "./cmd/cql-minerd/miner2.profile"), + "-traceFile", FJ(baseDir, "./cmd/cql-minerd/miner2.trace"), + "-metricGraphiteServer", "192.168.2.100:2003", + "-profileServer", "0.0.0.0:8082", + "-metricLog", bypassArg, }, "miner2", testWorkingDir, logDir, false, @@ -294,9 +316,12 @@ func TestFullProcess(t *testing.T) { Convey("test full process", t, func() { startNodes() defer stopNodes() - time.Sleep(5 * time.Second) - var err error + + time.Sleep(10 * time.Second) + + So(err, ShouldBeNil) + err = client.Init(FJ(testWorkingDir, "./integration/node_c/config.yaml"), []byte("")) So(err, ShouldBeNil) @@ -364,7 +389,7 @@ func TestFullProcess(t *testing.T) { }) } -func benchDB(b *testing.B, db *sql.DB) { +func prepareBenchTable(db *sql.DB) { _, err := db.Exec("DROP TABLE IF EXISTS test;") So(err, ShouldBeNil) @@ -376,14 +401,26 @@ func benchDB(b *testing.B, db *sql.DB) { _, err = db.Exec("INSERT INTO test VALUES(?, ?)", 4, 4) So(err, ShouldBeNil) +} + +func benchDB(b *testing.B, db *sql.DB, createDB bool) { + var err error + if createDB { + prepareBenchTable(db) + } + var i int32 var insertedCount int - b.Run("benchmark INSERT", func(b *testing.B) { + + rand.Seed(time.Now().UnixNano()) + start := (rand.Int31() % 100) * 10000 + + b.Run("benchmark Single INSERT", func(b *testing.B) { b.ResetTimer() insertedCount = b.N for i := 0; i < b.N; i++ { _, err = db.Exec("INSERT INTO test ( indexedColumn, nonIndexedColumn ) VALUES"+ - "(?, ?)", i, i, + "(?, ?)", int(start)+i, i, ) if err != nil { b.Fatal(err) @@ -391,6 +428,26 @@ func benchDB(b *testing.B, db *sql.DB) { } }) + if createDB { + prepareBenchTable(db) + } + + b.Run("benchmark Multi INSERT", func(b *testing.B) { + b.ResetTimer() + insertedCount = b.N + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + ii := atomic.AddInt32(&i, 1) + _, err = db.Exec("INSERT INTO test ( indexedColumn, nonIndexedColumn ) VALUES"+ + "(?, ?)", start+ii, ii, + ) + if err != nil { + b.Fatal(err) + } + } + }) + }) + rowCount := db.QueryRow("SELECT COUNT(1) FROM test") var count int err = rowCount.Scan(&count) @@ -402,7 +459,8 @@ func benchDB(b *testing.B, db *sql.DB) { b.Run("benchmark SELECT", func(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { - row := db.QueryRow("SELECT nonIndexedColumn FROM test WHERE indexedColumn = ? LIMIT 1", i%insertedCount) + index := i%insertedCount + int(start) + 1 + row := db.QueryRow("SELECT nonIndexedColumn FROM test WHERE indexedColumn = ? LIMIT 1", index) var result int err = row.Scan(&result) if err != nil || result < 0 { @@ -426,23 +484,56 @@ func benchDB(b *testing.B, db *sql.DB) { func benchMiner(b *testing.B, minerCount uint16, bypassSign bool) { log.Warnf("Benchmark for %d Miners, BypassSignature: %v", minerCount, bypassSign) asymmetric.BypassSignature = bypassSign - startNodesProfile(bypassSign) - time.Sleep(5 * time.Second) + if minerCount > 0 { + startNodesProfile(bypassSign) + utils.WaitToConnect(context.Background(), "127.0.0.1", []int{ + 2144, + 2145, + 2146, + 3122, + 3121, + 3120, + }, 2*time.Second) + time.Sleep(time.Second) + } - var err error - err = client.Init(FJ(testWorkingDir, "./integration/node_c/config.yaml"), []byte("")) + // Create temp directory + testDataDir, err := ioutil.TempDir(testWorkingDir, "covenantsql") + if err != nil { + panic(err) + } + defer os.RemoveAll(testDataDir) + clientConf := FJ(testWorkingDir, "./integration/node_c/config.yaml") + tempConf := FJ(testDataDir, "config.yaml") + clientKey := FJ(testWorkingDir, "./integration/node_c/private.key") + tempKey := FJ(testDataDir, "private.key") + utils.CopyFile(clientConf, tempConf) + utils.CopyFile(clientKey, tempKey) + + err = client.Init(tempConf, []byte("")) So(err, ShouldBeNil) - // create - dsn, err := client.Create(client.ResourceMeta{Node: minerCount}) - So(err, ShouldBeNil) + dsnFile := FJ(baseDir, "./cmd/cql-minerd/.dsn") + var dsn string + if minerCount > 0 { + // create + dsn, err = client.Create(client.ResourceMeta{Node: minerCount}) + So(err, ShouldBeNil) - log.Infof("the created database dsn is %v", dsn) + log.Infof("the created database dsn is %v", dsn) + err = ioutil.WriteFile(dsnFile, []byte(dsn), 0666) + if err != nil { + log.Errorf("write .dsn failed: %v", err) + } + defer os.Remove(dsnFile) + } else { + dsn = os.Getenv("DSN") + } db, err := sql.Open("covenantsql", dsn) So(err, ShouldBeNil) - benchDB(b, db) + benchDB(b, db, minerCount > 0) err = client.Drop(dsn) So(err, ShouldBeNil) @@ -454,17 +545,65 @@ func BenchmarkSQLite(b *testing.B) { os.Remove("./foo.db") defer os.Remove("./foo.db") - db, err := sql.Open("sqlite3", "./foo.db") + db, err := sql.Open("sqlite3", "./foo.db?_journal_mode=WAL&_synchronous=NORMAL&cache=shared") if err != nil { log.Fatal(err) } defer db.Close() Convey("bench SQLite", b, func() { - benchDB(b, db) + benchDB(b, db, true) }) } +func benchGNTEMiner(b *testing.B, minerCount uint16, bypassSign bool) { + log.Warnf("Benchmark GNTE for %d Miners, BypassSignature: %v", minerCount, bypassSign) + asymmetric.BypassSignature = bypassSign + + // Create temp directory + testDataDir, err := ioutil.TempDir(testWorkingDir, "covenantsql") + if err != nil { + panic(err) + } + defer os.RemoveAll(testDataDir) + clientConf := FJ(testWorkingDir, "./GNTE/conf/node_c/config.yaml") + tempConf := FJ(testDataDir, "config.yaml") + clientKey := FJ(testWorkingDir, "./GNTE/conf/node_c/private.key") + tempKey := FJ(testDataDir, "private.key") + utils.CopyFile(clientConf, tempConf) + utils.CopyFile(clientKey, tempKey) + + err = client.Init(tempConf, []byte("")) + So(err, ShouldBeNil) + + dsnFile := FJ(baseDir, "./cmd/cql-minerd/.dsn") + var dsn string + if minerCount > 0 { + // create + dsn, err = client.Create(client.ResourceMeta{Node: minerCount}) + So(err, ShouldBeNil) + + log.Infof("the created database dsn is %v", dsn) + err = ioutil.WriteFile(dsnFile, []byte(dsn), 0666) + if err != nil { + log.Errorf("write .dsn failed: %v", err) + } + defer os.Remove(dsnFile) + } else { + dsn = os.Getenv("DSN") + } + + db, err := sql.Open("covenantsql", dsn) + So(err, ShouldBeNil) + + benchDB(b, db, minerCount > 0) + + err = client.Drop(dsn) + So(err, ShouldBeNil) + time.Sleep(5 * time.Second) + stopNodes() +} + func BenchmarkMinerOneNoSign(b *testing.B) { Convey("bench single node", b, func() { benchMiner(b, 1, true) @@ -500,3 +639,38 @@ func BenchmarkMinerThree(b *testing.B) { benchMiner(b, 3, false) }) } + +func BenchmarkClientOnly(b *testing.B) { + Convey("bench three node", b, func() { + benchMiner(b, 0, false) + }) +} + +func BenchmarkMinerGNTE1(b *testing.B) { + Convey("bench GNTE one node", b, func() { + benchGNTEMiner(b, 1, false) + }) +} +func BenchmarkMinerGNTE2(b *testing.B) { + Convey("bench GNTE two node", b, func() { + benchGNTEMiner(b, 2, false) + }) +} + +func BenchmarkMinerGNTE3(b *testing.B) { + Convey("bench GNTE three node", b, func() { + benchGNTEMiner(b, 3, false) + }) +} + +func BenchmarkMinerGNTE4(b *testing.B) { + Convey("bench GNTE three node", b, func() { + benchGNTEMiner(b, 4, false) + }) +} + +func BenchmarkMinerGNTE8(b *testing.B) { + Convey("bench GNTE three node", b, func() { + benchGNTEMiner(b, 8, false) + }) +} diff --git a/cmd/cql-minerd/main.go b/cmd/cql-minerd/main.go index 893ee6c90..1da8ac364 100644 --- a/cmd/cql-minerd/main.go +++ b/cmd/cql-minerd/main.go @@ -20,11 +20,13 @@ import ( "flag" "fmt" "math/rand" + "net" "net/http" _ "net/http/pprof" "os" "os/signal" "runtime" + "runtime/trace" "syscall" "time" @@ -32,12 +34,13 @@ import ( "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" "github.com/CovenantSQL/CovenantSQL/crypto/kms" "github.com/CovenantSQL/CovenantSQL/metric" - "github.com/CovenantSQL/CovenantSQL/proto" "github.com/CovenantSQL/CovenantSQL/route" "github.com/CovenantSQL/CovenantSQL/rpc" "github.com/CovenantSQL/CovenantSQL/utils" "github.com/CovenantSQL/CovenantSQL/utils/log" "github.com/CovenantSQL/CovenantSQL/worker" + "github.com/cyberdelia/go-metrics-graphite" + "github.com/rcrowley/go-metrics" ) const logo = ` @@ -58,20 +61,21 @@ const logo = ` ` var ( - version = "1" - commit = "unknown" - branch = "unknown" + version = "unknown" ) var ( // config configFile string genKeyPair bool + metricLog bool // profile - cpuProfile string - memProfile string - profileServer string + cpuProfile string + memProfile string + profileServer string + metricGraphite string + traceFile string // other noLogo bool @@ -83,6 +87,7 @@ const desc = `CovenantSQL is a Distributed Database running on BlockChain` func init() { flag.BoolVar(&noLogo, "nologo", false, "Do not print logo") + flag.BoolVar(&metricLog, "metricLog", false, "Print metrics in log") flag.BoolVar(&showVersion, "version", false, "Show version information and exit") flag.BoolVar(&genKeyPair, "genKeyPair", false, "Gen new key pair when no private key found") flag.BoolVar(&asymmetric.BypassSignature, "bypassSignature", false, @@ -93,6 +98,8 @@ func init() { flag.StringVar(&profileServer, "profileServer", "", "Profile server address, default not started") flag.StringVar(&cpuProfile, "cpu-profile", "", "Path to file for CPU profiling information") flag.StringVar(&memProfile, "mem-profile", "", "Path to file for memory profiling information") + flag.StringVar(&metricGraphite, "metricGraphiteServer", "", "Metric graphite server to push metrics") + flag.StringVar(&traceFile, "traceFile", "", "trace profile") flag.Usage = func() { fmt.Fprintf(os.Stderr, "\n%s\n\n", desc) @@ -102,34 +109,41 @@ func init() { } func initLogs() { - log.Infof("%s starting, version %s, commit %s, branch %s", name, version, commit, branch) - log.Infof("%s, target architecture is %s, operating system target is %s", runtime.Version(), runtime.GOARCH, runtime.GOOS) - log.Infof("role: %s", conf.RoleTag) + log.Infof("%#v starting, version %#v", name, version) + log.Infof("%#v, target architecture is %#v, operating system target is %#v", runtime.Version(), runtime.GOARCH, runtime.GOOS) + log.Infof("role: %#v", conf.RoleTag) } func main() { // set random rand.Seed(time.Now().UnixNano()) - log.SetLevel(log.InfoLevel) + log.SetLevel(log.DebugLevel) flag.Parse() + + if showVersion { + fmt.Printf("%v %v %v %v %v\n", + name, version, runtime.GOOS, runtime.GOARCH, runtime.Version()) + os.Exit(0) + } + flag.Visit(func(f *flag.Flag) { - log.Infof("Args %s : %v", f.Name, f.Value) + log.Infof("Args %#v : %s", f.Name, f.Value) }) var err error conf.GConf, err = conf.LoadConfig(configFile) if err != nil { - log.Fatalf("load config from %s failed: %s", configFile, err) + log.WithField("config", configFile).WithError(err).Fatal("load config failed") } if conf.GConf.Miner == nil { - log.Fatalf("miner config does not exists") + log.Fatal("miner config does not exists") } if conf.GConf.Miner.MetricCollectInterval.Seconds() <= 0 { - log.Fatalf("miner metric collect interval is invalid") + log.Fatal("miner metric collect interval is invalid") } if conf.GConf.Miner.MaxReqTimeGap.Seconds() <= 0 { - log.Fatalf("miner request time gap is invalid") + log.Fatal("miner request time gap is invalid") } kms.InitBP() @@ -138,12 +152,6 @@ func main() { // init log initLogs() - if showVersion { - log.Infof("%s %s %s %s %s (commit %s, branch %s)", - name, version, runtime.GOOS, runtime.GOARCH, runtime.Version(), commit, branch) - os.Exit(0) - } - if !noLogo { fmt.Print(logo) } @@ -158,12 +166,12 @@ func main() { // start rpc var server *rpc.Server if server, err = initNode(); err != nil { - log.Fatalf("init node failed: %v", err) + log.WithError(err).Fatal("init node failed") } if conf.GConf.Miner.IsTestMode { // miner test mode enabled - log.Debugf("miner test mode enabled") + log.Debug("miner test mode enabled") } // stop channel for all daemon routines @@ -207,49 +215,10 @@ func main() { } }() - // start block producer pinger - go func() { - var localNodeID proto.NodeID - var err error - - // get local node id - if localNodeID, err = kms.GetLocalNodeID(); err != nil { - return - } - - // get local node info - var localNodeInfo *proto.Node - if localNodeInfo, err = kms.GetNodeInfo(localNodeID); err != nil { - return - } - - log.Debugf("construct local node info: %v", localNodeInfo) - - go func() { - for { - select { - case <-time.After(time.Second): - case <-stopCh: - return - } - - // send ping requests to block producer - bpNodeIDs := route.GetBPs() - - for _, bpNodeID := range bpNodeIDs { - err := rpc.PingBP(localNodeInfo, bpNodeID) - if err == nil { - return - } - } - } - }() - }() - // start dbms var dbms *worker.DBMS if dbms, err = startDBMS(server); err != nil { - log.Fatalf("start dbms failed: %v", err) + log.WithError(err).Fatal("start dbms failed") } defer dbms.Shutdown() @@ -271,6 +240,37 @@ func main() { ) signal.Ignore(syscall.SIGHUP, syscall.SIGTTIN, syscall.SIGTTOU) + if metricLog { + go metrics.Log(metrics.DefaultRegistry, 5*time.Second, log.StandardLogger()) + } + + if metricGraphite != "" { + addr, err := net.ResolveTCPAddr("tcp", metricGraphite) + if err != nil { + log.WithError(err).Error("resolve metric graphite server addr failed") + return + } + minerName := fmt.Sprintf("miner-%s", conf.GConf.ThisNodeID[len(conf.GConf.ThisNodeID)-5:]) + go graphite.Graphite(metrics.DefaultRegistry, 5*time.Second, minerName, addr) + } + + if traceFile != "" { + f, err := os.Create(traceFile) + if err != nil { + log.WithError(err).Fatal("failed to create trace output file") + } + defer func() { + if err := f.Close(); err != nil { + log.WithError(err).Fatal("failed to close trace file") + } + }() + + if err := trace.Start(f); err != nil { + log.WithError(err).Fatal("failed to start trace") + } + defer trace.Stop() + } + <-signalCh log.Info("miner stopped") diff --git a/cmd/cql-minerd/mcprof.sh b/cmd/cql-minerd/mcprof.sh new file mode 100755 index 000000000..4c002b7d8 --- /dev/null +++ b/cmd/cql-minerd/mcprof.sh @@ -0,0 +1,8 @@ +#!/bin/sh -x + +../../cleanupDB.sh +../../build.sh + +(go test -bench=^BenchmarkMinerTwo$ -benchtime=40s -run ^$ &) && \ + (sleep 25 && DSN=`cat .dsn` go test '-bench=^BenchmarkClientOnly$' -benchtime=20s -run '^$') + diff --git a/cmd/cql-minerd/node.go b/cmd/cql-minerd/node.go index ecc0ee6d0..2b7808e0a 100644 --- a/cmd/cql-minerd/node.go +++ b/cmd/cql-minerd/node.go @@ -19,13 +19,18 @@ package main import ( "fmt" "os" + "strings" "syscall" + "time" "github.com/CovenantSQL/CovenantSQL/conf" "github.com/CovenantSQL/CovenantSQL/crypto/kms" + "github.com/CovenantSQL/CovenantSQL/kayak" + "github.com/CovenantSQL/CovenantSQL/proto" "github.com/CovenantSQL/CovenantSQL/route" "github.com/CovenantSQL/CovenantSQL/rpc" "github.com/CovenantSQL/CovenantSQL/utils/log" + "github.com/pkg/errors" "golang.org/x/crypto/ssh/terminal" ) @@ -42,19 +47,24 @@ func initNode() (server *rpc.Server, err error) { } if err = kms.InitLocalKeyPair(conf.GConf.PrivateKeyFile, masterKey); err != nil { - log.Errorf("init local key pair failed: %s", err) + log.WithError(err).Error("init local key pair failed") return } - log.Infof("init routes") + log.Info("init routes") // init kms routing route.InitKMS(conf.GConf.PubKeyStoreFile) + err = registerNodeToBP(15 * time.Second) + if err != nil { + log.Fatalf("register node to BP failed: %v", err) + } + // init server if server, err = createServer( conf.GConf.PrivateKeyFile, conf.GConf.PubKeyStoreFile, masterKey, conf.GConf.ListenAddr); err != nil { - log.Errorf("create server failed: %v", err) + log.WithError(err).Error("create server failed") return } @@ -73,3 +83,53 @@ func createServer(privateKeyPath, pubKeyStorePath string, masterKey []byte, list return } + +func registerNodeToBP(timeout time.Duration) (err error) { + // get local node id + localNodeID, err := kms.GetLocalNodeID() + if err != nil { + err = errors.Wrap(err, "register node to BP") + return + } + + // get local node info + localNodeInfo, err := kms.GetNodeInfo(localNodeID) + if err != nil { + err = errors.Wrap(err, "register node to BP") + return + } + + log.WithField("node", localNodeInfo).Debug("construct local node info") + + pingWaitCh := make(chan proto.NodeID) + bpNodeIDs := route.GetBPs() + for _, bpNodeID := range bpNodeIDs { + go func(ch chan proto.NodeID, id proto.NodeID) { + for { + err := rpc.PingBP(localNodeInfo, id) + if err == nil { + log.Infof("ping BP succeed: %v", localNodeInfo) + ch <- id + return + } + if strings.Contains(err.Error(), kayak.ErrNotLeader.Error()) { + log.Debug("stop ping non leader BP node") + return + } + + log.Warnf("ping BP failed: %v", err) + time.Sleep(3 * time.Second) + } + }(pingWaitCh, bpNodeID) + } + + select { + case bp := <-pingWaitCh: + close(pingWaitCh) + log.WithField("BP", bp).Infof("ping BP succeed") + case <-time.After(timeout): + return errors.New("ping BP timeout") + } + + return +} diff --git a/cmd/cql-minerd/pprof.sh b/cmd/cql-minerd/pprof.sh index 82afc6dea..f59633a46 100755 --- a/cmd/cql-minerd/pprof.sh +++ b/cmd/cql-minerd/pprof.sh @@ -1,7 +1,9 @@ -#!/bin/sh +#!/bin/sh -x + +../../cleanupDB.sh ../../build.sh -go test -bench=^BenchmarkMinerTwo$ -benchtime=60s -run ^$ +go test -bench=^BenchmarkMinerTwo$ -benchtime=15s -run ^$ go tool pprof -text miner1.profile > pprof.txt go tool pprof -svg miner1.profile > tree.svg go-torch -t 180 --width=2400 miner1.profile diff --git a/cmd/cql-mysql-adapter/cursor.go b/cmd/cql-mysql-adapter/cursor.go index 98ab3154c..1622f5537 100644 --- a/cmd/cql-mysql-adapter/cursor.go +++ b/cmd/cql-mysql-adapter/cursor.go @@ -25,26 +25,43 @@ import ( "sync" "github.com/CovenantSQL/CovenantSQL/client" + "github.com/CovenantSQL/CovenantSQL/utils/log" my "github.com/siddontang/go-mysql/mysql" ) var ( - dbIDRegex = regexp.MustCompile("^[a-zA-Z0-9_\\.]+$") - emptyResultQuery = regexp.MustCompile("^(?i)\\s*(?:(?:SELECT\\s+)?@@(?:\\w+\\.)?|SHOW\\s+VARIABLES|SHOW\\s+DATABASES|SET|ROLLBACK).*$") - useDatabaseQuery = regexp.MustCompile("^(?i)\\s*USE\\s+(\\w+)\\s*$") - readQuery = regexp.MustCompile("^(?i)\\s*(?:SELECT|SHOW|DESC)") + dbIDRegex = regexp.MustCompile("^[a-zA-Z0-9_\\.]+$") + specialSelectQuery = regexp.MustCompile("^(?i)SELECT\\s+(DATABASE|USER)\\(\\)\\s*;?\\s*$") + emptyResultQuery = regexp.MustCompile("^(?i)\\s*(?:/\\*.*?\\*/)?\\s*(?:SET|ROLLBACK).*$") + emptyResultWithResultSetQuery = regexp.MustCompile("^(?i)\\s*(?:/\\*.*?\\*/)?\\s*(?:(?:SELECT\\s+)?@@(?:\\w+\\.)?|SHOW\\s+WARNINGS).*$") + showVariablesQuery = regexp.MustCompile("^(?i)\\s*(?:/\\*.*?\\*/)?\\s*SHOW\\s+VARIABLES.*$") + showDatabasesQuery = regexp.MustCompile("^(?i)\\s*(?:/\\*.*?\\*/)?\\s*SHOW\\s+DATABASES.*$") + useDatabaseQuery = regexp.MustCompile("^(?i)\\s*USE\\s+`?(\\w+)`?\\s*$") + readQuery = regexp.MustCompile("^(?i)\\s*(?:SELECT|SHOW|DESC)") + mysqlServerVariables = map[string]interface{}{ + "max_allowed_packet": 255 * 255 * 255, + "auto_increment_increment": 1, + "transaction_isolation": "SERIALIZABLE", + "tx_isolation": "SERIALIZABLE", + "transaction_read_only": 0, + "tx_read_only": 0, + "autocommit": 1, + "character_set_server": "utf8", + "collation_server": "utf8_general_ci", + } ) // Cursor is a mysql connection handler, like a cursor of normal database. type Cursor struct { + server *Server curDBLock sync.Mutex curDB string curDBInstance *sql.DB } // NewCursor returns a new cursor. -func NewCursor() (c *Cursor) { - return &Cursor{} +func NewCursor(s *Server) (c *Cursor) { + return &Cursor{server: s} } func (c *Cursor) buildResultSet(rows *sql.Rows) (r *my.Result, err error) { @@ -117,6 +134,134 @@ func (c *Cursor) detectColumnType(typeStr string) (typeByte uint8) { } } +func (c *Cursor) handleSpecialQuery(query string) (r *my.Result, processed bool, err error) { + if emptyResultQuery.MatchString(query) { // send empty result for variables query/table listing + // return empty result + r = &my.Result{ + Status: 0, + InsertId: 0, + AffectedRows: 0, + Resultset: nil, + } + processed = true + } else if emptyResultWithResultSetQuery.MatchString(query) { // send empty result include non-nil result set + // return empty result with empty result set + var resultSet *my.Resultset + var columns []string + var row []interface{} + + for k, v := range mysqlServerVariables { + if strings.Contains(query, k) { + columns = append(columns, k) + row = append(row, v) + } + } + + if len(columns) == 0 { + columns = append(columns, "_") + } + + if row != nil { + resultSet, _ = my.BuildSimpleTextResultset(columns, [][]interface{}{row}) + } else { + resultSet, _ = my.BuildSimpleTextResultset(columns, [][]interface{}{}) + } + + if resultSet.RowDatas == nil { + // force non-empty result set + resultSet.RowDatas = make([]my.RowData, 0) + } + + r = &my.Result{ + Status: 0, + InsertId: 0, + AffectedRows: 0, + Resultset: resultSet, + } + processed = true + } else if showVariablesQuery.MatchString(query) { // send show variables result with custom config + var rows [][]interface{} + + for k, v := range mysqlServerVariables { + rows = append(rows, []interface{}{k, v}) + } + + resultSet, _ := my.BuildSimpleTextResultset([]string{"Variable_name", "Value"}, rows) + r = &my.Result{ + Status: 0, + InsertId: 0, + AffectedRows: 0, + Resultset: resultSet, + } + processed = true + } else if showDatabasesQuery.MatchString(query) { // send show databases result + // return result including current database + var curDBStr string + c.curDBLock.Lock() + curDBStr = c.curDB + c.curDBLock.Unlock() + + var resultSet *my.Resultset + + if curDBStr != "" { + resultSet, _ = my.BuildSimpleTextResultset([]string{"Database"}, [][]interface{}{{curDBStr}}) + } else { + resultSet, _ = my.BuildSimpleTextResultset([]string{"Database"}, nil) + } + + r = &my.Result{ + Status: 0, + InsertId: 0, + AffectedRows: 0, + Resultset: resultSet, + } + processed = true + } else if matches := useDatabaseQuery.FindStringSubmatch(query); len(matches) > 1 { // use database query, same logic as COM_INIT_DB + dbID := matches[1] + + processed = true + if err = c.UseDB(dbID); err == nil { + r = &my.Result{ + Status: 0, + InsertId: 0, + AffectedRows: 0, + Resultset: nil, + } + } + } else if matches := specialSelectQuery.FindStringSubmatch(query); len(matches) > 1 { + // special select database + // for libmysql trivial implementations + // https://github.com/mysql/mysql-server/blob/4f1d7cf5fcb11a3f84cff27e37100d7295e7d5ca/client/mysql.cc#L4266 + + var resultSet *my.Resultset + + switch strings.ToUpper(matches[1]) { + case "DATABASE": + c.curDBLock.Lock() + resultSet, _ = my.BuildSimpleTextResultset( + []string{"DATABASE()"}, + [][]interface{}{{c.curDB}}, + ) + c.curDBLock.Unlock() + case "USER": + resultSet, _ = my.BuildSimpleTextResultset( + []string{"USER()"}, + [][]interface{}{{c.server.mysqlUser}}, + ) + } + + r = &my.Result{ + Status: 0, + InsertId: 0, + AffectedRows: 0, + Resultset: resultSet, + } + processed = true + } + + return +} + // UseDB handle COM_INIT_DB command, you can check whether the dbName is valid, or other. func (c *Cursor) UseDB(dbName string) (err error) { c.curDBLock.Lock() @@ -147,36 +292,17 @@ func (c *Cursor) UseDB(dbName string) (err error) { // HandleQuery handle COM_QUERY comamnd, like SELECT, INSERT, UPDATE, etc... // if Result has a Resultset (SELECT, SHOW, etc...), we will send this as the repsonse, otherwise, we will send Result. func (c *Cursor) HandleQuery(query string) (r *my.Result, err error) { - var conn *sql.DB + var processed bool - if conn, err = c.ensureDatabase(); err != nil { - return - } + log.WithField("query", query).Info("received query") - // send empty result for variables query/table listing - if emptyResultQuery.MatchString(query) { - // return empty result - return &my.Result{ - Status: 0, - InsertId: 0, - AffectedRows: 0, - Resultset: nil, - }, nil + if r, processed, err = c.handleSpecialQuery(query); processed { + return } - // use database query, same logic as COM_INIT_DB - if matches := useDatabaseQuery.FindStringSubmatch(query); len(matches) > 1 { - dbID := matches[1] - - if err = c.UseDB(dbID); err == nil { - r = &my.Result{ - Status: 0, - InsertId: 0, - AffectedRows: 0, - Resultset: nil, - } - } + var conn *sql.DB + if conn, err = c.ensureDatabase(); err != nil { return } diff --git a/cmd/cql-mysql-adapter/main.go b/cmd/cql-mysql-adapter/main.go index bb6668e09..ada223bd1 100644 --- a/cmd/cql-mysql-adapter/main.go +++ b/cmd/cql-mysql-adapter/main.go @@ -18,8 +18,10 @@ package main import ( "flag" + "fmt" "os" "os/signal" + "runtime" "github.com/CovenantSQL/CovenantSQL/client" "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" @@ -27,13 +29,17 @@ import ( "golang.org/x/sys/unix" ) +const name = "cql-mysql-adapter" + var ( + version = "unknown" configFile string password string listenAddr string mysqlUser string mysqlPassword string + showVersion bool ) func init() { @@ -41,6 +47,7 @@ func init() { flag.StringVar(&password, "password", "", "master key password") flag.BoolVar(&asymmetric.BypassSignature, "bypassSignature", false, "Disable signature sign and verify, for testing") + flag.BoolVar(&showVersion, "version", false, "Show version information and exit") flag.StringVar(&listenAddr, "listen", "127.0.0.1:4664", "listen address for mysql adapter") flag.StringVar(&mysqlUser, "mysql-user", "root", "mysql user for adapter server") @@ -49,13 +56,19 @@ func init() { func main() { flag.Parse() + if showVersion { + fmt.Printf("%v %v %v %v %v\n", + name, version, runtime.GOOS, runtime.GOARCH, runtime.Version()) + os.Exit(0) + } + flag.Visit(func(f *flag.Flag) { - log.Infof("Args %s : %v", f.Name, f.Value) + log.Infof("Args %#v : %s", f.Name, f.Value) }) // init client if err := client.Init(configFile, []byte(password)); err != nil { - log.Fatalf("init covenantsql client failed: %v", err) + log.WithError(err).Fatal("init covenantsql client failed") return } @@ -64,17 +77,17 @@ func main() { server, err := NewServer(listenAddr, mysqlUser, mysqlPassword) if err != nil { - log.Fatalf("init server failed: %v", err) + log.WithError(err).Fatal("init server failed") return } go server.Serve() - log.Infof("start mysql adapter") + log.Info("start mysql adapter") <-stop server.Shutdown() - log.Infof("stopped mysql adapter") + log.Info("stopped mysql adapter") } diff --git a/cmd/cql-mysql-adapter/server.go b/cmd/cql-mysql-adapter/server.go index c6728f7c6..db58a97d7 100644 --- a/cmd/cql-mysql-adapter/server.go +++ b/cmd/cql-mysql-adapter/server.go @@ -59,10 +59,10 @@ func (s *Server) Serve() { } func (s *Server) handleConn(conn net.Conn) { - h, err := mys.NewConn(conn, s.mysqlUser, s.mysqlPassword, NewCursor()) + h, err := mys.NewConn(conn, s.mysqlUser, s.mysqlPassword, NewCursor(s)) if err != nil { - log.Errorf("process connection failed: %v", err) + log.WithError(err).Error("process connection failed") return } diff --git a/cmd/cql-observer/api.go b/cmd/cql-observer/api.go index 26c2dc998..2d644eed1 100644 --- a/cmd/cql-observer/api.go +++ b/cmd/cql-observer/api.go @@ -425,7 +425,7 @@ func startAPI(service *Service, listenAddr string) (server *http.Server, err err go func() { if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { - log.Fatalf("start api server failed: %v", err) + log.WithError(err).Fatal("start api server failed") } }() diff --git a/cmd/cql-observer/config.go b/cmd/cql-observer/config.go index d304933b4..4b68f44c4 100644 --- a/cmd/cql-observer/config.go +++ b/cmd/cql-observer/config.go @@ -44,11 +44,11 @@ func loadConfig(path string) (config *Config, err error) { wrapper = &configWrapper{} ) if content, err = ioutil.ReadFile(path); err != nil { - log.Errorf("Failed to read config file: %v", err) + log.WithError(err).Error("Failed to read config file") return } if err = yaml.Unmarshal(content, wrapper); err != nil { - log.Errorf("Failed to unmarshal config file: %v", err) + log.WithError(err).Error("Failed to unmarshal config file") return } config = wrapper.Observer diff --git a/cmd/cql-observer/main.go b/cmd/cql-observer/main.go index fdf3efdc2..4fb15e7be 100644 --- a/cmd/cql-observer/main.go +++ b/cmd/cql-observer/main.go @@ -18,12 +18,13 @@ package main import ( "flag" + "fmt" "math/rand" - "time" - "os" "os/signal" + "runtime" "syscall" + "time" "github.com/CovenantSQL/CovenantSQL/conf" "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" @@ -33,23 +34,23 @@ import ( "github.com/CovenantSQL/CovenantSQL/utils/log" ) +const name = "cql-observer" + var ( version = "unknown" - commit = "unknown" - branch = "unknown" -) -var ( // config configFile string dbID string listenAddr string resetPosition string + showVersion bool ) func init() { - flag.StringVar(&configFile, "config", "./config.yaml", "Config file path") + flag.StringVar(&configFile, "config", "./config.yaml", "config file path") flag.StringVar(&dbID, "database", "", "database to listen for observation") + flag.BoolVar(&showVersion, "version", false, "Show version information and exit") flag.BoolVar(&asymmetric.BypassSignature, "bypassSignature", false, "Disable signature sign and verify, for testing") flag.StringVar(&resetPosition, "reset", "", "reset subscribe position") @@ -61,14 +62,20 @@ func main() { rand.Seed(time.Now().UnixNano()) log.SetLevel(log.DebugLevel) flag.Parse() + if showVersion { + fmt.Printf("%v %v %v %v %v\n", + name, version, runtime.GOOS, runtime.GOARCH, runtime.Version()) + os.Exit(0) + } + flag.Visit(func(f *flag.Flag) { - log.Infof("Args %s : %v", f.Name, f.Value) + log.Infof("Args %#v : %s", f.Name, f.Value) }) var err error conf.GConf, err = conf.LoadConfig(configFile) if err != nil { - log.Fatalf("load config from %s failed: %s", configFile, err) + log.WithField("config", configFile).WithError(err).Fatal("load config failed") } kms.InitBP() @@ -76,35 +83,35 @@ func main() { // start rpc var server *rpc.Server if server, err = initNode(); err != nil { - log.Fatalf("init node failed: %v", err) + log.WithError(err).Fatal("init node failed") } // start service var service *Service if service, err = startService(server); err != nil { - log.Fatalf("start observation failed: %v", err) + log.WithError(err).Fatal("start observation failed") } // start explorer api httpServer, err := startAPI(service, listenAddr) if err != nil { - log.Fatalf("start explorer api failed: %v", err) + log.WithError(err).Fatal("start explorer api failed") } // register node if err = registerNode(); err != nil { - log.Fatalf("register node failed: %v", err) + log.WithError(err).Fatal("register node failed") } // start subscription var cfg *Config if cfg, err = loadConfig(configFile); err != nil { - log.Fatalf("failed to load config: %v", err) + log.WithError(err).Fatal("failed to load config") } if cfg != nil { for _, v := range cfg.Databases { if err = service.subscribe(proto.DatabaseID(v.ID), v.Position); err != nil { - log.Fatalf("init subscription failed: %v", err) + log.WithError(err).Fatal("init subscription failed") } } } @@ -112,7 +119,7 @@ func main() { // without changing the config. if dbID != "" { if err = service.subscribe(proto.DatabaseID(dbID), resetPosition); err != nil { - log.Fatalf("init subscription failed: %v", err) + log.WithError(err).Fatal("init subscription failed") } } @@ -128,12 +135,12 @@ func main() { // stop explorer api if err = stopAPI(httpServer); err != nil { - log.Fatalf("stop explorer api failed: %v", err) + log.WithError(err).Fatal("stop explorer api failed") } // stop subscriptions if err = stopService(service, server); err != nil { - log.Fatalf("stop service failed: %v", err) + log.WithError(err).Fatal("stop service failed") } log.Info("observer stopped") diff --git a/cmd/cql-observer/node.go b/cmd/cql-observer/node.go index 2c687e619..49bb83513 100644 --- a/cmd/cql-observer/node.go +++ b/cmd/cql-observer/node.go @@ -41,11 +41,11 @@ func initNode() (server *rpc.Server, err error) { } if err = kms.InitLocalKeyPair(conf.GConf.PrivateKeyFile, masterKey); err != nil { - log.Errorf("init local key pair failed: %v", err) + log.WithError(err).Error("init local key pair failed") return } - log.Infof("init routes") + log.Info("init routes") // init kms routing route.InitKMS(conf.GConf.PubKeyStoreFile) @@ -53,7 +53,7 @@ func initNode() (server *rpc.Server, err error) { // init server if server, err = createServer( conf.GConf.PrivateKeyFile, conf.GConf.PubKeyStoreFile, masterKey, conf.GConf.ListenAddr); err != nil { - log.Errorf("create server failed: %v", err) + log.WithError(err).Error("create server failed") return } diff --git a/cmd/cql-observer/observation_test.go b/cmd/cql-observer/observation_test.go index 5ed3cb07e..a0be43d42 100644 --- a/cmd/cql-observer/observation_test.go +++ b/cmd/cql-observer/observation_test.go @@ -52,30 +52,14 @@ var nodeCmds []*utils.CMD var FJ = filepath.Join -func TestBuild(t *testing.T) { - Convey("build", t, func() { - log.SetLevel(log.DebugLevel) - So(utils.Build(), ShouldBeNil) - }) -} - func startNodes() { // wait for ports to be available var err error ctx := context.Background() err = utils.WaitForPorts(ctx, "127.0.0.1", []int{ - 2144, - 2145, - 2146, - }, time.Millisecond*200) - - if err != nil { - log.Fatalf("wait for port ready timeout: %v", err) - } - err = utils.WaitForPorts(ctx, "127.0.0.1", []int{ - 3122, - 3121, - 3120, + 4120, + 4121, + 4122, }, time.Millisecond*200) if err != nil { @@ -89,7 +73,7 @@ func startNodes() { []string{"-config", FJ(testWorkingDir, "./observation/node_0/config.yaml"), "-test.coverprofile", FJ(baseDir, "./cmd/cql-observer/leader.cover.out"), }, - "leader", testWorkingDir, logDir, false, + "leader", testWorkingDir, logDir, true, ); err == nil { nodeCmds = append(nodeCmds, cmd) } else { @@ -118,8 +102,29 @@ func startNodes() { log.Errorf("start node failed: %v", err) } - time.Sleep(time.Second * 3) + ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) + defer cancel() + err = utils.WaitToConnect(ctx, "127.0.0.1", []int{ + 4120, + 4121, + 4122, + }, time.Second) + if err != nil { + log.Fatalf("wait for port ready timeout: %v", err) + } + + ctx, cancel = context.WithTimeout(context.Background(), time.Second*30) + defer cancel() + err = utils.WaitForPorts(ctx, "127.0.0.1", []int{ + 4144, + 4145, + 4146, + }, time.Millisecond*200) + if err != nil { + log.Fatalf("wait for port ready timeout: %v", err) + } + time.Sleep(10 * time.Second) // start 3miners os.RemoveAll(FJ(testWorkingDir, "./observation/node_miner_0/data")) if cmd, err = utils.RunCommandNB( @@ -127,7 +132,7 @@ func startNodes() { []string{"-config", FJ(testWorkingDir, "./observation/node_miner_0/config.yaml"), "-test.coverprofile", FJ(baseDir, "./cmd/cql-observer/miner0.cover.out"), }, - "miner0", testWorkingDir, logDir, false, + "miner0", testWorkingDir, logDir, true, ); err == nil { nodeCmds = append(nodeCmds, cmd) } else { @@ -140,7 +145,7 @@ func startNodes() { []string{"-config", FJ(testWorkingDir, "./observation/node_miner_1/config.yaml"), "-test.coverprofile", FJ(baseDir, "./cmd/cql-observer/miner1.cover.out"), }, - "miner1", testWorkingDir, logDir, false, + "miner1", testWorkingDir, logDir, true, ); err == nil { nodeCmds = append(nodeCmds, cmd) } else { @@ -153,7 +158,7 @@ func startNodes() { []string{"-config", FJ(testWorkingDir, "./observation/node_miner_2/config.yaml"), "-test.coverprofile", FJ(baseDir, "./cmd/cql-observer/miner2.cover.out"), }, - "miner2", testWorkingDir, logDir, false, + "miner2", testWorkingDir, logDir, true, ); err == nil { nodeCmds = append(nodeCmds, cmd) } else { @@ -221,11 +226,12 @@ func TestFullProcess(t *testing.T) { log.SetLevel(log.DebugLevel) Convey("test full process", t, func() { + var err error startNodes() defer stopNodes() + time.Sleep(10 * time.Second) - var err error err = client.Init(FJ(testWorkingDir, "./observation/node_c/config.yaml"), []byte("")) So(err, ShouldBeNil) diff --git a/cmd/cql-observer/observer.go b/cmd/cql-observer/observer.go index a6913fb8a..ff7ed1b22 100644 --- a/cmd/cql-observer/observer.go +++ b/cmd/cql-observer/observer.go @@ -20,8 +20,8 @@ import ( "github.com/CovenantSQL/CovenantSQL/conf" "github.com/CovenantSQL/CovenantSQL/crypto/kms" "github.com/CovenantSQL/CovenantSQL/proto" + "github.com/CovenantSQL/CovenantSQL/route" "github.com/CovenantSQL/CovenantSQL/rpc" - ct "github.com/CovenantSQL/CovenantSQL/sqlchain/types" ) func registerNode() (err error) { @@ -48,7 +48,7 @@ func startService(server *rpc.Server) (service *Service, err error) { return } - if err = server.RegisterService(ct.ObserverService, service); err != nil { + if err = server.RegisterService(route.ObserverRPCName, service); err != nil { return } diff --git a/cmd/cql-observer/service.go b/cmd/cql-observer/service.go index e143c4305..53b4b9720 100644 --- a/cmd/cql-observer/service.go +++ b/cmd/cql-observer/service.go @@ -241,10 +241,15 @@ func (s *Service) AdviseNewBlock(req *sqlchain.MuxAdviseNewBlockReq, resp *sqlch } if req.Block == nil { - log.Infof("received empty block from node %v", req.GetNodeID().String()) + log.WithField("node", req.GetNodeID().String()).Warning("received empty block") return } + log.WithFields(log.Fields{ + "node": req.GetNodeID().String(), + "block": req.Block.BlockHash(), + }).Debug("received block") + return s.addBlock(req.DatabaseID, req.Count, req.Block) } @@ -256,7 +261,7 @@ func (s *Service) AdviseAckedQuery(req *sqlchain.MuxAdviseAckedQueryReq, resp *s } if req.Query == nil { - log.Infof("received empty acked query from node %v", req.GetNodeID().String()) + log.WithField("node", req.GetNodeID().String()).Info("received empty acked query") return } @@ -278,7 +283,7 @@ func (s *Service) start() (err error) { for _, dbID := range dbs { if err = s.startSubscribe(dbID); err != nil { - log.Warningf("start subscription failed on database %v: %v", dbID, err) + log.WithField("db", dbID).WithError(err).Warning("start subscription failed") } } @@ -295,7 +300,7 @@ func (s *Service) startSubscribe(dbID proto.DatabaseID) (err error) { defer s.lock.Unlock() // start subscribe on first node of each sqlchain server peers - log.Infof("start subscribing transactions from database %v", dbID) + log.WithField("db", dbID).Info("start subscribing transactions") instance, err := s.getUpstream(dbID) if err != nil { @@ -318,7 +323,10 @@ func (s *Service) startSubscribe(dbID proto.DatabaseID) (err error) { } func (s *Service) addAckedQuery(dbID proto.DatabaseID, ack *wt.SignedAckHeader) (err error) { - log.Debugf("add ack query %v: %v", dbID, ack.HeaderHash.String()) + log.WithFields(log.Fields{ + "ack": ack.HeaderHash.String(), + "db": dbID, + }).Debug("add ack query") if atomic.LoadInt32(&s.stopped) == 1 { // stopped @@ -347,8 +355,11 @@ func (s *Service) addAckedQuery(dbID proto.DatabaseID, ack *wt.SignedAckHeader) key := offsetToBytes(req.LogOffset) key = append(key, resp.Request.Header.HeaderHash.CloneBytes()...) - log.Debugf("add write request, offset: %v, %v, %v", - req.LogOffset, resp.Request.Header.HeaderHash.String(), resp.Request.Payload.Queries) + log.WithFields(log.Fields{ + "offset": req.LogOffset, + "reqHash": resp.Request.Header.HeaderHash.String(), + "reqQueries": resp.Request.Payload.Queries, + }).Debug("add write request") var reqBytes *bytes.Buffer if reqBytes, err = utils.EncodeMsgPack(resp.Request); err != nil { @@ -434,7 +445,7 @@ func (s *Service) addBlock(dbID proto.DatabaseID, count int32, b *ct.Block) (err } func (s *Service) stop() (err error) { - if atomic.LoadInt32(&s.stopped) == 1 { + if !atomic.CompareAndSwapInt32(&s.stopped, 0, 1) { // stopped return ErrStopped } @@ -442,10 +453,8 @@ func (s *Service) stop() (err error) { s.lock.Lock() defer s.lock.Unlock() - atomic.StoreInt32(&s.stopped, 1) - // send cancel subscription to all databases - log.Infof("stop subscribing all databases") + log.Info("stop subscribing all databases") for dbID := range s.subscription { // send cancel subscription rpc @@ -455,7 +464,7 @@ func (s *Service) stop() (err error) { if err = s.minerRequest(dbID, route.SQLCCancelSubscription.String(), req, resp); err != nil { // cancel subscription failed - log.Warningf("cancel subscription for database %v failed: %v", dbID, err) + log.WithField("db", dbID).WithError(err).Warning("cancel subscription") } } @@ -475,7 +484,7 @@ func (s *Service) minerRequest(dbID proto.DatabaseID, method string, request int } func (s *Service) getUpstream(dbID proto.DatabaseID) (instance *wt.ServiceInstance, err error) { - log.Infof("get peers info for database: %v", dbID) + log.WithField("db", dbID).Info("get peers info for database") if iInstance, exists := s.upstreamServers.Load(dbID); exists { instance = iInstance.(*wt.ServiceInstance) @@ -492,14 +501,8 @@ func (s *Service) getUpstream(dbID proto.DatabaseID) (instance *wt.ServiceInstan return } - pubKey, err := kms.GetLocalPublicKey() - if err != nil { - return - } - req := &bp.GetDatabaseRequest{} req.Header.DatabaseID = dbID - req.Header.Signee = pubKey if err = req.Sign(privateKey); err != nil { return } diff --git a/cmd/cql-utils/adapterconfgen.go b/cmd/cql-utils/adapterconfgen.go new file mode 100644 index 000000000..bcbad9273 --- /dev/null +++ b/cmd/cql-utils/adapterconfgen.go @@ -0,0 +1,278 @@ +/* + * Copyright 2018 The CovenantSQL Authors. + * + * 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. + */ + +package main + +import ( + "bufio" + "fmt" + "io/ioutil" + "os" + "strings" + + "github.com/CovenantSQL/CovenantSQL/utils/log" + "gopkg.in/yaml.v2" +) + +type adapterConfig struct { + ListenAddr string `yaml:"ListenAddr"` + CertificatePath string `yaml:"CertificatePath"` + PrivateKeyPath string `yaml:"PrivateKeyPath"` + VerifyCertificate bool `yaml:"VerifyCertificate"` + ClientCAPath string `yaml:"ClientCAPath"` + AdminCerts []string `yaml:"AdminCerts"` + WriteCerts []string `yaml:"WriteCerts"` + StorageDriver string `yaml:"StorageDriver"` + StorageRoot string `yaml:"StorageRoot"` +} + +var ( + defaultAdapterConfig = &adapterConfig{ + ListenAddr: "0.0.0.0:4661", + CertificatePath: "server.pem", + PrivateKeyPath: "server-key.pem", + VerifyCertificate: false, + ClientCAPath: "", + AdminCerts: []string{}, + WriteCerts: []string{}, + StorageDriver: "covenantsql", + StorageRoot: "", + } +) + +func (c *adapterConfig) readListenAddr() { + newAddr := readDataFromStdin("ListenAddr (default: %v): ", c.ListenAddr) + if newAddr != "" { + c.ListenAddr = newAddr + } +} + +func (c *adapterConfig) readCertificatePath() { + newCertPath := readDataFromStdin("CertificatePath (default: %v): ", c.CertificatePath) + if newCertPath != "" { + c.CertificatePath = newCertPath + } +} + +func (c *adapterConfig) readPrivateKeyPath() { + newPrivateKeyPath := readDataFromStdin("PrivateKeyPath (default: %v): ", c.PrivateKeyPath) + if newPrivateKeyPath != "" { + c.PrivateKeyPath = newPrivateKeyPath + } +} + +func (c *adapterConfig) readVerifyCertificate() bool { + shouldVerifyCertificate := readDataFromStdin( + "VerifyCertificate (default: %v) (y/n): ", c.VerifyCertificate) + if shouldVerifyCertificate != "" { + switch shouldVerifyCertificate { + case "y": + fallthrough + case "Y": + c.VerifyCertificate = true + case "N": + fallthrough + case "n": + c.VerifyCertificate = false + } + } + + return c.VerifyCertificate +} + +func (c *adapterConfig) readClientCAPath() { + newClientCAPath := readDataFromStdin("ClientCAPath (default: %v)", c.ClientCAPath) + if newClientCAPath != "" { + c.ClientCAPath = newClientCAPath + } +} + +func (c *adapterConfig) readAdminCerts() { + var newCerts []string + + for { + record := readDataFromStdin("AdminCerts: ") + + if record == "" { + break + } + + newCerts = append(newCerts, record) + } + + c.AdminCerts = newCerts +} + +func (c *adapterConfig) readWriteCerts() { + var newCerts []string + + for { + record := readDataFromStdin("WriteCerts: ") + + if record == "" { + break + } + + newCerts = append(newCerts, record) + } + + c.WriteCerts = newCerts +} + +func (c *adapterConfig) readStorageDriver() { + newStorageDriver := readDataFromStdin("StorageDriver (default: %v)", c.StorageDriver) + if newStorageDriver != "" { + c.StorageDriver = newStorageDriver + } +} + +func (c *adapterConfig) readStorageRoot() { + newStorageRoot := readDataFromStdin("StorageRoot (default: %v)", c.StorageRoot) + if newStorageRoot != "" { + c.StorageRoot = newStorageRoot + } +} + +func (c *adapterConfig) loadFromExistingConfig(rawConfig yaml.MapSlice) { + if rawConfig == nil { + return + } + + // find adapter config in map slice + var originalConfig interface{} + + for _, item := range rawConfig { + if keyStr, ok := item.Key.(string); ok && keyStr == "Adapter" { + originalConfig = item.Value + } + } + + if originalConfig == nil { + return + } + + // fill values to config structure + var configBytes []byte + var err error + + if configBytes, err = yaml.Marshal(originalConfig); err != nil { + log.WithError(err).Warning("load previous adapter config failed") + return + } + + if err = yaml.Unmarshal(configBytes, c); err != nil { + log.WithError(err).Warning("load previous adapter config failed") + return + } + + return +} + +func (c *adapterConfig) writeToRawConfig(rawConfig yaml.MapSlice) yaml.MapSlice { + if rawConfig == nil { + return rawConfig + } + + // find adapter config in map slice + for i, item := range rawConfig { + if keyStr, ok := item.Key.(string); ok && keyStr == "Adapter" { + rawConfig[i].Value = c + return rawConfig + } + } + + // not found + rawConfig = append(rawConfig, yaml.MapItem{ + Key: "Adapter", + Value: c, + }) + + return rawConfig +} + +func (c *adapterConfig) readAllConfig() { + c.readListenAddr() + c.readCertificatePath() + c.readPrivateKeyPath() + + if c.readVerifyCertificate() { + c.readClientCAPath() + c.readAdminCerts() + c.readWriteCerts() + } + + c.readStorageDriver() + c.readStorageRoot() +} + +func readDataFromStdin(prompt string, values ...interface{}) (s string) { + reader := bufio.NewReader(os.Stdin) + fmt.Printf(prompt, values...) + s, _ = reader.ReadString('\n') + s = strings.TrimSpace(s) + return +} + +func runAdapterConfGen() { + if configFile == "" { + log.Error("config file path is required for adapterconfgen tool") + os.Exit(1) + } + + var err error + var configBytes []byte + if configBytes, err = ioutil.ReadFile(configFile); err != nil { + log.WithError(err).Error("an existing config file is required for adapterconfggen") + os.Exit(1) + } + + // load config + var rawConfig yaml.MapSlice + if err = yaml.Unmarshal(configBytes, &rawConfig); err != nil { + log.WithError(err).Error("a valid config file is required for adapterconfgen") + os.Exit(1) + } + + if rawConfig == nil { + log.WithError(err).Error("a confgen generated config is required for adapterconfgen") + os.Exit(1) + } + + // backup config + bakConfigFile := configFile + ".bak" + if err = ioutil.WriteFile(bakConfigFile, configBytes, 0600); err != nil { + log.WithError(err).Error("backup config file failed") + os.Exit(1) + } + + defaultAdapterConfig.loadFromExistingConfig(rawConfig) + defaultAdapterConfig.readAllConfig() + rawConfig = defaultAdapterConfig.writeToRawConfig(rawConfig) + + if configBytes, err = yaml.Marshal(rawConfig); err != nil { + log.WithError(err).Error("marshal config failed") + os.Exit(1) + } + + if err = ioutil.WriteFile(configFile, configBytes, 0600); err != nil { + log.WithError(err).Error("write config to file failed") + os.Exit(1) + } + + log.Info("adapter config generated") + + return +} diff --git a/cmd/cql-utils/addrgen.go b/cmd/cql-utils/addrgen.go new file mode 100644 index 000000000..d0df440cf --- /dev/null +++ b/cmd/cql-utils/addrgen.go @@ -0,0 +1,72 @@ +/* + * Copyright 2018 The CovenantSQL Authors. + * + * 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. + */ + +package main + +import ( + "encoding/hex" + "flag" + "fmt" + "os" + + "github.com/CovenantSQL/CovenantSQL/crypto" + "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" + "github.com/CovenantSQL/CovenantSQL/crypto/kms" + "github.com/CovenantSQL/CovenantSQL/utils/log" +) + +var ( + isTestNetAddr bool +) + +func init() { + flag.BoolVar(&isTestNetAddr, "addrgen", false, "addrgen generates a testnet address from your key pair") +} + +func runAddrgen() { + var publicKey *asymmetric.PublicKey + + if publicKeyHex != "" { + publicKeyBytes, err := hex.DecodeString(publicKeyHex) + if err != nil { + log.WithError(err).Fatal("error converting hex") + } + publicKey, err = asymmetric.ParsePubKey(publicKeyBytes) + if err != nil { + log.WithError(err).Fatal("error converting public key") + } + } else if privateKeyFile != "" { + masterKey, err := readMasterKey() + if err != nil { + fmt.Printf("read master key failed: %v\n", err) + os.Exit(1) + } + privateKey, err := kms.LoadPrivateKey(privateKeyFile, []byte(masterKey)) + if err != nil { + log.WithError(err).Fatal("load private key file failed") + } + publicKey = privateKey.PubKey() + } else { + fmt.Println("privateKey path or publicKey hex is required for addrgen") + os.Exit(1) + } + + addr, err := crypto.PubKey2Addr(publicKey, crypto.TestNet) + if err != nil { + log.WithError(err).Fatal("unexpected error") + } + fmt.Printf("wallet address: %s\n", addr) +} diff --git a/cmd/cql-utils/confgen.go b/cmd/cql-utils/confgen.go new file mode 100644 index 000000000..4437f4626 --- /dev/null +++ b/cmd/cql-utils/confgen.go @@ -0,0 +1,167 @@ +/* + * Copyright 2018 The CovenantSQL Authors. + * + * 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. + */ + +package main + +import ( + "bufio" + "encoding/hex" + "flag" + "fmt" + "io/ioutil" + "os" + "path" + "strings" + + "github.com/CovenantSQL/CovenantSQL/utils/log" +) + +var ( + workingRoot string +) + +func init() { + flag.StringVar(&workingRoot, "root", "conf", "confgen root is the working root directory containing all auto-generating keys and certifications") +} + +func runConfgen() { + if workingRoot == "" { + log.Error("root directory is required for confgen") + os.Exit(1) + } + + privateKeyFileName := "private.key" + publicKeystoreFileName := "public.keystore" + + privateKeyFile = path.Join(workingRoot, privateKeyFileName) + + if _, err := os.Stat(workingRoot); err == nil { + reader := bufio.NewReader(os.Stdin) + fmt.Println("The directory has already existed. \nDo you want to delete it? (y or n, press Enter for default n):") + t, err := reader.ReadString('\n') + t = strings.Trim(t, "\n") + if err != nil { + log.WithError(err).Error("unexpected error") + os.Exit(1) + } + if strings.Compare(t, "y") == 0 || strings.Compare(t, "yes") == 0 { + os.RemoveAll(workingRoot) + } else { + os.Exit(0) + } + } + + err := os.Mkdir(workingRoot, 0755) + if err != nil { + log.WithError(err).Error("unexpected error") + os.Exit(1) + } + + fmt.Println("Generating key pair...") + publicKey := runKeygen() + fmt.Println("Generated key pair.") + + fmt.Println("Generating nonce...") + nonce := noncegen(publicKey) + fmt.Println("Generated nonce.") + + fmt.Println("Generating config file...") + + configContent := fmt.Sprintf(`IsTestMode: true +WorkingRoot: "./" +PrivateKeyFile: "%s" +PubKeyStoreFile: "%s" +DHTFileName: "dht.db" +ListenAddr: "0.0.0.0:4661" +ThisNodeID: %s +MinNodeIDDifficulty: 24 +BlockProducer: + PublicKey: 034b4319f2e2a9d9f3fd55d1233ff7a2f2ea2e815e7227b3861b4a6a24a8d62697 + NodeID: 0000011839f464418166658ef6dec09ea68da1619a7a9e0f247f16e0d6c6504d + Nonce: + a: 761802 + b: 0 + c: 0 + d: 4611686019290328603 + ChainFileName: "chain.db" + BPGenesisInfo: + Version: 1 + BlockHash: f745ca6427237aac858dd3c7f2df8e6f3c18d0f1c164e07a1c6b8eebeba6b154 + Producer: 0000000000000000000000000000000000000000000000000000000000000001 + MerkleRoot: 0000000000000000000000000000000000000000000000000000000000000001 + ParentHash: 0000000000000000000000000000000000000000000000000000000000000001 + Timestamp: 2018-09-01T00:00:00Z + BaseAccounts: + - Address: d3dce44e0a4f1dae79b93f04ce13fb5ab719059f7409d7ca899d4c921da70129 + StableCoinBalance: 100000000 + CovenantCoinBalance: 100000000 +KnownNodes: +- ID: 0000011839f464418166658ef6dec09ea68da1619a7a9e0f247f16e0d6c6504d + Nonce: + a: 761802 + b: 0 + c: 0 + d: 4611686019290328603 + Addr: 120.79.254.36:11105 + PublicKey: 034b4319f2e2a9d9f3fd55d1233ff7a2f2ea2e815e7227b3861b4a6a24a8d62697 + Role: Leader +- ID: 00000177647ade3bd86a085510113ccae4b8e690424bb99b95b3545039ae8e8c + Nonce: + a: 197619 + b: 0 + c: 0 + d: 4611686019249700888 + Addr: 120.79.254.36:11106 + PublicKey: 02d6f3afcd26aa8de25f5d088c5f8d6b052b4ad1b27ce5b84939bc9f105556844e + Role: Miner +- ID: 000004b0267f959e645b0df5cd38ae0652c1160b960cdcb97b322caafe627e4f + Nonce: + a: 455820 + b: 0 + c: 0 + d: 3627017019 + Addr: 120.79.254.36:11107 + PublicKey: 034b4319f2e2a9d9f3fd55d1233ff7a2f2ea2e815e7227b3861b4a6a24a8d62697 + Role: Follower +- ID: 00000328ef30233890f61d7504b640b45e8ba33d5671157a0cee81745e46b963 + Nonce: + a: 333847 + b: 0 + c: 0 + d: 6917529031239958890 + Addr: 120.79.254.36:11108 + PublicKey: 0202361b87a087cd61137ba3b5bd83c48c180566c8d7f1a0b386c3277bf0dc6ebd + Role: Miner +- ID: %s + Nonce: + a: %d + b: %d + c: %d + d: %d + Addr: 127.0.0.1:11109 + PublicKey: %s + Role: Client +`, privateKeyFileName, publicKeystoreFileName, + nonce.Hash.String(), nonce.Hash.String(), + nonce.Nonce.A, nonce.Nonce.B, nonce.Nonce.C, nonce.Nonce.D, hex.EncodeToString(publicKey.Serialize())) + + err = ioutil.WriteFile(path.Join(workingRoot, "config.yaml"), []byte(configContent), 0755) + if err != nil { + log.WithError(err).Error("unexpected error") + os.Exit(1) + } + fmt.Println("Generated nonce.") +} diff --git a/cmd/cql-utils/idminer.go b/cmd/cql-utils/idminer.go new file mode 100644 index 000000000..b99da343d --- /dev/null +++ b/cmd/cql-utils/idminer.go @@ -0,0 +1,125 @@ +/* + * Copyright 2018 The CovenantSQL Authors. + * + * 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. + */ + +package main + +import ( + "encoding/hex" + "flag" + "fmt" + "math" + "math/rand" + "os" + "os/signal" + "runtime" + "syscall" + "time" + + "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" + "github.com/CovenantSQL/CovenantSQL/crypto/kms" + mine "github.com/CovenantSQL/CovenantSQL/pow/cpuminer" + "github.com/CovenantSQL/CovenantSQL/proto" + "github.com/CovenantSQL/CovenantSQL/utils/log" +) + +var ( + difficulty int +) + +func init() { + flag.IntVar(&difficulty, "difficulty", 24, "difficulty for miner to mine nodes and generating nonce") +} + +func runMiner() { + masterKey, err := readMasterKey() + if err != nil { + fmt.Printf("read master key failed: %v\n", err) + os.Exit(1) + } + + var publicKey *asymmetric.PublicKey + + if publicKeyHex != "" { + publicKeyBytes, err := hex.DecodeString(publicKeyHex) + if err != nil { + log.WithError(err).Fatal("error converting hex") + } + publicKey, err = asymmetric.ParsePubKey(publicKeyBytes) + if err != nil { + log.WithError(err).Fatal("error converting public key") + } + } else if privateKeyFile != "" { + privateKey, err := kms.LoadPrivateKey(privateKeyFile, []byte(masterKey)) + if err != nil { + log.WithError(err).Fatal("load private key file failed") + } + publicKey = privateKey.PubKey() + } + + signalCh := make(chan os.Signal, 1) + signal.Notify( + signalCh, + syscall.SIGINT, + syscall.SIGTERM, + ) + signal.Ignore(syscall.SIGHUP, syscall.SIGTTIN, syscall.SIGTTOU) + + cpuCount := runtime.NumCPU() + log.Infof("cpu: %#v\n", cpuCount) + nonceChs := make([]chan mine.NonceInfo, cpuCount) + stopChs := make([]chan struct{}, cpuCount) + + rand.Seed(time.Now().UnixNano()) + step := math.MaxUint64 / uint64(cpuCount) + + for i := 0; i < cpuCount; i++ { + nonceChs[i] = make(chan mine.NonceInfo) + stopChs[i] = make(chan struct{}) + go func(i int) { + miner := mine.NewCPUMiner(stopChs[i]) + nonceCh := nonceChs[i] + block := mine.MiningBlock{ + Data: publicKey.Serialize(), + NonceChan: nonceCh, + Stop: nil, + } + start := mine.Uint256{D: step*uint64(i) + uint64(rand.Uint32())} + log.Infof("miner #%#v start: %#v\n", i, start) + miner.ComputeBlockNonce(block, start, difficulty) + }(i) + } + + sig := <-signalCh + log.Infof("received signal %#v\n", sig) + for i := 0; i < cpuCount; i++ { + close(stopChs[i]) + } + + max := mine.NonceInfo{} + for i := 0; i < cpuCount; i++ { + newNonce := <-nonceChs[i] + if max.Difficulty < newNonce.Difficulty { + max = newNonce + } + } + + // verify result + log.Infof("verify result: %#v\n", kms.IsIDPubNonceValid(&proto.RawNodeID{Hash: max.Hash}, &max.Nonce, publicKey)) + + // print result + fmt.Printf("nonce: %v\n", max) + fmt.Printf("node id: %v\n", max.Hash.String()) +} diff --git a/cmd/cql-utils/keygen.go b/cmd/cql-utils/keygen.go new file mode 100644 index 000000000..816477bde --- /dev/null +++ b/cmd/cql-utils/keygen.go @@ -0,0 +1,69 @@ +/* + * Copyright 2018 The CovenantSQL Authors. + * + * 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. + */ + +package main + +import ( + "bufio" + "encoding/hex" + "fmt" + "os" + "strings" + + "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" + "github.com/CovenantSQL/CovenantSQL/crypto/kms" + "github.com/CovenantSQL/CovenantSQL/utils/log" +) + +func runKeygen() *asymmetric.PublicKey { + if _, err := os.Stat(privateKeyFile); err == nil { + reader := bufio.NewReader(os.Stdin) + fmt.Println("Private key file has already existed. \nDo you want to delete it? (y or n, press Enter for default n):") + t, err := reader.ReadString('\n') + t = strings.Trim(t, "\n") + if err != nil { + log.WithError(err).Error("unexpected error") + os.Exit(1) + } + if strings.Compare(t, "y") == 0 || strings.Compare(t, "yes") == 0 { + err = os.Remove(privateKeyFile) + if err != nil { + log.WithError(err).Error("unexpected error") + os.Exit(1) + } + } else { + os.Exit(0) + } + } + + privateKey, _, err := asymmetric.GenSecp256k1KeyPair() + if err != nil { + log.WithError(err).Fatal("generate key pair failed") + } + + masterKey, err := readMasterKey() + if err != nil { + log.WithError(err).Fatal("read master key failed") + } + + if err = kms.SavePrivateKey(privateKeyFile, privateKey, []byte(masterKey)); err != nil { + log.WithError(err).Fatal("save generated keypair failed") + } + + fmt.Printf("Private key file: %s\n", privateKeyFile) + fmt.Printf("Public key's hex: %s\n", hex.EncodeToString(privateKey.PubKey().Serialize())) + return privateKey.PubKey() +} diff --git a/cmd/cql-utils/keytool.go b/cmd/cql-utils/keytool.go new file mode 100644 index 000000000..d96afcf64 --- /dev/null +++ b/cmd/cql-utils/keytool.go @@ -0,0 +1,41 @@ +/* + * Copyright 2018 The CovenantSQL Authors. + * + * 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. + */ + +package main + +import ( + "encoding/hex" + "fmt" + "os" + + "github.com/CovenantSQL/CovenantSQL/crypto/kms" + "github.com/CovenantSQL/CovenantSQL/utils/log" +) + +func runKeytool() { + masterKey, err := readMasterKey() + if err != nil { + fmt.Printf("read master key failed: %v\n", err) + os.Exit(1) + } + + privateKey, err := kms.LoadPrivateKey(privateKeyFile, []byte(masterKey)) + if err != nil { + log.WithError(err).Error("load private key failed") + } + + fmt.Printf("Public key's hex: %s\n", hex.EncodeToString(privateKey.PubKey().Serialize())) +} diff --git a/cmd/cql-utils/main.go b/cmd/cql-utils/main.go index a769b1494..052f5b87c 100644 --- a/cmd/cql-utils/main.go +++ b/cmd/cql-utils/main.go @@ -17,36 +17,13 @@ package main import ( - "bufio" - "encoding/hex" - "encoding/json" "flag" "fmt" - "io/ioutil" - "math" - "math/rand" "os" - "os/signal" - "path" - "reflect" "runtime" - "strings" "syscall" - "time" - "github.com/CovenantSQL/CovenantSQL/blockproducer" - "github.com/CovenantSQL/CovenantSQL/client" - "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" - "github.com/CovenantSQL/CovenantSQL/crypto/kms" - mine "github.com/CovenantSQL/CovenantSQL/pow/cpuminer" - "github.com/CovenantSQL/CovenantSQL/proto" - "github.com/CovenantSQL/CovenantSQL/route" - "github.com/CovenantSQL/CovenantSQL/rpc" - "github.com/CovenantSQL/CovenantSQL/sqlchain" "github.com/CovenantSQL/CovenantSQL/utils/log" - "github.com/CovenantSQL/CovenantSQL/worker" - - "github.com/CovenantSQL/CovenantSQL/crypto" "golang.org/x/crypto/ssh/terminal" ) @@ -55,39 +32,30 @@ var ( tool string publicKeyHex string privateKeyFile string - difficulty int - rpcName string - rpcEndpoint string - rpcReq string configFile string - workingRoot string - isTestNetAddr bool - rpcServiceMap = map[string]interface{}{ - "DHT": &route.DHTService{}, - "DBS": &worker.DBMSRPCService{}, - "BPDB": &blockproducer.DBService{}, - "SQLC": &sqlchain.MuxService{}, - } + showVersion bool ) +const name = "cql-utils" + func init() { - log.SetLevel(log.ErrorLevel) + log.SetLevel(log.InfoLevel) - flag.StringVar(&tool, "tool", "", "tool type, miner, keygen, keytool, rpc, nonce, confgen, addrgen") + flag.StringVar(&tool, "tool", "", "tool type, miner, keygen, keytool, rpc, nonce, confgen, addrgen, adapterconfgen") flag.StringVar(&publicKeyHex, "public", "", "public key hex string to mine node id/nonce") flag.StringVar(&privateKeyFile, "private", "private.key", "private key file to generate/show") - flag.IntVar(&difficulty, "difficulty", 24, "difficulty for miner to mine nodes and generating nonce") - flag.StringVar(&rpcName, "rpc", "", "rpc name to do test call") - flag.StringVar(&rpcEndpoint, "endpoint", "", "rpc endpoint to do test call") - flag.StringVar(&rpcReq, "req", "", "rpc request to do test call, in json format") - flag.StringVar(&configFile, "config", "", "rpc config file") - flag.StringVar(&workingRoot, "root", "conf", "confgen root is the working root directory containing all auto-generating keys and certifications") - flag.BoolVar(&isTestNetAddr, "addrgen", false, "addrgen generates a testnet address from your key pair") + flag.StringVar(&configFile, "config", "config.yaml", "config file to use") + flag.BoolVar(&showVersion, "version", false, "Show version information and exit") } func main() { - log.Infof("idminer build: %s\n", version) flag.Parse() + if showVersion { + fmt.Printf("%v %v %v %v %v\n", + name, version, runtime.GOOS, runtime.GOARCH, runtime.Version()) + os.Exit(0) + } + log.Infof("cql-utils build: %#v\n", version) switch tool { case "miner": @@ -112,25 +80,13 @@ func main() { } runKeytool() case "rpc": - if configFile == "" { - // error - log.Error("config file path is required for rpc tool") - os.Exit(1) - } - if rpcEndpoint == "" || rpcName == "" || rpcReq == "" { - // error - log.Error("rpc payload is required for rpc tool") - os.Exit(1) - } runRPC() case "nonce": runNonce() case "confgen": - if workingRoot == "" { - log.Error("root directory is required for confgen") - os.Exit(1) - } runConfgen() + case "adapterconfgen": + runAdapterConfGen() case "addrgen": if privateKeyFile == "" && publicKeyHex == "" { log.Error("privateKey path or publicKey hex is required for addrgen") @@ -143,477 +99,6 @@ func main() { } } -func runMiner() { - masterKey, err := readMasterKey() - if err != nil { - fmt.Printf("read master key failed: %v\n", err) - os.Exit(1) - } - - var publicKey *asymmetric.PublicKey - - if publicKeyHex != "" { - publicKeyBytes, err := hex.DecodeString(publicKeyHex) - if err != nil { - log.Fatalf("error converting hex: %s\n", err) - } - publicKey, err = asymmetric.ParsePubKey(publicKeyBytes) - if err != nil { - log.Fatalf("error converting public key: %s\n", err) - } - } else if privateKeyFile != "" { - privateKey, err := kms.LoadPrivateKey(privateKeyFile, []byte(masterKey)) - if err != nil { - log.Fatalf("load private key file faile: %v\n", err) - } - publicKey = privateKey.PubKey() - } - - signalCh := make(chan os.Signal, 1) - signal.Notify( - signalCh, - syscall.SIGINT, - syscall.SIGTERM, - ) - signal.Ignore(syscall.SIGHUP, syscall.SIGTTIN, syscall.SIGTTOU) - - cpuCount := runtime.NumCPU() - log.Infof("cpu: %d\n", cpuCount) - nonceChs := make([]chan mine.NonceInfo, cpuCount) - stopChs := make([]chan struct{}, cpuCount) - - rand.Seed(time.Now().UnixNano()) - step := math.MaxUint64 / uint64(cpuCount) - - for i := 0; i < cpuCount; i++ { - nonceChs[i] = make(chan mine.NonceInfo) - stopChs[i] = make(chan struct{}) - go func(i int) { - miner := mine.NewCPUMiner(stopChs[i]) - nonceCh := nonceChs[i] - block := mine.MiningBlock{ - Data: publicKey.Serialize(), - NonceChan: nonceCh, - Stop: nil, - } - start := mine.Uint256{D: step*uint64(i) + uint64(rand.Uint32())} - log.Infof("miner #%d start: %v\n", i, start) - miner.ComputeBlockNonce(block, start, difficulty) - }(i) - } - - sig := <-signalCh - log.Infof("received signal %s\n", sig) - for i := 0; i < cpuCount; i++ { - close(stopChs[i]) - } - - max := mine.NonceInfo{} - for i := 0; i < cpuCount; i++ { - newNonce := <-nonceChs[i] - if max.Difficulty < newNonce.Difficulty { - max = newNonce - } - } - - // verify result - log.Infof("verify result: %v\n", kms.IsIDPubNonceValid(&proto.RawNodeID{Hash: max.Hash}, &max.Nonce, publicKey)) - - // print result - fmt.Printf("nonce: %v\n", max) - fmt.Printf("node id: %v\n", max.Hash.String()) -} - -func runKeygen() *asymmetric.PublicKey { - if _, err := os.Stat(privateKeyFile); err == nil { - reader := bufio.NewReader(os.Stdin) - fmt.Println("Private key file has already existed. \nDo you want to delete it? (y or n, press Enter for default n):") - t, err := reader.ReadString('\n') - t = strings.Trim(t, "\n") - if err != nil { - log.Errorf("Unexpected error: %v\n", err) - os.Exit(1) - } - if strings.Compare(t, "y") == 0 || strings.Compare(t, "yes") == 0 { - err = os.Remove(privateKeyFile) - if err != nil { - log.Errorf("Unexpected error: %v\n", err) - os.Exit(1) - } - } else { - os.Exit(0) - } - } - - privateKey, _, err := asymmetric.GenSecp256k1KeyPair() - if err != nil { - log.Fatalf("generate key pair failed: %v\n", err) - } - - masterKey, err := readMasterKey() - if err != nil { - log.Fatalf("read master key failed: %v\n", err) - } - - if err = kms.SavePrivateKey(privateKeyFile, privateKey, []byte(masterKey)); err != nil { - log.Fatalf("save generated keypair failed: %v\n", err) - } - - fmt.Printf("Private key file: %s\n", privateKeyFile) - fmt.Printf("Public key's hex: %s\n", hex.EncodeToString(privateKey.PubKey().Serialize())) - return privateKey.PubKey() -} - -func runKeytool() { - masterKey, err := readMasterKey() - if err != nil { - fmt.Printf("read master key failed: %v\n", err) - os.Exit(1) - } - - privateKey, err := kms.LoadPrivateKey(privateKeyFile, []byte(masterKey)) - if err != nil { - log.Errorf("load private key failed: %v\n", err) - } - - fmt.Printf("Public key's hex: %s\n", hex.EncodeToString(privateKey.PubKey().Serialize())) -} - -func runRPC() { - if err := client.Init(configFile, []byte("")); err != nil { - fmt.Printf("init rpc client failed: %v\n", err) - os.Exit(1) - return - } - - req, resp := resolveRPCEntities() - - // fill the req with request body - if err := json.Unmarshal([]byte(rpcReq), req); err != nil { - fmt.Printf("decode request body failed: %v\n", err) - os.Exit(1) - return - } - - if err := rpc.NewCaller().CallNode(proto.NodeID(rpcEndpoint), rpcName, req, resp); err != nil { - // send request failed - fmt.Printf("call rpc failed: %v\n", err) - os.Exit(1) - return - } - - // print the response - if resBytes, err := json.MarshalIndent(resp, "", " "); err != nil { - fmt.Printf("marshal response failed: %v\n", err) - os.Exit(1) - } else { - fmt.Println(string(resBytes)) - } -} - -func resolveRPCEntities() (req interface{}, resp interface{}) { - rpcParts := strings.SplitN(rpcName, ".", 2) - - if len(rpcParts) != 2 { - // error rpc name - fmt.Printf("%v is not a valid rpc name\n", rpcName) - os.Exit(1) - return - } - - rpcService := rpcParts[0] - - if s, supported := rpcServiceMap[rpcService]; supported { - typ := reflect.TypeOf(s) - - // traversing methods - for m := 0; m < typ.NumMethod(); m++ { - method := typ.Method(m) - mtype := method.Type - - if method.Name == rpcParts[1] { - // name matched - if mtype.PkgPath() != "" || mtype.NumIn() != 3 || mtype.NumOut() != 1 { - fmt.Printf("%v is not a valid rpc endpoint method\n", rpcName) - os.Exit(1) - return - } - - argType := mtype.In(1) - replyType := mtype.In(2) - - if argType.Kind() == reflect.Ptr { - req = reflect.New(argType.Elem()).Interface() - } else { - req = reflect.New(argType).Interface() - - } - - resp = reflect.New(replyType.Elem()).Interface() - - return - } - } - } - - // not found - fmt.Printf("rpc method %v not found\n", rpcName) - os.Exit(1) - - return -} - -func runNonce() { - var publicKey *asymmetric.PublicKey - - if publicKeyHex != "" { - publicKeyBytes, err := hex.DecodeString(publicKeyHex) - if err != nil { - log.Fatalf("error converting hex: %s\n", err) - } - publicKey, err = asymmetric.ParsePubKey(publicKeyBytes) - if err != nil { - log.Fatalf("error converting public key: %s\n", err) - } - } else if privateKeyFile != "" { - masterKey, err := readMasterKey() - if err != nil { - fmt.Printf("read master key failed: %v\n", err) - os.Exit(1) - } - privateKey, err := kms.LoadPrivateKey(privateKeyFile, []byte(masterKey)) - if err != nil { - log.Fatalf("load private key file fail: %v\n", err) - } - publicKey = privateKey.PubKey() - } else { - log.Fatalln("can neither convert public key nor load private key") - } - - noncegen(publicKey) -} - -func noncegen(publicKey *asymmetric.PublicKey) *mine.NonceInfo { - publicKeyBytes := publicKey.Serialize() - - cpuCount := runtime.NumCPU() - log.Infof("cpu: %d\n", cpuCount) - stopCh := make(chan struct{}) - nonceCh := make(chan mine.NonceInfo) - - rand.Seed(time.Now().UnixNano()) - step := 256 / cpuCount - for i := 0; i < cpuCount; i++ { - go func(i int) { - startBit := i * step - position := startBit / 64 - shift := uint(startBit % 64) - log.Infof("position: %d, shift: %d, i: %d", position, shift, i) - var start mine.Uint256 - if position == 0 { - start = mine.Uint256{A: uint64(1<= difficulty { - nonce := mine.NonceInfo{ - Nonce: j, - Difficulty: currentDifficulty, - Hash: currentHash, - } - nonceCh <- nonce - } - } - } - }(i) - } - - nonce := <-nonceCh - close(stopCh) - - // verify result - if !kms.IsIDPubNonceValid(&proto.RawNodeID{Hash: nonce.Hash}, &nonce.Nonce, publicKey) { - log.Fatalf("nonce: %v\nnode id: %s", nonce, nonce.Hash.String()) - } - - // print result - fmt.Printf("nonce: %v\n", nonce) - fmt.Printf("node id: %v\n", nonce.Hash.String()) - - return &nonce -} - -func runConfgen() { - privateKeyFileName := "private.key" - publicKeystoreFileName := "public.keystore" - - privateKeyFile = path.Join(workingRoot, privateKeyFileName) - - if _, err := os.Stat(workingRoot); err == nil { - reader := bufio.NewReader(os.Stdin) - fmt.Println("The directory has already existed. \nDo you want to delete it? (y or n, press Enter for default n):") - t, err := reader.ReadString('\n') - t = strings.Trim(t, "\n") - if err != nil { - log.Errorf("Unexpected error: %v\n", err) - os.Exit(1) - } - if strings.Compare(t, "y") == 0 || strings.Compare(t, "yes") == 0 { - os.RemoveAll(workingRoot) - } else { - os.Exit(0) - } - } - - err := os.Mkdir(workingRoot, 0755) - if err != nil { - log.Errorf("Unexpected error: %v", err) - os.Exit(1) - } - - fmt.Println("Generating key pair...") - publicKey := runKeygen() - fmt.Println("Generated key pair.") - - fmt.Println("Generating nonce...") - nonce := noncegen(publicKey) - fmt.Println("Generated nonce.") - - fmt.Println("Generating config file...") - - configContent := fmt.Sprintf(`IsTestMode: true -WorkingRoot: "./" -PrivateKeyFile: "%s" -PubKeyStoreFile: "%s" -DHTFileName: "dht.db" -ListenAddr: "0.0.0.0:4661" -ThisNodeID: %s -MinNodeIDDifficulty: 24 -BlockProducer: - PublicKey: 034b4319f2e2a9d9f3fd55d1233ff7a2f2ea2e815e7227b3861b4a6a24a8d62697 - NodeID: 0000011839f464418166658ef6dec09ea68da1619a7a9e0f247f16e0d6c6504d - Nonce: - a: 761802 - b: 0 - c: 0 - d: 4611686019290328603 - ChainFileName: "chain.db" - BPGenesisInfo: - Version: 1 - BlockHash: f745ca6427237aac858dd3c7f2df8e6f3c18d0f1c164e07a1c6b8eebeba6b154 - Producer: 0000000000000000000000000000000000000000000000000000000000000001 - MerkleRoot: 0000000000000000000000000000000000000000000000000000000000000001 - ParentHash: 0000000000000000000000000000000000000000000000000000000000000001 - Timestamp: 2018-09-01T00:00:00Z - BaseAccounts: - - Address: d3dce44e0a4f1dae79b93f04ce13fb5ab719059f7409d7ca899d4c921da70129 - StableCoinBalance: 100000000 - CovenantCoinBalance: 100000000 -KnownNodes: -- ID: 0000011839f464418166658ef6dec09ea68da1619a7a9e0f247f16e0d6c6504d - Nonce: - a: 761802 - b: 0 - c: 0 - d: 4611686019290328603 - Addr: 120.79.254.36:11105 - PublicKey: 034b4319f2e2a9d9f3fd55d1233ff7a2f2ea2e815e7227b3861b4a6a24a8d62697 - Role: Leader -- ID: 00000177647ade3bd86a085510113ccae4b8e690424bb99b95b3545039ae8e8c - Nonce: - a: 197619 - b: 0 - c: 0 - d: 4611686019249700888 - Addr: 120.79.254.36:11106 - PublicKey: 02d6f3afcd26aa8de25f5d088c5f8d6b052b4ad1b27ce5b84939bc9f105556844e - Role: Miner -- ID: 000004b0267f959e645b0df5cd38ae0652c1160b960cdcb97b322caafe627e4f - Nonce: - a: 455820 - b: 0 - c: 0 - d: 3627017019 - Addr: 120.79.254.36:11107 - PublicKey: 034b4319f2e2a9d9f3fd55d1233ff7a2f2ea2e815e7227b3861b4a6a24a8d62697 - Role: Follower -- ID: 00000328ef30233890f61d7504b640b45e8ba33d5671157a0cee81745e46b963 - Nonce: - a: 333847 - b: 0 - c: 0 - d: 6917529031239958890 - Addr: 120.79.254.36:11108 - PublicKey: 0202361b87a087cd61137ba3b5bd83c48c180566c8d7f1a0b386c3277bf0dc6ebd - Role: Miner -- ID: %s - Nonce: - a: %d - b: %d - c: %d - d: %d - Addr: 127.0.0.1:11109 - PublicKey: %s - Role: Client -`, privateKeyFileName, publicKeystoreFileName, - nonce.Hash.String(), nonce.Hash.String(), - nonce.Nonce.A, nonce.Nonce.B, nonce.Nonce.C, nonce.Nonce.D, hex.EncodeToString(publicKey.Serialize())) - - err = ioutil.WriteFile(path.Join(workingRoot, "config.yaml"), []byte(configContent), 0755) - if err != nil { - log.Errorf("Unexpected error: %v\n", err) - os.Exit(1) - } - fmt.Println("Generated nonce.") -} - -func runAddrgen() { - var publicKey *asymmetric.PublicKey - - if publicKeyHex != "" { - publicKeyBytes, err := hex.DecodeString(publicKeyHex) - if err != nil { - log.Fatalf("error converting hex: %s\n", err) - } - publicKey, err = asymmetric.ParsePubKey(publicKeyBytes) - if err != nil { - log.Fatalf("error converting public key: %s\n", err) - } - } else if privateKeyFile != "" { - masterKey, err := readMasterKey() - if err != nil { - fmt.Printf("read master key failed: %v\n", err) - os.Exit(1) - } - privateKey, err := kms.LoadPrivateKey(privateKeyFile, []byte(masterKey)) - if err != nil { - log.Fatalf("load private key file fail: %v\n", err) - } - publicKey = privateKey.PubKey() - } else { - fmt.Println("privateKey path or publicKey hex is required for addrgen") - os.Exit(1) - } - - addr, err := crypto.PubKey2Addr(publicKey, crypto.TestNet) - if err != nil { - log.Fatalf("unexpected error: %v\n", err) - } - fmt.Printf("wallet address: %s\n", addr) -} - func readMasterKey() (string, error) { fmt.Println("Enter master key(press Enter for default: \"\"): ") bytePwd, err := terminal.ReadPassword(int(syscall.Stdin)) diff --git a/cmd/cql-utils/noncegen.go b/cmd/cql-utils/noncegen.go new file mode 100644 index 000000000..be8acad38 --- /dev/null +++ b/cmd/cql-utils/noncegen.go @@ -0,0 +1,127 @@ +/* + * Copyright 2018 The CovenantSQL Authors. + * + * 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. + */ + +package main + +import ( + "encoding/hex" + "fmt" + "math/rand" + "os" + "runtime" + "time" + + "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" + "github.com/CovenantSQL/CovenantSQL/crypto/kms" + mine "github.com/CovenantSQL/CovenantSQL/pow/cpuminer" + "github.com/CovenantSQL/CovenantSQL/proto" + "github.com/CovenantSQL/CovenantSQL/utils/log" +) + +func runNonce() { + var publicKey *asymmetric.PublicKey + + if publicKeyHex != "" { + publicKeyBytes, err := hex.DecodeString(publicKeyHex) + if err != nil { + log.WithError(err).Fatal("error converting hex") + } + publicKey, err = asymmetric.ParsePubKey(publicKeyBytes) + if err != nil { + log.WithError(err).Fatal("error converting public key") + } + } else if privateKeyFile != "" { + masterKey, err := readMasterKey() + if err != nil { + log.WithError(err).Error("read master key failed") + os.Exit(1) + } + privateKey, err := kms.LoadPrivateKey(privateKeyFile, []byte(masterKey)) + if err != nil { + log.WithError(err).Fatal("load private key file failed") + } + publicKey = privateKey.PubKey() + } else { + log.Fatalln("can neither convert public key nor load private key") + } + + noncegen(publicKey) +} + +func noncegen(publicKey *asymmetric.PublicKey) *mine.NonceInfo { + publicKeyBytes := publicKey.Serialize() + + cpuCount := runtime.NumCPU() + log.Infof("cpu: %#v\n", cpuCount) + stopCh := make(chan struct{}) + nonceCh := make(chan mine.NonceInfo) + + rand.Seed(time.Now().UnixNano()) + step := 256 / cpuCount + for i := 0; i < cpuCount; i++ { + go func(i int) { + startBit := i * step + position := startBit / 64 + shift := uint(startBit % 64) + log.Infof("position: %#v, shift: %#v, i: %#v", position, shift, i) + var start mine.Uint256 + if position == 0 { + start = mine.Uint256{A: uint64(1<= difficulty { + nonce := mine.NonceInfo{ + Nonce: j, + Difficulty: currentDifficulty, + Hash: currentHash, + } + nonceCh <- nonce + } + } + } + }(i) + } + + nonce := <-nonceCh + close(stopCh) + + // verify result + if !kms.IsIDPubNonceValid(&proto.RawNodeID{Hash: nonce.Hash}, &nonce.Nonce, publicKey) { + log.WithFields(log.Fields{ + "nonce": nonce, + "id": nonce.Hash.String(), + }).Fatal("invalid nonce") + } + + // print result + fmt.Printf("nonce: %v\n", nonce) + fmt.Printf("node id: %v\n", nonce.Hash.String()) + + return &nonce +} diff --git a/cmd/cql-utils/rpc.go b/cmd/cql-utils/rpc.go new file mode 100644 index 000000000..f3663fceb --- /dev/null +++ b/cmd/cql-utils/rpc.go @@ -0,0 +1,181 @@ +/* + * Copyright 2018 The CovenantSQL Authors. + * + * 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. + */ + +package main + +import ( + "encoding/json" + "flag" + "fmt" + "os" + "reflect" + "strings" + + "github.com/CovenantSQL/CovenantSQL/blockproducer" + bp "github.com/CovenantSQL/CovenantSQL/blockproducer" + "github.com/CovenantSQL/CovenantSQL/client" + "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" + "github.com/CovenantSQL/CovenantSQL/crypto/kms" + "github.com/CovenantSQL/CovenantSQL/proto" + "github.com/CovenantSQL/CovenantSQL/route" + "github.com/CovenantSQL/CovenantSQL/rpc" + "github.com/CovenantSQL/CovenantSQL/sqlchain" + "github.com/CovenantSQL/CovenantSQL/utils/log" + "github.com/CovenantSQL/CovenantSQL/worker" + "gopkg.in/yaml.v2" +) + +var ( + rpcServiceMap = map[string]interface{}{ + route.DHTRPCName: &route.DHTService{}, + route.DBRPCName: &worker.DBMSRPCService{}, + route.BPDBRPCName: &blockproducer.DBService{}, + route.SQLChainRPCName: &sqlchain.MuxService{}, + route.BlockProducerRPCName: &bp.ChainRPCService{}, + } + rpcName string + rpcEndpoint string + rpcReq string +) + +type canSign interface { + Sign(signer *asymmetric.PrivateKey) error +} + +func init() { + flag.StringVar(&rpcName, "rpc", "", "rpc name to do test call") + flag.StringVar(&rpcEndpoint, "rpc-endpoint", "", "rpc endpoint to do test call") + flag.StringVar(&rpcReq, "rpc-req", "", "rpc request to do test call, in json format") +} + +func runRPC() { + if configFile == "" { + // error + log.Error("config file path is required for rpc tool") + os.Exit(1) + } + if rpcEndpoint == "" || rpcName == "" || rpcReq == "" { + // error + log.Error("rpc payload is required for rpc tool") + os.Exit(1) + } + + if err := client.Init(configFile, []byte("")); err != nil { + fmt.Printf("init rpc client failed: %v\n", err) + os.Exit(1) + return + } + + req, resp := resolveRPCEntities() + + // fill the req with request body + if err := json.Unmarshal([]byte(rpcReq), req); err != nil { + fmt.Printf("decode request body failed: %v\n", err) + os.Exit(1) + return + } + + // requires signature? + if err := checkAndSign(req); err != nil { + fmt.Printf("sign request failed: %v\n", err) + os.Exit(1) + return + } + + if err := rpc.NewCaller().CallNode(proto.NodeID(rpcEndpoint), rpcName, req, resp); err != nil { + // send request failed + fmt.Printf("call rpc failed: %v\n", err) + os.Exit(1) + return + } + + // print the response + if resBytes, err := yaml.Marshal(resp); err != nil { + fmt.Printf("marshal response failed: %v\n", err) + os.Exit(1) + } else { + fmt.Println(string(resBytes)) + } +} + +func checkAndSign(req interface{}) (err error) { + if reflect.ValueOf(req).Kind() != reflect.Ptr { + return checkAndSign(&req) + } + + if canSignObj, ok := req.(canSign); ok { + var privKey *asymmetric.PrivateKey + if privKey, err = kms.GetLocalPrivateKey(); err != nil { + return + } + if err = canSignObj.Sign(privKey); err != nil { + return + } + } + + return +} + +func resolveRPCEntities() (req interface{}, resp interface{}) { + rpcParts := strings.SplitN(rpcName, ".", 2) + + if len(rpcParts) != 2 { + // error rpc name + fmt.Printf("%v is not a valid rpc name\n", rpcName) + os.Exit(1) + return + } + + rpcService := rpcParts[0] + + if s, supported := rpcServiceMap[rpcService]; supported { + typ := reflect.TypeOf(s) + + // traversing methods + for m := 0; m < typ.NumMethod(); m++ { + method := typ.Method(m) + mtype := method.Type + + if method.Name == rpcParts[1] { + // name matched + if mtype.PkgPath() != "" || mtype.NumIn() != 3 || mtype.NumOut() != 1 { + fmt.Printf("%v is not a valid rpc endpoint method\n", rpcName) + os.Exit(1) + return + } + + argType := mtype.In(1) + replyType := mtype.In(2) + + if argType.Kind() == reflect.Ptr { + req = reflect.New(argType.Elem()).Interface() + } else { + req = reflect.New(argType).Interface() + } + + resp = reflect.New(replyType.Elem()).Interface() + + return + } + } + } + + // not found + fmt.Printf("rpc method %v not found\n", rpcName) + os.Exit(1) + + return +} diff --git a/cmd/cql/main.go b/cmd/cql/main.go index 9fed8cdf5..5ec683a4c 100644 --- a/cmd/cql/main.go +++ b/cmd/cql/main.go @@ -25,6 +25,7 @@ import ( "io" "os" "os/user" + "runtime" "strconv" "strings" @@ -40,6 +41,8 @@ import ( "github.com/xo/usql/text" ) +const name = "cql" + var ( version = "unknown" dsn string @@ -50,6 +53,7 @@ var ( configFile string password string singleTransaction bool + showVersion bool variables varsFlag // DML variables @@ -145,7 +149,7 @@ func init() { return 0, nil }, Open: func(url *dburl.URL) (func(string, string) (*sql.DB, error), error) { - log.Infof("connecting to %v", url.DSN) + log.Infof("connecting to %#v", url.DSN) return sql.Open, nil }, }) @@ -171,6 +175,7 @@ func init() { flag.StringVar(&dsn, "dsn", "", "database url") flag.StringVar(&command, "command", "", "run only single command (SQL or usql internal command) and exit") flag.StringVar(&fileName, "file", "", "execute commands from file and exit") + flag.BoolVar(&showVersion, "version", false, "Show version information and exit") flag.BoolVar(&noRC, "no-rc", false, "do not read start up file") flag.BoolVar(&asymmetric.BypassSignature, "bypassSignature", false, "Disable signature sign and verify, for testing") @@ -188,12 +193,17 @@ func init() { func main() { flag.Parse() + if showVersion { + fmt.Printf("%v %v %v %v %v\n", + name, version, runtime.GOOS, runtime.GOARCH, runtime.Version()) + os.Exit(0) + } var err error // init covenantsql driver if err = client.Init(configFile, []byte(password)); err != nil { - log.Errorf("init covenantsql client failed: %v", err) + log.WithError(err).Error("init covenantsql client failed") os.Exit(-1) return } @@ -202,16 +212,16 @@ func main() { var stableCoinBalance, covenantCoinBalance uint64 if stableCoinBalance, err = client.GetStableCoinBalance(); err != nil { - log.Errorf("get stable coin balance failed: %v", err) + log.WithError(err).Error("get stable coin balance failed") return } if covenantCoinBalance, err = client.GetCovenantCoinBalance(); err != nil { - log.Errorf("get covenant coin balance failed: %v", err) + log.WithError(err).Error("get covenant coin balance failed") return } - log.Infof("stable coin balance is: %v", stableCoinBalance) - log.Infof("covenant coin balance is: %v", covenantCoinBalance) + log.Infof("stable coin balance is: %#v", stableCoinBalance) + log.Infof("covenant coin balance is: %#v", covenantCoinBalance) return } @@ -227,12 +237,12 @@ func main() { if err := client.Drop(dropDB); err != nil { // drop database failed - log.Errorf("drop database %v failed: %v", dropDB, err) + log.WithField("db", dropDB).WithError(err).Error("drop database failed") return } // drop database success - log.Infof("drop database %v success", dropDB) + log.Infof("drop database %#v success", dropDB) return } @@ -246,7 +256,7 @@ func main() { nodeCnt, err := strconv.ParseUint(createDB, 10, 16) if err != nil { // still failing - log.Errorf("create database failed: %v is not a valid instance description", createDB) + log.WithField("db", createDB).Error("create database failed: invalid instance description") os.Exit(-1) return } @@ -256,19 +266,19 @@ func main() { dsn, err := client.Create(meta) if err != nil { - log.Infof("create database failed: %v", err) + log.WithError(err).Error("create database failed") os.Exit(-1) return } - log.Infof("the newly created database is: %v", dsn) + log.Infof("the newly created database is: %#v", dsn) return } available := drivers.Available() cur, err := user.Current() if err != nil { - log.Errorf("get current failed: %v", err) + log.WithError(err).Error("get current user failed") os.Exit(-1) return } @@ -276,14 +286,14 @@ func main() { // run err = run(cur) if err != nil && err != io.EOF && err != rline.ErrInterrupt { - log.Errorf("run cli error: %v", err) + log.WithError(err).Error("run cli error") if e, ok := err.(*drivers.Error); ok && e.Err == text.ErrDriverNotAvailable { bindings := make([]string, 0, len(available)) for name := range available { bindings = append(bindings, name) } - log.Infof("Available drivers are: %v", bindings) + log.Infof("Available drivers are: %#v", bindings) return } } @@ -343,14 +353,14 @@ func run(u *user.User) (err error) { h.SetSingleLineMode(true) h.Reset([]rune(command)) if err = h.Run(); err != nil && err != io.EOF { - log.Errorf("run command failed: %v", err) + log.WithError(err).Error("run command failed") os.Exit(-1) return } } else if fileName != "" { // file if err = h.Include(fileName, false); err != nil { - log.Errorf("run file failed: %v", err) + log.WithError(err).Error("run file failed") os.Exit(-1) return } diff --git a/cmd/cql/util.go b/cmd/cql/util.go index af29b3bc3..8622c372b 100644 --- a/cmd/cql/util.go +++ b/cmd/cql/util.go @@ -47,7 +47,6 @@ func (t *SqTime) Scan(v interface{}) error { return nil case []byte: return t.parse(string(x)) - case string: return t.parse(x) } diff --git a/cmd/cqld/adapter.go b/cmd/cqld/adapter.go index ba63f5224..af8d5ad4c 100644 --- a/cmd/cqld/adapter.go +++ b/cmd/cqld/adapter.go @@ -67,7 +67,7 @@ func initStorage(dbFile string) (stor *LocalStorage, err error) { }) if err != nil { wd, _ := os.Getwd() - log.Errorf("create dht table %s failed: %s", utils.FJ(wd, dbFile), err) + log.WithField("file", utils.FJ(wd, dbFile)).WithError(err).Error("create dht table failed") return } @@ -82,12 +82,12 @@ func initStorage(dbFile string) (stor *LocalStorage, err error) { func (s *LocalStorage) Prepare(ctx context.Context, wb twopc.WriteBatch) (err error) { payload, err := s.decodeLog(wb) if err != nil { - log.Errorf("decode log failed: %s", err) + log.WithError(err).Error("decode log failed") return } execLog, err := s.compileExecLog(payload) if err != nil { - log.Errorf("compile exec log failed: %s", err) + log.WithError(err).Error("compile exec log failed") return } return s.Storage.Prepare(ctx, execLog) @@ -97,7 +97,7 @@ func (s *LocalStorage) Prepare(ctx context.Context, wb twopc.WriteBatch) (err er func (s *LocalStorage) Commit(ctx context.Context, wb twopc.WriteBatch) (err error) { payload, err := s.decodeLog(wb) if err != nil { - log.Errorf("decode log failed: %s", err) + log.WithError(err).Error("decode log failed") return } return s.commit(ctx, payload) @@ -107,30 +107,29 @@ func (s *LocalStorage) commit(ctx context.Context, payload *KayakPayload) (err e var nodeToSet proto.Node err = utils.DecodeMsgPack(payload.Data, &nodeToSet) if err != nil { - log.Errorf("unmarshal node from payload failed: %s", err) + log.WithError(err).Error("unmarshal node from payload failed") return } execLog, err := s.compileExecLog(payload) if err != nil { - log.Errorf("compile exec log failed: %s", err) + log.WithError(err).Error("compile exec log failed") return } err = route.SetNodeAddrCache(nodeToSet.ID.ToRawNodeID(), nodeToSet.Addr) if err != nil { - log.Errorf("set node addr %s %s cache failed: %v", nodeToSet.ID, nodeToSet.Addr, err) + log.WithFields(log.Fields{ + "id": nodeToSet.ID, + "addr": nodeToSet.Addr, + }).WithError(err).Error("set node addr cache failed") } err = kms.SetNode(&nodeToSet) if err != nil { - log.Errorf("kms set node %v failed: %v", nodeToSet, err) + log.WithField("node", nodeToSet).WithError(err).Error("kms set node failed") } // if s.consistent == nil, it is called during Init. and AddCache will be called by consistent.InitConsistent if s.consistent != nil { - err = s.consistent.AddCache(nodeToSet) - if err != nil { - //TODO(auxten) even no error will be returned, there may be some inconsistency and needs sync periodically - log.Errorf("add consistent cache failed: %s", err) - } + s.consistent.AddCache(nodeToSet) } return s.Storage.Commit(ctx, execLog) @@ -140,12 +139,12 @@ func (s *LocalStorage) commit(ctx context.Context, payload *KayakPayload) (err e func (s *LocalStorage) Rollback(ctx context.Context, wb twopc.WriteBatch) (err error) { payload, err := s.decodeLog(wb) if err != nil { - log.Errorf("decode log failed: %s", err) + log.WithError(err).Error("decode log failed") return } execLog, err := s.compileExecLog(payload) if err != nil { - log.Errorf("compile exec log failed: %s", err) + log.WithError(err).Error("compile exec log failed") return } @@ -158,11 +157,11 @@ func (s *LocalStorage) compileExecLog(payload *KayakPayload) (execLog *storage.E var nodeToSet proto.Node err = utils.DecodeMsgPack(payload.Data, &nodeToSet) if err != nil { - log.Errorf("compileExecLog: unmarshal node from payload failed: %s", err) + log.WithError(err).Error("compileExecLog: unmarshal node from payload failed") return } query := "INSERT OR REPLACE INTO `dht` (`id`, `node`) VALUES (?, ?);" - log.Debugf("sql: %s", query) + log.Debugf("sql: %#v", query) execLog = &storage.ExecLog{ Queries: []storage.Query{ { @@ -177,7 +176,7 @@ func (s *LocalStorage) compileExecLog(payload *KayakPayload) (execLog *storage.E case CmdSetDatabase: var instance wt.ServiceInstance if err = utils.DecodeMsgPack(payload.Data, &instance); err != nil { - log.Errorf("compileExecLog: unmarshal instance meta failed: %v", err) + log.WithError(err).Error("compileExecLog: unmarshal instance meta failed") return } query := "INSERT OR REPLACE INTO `databases` (`id`, `meta`) VALUES (? ,?);" @@ -195,7 +194,7 @@ func (s *LocalStorage) compileExecLog(payload *KayakPayload) (execLog *storage.E case CmdDeleteDatabase: var instance wt.ServiceInstance if err = utils.DecodeMsgPack(payload.Data, &instance); err != nil { - log.Errorf("compileExecLog: unmarshal instance id failed: %v", err) + log.WithError(err).Error("compileExecLog: unmarshal instance id failed") return } // TODO(xq262144), should add additional limit 1 after delete clause @@ -229,7 +228,7 @@ func (s *LocalStorage) decodeLog(wb twopc.WriteBatch) (payload *KayakPayload, er } err = utils.DecodeMsgPack(bytesPayload, payload) if err != nil { - log.Errorf("unmarshal payload failed: %s", err) + log.WithError(err).Error("unmarshal payload failed") return } @@ -248,7 +247,7 @@ func (s *KayakKVServer) Init(storePath string, initNodes []proto.Node) (err erro var nodeBuf *bytes.Buffer nodeBuf, err = utils.EncodeMsgPack(n) if err != nil { - log.Errorf("marshal node failed: %v", err) + log.WithError(err).Error("marshal node failed") return } payload := &KayakPayload{ @@ -259,18 +258,18 @@ func (s *KayakKVServer) Init(storePath string, initNodes []proto.Node) (err erro var execLog *storage.ExecLog execLog, err = s.KVStorage.compileExecLog(payload) if err != nil { - log.Errorf("compile exec log failed: %s", err) + log.WithError(err).Error("compile exec log failed") return } err = s.KVStorage.Storage.Prepare(context.Background(), execLog) if err != nil { - log.Errorf("init kayak KV prepare node failed: %v", err) + log.WithError(err).Error("init kayak KV prepare node failed") return } err = s.KVStorage.commit(context.Background(), payload) if err != nil { - log.Errorf("init kayak KV commit node failed: %v", err) + log.WithError(err).Error("init kayak KV commit node failed") return } } @@ -287,7 +286,7 @@ type KayakPayload struct { func (s *KayakKVServer) SetNode(node *proto.Node) (err error) { nodeBuf, err := utils.EncodeMsgPack(node) if err != nil { - log.Errorf("marshal node failed: %v", err) + log.WithError(err).Error("marshal node failed") return } payload := &KayakPayload{ @@ -297,13 +296,13 @@ func (s *KayakKVServer) SetNode(node *proto.Node) (err error) { writeData, err := utils.EncodeMsgPack(payload) if err != nil { - log.Errorf("marshal payload failed: %v", err) + log.WithError(err).Error("marshal payload failed") return err } _, err = s.Runtime.Apply(writeData.Bytes()) if err != nil { - log.Errorf("Apply set node failed: %s\nPayload:\n %s", err, writeData) + log.Errorf("Apply set node failed: %#v\nPayload:\n %#v", err, writeData) } return @@ -334,7 +333,7 @@ func (s *KayakKVServer) GetDatabase(dbID proto.DatabaseID) (instance wt.ServiceI }, }) if err != nil { - log.Errorf("Query database %v instance meta failed: %v", dbID, err) + log.WithField("db", dbID).WithError(err).Error("query database instance meta failed") return } @@ -368,13 +367,13 @@ func (s *KayakKVServer) SetDatabase(meta wt.ServiceInstance) (err error) { writeData, err := utils.EncodeMsgPack(payload) if err != nil { - log.Errorf("marshal payload failed: %s", err) + log.WithError(err).Error("marshal payload failed") return err } _, err = s.Runtime.Apply(writeData.Bytes()) if err != nil { - log.Errorf("Apply set database failed: %s\nPayload:\n %s", err, writeData) + log.Errorf("Apply set database failed: %#v\nPayload:\n %#v", err, writeData) } return @@ -397,13 +396,13 @@ func (s *KayakKVServer) DeleteDatabase(dbID proto.DatabaseID) (err error) { writeData, err := utils.EncodeMsgPack(payload) if err != nil { - log.Errorf("marshal payload failed: %s", err) + log.WithError(err).Error("marshal payload failed") return err } _, err = s.Runtime.Apply(writeData.Bytes()) if err != nil { - log.Errorf("Apply set database failed: %s\nPayload:\n %s", err, writeData) + log.Errorf("Apply set database failed: %#v\nPayload:\n %#v", err, writeData) } return @@ -419,7 +418,7 @@ func (s *KayakKVServer) GetAllDatabases() (instances []wt.ServiceInstance, err e }, }) if err != nil { - log.Errorf("Query all database instance meta failed: %v", err) + log.WithError(err).Error("query all database instance meta failed") return } @@ -462,10 +461,10 @@ func (s *KayakKVServer) GetAllNodeInfo() (nodes []proto.Node, err error) { }, }) if err != nil { - log.Errorf("Query: %s failed: %s", query, err) + log.WithField("query", query).WithError(err).Error("query failed") return } - log.Debugf("SQL: %v\nResults: %s", query, result) + log.Debugf("SQL: %#v\nResults: %#v", query, result) nodes = make([]proto.Node, 0, len(result)) @@ -474,7 +473,7 @@ func (s *KayakKVServer) GetAllNodeInfo() (nodes []proto.Node, err error) { continue } nodeBytes, ok := r[0].([]byte) - log.Debugf("nodeBytes: %s, %v", nodeBytes, ok) + log.Debugf("nodeBytes: %#v, %#v", nodeBytes, ok) if !ok { continue } @@ -482,7 +481,7 @@ func (s *KayakKVServer) GetAllNodeInfo() (nodes []proto.Node, err error) { nodeDec := proto.NewNode() err = utils.DecodeMsgPack(nodeBytes, nodeDec) if err != nil { - log.Errorf("unmarshal node info failed: %s", err) + log.WithError(err).Error("unmarshal node info failed") continue } nodes = append(nodes, *nodeDec) diff --git a/cmd/cqld/bench_test.go b/cmd/cqld/bench_test.go index 4c0c14ca6..0ead03fe0 100644 --- a/cmd/cqld/bench_test.go +++ b/cmd/cqld/bench_test.go @@ -32,7 +32,6 @@ import ( "github.com/CovenantSQL/CovenantSQL/rpc" "github.com/CovenantSQL/CovenantSQL/utils" "github.com/CovenantSQL/CovenantSQL/utils/log" - . "github.com/smartystreets/goconvey/convey" ) var ( @@ -43,13 +42,6 @@ var ( var FJ = filepath.Join -func TestBuild(t *testing.T) { - Convey("build", t, func() { - log.SetLevel(log.DebugLevel) - So(utils.Build(), ShouldBeNil) - }) -} - func start3BPs() { ctx, cancel := context.WithTimeout(context.Background(), time.Second*15) defer cancel() @@ -90,7 +82,19 @@ func TestStartBP_CallRPC(t *testing.T) { var err error start3BPs() - time.Sleep(5 * time.Second) + + ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) + defer cancel() + err = utils.WaitToConnect(ctx, "127.0.0.1", []int{ + 2122, + 2121, + 2120, + }, time.Second) + if err != nil { + log.Fatalf("wait for port ready timeout: %v", err) + } + + time.Sleep(2 * time.Second) conf.GConf, err = conf.LoadConfig(FJ(testWorkingDir, "./node_c/config.yaml")) if err != nil { @@ -135,8 +139,8 @@ func TestStartBP_CallRPC(t *testing.T) { reqType = "FindNeighbor" reqFindNeighbor := &proto.FindNeighborReq{ - NodeID: proto.NodeID(nodePayload.ID), - Count: 1, + ID: proto.NodeID(nodePayload.ID), + Count: 1, } respFindNeighbor := new(proto.FindNeighborResp) log.Debugf("req %s: %v", reqType, reqFindNeighbor) @@ -159,7 +163,7 @@ func TestStartBP_CallRPC(t *testing.T) { reqType = "FindNode" reqFN := &proto.FindNodeReq{ - NodeID: nodePayload.ID, + ID: nodePayload.ID, } respFN := new(proto.FindNodeResp) err = RPCClient.Call("DHT."+reqType, reqFN, respFN) @@ -214,18 +218,18 @@ func BenchmarkKayakKVServer_GetAllNodeInfo(b *testing.B) { err = kms.InitLocalKeyPair(privateKeyPath, masterKey) if err != nil { - log.Errorf("init local key pair failed: %s", err) + log.WithError(err).Error("init local key pair failed") return } conf.GConf.KnownNodes[idx].PublicKey, err = kms.GetLocalPublicKey() if err != nil { - log.Errorf("get local public key failed: %s", err) + log.WithError(err).Error("get local public key failed") return } // init nodes - log.Infof("init peers") + log.Info("init peers") _, _, _, err = initNodePeers(nodeID, pubKeyStorePath) if err != nil { return @@ -254,8 +258,8 @@ func BenchmarkKayakKVServer_GetAllNodeInfo(b *testing.B) { nodePayload.Addr = "nodePayloadAddr" reqFindNeighbor := &proto.FindNeighborReq{ - NodeID: proto.NodeID(nodePayload.ID), - Count: 1, + ID: proto.NodeID(nodePayload.ID), + Count: 1, } respFindNeighbor := new(proto.FindNeighborResp) log.Debugf("req %s: %v", reqType, reqFindNeighbor) @@ -288,7 +292,7 @@ func BenchmarkKayakKVServer_GetAllNodeInfo(b *testing.B) { reqType = "FindNode" reqFN := &proto.FindNodeReq{ - NodeID: nodePayload.ID, + ID: nodePayload.ID, } respFN := new(proto.FindNodeResp) b.Run("benchmark "+reqType, func(b *testing.B) { diff --git a/cmd/cqld/bootstrap.go b/cmd/cqld/bootstrap.go index d12681193..e885e5d3a 100644 --- a/cmd/cqld/bootstrap.go +++ b/cmd/cqld/bootstrap.go @@ -46,7 +46,6 @@ const ( //privateKeyFile = "private.key" //dhtFileName = "dht.db" kayakServiceName = "Kayak" - dhtServiceName = "DHT" ) func runNode(nodeID proto.NodeID, listenAddr string) (err error) { @@ -67,15 +66,15 @@ func runNode(nodeID proto.NodeID, listenAddr string) (err error) { err = kms.InitLocalKeyPair(conf.GConf.PrivateKeyFile, masterKey) if err != nil { - log.Errorf("init local key pair failed: %s", err) + log.WithError(err).Error("init local key pair failed") return } // init nodes - log.Infof("init peers") + log.Info("init peers") _, peers, thisNode, err := initNodePeers(nodeID, conf.GConf.PubKeyStoreFile) if err != nil { - log.Errorf("init nodes and peers failed: %s", err) + log.WithError(err).Error("init nodes and peers failed") return } @@ -83,38 +82,38 @@ func runNode(nodeID proto.NodeID, listenAddr string) (err error) { var server *rpc.Server // create server - log.Infof("create server") + log.Info("create server") if service, server, err = createServer( conf.GConf.PrivateKeyFile, conf.GConf.PubKeyStoreFile, masterKey, listenAddr); err != nil { - log.Errorf("create server failed: %s", err) + log.WithError(err).Error("create server failed") return } // init storage - log.Infof("init storage") + log.Info("init storage") var st *LocalStorage if st, err = initStorage(conf.GConf.DHTFileName); err != nil { - log.Errorf("init storage failed: %s", err) + log.WithError(err).Error("init storage failed") return } // init kayak - log.Infof("init kayak runtime") + log.Info("init kayak runtime") var kayakRuntime *kayak.Runtime if _, kayakRuntime, err = initKayakTwoPC(rootPath, thisNode, peers, st, service); err != nil { - log.Errorf("init kayak runtime failed: %s", err) + log.WithError(err).Error("init kayak runtime failed") return } // init kayak and consistent - log.Infof("init kayak and consistent runtime") + log.Info("init kayak and consistent runtime") kvServer := &KayakKVServer{ Runtime: kayakRuntime, KVStorage: st, } dht, err := route.NewDHTService(conf.GConf.DHTFileName, kvServer, true) if err != nil { - log.Errorf("init consistent hash failed: %s", err) + log.WithError(err).Error("init consistent hash failed") return } @@ -122,35 +121,35 @@ func runNode(nodeID proto.NodeID, listenAddr string) (err error) { kvServer.KVStorage.consistent = dht.Consistent // register service rpc - log.Infof("register dht service rpc") - err = server.RegisterService(dhtServiceName, dht) + log.Info("register dht service rpc") + err = server.RegisterService(route.DHTRPCName, dht) if err != nil { - log.Errorf("register dht service failed: %s", err) + log.WithError(err).Error("register dht service failed") return } // init metrics - log.Infof("register metric service rpc") + log.Info("register metric service rpc") metricService := metric.NewCollectServer() if err = server.RegisterService(metric.MetricServiceName, metricService); err != nil { - log.Errorf("init metric service failed: %v", err) + log.WithError(err).Error("init metric service failed") return } // init block producer database service - log.Infof("register block producer database service rpc") + log.Info("register block producer database service rpc") var dbService *bp.DBService if dbService, err = initDBService(kvServer, metricService); err != nil { - log.Errorf("init block producer db service failed: %v", err) + log.WithError(err).Error("init block producer db service failed") return } - if err = server.RegisterService(bp.DBServiceName, dbService); err != nil { - log.Errorf("init block producer db service failed: %v", err) + if err = server.RegisterService(route.BPDBRPCName, dbService); err != nil { + log.WithError(err).Error("init block producer db service failed") return } // init main chain service - log.Infof("register main chain service rpc") + log.Info("register main chain service rpc") chainConfig := bp.NewConfig( genesis, conf.GConf.BP.ChainFileName, @@ -158,11 +157,11 @@ func runNode(nodeID proto.NodeID, listenAddr string) (err error) { peers, nodeID, 2*time.Second, - 100*time.Millisecond, + 900*time.Millisecond, ) chain, err := bp.NewChain(chainConfig) if err != nil { - log.Errorf("init chain failed: %v", err) + log.WithError(err).Error("init chain failed") return } chain.Start() @@ -209,18 +208,18 @@ func createServer(privateKeyPath, pubKeyStorePath string, masterKey []byte, list func initKayakTwoPC(rootDir string, node *proto.Node, peers *kayak.Peers, worker twopc.Worker, service *kt.ETLSTransportService) (config kayak.Config, runtime *kayak.Runtime, err error) { // create kayak config - log.Infof("create twopc config") + log.Info("create twopc config") config = ka.NewTwoPCConfig(rootDir, service, worker) // create kayak runtime - log.Infof("create kayak runtime") + log.Info("create kayak runtime") runtime, err = ka.NewTwoPCKayak(peers, config) if err != nil { return } // init runtime - log.Infof("init kayak twopc runtime") + log.Info("init kayak twopc runtime") err = runtime.Init() return @@ -229,7 +228,7 @@ func initKayakTwoPC(rootDir string, node *proto.Node, peers *kayak.Peers, worker func initDBService(kvServer *KayakKVServer, metricService *metric.CollectServer) (dbService *bp.DBService, err error) { var serviceMap *bp.DBServiceMap if serviceMap, err = bp.InitServiceMap(kvServer); err != nil { - log.Errorf("init bp database service map failed") + log.WithError(err).Error("init bp database service map failed") return } @@ -243,41 +242,9 @@ func initDBService(kvServer *KayakKVServer, metricService *metric.CollectServer) return } -//FIXME(auxten): clean up ugly periodicPingBlockProducer -func periodicPingBlockProducer() { - var localNodeID proto.NodeID - var err error - - // get local node id - if localNodeID, err = kms.GetLocalNodeID(); err != nil { - return - } - - // get local node info - var localNodeInfo *proto.Node - if localNodeInfo, err = kms.GetNodeInfo(localNodeID); err != nil { - return - } - - log.Debugf("construct local node info: %v", localNodeInfo) - - go func() { - for { - time.Sleep(time.Second) - - // send ping requests to block producer - bpNodeIDs := route.GetBPs() - - for _, bpNodeID := range bpNodeIDs { - rpc.PingBP(localNodeInfo, bpNodeID) - } - } - }() -} - func loadGenesis() *types.Block { genesisInfo := conf.GConf.BP.BPGenesis - log.Infof("genesis config: %v", genesisInfo) + log.WithField("config", genesisInfo).Info("load genesis config") genesis := &types.Block{ SignedHeader: types.SignedHeader{ @@ -297,14 +264,13 @@ func loadGenesis() *types.Block { "address": ba.Address.String(), "stableCoinBalance": ba.StableCoinBalance, "covenantCoinBalance": ba.CovenantCoinBalance, - }).Debugf("setting one balance fixture in genesis block") - genesis.Transactions = append(genesis.Transactions, &pt.BaseAccount{ - Account: pt.Account{ + }).Debug("setting one balance fixture in genesis block") + genesis.Transactions = append(genesis.Transactions, pt.NewBaseAccount( + &pt.Account{ Address: proto.AccountAddress(ba.Address), StableCoinBalance: ba.StableCoinBalance, CovenantCoinBalance: ba.CovenantCoinBalance, - }, - }) + })) } return genesis diff --git a/cmd/cqld/client.go b/cmd/cqld/client.go index 40e45f09e..f70b2a411 100644 --- a/cmd/cqld/client.go +++ b/cmd/cqld/client.go @@ -59,13 +59,13 @@ func runClient(nodeID proto.NodeID) (err error) { err = kms.InitLocalKeyPair(privateKeyPath, masterKey) if err != nil { - log.Errorf("init local key pair failed: %s", err) + log.WithError(err).Error("init local key pair failed") return } conf.GConf.KnownNodes[idx].PublicKey, err = kms.GetLocalPublicKey() if err != nil { - log.Errorf("get local public key failed: %s", err) + log.WithError(err).Error("get local public key failed") return } //nodeInfo := asymmetric.GetPubKeyNonce(AllNodes[idx].PublicKey, 20, 500*time.Millisecond, nil) @@ -73,7 +73,7 @@ func runClient(nodeID proto.NodeID) (err error) { //log.Debugf("client nonce:\n%v", nodeInfo) // init nodes - log.Infof("init peers") + log.Info("init peers") _, _, _, err = initNodePeers(nodeID, pubKeyStorePath) if err != nil { return @@ -109,12 +109,12 @@ func clientRequest(reqType string, sql string) (err error) { } respA := new(proto.PingResp) - log.Debugf("req %s: %v", reqType, reqA) + log.Debugf("req %#v: %#v", reqType, reqA) err = client.Call("DHT."+reqType, reqA, respA) if err != nil { log.Fatal(err) } - log.Debugf("resp %s: %v", reqType, respA) + log.Debugf("resp %#v: %#v", reqType, respA) } else { for _, bp := range conf.GConf.KnownNodes { if bp.Role == proto.Leader || bp.Role == proto.Follower { @@ -124,19 +124,19 @@ func clientRequest(reqType string, sql string) (err error) { if client, err = rpc.InitClientConn(conn); err != nil { return } - log.Debugf("Calling BP: %s", bp.ID) + log.WithField("bp", bp.ID).Debug("Calling BP") reqType = "FindNeighbor" req := &proto.FindNeighborReq{ - NodeID: proto.NodeID(flag.Arg(0)), - Count: 10, + ID: proto.NodeID(flag.Arg(0)), + Count: 10, } resp := new(proto.FindNeighborResp) - log.Debugf("req %s: %v", reqType, req) + log.Debugf("req %#v: %#v", reqType, req) err = client.Call("DHT."+reqType, req, resp) if err != nil { log.Fatal(err) } - log.Debugf("resp %s: %v", reqType, resp) + log.Debugf("resp %#v: %#v", reqType, resp) } } } diff --git a/cmd/cqld/initconf.go b/cmd/cqld/initconf.go index 0b212b40c..cf2f96a0d 100644 --- a/cmd/cqld/initconf.go +++ b/cmd/cqld/initconf.go @@ -29,11 +29,11 @@ import ( func initNodePeers(nodeID proto.NodeID, publicKeystorePath string) (nodes *[]proto.Node, peers *kayak.Peers, thisNode *proto.Node, err error) { privateKey, err := kms.GetLocalPrivateKey() if err != nil { - log.Fatalf("get local private key failed: %s", err) + log.WithError(err).Fatal("get local private key failed") } publicKey, err := kms.GetLocalPublicKey() if err != nil { - log.Fatalf("get local public key failed: %s", err) + log.WithError(err).Fatal("get local public key failed") } leader := &kayak.Server{ @@ -63,14 +63,14 @@ func initNodePeers(nodeID proto.NodeID, publicKeystorePath string) (nodes *[]pro } } - log.Debugf("AllNodes:\n %v\n", conf.GConf.KnownNodes) + log.Debugf("AllNodes:\n %#v\n", conf.GConf.KnownNodes) err = peers.Sign(privateKey) if err != nil { - log.Errorf("sign peers failed: %s", err) + log.WithError(err).Error("sign peers failed") return nil, nil, nil, err } - log.Debugf("peers:\n %v\n", peers) + log.Debugf("peers:\n %#v\n", peers) //route.initResolver() kms.InitPublicKeyStore(publicKeystorePath, nil) @@ -80,10 +80,13 @@ func initNodePeers(nodeID proto.NodeID, publicKeystorePath string) (nodes *[]pro for _, p := range conf.GConf.KnownNodes { rawNodeIDHash, err := hash.NewHashFromStr(string(p.ID)) if err != nil { - log.Errorf("load hash from node id failed: %s", err) + log.WithError(err).Error("load hash from node id failed") return nil, nil, nil, err } - log.Debugf("set node addr: %v, %v", rawNodeIDHash, p.Addr) + log.WithFields(log.Fields{ + "node": rawNodeIDHash.String(), + "addr": p.Addr, + }).Debug("set node addr") rawNodeID := &proto.RawNodeID{Hash: *rawNodeIDHash} route.SetNodeAddrCache(rawNodeID, p.Addr) node := &proto.Node{ @@ -95,7 +98,7 @@ func initNodePeers(nodeID proto.NodeID, publicKeystorePath string) (nodes *[]pro } err = kms.SetNode(node) if err != nil { - log.Errorf("set node failed: %v\n %s", node, err) + log.WithField("node", node).WithError(err).Error("set node failed") } if p.ID == nodeID { kms.SetLocalNodeIDNonce(rawNodeID.CloneBytes(), &p.Nonce) diff --git a/cmd/cqld/main.go b/cmd/cqld/main.go index 430058b2a..04d6d401b 100644 --- a/cmd/cqld/main.go +++ b/cmd/cqld/main.go @@ -85,9 +85,9 @@ func init() { } func initLogs() { - log.Infof("%s starting, version %s, commit %s, branch %s", name, version, commit, branch) - log.Infof("%s, target architecture is %s, operating system target is %s", runtime.Version(), runtime.GOARCH, runtime.GOOS) - log.Infof("role: %s", conf.RoleTag) + log.Infof("%#v starting, version %#v, commit %#v, branch %#v", name, version, commit, branch) + log.Infof("%#v, target architecture is %#v, operating system target is %#v", runtime.Version(), runtime.GOARCH, runtime.GOOS) + log.Infof("role: %#v", conf.RoleTag) } func main() { @@ -95,14 +95,21 @@ func main() { rand.Seed(time.Now().UnixNano()) log.SetLevel(log.DebugLevel) flag.Parse() + + if showVersion { + fmt.Printf("%v %v %v %v %v\n", + name, version, runtime.GOOS, runtime.GOARCH, runtime.Version()) + os.Exit(0) + } + flag.Visit(func(f *flag.Flag) { - log.Infof("Args %s : %v", f.Name, f.Value) + log.Infof("Args %#v : %s", f.Name, f.Value) }) var err error conf.GConf, err = conf.LoadConfig(configFile) if err != nil { - log.Fatalf("load config from %s failed: %s", configFile, err) + log.WithField("config", configFile).WithError(err).Fatal("load config failed") } kms.InitBP() @@ -113,12 +120,6 @@ func main() { // init log initLogs() - if showVersion { - log.Infof("%s %s %s %s %s (commit %s, branch %s)", - name, version, runtime.GOOS, runtime.GOARCH, runtime.Version(), commit, branch) - os.Exit(0) - } - if !noLogo { fmt.Print(logo) } @@ -129,15 +130,15 @@ func main() { if clientMode { if err := runClient(conf.GConf.ThisNodeID); err != nil { - log.Fatalf("run client failed: %v", err.Error()) + log.WithError(err).Fatal("run client failed") } else { - log.Infof("run client success") + log.Info("run client success") } return } if err := runNode(conf.GConf.ThisNodeID, conf.GConf.ListenAddr); err != nil { - log.Fatalf("run kayak failed: %v", err.Error()) + log.WithError(err).Fatal("run kayak failed") } log.Info("server stopped") diff --git a/cmd/hotfix/msgpack-20180824/main.go b/cmd/hotfix/hash-upgrade/main.go similarity index 85% rename from cmd/hotfix/msgpack-20180824/main.go rename to cmd/hotfix/hash-upgrade/main.go index d80453001..0b51cfa96 100644 --- a/cmd/hotfix/msgpack-20180824/main.go +++ b/cmd/hotfix/hash-upgrade/main.go @@ -92,24 +92,24 @@ type ServiceInstance struct { func main() { flag.Parse() - log.Infof("start hotfix") + log.Info("start hotfix") // load private key privateKey, err := kms.LoadPrivateKey(privateKey, []byte("")) if err != nil { - log.Fatalf("load private key failed: %v", err) + log.WithError(err).Fatal("load private key failed") return } // backup dht file if err := exec.Command("cp", "-av", dhtFile, dhtFile+".bak").Run(); err != nil { - log.Fatalf("backup database failed: %v", err) + log.WithError(err).Fatal("backup database failed") return } st, err := storage.New(dhtFile) if err != nil { - log.Fatalf("open database failed: %v", err) + log.WithError(err).Fatal("open database failed") return } defer st.Close() @@ -118,7 +118,7 @@ func main() { []storage.Query{{Pattern: "SELECT `id`, `meta` FROM `databases`"}}) if err != nil { - log.Fatalf("select databases failed: %v", err) + log.WithError(err).Fatal("select database failed") return } @@ -137,7 +137,7 @@ func main() { var newInstance wt.ServiceInstance if err := utils.DecodeMsgPackPlain(rawInstance, &testDecode); err != nil { - log.Fatalf("test decode failed: %v", err) + log.WithError(err).Fatal("test decode failed") } else { // detect if the genesis block is in old version if strings.Contains(fmt.Sprintf("%#v", testDecode), "\"GenesisBlock\":[]uint8") { @@ -145,7 +145,7 @@ func main() { var instance ServiceInstance if err := utils.DecodeMsgPackPlain(rawInstance, &instance); err != nil { - log.Fatalf("decode msgpack failed: %v", err) + log.WithError(err).Fatal("decode msgpack failed") return } @@ -160,25 +160,32 @@ func main() { log.Info("detected new version, need re-signature") if err := utils.DecodeMsgPack(rawInstance, &newInstance); err != nil { - log.Fatalf("decode msgpack failed: %v", err) + log.WithError(err).Fatal("decode msgpack failed") return } // set genesis block to now newInstance.GenesisBlock.SignedHeader.Timestamp = time.Now().UTC() + // sign peers again + if err := newInstance.Peers.Sign(privateKey); err != nil { + log.WithError(err).Fatal("sign peers failed") + return + } + if err := newInstance.GenesisBlock.PackAndSignBlock(privateKey); err != nil { - log.Fatalf("sign genesis block failed: %v", err) + log.WithError(err).Fatal("sign genesis block failed") + return } } } - log.Infof("database is: %v -> %v", id, newInstance) + log.Infof("database is: %#v -> %#v", id, newInstance) // encode and put back to database rawInstanceBuffer, err := utils.EncodeMsgPack(newInstance) if err != nil { - log.Fatalf("encode msgpack failed: %v", err) + log.WithError(err).Fatal("encode msgpack failed") return } @@ -197,10 +204,10 @@ func main() { }, }, }); err != nil { - log.Fatalf("update meta failed: %v", err) + log.WithError(err).Fatal("update meta failed") return } } - log.Infof("hotfix complete") + log.Info("hotfix complete") } diff --git a/cmd/hotfix/msgpack-20180824/serial.go b/cmd/hotfix/hash-upgrade/serial.go similarity index 99% rename from cmd/hotfix/msgpack-20180824/serial.go rename to cmd/hotfix/hash-upgrade/serial.go index c5e3561b6..9fe483ecd 100644 --- a/cmd/hotfix/msgpack-20180824/serial.go +++ b/cmd/hotfix/hash-upgrade/serial.go @@ -1099,7 +1099,7 @@ func readElement(r io.Reader, order binary.ByteOrder, element interface{}) (err return i.UnmarshalBinary(buffer) } - log.Debugf("element type is: %s", reflect.TypeOf(e)) + log.Debugf("element type is: %#v", reflect.TypeOf(e).String()) return ErrInvalidType } @@ -1317,7 +1317,7 @@ func writeElement(w io.Writer, order binary.ByteOrder, element interface{}) (err return } - log.Debugf("element type is: %s", reflect.TypeOf(e)) + log.Debugf("element type is: %#v", reflect.TypeOf(e).String()) return ErrInvalidType } diff --git a/conf/config.go b/conf/config.go index 79cba0795..59e4a8e0c 100644 --- a/conf/config.go +++ b/conf/config.go @@ -143,13 +143,13 @@ var GConf *Config func LoadConfig(configPath string) (config *Config, err error) { configBytes, err := ioutil.ReadFile(configPath) if err != nil { - log.Errorf("read config file failed: %s", err) + log.WithError(err).Error("read config file failed") return } config = &Config{} err = yaml.Unmarshal(configBytes, config) if err != nil { - log.Errorf("unmarshal config file failed: %s", err) + log.WithError(err).Error("unmarshal config file failed") return } @@ -177,5 +177,14 @@ func LoadConfig(configPath string) (config *Config, err error) { if config.Miner != nil && !path.IsAbs(config.Miner.RootDir) { config.Miner.RootDir = path.Join(configDir, config.Miner.RootDir) } + /* + The `go test -race` makes BP catch up block too slow, so let's make + genesis block just one day ago in test mode + */ + if config.IsTestMode { + if config.BP != nil { + config.BP.BPGenesis.Timestamp = time.Now().AddDate(0, 0, -1) + } + } return } diff --git a/conf/config_test.go b/conf/config_test.go index c2b56571b..84d5d0103 100644 --- a/conf/config_test.go +++ b/conf/config_test.go @@ -23,9 +23,8 @@ import ( "testing" "time" - "github.com/CovenantSQL/CovenantSQL/crypto/hash" - "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" + "github.com/CovenantSQL/CovenantSQL/crypto/hash" "github.com/CovenantSQL/CovenantSQL/pow/cpuminer" "github.com/CovenantSQL/CovenantSQL/proto" "github.com/CovenantSQL/CovenantSQL/utils/log" diff --git a/consistent/consistent.go b/consistent/consistent.go index 5f8fbe6bb..22166a250 100644 --- a/consistent/consistent.go +++ b/consistent/consistent.go @@ -73,6 +73,7 @@ type Consistent struct { NumberOfReplicas int count int64 persist Persistence + cacheLock sync.RWMutex sync.RWMutex } @@ -97,21 +98,21 @@ func InitConsistent(storePath string, persistImpl Persistence, initBP bool) (c * err = c.persist.Init(storePath, BPNodes) if err != nil { - log.Errorf("init persist BP nodes failed: %v", err) + log.WithError(err).Error("init persist BP nodes failed") return } nodes, err := c.persist.GetAllNodeInfo() if err != nil { - log.Errorf("get all node id failed: %s", err) + log.WithError(err).Error("get all node id failed") return } - log.Debugf("c.persist.GetAllNodeInfo: %v", nodes) + log.Debugf("c.persist.GetAllNodeInfo: %#v", nodes) _, isKMSStorage := c.persist.(*KMSStorage) if isKMSStorage { for _, n := range nodes[:] { - c.add(n) + c.Add(n) } } else { // currently just for KayakKVServer @@ -131,25 +132,64 @@ func (c *Consistent) nodeKey(nodeID proto.NodeID, idx int) string { // Add inserts a string node in the consistent hash. func (c *Consistent) Add(node proto.Node) (err error) { - log.Debugf("add node %v to consistent ring", node) + log.WithField("node", node).Debug("add node to consistent ring") c.Lock() defer c.Unlock() return c.add(node) } +// Remove removes an node from the hash. +func (c *Consistent) Remove(nodeID proto.NodeID) (err error) { + c.Lock() + defer c.Unlock() + err = c.persist.DelNode(nodeID) + if err != nil { + log.WithField("node", nodeID).WithError(err).Error("del node failed") + return + } + + c.RemoveCache(nodeID) + return +} + +// Set sets all the nodes in the hash. If there are existing nodes not +// present in nodes, they will be removed. +func (c *Consistent) Set(nodes []proto.Node) (err error) { + c.Lock() + defer c.Unlock() + + err = c.persist.Reset() + if err != nil { + log.WithError(err).Error("reset bucket failed") + return + } + + c.ResetCache() + + for _, v := range nodes { + c.add(v) + } + + return +} + // need c.Lock() before calling func (c *Consistent) add(node proto.Node) (err error) { err = c.persist.SetNode(&node) if err != nil { - log.Errorf("set node info failed: %s", err) + log.WithField("node", node).WithError(err).Error("set node info failed") return } - return c.AddCache(node) + c.AddCache(node) + return } -// AddCache only adds c.circle skips persist -func (c *Consistent) AddCache(node proto.Node) (err error) { +// AddCache only adds c.circle skips persist. +func (c *Consistent) AddCache(node proto.Node) { + c.cacheLock.Lock() + defer c.cacheLock.Unlock() + for i := 0; i < c.NumberOfReplicas; i++ { c.circle[hashKey(c.nodeKey(node.ID, i))] = &node } @@ -158,56 +198,35 @@ func (c *Consistent) AddCache(node proto.Node) (err error) { return } -// Remove removes an node from the hash. -func (c *Consistent) Remove(node proto.NodeID) (err error) { - c.Lock() - defer c.Unlock() - return c.remove(node) -} - -// need c.Lock() before calling -func (c *Consistent) remove(nodeID proto.NodeID) (err error) { - err = c.persist.DelNode(nodeID) - if err != nil { - log.Errorf("del node failed: %s", err) - return - } +// RemoveCache removes an node from the hash cache. +func (c *Consistent) RemoveCache(nodeID proto.NodeID) { + c.cacheLock.Lock() + defer c.cacheLock.Unlock() for i := 0; i < c.NumberOfReplicas; i++ { delete(c.circle, hashKey(c.nodeKey(nodeID, i))) } c.updateSortedHashes() c.count-- - - return } -// Set sets all the nodes in the hash. If there are existing nodes not -// present in nodes, they will be removed. -func (c *Consistent) Set(nodes []proto.Node) (err error) { - c.Lock() - defer c.Unlock() - err = c.persist.Reset() - if err != nil { - log.Errorf("reset bucket failed: %s", err) - return - } +// ResetCache removes all node from the hash cache. +func (c *Consistent) ResetCache() { + c.cacheLock.Lock() + defer c.cacheLock.Unlock() c.circle = make(map[proto.NodeKey]*proto.Node) c.count = 0 c.sortedHashes = NodeKeys{} - - for _, v := range nodes { - c.add(v) - } - - return } // GetNeighbor returns an node close to where name hashes to in the circle. func (c *Consistent) GetNeighbor(name string) (proto.Node, error) { c.RLock() defer c.RUnlock() + c.cacheLock.RLock() + defer c.cacheLock.RUnlock() + if len(c.circle) == 0 { return proto.Node{}, ErrEmptyCircle } @@ -220,6 +239,9 @@ func (c *Consistent) GetNeighbor(name string) (proto.Node, error) { func (c *Consistent) GetNode(name string) (*proto.Node, error) { c.RLock() defer c.RUnlock() + c.cacheLock.RLock() + defer c.cacheLock.RUnlock() + n, ok := c.circle[hashKey(c.nodeKey(proto.NodeID(name), 0))] if ok { return n, nil @@ -243,6 +265,9 @@ func (c *Consistent) search(key proto.NodeKey) (i int) { func (c *Consistent) GetTwoNeighbors(name string) (proto.Node, proto.Node, error) { c.RLock() defer c.RUnlock() + c.cacheLock.RLock() + defer c.cacheLock.RUnlock() + if len(c.circle) == 0 { return proto.Node{}, proto.Node{}, ErrEmptyCircle } @@ -272,6 +297,8 @@ func (c *Consistent) GetTwoNeighbors(name string) (proto.Node, proto.Node, error func (c *Consistent) GetNeighborsEx(name string, n int, roles proto.ServerRoles) ([]proto.Node, error) { c.RLock() defer c.RUnlock() + c.cacheLock.RLock() + defer c.cacheLock.RUnlock() if len(c.circle) == 0 { return nil, ErrEmptyCircle diff --git a/consistent/consistent_test.go b/consistent/consistent_test.go index af0c9a1c4..8f890a7b4 100644 --- a/consistent/consistent_test.go +++ b/consistent/consistent_test.go @@ -31,10 +31,24 @@ import ( "github.com/CovenantSQL/CovenantSQL/crypto/kms" "github.com/CovenantSQL/CovenantSQL/pow/cpuminer" . "github.com/CovenantSQL/CovenantSQL/proto" + "github.com/CovenantSQL/CovenantSQL/utils/log" ) const testStorePath = "./test.store" +var o sync.Once + +func init() { + o.Do(func() { + kms.Unittest = true + os.Remove(testStorePath) + x, _ := InitConsistent(testStorePath, new(KMSStorage), false) + if x == nil { + log.Fatal("InitConsistent failed") + } + }) +} + // CheckNum make int assertion func CheckNum(num, expected int, t *testing.T) { if num != expected { @@ -42,7 +56,7 @@ func CheckNum(num, expected int, t *testing.T) { } } -func NewNodeFromID(id string) Node { +func NewNodeFromString(id string) Node { _, publicKey, _ := asymmetric.GenSecp256k1KeyPair() return Node{ ID: NodeID(id), @@ -59,7 +73,7 @@ func TestNew(t *testing.T) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) if x == nil { - t.Errorf("expected obj") + t.Error("expected obj") } } @@ -70,17 +84,17 @@ func TestAdd(t *testing.T) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID("abcdefg")) + x.Add(NewNodeFromString("0000000000000000000000000000000000000000000000000000000000000000")) CheckNum(len(x.circle), x.NumberOfReplicas, t) CheckNum(len(x.sortedHashes), x.NumberOfReplicas, t) if sort.IsSorted(x.sortedHashes) == false { - t.Errorf("expected sorted hashes to be sorted") + t.Error("expected sorted hashes to be sorted") } - x.Add(NewNodeFromID(("qwer"))) + x.Add(NewNodeFromString(("3333333333333333333333333333333333333333333333333333333333333333"))) CheckNum(len(x.circle), 2*x.NumberOfReplicas, t) CheckNum(len(x.sortedHashes), 2*x.NumberOfReplicas, t) if sort.IsSorted(x.sortedHashes) == false { - t.Errorf("expected sorted hashes to be sorted") + t.Error("expected sorted hashes to be sorted") } } @@ -91,8 +105,8 @@ func TestRemove(t *testing.T) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID("abcdefg")) - x.Remove("abcdefg") + x.Add(NewNodeFromString("0000000000000000000000000000000000000000000000000000000000000000")) + x.Remove("0000000000000000000000000000000000000000000000000000000000000000") CheckNum(len(x.circle), 0, t) CheckNum(len(x.sortedHashes), 0, t) } @@ -104,8 +118,8 @@ func TestRemoveNonExisting(t *testing.T) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID("abcdefg")) - x.Remove("abcdefghijk") + x.Add(NewNodeFromString("0000000000000000000000000000000000000000000000000000000000000000")) + x.Remove("0000000000000000000000000000000000000000000000000000000000000000hijk") CheckNum(len(x.circle), x.NumberOfReplicas, t) } @@ -118,10 +132,10 @@ func TestGetEmpty(t *testing.T) { defer os.Remove(testStorePath) _, err := x.GetNeighbor("asdfsadfsadf") if err == nil { - t.Errorf("expected error") + t.Error("expected error") } if err != ErrEmptyCircle { - t.Errorf("expected empty circle error") + t.Error("expected empty circle error") } } @@ -132,7 +146,7 @@ func TestGetSingle(t *testing.T) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID("abcdefg")) + x.Add(NewNodeFromString("0000000000000000000000000000000000000000000000000000000000000000")) f := func(s string) bool { y, err := x.GetNeighbor(s) if err != nil { @@ -140,7 +154,7 @@ func TestGetSingle(t *testing.T) { return false } //t.Logf("s = %v, y = %v", s, y) - return y.ID == "abcdefg" + return y.ID == "0000000000000000000000000000000000000000000000000000000000000000" } if err := quick.Check(f, nil); err != nil { t.Fatal(err) @@ -150,10 +164,10 @@ func TestConsistent_GetNode(t *testing.T) { kms.Unittest = true os.Remove(testStorePath) kms.ResetBucket() - nodeID := "40f26f9c816577adcb271734fec72c76" + nodeID := "40f26f9c816577adcb271734fec72c7640f26f9c816577adcb271734fec72c76" x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID(nodeID)) + x.Add(NewNodeFromString(nodeID)) f := func(s string) bool { _, err := x.GetNode(s) return err == ErrKeyNotFound @@ -176,9 +190,9 @@ type gtest struct { } var gmtests = []gtest{ - {"iiii", "abcdefg"}, - {"hhh", "opqrstu"}, - {"ggg", "abcdefg"}, + {"0000", "2222222222222222222222222222222222222222222222222222222222222222"}, + {"2222", "1111111111111111111111111111111111111111111111111111111111111111"}, + {"1111", "1111111111111111111111111111111111111111111111111111111111111111"}, } func TestGetMultiple(t *testing.T) { @@ -188,9 +202,9 @@ func TestGetMultiple(t *testing.T) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID("abcdefg")) - x.Add(NewNodeFromID("hijklmn")) - x.Add(NewNodeFromID("opqrstu")) + x.Add(NewNodeFromString("0000000000000000000000000000000000000000000000000000000000000000")) + x.Add(NewNodeFromString("1111111111111111111111111111111111111111111111111111111111111111")) + x.Add(NewNodeFromString("2222222222222222222222222222222222222222222222222222222222222222")) for i, v := range gmtests { result, err := x.GetNeighbor(v.in) if err != nil { @@ -209,9 +223,9 @@ func TestGetMultipleQuick(t *testing.T) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID("abcdefg")) - x.Add(NewNodeFromID("hijklmn")) - x.Add(NewNodeFromID("opqrstu")) + x.Add(NewNodeFromString("0000000000000000000000000000000000000000000000000000000000000000")) + x.Add(NewNodeFromString("1111111111111111111111111111111111111111111111111111111111111111")) + x.Add(NewNodeFromString("2222222222222222222222222222222222222222222222222222222222222222")) f := func(s string) bool { y, err := x.GetNeighbor(s) if err != nil { @@ -219,7 +233,7 @@ func TestGetMultipleQuick(t *testing.T) { return false } //t.Logf("s = %v, y = %v", s, y) - return y.ID == "abcdefg" || y.ID == "hijklmn" || y.ID == "opqrstu" + return y.ID == "0000000000000000000000000000000000000000000000000000000000000000" || y.ID == "1111111111111111111111111111111111111111111111111111111111111111" || y.ID == "2222222222222222222222222222222222222222222222222222222222222222" } if err := quick.Check(f, nil); err != nil { t.Fatal(err) @@ -227,15 +241,15 @@ func TestGetMultipleQuick(t *testing.T) { } var rtestsBefore = []gtest{ - {"iiii", "abcdefg"}, - {"hhh", "opqrstu"}, - {"ggg", "abcdefg"}, + {"0000", "2222222222222222222222222222222222222222222222222222222222222222"}, + {"2222", "1111111111111111111111111111111111111111111111111111111111111111"}, + {"1111", "1111111111111111111111111111111111111111111111111111111111111111"}, } var rtestsAfter = []gtest{ - {"iiii", "abcdefg"}, - {"hhh", "opqrstu"}, - {"ggg", "abcdefg"}, + {"0000", "2222222222222222222222222222222222222222222222222222222222222222"}, + {"2222", "0000000000000000000000000000000000000000000000000000000000000000"}, + {"1111", "2222222222222222222222222222222222222222222222222222222222222222"}, } func TestGetMultipleRemove(t *testing.T) { @@ -245,9 +259,9 @@ func TestGetMultipleRemove(t *testing.T) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID("abcdefg")) - x.Add(NewNodeFromID("hijklmn")) - x.Add(NewNodeFromID("opqrstu")) + x.Add(NewNodeFromString("0000000000000000000000000000000000000000000000000000000000000000")) + x.Add(NewNodeFromString("1111111111111111111111111111111111111111111111111111111111111111")) + x.Add(NewNodeFromString("2222222222222222222222222222222222222222222222222222222222222222")) for i, v := range rtestsBefore { result, err := x.GetNeighbor(v.in) if err != nil { @@ -257,7 +271,7 @@ func TestGetMultipleRemove(t *testing.T) { t.Errorf("%d. got %v, expected %v before rm", i, result, v.out) } } - x.Remove("hijklmn") + x.Remove("1111111111111111111111111111111111111111111111111111111111111111") for i, v := range rtestsAfter { result, err := x.GetNeighbor(v.in) if err != nil { @@ -276,10 +290,10 @@ func TestGetMultipleRemoveQuick(t *testing.T) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID("abcdefg")) - x.Add(NewNodeFromID("hijklmn")) - x.Add(NewNodeFromID("opqrstu")) - x.Remove(NodeID("opqrstu")) + x.Add(NewNodeFromString("0000000000000000000000000000000000000000000000000000000000000000")) + x.Add(NewNodeFromString("1111111111111111111111111111111111111111111111111111111111111111")) + x.Add(NewNodeFromString("2222222222222222222222222222222222222222222222222222222222222222")) + x.Remove(NodeID("2222222222222222222222222222222222222222222222222222222222222222")) f := func(s string) bool { y, err := x.GetNeighbor(s) if err != nil { @@ -287,7 +301,7 @@ func TestGetMultipleRemoveQuick(t *testing.T) { return false } //t.Logf("s = %v, y = %v", s, y) - return y.ID == "abcdefg" || y.ID == "hijklmn" + return y.ID == "0000000000000000000000000000000000000000000000000000000000000000" || y.ID == "1111111111111111111111111111111111111111111111111111111111111111" } if err := quick.Check(f, nil); err != nil { t.Fatal(err) @@ -301,20 +315,20 @@ func TestGetTwo(t *testing.T) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID("abcdefg")) - x.Add(NewNodeFromID("hijklmn")) - x.Add(NewNodeFromID("opqrstu")) - a, b, err := x.GetTwoNeighbors("99999999") + x.Add(NewNodeFromString("0000000000000000000000000000000000000000000000000000000000000000")) + x.Add(NewNodeFromString("1111111111111111111111111111111111111111111111111111111111111111")) + x.Add(NewNodeFromString("2222222222222222222222222222222222222222222222222222222222222222")) + a, b, err := x.GetTwoNeighbors("9999999999999999999999999999999999999999999999999999999999999999") if err != nil { t.Fatal(err) } if a.ID == b.ID { - t.Errorf("a shouldn't equal b") + t.Error("a shouldn't equal b") } - if a.ID != "abcdefg" { + if a.ID != "0000000000000000000000000000000000000000000000000000000000000000" { t.Errorf("wrong a: %v", a) } - if b.ID != "opqrstu" { + if b.ID != "1111111111111111111111111111111111111111111111111111111111111111" { t.Errorf("wrong b: %v", b) } } @@ -326,7 +340,7 @@ func TestGetTwoEmpty(t *testing.T) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - _, _, err := x.GetTwoNeighbors("9999999") + _, _, err := x.GetTwoNeighbors("9999999999999999999999999999999999999999999999999999999999999999") if err != ErrEmptyCircle { t.Fatal(err) } @@ -339,9 +353,9 @@ func TestGetTwoQuick(t *testing.T) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID("abcdefg")) - x.Add(NewNodeFromID("hijklmn")) - x.Add(NewNodeFromID("opqrstu")) + x.Add(NewNodeFromString("0000000000000000000000000000000000000000000000000000000000000000")) + x.Add(NewNodeFromString("1111111111111111111111111111111111111111111111111111111111111111")) + x.Add(NewNodeFromString("2222222222222222222222222222222222222222222222222222222222222222")) f := func(s string) bool { a, b, err := x.GetTwoNeighbors(s) if err != nil { @@ -349,15 +363,15 @@ func TestGetTwoQuick(t *testing.T) { return false } if a.ID == b.ID { - t.Logf("a.ID == b.ID") + t.Log("a.ID == b.ID") return false } - if a.ID != "abcdefg" && a.ID != "hijklmn" && a.ID != "opqrstu" { + if a.ID != "0000000000000000000000000000000000000000000000000000000000000000" && a.ID != "1111111111111111111111111111111111111111111111111111111111111111" && a.ID != "2222222222222222222222222222222222222222222222222222222222222222" { t.Logf("invalid a: %v", a) return false } - if b.ID != "abcdefg" && b.ID != "hijklmn" && b.ID != "opqrstu" { + if b.ID != "0000000000000000000000000000000000000000000000000000000000000000" && b.ID != "1111111111111111111111111111111111111111111111111111111111111111" && b.ID != "2222222222222222222222222222222222222222222222222222222222222222" { t.Logf("invalid b: %v", b) return false } @@ -375,8 +389,8 @@ func TestGetTwoOnlyTwoQuick(t *testing.T) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID("abcdefg")) - x.Add(NewNodeFromID("hijklmn")) + x.Add(NewNodeFromString("0000000000000000000000000000000000000000000000000000000000000000")) + x.Add(NewNodeFromString("1111111111111111111111111111111111111111111111111111111111111111")) f := func(s string) bool { a, b, err := x.GetTwoNeighbors(s) if err != nil { @@ -384,15 +398,15 @@ func TestGetTwoOnlyTwoQuick(t *testing.T) { return false } if a.ID == b.ID { - t.Logf("a.ID == b.ID") + t.Log("a.ID == b.ID") return false } - if a.ID != "abcdefg" && a.ID != "hijklmn" { + if a.ID != "0000000000000000000000000000000000000000000000000000000000000000" && a.ID != "1111111111111111111111111111111111111111111111111111111111111111" { t.Logf("invalid a: %v", a) return false } - if b.ID != "abcdefg" && b.ID != "hijklmn" { + if b.ID != "0000000000000000000000000000000000000000000000000000000000000000" && b.ID != "1111111111111111111111111111111111111111111111111111111111111111" { t.Logf("invalid b: %v", b) return false } @@ -410,15 +424,15 @@ func TestGetTwoOnlyOneInCircle(t *testing.T) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID("abcdefg")) - a, b, err := x.GetTwoNeighbors("99999999") + x.Add(NewNodeFromString("0000000000000000000000000000000000000000000000000000000000000000")) + a, b, err := x.GetTwoNeighbors("9999999999999999999999999999999999999999999999999999999999999999") if err != nil { t.Fatal(err) } if a.ID == b.ID { - t.Errorf("a shouldn't equal b") + t.Error("a shouldn't equal b") } - if a.ID != "abcdefg" { + if a.ID != "0000000000000000000000000000000000000000000000000000000000000000" { t.Errorf("wrong a: %v", a) } if b.ID != "" { @@ -433,24 +447,24 @@ func TestGetN(t *testing.T) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID("abcdefg")) - x.Add(NewNodeFromID("hijklmn")) - x.Add(NewNodeFromID("opqrstu")) + x.Add(NewNodeFromString("0000000000000000000000000000000000000000000000000000000000000000")) + x.Add(NewNodeFromString("1111111111111111111111111111111111111111111111111111111111111111")) + x.Add(NewNodeFromString("2222222222222222222222222222222222222222222222222222222222222222")) members, err := x.GetNeighbors("9999999", 3) - //members, err := x.GetNeighbors("abcdefg", 3) + //members, err := x.GetNeighbors("0000000000000000000000000000000000000000000000000000000000000000", 3) if err != nil { t.Fatal(err) } if len(members) != 3 { t.Errorf("expected 3 members instead of %d", len(members)) } - if members[0].ID != "opqrstu" { + if members[0].ID != "0000000000000000000000000000000000000000000000000000000000000000" { t.Errorf("wrong members[0]: %v", members[0]) } - if members[1].ID != "hijklmn" { + if members[1].ID != "2222222222222222222222222222222222222222222222222222222222222222" { t.Errorf("wrong members[1]: %v", members[1]) } - if members[2].ID != "abcdefg" { + if members[2].ID != "1111111111111111111111111111111111111111111111111111111111111111" { t.Errorf("wrong members[2]: %v", members[2]) } } @@ -462,11 +476,11 @@ func TestGetNFilterRole(t *testing.T) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - n := NewNodeFromID("abcdefg") + n := NewNodeFromString("0000000000000000000000000000000000000000000000000000000000000000") n.Role = Leader x.Add(n) - x.Add(NewNodeFromID("hijklmn")) - x.Add(NewNodeFromID("opqrstu")) + x.Add(NewNodeFromString("1111111111111111111111111111111111111111111111111111111111111111")) + x.Add(NewNodeFromString("2222222222222222222222222222222222222222222222222222222222222222")) members, err := x.GetNeighborsEx("9999999", 3, ServerRoles{Unknown}) if err != nil { t.Fatal(err) @@ -474,10 +488,10 @@ func TestGetNFilterRole(t *testing.T) { if len(members) != 2 { t.Errorf("expected 2 members instead of %d", len(members)) } - if members[0].ID != "opqrstu" { + if members[0].ID != "2222222222222222222222222222222222222222222222222222222222222222" { t.Errorf("wrong members[0]: %v", members[0]) } - if members[1].ID != "hijklmn" { + if members[1].ID != "1111111111111111111111111111111111111111111111111111111111111111" { t.Errorf("wrong members[1]: %v", members[1]) } @@ -488,7 +502,7 @@ func TestGetNFilterRole(t *testing.T) { if len(members) != 1 { t.Errorf("expected 1 members instead of %d", len(members)) } - if members[0].ID != "abcdefg" { + if members[0].ID != "0000000000000000000000000000000000000000000000000000000000000000" { t.Errorf("wrong members[0]: %v", members[0]) } } @@ -500,20 +514,20 @@ func TestGetNLess(t *testing.T) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID("abcdefg")) - x.Add(NewNodeFromID("hijklmn")) - x.Add(NewNodeFromID("opqrstu")) - members, err := x.GetNeighbors("99999999", 2) + x.Add(NewNodeFromString("0000000000000000000000000000000000000000000000000000000000000000")) + x.Add(NewNodeFromString("1111111111111111111111111111111111111111111111111111111111111111")) + x.Add(NewNodeFromString("2222222222222222222222222222222222222222222222222222222222222222")) + members, err := x.GetNeighbors("9999999999999999999999999999999999999999999999999999999999999999", 2) if err != nil { t.Fatal(err) } if len(members) != 2 { t.Errorf("expected 2 members instead of %d", len(members)) } - if members[0].ID != "abcdefg" { + if members[0].ID != "0000000000000000000000000000000000000000000000000000000000000000" { t.Errorf("wrong members[0]: %v", members[0]) } - if members[1].ID != "opqrstu" { + if members[1].ID != "1111111111111111111111111111111111111111111111111111111111111111" { t.Errorf("wrong members[1]: %v", members[1]) } } @@ -525,9 +539,9 @@ func TestGetNMore(t *testing.T) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID("abcdefg")) - x.Add(NewNodeFromID("hijklmn")) - x.Add(NewNodeFromID("opqrstu")) + x.Add(NewNodeFromString("0000000000000000000000000000000000000000000000000000000000000000")) + x.Add(NewNodeFromString("1111111111111111111111111111111111111111111111111111111111111111")) + x.Add(NewNodeFromString("2222222222222222222222222222222222222222222222222222222222222222")) members, err := x.GetNeighbors("9999999", 5) if err != nil { t.Fatal(err) @@ -535,13 +549,13 @@ func TestGetNMore(t *testing.T) { if len(members) != 3 { t.Errorf("expected 3 members instead of %d", len(members)) } - if members[0].ID != "opqrstu" { + if members[0].ID != "0000000000000000000000000000000000000000000000000000000000000000" { t.Errorf("wrong members[0]: %v", members[0]) } - if members[1].ID != "hijklmn" { + if members[1].ID != "2222222222222222222222222222222222222222222222222222222222222222" { t.Errorf("wrong members[1]: %v", members[1]) } - if members[2].ID != "abcdefg" { + if members[2].ID != "1111111111111111111111111111111111111111111111111111111111111111" { t.Errorf("wrong members[2]: %v", members[2]) } } @@ -569,9 +583,9 @@ func TestGetNQuick(t *testing.T) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID("abcdefg")) - x.Add(NewNodeFromID("hijklmn")) - x.Add(NewNodeFromID("opqrstu")) + x.Add(NewNodeFromString("0000000000000000000000000000000000000000000000000000000000000000")) + x.Add(NewNodeFromString("1111111111111111111111111111111111111111111111111111111111111111")) + x.Add(NewNodeFromString("2222222222222222222222222222222222222222222222222222222222222222")) f := func(s string) bool { members, err := x.GetNeighbors(s, 3) if err != nil { @@ -585,11 +599,11 @@ func TestGetNQuick(t *testing.T) { set := make(map[NodeID]Node, 4) for _, member := range members { if set[member.ID].ID != "" { - t.Logf("duplicate error") + t.Log("duplicate error") return false } set[member.ID] = Node{} - if member.ID != "abcdefg" && member.ID != "hijklmn" && member.ID != "opqrstu" { + if member.ID != "0000000000000000000000000000000000000000000000000000000000000000" && member.ID != "1111111111111111111111111111111111111111111111111111111111111111" && member.ID != "2222222222222222222222222222222222222222222222222222222222222222" { t.Logf("invalid member: %v", member) return false } @@ -608,9 +622,9 @@ func TestGetNLessQuick(t *testing.T) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID("abcdefg")) - x.Add(NewNodeFromID("hijklmn")) - x.Add(NewNodeFromID("opqrstu")) + x.Add(NewNodeFromString("0000000000000000000000000000000000000000000000000000000000000000")) + x.Add(NewNodeFromString("1111111111111111111111111111111111111111111111111111111111111111")) + x.Add(NewNodeFromString("2222222222222222222222222222222222222222222222222222222222222222")) f := func(s string) bool { members, err := x.GetNeighbors(s, 2) if err != nil { @@ -624,11 +638,11 @@ func TestGetNLessQuick(t *testing.T) { set := make(map[NodeID]Node, 4) for _, member := range members { if set[member.ID].ID != "" { - t.Logf("duplicate error") + t.Log("duplicate error") return false } set[member.ID] = Node{} - if member.ID != "abcdefg" && member.ID != "hijklmn" && member.ID != "opqrstu" { + if member.ID != "0000000000000000000000000000000000000000000000000000000000000000" && member.ID != "1111111111111111111111111111111111111111111111111111111111111111" && member.ID != "2222222222222222222222222222222222222222222222222222222222222222" { t.Logf("invalid member: %v", member) return false } @@ -647,9 +661,9 @@ func TestGetNMoreQuick(t *testing.T) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID("abcdefg")) - x.Add(NewNodeFromID("hijklmn")) - x.Add(NewNodeFromID("opqrstu")) + x.Add(NewNodeFromString("0000000000000000000000000000000000000000000000000000000000000000")) + x.Add(NewNodeFromString("1111111111111111111111111111111111111111111111111111111111111111")) + x.Add(NewNodeFromString("2222222222222222222222222222222222222222222222222222222222222222")) f := func(s string) bool { members, err := x.GetNeighbors(s, 5) if err != nil { @@ -663,11 +677,11 @@ func TestGetNMoreQuick(t *testing.T) { set := make(map[NodeID]Node, 4) for _, member := range members { if set[member.ID].ID != "" { - t.Logf("duplicate error") + t.Log("duplicate error") return false } set[member.ID] = Node{} - if member.ID != "abcdefg" && member.ID != "hijklmn" && member.ID != "opqrstu" { + if member.ID != "0000000000000000000000000000000000000000000000000000000000000000" && member.ID != "1111111111111111111111111111111111111111111111111111111111111111" && member.ID != "2222222222222222222222222222222222222222222222222222222222222222" { t.Logf("invalid member: %v", member) return false } @@ -686,57 +700,57 @@ func TestSet(t *testing.T) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID("abc")) - x.Add(NewNodeFromID("def")) - x.Add(NewNodeFromID("ghi")) + x.Add(NewNodeFromString("0000")) + x.Add(NewNodeFromString("1111")) + x.Add(NewNodeFromString("2222")) - x.Set([]Node{NewNodeFromID("jkl"), NewNodeFromID("mno")}) + x.Set([]Node{NewNodeFromString("3333"), NewNodeFromString("4444")}) if x.count != 2 { t.Errorf("expected 2 elts, got %d", x.count) } - a, b, err := x.GetTwoNeighbors("qwerqwerwqer") + a, b, err := x.GetTwoNeighbors("33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333wqer") if err != nil { t.Fatal(err) } - if a.ID != "jkl" && a.ID != "mno" { - t.Errorf("expected jkl or mno, got %v", a) + if a.ID != "3333" && a.ID != "4444" { + t.Errorf("expected 3333 or 4444, got %v", a) } - if b.ID != "jkl" && b.ID != "mno" { - t.Errorf("expected jkl or mno, got %v", b) + if b.ID != "3333" && b.ID != "4444" { + t.Errorf("expected 3333 or 4444, got %v", b) } if a.ID == b.ID { t.Errorf("expected a != b, they were both %v", a) } - x.Set([]Node{NewNodeFromID("pqr"), NewNodeFromID("mno")}) + x.Set([]Node{NewNodeFromString("5555"), NewNodeFromString("4444")}) if x.count != 2 { t.Errorf("expected 2 elts, got %d", x.count) } - a, b, err = x.GetTwoNeighbors("qwerqwerwqer") + a, b, err = x.GetTwoNeighbors("33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333wqer") if err != nil { t.Fatal(err) } - if a.ID != "pqr" && a.ID != "mno" { - t.Errorf("expected jkl or mno, got %v", a) + if a.ID != "5555" && a.ID != "4444" { + t.Errorf("expected 3333 or 4444, got %v", a) } - if b.ID != "pqr" && b.ID != "mno" { - t.Errorf("expected jkl or mno, got %v", b) + if b.ID != "5555" && b.ID != "4444" { + t.Errorf("expected 3333 or 4444, got %v", b) } if a.ID == b.ID { t.Errorf("expected a != b, they were both %v", a) } - x.Set([]Node{NewNodeFromID("pqr"), NewNodeFromID("mno")}) + x.Set([]Node{NewNodeFromString("5555"), NewNodeFromString("4444")}) if x.count != 2 { t.Errorf("expected 2 elts, got %d", x.count) } - a, b, err = x.GetTwoNeighbors("qwerqwerwqer") + a, b, err = x.GetTwoNeighbors("33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333wqer") if err != nil { t.Fatal(err) } - if a.ID != "pqr" && a.ID != "mno" { - t.Errorf("expected jkl or mno, got %v", a) + if a.ID != "5555" && a.ID != "4444" { + t.Errorf("expected 3333 or 4444, got %v", a) } - if b.ID != "pqr" && b.ID != "mno" { - t.Errorf("expected jkl or mno, got %v", b) + if b.ID != "5555" && b.ID != "4444" { + t.Errorf("expected 3333 or 4444, got %v", b) } if a.ID == b.ID { t.Errorf("expected a != b, they were both %v", a) @@ -769,11 +783,11 @@ func BenchmarkAllocations(b *testing.B) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID("stays")) + x.Add(NewNodeFromString("stays")) b.ResetTimer() allocSize := allocBytes(func() { for i := 0; i < b.N; i++ { - x.Add(NewNodeFromID("Foo")) + x.Add(NewNodeFromString("Foo")) x.Remove(NodeID("Foo")) } }) @@ -787,11 +801,11 @@ func BenchmarkMalloc(b *testing.B) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID("stays")) + x.Add(NewNodeFromString("stays")) b.ResetTimer() mallocs := mallocNum(func() { for i := 0; i < b.N; i++ { - x.Add(NewNodeFromID("Foo")) + x.Add(NewNodeFromString("Foo")) x.Remove(NodeID("Foo")) } }) @@ -805,10 +819,10 @@ func BenchmarkCycle(b *testing.B) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID("nothing")) + x.Add(NewNodeFromString("nothing")) b.ResetTimer() for i := 0; i < b.N; i++ { - x.Add(NewNodeFromID("foo" + strconv.Itoa(i))) + x.Add(NewNodeFromString("foo" + strconv.Itoa(i))) x.Remove(NodeID("foo" + strconv.Itoa(i))) } } @@ -821,11 +835,11 @@ func BenchmarkCycleLarge(b *testing.B) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) for i := 0; i < 10; i++ { - x.Add(NewNodeFromID("start" + strconv.Itoa(i))) + x.Add(NewNodeFromString("start" + strconv.Itoa(i))) } b.ResetTimer() for i := 0; i < b.N; i++ { - x.Add(NewNodeFromID("foo" + strconv.Itoa(i))) + x.Add(NewNodeFromString("foo" + strconv.Itoa(i))) x.Remove(NodeID("foo" + strconv.Itoa(i))) } } @@ -837,7 +851,7 @@ func BenchmarkGet(b *testing.B) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID("nothing")) + x.Add(NewNodeFromString("nothing")) b.ResetTimer() for i := 0; i < b.N; i++ { x.GetNeighbor("nothing") @@ -852,7 +866,7 @@ func BenchmarkGetLarge(b *testing.B) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) for i := 0; i < 10; i++ { - x.Add(NewNodeFromID("start" + strconv.Itoa(i))) + x.Add(NewNodeFromString("start" + strconv.Itoa(i))) } b.ResetTimer() for i := 0; i < b.N; i++ { @@ -867,7 +881,7 @@ func BenchmarkGetN(b *testing.B) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID("nothing")) + x.Add(NewNodeFromString("nothing")) b.ResetTimer() for i := 0; i < b.N; i++ { x.GetNeighbors("nothing", 3) @@ -882,7 +896,7 @@ func BenchmarkGetNLarge(b *testing.B) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) for i := 0; i < 10; i++ { - x.Add(NewNodeFromID("start" + strconv.Itoa(i))) + x.Add(NewNodeFromString("start" + strconv.Itoa(i))) } b.ResetTimer() for i := 0; i < b.N; i++ { @@ -897,7 +911,7 @@ func BenchmarkGetTwo(b *testing.B) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID("nothing")) + x.Add(NewNodeFromString("nothing")) b.ResetTimer() for i := 0; i < b.N; i++ { x.GetTwoNeighbors("nothing") @@ -912,7 +926,7 @@ func BenchmarkGetTwoLarge(b *testing.B) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) for i := 0; i < 10; i++ { - x.Add(NewNodeFromID("start" + strconv.Itoa(i))) + x.Add(NewNodeFromString("start" + strconv.Itoa(i))) } b.ResetTimer() for i := 0; i < b.N; i++ { @@ -924,17 +938,17 @@ func BenchmarkGetTwoLarge(b *testing.B) { func TestAddCollision(t *testing.T) { // These two strings produce several crc32 collisions after "|i" is // appended added by Consistent.eltKey. - const s1 = "abear" - const s2 = "solidiform" + const s1 = "111111" + const s2 = "222222" kms.Unittest = true os.Remove(testStorePath) kms.ResetBucket() x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Add(NewNodeFromID(s1)) - x.Add(NewNodeFromID(s2)) - elt1, err := x.GetNeighbor("abear") + x.Add(NewNodeFromString(s1)) + x.Add(NewNodeFromString(s2)) + elt1, err := x.GetNeighbor("111111") if err != nil { t.Fatal("unexpected error:", err) } @@ -942,8 +956,8 @@ func TestAddCollision(t *testing.T) { y, _ := InitConsistent(testStorePath+"2", new(KMSStorage), false) defer os.Remove(testStorePath + "2") // add elements in opposite order - y.Add(NewNodeFromID(s2)) - y.Add(NewNodeFromID(s1)) + y.Add(NewNodeFromString(s2)) + y.Add(NewNodeFromString(s1)) elt2, err := y.GetNeighbor(s1) if err != nil { t.Fatal("unexpected error:", err) @@ -961,16 +975,16 @@ func TestConcurrentGetSet(t *testing.T) { x, _ := InitConsistent(testStorePath, new(KMSStorage), false) defer os.Remove(testStorePath) - x.Set([]Node{NewNodeFromID("abc"), NewNodeFromID("def"), NewNodeFromID("ghi"), NewNodeFromID("jkl"), NewNodeFromID("mno")}) + x.Set([]Node{NewNodeFromString("0000"), NewNodeFromString("1111"), NewNodeFromString("2222"), NewNodeFromString("3333"), NewNodeFromString("4444")}) var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.Add(1) go func() { for i := 0; i < 100; i++ { - x.Set([]Node{NewNodeFromID("abc"), NewNodeFromID("def"), NewNodeFromID("ghi"), NewNodeFromID("jkl"), NewNodeFromID("mno")}) + x.Set([]Node{NewNodeFromString("0000"), NewNodeFromString("1111"), NewNodeFromString("2222"), NewNodeFromString("3333"), NewNodeFromString("4444")}) time.Sleep(time.Duration(rand.Intn(10)) * time.Millisecond) - x.Set([]Node{NewNodeFromID("pqr"), NewNodeFromID("stu"), NewNodeFromID("vwx")}) + x.Set([]Node{NewNodeFromString("5555"), NewNodeFromString("6666"), NewNodeFromString("7777")}) time.Sleep(time.Duration(rand.Intn(10)) * time.Millisecond) } wg.Done() @@ -981,12 +995,12 @@ func TestConcurrentGetSet(t *testing.T) { wg.Add(1) go func() { for i := 0; i < 100; i++ { - a, err := x.GetNeighbor("xxxxxxx") + a, err := x.GetNeighbor("111111") if err != nil { t.Error(err) } - if a.ID != "jkl" && a.ID != "vwx" { - t.Errorf("got %v, expected vwx", a) + if a.ID != "5555" && a.ID != "3333" { + t.Errorf("got %v, expected 5555 or 3333", a) } time.Sleep(time.Duration(rand.Intn(10)) * time.Millisecond) } diff --git a/consistent/load_test.go b/consistent/load_test.go index aeda95752..a85073b84 100644 --- a/consistent/load_test.go +++ b/consistent/load_test.go @@ -37,8 +37,8 @@ func TestSaveDHT(t *testing.T) { Convey("save DHT", t, func() { x, _ := InitConsistent(testStorePath1, new(KMSStorage), false) - x.Add(NewNodeFromID("abcdefg")) - x.Add(NewNodeFromID(("qwer"))) + x.Add(NewNodeFromString("111111")) + x.Add(NewNodeFromString(("3333"))) So(len(x.circle), ShouldEqual, x.NumberOfReplicas*2) So(len(x.sortedHashes), ShouldEqual, x.NumberOfReplicas*2) So(sort.IsSorted(x.sortedHashes), ShouldBeTrue) diff --git a/consistent/persistence.go b/consistent/persistence.go index 90529e98e..8a9bb3a9c 100644 --- a/consistent/persistence.go +++ b/consistent/persistence.go @@ -58,7 +58,7 @@ func (s *KMSStorage) Reset() (err error) { func (s *KMSStorage) GetAllNodeInfo() (nodes []proto.Node, err error) { IDs, err := kms.GetAllNodeID() if err != nil { - log.Errorf("get all node id failed: %s", err) + log.WithError(err).Error("get all node id failed") return } nodes = make([]proto.Node, 0, len(IDs)) @@ -67,7 +67,7 @@ func (s *KMSStorage) GetAllNodeInfo() (nodes []proto.Node, err error) { node, err := kms.GetNodeInfo(id) if err != nil { // this may happen, just continue - log.Errorf("get node info for %s failed: %s", id, err) + log.WithField("node", node).WithError(err).Error("get node info failed") continue } nodes = append(nodes, *node) diff --git a/crypto/asymmetric/keypair.go b/crypto/asymmetric/keypair.go index d563b4a18..2f78a5d93 100644 --- a/crypto/asymmetric/keypair.go +++ b/crypto/asymmetric/keypair.go @@ -21,6 +21,7 @@ import ( "encoding/hex" "fmt" "math/big" + "sync" "time" mine "github.com/CovenantSQL/CovenantSQL/pow/cpuminer" @@ -32,6 +33,8 @@ import ( // PrivateKeyBytesLen defines the length in bytes of a serialized private key. const PrivateKeyBytesLen = 32 +var parsedPublicKeyCache sync.Map + // PrivateKey wraps an ec.PrivateKey as a convenience mainly for signing things with the the // private key without having to directly import the ecdsa package. type PrivateKey ec.PrivateKey @@ -58,9 +61,15 @@ func (k *PublicKey) MarshalBinary() (keyBytes []byte, err error) { // UnmarshalBinary does the deserialization func (k *PublicKey) UnmarshalBinary(keyBytes []byte) (err error) { - pubNew, err := ParsePubKey(keyBytes) - if err == nil { - *k = *pubNew + pubKeyI, ok := parsedPublicKeyCache.Load(string(keyBytes)) + if ok { + *k = *pubKeyI.(*PublicKey) + } else { + pubNew, err := ParsePubKey(keyBytes) + if err == nil { + *k = *pubNew + parsedPublicKeyCache.Store(string(keyBytes), pubNew) + } } return } @@ -158,7 +167,7 @@ func GenSecp256k1KeyPair() ( privateKeyEc, err := ec.NewPrivateKey(ec.S256()) if err != nil { - log.Errorf("private key generation error: %s", err) + log.WithError(err).Error("private key generation failed") return nil, nil, err } publicKey = (*PublicKey)(privateKeyEc.PubKey()) diff --git a/crypto/asymmetric/keypair_test.go b/crypto/asymmetric/keypair_test.go index ead4e40bf..34f95c230 100644 --- a/crypto/asymmetric/keypair_test.go +++ b/crypto/asymmetric/keypair_test.go @@ -20,7 +20,6 @@ import ( "bytes" "strings" "testing" - "time" "github.com/CovenantSQL/CovenantSQL/utils/log" @@ -142,7 +141,7 @@ func TestPubKey(t *testing.T) { } func TestPublicKey_MarshalBinary(t *testing.T) { - Convey("marshal unmarshal key", t, func() { + Convey("marshal unmarshal public key", t, func() { _, publicKey, _ := GenSecp256k1KeyPair() publicKey2 := new(PublicKey) buf, _ := publicKey.MarshalBinary() @@ -150,13 +149,40 @@ func TestPublicKey_MarshalBinary(t *testing.T) { So(publicKey.IsEqual(publicKey2), ShouldBeTrue) + publicKey3 := new(PublicKey) + publicKey3.UnmarshalBinary(buf) + buf1, _ := publicKey.MarshalHash() buf2, _ := publicKey2.MarshalHash() + buf3, _ := publicKey3.MarshalHash() + So(buf1, ShouldResemble, buf2) + So(buf1, ShouldResemble, buf3) So(publicKey.Msgsize(), ShouldEqual, publicKey2.Msgsize()) }) } +func TestPrivateKey_Serialize(t *testing.T) { + Convey("marshal unmarshal private key", t, func() { + pk, _, _ := GenSecp256k1KeyPair() + buf := pk.Serialize() + priv2, pub2 := PrivKeyFromBytes(buf) + + So(priv2.PubKey().IsEqual(pub2), ShouldBeTrue) + }) +} + +func TestPaddedAppend(t *testing.T) { + Convey("paddedAppend", t, func() { + src := []byte("aaaa") + dst := make([]byte, 0, 16) + dst = paddedAppend(16, dst, src) + + So(len(dst), ShouldEqual, 16) + So(dst, ShouldResemble, append([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, src...)) + }) +} + func unmarshalAndMarshal(str string) string { var key PublicKey yaml.Unmarshal([]byte(str), &key) diff --git a/crypto/asymmetric/signature.go b/crypto/asymmetric/signature.go index 19d9b310a..77ac14580 100644 --- a/crypto/asymmetric/signature.go +++ b/crypto/asymmetric/signature.go @@ -20,7 +20,6 @@ import ( "crypto/elliptic" "errors" "math/big" - "sync" "github.com/CovenantSQL/CovenantSQL/crypto/secp256k1" diff --git a/crypto/etls/conn.go b/crypto/etls/conn.go index 4820cfadb..fe471adfc 100644 --- a/crypto/etls/conn.go +++ b/crypto/etls/conn.go @@ -49,7 +49,7 @@ func NewConn(c net.Conn, cipher *Cipher, nodeID *proto.RawNodeID) *CryptoConn { func Dial(network, address string, cipher *Cipher) (c *CryptoConn, err error) { conn, err := net.Dial(network, address) if err != nil { - log.Errorf("connect to %s failed: %s", address, err) + log.WithField("addr", address).WithError(err).Error("connect failed") return } @@ -67,7 +67,7 @@ func (c *CryptoConn) Read(b []byte) (n int, err error) { if c.decStream == nil { iv := make([]byte, c.info.ivLen) if _, err = io.ReadFull(c.Conn, iv); err != nil { - log.Infof("ReadFull failed: %s", err) + log.WithError(err).Info("read full failed") return } if err = c.initDecrypt(iv); err != nil { @@ -82,7 +82,6 @@ func (c *CryptoConn) Read(b []byte) (n int, err error) { n, err = c.Conn.Read(cipherData) if err != nil { - log.Debugf("Read got: %s", err) return } if n > 0 { diff --git a/crypto/etls/conn_test.go b/crypto/etls/conn_test.go index a76d0bcda..e9aa09224 100644 --- a/crypto/etls/conn_test.go +++ b/crypto/etls/conn_test.go @@ -35,7 +35,7 @@ type Result struct { func (f *Foo) Bar(args *string, res *Result) error { res.Data = len(*args) log.Printf("Received %q, its length is %d", *args, res.Data) - //return fmt.Errorf("Whoops, error happened") + //return fmt.Error("Whoops, error happened") return nil } diff --git a/crypto/etls/encrypt_test.go b/crypto/etls/encrypt_test.go index 9c98b47c2..129ccf94c 100644 --- a/crypto/etls/encrypt_test.go +++ b/crypto/etls/encrypt_test.go @@ -17,9 +17,8 @@ package etls import ( - "testing" - "bytes" + "testing" "github.com/CovenantSQL/CovenantSQL/crypto/hash" . "github.com/smartystreets/goconvey/convey" diff --git a/crypto/hash/hash.go b/crypto/hash/hash.go index a9ae982b2..8108e9f3e 100644 --- a/crypto/hash/hash.go +++ b/crypto/hash/hash.go @@ -127,7 +127,7 @@ func (h *Hash) UnmarshalYAML(unmarshal func(interface{}) error) error { // load hash err := Decode(h, str) if err != nil { - log.Errorf("Error in UnmarshalYAML: %v", err) + log.WithError(err).Error("unmarshal YAML failed") return err } return nil diff --git a/crypto/hash/hash_test.go b/crypto/hash/hash_test.go index 2811a3bfd..0ef77d42b 100644 --- a/crypto/hash/hash_test.go +++ b/crypto/hash/hash_test.go @@ -101,14 +101,14 @@ func TestHash(t *testing.T) { // Invalid size for SetBytes. err = hash.SetBytes([]byte{0x00}) if err == nil { - t.Errorf("SetBytes: failed to received expected err - got: nil") + t.Error("SetBytes: failed to received expected err - got: nil") } // Invalid size for NewHash. invalidHash := make([]byte, HashSize+1) _, err = NewHash(invalidHash) if err == nil { - t.Errorf("NewHash: failed to received expected err - got: nil") + t.Error("NewHash: failed to received expected err - got: nil") } } diff --git a/crypto/hash/hashfuncs.go b/crypto/hash/hashfuncs.go index ba3d16caf..6235c4964 100644 --- a/crypto/hash/hashfuncs.go +++ b/crypto/hash/hashfuncs.go @@ -19,11 +19,9 @@ package hash import ( "encoding/binary" "hash/fnv" - // "crypto/sha256" benchmark is at least 10% faster on // i7-4870HQ CPU @ 2.50GHz than "github.com/minio/sha256-simd" "crypto/sha256" - // "minio/blake2b-simd" benchmark is at least 3% faster on // i7-4870HQ CPU @ 2.50GHz than "golang.org/x/crypto/blake2b" // and supports more CPU instructions diff --git a/crypto/kms/privatekeystore.go b/crypto/kms/privatekeystore.go index fb2bcfb34..ef4daf926 100644 --- a/crypto/kms/privatekeystore.go +++ b/crypto/kms/privatekeystore.go @@ -41,20 +41,22 @@ var ( func LoadPrivateKey(keyFilePath string, masterKey []byte) (key *asymmetric.PrivateKey, err error) { fileContent, err := ioutil.ReadFile(keyFilePath) if err != nil { - log.Errorf("error read key file: %s, err: %s", keyFilePath, err) + log.WithField("path", keyFilePath).WithError(err).Error("read key file failed") return } decData, err := symmetric.DecryptWithPassword(fileContent, masterKey) if err != nil { - log.Errorf("decrypt private key error") + log.Error("decrypt private key error") return } // sha256 + privateKey if len(decData) != hash.HashBSize+asymmetric.PrivateKeyBytesLen { - log.Errorf("private key file size should be %d bytes", - hash.HashBSize+asymmetric.PrivateKeyBytesLen) + log.WithFields(log.Fields{ + "expected": hash.HashBSize + asymmetric.PrivateKeyBytesLen, + "actual": len(decData), + }).Error("wrong private key file size") return nil, ErrNotKeyFile } @@ -87,33 +89,33 @@ func InitLocalKeyPair(privateKeyPath string, masterKey []byte) (err error) { initLocalKeyStore() privateKey, err = LoadPrivateKey(privateKeyPath, masterKey) if err != nil { - log.Infof("load private key failed: %s", err) + log.WithError(err).Info("load private key failed") if err == ErrNotKeyFile { - log.Errorf("not a valid private key file: %s", privateKeyPath) + log.WithField("path", privateKeyPath).Error("not a valid private key file") return } if _, ok := err.(*os.PathError); (ok || err == os.ErrNotExist) && conf.GConf.GenerateKeyPair { log.Info("private key file not exist, generating one") privateKey, publicKey, err = asymmetric.GenSecp256k1KeyPair() if err != nil { - log.Errorf("generate private key failed: %s", err) + log.WithError(err).Error("generate private key failed") return } - log.Infof("saving new private key file: %s", privateKeyPath) + log.WithField("path", privateKeyPath).Info("saving new private key file") err = SavePrivateKey(privateKeyPath, privateKey, masterKey) if err != nil { - log.Errorf("save private key failed: %s", err) + log.WithError(err).Error("save private key failed") return } } else { - log.Errorf("unexpected error while loading private key: %s", err) + log.WithError(err).Error("unexpected error while loading private key") return } } if publicKey == nil { publicKey = privateKey.PubKey() } - log.Debugf("\n### Public Key ###\n%x\n### Public Key ###\n", publicKey.Serialize()) + log.Debugf("\n### Public Key ###\n%#x\n### Public Key ###\n", publicKey.Serialize()) SetLocalKeyPair(privateKey, publicKey) return } diff --git a/crypto/kms/privatekeystore_test.go b/crypto/kms/privatekeystore_test.go index 44682c76f..0485552af 100644 --- a/crypto/kms/privatekeystore_test.go +++ b/crypto/kms/privatekeystore_test.go @@ -17,14 +17,11 @@ package kms import ( + "bytes" "encoding/hex" - "testing" - - "os" - "io/ioutil" - - "bytes" + "os" + "testing" "github.com/CovenantSQL/CovenantSQL/conf" "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" diff --git a/crypto/kms/pubkeystore.go b/crypto/kms/pubkeystore.go index 7a952605a..0c3e15e6f 100644 --- a/crypto/kms/pubkeystore.go +++ b/crypto/kms/pubkeystore.go @@ -17,7 +17,6 @@ package kms import ( - "bytes" "errors" "os" "path/filepath" @@ -26,14 +25,13 @@ import ( "sync" "github.com/CovenantSQL/CovenantSQL/conf" - "github.com/CovenantSQL/CovenantSQL/utils/log" - "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" "github.com/CovenantSQL/CovenantSQL/crypto/hash" mine "github.com/CovenantSQL/CovenantSQL/pow/cpuminer" "github.com/CovenantSQL/CovenantSQL/proto" + "github.com/CovenantSQL/CovenantSQL/utils" + "github.com/CovenantSQL/CovenantSQL/utils/log" "github.com/coreos/bbolt" - "github.com/ugorji/go/codec" ) // PublicKeyStore holds db and bucket name @@ -69,13 +67,13 @@ func init() { strings.HasPrefix(filepath.Base(os.Args[0]), "___") { _, testFile, _, _ := runtime.Caller(0) confFile := filepath.Join(filepath.Dir(testFile), "config.yaml") - log.Debugf("Current test filename: %s", confFile) - log.Debugf("os.Args: %v", os.Args) + log.WithField("conf", confFile).Debug("current test filename") + log.Debugf("os.Args: %#v", os.Args) var err error conf.GConf, err = conf.LoadConfig(confFile) if err != nil { - log.Fatalf("load config for test in kms failed: %s", err) + log.WithError(err).Fatal("load config for test in kms failed") } InitBP() } @@ -90,7 +88,7 @@ func InitBP() { err := hash.Decode(&BP.RawNodeID.Hash, string(BP.NodeID)) if err != nil { - log.Fatalf("BP.NodeID error: %s", err) + log.WithError(err).Fatal("BP.NodeID error") } } @@ -120,7 +118,7 @@ func InitPublicKeyStore(dbPath string, initNodes []proto.Node) (err error) { var bdb *bolt.DB bdb, err = bolt.Open(dbPath, 0600, nil) if err != nil { - log.Errorf("InitPublicKeyStore failed: %s", err) + log.WithError(err).Error("InitPublicKeyStore failed") pksLock.Unlock() return } @@ -128,13 +126,13 @@ func InitPublicKeyStore(dbPath string, initNodes []proto.Node) (err error) { name := []byte(kmsBucketName) err = bdb.Update(func(tx *bolt.Tx) error { if _, err := tx.CreateBucketIfNotExists(name); err != nil { - log.Errorf("could not create bucket: %s", err) + log.WithError(err).Error("could not create bucket") return err } return nil // return from Update func }) if err != nil { - log.Errorf("InitPublicKeyStore failed: %s", err) + log.WithError(err).Error("InitPublicKeyStore failed") pksLock.Unlock() return } @@ -149,7 +147,7 @@ func InitPublicKeyStore(dbPath string, initNodes []proto.Node) (err error) { for _, n := range initNodes { err = setNode(&n) if err != nil { - log.Errorf("set init nodes failed: %v", err) + log.WithError(err).Error("set init nodes failed") return } } @@ -185,16 +183,12 @@ func GetNodeInfo(id proto.NodeID) (nodeInfo *proto.Node, err error) { if byteVal == nil { return ErrKeyNotFound } - reader := bytes.NewReader(byteVal) - mh := &codec.MsgpackHandle{} - dec := codec.NewDecoder(reader, mh) - nodeInfo = proto.NewNode() - err = dec.Decode(nodeInfo) - log.Debugf("get node info: %v", nodeInfo) + err = utils.DecodeMsgPack(byteVal, &nodeInfo) + log.Debugf("get node info: %#v", nodeInfo) return err // return from View func }) if err != nil { - log.Infof("get node info failed: %s", err) + log.WithError(err).Error("get node info failed") } return } @@ -218,7 +212,7 @@ func GetAllNodeID() (nodeIDs []proto.NodeID, err error) { return err // return from View func }) if err != nil { - log.Errorf("get all node id failed: %s", err) + log.WithError(err).Error("get all node id failed") } return @@ -266,15 +260,12 @@ func setNode(nodeInfo *proto.Node) (err error) { return ErrPKSNotInitialized } - nodeBuf := new(bytes.Buffer) - mh := &codec.MsgpackHandle{} - enc := codec.NewEncoder(nodeBuf, mh) - err = enc.Encode(*nodeInfo) + nodeBuf, err := utils.EncodeMsgPack(nodeInfo) if err != nil { - log.Errorf("marshal node info failed: %s", err) + log.WithError(err).Error("marshal node info failed") return } - log.Debugf("set node: %v", nodeInfo) + log.Debugf("set node: %#v", nodeInfo) err = pks.db.Update(func(tx *bolt.Tx) error { bucket := tx.Bucket(pks.bucket) @@ -284,7 +275,7 @@ func setNode(nodeInfo *proto.Node) (err error) { return bucket.Put([]byte(nodeInfo.ID), nodeBuf.Bytes()) }) if err != nil { - log.Errorf("get node info failed: %s", err) + log.WithError(err).Error("get node info failed") } return @@ -306,7 +297,7 @@ func DelNode(id proto.NodeID) (err error) { return bucket.Delete([]byte(id)) }) if err != nil { - log.Errorf("del node failed: %s", err) + log.WithError(err).Error("del node failed") } return } @@ -320,7 +311,7 @@ func removeBucket() (err error) { return tx.DeleteBucket([]byte(kmsBucketName)) }) if err != nil { - log.Errorf("remove bucket failed: %s", err) + log.WithError(err).Error("remove bucket failed") return } // ks.bucket == nil means bucket not exist @@ -343,7 +334,7 @@ func ResetBucket() error { }) pks.bucket = bucketName if err != nil { - log.Errorf("reset bucket failed: %s", err) + log.WithError(err).Error("reset bucket failed") } return err diff --git a/crypto/kms/pubkeystore_test.go b/crypto/kms/pubkeystore_test.go index de6c6fba7..eae61e309 100644 --- a/crypto/kms/pubkeystore_test.go +++ b/crypto/kms/pubkeystore_test.go @@ -17,7 +17,6 @@ package kms import ( - "bytes" "os" "reflect" "testing" @@ -25,9 +24,9 @@ import ( "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" "github.com/CovenantSQL/CovenantSQL/pow/cpuminer" "github.com/CovenantSQL/CovenantSQL/proto" + "github.com/CovenantSQL/CovenantSQL/utils" "github.com/CovenantSQL/CovenantSQL/utils/log" . "github.com/smartystreets/goconvey/convey" - "github.com/ugorji/go/codec" "gopkg.in/yaml.v2" ) @@ -38,13 +37,13 @@ func TestDB(t *testing.T) { privKey1, pubKey1, _ := asymmetric.GenSecp256k1KeyPair() privKey2, pubKey2, _ := asymmetric.GenSecp256k1KeyPair() node1 := &proto.Node{ - ID: proto.NodeID("node1"), + ID: proto.NodeID("1111"), Addr: "", PublicKey: pubKey1, Nonce: cpuminer.Uint256{}, } node2 := &proto.Node{ - ID: proto.NodeID("node2"), + ID: proto.NodeID("2222"), Addr: "", PublicKey: pubKey2, Nonce: cpuminer.Uint256{}, @@ -70,7 +69,7 @@ func TestDB(t *testing.T) { So(err, ShouldBeNil) So(pubk.IsEqual(BP.PublicKey), ShouldBeTrue) - pubk, err = GetPublicKey(proto.NodeID("not exist")) + pubk, err = GetPublicKey(proto.NodeID("99999999")) So(pubk, ShouldBeNil) So(err, ShouldEqual, ErrKeyNotFound) @@ -89,15 +88,15 @@ func TestDB(t *testing.T) { err = SetPublicKey(BP.NodeID, cpuminer.Uint256{}, BP.PublicKey) So(err, ShouldEqual, ErrNodeIDKeyNonceNotMatch) - err = SetPublicKey(proto.NodeID("0"+BP.NodeID), BP.Nonce, BP.PublicKey) + err = SetPublicKey(proto.NodeID("00"+BP.NodeID), BP.Nonce, BP.PublicKey) So(err, ShouldEqual, ErrNodeIDKeyNonceNotMatch) - pubk, err = GetPublicKey(proto.NodeID("node1")) + pubk, err = GetPublicKey(proto.NodeID("1111")) So(pubk, ShouldNotBeNil) So(err, ShouldBeNil) So(privKey1.PubKey().IsEqual(pubKey1), ShouldBeTrue) - pubk, err = GetPublicKey(proto.NodeID("node2")) + pubk, err = GetPublicKey(proto.NodeID("2222")) So(pubk, ShouldNotBeNil) So(err, ShouldBeNil) So(privKey2.PubKey().IsEqual(pubKey2), ShouldBeTrue) @@ -105,17 +104,17 @@ func TestDB(t *testing.T) { IDs, err := GetAllNodeID() So(err, ShouldBeNil) So(IDs, ShouldHaveLength, 3) - So(IDs, ShouldContain, proto.NodeID("node1")) - So(IDs, ShouldContain, proto.NodeID("node2")) + So(IDs, ShouldContain, proto.NodeID("1111")) + So(IDs, ShouldContain, proto.NodeID("2222")) So(IDs, ShouldContain, BP.NodeID) - err = DelNode(proto.NodeID("node2")) + err = DelNode(proto.NodeID("2222")) So(err, ShouldBeNil) - err = DelNode(proto.NodeID("node2")) + err = DelNode(proto.NodeID("2222")) So(err, ShouldBeNil) - pubk, err = GetPublicKey(proto.NodeID("node2")) + pubk, err = GetPublicKey(proto.NodeID("2222")) So(pubk, ShouldBeNil) So(err, ShouldEqual, ErrKeyNotFound) @@ -129,7 +128,7 @@ func TestDB(t *testing.T) { err = setNode(node1) So(err, ShouldEqual, ErrBucketNotInitialized) - err = DelNode(proto.NodeID("node2")) + err = DelNode(proto.NodeID("2222")) So(err, ShouldEqual, ErrBucketNotInitialized) IDs, err = GetAllNodeID() @@ -139,7 +138,7 @@ func TestDB(t *testing.T) { err = ResetBucket() So(err, ShouldBeNil) - pubk, err = GetPublicKey(proto.NodeID("node2")) + pubk, err = GetPublicKey(proto.NodeID("2222")) So(pubk, ShouldBeNil) So(err, ShouldEqual, ErrKeyNotFound) @@ -161,7 +160,7 @@ func TestErrorPath(t *testing.T) { func TestMarshalNode(t *testing.T) { Convey("marshal unmarshal node", t, func() { nodeInfo := &proto.Node{ - ID: "abc", + ID: "0000000000000000000000000000000000000000000000000000000000001111", Addr: "addr", PublicKey: nil, Nonce: cpuminer.Uint256{ @@ -171,18 +170,13 @@ func TestMarshalNode(t *testing.T) { D: 4, }, } - nodeBuf := new(bytes.Buffer) - mh := &codec.MsgpackHandle{} - enc := codec.NewEncoder(nodeBuf, mh) - err := enc.Encode(nodeInfo) + nodeBuf, err := utils.EncodeMsgPack(nodeInfo) if err != nil { log.Errorf("encode error: %s", err) } nodeDec := proto.NewNode() - reader := bytes.NewReader(nodeBuf.Bytes()) - dec := codec.NewDecoder(reader, mh) - err = dec.Decode(nodeDec) + err = utils.DecodeMsgPack(nodeBuf.Bytes(), nodeDec) So(reflect.DeepEqual(nodeDec, nodeInfo), ShouldBeTrue) }) diff --git a/crypto/symmetric/aes.go b/crypto/symmetric/aes.go index f04414dc7..41c7a0f1d 100644 --- a/crypto/symmetric/aes.go +++ b/crypto/symmetric/aes.go @@ -21,9 +21,8 @@ import ( "crypto/aes" "crypto/cipher" "crypto/rand" - "io" - "errors" + "io" "github.com/CovenantSQL/CovenantSQL/crypto" "github.com/CovenantSQL/CovenantSQL/crypto/hash" diff --git a/kayak/boltdb_store_test.go b/kayak/boltdb_store_test.go index b022bf62d..994f12857 100644 --- a/kayak/boltdb_store_test.go +++ b/kayak/boltdb_store_test.go @@ -87,7 +87,7 @@ func TestBoltOptionsTimeout(t *testing.T) { So(err, ShouldNotBeNil) So(err.Error(), ShouldEqual, "timeout") case <-time.After(5 * time.Second): - Printf("Gave up waiting for timeout response") + Print("Gave up waiting for timeout response") } }) } diff --git a/kayak/twopc_runner.go b/kayak/twopc_runner.go index e36cd3648..3f9c75069 100644 --- a/kayak/twopc_runner.go +++ b/kayak/twopc_runner.go @@ -19,6 +19,7 @@ package kayak import ( "context" "fmt" + "runtime/trace" "sync" "time" @@ -73,7 +74,6 @@ type TwoPCRunner struct { shutdownLock sync.Mutex // Lock/events - processLock sync.Mutex processReq chan []byte processRes chan logProcessResult updatePeersLock sync.Mutex @@ -193,8 +193,10 @@ func (r *TwoPCRunner) tryRestore() error { if lastIndex > lastCommitted { // uncommitted log found, print warning - log.Warningf("truncating local uncommitted log, uncommitted: %d, committed: %d", - lastIndex, lastCommitted) + log.WithFields(log.Fields{ + "uncommitted": lastIndex, + "committed": lastCommitted, + }).Warning("truncating local uncommitted log") // truncate local uncommitted logs r.logStore.DeleteRange(lastCommitted+1, lastIndex) @@ -278,14 +280,12 @@ func (r *TwoPCRunner) UpdatePeers(peers *Peers) error { // Apply implements Runner.Apply. func (r *TwoPCRunner) Apply(data []byte) (uint64, error) { - r.processLock.Lock() - defer r.processLock.Unlock() - // check leader privilege if r.role != proto.Leader { return 0, ErrNotLeader } + //TODO(auxten): need throughput optimization r.processReq <- data res := <-r.processRes @@ -335,6 +335,11 @@ func (r *TwoPCRunner) safeForPeersUpdate() chan *Peers { } func (r *TwoPCRunner) processNewLog(data []byte) (res logProcessResult) { + ctx := context.Background() + ctx, task := trace.NewTask(ctx, "processNewLog") + defer task.End() + defer trace.StartRegion(ctx, "processNewLogRegion").End() + // build Log l := &Log{ Index: r.lastLogIndex + 1, @@ -428,6 +433,11 @@ func (r *TwoPCRunner) getState() ServerState { } func (r *TwoPCRunner) processRequest(req Request) { + ctx := context.Background() + ctx, task := trace.NewTask(ctx, "processRequest") + defer task.End() + defer trace.StartRegion(ctx, "processRequestRegion").End() + // verify call from leader if err := r.verifyLeader(req); err != nil { req.SendResponse(nil, err) diff --git a/kayak/types.go b/kayak/types.go index 15d9c4749..e71aa5872 100644 --- a/kayak/types.go +++ b/kayak/types.go @@ -221,6 +221,7 @@ func (c *Peers) Serialize() []byte { // Sign generates signature. func (c *Peers) Sign(signer *asymmetric.PrivateKey) error { + c.PubKey = signer.PubKey() h := hash.THashB(c.Serialize()) sig, err := signer.Sign(h) diff --git a/merkle/merkletrie_test.go b/merkle/merkletrie_test.go index 973ae4650..58a94cbe0 100644 --- a/merkle/merkletrie_test.go +++ b/merkle/merkletrie_test.go @@ -1,13 +1,10 @@ package merkle import ( - "testing" - "bytes" - "crypto/rand" - "math" + "testing" "github.com/CovenantSQL/CovenantSQL/crypto/hash" . "github.com/smartystreets/goconvey/convey" diff --git a/merkle/patriciatrie_test.go b/merkle/patriciatrie_test.go index 375d2c8bb..c5cf5ce62 100644 --- a/merkle/patriciatrie_test.go +++ b/merkle/patriciatrie_test.go @@ -1,12 +1,10 @@ package merkle import ( - "testing" - "bytes" "encoding/gob" - "strings" + "testing" "github.com/CovenantSQL/CovenantSQL/crypto/hash" . "github.com/smartystreets/goconvey/convey" diff --git a/metric/covenantmetric_test.go b/metric/covenantmetric_test.go index dbaa8d00b..90d8646e2 100644 --- a/metric/covenantmetric_test.go +++ b/metric/covenantmetric_test.go @@ -31,7 +31,7 @@ func TestMetrics(t *testing.T) { log.SetLevel(log.DebugLevel) reg := prometheus.NewRegistry() reg.MustRegister(NewCovenantSQLCollector()) - log.Debugf("Gauge Collector 'CovenantSQLCollector' registered.") + log.Debug("Gauge Collector 'CovenantSQLCollector' registered.") time.Sleep(1100 * time.Millisecond) Convey("get metric", t, func() { diff --git a/metric/cpu_dragonfly_test.go b/metric/cpu_dragonfly_test.go index 7355437a3..a01d2d835 100644 --- a/metric/cpu_dragonfly_test.go +++ b/metric/cpu_dragonfly_test.go @@ -31,7 +31,7 @@ func TestCPU(t *testing.T) { } if len(times) == 0 { - t.Fatalf("no cputimes found") + t.Fatal("no cputimes found") } want := runtime.NumCPU() * fieldsCount diff --git a/metric/metric.go b/metric/metric.go index 94f58113f..10895dc41 100644 --- a/metric/metric.go +++ b/metric/metric.go @@ -49,18 +49,18 @@ func init() { func StartMetricCollector() (registry *prometheus.Registry) { nc, err := NewNodeCollector() if err != nil { - log.Errorf("couldn't create node collector: %s", err) + log.WithError(err).Error("couldn't create node collector") return } registry = prometheus.NewRegistry() err = registry.Register(nc) if err != nil { - log.Errorf("couldn't register collector: %s", err) + log.WithError(err).Error("couldn't register collector") return nil } - log.Infof("Enabled collectors:") + log.Info("Enabled collectors:") var collectors []string for n := range nc.Collectors { collectors = append(collectors, n) diff --git a/metric/ntp.go b/metric/ntp.go index 2dfa395d9..5b12c0434 100644 --- a/metric/ntp.go +++ b/metric/ntp.go @@ -16,6 +16,7 @@ package metric import ( + "errors" "fmt" "net" "time" @@ -53,7 +54,7 @@ type ntpCollector struct { func NewNtpCollector() (Collector, error) { ipaddr := net.ParseIP(ntpServer) if !ntpServerIsLocal && (ipaddr == nil || !ipaddr.IsLoopback()) { - return nil, fmt.Errorf("only IP address of local NTP server is valid for --collector.ntp.server") + return nil, errors.New("only IP address of local NTP server is valid for --collector.ntp.server") } if ntpProtocolVersion < 2 || ntpProtocolVersion > 4 { @@ -61,7 +62,7 @@ func NewNtpCollector() (Collector, error) { } if ntpOffsetTolerance < 0 { - return nil, fmt.Errorf("Offset tolerance must be non-negative") + return nil, errors.New("Offset tolerance must be non-negative") } return &ntpCollector{ diff --git a/pow/cpuminer/miner_test.go b/pow/cpuminer/miner_test.go index 814204f33..24e81380d 100644 --- a/pow/cpuminer/miner_test.go +++ b/pow/cpuminer/miner_test.go @@ -17,11 +17,9 @@ package cpuminer import ( + "sync" "testing" - "time" - - "sync" ) func TestCPUMiner_HashBlock(t *testing.T) { diff --git a/pow/cpuminer/uint256_test.go b/pow/cpuminer/uint256_test.go index 53204f680..d6d87ee81 100644 --- a/pow/cpuminer/uint256_test.go +++ b/pow/cpuminer/uint256_test.go @@ -19,11 +19,9 @@ package cpuminer import ( "math" "testing" - - "github.com/CovenantSQL/CovenantSQL/utils/log" - "unsafe" + "github.com/CovenantSQL/CovenantSQL/utils/log" . "github.com/smartystreets/goconvey/convey" ) diff --git a/proto/nodeinfo.go b/proto/nodeinfo.go index 5c40549aa..019e32237 100644 --- a/proto/nodeinfo.go +++ b/proto/nodeinfo.go @@ -114,7 +114,7 @@ func (id *NodeID) Difficulty() (difficulty int) { func (id *NodeID) ToRawNodeID() *RawNodeID { idHash, err := hash.NewHashFromStr(string(*id)) if err != nil { - log.Errorf("error node id %s %s", *id, err) + log.WithField("id", *id).WithError(err).Error("error node id") return nil } return &RawNodeID{*idHash} @@ -130,6 +130,26 @@ func (id *NodeID) IsEqual(target *NodeID) bool { return strings.Compare(string(*id), string(*target)) == 0 } +// MarshalBinary does the serialization +func (id *NodeID) MarshalBinary() (keyBytes []byte, err error) { + if id == nil { + return []byte{}, nil + } + h, err := hash.NewHashFromStr(string(*id)) + return h[:], err +} + +// UnmarshalBinary does the deserialization +func (id *NodeID) UnmarshalBinary(keyBytes []byte) (err error) { + h, err := hash.NewHash(keyBytes) + if err != nil { + log.Error("nodeID bytes len should be 32") + return + } + *id = NodeID(h.String()) + return +} + // InitNodeCryptoInfo generate Node asymmetric key pair and generate Node.NonceInfo // Node.ID = Node.NonceInfo.Hash func (node *Node) InitNodeCryptoInfo(timeThreshold time.Duration) (err error) { @@ -141,7 +161,7 @@ func (node *Node) InitNodeCryptoInfo(timeThreshold time.Duration) (err error) { nonce := asymmetric.GetPubKeyNonce(node.PublicKey, NewNodeIDDifficulty, timeThreshold, nil) node.ID = NodeID(nonce.Hash.String()) node.Nonce = nonce.Nonce - log.Debugf("Node: %v", node) + log.Debugf("Node: %#v", node) return } diff --git a/proto/nodeinfo_test.go b/proto/nodeinfo_test.go index d66f4f3bf..f033d7865 100644 --- a/proto/nodeinfo_test.go +++ b/proto/nodeinfo_test.go @@ -19,7 +19,6 @@ package proto import ( "strings" "testing" - "time" "github.com/CovenantSQL/CovenantSQL/crypto/hash" @@ -129,3 +128,24 @@ func TestNodeID_IsEmpty(t *testing.T) { So(node.IsEmpty(), ShouldBeTrue) }) } + +func TestNodeID_MarshalBinary(t *testing.T) { + Convey("NodeID MarshalBinary", t, func() { + var nodeID, nodeID2 NodeID + + nb, err := nodeID.MarshalBinary() + So(err, ShouldBeNil) + + nodeID = NodeID("0000000000000000000000000000000000000000000000000000000000000000") + nb, err = nodeID.MarshalBinary() + So(err, ShouldBeNil) + So(len(nb), ShouldEqual, hash.HashSize) + + err = nodeID2.UnmarshalBinary([]byte("0000")) + So(err, ShouldNotBeNil) + + err = nodeID2.UnmarshalBinary(nb) + So(err, ShouldBeNil) + So(nodeID2, ShouldResemble, nodeID) + }) +} diff --git a/proto/proto.go b/proto/proto.go index 7bda48178..2f5a812f8 100644 --- a/proto/proto.go +++ b/proto/proto.go @@ -39,10 +39,10 @@ type EnvelopeAPI interface { // Envelope is the protocol header type Envelope struct { - Version string - TTL time.Duration - Expire time.Duration - NodeID *RawNodeID + Version string `json:"v"` + TTL time.Duration `json:"t"` + Expire time.Duration `json:"e"` + NodeID *RawNodeID `json:"id"` } // PingReq is Ping RPC request @@ -72,9 +72,9 @@ type UploadMetricsResp struct { // FindNeighborReq is FindNeighbor RPC request type FindNeighborReq struct { - NodeID NodeID - Roles []ServerRole - Count int + ID NodeID + Roles []ServerRole + Count int Envelope } @@ -87,7 +87,7 @@ type FindNeighborResp struct { // FindNodeReq is FindNode RPC request type FindNodeReq struct { - NodeID NodeID + ID NodeID Envelope } diff --git a/proto/proto_gen.go b/proto/proto_gen.go index 2a1454710..d0aab0198 100644 --- a/proto/proto_gen.go +++ b/proto/proto_gen.go @@ -68,7 +68,7 @@ func (z *FindNeighborReq) MarshalHash() (o []byte, err error) { o = hsp.AppendBytes(o, oTemp) } o = append(o, 0x84) - if oTemp, err := z.NodeID.MarshalHash(); err != nil { + if oTemp, err := z.ID.MarshalHash(); err != nil { return nil, err } else { o = hsp.AppendBytes(o, oTemp) @@ -89,7 +89,7 @@ func (z *FindNeighborReq) MarshalHash() (o []byte, err error) { // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message func (z *FindNeighborReq) Msgsize() (s int) { - s = 1 + 9 + z.Envelope.Msgsize() + 7 + z.NodeID.Msgsize() + 6 + hsp.ArrayHeaderSize + s = 1 + 9 + z.Envelope.Msgsize() + 3 + z.ID.Msgsize() + 6 + hsp.ArrayHeaderSize for za0001 := range z.Roles { s += z.Roles[za0001].Msgsize() } @@ -144,7 +144,7 @@ func (z *FindNodeReq) MarshalHash() (o []byte, err error) { o = hsp.AppendBytes(o, oTemp) } o = append(o, 0x82) - if oTemp, err := z.NodeID.MarshalHash(); err != nil { + if oTemp, err := z.ID.MarshalHash(); err != nil { return nil, err } else { o = hsp.AppendBytes(o, oTemp) @@ -154,7 +154,7 @@ func (z *FindNodeReq) MarshalHash() (o []byte, err error) { // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message func (z *FindNodeReq) Msgsize() (s int) { - s = 1 + 9 + z.Envelope.Msgsize() + 7 + z.NodeID.Msgsize() + s = 1 + 9 + z.Envelope.Msgsize() + 3 + z.ID.Msgsize() return } diff --git a/proto/proto_test.go b/proto/proto_test.go index fdca927f6..82428d995 100644 --- a/proto/proto_test.go +++ b/proto/proto_test.go @@ -18,7 +18,6 @@ package proto import ( "testing" - "time" "github.com/CovenantSQL/CovenantSQL/crypto/hash" diff --git a/route/acl.go b/route/acl.go index 5c6b073d3..25fdf7494 100644 --- a/route/acl.go +++ b/route/acl.go @@ -101,6 +101,10 @@ const ( SQLCFetchBlock // SQLCFetchAckedQuery is used by sqlchain to fetch response ack from adjacent nodes SQLCFetchAckedQuery + // SQLCSignBilling is used by sqlchain to response billing signature for periodic billing request + SQLCSignBilling + // SQLCLaunchBilling is used by blockproducer to trigger the billing process in sqlchain + SQLCLaunchBilling // SQLCSubscribeTransactions is used by sqlchain to handle observer subscription request SQLCSubscribeTransactions // SQLCCancelSubscription is used by sqlchain to handle observer subscription cancellation request @@ -109,16 +113,39 @@ const ( OBSAdviseAckedQuery // OBSAdviseNewBlock is used by sqlchain to push new block to observers OBSAdviseNewBlock + // MCCAdviseNewBlock is used by block producer to push block to adjacent nodes + MCCAdviseNewBlock + // MCCAdviseTxBilling is used by block producer to push billing transaction to adjacent nodes + MCCAdviseTxBilling + // MCCAdviseBillingRequest is used by block producer to push billing request to adjacent nodes + MCCAdviseBillingRequest + // MCCFetchBlock is used by nodes to fetch block from block producer + MCCFetchBlock + // MCCFetchBlockByCount is used by nodes to fetch block from block producer by block count since genesis + MCCFetchBlockByCount + // MCCFetchTxBilling is used by nodes to fetch billing transaction from block producer + MCCFetchTxBilling // MCCNextAccountNonce is used by block producer main chain to allocate next nonce for transactions MCCNextAccountNonce // MCCAddTx is used by block producer main chain to upload transaction MCCAddTx - // MCCAddTxTransfer is used by block producer main chain to upload transfer transaction - MCCAddTxTransfer // MCCQueryAccountStableBalance is used by block producer to provide account stable coin balance MCCQueryAccountStableBalance // MCCQueryAccountCovenantBalance is used by block producer to provide account covenant coin balance MCCQueryAccountCovenantBalance + + // DHTRPCName defines the block producer dh-rpc service name + DHTRPCName = "DHT" + // BlockProducerRPCName defines main chain rpc name + BlockProducerRPCName = "MCC" + // SQLChainRPCName defines the sql chain rpc name + SQLChainRPCName = "SQLC" + // DBRPCName defines the sql chain db service rpc name + DBRPCName = "DBS" + // BPDBRPCName defines the block producer db service rpc name + BPDBRPCName = "BPDB" + // ObserverRPCName defines the observer node service rpc name + ObserverRPCName = "OBS" ) // String returns the RemoteFunc string @@ -164,6 +191,10 @@ func (s RemoteFunc) String() string { return "SQLC.FetchBlock" case SQLCFetchAckedQuery: return "SQLC.FetchAckedQuery" + case SQLCSignBilling: + return "SQLC.SignBilling" + case SQLCLaunchBilling: + return "SQLC.LaunchBilling" case SQLCSubscribeTransactions: return "SQLC.SubscribeTransactions" case SQLCCancelSubscription: @@ -172,12 +203,22 @@ func (s RemoteFunc) String() string { return "OBS.AdviseAckedQuery" case OBSAdviseNewBlock: return "OBS.AdviseNewBlock" + case MCCAdviseNewBlock: + return "MCC.AdviseNewBlock" + case MCCAdviseTxBilling: + return "MCC.AdviseTxBilling" + case MCCAdviseBillingRequest: + return "MCC.AdviseBillingRequest" + case MCCFetchBlock: + return "MCC.FetchBlock" + case MCCFetchBlockByCount: + return "MCC.FetchBlockByCount" + case MCCFetchTxBilling: + return "MCC.FetchTxBilling" case MCCNextAccountNonce: return "MCC.NextAccountNonce" case MCCAddTx: return "MCC.AddTx" - case MCCAddTxTransfer: - return "MCC.AddTxTransfer" case MCCQueryAccountStableBalance: return "MCC.QueryAccountStableBalance" case MCCQueryAccountCovenantBalance: @@ -195,7 +236,7 @@ func IsPermitted(callerEnvelope *proto.Envelope, funcName RemoteFunc) (ok bool) if callerETLSNodeID != nil { if callerETLSNodeID.IsEqual(&kms.AnonymousRawNodeID.Hash) { if funcName != DHTPing { - log.Warnf("anonymous ETLS connection can not used by %s", funcName) + log.WithField("field", funcName).Warning("anonymous ETLS connection can not used") return false } } diff --git a/route/bootstrap.go b/route/bootstrap.go index 9f27aa105..3ad304699 100644 --- a/route/bootstrap.go +++ b/route/bootstrap.go @@ -71,7 +71,7 @@ func NewDNSClient() *DNSClient { } else { clientConfig, err = dns.ClientConfigFromFile("/etc/resolv.conf") if err != nil || clientConfig == nil { - log.Errorf("can not initialize the local resolver: %s", err) + log.WithError(err).Error("can not initialize the local resolver") } } @@ -95,7 +95,7 @@ func (dc *DNSClient) Query(qname string, qtype uint16) (*dns.Msg, error) { } return r, fmt.Errorf("DNS query failed with Rcode %v", r.Rcode) } - return nil, fmt.Errorf("no available name server") + return nil, errors.New("no available name server") } // GetKey returns the DNSKey for a name server @@ -111,7 +111,7 @@ func (dc *DNSClient) GetKey(name string, keytag uint16) (*dns.DNSKEY, error) { } } } - return nil, fmt.Errorf("no DNSKEY returned by nameserver") + return nil, errors.New("no DNSKEY returned by nameserver") } // VerifySection checks RRSIGs to make sure the name server is authentic @@ -134,16 +134,24 @@ func (dc *DNSClient) VerifySection(set []dns.RR) error { if !validDNSKey { return fmt.Errorf("DNSKEY %s not valid", key.PublicKey) } - log.Debugf("valid DNSKEY %s of %s", key.PublicKey, domain) + log.WithFields(log.Fields{ + "pub": key.PublicKey, + "domain": domain, + }).Debug("valid DNSKEY") if err := rr.(*dns.RRSIG).Verify(key, rrset); err != nil { return fmt.Errorf(";- Bogus signature, %s does not validate (DNSKEY %s/%d) [%s]", shortSig(rr.(*dns.RRSIG)), key.Header().Name, key.KeyTag(), err.Error()) } - log.Debugf(";+ Secure signature, %s validates (DNSKEY %s/%d %s)", shortSig(rr.(*dns.RRSIG)), key.Header().Name, key.KeyTag(), key.PublicKey) + log.WithFields(log.Fields{ + "rrsig": shortSig(rr.(*dns.RRSIG)), + "name": key.Header().Name, + "tag": key.KeyTag(), + "pub": key.PublicKey, + }).Debug("signature secured") return nil } } - return fmt.Errorf("not DNSSEC record") + return errors.New("not DNSSEC record") } // GetRRSet returns the RRset belonging to the signature with name and type t @@ -166,12 +174,12 @@ func shortSig(sig *dns.RRSIG) string { func (dc *DNSClient) GetBPFromDNSSeed(BPDomain string) (BPNodes IDNodeMap, err error) { srvRR := dc.GetSRVRecords(BPDomain) if srvRR == nil { - err = fmt.Errorf("got empty SRV records set") + err = errors.New("got empty SRV records set") log.Error(err) return } if err = dc.VerifySection(srvRR.Answer); err != nil { - log.Errorf("record verify failed: %s", err) + log.WithError(err).Error("record verify failed") return } BPNodes = make(IDNodeMap) @@ -183,7 +191,7 @@ func (dc *DNSClient) GetBPFromDNSSeed(BPDomain string) (BPNodes IDNodeMap, err e aRR := dc.GetARecord(srv.Target) if aRR != nil { if err = dc.VerifySection(aRR.Answer); err != nil { - log.Errorf("verify SRV section failed: %v", err) + log.WithError(err).Error("verify SRV section failed") return } for _, rr1 := range aRR.Answer { @@ -207,11 +215,11 @@ func (dc *DNSClient) GetBPFromDNSSeed(BPDomain string) (BPNodes IDNodeMap, err e ABIPv6R := dc.GetAAAARecord(target) if ABIPv6R == nil { err = errors.New("empty AAAA record") - log.Errorf("get AAAA section of %s failed: %v", target, err) + log.WithField("target", target).WithError(err).Error("get AAAA section failed") return } if err = dc.VerifySection(ABIPv6R.Answer); err != nil { - log.Errorf("verify ab AAAA section of %s failed: %v", target, err) + log.WithError(err).WithError(err).Error("verify ab AAAA section failed") return } for _, rr := range ABIPv6R.Answer { @@ -225,12 +233,12 @@ func (dc *DNSClient) GetBPFromDNSSeed(BPDomain string) (BPNodes IDNodeMap, err e CDIPv6R := dc.GetAAAARecord(target) if CDIPv6R == nil { err = errors.New("empty AAAA record") - log.Errorf("get AAAA section of %s failed: %v", target, err) + log.WithField("target", target).WithError(err).Error("get AAAA section failed") return } if err = dc.VerifySection(CDIPv6R.Answer); err != nil { - log.Errorf("verify cd AAAA section of %s failed: %v", target, err) + log.WithField("target", target).WithError(err).Error("verify cd AAAA section failed") return } for _, rr := range CDIPv6R.Answer { @@ -243,7 +251,7 @@ func (dc *DNSClient) GetBPFromDNSSeed(BPDomain string) (BPNodes IDNodeMap, err e var nonce *mine.Uint256 nonce, err = mine.FromIPv6(ab, cd) if err != nil { - log.Errorf("convert IPv6 addr to nonce failed: %v", err) + log.WithError(err).Error("convert IPv6 addr to nonce failed") return } @@ -251,33 +259,33 @@ func (dc *DNSClient) GetBPFromDNSSeed(BPDomain string) (BPNodes IDNodeMap, err e publicKeyTXTR := dc.GetTXTRecord(srv.Target) if publicKeyTXTR == nil { err = errors.New("empty TXT record") - log.Errorf("get TXT section of %s failed: %v", srv.Target, err) + log.WithField("target", srv.Target).WithError(err).Error("get TXT section failed") return } if err = dc.VerifySection(publicKeyTXTR.Answer); err != nil { - log.Errorf("verify TXT section of %s failed: %v", srv.Target, err) + log.WithField("target", srv.Target).WithError(err).Error("verify TXT section failed") return } for _, rr := range publicKeyTXTR.Answer { if ss, ok := rr.(*dns.TXT); ok { if len(ss.Txt) == 0 { err = errors.New("empty TXT record") - log.Errorf("%v for %s", err, srv.Target) + log.WithField("target", srv.Target).WithError(err).Error("got empty TXT record") return } publicKeyStr := ss.Txt[0] - log.Debugf("TXT Record: %s", publicKeyStr) + log.Debugf("TXT Record: %#v", publicKeyStr) var pubKeyBytes []byte // load public key string pubKeyBytes, err = hex.DecodeString(publicKeyStr) if err != nil { - log.Errorf("decode TXT record to hex failed: %v", err) + log.WithError(err).Error("decode TXT record to hex failed") return } err = publicKey.UnmarshalBinary(pubKeyBytes) if err != nil { - log.Errorf("unmarshal TXT record to public key failed: %v", err) + log.WithError(err).Error("unmarshal TXT record to public key failed") return } @@ -306,7 +314,7 @@ func (dc *DNSClient) GetBPFromDNSSeed(BPDomain string) (BPNodes IDNodeMap, err e func (dc *DNSClient) GetSRVRecords(name string) *dns.Msg { in, err := dc.Query(name, dns.TypeSRV) if err != nil { - log.Errorf("SRV record query failed: %v", err) + log.WithField("name", name).WithError(err).Error("SRV record query failed") return nil } return in @@ -316,7 +324,7 @@ func (dc *DNSClient) GetSRVRecords(name string) *dns.Msg { func (dc *DNSClient) GetARecord(name string) *dns.Msg { in, err := dc.Query(name, dns.TypeA) if err != nil { - log.Errorf("A record query failed: %v", err) + log.WithField("name", name).WithError(err).Error("A record query failed") return nil } return in @@ -326,7 +334,7 @@ func (dc *DNSClient) GetARecord(name string) *dns.Msg { func (dc *DNSClient) GetAAAARecord(name string) *dns.Msg { in, err := dc.Query(name, dns.TypeAAAA) if err != nil { - log.Errorf("AAAA record query failed: %v", err) + log.WithField("name", name).WithError(err).Error("AAAA record query failed") return nil } return in @@ -336,7 +344,7 @@ func (dc *DNSClient) GetAAAARecord(name string) *dns.Msg { func (dc *DNSClient) GetTXTRecord(name string) *dns.Msg { in, err := dc.Query(name, dns.TypeTXT) if err != nil { - log.Errorf("TXT record query failed: %v", err) + log.WithField("name", name).WithError(err).Error("TXT record query failed") return nil } return in diff --git a/route/dns.go b/route/dns.go index 53c9bde4e..e3647f968 100644 --- a/route/dns.go +++ b/route/dns.go @@ -135,7 +135,7 @@ func initBPNodeIDs() (bpNodeIDs NodeIDAddressMap) { var err error BPNodes, err = dc.GetBPFromDNSSeed(seedDomain) if err != nil { - log.Errorf("getting BP addr from DNS %s failed: %s", seedDomain, err) + log.WithField("seed", seedDomain).WithError(err).Error("getting BP addr from DNS failed") return } } @@ -192,7 +192,10 @@ func InitKMS(PubKeyStoreFile string) { for _, n := range conf.GConf.KnownNodes { rawNodeID := n.ID.ToRawNodeID() - log.Debugf("set node addr: %v, %v", rawNodeID, n.Addr) + log.WithFields(log.Fields{ + "node": rawNodeID.String(), + "addr": n.Addr, + }).Debug("set node addr") SetNodeAddrCache(rawNodeID, n.Addr) node := &proto.Node{ ID: n.ID, @@ -201,15 +204,15 @@ func InitKMS(PubKeyStoreFile string) { Nonce: n.Nonce, Role: n.Role, } - log.Debugf("known node to set: %v", node) + log.WithField("node", node).Debug("known node to set") err := kms.SetNode(node) if err != nil { - log.Errorf("set node failed: %v\n %s", node, err) + log.WithField("node", node).WithError(err).Error("set node failed") } if n.ID == conf.GConf.ThisNodeID { kms.SetLocalNodeIDNonce(rawNodeID.CloneBytes(), &n.Nonce) } } } - log.Debugf("AllNodes:\n %v\n", conf.GConf.KnownNodes) + log.Debugf("AllNodes:\n %#v\n", conf.GConf.KnownNodes) } diff --git a/route/service.go b/route/service.go index a234b57fc..ad7d34da7 100644 --- a/route/service.go +++ b/route/service.go @@ -43,12 +43,17 @@ func NewDHTServiceWithRing(c *consistent.Consistent) (s *DHTService, err error) func NewDHTService(DHTStorePath string, persistImpl consistent.Persistence, initBP bool) (s *DHTService, err error) { c, err := consistent.InitConsistent(DHTStorePath, persistImpl, initBP) if err != nil { - log.Errorf("init DHT service failed: %s", err) + log.WithError(err).Error("init DHT service failed") return } return NewDHTServiceWithRing(c) } +// Nil RPC does nothing just for probe +func (DHT *DHTService) Nil(req *proto.PingReq, resp *proto.PingResp) (err error) { + return +} + // FindNode RPC returns node with requested node id from DHT func (DHT *DHTService) FindNode(req *proto.FindNodeReq, resp *proto.FindNodeResp) (err error) { if !IsPermitted(&req.Envelope, DHTFindNode) { @@ -56,7 +61,7 @@ func (DHT *DHTService) FindNode(req *proto.FindNodeReq, resp *proto.FindNodeResp log.Error(err) return } - node, err := DHT.Consistent.GetNode(string(req.NodeID)) + node, err := DHT.Consistent.GetNode(string(req.ID)) if err != nil { err = fmt.Errorf("get node %s from DHT failed: %s", req.NodeID, err) log.Error(err) @@ -74,14 +79,17 @@ func (DHT *DHTService) FindNeighbor(req *proto.FindNeighborReq, resp *proto.Find return } - nodes, err := DHT.Consistent.GetNeighborsEx(string(req.NodeID), req.Count, req.Roles) + nodes, err := DHT.Consistent.GetNeighborsEx(string(req.ID), req.Count, req.Roles) if err != nil { err = fmt.Errorf("get nodes from DHT failed: %s", err) log.Error(err) return } resp.Nodes = nodes - log.Debugf("found %v nodes for find neighbor request %v", len(nodes), req) + log.WithFields(log.Fields{ + "neighCount": len(nodes), + "req": req, + }).Debug("found nodes for find neighbor request") return } diff --git a/route/service_test.go b/route/service_test.go index 620c56e75..3125f5590 100644 --- a/route/service_test.go +++ b/route/service_test.go @@ -29,9 +29,9 @@ import ( "github.com/CovenantSQL/CovenantSQL/consistent" "github.com/CovenantSQL/CovenantSQL/crypto/kms" . "github.com/CovenantSQL/CovenantSQL/proto" + "github.com/CovenantSQL/CovenantSQL/utils" "github.com/CovenantSQL/CovenantSQL/utils/log" . "github.com/smartystreets/goconvey/convey" - "github.com/ugorji/go/codec" ) const DHTStorePath = "./DHTStore" @@ -43,7 +43,7 @@ func TestDHTService_FindNeighbor_FindNode(t *testing.T) { addr := "127.0.0.1:0" dht, _ := NewDHTService(DHTStorePath+"1", new(consistent.KMSStorage), false) kms.ResetBucket() - rpc.RegisterName("DHT", dht) + rpc.RegisterName(DHTRPCName, dht) ln, err := net.Listen("tcp", addr) if err != nil { fmt.Println(err) @@ -65,8 +65,8 @@ func TestDHTService_FindNeighbor_FindNode(t *testing.T) { } req := &FindNeighborReq{ - NodeID: "123", - Count: 2, + ID: "123", + Count: 2, } resp := new(FindNeighborResp) err = client.Call("DHT.FindNeighbor", req, resp) @@ -81,7 +81,7 @@ func TestDHTService_FindNeighbor_FindNode(t *testing.T) { }) reqFN1 := &FindNodeReq{ - NodeID: "123", + ID: "123", } respFN1 := new(FindNodeResp) err = client.Call("DHT.FindNode", reqFN1, respFN1) @@ -110,7 +110,7 @@ func TestDHTService_FindNeighbor_FindNode(t *testing.T) { log.Debugf("respA: %v", respA) reqFN2 := &FindNodeReq{ - NodeID: node1.ID, + ID: node1.ID, } respFN2 := new(FindNodeResp) err = client.Call("DHT.FindNode", reqFN2, respFN2) @@ -140,8 +140,8 @@ func TestDHTService_FindNeighbor_FindNode(t *testing.T) { log.Debugf("respA: %v", respB) req = &FindNeighborReq{ - NodeID: "123", - Count: 10, + ID: "123", + Count: 10, } resp = new(FindNeighborResp) err = client.Call("DHT.FindNeighbor", req, resp) @@ -160,9 +160,9 @@ func TestDHTService_FindNeighbor_FindNode(t *testing.T) { }) req = &FindNeighborReq{ - NodeID: "123", - Count: 10, - Roles: ServerRoles{Miner}, + ID: "123", + Count: 10, + Roles: ServerRoles{Miner}, } resp = new(FindNeighborResp) err = client.Call("DHT.FindNeighbor", req, resp) @@ -181,7 +181,7 @@ func TestDHTService_FindNeighbor_FindNode(t *testing.T) { }) reqFN3 := &FindNodeReq{ - NodeID: node2.ID, + ID: node2.ID, } respFN3 := new(FindNodeResp) err = client.Call("DHT.FindNode", reqFN3, respFN3) @@ -207,13 +207,12 @@ func TestDHTService_Ping(t *testing.T) { addr := "127.0.0.1:0" dht, _ := NewDHTService(DHTStorePath, new(consistent.KMSStorage), false) - rpc.RegisterName("DHT", dht) + rpc.RegisterName(DHTRPCName, dht) ln, err := net.Listen("tcp", addr) if err != nil { fmt.Println(err) return } - mh := &codec.MsgpackHandle{} go func() { for { @@ -221,8 +220,7 @@ func TestDHTService_Ping(t *testing.T) { if err != nil { continue } - msgpackCodec := codec.MsgpackSpecRpc.ServerCodec(c, mh) - go rpc.ServeCodec(msgpackCodec) + go rpc.ServeCodec(utils.GetMsgPackServerCodec(c)) } }() @@ -239,8 +237,7 @@ func TestDHTService_Ping(t *testing.T) { Node: *node1, } respA := new(PingResp) - msgpackCodec := codec.MsgpackSpecRpc.ClientCodec(client, mh) - rc := rpc.NewClientWithCodec(msgpackCodec) + rc := rpc.NewClientWithCodec(utils.GetMsgPackClientCodec(client)) err = rc.Call("DHT.Ping", reqA, respA) if err != nil { t.Error(err) @@ -251,8 +248,7 @@ func TestDHTService_Ping(t *testing.T) { respA3 := new(PingResp) conf.GConf.MinNodeIDDifficulty = 256 client, _ = net.Dial("tcp", ln.Addr().String()) - msgpackCodec = codec.MsgpackSpecRpc.ClientCodec(client, mh) - rc = rpc.NewClientWithCodec(msgpackCodec) + rc = rpc.NewClientWithCodec(utils.GetMsgPackClientCodec(client)) err = rc.Call("DHT.Ping", reqA, respA3) if err == nil || !strings.Contains(err.Error(), "difficulty too low") { t.Error(err) @@ -263,8 +259,7 @@ func TestDHTService_Ping(t *testing.T) { respA2 := new(PingResp) reqA.Node.Nonce.A = ^uint64(0) client, _ = net.Dial("tcp", ln.Addr().String()) - msgpackCodec = codec.MsgpackSpecRpc.ClientCodec(client, mh) - rc = rpc.NewClientWithCodec(msgpackCodec) + rc = rpc.NewClientWithCodec(utils.GetMsgPackClientCodec(client)) err = rc.Call("DHT.Ping", reqA, respA2) if err == nil || !strings.Contains(err.Error(), "nonce public key not match") { t.Error(err) diff --git a/rpc/README.md b/rpc/README.md index 4aafc248d..a68aa9b1a 100644 --- a/rpc/README.md +++ b/rpc/README.md @@ -21,7 +21,7 @@ CovenantSQL is built on DH-RPC, including: ## Usage -![](https://cdn.rawgit.com/CovenantSQL/CovenantSQL/develop/logo/dh-rpc.svg) +![](https://cdn.jsdelivr.net/gh/CovenantSQL/CovenantSQL@cc4aa933d80a5d31738081d13c7b1587ad47cffb/logo/dh-rpc.svg) Alice Client: @@ -164,7 +164,7 @@ func main() { } // Register DHT service - server, err := rpc.NewServerWithService(rpc.ServiceMap{"DHT": dht}) + server, err := rpc.NewServerWithService(rpc.ServiceMap{route.DHTRPCName: dht}) if err != nil { log.Fatal(err) } diff --git a/rpc/_example/tracker/main.go b/rpc/_example/tracker/main.go index 1b00d67d7..706d35afa 100644 --- a/rpc/_example/tracker/main.go +++ b/rpc/_example/tracker/main.go @@ -25,7 +25,7 @@ func main() { } // Register DHT service - server, err := rpc.NewServerWithService(rpc.ServiceMap{"DHT": dht}) + server, err := rpc.NewServerWithService(rpc.ServiceMap{route.DHTRPCName: dht}) if err != nil { log.Fatal(err) } diff --git a/rpc/client.go b/rpc/client.go index b918e1b5e..0600d8dac 100644 --- a/rpc/client.go +++ b/rpc/client.go @@ -21,15 +21,13 @@ import ( "net" "net/rpc" - "io/ioutil" - "github.com/CovenantSQL/CovenantSQL/crypto/etls" "github.com/CovenantSQL/CovenantSQL/crypto/kms" "github.com/CovenantSQL/CovenantSQL/pow/cpuminer" "github.com/CovenantSQL/CovenantSQL/proto" + "github.com/CovenantSQL/CovenantSQL/utils" "github.com/CovenantSQL/CovenantSQL/utils/log" - "github.com/hashicorp/yamux" - "github.com/ugorji/go/codec" + mux "github.com/xtaci/smux" ) // Client is RPC client @@ -41,14 +39,13 @@ type Client struct { var ( // YamuxConfig holds the default Yamux config - YamuxConfig *yamux.Config + YamuxConfig *mux.Config // DefaultDialer holds the default dialer of SessionPool DefaultDialer func(nodeID proto.NodeID) (conn net.Conn, err error) ) func init() { - YamuxConfig = yamux.DefaultConfig() - YamuxConfig.LogOutput = ioutil.Discard + YamuxConfig = mux.DefaultConfig() DefaultDialer = dialToNode } @@ -57,7 +54,7 @@ func init() { func dial(network, address string, remoteNodeID *proto.RawNodeID, cipher *etls.Cipher, isAnonymous bool) (c *etls.CryptoConn, err error) { conn, err := net.Dial(network, address) if err != nil { - log.Errorf("connect to %s failed: %s", address, err) + log.WithField("addr", address).WithError(err).Error("connect to node failed") return } var writeBuf []byte @@ -69,19 +66,19 @@ func dial(network, address string, remoteNodeID *proto.RawNodeID, cipher *etls.C var nonce *cpuminer.Uint256 nodeIDBytes, err = kms.GetLocalNodeIDBytes() if err != nil { - log.Errorf("get local node id failed: %s", err) + log.WithError(err).Error("get local node id failed") return } nonce, err = kms.GetLocalNonce() if err != nil { - log.Errorf("get local nonce failed: %s", err) + log.WithError(err).Error("get local nonce failed") return } writeBuf = append(nodeIDBytes, nonce.Bytes()...) } wrote, err := conn.Write(writeBuf) if err != nil || wrote != len(writeBuf) { - log.Errorf("write node id and nonce failed: %s", err) + log.WithError(err).Error("write node id and nonce failed") return } @@ -93,24 +90,24 @@ func dial(network, address string, remoteNodeID *proto.RawNodeID, cipher *etls.C func DialToNode(nodeID proto.NodeID, pool *SessionPool, isAnonymous bool) (conn net.Conn, err error) { if pool == nil || isAnonymous { var ETLSConn net.Conn - var sess *yamux.Session + var sess *mux.Session ETLSConn, err = dialToNodeEx(nodeID, isAnonymous) if err != nil { - log.Errorf("dialToNode failed: %s", err) + log.WithField("target", nodeID).WithError(err).Error("dialToNode failed") return } - sess, err = yamux.Client(ETLSConn, YamuxConfig) + sess, err = mux.Client(ETLSConn, YamuxConfig) if err != nil { - log.Errorf("init yamux client failed: %s", err) + log.WithField("target", nodeID).WithError(err).Error("init yamux client failed") return } - conn, err = sess.Open() + conn, err = sess.OpenStream() if err != nil { - log.Errorf("open new session failed: %s", err) + log.WithField("target", nodeID).WithError(err).Error("open new session failed") } return } - log.Debugf("session pool len: %d", pool.Len()) + log.WithField("poolSize", pool.Len()).Debug("session pool size") conn, err = pool.Get(nodeID) return } @@ -140,20 +137,23 @@ func dialToNodeEx(nodeID proto.NodeID, isAnonymous bool) (conn net.Conn, err err */ symmetricKey, err := GetSharedSecretWith(rawNodeID, isAnonymous) if err != nil { - log.Errorf("get shared secret for %s failed: %s", rawNodeID.ToNodeID(), err) + log.WithField("target", rawNodeID.String()).WithError(err).Error("get shared secret failed") return } nodeAddr, err := GetNodeAddr(rawNodeID) if err != nil { - log.Errorf("resolve node %x failed, err: %s", *rawNodeID, err) + log.WithField("target", rawNodeID.String()).WithError(err).Error("resolve node failed") return } cipher := etls.NewCipher(symmetricKey) conn, err = dial("tcp", nodeAddr, rawNodeID, cipher, isAnonymous) if err != nil { - log.Errorf("connect to %s: %s", nodeAddr, err) + log.WithFields(log.Fields{ + "target": rawNodeID.String(), + "addr": nodeAddr, + }).WithError(err).Error("connect failed") return } @@ -177,29 +177,24 @@ func initClient(addr string) (client *Client, err error) { // InitClientConn initializes client with connection to given addr func InitClientConn(conn net.Conn) (client *Client, err error) { client = NewClient() - var muxConn *yamux.Stream - muxConn, ok := conn.(*yamux.Stream) + var muxConn *mux.Stream + muxConn, ok := conn.(*mux.Stream) if !ok { - var sess *yamux.Session - sess, err = yamux.Client(conn, YamuxConfig) + var sess *mux.Session + sess, err = mux.Client(conn, YamuxConfig) if err != nil { - log.Errorf("init yamux client failed: %v", err) + log.WithError(err).Error("init yamux client failed") return } muxConn, err = sess.OpenStream() if err != nil { - log.Errorf("open stream failed: %v", err) + log.WithError(err).Error("open stream failed") return } } client.Conn = muxConn - mh := &codec.MsgpackHandle{ - WriteExt: true, - RawToString: true, - } - msgpackCodec := codec.MsgpackSpecRpc.ClientCodec(muxConn, mh) - client.Client = rpc.NewClientWithCodec(msgpackCodec) + client.Client = rpc.NewClientWithCodec(utils.GetMsgPackClientCodec(muxConn)) client.RemoteAddr = conn.RemoteAddr().String() return client, nil @@ -207,6 +202,6 @@ func InitClientConn(conn net.Conn) (client *Client, err error) { // Close the client RPC connection func (c *Client) Close() { - log.Debugf("closing %s", c.RemoteAddr) + log.WithField("addr", c.RemoteAddr).Debug("closing client") c.Client.Close() } diff --git a/rpc/leak_test.go b/rpc/leak_test.go index 73a26ccb4..d90f4fe83 100644 --- a/rpc/leak_test.go +++ b/rpc/leak_test.go @@ -97,7 +97,7 @@ func TestSessionPool_SessionBroken(t *testing.T) { reqType = "FindNode" reqFN := &proto.FindNodeReq{ - NodeID: thisClient.ID, + ID: thisClient.ID, } respFN := new(proto.FindNodeResp) err = caller.CallNode(leaderNodeID, "DHT."+reqType, reqFN, respFN) @@ -113,7 +113,7 @@ func TestSessionPool_SessionBroken(t *testing.T) { reqType = "FindNode" reqFN = &proto.FindNodeReq{ - NodeID: thisClient.ID, + ID: thisClient.ID, } respFN = new(proto.FindNodeResp) err = caller.CallNode(leaderNodeID, "DHT."+reqType, reqFN, respFN) diff --git a/rpc/pool.go b/rpc/pool.go index 9193ff3f2..ae45102c0 100644 --- a/rpc/pool.go +++ b/rpc/pool.go @@ -22,7 +22,7 @@ import ( "github.com/CovenantSQL/CovenantSQL/proto" "github.com/CovenantSQL/CovenantSQL/utils/log" - "github.com/hashicorp/yamux" + mux "github.com/xtaci/smux" ) // SessPool is the session pool interface @@ -43,7 +43,8 @@ type SessionMap map[proto.NodeID]*Session // Session is the Session type of SessionPool type Session struct { ID proto.NodeID - Sess *yamux.Session + Sess *mux.Session + conn net.Conn } // SessionPool is the struct type of session pool @@ -79,10 +80,10 @@ func GetSessionPoolInstance() *SessionPool { return instance } -// toSession wraps net.Conn to yamux.Session +// toSession wraps net.Conn to mux.Session func toSession(id proto.NodeID, conn net.Conn) (sess *Session, err error) { - // create yamux session - newSess, err := yamux.Client(conn, YamuxConfig) + // create mux session + newSess, err := mux.Client(conn, YamuxConfig) if err != nil { //log.Errorf("dial to new node %s failed: %s", id, err) // no log in lock return @@ -91,6 +92,7 @@ func toSession(id proto.NodeID, conn net.Conn) (sess *Session, err error) { sess = &Session{ ID: id, Sess: newSess, + conn: conn, } return } @@ -103,7 +105,7 @@ func (p *SessionPool) LoadOrStore(id proto.NodeID, newSess *Session) (sess *Sess defer p.Unlock() sess, exist := p.sessions[id] if exist { - log.Debugf("load session for %s", id) + log.WithField("node", id).Debug("load session for target node") loaded = true } else { sess = newSess @@ -124,33 +126,33 @@ func (p *SessionPool) Get(id proto.NodeID) (conn net.Conn, err error) { // first try to get one session from pool cachedConn, ok := p.getSessionFromPool(id) if ok { - conn, err = cachedConn.Sess.Open() + conn, err = cachedConn.Sess.OpenStream() if err == nil { - log.Debugf("reusing session to %s", id) + log.WithField("node", id).Debug("reusing session") return } - log.Errorf("open session to %s from pool failed: %v", id, err) + log.WithField("target", id).WithError(err).Error("open session failed") p.Remove(id) } - log.Debugf("dial new session to %s", id) + log.WithField("target", id).Debug("dialing new session") // Can't find existing Session, try to dial one newConn, err := p.nodeDialer(id) if err != nil { - log.Errorf("dial new session to node %s failed: %v", id, err) + log.WithField("node", id).WithError(err).Error("dial new session failed") return } newSess, err := toSession(id, newConn) if err != nil { newConn.Close() - log.Errorf("dial new session to node %s failed: %v", id, err) + log.WithField("node", id).WithError(err).Error("dial new session failed") return } sess, loaded := p.LoadOrStore(id, newSess) if loaded { newSess.Close() } - return sess.Sess.Open() + return sess.Sess.OpenStream() } // Set tries to set a new connection to the pool, typically from Accept() diff --git a/rpc/pool_test.go b/rpc/pool_test.go index 69abbcdfa..6e003e901 100644 --- a/rpc/pool_test.go +++ b/rpc/pool_test.go @@ -25,8 +25,8 @@ import ( "github.com/CovenantSQL/CovenantSQL/proto" "github.com/CovenantSQL/CovenantSQL/utils" "github.com/CovenantSQL/CovenantSQL/utils/log" - "github.com/hashicorp/yamux" . "github.com/smartystreets/goconvey/convey" + mux "github.com/xtaci/smux" ) const ( @@ -53,9 +53,9 @@ func server(c C, localAddr string, wg *sync.WaitGroup, p *SessionPool, n int) er conn, err := listener.Accept() c.So(err, ShouldBeNil) - // Setup server side of yamux + // Setup server side of mux log.Println("creating server session") - session, err := yamux.Server(conn, nil) + session, err := mux.Server(conn, nil) c.So(err, ShouldBeNil) for i := 0; i < concurrency; i++ { @@ -68,7 +68,7 @@ func server(c C, localAddr string, wg *sync.WaitGroup, p *SessionPool, n int) er //c2.So(string(buf1), ShouldEqual, "ping") defer wg.Done() log.Println("accepting stream") - stream, err := session.Accept() + stream, err := session.AcceptStream() if err == nil { buf1 := make([]byte, 4) for i := 0; i < n; i++ { diff --git a/rpc/rpcutil.go b/rpc/rpcutil.go index 5b9033496..cf971c554 100644 --- a/rpc/rpcutil.go +++ b/rpc/rpcutil.go @@ -29,7 +29,7 @@ import ( "github.com/CovenantSQL/CovenantSQL/proto" "github.com/CovenantSQL/CovenantSQL/route" "github.com/CovenantSQL/CovenantSQL/utils/log" - "github.com/hashicorp/yamux" + mux "github.com/xtaci/smux" ) var ( @@ -68,13 +68,13 @@ func (c *PersistentCaller) initClient(method string) (err error) { var conn net.Conn conn, err = DialToNode(c.TargetID, c.pool, method == route.DHTPing.String()) if err != nil { - log.Errorf("dialing to node: %s failed: %s", c.TargetID, err) + log.WithField("target", c.TargetID).WithError(err).Error("dial to node failed") return } //conn.SetDeadline(time.Time{}) c.client, err = InitClientConn(conn) if err != nil { - log.Errorf("init RPC client failed: %s", err) + log.WithError(err).Error("init RPC client failed") return } } @@ -83,7 +83,11 @@ func (c *PersistentCaller) initClient(method string) (err error) { // Call invokes the named function, waits for it to complete, and returns its error status. func (c *PersistentCaller) Call(method string, args interface{}, reply interface{}) (err error) { - c.initClient(method) + err = c.initClient(method) + if err != nil { + log.WithError(err).Error("init PersistentCaller client failed") + return + } err = c.client.Call(method, args, reply) if err != nil { if err == io.EOF || err == io.ErrUnexpectedEOF { @@ -92,26 +96,39 @@ func (c *PersistentCaller) Call(method string, args interface{}, reply interface c.Close() c.client = nil c.Unlock() - c.initClient(method) + err = c.initClient(method) + if err != nil { + log.WithField("rpc", method).WithError(err).Error("second init client for RPC failed") + return + } err = c.client.Call(method, args, reply) if err != nil { - log.Errorf("second time call RPC %s failed: %v", method, err) + log.WithField("rpc", method).WithError(err).Error("second time call RPC failed") return } } - log.Errorf("call RPC %s failed: %v", method, err) + log.WithField("rpc", method).WithError(err).Error("call RPC failed") } return } // Close closes the stream and RPC client -func (c *PersistentCaller) Close() { - stream, ok := c.client.Conn.(*yamux.Stream) - if ok { - stream.Close() +func (c *PersistentCaller) CloseStream() { + if c.client != nil { + if c.client.Conn != nil { + stream, ok := c.client.Conn.(*mux.Stream) + if ok { + stream.Close() + } + } + c.client.Close() } - c.client.Close() - c.pool.Remove(c.TargetID) +} + +// Close closes the stream and RPC client +func (c *PersistentCaller) Close() { + c.CloseStream() + //c.pool.Remove(c.TargetID) } // Caller is a wrapper for session pooling and RPC calling. @@ -137,14 +154,14 @@ func (c *Caller) CallNodeWithContext( ctx context.Context, node proto.NodeID, method string, args interface{}, reply interface{}) (err error) { conn, err := DialToNode(node, c.pool, method == route.DHTPing.String()) if err != nil { - log.Errorf("dialing to node: %s failed: %s", node, err) + log.WithField("node", node).WithError(err).Error("dial to node failed") return } defer func() { - // call the yamux stream Close explicitly + // call the mux stream Close explicitly //TODO(auxten) maybe a rpc client pool will gain much more performance - stream, ok := conn.(*yamux.Stream) + stream, ok := conn.(*mux.Stream) if ok { stream.Close() } @@ -152,7 +169,7 @@ func (c *Caller) CallNodeWithContext( client, err := InitClientConn(conn) if err != nil { - log.Errorf("init RPC client failed: %s", err) + log.WithError(err).Error("init RPC client failed") return } @@ -175,16 +192,16 @@ func (c *Caller) CallNodeWithContext( func GetNodeAddr(id *proto.RawNodeID) (addr string, err error) { addr, err = route.GetNodeAddrCache(id) if err != nil { - log.Infof("get node %s addr failed: %s", id, err) + log.WithField("target", id.String()).WithError(err).Info("get node addr from cache failed") if err == route.ErrUnknownNodeID { BPs := route.GetBPs() if len(BPs) == 0 { - log.Errorf("no available BP") + log.Error("no available BP") return } client := NewCaller() reqFN := &proto.FindNodeReq{ - NodeID: proto.NodeID(id.String()), + ID: proto.NodeID(id.String()), } respFN := new(proto.FindNodeResp) @@ -192,7 +209,10 @@ func GetNodeAddr(id *proto.RawNodeID) (addr string, err error) { method := "DHT.FindNode" err = client.CallNode(bp, method, reqFN, respFN) if err != nil { - log.Errorf("call %s %s failed: %s", bp, method, err) + log.WithFields(log.Fields{ + "bpNode": bp, + "rpc": method, + }).WithError(err).Error("call dht rpc failed") return } route.SetNodeAddrCache(id, respFN.Node.Addr) @@ -206,33 +226,36 @@ func GetNodeAddr(id *proto.RawNodeID) (addr string, err error) { func GetNodeInfo(id *proto.RawNodeID) (nodeInfo *proto.Node, err error) { nodeInfo, err = kms.GetNodeInfo(proto.NodeID(id.String())) if err != nil { - log.Infof("get node info from KMS for %s failed: %s", id, err) + log.WithField("target", id.String()).WithError(err).Info("get node info from KMS failed") if err == kms.ErrKeyNotFound { BPs := route.GetBPs() if len(BPs) == 0 { - log.Errorf("no available BP") + log.Error("no available BP") return } client := NewCaller() reqFN := &proto.FindNodeReq{ - NodeID: proto.NodeID(id.String()), + ID: proto.NodeID(id.String()), } respFN := new(proto.FindNodeResp) bp := BPs[rand.Intn(len(BPs))] method := "DHT.FindNode" err = client.CallNode(bp, method, reqFN, respFN) if err != nil { - log.Errorf("call %s %s failed: %s", bp, method, err) + log.WithFields(log.Fields{ + "bpNode": bp, + "rpc": method, + }).WithError(err).Error("call dht rpc failed") return } nodeInfo = respFN.Node errSet := route.SetNodeAddrCache(id, nodeInfo.Addr) if errSet != nil { - log.Warnf("set node addr cache failed: %v", errSet) + log.WithError(errSet).Warning("set node addr cache failed") } errSet = kms.SetNode(nodeInfo) if errSet != nil { - log.Warnf("set node to kms failed: %v", errSet) + log.WithError(errSet).Warning("set node to kms failed") } } } @@ -250,10 +273,10 @@ func PingBP(node *proto.Node, BPNodeID proto.NodeID) (err error) { resp := new(proto.PingResp) err = client.CallNode(BPNodeID, "DHT.Ping", req, resp) if err != nil { - log.Errorf("call DHT.Ping failed: %v", err) + log.WithError(err).Error("call DHT.Ping failed") return } - log.Debugf("PingBP resp: %v", resp) + log.Debugf("PingBP resp: %#v", resp) return } @@ -285,7 +308,7 @@ func GetCurrentBP() (bpNodeID proto.NodeID, err error) { // call random block producer for nearest block producer node req := &proto.FindNeighborReq{ - NodeID: localNodeID, + ID: localNodeID, Roles: []proto.ServerRole{ proto.Leader, // only leader is capable of allocating database in current implementation diff --git a/rpc/rpcutil_test.go b/rpc/rpcutil_test.go index e10da5c6d..c3442336c 100644 --- a/rpc/rpcutil_test.go +++ b/rpc/rpcutil_test.go @@ -21,12 +21,11 @@ import ( "os" "path/filepath" "runtime" + "strings" "sync" "testing" "time" - "strings" - "github.com/CovenantSQL/CovenantSQL/conf" "github.com/CovenantSQL/CovenantSQL/consistent" "github.com/CovenantSQL/CovenantSQL/crypto/kms" @@ -40,7 +39,7 @@ import ( const ( DHTStorePath = "./DHTStore" RPCConcurrent = 10 - RPCCount = 10 + RPCCount = 100 ) func TestCaller_CallNode(t *testing.T) { @@ -64,7 +63,7 @@ func TestCaller_CallNode(t *testing.T) { masterKey := []byte("") dht, err := route.NewDHTService(PubKeyStorePath, new(consistent.KMSStorage), true) - server, err := NewServerWithService(ServiceMap{"DHT": dht}) + server, err := NewServerWithService(ServiceMap{route.DHTRPCName: dht}) if err != nil { t.Fatal(err) } @@ -90,7 +89,7 @@ func TestCaller_CallNode(t *testing.T) { } respA := new(proto.PingResp) - err = client.CallNode(conf.GConf.BP.NodeID, "DHT.Ping", reqA, respA) + err = client.CallNode(conf.GConf.BP.NodeID, route.DHTPing.String(), reqA, respA) if err != nil { t.Fatal(err) } @@ -160,6 +159,7 @@ func TestCaller_CallNode(t *testing.T) { } server.Stop() + client.pool.Close() } func TestNewPersistentCaller(t *testing.T) { @@ -169,18 +169,8 @@ func TestNewPersistentCaller(t *testing.T) { os.Remove(publicKeyStore) defer os.Remove(publicKeyStore) - ctx, cancel := context.WithTimeout(context.Background(), time.Second*15) - defer cancel() - err := utils.WaitForPorts(ctx, "127.0.0.1", []int{ - 2230, - }, time.Millisecond*200) - - if err != nil { - log.Fatalf("wait for port ready timeout: %v", err) - } - _, testFile, _, _ := runtime.Caller(0) - confFile := filepath.Join(filepath.Dir(testFile), "../test/node_standalone/config.yaml") + confFile := filepath.Join(filepath.Dir(testFile), "../test/node_standalone/config2.yaml") privateKeyPath := filepath.Join(filepath.Dir(testFile), "../test/node_standalone/private.key") conf.GConf, _ = conf.LoadConfig(confFile) @@ -193,12 +183,25 @@ func TestNewPersistentCaller(t *testing.T) { masterKey := []byte("") dht, err := route.NewDHTService(PubKeyStorePath, new(consistent.KMSStorage), true) - server, err := NewServerWithService(ServiceMap{"DHT": dht}) + server, err := NewServerWithService(ServiceMap{route.DHTRPCName: dht}) if err != nil { t.Fatal(err) } - server.InitRPCServer(addr, privateKeyPath, masterKey) + ctx, cancel := context.WithTimeout(context.Background(), time.Second*15) + defer cancel() + err = utils.WaitForPorts(ctx, "127.0.0.1", []int{ + 12230, + }, time.Millisecond*200) + + if err != nil { + log.Fatalf("wait for port ready timeout: %v", err) + } + + err = server.InitRPCServer(addr, privateKeyPath, masterKey) + if err != nil { + t.Fatal(err) + } go server.Serve() client := NewPersistentCaller(conf.GConf.BP.NodeID) @@ -218,8 +221,8 @@ func TestNewPersistentCaller(t *testing.T) { log.Debugf("respA: %v", respA) req := &proto.FindNeighborReq{ - NodeID: "1234", - Count: 10, + ID: "1234567812345678123456781234567812345678123456781234567812345678", + Count: 10, } resp := new(proto.FindNeighborResp) @@ -234,13 +237,13 @@ func TestNewPersistentCaller(t *testing.T) { wg := sync.WaitGroup{} client = NewPersistentCaller(conf.GConf.BP.NodeID) + wg.Add(RPCConcurrent * RPCCount) for i := 0; i < RPCConcurrent; i++ { - wg.Add(1) go func(tt *testing.T, wg *sync.WaitGroup) { for j := 0; j < RPCCount; j++ { reqF := &proto.FindNeighborReq{ - NodeID: "1234", - Count: 10, + ID: "1234567812345678123456781234567812345678123456781234567812345678", + Count: 10, } respF := new(proto.FindNeighborResp) err := client.Call("DHT.FindNeighbor", reqF, respF) @@ -248,13 +251,38 @@ func TestNewPersistentCaller(t *testing.T) { tt.Error(err) } log.Debugf("resp: %v", respF) + wg.Done() } - wg.Done() }(t, &wg) } + client2 := NewPersistentCaller(conf.GConf.BP.NodeID) + reqF2 := &proto.FindNeighborReq{ + ID: "1234567812345678123456781234567812345678123456781234567812345678", + Count: 10, + } + respF2 := new(proto.FindNeighborResp) + + err = client2.Call("DHT.FindNeighbor", reqF2, respF2) + if err != nil { + t.Error(err) + } + client2.CloseStream() + wg.Wait() - server.Stop() + sess, ok := client2.pool.getSessionFromPool(conf.GConf.BP.NodeID) + if !ok { + t.Fatalf("can not find session for %s", conf.GConf.BP.NodeID) + } + sess.conn.Close() + + client3 := NewPersistentCaller(conf.GConf.BP.NodeID) + err = client3.Call("DHT.FindNeighbor", reqF2, respF2) + if err != nil { + t.Error(err) + } + client3.CloseStream() + } func BenchmarkPersistentCaller_Call(b *testing.B) { @@ -288,7 +316,7 @@ func BenchmarkPersistentCaller_Call(b *testing.B) { masterKey := []byte("") dht, err := route.NewDHTService(PubKeyStorePath, new(consistent.KMSStorage), true) - server, err := NewServerWithService(ServiceMap{"DHT": dht}) + server, err := NewServerWithService(ServiceMap{route.DHTRPCName: dht}) if err != nil { b.Fatal(err) } @@ -312,14 +340,30 @@ func BenchmarkPersistentCaller_Call(b *testing.B) { } log.Debugf("respA: %v", respA) + client = NewPersistentCaller(conf.GConf.BP.NodeID) + b.Run("benchmark Persistent Call Nil", func(b *testing.B) { + var ( + req proto.PingReq + resp proto.PingResp + ) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + err = client.Call("DHT.Nil", &req, &resp) + if err != nil { + b.Error(err) + } + } + }) + req := &proto.FindNeighborReq{ - NodeID: "1234", - Count: 10, + ID: "1234567812345678123456781234567812345678123456781234567812345678", + Count: 10, } resp := new(proto.FindNeighborResp) - b.Run("benchmark Persistent", func(b *testing.B) { - client = NewPersistentCaller(conf.GConf.BP.NodeID) + client = NewPersistentCaller(conf.GConf.BP.NodeID) + b.Run("benchmark Persistent Call", func(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { err = client.Call("DHT.FindNeighbor", req, resp) @@ -329,6 +373,32 @@ func BenchmarkPersistentCaller_Call(b *testing.B) { } }) + routineCount := runtime.NumGoroutine() + if routineCount > 100 { + b.Errorf("go routine count: %d", routineCount) + } else { + log.Infof("go routine count: %d", routineCount) + } + + b.Run("benchmark Persistent New and Call", func(b *testing.B) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + client = NewPersistentCaller(conf.GConf.BP.NodeID) + err = client.Call("DHT.FindNeighbor", req, resp) + if err != nil { + b.Error(err) + } + client.Close() + } + }) + + routineCount = runtime.NumGoroutine() + if routineCount > 100 { + b.Errorf("go routine count: %d", routineCount) + } else { + log.Infof("go routine count: %d", routineCount) + } + b.Run("benchmark non-Persistent", func(b *testing.B) { oldClient := NewCaller() b.ResetTimer() @@ -339,5 +409,13 @@ func BenchmarkPersistentCaller_Call(b *testing.B) { } } }) + + routineCount = runtime.NumGoroutine() + if routineCount > 100 { + b.Errorf("go routine count: %d", routineCount) + } else { + log.Infof("go routine count: %d", routineCount) + } + server.Stop() } diff --git a/rpc/server.go b/rpc/server.go index 321d9169c..159ad76a0 100644 --- a/rpc/server.go +++ b/rpc/server.go @@ -26,9 +26,9 @@ import ( "github.com/CovenantSQL/CovenantSQL/crypto/kms" "github.com/CovenantSQL/CovenantSQL/pow/cpuminer" "github.com/CovenantSQL/CovenantSQL/proto" + "github.com/CovenantSQL/CovenantSQL/utils" "github.com/CovenantSQL/CovenantSQL/utils/log" - "github.com/hashicorp/yamux" - "github.com/ugorji/go/codec" + mux "github.com/xtaci/smux" ) // ServiceMap maps service name to service instance @@ -63,13 +63,13 @@ func (s *Server) InitRPCServer( err = kms.InitLocalKeyPair(privateKeyPath, masterKey) if err != nil { - log.Errorf("init local key pair failed: %s", err) + log.WithError(err).Error("init local key pair failed") return } l, err := etls.NewCryptoListener("tcp", addr, handleCipher) if err != nil { - log.Errorf("create crypto listener failed: %s", err) + log.WithError(err).Error("create crypto listener failed") return } @@ -80,7 +80,6 @@ func (s *Server) InitRPCServer( // NewServerWithService also return a new Server, and also register the Server.ServiceMap func NewServerWithService(serviceMap ServiceMap) (server *Server, err error) { - server = NewServer() for k, v := range serviceMap { err = server.RegisterService(k, v) @@ -108,7 +107,6 @@ serverLoop: default: conn, err := s.Listener.Accept() if err != nil { - log.Info(err) continue } go s.handleConn(conn) @@ -128,7 +126,7 @@ func (s *Server) handleConn(conn net.Conn) { remoteNodeID = c.NodeID } - sess, err := yamux.Server(conn, YamuxConfig) + sess, err := mux.Server(conn, YamuxConfig) if err != nil { log.Error(err) return @@ -145,23 +143,16 @@ sessionLoop: muxConn, err := sess.AcceptStream() if err != nil { if err == io.EOF { - log.Infof("session %s connection closed", remoteNodeID) + log.WithField("remote", remoteNodeID).Debug("session connection closed") } else { - log.Errorf("session %s accept failed: %s", remoteNodeID, err) + log.WithField("remote", remoteNodeID).WithError(err).Error("session accept failed") } break sessionLoop } - log.Debugf("session accepted %d for %v", muxConn.StreamID(), remoteNodeID) - msgpackCodec := codec.MsgpackSpecRpc.ServerCodec(muxConn, &codec.MsgpackHandle{ - WriteExt: true, - RawToString: true, - }) - nodeAwareCodec := NewNodeAwareServerCodec(msgpackCodec, remoteNodeID) + nodeAwareCodec := NewNodeAwareServerCodec(utils.GetMsgPackServerCodec(muxConn), remoteNodeID) go s.rpcServer.ServeCodec(nodeAwareCodec) } } - - log.Debugf("Server.handleConn finished for %s %s", remoteNodeID, conn.RemoteAddr()) } // RegisterService with a Service name, used by Client RPC @@ -182,7 +173,7 @@ func handleCipher(conn net.Conn) (cryptoConn *etls.CryptoConn, err error) { headerBuf := make([]byte, hash.HashBSize+32) rCount, err := conn.Read(headerBuf) if err != nil || rCount != hash.HashBSize+32 { - log.Errorf("read node header error: %s", err) + log.WithError(err).Error("read node header error") return } @@ -197,7 +188,7 @@ func handleCipher(conn net.Conn) (cryptoConn *etls.CryptoConn, err error) { rawNodeID.IsEqual(&kms.AnonymousRawNodeID.Hash), ) if err != nil { - log.Errorf("get shared secret for %s failed: %s", rawNodeID.ToNodeID(), err) + log.WithField("target", rawNodeID.String()).WithError(err).Error("get shared secret") return } cipher := etls.NewCipher(symmetricKey) diff --git a/rpc/server_test.go b/rpc/server_test.go index ba901f804..04b92bcc8 100644 --- a/rpc/server_test.go +++ b/rpc/server_test.go @@ -59,14 +59,20 @@ func NewTestService() *TestService { } func (s *TestService) IncCounter(req *TestReq, rep *TestRep) error { - log.Debugf("calling IncCounter req:%v, rep:%v", *req, *rep) + log.WithFields(log.Fields{ + "req": *req, + "reply": *rep, + }).Debug("calling IncCounter") s.counter += req.Step rep.Ret = s.counter return nil } func (s *TestService) IncCounterSimpleArgs(step int, ret *int) error { - log.Debugf("calling IncCounter req:%v, rep:%v", step, ret) + log.WithFields(log.Fields{ + "req": step, + "reply": ret, + }).Debug("calling IncCounter") s.counter += step *ret = s.counter return nil @@ -187,7 +193,7 @@ func TestEncPingFindNeighbor(t *testing.T) { masterKey := []byte("abc") dht, err := route.NewDHTService(PubKeyStorePath, new(consistent.KMSStorage), true) - server, err := NewServerWithService(ServiceMap{"DHT": dht}) + server, err := NewServerWithService(ServiceMap{route.DHTRPCName: dht}) if err != nil { log.Fatal(err) } @@ -238,8 +244,8 @@ func TestEncPingFindNeighbor(t *testing.T) { log.Debugf("respB: %v", respB) req := &proto.FindNeighborReq{ - NodeID: "123", - Count: 10, + ID: "1234567812345678123456781234567812345678123456781234567812345678", + Count: 10, } resp := new(proto.FindNeighborResp) err = client.Call("DHT.FindNeighbor", req, resp) diff --git a/rpc/sharedsecret.go b/rpc/sharedsecret.go index 936a1179e..e9166a1c3 100644 --- a/rpc/sharedsecret.go +++ b/rpc/sharedsecret.go @@ -17,6 +17,8 @@ package rpc import ( + "sync" + "github.com/CovenantSQL/CovenantSQL/conf" "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" "github.com/CovenantSQL/CovenantSQL/crypto/kms" @@ -25,42 +27,53 @@ import ( "github.com/CovenantSQL/CovenantSQL/utils/log" ) +var symmetricKeyCache sync.Map + // GetSharedSecretWith gets shared symmetric key with ECDH func GetSharedSecretWith(nodeID *proto.RawNodeID, isAnonymous bool) (symmetricKey []byte, err error) { if isAnonymous { symmetricKey = []byte(`!&\\!qEyey*\cbLc,aKl`) log.Debug("using anonymous ETLS") } else { - var remotePublicKey *asymmetric.PublicKey - if route.IsBPNodeID(nodeID) { - remotePublicKey = kms.BP.PublicKey - } else if conf.RoleTag[0] == conf.BlockProducerBuildTag[0] { - remotePublicKey, err = kms.GetPublicKey(proto.NodeID(nodeID.String())) - if err != nil { - log.Errorf("get public key locally failed, node id: %s, err: %s", nodeID.ToNodeID(), err) - return - } + symmetricKeyI, ok := symmetricKeyCache.Load(nodeID) + if ok { + symmetricKey, _ = symmetricKeyI.([]byte) } else { - // if non BP running and key not found, ask BlockProducer - var nodeInfo *proto.Node - nodeInfo, err = GetNodeInfo(nodeID) + var remotePublicKey *asymmetric.PublicKey + if route.IsBPNodeID(nodeID) { + remotePublicKey = kms.BP.PublicKey + } else if conf.RoleTag[0] == conf.BlockProducerBuildTag[0] { + remotePublicKey, err = kms.GetPublicKey(proto.NodeID(nodeID.String())) + if err != nil { + log.WithField("node", nodeID).WithError(err).Error("get public key locally failed") + return + } + } else { + // if non BP running and key not found, ask BlockProducer + var nodeInfo *proto.Node + nodeInfo, err = GetNodeInfo(nodeID) + if err != nil { + log.WithField("node", nodeID).WithError(err).Error("get public key failed") + return + } + remotePublicKey = nodeInfo.PublicKey + } + + var localPrivateKey *asymmetric.PrivateKey + localPrivateKey, err = kms.GetLocalPrivateKey() if err != nil { - log.Errorf("get public key failed, node id: %s, err: %s", nodeID.ToNodeID(), err) + log.WithError(err).Error("get local private key failed") return } - remotePublicKey = nodeInfo.PublicKey - } - var localPrivateKey *asymmetric.PrivateKey - localPrivateKey, err = kms.GetLocalPrivateKey() - if err != nil { - log.Errorf("get local private key failed: %s", err) - return + symmetricKey = asymmetric.GenECDHSharedSecret(localPrivateKey, remotePublicKey) + symmetricKeyCache.Store(nodeID, symmetricKey) + log.WithFields(log.Fields{ + "node": nodeID.String(), + "remotePub": remotePublicKey.Serialize(), + "sessionKey": symmetricKey, + }).Debug("generated shared secret") } - - symmetricKey = asymmetric.GenECDHSharedSecret(localPrivateKey, remotePublicKey) - log.Debugf("ECDH for %s Public Key: %x, Session Key: %x", - nodeID.ToNodeID(), remotePublicKey.Serialize(), symmetricKey) //log.Debugf("ECDH for %s Public Key: %x, Private Key: %x Session Key: %x", // nodeID.ToNodeID(), remotePublicKey.Serialize(), localPrivateKey.Serialize(), symmetricKey) } diff --git a/sqlchain/blockindex_test.go b/sqlchain/blockindex_test.go index c00691765..df47a4cdd 100644 --- a/sqlchain/blockindex_test.go +++ b/sqlchain/blockindex_test.go @@ -55,7 +55,7 @@ func TestNewBlockNode(t *testing.T) { parent := newBlockNode(0, testBlocks[0], nil) if parent == nil { - t.Fatalf("unexpected result: nil") + t.Fatal("unexpected result: nil") } else if parent.parent != nil { t.Fatalf("unexpected parent: %v", parent.parent) } else if parent.count != 0 { @@ -65,7 +65,7 @@ func TestNewBlockNode(t *testing.T) { child := newBlockNode(1, testBlocks[1], parent) if child == nil { - t.Fatalf("unexpected result: nil") + t.Fatal("unexpected result: nil") } else if child.parent != parent { t.Fatalf("unexpected parent: %v", child.parent) } else if child.count != parent.count+1 { @@ -89,7 +89,7 @@ func TestInitBlockNode(t *testing.T) { parent.initBlockNode(0, testBlocks[0], nil) if parent == nil { - t.Fatalf("unexpected result: nil") + t.Fatal("unexpected result: nil") } else if parent.parent != nil { t.Fatalf("unexpected parent: %v", parent.parent) } else if parent.count != 0 { @@ -99,7 +99,7 @@ func TestInitBlockNode(t *testing.T) { child.initBlockNode(1, testBlocks[1], parent) if child == nil { - t.Fatalf("unexpected result: nil") + t.Fatal("unexpected result: nil") } else if child.parent != parent { t.Fatalf("unexpected parent: %v", child.parent) } else if child.count != parent.count+1 { diff --git a/sqlchain/chain.go b/sqlchain/chain.go index 8817ed6e4..8984fd8aa 100644 --- a/sqlchain/chain.go +++ b/sqlchain/chain.go @@ -21,7 +21,6 @@ import ( "encoding/binary" "fmt" "os" - "reflect" "sync" "time" @@ -38,7 +37,6 @@ import ( "github.com/CovenantSQL/CovenantSQL/utils" "github.com/CovenantSQL/CovenantSQL/utils/log" wt "github.com/CovenantSQL/CovenantSQL/worker/types" - "github.com/coreos/bbolt" "github.com/pkg/errors" "github.com/syndtr/goleveldb/leveldb" "github.com/syndtr/goleveldb/leveldb/opt" @@ -46,14 +44,12 @@ import ( ) var ( - metaBucket = [4]byte{0x0, 0x0, 0x0, 0x0} - metaStateKey = []byte("covenantsql-state") - metaBlockIndexBucket = []byte("covenantsql-block-index-bucket") - metaHeightIndexBucket = []byte("covenantsql-query-height-index-bucket") - metaRequestIndexBucket = []byte("covenantsql-query-request-index-bucket") - metaResponseIndexBucket = []byte("covenantsql-query-response-index-bucket") - metaAckIndexBucket = [4]byte{'Q', 'A', 'C', 'K'} - leveldbConf = opt.Options{} + metaState = [4]byte{'S', 'T', 'A', 'T'} + metaBlockIndex = [4]byte{'B', 'L', 'C', 'K'} + metaRequestIndex = [4]byte{'R', 'E', 'Q', 'U'} + metaResponseIndex = [4]byte{'R', 'E', 'S', 'P'} + metaAckIndex = [4]byte{'Q', 'A', 'C', 'K'} + leveldbConf = opt.Options{} ) func init() { @@ -75,10 +71,28 @@ func keyToHeight(k []byte) int32 { return int32(binary.BigEndian.Uint32(k)) } +// keyWithSymbolToHeight converts a height back from a key(ack/resp/req/block) in bytes. +// ack key: +// ['Q', 'A', 'C', 'K', height, hash] +// resp key: +// ['R', 'E', 'S', 'P', height, hash] +// req key: +// ['R', 'E', 'Q', 'U', height, hash] +// block key: +// ['B', 'L', 'C', 'K', height, hash] +func keyWithSymbolToHeight(k []byte) int32 { + if len(k) < 8 { + return -1 + } + return int32(binary.BigEndian.Uint32(k[4:])) +} + // Chain represents a sql-chain. type Chain struct { - db *bolt.DB - ldb *leveldb.DB + // bdb stores state and block + bdb *leveldb.DB + // tdb stores ack/request/response + tdb *leveldb.DB bi *blockIndex qi *queryIndex cl *rpc.Caller @@ -107,7 +121,7 @@ func NewChain(c *Config) (chain *Chain, err error) { // TODO(leventeliu): this is a rough solution, you may also want to clean database file and // force rebuilding. var fi os.FileInfo - if fi, err = os.Stat(c.DataFile); err == nil && fi.Mode().IsRegular() { + if fi, err = os.Stat(c.DataFile + "-block-state.ldb"); err == nil && fi.Mode().IsDir() { return LoadChain(c) } @@ -116,42 +130,26 @@ func NewChain(c *Config) (chain *Chain, err error) { return } - // Open DB file - db, err := bolt.Open(c.DataFile, 0600, nil) + // Open LevelDB for block and state + bdbFile := c.DataFile + "-block-state.ldb" + bdb, err := leveldb.OpenFile(bdbFile, &leveldbConf) if err != nil { + err = errors.Wrapf(err, "open leveldb %s", bdbFile) return } - // Create buckets for chain meta - if err = db.Update(func(tx *bolt.Tx) (err error) { - bucket, err := tx.CreateBucketIfNotExists(metaBucket[:]) - - if err != nil { - return - } - - if _, err = bucket.CreateBucketIfNotExists(metaBlockIndexBucket); err != nil { - return - } - - _, err = bucket.CreateBucketIfNotExists(metaHeightIndexBucket) - return - }); err != nil { - return - } - - // Open LevelDB - ldbFile := c.DataFile + ".ldb" - ldb, err := leveldb.OpenFile(ldbFile, &leveldbConf) + // Open LevelDB for ack/request/response + tdbFile := c.DataFile + "-ack-req-resp.ldb" + tdb, err := leveldb.OpenFile(tdbFile, &leveldbConf) if err != nil { - err = errors.Wrapf(err, "open leveldb %s", ldbFile) + err = errors.Wrapf(err, "open leveldb %s", tdbFile) return } // Create chain state chain = &Chain{ - db: db, - ldb: ldb, + bdb: bdb, + tdb: tdb, bi: newBlockIndex(c), qi: newQueryIndex(), cl: rpc.NewCaller(), @@ -177,24 +175,27 @@ func NewChain(c *Config) (chain *Chain, err error) { // LoadChain loads the chain state from the specified database and rebuilds a memory index. func LoadChain(c *Config) (chain *Chain, err error) { - // Open DB file - db, err := bolt.Open(c.DataFile, 0600, nil) + + // Open LevelDB for block and state + bdbFile := c.DataFile + "-block-state.ldb" + bdb, err := leveldb.OpenFile(bdbFile, &leveldbConf) if err != nil { + err = errors.Wrapf(err, "open leveldb %s", bdbFile) return } - // Open LevelDB - ldbFile := c.DataFile + ".ldb" - ldb, err := leveldb.OpenFile(ldbFile, &leveldbConf) + // Open LevelDB for ack/request/response + tdbFile := c.DataFile + "-ack-req-resp.ldb" + tdb, err := leveldb.OpenFile(tdbFile, &leveldbConf) if err != nil { - err = errors.Wrapf(err, "open leveldb %s", ldbFile) + err = errors.Wrapf(err, "open leveldb %s", tdbFile) return } // Create chain state chain = &Chain{ - db: db, - ldb: ldb, + bdb: bdb, + tdb: tdb, bi: newBlockIndex(c), qi: newQueryIndex(), cl: rpc.NewCaller(), @@ -211,145 +212,133 @@ func LoadChain(c *Config) (chain *Chain, err error) { replCh: make(chan struct{}), } - err = chain.db.View(func(tx *bolt.Tx) (err error) { - // Read state struct - meta := tx.Bucket(metaBucket[:]) - metaEnc := meta.Get(metaStateKey) - if metaEnc == nil { - return ErrMetaStateNotFound - } - st := &state{} - if err = utils.DecodeMsgPack(metaEnc, st); err != nil { - return err + // Read state struct + stateEnc, err := chain.bdb.Get(metaState[:], nil) + if err != nil { + return nil, err + } + st := &state{} + if err = utils.DecodeMsgPack(stateEnc, st); err != nil { + return nil, err + } + + log.WithFields(log.Fields{ + "peer": chain.rt.getPeerInfoString(), + "state": st, + }).Debug("Loading state from database") + + // Read blocks and rebuild memory index + var last *blockNode + var index int32 + // TODO(lambda): select a better init length + nodes := make([]blockNode, 100) + blockIter := chain.bdb.NewIterator(util.BytesPrefix(metaBlockIndex[:]), nil) + defer blockIter.Release() + for blockIter.Next() { + k := blockIter.Key() + v := blockIter.Value() + + block := &ct.Block{} + + if err = utils.DecodeMsgPack(v, block); err != nil { + err = errors.Wrapf(err, "block height %d, key index %s", keyWithSymbolToHeight(k), string(k)) + return } log.WithFields(log.Fields{ "peer": chain.rt.getPeerInfoString(), - "state": st, - }).Debug("Loading state from database") - - // Read blocks and rebuild memory index - var last *blockNode - var index int32 - blocks := meta.Bucket(metaBlockIndexBucket) - nodes := make([]blockNode, blocks.Stats().KeyN) + "block": block.BlockHash().String(), + }).Debug("Loading block from database") + parent := (*blockNode)(nil) - if err = blocks.ForEach(func(k, v []byte) (err error) { - block := &ct.Block{} - - if err = utils.DecodeMsgPack(v, block); err != nil { + if last == nil { + if err = block.VerifyAsGenesis(); err != nil { return } - log.WithFields(log.Fields{ - "peer": chain.rt.getPeerInfoString(), - "block": block.BlockHash().String(), - }).Debug("Loading block from database") - parent := (*blockNode)(nil) - - if last == nil { - if err = block.VerifyAsGenesis(); err != nil { - return - } - - // Set constant fields from genesis block - chain.rt.setGenesis(block) - } else if block.ParentHash().IsEqual(&last.hash) { - if err = block.Verify(); err != nil { - return - } + // Set constant fields from genesis block + chain.rt.setGenesis(block) + } else if block.ParentHash().IsEqual(&last.hash) { + if err = block.Verify(); err != nil { + return + } - parent = last - } else { - parent = chain.bi.lookupNode(block.ParentHash()) + parent = last + } else { + parent = chain.bi.lookupNode(block.ParentHash()) - if parent == nil { - return ErrParentNotFound - } + if parent == nil { + return nil, ErrParentNotFound } + } - height := chain.rt.getHeightFromTime(block.Timestamp()) - nodes[index].initBlockNode(height, block, parent) - chain.bi.addBlock(&nodes[index]) - last = &nodes[index] - index++ + height := chain.rt.getHeightFromTime(block.Timestamp()) + nodes[index].initBlockNode(height, block, parent) + chain.bi.addBlock(&nodes[index]) + last = &nodes[index] + index++ + } + if err = blockIter.Error(); err != nil { + err = errors.Wrap(err, "load block") + return + } + + // Set chain state + st.node = last + chain.rt.setHead(st) + + // Read queries and rebuild memory index + respIter := chain.tdb.NewIterator(util.BytesPrefix(metaResponseIndex[:]), nil) + defer respIter.Release() + for respIter.Next() { + k := respIter.Key() + v := respIter.Value() + h := keyWithSymbolToHeight(k) + var resp = &wt.SignedResponseHeader{} + if err = utils.DecodeMsgPack(v, resp); err != nil { + err = errors.Wrapf(err, "load resp, height %d, index %s", h, string(k)) return - }); err != nil { + } + log.WithFields(log.Fields{ + "height": h, + "header": resp.HeaderHash.String(), + }).Debug("Loaded new resp header") + err = chain.qi.addResponse(h, resp) + if err != nil { + err = errors.Wrapf(err, "load resp, height %d, hash %s", h, resp.HeaderHash.String()) return } + } + if err = respIter.Error(); err != nil { + err = errors.Wrap(err, "load resp") + return + } - // Set chain state - st.node = last - chain.rt.setHead(st) - - // Read queries and rebuild memory index - heights := meta.Bucket(metaHeightIndexBucket) - - if err = heights.ForEach(func(k, v []byte) (err error) { - h := keyToHeight(k) - - if resps := heights.Bucket(k).Bucket( - metaResponseIndexBucket); resps != nil { - if err = resps.ForEach(func(k []byte, v []byte) (err error) { - var resp = &wt.SignedResponseHeader{} - if err = utils.DecodeMsgPack(v, resp); err != nil { - return - } - log.WithFields(log.Fields{ - "height": h, - "header": resp.HeaderHash.String(), - }).Debug("Loaded new resp header") - return chain.qi.addResponse(h, resp) - }); err != nil { - return - } - } - - ldbKey := make([]byte, 0, len(metaAckIndexBucket)+len(k)+hash.HashSize) - ldbKey = append(append(ldbKey, metaAckIndexBucket[:]...), k...) - iter := ldb.NewIterator(util.BytesPrefix(ldbKey), nil) - defer iter.Release() - for iter.Next() { - var ack = &wt.SignedAckHeader{} - if err = utils.DecodeMsgPack(iter.Value(), ack); err != nil { - return - } - log.WithFields(log.Fields{ - "height": h, - "header": ack.HeaderHash.String(), - }).Debug("Loaded new ack header") - return chain.qi.addAck(h, ack) - } - err = iter.Error() - if err != nil { - err = errors.Wrap(err, "load new ack header") - return - } - - //acks := heights.Bucket(k).Bucket(metaAckIndexBucket) - //if acks != nil { - // if err = acks.ForEach(func(k []byte, v []byte) (err error) { - // var ack = &wt.SignedAckHeader{} - // if err = utils.DecodeMsgPack(v, ack); err != nil { - // return - // } - // log.WithFields(log.Fields{ - // "height": h, - // "header": ack.HeaderHash.String(), - // }).Debug("Loaded new ack header") - // return chain.qi.addAck(h, ack) - // }); err != nil { - // return - // } - //} - + ackIter := chain.tdb.NewIterator(util.BytesPrefix(metaAckIndex[:]), nil) + defer ackIter.Release() + for ackIter.Next() { + k := ackIter.Key() + v := ackIter.Value() + h := keyWithSymbolToHeight(k) + var ack = &wt.SignedAckHeader{} + if err = utils.DecodeMsgPack(v, ack); err != nil { + err = errors.Wrapf(err, "load ack, height %d, index %s", h, string(k)) return - }); err != nil { + } + log.WithFields(log.Fields{ + "height": h, + "header": ack.HeaderHash.String(), + }).Debug("Loaded new ack header") + err = chain.qi.addAck(h, ack) + if err != nil { + err = errors.Wrapf(err, "load ack, height %d, hash %s", h, ack.HeaderHash.String()) return } - + } + if err = respIter.Error(); err != nil { + err = errors.Wrap(err, "load ack") return - }) + } return } @@ -375,21 +364,26 @@ func (c *Chain) pushBlock(b *ct.Block) (err error) { } // Update in transaction - err = c.db.Update(func(tx *bolt.Tx) (err error) { - if err = tx.Bucket(metaBucket[:]).Put(metaStateKey, encState.Bytes()); err != nil { - return - } - - if err = tx.Bucket(metaBucket[:]).Bucket(metaBlockIndexBucket).Put( - node.indexKey(), encBlock.Bytes()); err != nil { - return - } - - c.rt.setHead(st) - c.bi.addBlock(node) - c.qi.setSignedBlock(h, b) + t, err := c.bdb.OpenTransaction() + if err = t.Put(metaState[:], encState.Bytes(), nil); err != nil { + err = errors.Wrapf(err, "put %s", string(metaState[:])) + t.Discard() + return + } + blockKey := utils.ConcatAll(metaBlockIndex[:], node.indexKey()) + if err = t.Put(blockKey, encBlock.Bytes(), nil); err != nil { + err = errors.Wrapf(err, "put %s", string(node.indexKey())) + t.Discard() + return + } + if err = t.Commit(); err != nil { + err = errors.Wrapf(err, "commit error") + t.Discard() return - }) + } + c.rt.setHead(st) + c.bi.addBlock(node) + c.qi.setSignedBlock(h, b) if err == nil { log.WithFields(log.Fields{ @@ -414,27 +408,6 @@ func (c *Chain) pushBlock(b *ct.Block) (err error) { return } -func ensureHeight(tx *bolt.Tx, k []byte) (hb *bolt.Bucket, err error) { - b := tx.Bucket(metaBucket[:]).Bucket(metaHeightIndexBucket) - - if hb = b.Bucket(k); hb == nil { - // Create and initialize bucket in new height - if hb, err = b.CreateBucketIfNotExists(k); err != nil { - return - } - - if _, err = hb.CreateBucketIfNotExists(metaRequestIndexBucket); err != nil { - return - } - - if _, err = hb.CreateBucketIfNotExists(metaResponseIndexBucket); err != nil { - return - } - } - - return -} - // pushResponedQuery pushes a responsed, signed and verified query into the chain. func (c *Chain) pushResponedQuery(resp *wt.SignedResponseHeader) (err error) { h := c.rt.getHeightFromTime(resp.Request.Timestamp) @@ -445,25 +418,23 @@ func (c *Chain) pushResponedQuery(resp *wt.SignedResponseHeader) (err error) { return } - return c.db.Update(func(tx *bolt.Tx) (err error) { - heightBucket, err := ensureHeight(tx, k) - - if err != nil { - return - } + tdbKey := utils.ConcatAll(metaResponseIndex[:], k, resp.HeaderHash[:]) + if err = c.tdb.Put(tdbKey, enc.Bytes(), nil); err != nil { + err = errors.Wrapf(err, "put response %d %s", h, resp.HeaderHash.String()) + return + } - if err = heightBucket.Bucket(metaResponseIndexBucket).Put( - resp.HeaderHash[:], enc.Bytes()); err != nil { - return - } + if err = c.qi.addResponse(h, resp); err != nil { + err = errors.Wrapf(err, "add resp h %d hash %s", h, resp.HeaderHash) + return err + } - // Always put memory changes which will not be affected by rollback after DB operations - return c.qi.addResponse(h, resp) - }) + return } // pushAckedQuery pushes a acknowledged, signed and verified query into the chain. func (c *Chain) pushAckedQuery(ack *wt.SignedAckHeader) (err error) { + log.Debugf("push ack %s", ack.HeaderHash.String()) h := c.rt.getHeightFromTime(ack.SignedResponseHeader().Timestamp) k := heightToKey(h) var enc *bytes.Buffer @@ -472,28 +443,19 @@ func (c *Chain) pushAckedQuery(ack *wt.SignedAckHeader) (err error) { return } - return c.db.Update(func(tx *bolt.Tx) (err error) { - _, err = ensureHeight(tx, k) - if err != nil { - return - } + tdbKey := utils.ConcatAll(metaAckIndex[:], k, ack.HeaderHash[:]) - ldbKey := make([]byte, 0, len(metaAckIndexBucket)+len(k)+hash.HashSize) - ldbKey = append(append(append(ldbKey, metaAckIndexBucket[:]...), k...), ack.HeaderHash[:]...) - err = c.ldb.Put(ldbKey, enc.Bytes(), nil) - //err = b.Bucket(metaAckIndexBucket).Put(ack.HeaderHash[:], enc.Bytes()) - if err != nil { - err = errors.Wrapf(err, "put %s %d %s", string(metaAckIndexBucket[:]), h, ack.HeaderHash) - return - } + if err = c.tdb.Put(tdbKey, enc.Bytes(), nil); err != nil { + err = errors.Wrapf(err, "put ack %d %s", h, ack.HeaderHash.String()) + return + } - // Always put memory changes which will not be affected by rollback after DB operations - if err = c.qi.addAck(h, ack); err != nil { - return - } + if err = c.qi.addAck(h, ack); err != nil { + err = errors.Wrapf(err, "add ack h %d hash %s", h, ack.HeaderHash) + return err + } - return - }) + return } // produceBlock prepares, signs and advises the pending block to the orther peers. @@ -708,15 +670,15 @@ func (c *Chain) mainCycle() { c.syncHead() if t, d := c.rt.nextTick(); d > 0 { - log.WithFields(log.Fields{ - "peer": c.rt.getPeerInfoString(), - "time": c.rt.getChainTimeString(), - "next_turn": c.rt.getNextTurn(), - "head_height": c.rt.getHead().Height, - "head_block": c.rt.getHead().Head.String(), - "using_timestamp": t.Format(time.RFC3339Nano), - "duration": d, - }).Debug("Main cycle") + //log.WithFields(log.Fields{ + // "peer": c.rt.getPeerInfoString(), + // "time": c.rt.getChainTimeString(), + // "next_turn": c.rt.getNextTurn(), + // "head_height": c.rt.getHead().Height, + // "head_block": c.rt.getHead().Head.String(), + // "using_timestamp": t.Format(time.RFC3339Nano), + // "duration": d, + //}).Debug("Main cycle") time.Sleep(d) } else { c.runCurrentTurn(t) @@ -812,7 +774,7 @@ func (c *Chain) processBlocks() { "head_block": c.rt.getHead().Head.String(), "block_height": height, "block_hash": block.BlockHash().String(), - }).Error("Failed to check and push new block") + }).WithError(err).Error("Failed to check and push new block") } } } @@ -878,14 +840,13 @@ func (c *Chain) Stop() (err error) { "peer": c.rt.getPeerInfoString(), "time": c.rt.getChainTimeString(), }).Debug("Chain service stopped") - // Close database file - err = c.db.Close() + // Close LevelDB file + err = c.bdb.Close() log.WithFields(log.Fields{ "peer": c.rt.getPeerInfoString(), "time": c.rt.getChainTimeString(), }).Debug("Chain database closed") - // Close LevelDB file - err = c.ldb.Close() + err = c.tdb.Close() log.WithFields(log.Fields{ "peer": c.rt.getPeerInfoString(), "time": c.rt.getChainTimeString(), @@ -896,15 +857,20 @@ func (c *Chain) Stop() (err error) { // FetchBlock fetches the block at specified height from local cache. func (c *Chain) FetchBlock(height int32) (b *ct.Block, err error) { if n := c.rt.getHead().node.ancestor(height); n != nil { - k := n.indexKey() - err = c.db.View(func(tx *bolt.Tx) (err error) { - if v := tx.Bucket(metaBucket[:]).Bucket(metaBlockIndexBucket).Get(k); v != nil { - b = &ct.Block{} - err = utils.DecodeMsgPack(v, b) - } + k := utils.ConcatAll(metaBlockIndex[:], n.indexKey()) + var v []byte + v, err = c.bdb.Get(k, nil) + if err != nil { + err = errors.Wrapf(err, "fetch block %s", string(k)) + return + } + b = &ct.Block{} + err = utils.DecodeMsgPack(v, b) + if err != nil { + err = errors.Wrapf(err, "fetch block %s", string(k)) return - }) + } } return @@ -914,33 +880,31 @@ func (c *Chain) FetchBlock(height int32) (b *ct.Block, err error) { func (c *Chain) FetchAckedQuery(height int32, header *hash.Hash) ( ack *wt.SignedAckHeader, err error, ) { - if ack, err = c.qi.getAck(height, header); err == nil && ack != nil { - return - } - err = c.db.View(func(tx *bolt.Tx) (err error) { - var hb = tx.Bucket(metaBucket[:]).Bucket(metaHeightIndexBucket) + if ack, err = c.qi.getAck(height, header); err != nil || ack == nil { for h := height - c.rt.queryTTL - 1; h <= height; h++ { k := heightToKey(h) - if ab := hb.Bucket(heightToKey(h)); ab != nil { - ldbKey := make([]byte, 0, len(metaAckIndexBucket)+len(k)+hash.HashSize) - ldbKey = append(append(append(ldbKey, metaAckIndexBucket[:]...), k...), header[:]...) - v, _ := c.ldb.Get(ldbKey, nil) - //v := ab.Bucket(metaAckIndexBucket).Get(header[:]) - if v != nil { - var dec = &wt.SignedAckHeader{} - if err = utils.DecodeMsgPack(v, dec); err != nil { - return - } - ack = dec - break + ackKey := utils.ConcatAll(metaAckIndex[:], k, header[:]) + var v []byte + if v, err = c.tdb.Get(ackKey, nil); err != nil { + // if err == leveldb.ErrNotFound, just loop for next h + if err != leveldb.ErrNotFound { + err = errors.Wrapf(err, "fetch ack in height %d hash %s", h, header.String()) + return } + } else { + var dec = &wt.SignedAckHeader{} + if err = utils.DecodeMsgPack(v, dec); err != nil { + err = errors.Wrapf(err, "fetch ack in height %d hash %s", h, header.String()) + return + } + ack = dec + break } } - if ack == nil { - err = ErrAckQueryNotFound - } - return - }) + } + if ack == nil { + err = errors.Wrapf(ErrAckQueryNotFound, "fetch ack not found") + } return } @@ -998,7 +962,7 @@ func (c *Chain) CheckAndPushNewBlock(block *ct.Block) (err error) { total := int32(len(peers.Servers)) next := func() int32 { if total > 0 { - return (head.Height + 1) % total + return (c.rt.getNextTurn() - 1) % total } return -1 }() @@ -1081,10 +1045,12 @@ func (c *Chain) CheckAndPushNewBlock(block *ct.Block) (err error) { func (c *Chain) VerifyAndPushResponsedQuery(resp *wt.SignedResponseHeader) (err error) { // TODO(leventeliu): check resp. if c.rt.queryTimeIsExpired(resp.Timestamp) { - return ErrQueryExpired + err = errors.Wrapf(ErrQueryExpired, "Verify response query, min valid height %d, response height %d", c.rt.getMinValidHeight(), c.rt.getHeightFromTime(resp.Timestamp)) + return } if err = resp.Verify(); err != nil { + err = errors.Wrapf(err, "") return } @@ -1095,7 +1061,8 @@ func (c *Chain) VerifyAndPushResponsedQuery(resp *wt.SignedResponseHeader) (err func (c *Chain) VerifyAndPushAckedQuery(ack *wt.SignedAckHeader) (err error) { // TODO(leventeliu): check ack. if c.rt.queryTimeIsExpired(ack.SignedResponseHeader().Timestamp) { - return ErrQueryExpired + err = errors.Wrapf(ErrQueryExpired, "Verify ack query, min valid height %d, ack height %d", c.rt.getMinValidHeight(), c.rt.getHeightFromTime(ack.Timestamp)) + return } if err = ack.Verify(); err != nil { @@ -1221,32 +1188,41 @@ func (c *Chain) collectBillingSignatures(billings *pt.BillingRequest) { proWG.Add(1) go func() { defer proWG.Done() - for resp := range respC { - req.Signees = append(req.Signees, resp.Signee) - req.Signatures = append(req.Signatures, resp.Signature) + + bpReq := &ct.AdviseBillingReq{ + Req: billings, } var ( - bp proto.NodeID - err error + bpNodeID proto.NodeID + err error ) + for resp := range respC { + if err = bpReq.Req.AddSignature(resp.Signee, resp.Signature, false); err != nil { + // consume all rpc result + for range respC { + } + + return + } + } + defer log.WithFields(log.Fields{ "peer": c.rt.getPeerInfoString(), "time": c.rt.getChainTimeString(), "signees_count": len(req.Signees), "signatures_count": len(req.Signatures), - "bp": bp, + "bp": bpNodeID, }).WithError(err).Debug( "Sent billing request") - if bp, err = rpc.GetCurrentBP(); err != nil { + if bpNodeID, err = rpc.GetCurrentBP(); err != nil { return } - resp := &pt.BillingResponse{} - - if err = c.cl.CallNode(bp, "MCC.AdviseBillingRequest", req, resp); err != nil { + var resp interface{} + if err = c.cl.CallNode(bpNodeID, route.MCCAdviseBillingRequest.String(), bpReq, resp); err != nil { return } }() @@ -1266,7 +1242,7 @@ func (c *Chain) collectBillingSignatures(billings *pt.BillingRequest) { defer rpcWG.Done() resp := &MuxSignBillingResp{} - if err := c.cl.CallNode(id, "SQLC.SignBilling", req, resp); err != nil { + if err := c.cl.CallNode(id, route.SQLCSignBilling.String(), req, resp); err != nil { log.WithFields(log.Fields{ "peer": c.rt.getPeerInfoString(), "time": c.rt.getChainTimeString(), @@ -1285,7 +1261,6 @@ func (c *Chain) collectBillingSignatures(billings *pt.BillingRequest) { func (c *Chain) LaunchBilling(low, high int32) (err error) { var ( req *pt.BillingRequest - h *hash.Hash ) defer log.WithFields(log.Fields{ @@ -1299,11 +1274,10 @@ func (c *Chain) LaunchBilling(low, high int32) (err error) { return } - if h, err = req.PackRequestHeader(); err != nil { + if _, err = req.PackRequestHeader(); err != nil { return } - req.RequestHash = *h c.rt.wg.Add(1) go c.collectBillingSignatures(req) return @@ -1314,7 +1288,6 @@ func (c *Chain) SignBilling(req *pt.BillingRequest) ( pub *asymmetric.PublicKey, sig *asymmetric.Signature, err error, ) { var ( - h *hash.Hash loc *pt.BillingRequest ) defer log.WithFields(log.Fields{ @@ -1325,12 +1298,7 @@ func (c *Chain) SignBilling(req *pt.BillingRequest) ( }).WithError(err).Debug("Processing sign billing request") // Verify billing results - if h, err = req.PackRequestHeader(); err != nil { - return - } - - if !req.RequestHash.IsEqual(h) { - err = ErrBillingNotMatch + if err = req.VerifySignatures(); err != nil { return } @@ -1338,25 +1306,7 @@ func (c *Chain) SignBilling(req *pt.BillingRequest) ( return } - if !req.Header.LowBlock.IsEqual(&loc.Header.LowBlock) || - !req.Header.HighBlock.IsEqual(&loc.Header.HighBlock) { - err = ErrBillingNotMatch - return - } - - reqMap := make(map[proto.AccountAddress]*proto.AddrAndGas) - locMap := make(map[proto.AccountAddress]*proto.AddrAndGas) - - for _, v := range req.Header.GasAmounts { - reqMap[v.AccountAddress] = v - } - - for _, v := range loc.Header.GasAmounts { - locMap[v.AccountAddress] = v - } - - if !reflect.DeepEqual(reqMap, locMap) { - err = ErrBillingNotMatch + if err = req.Compare(loc); err != nil { return } @@ -1367,11 +1317,8 @@ func (c *Chain) SignBilling(req *pt.BillingRequest) ( return } - if sig, err = req.SignRequestHeader(priv); err != nil { - return - } + pub, sig, err = req.SignRequestHeader(priv, false) - pub = priv.PubKey() return } diff --git a/sqlchain/chain_test.go b/sqlchain/chain_test.go index fd69cdb59..5afd1f227 100644 --- a/sqlchain/chain_test.go +++ b/sqlchain/chain_test.go @@ -33,6 +33,7 @@ import ( "github.com/CovenantSQL/CovenantSQL/proto" "github.com/CovenantSQL/CovenantSQL/route" "github.com/CovenantSQL/CovenantSQL/rpc" + "github.com/CovenantSQL/CovenantSQL/utils/log" ) var ( @@ -41,7 +42,6 @@ var ( testTick = 100 * time.Millisecond testQueryTTL int32 = 10 testDatabaseID proto.DatabaseID = "tdb-test" - testChainService = "SQLC" testPeriodNumber int32 = 10 testClientNumberPerChain = 3 ) @@ -87,6 +87,7 @@ func TestIndexKey(t *testing.T) { } func TestMultiChain(t *testing.T) { + log.SetLevel(log.InfoLevel) // Create genesis block genesis, err := createRandomBlock(genesisHash, true) @@ -155,7 +156,7 @@ func TestMultiChain(t *testing.T) { defer server.Stop() // Create multiplexing service from RPC server - mux := NewMuxService(testChainService, server) + mux := NewMuxService(route.SQLChainRPCName, server) // Create chain instance config := &Config{ @@ -183,6 +184,8 @@ func TestMultiChain(t *testing.T) { config: config, chain: chain, } + + } // Create a master BP for RPC test @@ -232,7 +235,7 @@ func TestMultiChain(t *testing.T) { // Start BP if dht, err := route.NewDHTService(testDHTStoreFile, new(consistent.KMSStorage), true); err != nil { t.Fatalf("Error occurred: %v", err) - } else if err = bpsvr.RegisterService("DHT", dht); err != nil { + } else if err = bpsvr.RegisterService(route.DHTRPCName, dht); err != nil { t.Fatalf("Error occurred: %v", err) } diff --git a/sqlchain/errors.go b/sqlchain/errors.go index 707ef6fcb..0cbf1c682 100644 --- a/sqlchain/errors.go +++ b/sqlchain/errors.go @@ -84,9 +84,6 @@ var ( // given in its hash field. ErrHashNotMatch = errors.New("hash value doesn't match") - // ErrBillingNotMatch indicates that the billing request doesn't match the local result. - ErrBillingNotMatch = errors.New("billing request doesn't match") - // ErrMetaStateNotFound indicates that meta state not found in db. ErrMetaStateNotFound = errors.New("meta state not found in db") diff --git a/sqlchain/observer.go b/sqlchain/observer.go index ca76876df..495c723d3 100644 --- a/sqlchain/observer.go +++ b/sqlchain/observer.go @@ -91,28 +91,43 @@ func (r *observerReplicator) replicate() { curHeight := r.c.rt.getHead().Height if r.height == ct.ReplicateFromNewest { - log.Warningf("observer %v set to read from the newest block, which is in height %v", r.nodeID, curHeight) + log.WithFields(log.Fields{ + "node": r.nodeID, + "height": curHeight, + }).Warning("observer being set to read from the newest block") r.height = curHeight } else if r.height > curHeight+1 { - log.Warningf("observer %v subscribes block height %v, which is not produced yet", r.nodeID, r.height) - log.Warningf("reset observer %v height to %v", r.nodeID, curHeight+1) + log.WithFields(log.Fields{ + "node": r.nodeID, + "height": r.height, + }).Warning("observer subscribes to height not yet produced") + log.WithFields(log.Fields{ + "node": r.nodeID, + "height": curHeight + 1, + }).Warning("reset observer to height") r.height = curHeight + 1 } else if r.height == curHeight+1 { // wait for next block - log.Infof("no more blocks for observer %v to read", r.nodeID) + log.WithField("node", r.nodeID).Info("no more blocks for observer to read") return } - log.Debugf("try replicating block %v for observer %v", r.height, r.nodeID) + log.WithFields(log.Fields{ + "node": r.nodeID, + "height": r.height, + }).Debug("try replicating block for observer") // replicate one record var block *ct.Block if block, err = r.c.FetchBlock(r.height); err != nil { // fetch block failed - log.Warningf("fetch block with height %v failed: %v", r.height, err) + log.WithField("height", r.height).WithError(err).Warning("fetch block with height failed") return } else if block == nil { - log.Debugf("no block of height %v for observer %v", r.height, r.nodeID) + log.WithFields(log.Fields{ + "node": r.nodeID, + "height": r.height, + }).Debug("no block of height for observer") // black hole in chain? // find last available block @@ -124,8 +139,10 @@ func (r *observerReplicator) replicate() { for h := r.height - 1; h >= 0; h-- { if lastBlock, err = r.c.FetchBlock(h); err == nil && lastBlock != nil { lastHeight = h - log.Debugf("found last available block %v with height %v", - lastBlock.BlockHash().String(), lastHeight) + log.WithFields(log.Fields{ + "block": lastBlock.BlockHash().String(), + "height": lastHeight, + }).Debug("found last available block of height") break } } @@ -141,17 +158,22 @@ func (r *observerReplicator) replicate() { if nextBlock, err = r.c.FetchBlock(h); err == nil && nextBlock != nil { if !nextBlock.ParentHash().IsEqual(lastBlock.BlockHash()) { // inconsistency - log.Warningf("inconsistency detected during hole detection, "+ - "last block height: %v, hash: %v, next block height: %v, hash: %v, parent hash: %v", - lastBlock.BlockHash().String(), lastHeight, - nextBlock.BlockHash().String(), h, nextBlock.ParentHash().String()) + log.WithFields(log.Fields{ + "lastHeight": lastHeight, + "lastHash": lastBlock.BlockHash().String(), + "nextHeight": h, + "nextHash": nextBlock.BlockHash().String(), + "actualParentHash": nextBlock.ParentHash().String(), + }).Warning("inconsistency detected during hole detection") return } nextHeight = h - log.Debugf("found next available block %v with height %v", - nextBlock.BlockHash().String(), nextHeight) + log.WithFields(log.Fields{ + "block": nextBlock.BlockHash().String(), + "height": nextHeight, + }).Debug("found next available block of height") break } } @@ -163,21 +185,31 @@ func (r *observerReplicator) replicate() { } // successfully found a hole in chain - log.Debugf("found a hole in chain, started with block: %v, height: %v to block: %v, height: %v, skipped %v blocks", - lastBlock.BlockHash().String(), lastHeight, nextBlock.BlockHash().String(), nextHeight, nextHeight-lastHeight-1) + log.WithFields(log.Fields{ + "fromBlock": lastBlock.BlockHash().String(), + "fromHeight": lastHeight, + "toBlock": nextBlock.BlockHash().String(), + "toHeight": nextHeight, + "skipped": nextHeight - lastHeight - 1, + }).Debug("found a hole in chain, skipping") r.height = nextHeight block = nextBlock - log.Debugf("finish block height hole detection, skipping to block: %v, height: %v", - block.BlockHash().String(), r.height) + log.WithFields(log.Fields{ + "block": block.BlockHash().String(), + "height": r.height, + }).Debug("finish block height hole detection, skipping") } // fetch acks in block for _, h := range block.Queries { var ack *wt.SignedAckHeader if ack, err = r.c.queryOrSyncAckedQuery(r.height, h, block.Producer()); err != nil || ack == nil { - log.Warningf("fetch ack %v in block height %v failed: %v", h, r.height, err) + log.WithFields(log.Fields{ + "ack": h.String(), + "height": r.height, + }).WithError(err).Warning("fetch ack of block height") continue } @@ -192,8 +224,10 @@ func (r *observerReplicator) replicate() { resp := &MuxAdviseAckedQueryResp{} err = r.c.cl.CallNode(r.nodeID, route.OBSAdviseAckedQuery.String(), req, resp) if err != nil { - log.Warningf("send ack advise for block height %v to observer %v failed: %v", - r.height, r.nodeID, err) + log.WithFields(log.Fields{ + "node": r.nodeID, + "height": r.height, + }).WithError(err).Warning("send ack advise to observer") return } } @@ -218,7 +252,10 @@ func (r *observerReplicator) replicate() { resp := &MuxAdviseNewBlockResp{} err = r.c.cl.CallNode(r.nodeID, route.OBSAdviseNewBlock.String(), req, resp) if err != nil { - log.Warningf("send block height %v advise to observer %v failed: %v", r.height, r.nodeID, err) + log.WithFields(log.Fields{ + "node": r.nodeID, + "height": r.height, + }).WithError(err).Warning("send block advise to observer failed") return } diff --git a/sqlchain/queryindex.go b/sqlchain/queryindex.go index 7a8a28fd0..27fa77ca9 100644 --- a/sqlchain/queryindex.go +++ b/sqlchain/queryindex.go @@ -19,6 +19,7 @@ package sqlchain // TODO(leventeliu): use pooled objects to speed up this index. import ( + "github.com/pkg/errors" "sync" "github.com/CovenantSQL/CovenantSQL/crypto/hash" @@ -482,7 +483,7 @@ func (i *queryIndex) checkAckFromBlock(h int32, b *hash.Hash, ack *hash.Hash) ( l := i.getBarrier() if h < l { - err = ErrQueryExpired + err = errors.Wrapf(ErrQueryExpired, "check Ack, height %d, barrier %d", h, l) return } @@ -527,7 +528,7 @@ func (i *queryIndex) getAck(h int32, header *hash.Hash) (ack *wt.SignedAckHeader b := i.getBarrier() if h < b { - err = ErrQueryExpired + err = errors.Wrapf(ErrQueryExpired, "get Ack, height %d, barrier %d", h, b) return } diff --git a/sqlchain/queryindex_test.go b/sqlchain/queryindex_test.go index b567107d1..609b55b35 100644 --- a/sqlchain/queryindex_test.go +++ b/sqlchain/queryindex_test.go @@ -17,11 +17,13 @@ package sqlchain import ( + "github.com/pkg/errors" "math/rand" "reflect" "testing" "github.com/CovenantSQL/CovenantSQL/crypto/hash" + "github.com/CovenantSQL/CovenantSQL/utils/log" ) const ( @@ -129,7 +131,7 @@ func TestCheckAckFromBlock(t *testing.T) { if _, err := qi.checkAckFromBlock( 0, b1.BlockHash(), b1.Queries[0], - ); err != ErrQueryExpired { + ); errors.Cause(err) != ErrQueryExpired { t.Fatalf("Unexpected error: %v", err) } @@ -247,16 +249,17 @@ func TestGetAck(t *testing.T) { qi := newQueryIndex() qh := &hash.Hash{} - if _, err := qi.getAck(-1, qh); err != ErrQueryExpired { + if _, err := qi.getAck(-1, qh); errors.Cause(err) != ErrQueryExpired { t.Fatalf("Unexpected error: %v", err) } - if _, err := qi.getAck(0, qh); err != ErrQueryNotCached { + if _, err := qi.getAck(0, qh); errors.Cause(err) != ErrQueryNotCached { t.Fatalf("Unexpected error: %v", err) } } func TestQueryIndex(t *testing.T) { + log.SetLevel(log.InfoLevel) // Initialize clients and workers clients, err := newRandomNodes(testClientNumber) @@ -303,7 +306,7 @@ func TestQueryIndex(t *testing.T) { t.Fatalf("Error occurred: %v", err) } - t.Logf("i = %d, j = %d, k = %d\n\tseqno = %+v, req = %v, resp = %v", i, j, k, + log.Debugf("i = %d, j = %d, k = %d\n\tseqno = %+v, req = %v, resp = %v", i, j, k, resp.Request.GetQueryKey(), &req.HeaderHash, &resp.HeaderHash) if err = qi.addResponse(int32(i), resp); err != nil { @@ -316,7 +319,7 @@ func TestQueryIndex(t *testing.T) { for l := 0; l < dupAckNumber; l++ { ack, err := createRandomQueryAckWithResponse(resp, cli) - t.Logf("i = %d, j = %d, k = %d, l = %d\n\tseqno = %+v, "+ + log.Debugf("i = %d, j = %d, k = %d, l = %d\n\tseqno = %+v, "+ "req = %v, resp = %v, ack = %v", i, j, k, l, ack.SignedRequestHeader().GetQueryKey(), @@ -383,7 +386,7 @@ func TestQueryIndex(t *testing.T) { ); err != nil { t.Fatalf("Error occurred: %v", err) } else if !isKnown { - t.Fatalf("Unexpected result: block is known") + t.Fatal("Unexpected result: block is known") } } } diff --git a/sqlchain/runtime.go b/sqlchain/runtime.go index d88c30d2f..c846bf2b9 100644 --- a/sqlchain/runtime.go +++ b/sqlchain/runtime.go @@ -298,17 +298,6 @@ func (r *runtime) isMyTurn() (ret bool) { return } -func (r *runtime) getNextProducerIndex() int32 { - r.stateMutex.Lock() - defer r.stateMutex.Unlock() - - if r.total > 0 { - return (r.head.Height + 1) % r.total - } - - return -1 -} - func (r *runtime) getPeers() *kayak.Peers { r.peersMutex.Lock() defer r.peersMutex.Unlock() diff --git a/sqlchain/storage/storage.go b/sqlchain/storage/storage.go index d0190ba94..d902b3e61 100644 --- a/sqlchain/storage/storage.go +++ b/sqlchain/storage/storage.go @@ -26,7 +26,6 @@ import ( "github.com/CovenantSQL/CovenantSQL/twopc" "github.com/CovenantSQL/CovenantSQL/utils/log" - // Register CovenantSQL/go-sqlite3-encrypt engine. _ "github.com/CovenantSQL/go-sqlite3-encrypt" ) @@ -63,7 +62,7 @@ func openDB(dsn string) (db *sql.DB, err error) { } d.AddParam("_journal_mode", "WAL") - d.AddParam("_synchronous", "FULL") + d.AddParam("_synchronous", "NORMAL") fdsn := d.Format() fn := d.GetFileName() @@ -187,7 +186,7 @@ func (s *Storage) Commit(ctx context.Context, wb twopc.WriteBatch) (err error) { _, err = s.tx.ExecContext(ctx, q.Pattern, args...) if err != nil { - log.Debugf("commit query failed: %v", err) + log.WithError(err).Debug("commit query failed") s.tx.Rollback() s.tx = nil s.queries = nil @@ -254,7 +253,7 @@ func (s *Storage) Query(ctx context.Context, queries []Query) (columns []string, // always rollback on complete defer tx.Rollback() - q := queries[0] + q := queries[len(queries)-1] // convert arguments types args := make([]interface{}, len(q.Args)) @@ -328,7 +327,7 @@ func (s *Storage) Exec(ctx context.Context, queries []Query) (rowsAffected int64 var result sql.Result if result, err = tx.Exec(q.Pattern, args...); err != nil { - log.Debugf("execute query failed: %v", err) + log.WithError(err).Debug("execute query failed") return } diff --git a/sqlchain/storage/storage_test.go b/sqlchain/storage/storage_test.go index ef93c821a..e72d57b26 100644 --- a/sqlchain/storage/storage_test.go +++ b/sqlchain/storage/storage_test.go @@ -247,7 +247,7 @@ func TestStorage(t *testing.T) { columns, types, data, err = st.Query(context.Background(), []Query{newQuery("SQL???? WHAT!!!!")}) if err == nil { - t.Fatalf("Query should failed") + t.Fatal("Query should failed") } else { t.Logf("Query failed as expected with: %v", err.Error()) } diff --git a/sqlchain/storageproof_test.go b/sqlchain/storageproof_test.go index 062ed12ab..17594bd01 100644 --- a/sqlchain/storageproof_test.go +++ b/sqlchain/storageproof_test.go @@ -104,13 +104,13 @@ func TestGetNextVerifier(t *testing.T) { func TestSelectRecord(t *testing.T) { if strings.Compare(selectRecord(0), "hello world") != 0 { - t.Errorf("It should be hello world") + t.Error("It should be hello world") } } func TestCheckValid(t *testing.T) { if !CheckValid(answers) { - t.Errorf("It should be true") + t.Error("It should be true") } } diff --git a/blockproducer/types/tx.go b/sqlchain/types/billing_req.go similarity index 59% rename from blockproducer/types/tx.go rename to sqlchain/types/billing_req.go index 3e102d338..00ee3cde2 100644 --- a/blockproducer/types/tx.go +++ b/sqlchain/types/billing_req.go @@ -16,27 +16,19 @@ package types -//go:generate hsp - -// TxType represents the type of tx. -type TxType byte - -const ( - // TxTypeBilling defines TxType for database service billing. - TxTypeBilling TxType = 0 +import ( + pt "github.com/CovenantSQL/CovenantSQL/blockproducer/types" + "github.com/CovenantSQL/CovenantSQL/proto" ) -// String returns the TxType name. -func (tt *TxType) String() string { - switch *tt { - case TxTypeBilling: - return "TxBilling" - default: - return "TxUnknown" - } +// AdviseBillingReq defines a request of the AdviseBillingRequest RPC method. +type AdviseBillingReq struct { + proto.Envelope + Req *pt.BillingRequest } -// ToByte returns the the that represents the TxType. -func (tt *TxType) ToByte() byte { - return byte(*tt) +// AdviseBillingResp defines a request of the AdviseBillingRequest RPC method. +type AdviseBillingResp struct { + proto.Envelope + Resp *pt.BillingRequest } diff --git a/sqlchain/types/block.go b/sqlchain/types/block.go index faec9b3db..22b10167d 100644 --- a/sqlchain/types/block.go +++ b/sqlchain/types/block.go @@ -98,14 +98,13 @@ func (s *SignedHeader) Verify() error { // VerifyAsGenesis verifies the signed header as a genesis block header. func (s *SignedHeader) VerifyAsGenesis() (err error) { - log.Debugf("verify genesis header: producer = %s, root = %s, parent = %s, merkle = %s,"+ - " block = %s", - string(s.Producer[:]), - s.GenesisHash.String(), - s.ParentHash.String(), - s.MerkleRoot.String(), - s.BlockHash.String(), - ) + log.WithFields(log.Fields{ + "producer": s.Producer, + "root": s.GenesisHash.String(), + "parent": s.ParentHash.String(), + "merkle": s.MerkleRoot.String(), + "block": s.BlockHash.String(), + }).Debug("verify genesis header") // Assume that we can fetch public key from kms after initialization. pk, err := kms.GetPublicKey(s.Producer) diff --git a/sqlchain/types/block_test.go b/sqlchain/types/block_test.go index cfb40b505..2a0f74dee 100644 --- a/sqlchain/types/block_test.go +++ b/sqlchain/types/block_test.go @@ -17,12 +17,11 @@ package types import ( + "bytes" "math/big" "reflect" "testing" - "bytes" - "github.com/CovenantSQL/CovenantSQL/crypto/asymmetric" "github.com/CovenantSQL/CovenantSQL/crypto/hash" "github.com/CovenantSQL/CovenantSQL/utils" diff --git a/sqlchain/types/observer.go b/sqlchain/types/observer.go index 9e0aa35cc..112e99257 100644 --- a/sqlchain/types/observer.go +++ b/sqlchain/types/observer.go @@ -17,8 +17,6 @@ package types const ( - // ObserverService is the service name for observer to receive. - ObserverService = "OBS" // ReplicateFromBeginning is the replication offset observes from genesis block. ReplicateFromBeginning = int32(0) // ReplicateFromNewest is the replication offset observes from block head of current node. diff --git a/sqlchain/types/xxx_test.go b/sqlchain/types/xxx_test.go index 1a21a213c..d6545d79d 100644 --- a/sqlchain/types/xxx_test.go +++ b/sqlchain/types/xxx_test.go @@ -98,8 +98,6 @@ func createRandomBlock(parent hash.Hash, isGenesis bool) (b *Block, err error) { ParentHash: parent, Timestamp: time.Now().UTC(), }, - Signee: pub, - Signature: nil, }, } diff --git a/sqlchain/xxx_test.go b/sqlchain/xxx_test.go index 1aea3d25d..96870cc01 100644 --- a/sqlchain/xxx_test.go +++ b/sqlchain/xxx_test.go @@ -131,8 +131,6 @@ func createRandomQueryRequest(cli *nodeProfile) (r *wt.SignedRequestHeader, err Timestamp: time.Now().UTC(), // BatchCount and QueriesHash will be set by req.Sign() }, - Signee: cli.PublicKey, - Signature: nil, }, Payload: wt.RequestPayload{ Queries: createRandomStorageQueries(10, 10, 10, 10), @@ -165,8 +163,6 @@ func createRandomQueryResponse(cli, worker *nodeProfile) ( NodeID: worker.NodeID, Timestamp: createRandomTimeAfter(req.Timestamp, 100), }, - Signee: worker.PublicKey, - Signature: nil, }, Payload: wt.ResponsePayload{ Columns: createRandomStrings(10, 10, 10, 10), @@ -201,8 +197,6 @@ func createRandomQueryResponseWithRequest(req *wt.SignedRequestHeader, worker *n NodeID: worker.NodeID, Timestamp: createRandomTimeAfter(req.Timestamp, 100), }, - Signee: worker.PublicKey, - Signature: nil, }, Payload: wt.ResponsePayload{ Columns: createRandomStrings(10, 10, 10, 10), @@ -237,12 +231,10 @@ func createRandomQueryAckWithResponse(resp *wt.SignedResponseHeader, cli *nodePr NodeID: cli.NodeID, Timestamp: createRandomTimeAfter(resp.Timestamp, 100), }, - Signee: cli.PublicKey, - Signature: nil, }, } - if err = ack.Sign(cli.PrivateKey); err != nil { + if err = ack.Sign(cli.PrivateKey, true); err != nil { return } @@ -264,12 +256,10 @@ func createRandomQueryAck(cli, worker *nodeProfile) (r *wt.SignedAckHeader, err NodeID: cli.NodeID, Timestamp: createRandomTimeAfter(resp.Timestamp, 100), }, - Signee: cli.PublicKey, - Signature: nil, }, } - if err = ack.Sign(cli.PrivateKey); err != nil { + if err = ack.Sign(cli.PrivateKey, true); err != nil { return } @@ -351,8 +341,6 @@ func createRandomBlock(parent hash.Hash, isGenesis bool) (b *ct.Block, err error ParentHash: parent, Timestamp: time.Now().UTC(), }, - Signee: pub, - Signature: nil, }, } @@ -397,7 +385,7 @@ func createRandomBlockWithQueries(genesis, parent hash.Hash, acks []*wt.SignedAc b *ct.Block, err error, ) { // Generate key pair - priv, pub, err := asymmetric.GenSecp256k1KeyPair() + priv, _, err := asymmetric.GenSecp256k1KeyPair() if err != nil { return @@ -415,8 +403,6 @@ func createRandomBlockWithQueries(genesis, parent hash.Hash, acks []*wt.SignedAc ParentHash: parent, Timestamp: time.Now().UTC(), }, - Signee: pub, - Signature: nil, }, } diff --git a/storage/storage.go b/storage/storage.go index 9632d8ff5..55141a8d9 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -32,7 +32,6 @@ import ( "database/sql" "fmt" "sync" - // Register CovenantSQL/go-sqlite3-encrypt engine. _ "github.com/CovenantSQL/go-sqlite3-encrypt" ) diff --git a/test/GNTE/GNTE b/test/GNTE/GNTE index 51de88917..46a509a58 160000 --- a/test/GNTE/GNTE +++ b/test/GNTE/GNTE @@ -1 +1 @@ -Subproject commit 51de889172de377ec104900b9566ef8c8510525e +Subproject commit 46a509a5800a5acf9f6f243fd259e48551b856c2 diff --git a/test/GNTE/conf/gnte.yaml b/test/GNTE/conf/gnte.yaml index 7a9d6b90a..11c5eebb6 100644 --- a/test/GNTE/conf/gnte.yaml +++ b/test/GNTE/conf/gnte.yaml @@ -3,13 +3,13 @@ group: - name: bp nodes: - - # node_0 + - # bp10.250.1.2 ip: 10.250.1.2/32 cmd: "cd /scripts && ./bin/cqld -config ./node_0/config.yaml" - - # node_1 + - # bp10.250.1.3 ip: 10.250.1.3/32 cmd: "cd /scripts && ./bin/cqld -config ./node_1/config.yaml" - - # node_2 + - # bp10.250.1.4 ip: 10.250.1.4/32 cmd: "cd /scripts && ./bin/cqld -config ./node_2/config.yaml" delay: "100ms 1ms 1%" @@ -17,23 +17,41 @@ group: - name: miner nodes: - - # miner_0 - ip: 10.250.1.5/32 - cmd: "cd /scripts && ./bin/cql-minerd -config ./node_miner_0/config.yaml" - - # miner_1 - ip: 10.250.1.6/32 - cmd: "cd /scripts && ./bin/cql-minerd -config ./node_miner_1/config.yaml" - - # miner_2 - ip: 10.250.1.7/32 - cmd: "cd /scripts && ./bin/cql-minerd -config ./node_miner_2/config.yaml" + - # miner10.250.100.2 + ip: 10.250.100.2/32 + cmd: "cd /scripts && ./bin/cql-minerd -config ./node_miner_10.250.100.2/config.yaml" + - # miner10.250.100.3 + ip: 10.250.100.3/32 + cmd: "cd /scripts && ./bin/cql-minerd -config ./node_miner_10.250.100.3/config.yaml" + - # miner10.250.100.4 + ip: 10.250.100.4/32 + cmd: "cd /scripts && ./bin/cql-minerd -config ./node_miner_10.250.100.4/config.yaml" + - # miner10.250.100.5 + ip: 10.250.100.5/32 + cmd: "cd /scripts && ./bin/cql-minerd -config ./node_miner_10.250.100.5/config.yaml" + - # miner10.250.100.6 + ip: 10.250.100.6/32 + cmd: "cd /scripts && ./bin/cql-minerd -config ./node_miner_10.250.100.6/config.yaml" + - # miner10.250.100.7 + ip: 10.250.100.7/32 + cmd: "cd /scripts && ./bin/cql-minerd -config ./node_miner_10.250.100.7/config.yaml" + - # miner10.250.100.8 + ip: 10.250.100.8/32 + cmd: "cd /scripts && ./bin/cql-minerd -config ./node_miner_10.250.100.8/config.yaml" + - # miner10.250.100.9 + ip: 10.250.100.9/32 + cmd: "cd /scripts && ./bin/cql-minerd -config ./node_miner_10.250.100.9/config.yaml" delay: "100ms 1ms 1%" rate: "100mbit" - name: client nodes: - # node_c - ip: 10.250.1.8/32 + ip: 10.250.0.2/32 cmd: "ping -c3 g.cn" + - # node_adapter + ip: 10.250.0.254/32 + cmd: "cd /scripts && ./bin/cql-adapter -config ./node_c/config.yaml" delay: "100ms 1ms 1%" rate: "100mbit" diff --git a/test/GNTE/conf/node_0/config.yaml b/test/GNTE/conf/node_0/config.yaml index a5fb370cd..d0f183e52 100644 --- a/test/GNTE/conf/node_0/config.yaml +++ b/test/GNTE/conf/node_0/config.yaml @@ -76,7 +76,7 @@ KnownNodes: b: 0 c: 0 d: 3104982049 - Addr: 10.250.1.5:4661 + Addr: 10.250.100.2:4661 PublicKey: 0367aa51809a7c1dc0f82c02452fec9557b3e1d10ce7c919d8e73d90048df86d20 Role: Miner - ID: 000005f4f22c06f76c43c4f48d5a7ec1309cc94030cbf9ebae814172884ac8b5 @@ -85,7 +85,7 @@ KnownNodes: b: 0 c: 0 d: 2305843010430351476 - Addr: 10.250.1.6:4661 + Addr: 10.250.100.3:4661 PublicKey: 02914bca0806f040dd842207c44474ab41ecd29deee7f2d355789c5c78d448ca16 Role: Miner - ID: 000003f49592f83d0473bddb70d543f1096b4ffed5e5f942a3117e256b7052b8 @@ -94,6 +94,51 @@ KnownNodes: b: 0 c: 0 d: 13835058056920509601 - Addr: 10.250.1.7:4661 + Addr: 10.250.100.4:4661 PublicKey: 03ae859eac5b72ee428c7a85f10b2ce748d9de5e480aefbb70f6597dfa8b2175e5 Role: Miner +- ID: 00eda359cd2aa0920cdd37b083b896cb18cd26b3bd51744d1b4f127830f820f2 + Nonce: + a: 11 + b: 0 + c: 2686176025 + d: 0 + Addr: 10.250.100.5:4661 + PublicKey: 02b0da0b36dec5db1b2cf88b5ddbe2dc433d09ddc9a4401a9624995d2319c1d233 + Role: Miner +- ID: 0017017845ff9f9f7e8599d308652eb8ce480e689fbd49afb6b44cc9726cf84b + Nonce: + a: 60 + b: 3189902350 + c: 0 + d: 0 + Addr: 10.250.100.6:4661 + PublicKey: 03075d6743c22bb79208da88c6324b18f3db418d4089c4bad696296c866a65e0e1 + Role: Miner +- ID: 0075b97519d0a5cf9f7269a61b82bb3e082a5e7d796604e877ee28d08491979a + Nonce: + a: 34 + b: 0 + c: 0 + d: 4246204982 + Addr: 10.250.100.7:4661 + PublicKey: 0306678beed432377133f1dfb83b0bdb534d2b0c44e09f457cbb86762a13e88fe1 + Role: Miner +- ID: 0060bb3394f5185f760af690b0c124a70acbaf952fd79d794a0d394c37d7c0bc + Nonce: + a: 13 + b: 515393120 + c: 0 + d: 0 + Addr: 10.250.100.8:4661 + PublicKey: 0303e066f858f98b473ae6cb342c01f1f328021144621dcafce93a023223cba606 + Role: Miner +- ID: 004e5cf49e88f6e35e344f35d73ffe6232d4ebe93a63a825e171b8f6f2a88859 + Nonce: + a: 17 + b: 4213590245 + c: 0 + d: 0 + Addr: 10.250.100.9:4661 + PublicKey: 0297e8deccd7ada1ace2e1ed5b565abf2d3e8aa64b1bb5b36f485714e0f570adba + Role: Miner diff --git a/test/GNTE/conf/node_1/config.yaml b/test/GNTE/conf/node_1/config.yaml index ac4101ce4..70f6ca0f8 100644 --- a/test/GNTE/conf/node_1/config.yaml +++ b/test/GNTE/conf/node_1/config.yaml @@ -76,7 +76,7 @@ KnownNodes: b: 0 c: 0 d: 3104982049 - Addr: 10.250.1.5:4661 + Addr: 10.250.100.2:4661 PublicKey: 0367aa51809a7c1dc0f82c02452fec9557b3e1d10ce7c919d8e73d90048df86d20 Role: Miner - ID: 000005f4f22c06f76c43c4f48d5a7ec1309cc94030cbf9ebae814172884ac8b5 @@ -85,7 +85,7 @@ KnownNodes: b: 0 c: 0 d: 2305843010430351476 - Addr: 10.250.1.6:4661 + Addr: 10.250.100.3:4661 PublicKey: 02914bca0806f040dd842207c44474ab41ecd29deee7f2d355789c5c78d448ca16 Role: Miner - ID: 000003f49592f83d0473bddb70d543f1096b4ffed5e5f942a3117e256b7052b8 @@ -94,6 +94,51 @@ KnownNodes: b: 0 c: 0 d: 13835058056920509601 - Addr: 10.250.1.7:4661 + Addr: 10.250.100.4:4661 PublicKey: 03ae859eac5b72ee428c7a85f10b2ce748d9de5e480aefbb70f6597dfa8b2175e5 Role: Miner +- ID: 00eda359cd2aa0920cdd37b083b896cb18cd26b3bd51744d1b4f127830f820f2 + Nonce: + a: 11 + b: 0 + c: 2686176025 + d: 0 + Addr: 10.250.100.5:4661 + PublicKey: 02b0da0b36dec5db1b2cf88b5ddbe2dc433d09ddc9a4401a9624995d2319c1d233 + Role: Miner +- ID: 0017017845ff9f9f7e8599d308652eb8ce480e689fbd49afb6b44cc9726cf84b + Nonce: + a: 60 + b: 3189902350 + c: 0 + d: 0 + Addr: 10.250.100.6:4661 + PublicKey: 03075d6743c22bb79208da88c6324b18f3db418d4089c4bad696296c866a65e0e1 + Role: Miner +- ID: 0075b97519d0a5cf9f7269a61b82bb3e082a5e7d796604e877ee28d08491979a + Nonce: + a: 34 + b: 0 + c: 0 + d: 4246204982 + Addr: 10.250.100.7:4661 + PublicKey: 0306678beed432377133f1dfb83b0bdb534d2b0c44e09f457cbb86762a13e88fe1 + Role: Miner +- ID: 0060bb3394f5185f760af690b0c124a70acbaf952fd79d794a0d394c37d7c0bc + Nonce: + a: 13 + b: 515393120 + c: 0 + d: 0 + Addr: 10.250.100.8:4661 + PublicKey: 0303e066f858f98b473ae6cb342c01f1f328021144621dcafce93a023223cba606 + Role: Miner +- ID: 004e5cf49e88f6e35e344f35d73ffe6232d4ebe93a63a825e171b8f6f2a88859 + Nonce: + a: 17 + b: 4213590245 + c: 0 + d: 0 + Addr: 10.250.100.9:4661 + PublicKey: 0297e8deccd7ada1ace2e1ed5b565abf2d3e8aa64b1bb5b36f485714e0f570adba + Role: Miner diff --git a/test/GNTE/conf/node_2/config.yaml b/test/GNTE/conf/node_2/config.yaml index d40e26700..c1321a15c 100644 --- a/test/GNTE/conf/node_2/config.yaml +++ b/test/GNTE/conf/node_2/config.yaml @@ -76,7 +76,7 @@ KnownNodes: b: 0 c: 0 d: 3104982049 - Addr: 10.250.1.5:4661 + Addr: 10.250.100.2:4661 PublicKey: 0367aa51809a7c1dc0f82c02452fec9557b3e1d10ce7c919d8e73d90048df86d20 Role: Miner - ID: 000005f4f22c06f76c43c4f48d5a7ec1309cc94030cbf9ebae814172884ac8b5 @@ -85,7 +85,7 @@ KnownNodes: b: 0 c: 0 d: 2305843010430351476 - Addr: 10.250.1.6:4661 + Addr: 10.250.100.3:4661 PublicKey: 02914bca0806f040dd842207c44474ab41ecd29deee7f2d355789c5c78d448ca16 Role: Miner - ID: 000003f49592f83d0473bddb70d543f1096b4ffed5e5f942a3117e256b7052b8 @@ -94,6 +94,51 @@ KnownNodes: b: 0 c: 0 d: 13835058056920509601 - Addr: 10.250.1.7:4661 + Addr: 10.250.100.4:4661 PublicKey: 03ae859eac5b72ee428c7a85f10b2ce748d9de5e480aefbb70f6597dfa8b2175e5 Role: Miner +- ID: 00eda359cd2aa0920cdd37b083b896cb18cd26b3bd51744d1b4f127830f820f2 + Nonce: + a: 11 + b: 0 + c: 2686176025 + d: 0 + Addr: 10.250.100.5:4661 + PublicKey: 02b0da0b36dec5db1b2cf88b5ddbe2dc433d09ddc9a4401a9624995d2319c1d233 + Role: Miner +- ID: 0017017845ff9f9f7e8599d308652eb8ce480e689fbd49afb6b44cc9726cf84b + Nonce: + a: 60 + b: 3189902350 + c: 0 + d: 0 + Addr: 10.250.100.6:4661 + PublicKey: 03075d6743c22bb79208da88c6324b18f3db418d4089c4bad696296c866a65e0e1 + Role: Miner +- ID: 0075b97519d0a5cf9f7269a61b82bb3e082a5e7d796604e877ee28d08491979a + Nonce: + a: 34 + b: 0 + c: 0 + d: 4246204982 + Addr: 10.250.100.7:4661 + PublicKey: 0306678beed432377133f1dfb83b0bdb534d2b0c44e09f457cbb86762a13e88fe1 + Role: Miner +- ID: 0060bb3394f5185f760af690b0c124a70acbaf952fd79d794a0d394c37d7c0bc + Nonce: + a: 13 + b: 515393120 + c: 0 + d: 0 + Addr: 10.250.100.8:4661 + PublicKey: 0303e066f858f98b473ae6cb342c01f1f328021144621dcafce93a023223cba606 + Role: Miner +- ID: 004e5cf49e88f6e35e344f35d73ffe6232d4ebe93a63a825e171b8f6f2a88859 + Nonce: + a: 17 + b: 4213590245 + c: 0 + d: 0 + Addr: 10.250.100.9:4661 + PublicKey: 0297e8deccd7ada1ace2e1ed5b565abf2d3e8aa64b1bb5b36f485714e0f570adba + Role: Miner diff --git a/test/GNTE/conf/node_c/config.yaml b/test/GNTE/conf/node_c/config.yaml index 5073d8108..75aa1975c 100644 --- a/test/GNTE/conf/node_c/config.yaml +++ b/test/GNTE/conf/node_c/config.yaml @@ -3,7 +3,7 @@ WorkingRoot: "./" PubKeyStoreFile: "public.keystore" PrivateKeyFile: "private.key" DHTFileName: "dht.db" -ListenAddr: "10.250.1.4:4661" +ListenAddr: "10.250.0.254:4661" ThisNodeID: "00000f3b43288fe99831eb533ab77ec455d13e11fc38ec35a42d4edd17aa320d" ValidDNSKeys: koPbw9wmYZ7ggcjnQ6ayHyhHaDNMYELKTqT+qRGrZpWSccr/lBcrm10Z1PuQHB3Azhii+sb0PYFkH1ruxLhe5g==: cloudflare.com @@ -76,7 +76,7 @@ KnownNodes: b: 0 c: 0 d: 3104982049 - Addr: 10.250.1.5:4661 + Addr: 10.250.100.2:4661 PublicKey: 0367aa51809a7c1dc0f82c02452fec9557b3e1d10ce7c919d8e73d90048df86d20 Role: Miner - ID: 000005f4f22c06f76c43c4f48d5a7ec1309cc94030cbf9ebae814172884ac8b5 @@ -85,7 +85,7 @@ KnownNodes: b: 0 c: 0 d: 2305843010430351476 - Addr: 10.250.1.6:4661 + Addr: 10.250.100.3:4661 PublicKey: 02914bca0806f040dd842207c44474ab41ecd29deee7f2d355789c5c78d448ca16 Role: Miner - ID: 000003f49592f83d0473bddb70d543f1096b4ffed5e5f942a3117e256b7052b8 @@ -94,17 +94,62 @@ KnownNodes: b: 0 c: 0 d: 13835058056920509601 - Addr: 10.250.1.7:4661 + Addr: 10.250.100.4:4661 PublicKey: 03ae859eac5b72ee428c7a85f10b2ce748d9de5e480aefbb70f6597dfa8b2175e5 Role: Miner +- ID: 00eda359cd2aa0920cdd37b083b896cb18cd26b3bd51744d1b4f127830f820f2 + Nonce: + a: 11 + b: 0 + c: 2686176025 + d: 0 + Addr: 10.250.100.5:4661 + PublicKey: 02b0da0b36dec5db1b2cf88b5ddbe2dc433d09ddc9a4401a9624995d2319c1d233 + Role: Miner +- ID: 0017017845ff9f9f7e8599d308652eb8ce480e689fbd49afb6b44cc9726cf84b + Nonce: + a: 60 + b: 3189902350 + c: 0 + d: 0 + Addr: 10.250.100.6:4661 + PublicKey: 03075d6743c22bb79208da88c6324b18f3db418d4089c4bad696296c866a65e0e1 + Role: Miner +- ID: 0075b97519d0a5cf9f7269a61b82bb3e082a5e7d796604e877ee28d08491979a + Nonce: + a: 34 + b: 0 + c: 0 + d: 4246204982 + Addr: 10.250.100.7:4661 + PublicKey: 0306678beed432377133f1dfb83b0bdb534d2b0c44e09f457cbb86762a13e88fe1 + Role: Miner +- ID: 0060bb3394f5185f760af690b0c124a70acbaf952fd79d794a0d394c37d7c0bc + Nonce: + a: 13 + b: 515393120 + c: 0 + d: 0 + Addr: 10.250.100.8:4661 + PublicKey: 0303e066f858f98b473ae6cb342c01f1f328021144621dcafce93a023223cba606 + Role: Miner +- ID: 004e5cf49e88f6e35e344f35d73ffe6232d4ebe93a63a825e171b8f6f2a88859 + Nonce: + a: 17 + b: 4213590245 + c: 0 + d: 0 + Addr: 10.250.100.9:4661 + PublicKey: 0297e8deccd7ada1ace2e1ed5b565abf2d3e8aa64b1bb5b36f485714e0f570adba + Role: Miner Adapter: ListenAddr: 0.0.0.0:4661 - CertificatePath: ./node_c/server.test.covenantsql.io.pem - PrivateKeyPath: ./node_c/server.test.covenantsql.io-key.pem + CertificatePath: ./server.test.covenantsql.io.pem + PrivateKeyPath: ./server.test.covenantsql.io-key.pem VerifyCertificate: true - ClientCAPath: ./node_c/rootCA.pem + ClientCAPath: ./rootCA.pem AdminCerts: - - ./node_c/admin.test.covenantsql.io.pem + - ./admin.test.covenantsql.io.pem WriteCerts: - - ./node_c/write.test.covenantsql.io.pem + - ./write.test.covenantsql.io.pem StorageDriver: covenantsql diff --git a/test/GNTE/conf/node_miner_0/config.yaml b/test/GNTE/conf/node_miner_10.250.100.2/config.yaml similarity index 67% rename from test/GNTE/conf/node_miner_0/config.yaml rename to test/GNTE/conf/node_miner_10.250.100.2/config.yaml index 25c8362c5..97cb6d3a4 100644 --- a/test/GNTE/conf/node_miner_0/config.yaml +++ b/test/GNTE/conf/node_miner_10.250.100.2/config.yaml @@ -3,7 +3,7 @@ WorkingRoot: "./" PubKeyStoreFile: "public.keystore" PrivateKeyFile: "private.key" DHTFileName: "dht.db" -ListenAddr: "10.250.1.5:4661" +ListenAddr: "10.250.100.2:4661" ThisNodeID: "000005aa62048f85da4ae9698ed59c14ec0d48a88a07c15a32265634e7e64ade" ValidDNSKeys: koPbw9wmYZ7ggcjnQ6ayHyhHaDNMYELKTqT+qRGrZpWSccr/lBcrm10Z1PuQHB3Azhii+sb0PYFkH1ruxLhe5g==: cloudflare.com @@ -27,7 +27,7 @@ BlockProducer: Miner: IsTestMode: true RootDir: "./data" - MaxReqTimeGap: "2s" + MaxReqTimeGap: "60s" MetricCollectInterval: "60s" KnownNodes: - ID: 00000bef611d346c0cbe1beaa76e7f0ed705a194fdf9ac3a248ec70e9c198bf9 @@ -72,7 +72,7 @@ KnownNodes: b: 0 c: 0 d: 3104982049 - Addr: 10.250.1.5:4661 + Addr: 10.250.100.2:4661 PublicKey: 0367aa51809a7c1dc0f82c02452fec9557b3e1d10ce7c919d8e73d90048df86d20 Role: Miner - ID: 000005f4f22c06f76c43c4f48d5a7ec1309cc94030cbf9ebae814172884ac8b5 @@ -81,7 +81,7 @@ KnownNodes: b: 0 c: 0 d: 2305843010430351476 - Addr: 10.250.1.6:4661 + Addr: 10.250.100.3:4661 PublicKey: 02914bca0806f040dd842207c44474ab41ecd29deee7f2d355789c5c78d448ca16 Role: Miner - ID: 000003f49592f83d0473bddb70d543f1096b4ffed5e5f942a3117e256b7052b8 @@ -90,6 +90,51 @@ KnownNodes: b: 0 c: 0 d: 13835058056920509601 - Addr: 10.250.1.7:4661 + Addr: 10.250.100.4:4661 PublicKey: 03ae859eac5b72ee428c7a85f10b2ce748d9de5e480aefbb70f6597dfa8b2175e5 Role: Miner +- ID: 00eda359cd2aa0920cdd37b083b896cb18cd26b3bd51744d1b4f127830f820f2 + Nonce: + a: 11 + b: 0 + c: 2686176025 + d: 0 + Addr: 10.250.100.5:4661 + PublicKey: 02b0da0b36dec5db1b2cf88b5ddbe2dc433d09ddc9a4401a9624995d2319c1d233 + Role: Miner +- ID: 0017017845ff9f9f7e8599d308652eb8ce480e689fbd49afb6b44cc9726cf84b + Nonce: + a: 60 + b: 3189902350 + c: 0 + d: 0 + Addr: 10.250.100.6:4661 + PublicKey: 03075d6743c22bb79208da88c6324b18f3db418d4089c4bad696296c866a65e0e1 + Role: Miner +- ID: 0075b97519d0a5cf9f7269a61b82bb3e082a5e7d796604e877ee28d08491979a + Nonce: + a: 34 + b: 0 + c: 0 + d: 4246204982 + Addr: 10.250.100.7:4661 + PublicKey: 0306678beed432377133f1dfb83b0bdb534d2b0c44e09f457cbb86762a13e88fe1 + Role: Miner +- ID: 0060bb3394f5185f760af690b0c124a70acbaf952fd79d794a0d394c37d7c0bc + Nonce: + a: 13 + b: 515393120 + c: 0 + d: 0 + Addr: 10.250.100.8:4661 + PublicKey: 0303e066f858f98b473ae6cb342c01f1f328021144621dcafce93a023223cba606 + Role: Miner +- ID: 004e5cf49e88f6e35e344f35d73ffe6232d4ebe93a63a825e171b8f6f2a88859 + Nonce: + a: 17 + b: 4213590245 + c: 0 + d: 0 + Addr: 10.250.100.9:4661 + PublicKey: 0297e8deccd7ada1ace2e1ed5b565abf2d3e8aa64b1bb5b36f485714e0f570adba + Role: Miner diff --git a/test/GNTE/conf/node_miner_0/private.key b/test/GNTE/conf/node_miner_10.250.100.2/private.key similarity index 100% rename from test/GNTE/conf/node_miner_0/private.key rename to test/GNTE/conf/node_miner_10.250.100.2/private.key diff --git a/test/GNTE/conf/node_miner_1/config.yaml b/test/GNTE/conf/node_miner_10.250.100.3/config.yaml similarity index 67% rename from test/GNTE/conf/node_miner_1/config.yaml rename to test/GNTE/conf/node_miner_10.250.100.3/config.yaml index 9a5170f0e..af65305fa 100644 --- a/test/GNTE/conf/node_miner_1/config.yaml +++ b/test/GNTE/conf/node_miner_10.250.100.3/config.yaml @@ -3,7 +3,7 @@ WorkingRoot: "./" PubKeyStoreFile: "public.keystore" PrivateKeyFile: "private.key" DHTFileName: "dht.db" -ListenAddr: "10.250.1.6:4661" +ListenAddr: "10.250.100.3:4661" ThisNodeID: "000005f4f22c06f76c43c4f48d5a7ec1309cc94030cbf9ebae814172884ac8b5" ValidDNSKeys: koPbw9wmYZ7ggcjnQ6ayHyhHaDNMYELKTqT+qRGrZpWSccr/lBcrm10Z1PuQHB3Azhii+sb0PYFkH1ruxLhe5g==: cloudflare.com @@ -27,7 +27,7 @@ BlockProducer: Miner: IsTestMode: true RootDir: "./data" - MaxReqTimeGap: "2s" + MaxReqTimeGap: "60s" MetricCollectInterval: "60s" KnownNodes: - ID: 00000bef611d346c0cbe1beaa76e7f0ed705a194fdf9ac3a248ec70e9c198bf9 @@ -72,7 +72,7 @@ KnownNodes: b: 0 c: 0 d: 3104982049 - Addr: 10.250.1.5:4661 + Addr: 10.250.100.2:4661 PublicKey: 0367aa51809a7c1dc0f82c02452fec9557b3e1d10ce7c919d8e73d90048df86d20 Role: Miner - ID: 000005f4f22c06f76c43c4f48d5a7ec1309cc94030cbf9ebae814172884ac8b5 @@ -81,7 +81,7 @@ KnownNodes: b: 0 c: 0 d: 2305843010430351476 - Addr: 10.250.1.6:4661 + Addr: 10.250.100.3:4661 PublicKey: 02914bca0806f040dd842207c44474ab41ecd29deee7f2d355789c5c78d448ca16 Role: Miner - ID: 000003f49592f83d0473bddb70d543f1096b4ffed5e5f942a3117e256b7052b8 @@ -90,6 +90,51 @@ KnownNodes: b: 0 c: 0 d: 13835058056920509601 - Addr: 10.250.1.7:4661 + Addr: 10.250.100.4:4661 PublicKey: 03ae859eac5b72ee428c7a85f10b2ce748d9de5e480aefbb70f6597dfa8b2175e5 Role: Miner +- ID: 00eda359cd2aa0920cdd37b083b896cb18cd26b3bd51744d1b4f127830f820f2 + Nonce: + a: 11 + b: 0 + c: 2686176025 + d: 0 + Addr: 10.250.100.5:4661 + PublicKey: 02b0da0b36dec5db1b2cf88b5ddbe2dc433d09ddc9a4401a9624995d2319c1d233 + Role: Miner +- ID: 0017017845ff9f9f7e8599d308652eb8ce480e689fbd49afb6b44cc9726cf84b + Nonce: + a: 60 + b: 3189902350 + c: 0 + d: 0 + Addr: 10.250.100.6:4661 + PublicKey: 03075d6743c22bb79208da88c6324b18f3db418d4089c4bad696296c866a65e0e1 + Role: Miner +- ID: 0075b97519d0a5cf9f7269a61b82bb3e082a5e7d796604e877ee28d08491979a + Nonce: + a: 34 + b: 0 + c: 0 + d: 4246204982 + Addr: 10.250.100.7:4661 + PublicKey: 0306678beed432377133f1dfb83b0bdb534d2b0c44e09f457cbb86762a13e88fe1 + Role: Miner +- ID: 0060bb3394f5185f760af690b0c124a70acbaf952fd79d794a0d394c37d7c0bc + Nonce: + a: 13 + b: 515393120 + c: 0 + d: 0 + Addr: 10.250.100.8:4661 + PublicKey: 0303e066f858f98b473ae6cb342c01f1f328021144621dcafce93a023223cba606 + Role: Miner +- ID: 004e5cf49e88f6e35e344f35d73ffe6232d4ebe93a63a825e171b8f6f2a88859 + Nonce: + a: 17 + b: 4213590245 + c: 0 + d: 0 + Addr: 10.250.100.9:4661 + PublicKey: 0297e8deccd7ada1ace2e1ed5b565abf2d3e8aa64b1bb5b36f485714e0f570adba + Role: Miner diff --git a/test/GNTE/conf/node_miner_1/private.key b/test/GNTE/conf/node_miner_10.250.100.3/private.key similarity index 100% rename from test/GNTE/conf/node_miner_1/private.key rename to test/GNTE/conf/node_miner_10.250.100.3/private.key diff --git a/test/GNTE/conf/node_miner_2/config.yaml b/test/GNTE/conf/node_miner_10.250.100.4/config.yaml similarity index 67% rename from test/GNTE/conf/node_miner_2/config.yaml rename to test/GNTE/conf/node_miner_10.250.100.4/config.yaml index dea5534c4..1b829fb70 100644 --- a/test/GNTE/conf/node_miner_2/config.yaml +++ b/test/GNTE/conf/node_miner_10.250.100.4/config.yaml @@ -3,7 +3,7 @@ WorkingRoot: "./" PubKeyStoreFile: "public.keystore" PrivateKeyFile: "private.key" DHTFileName: "dht.db" -ListenAddr: "10.250.1.7:4661" +ListenAddr: "10.250.100.4:4661" ThisNodeID: "000003f49592f83d0473bddb70d543f1096b4ffed5e5f942a3117e256b7052b8" ValidDNSKeys: koPbw9wmYZ7ggcjnQ6ayHyhHaDNMYELKTqT+qRGrZpWSccr/lBcrm10Z1PuQHB3Azhii+sb0PYFkH1ruxLhe5g==: cloudflare.com @@ -27,7 +27,7 @@ BlockProducer: Miner: IsTestMode: true RootDir: "./data" - MaxReqTimeGap: "2s" + MaxReqTimeGap: "60s" MetricCollectInterval: "60s" KnownNodes: - ID: 00000bef611d346c0cbe1beaa76e7f0ed705a194fdf9ac3a248ec70e9c198bf9 @@ -72,7 +72,7 @@ KnownNodes: b: 0 c: 0 d: 3104982049 - Addr: 10.250.1.5:4661 + Addr: 10.250.100.2:4661 PublicKey: 0367aa51809a7c1dc0f82c02452fec9557b3e1d10ce7c919d8e73d90048df86d20 Role: Miner - ID: 000005f4f22c06f76c43c4f48d5a7ec1309cc94030cbf9ebae814172884ac8b5 @@ -81,7 +81,7 @@ KnownNodes: b: 0 c: 0 d: 2305843010430351476 - Addr: 10.250.1.6:4661 + Addr: 10.250.100.3:4661 PublicKey: 02914bca0806f040dd842207c44474ab41ecd29deee7f2d355789c5c78d448ca16 Role: Miner - ID: 000003f49592f83d0473bddb70d543f1096b4ffed5e5f942a3117e256b7052b8 @@ -90,6 +90,51 @@ KnownNodes: b: 0 c: 0 d: 13835058056920509601 - Addr: 10.250.1.7:4661 + Addr: 10.250.100.4:4661 PublicKey: 03ae859eac5b72ee428c7a85f10b2ce748d9de5e480aefbb70f6597dfa8b2175e5 Role: Miner +- ID: 00eda359cd2aa0920cdd37b083b896cb18cd26b3bd51744d1b4f127830f820f2 + Nonce: + a: 11 + b: 0 + c: 2686176025 + d: 0 + Addr: 10.250.100.5:4661 + PublicKey: 02b0da0b36dec5db1b2cf88b5ddbe2dc433d09ddc9a4401a9624995d2319c1d233 + Role: Miner +- ID: 0017017845ff9f9f7e8599d308652eb8ce480e689fbd49afb6b44cc9726cf84b + Nonce: + a: 60 + b: 3189902350 + c: 0 + d: 0 + Addr: 10.250.100.6:4661 + PublicKey: 03075d6743c22bb79208da88c6324b18f3db418d4089c4bad696296c866a65e0e1 + Role: Miner +- ID: 0075b97519d0a5cf9f7269a61b82bb3e082a5e7d796604e877ee28d08491979a + Nonce: + a: 34 + b: 0 + c: 0 + d: 4246204982 + Addr: 10.250.100.7:4661 + PublicKey: 0306678beed432377133f1dfb83b0bdb534d2b0c44e09f457cbb86762a13e88fe1 + Role: Miner +- ID: 0060bb3394f5185f760af690b0c124a70acbaf952fd79d794a0d394c37d7c0bc + Nonce: + a: 13 + b: 515393120 + c: 0 + d: 0 + Addr: 10.250.100.8:4661 + PublicKey: 0303e066f858f98b473ae6cb342c01f1f328021144621dcafce93a023223cba606 + Role: Miner +- ID: 004e5cf49e88f6e35e344f35d73ffe6232d4ebe93a63a825e171b8f6f2a88859 + Nonce: + a: 17 + b: 4213590245 + c: 0 + d: 0 + Addr: 10.250.100.9:4661 + PublicKey: 0297e8deccd7ada1ace2e1ed5b565abf2d3e8aa64b1bb5b36f485714e0f570adba + Role: Miner diff --git a/test/GNTE/conf/node_miner_2/private.key b/test/GNTE/conf/node_miner_10.250.100.4/private.key similarity index 100% rename from test/GNTE/conf/node_miner_2/private.key rename to test/GNTE/conf/node_miner_10.250.100.4/private.key diff --git a/test/GNTE/conf/node_miner_10.250.100.5/config.yaml b/test/GNTE/conf/node_miner_10.250.100.5/config.yaml new file mode 100755 index 000000000..810af9a5f --- /dev/null +++ b/test/GNTE/conf/node_miner_10.250.100.5/config.yaml @@ -0,0 +1,140 @@ +IsTestMode: true +WorkingRoot: "./" +PubKeyStoreFile: "public.keystore" +PrivateKeyFile: "private.key" +DHTFileName: "dht.db" +ListenAddr: "10.250.100.5:4661" +ThisNodeID: "00eda359cd2aa0920cdd37b083b896cb18cd26b3bd51744d1b4f127830f820f2" +ValidDNSKeys: + koPbw9wmYZ7ggcjnQ6ayHyhHaDNMYELKTqT+qRGrZpWSccr/lBcrm10Z1PuQHB3Azhii+sb0PYFkH1ruxLhe5g==: cloudflare.com + mdsswUyr3DPW132mOi8V9xESWE8jTo0dxCjjnopKl+GqJxpVXckHAeF+KkxLbxILfDLUT0rAK9iUzy1L53eKGQ==: cloudflare.com +BlockProducer: + PublicKey: "02c76216704d797c64c58bc11519fb68582e8e63de7e5b3b2dbbbe8733efe5fd24" + NodeID: 00000bef611d346c0cbe1beaa76e7f0ed705a194fdf9ac3a248ec70e9c198bf9 + Nonce: + a: 313283 + b: 0 + c: 0 + d: 0 + ChainFileName: "chain.db" + BPGenesisInfo: + Version: 1 + BlockHash: f745ca6427237aac858dd3c7f2df8e6f3c18d0f1c164e07a1c6b8eebeba6b154 + Producer: 0000000000000000000000000000000000000000000000000000000000000001 + MerkleRoot: 0000000000000000000000000000000000000000000000000000000000000001 + ParentHash: 0000000000000000000000000000000000000000000000000000000000000001 + Timestamp: 2018-08-13T21:59:59.12Z +Miner: + IsTestMode: true + RootDir: "./data" + MaxReqTimeGap: "60s" + MetricCollectInterval: "60s" +KnownNodes: +- ID: 00000bef611d346c0cbe1beaa76e7f0ed705a194fdf9ac3a248ec70e9c198bf9 + Nonce: + a: 313283 + b: 0 + c: 0 + d: 0 + Addr: 10.250.1.2:4661 + PublicKey: "02c76216704d797c64c58bc11519fb68582e8e63de7e5b3b2dbbbe8733efe5fd24" + Role: Leader +- ID: 00000381d46fd6cf7742d7fb94e2422033af989c0e348b5781b3219599a3af35 + Nonce: + a: 478373 + b: 0 + c: 0 + d: 2305843009893772025 + Addr: 10.250.1.3:4661 + PublicKey: "02c76216704d797c64c58bc11519fb68582e8e63de7e5b3b2dbbbe8733efe5fd24" + Role: Follower +- ID: 000000172580063ded88e010556b0aca2851265be8845b1ef397e8fce6ab5582 + Nonce: + a: 259939 + b: 0 + c: 0 + d: 2305843012544226372 + Addr: 10.250.1.4:4661 + PublicKey: "02c76216704d797c64c58bc11519fb68582e8e63de7e5b3b2dbbbe8733efe5fd24" + Role: Follower +- ID: 00000f3b43288fe99831eb533ab77ec455d13e11fc38ec35a42d4edd17aa320d + Nonce: + a: 22403 + b: 0 + c: 0 + d: 0 + Addr: "" + PublicKey: 02ec784ca599f21ef93fe7abdc68d78817ab6c9b31f2324d15ea174d9da498b4c4 + Role: Client +- ID: 000005aa62048f85da4ae9698ed59c14ec0d48a88a07c15a32265634e7e64ade + Nonce: + a: 567323 + b: 0 + c: 0 + d: 3104982049 + Addr: 10.250.100.2:4661 + PublicKey: 0367aa51809a7c1dc0f82c02452fec9557b3e1d10ce7c919d8e73d90048df86d20 + Role: Miner +- ID: 000005f4f22c06f76c43c4f48d5a7ec1309cc94030cbf9ebae814172884ac8b5 + Nonce: + a: 240524 + b: 0 + c: 0 + d: 2305843010430351476 + Addr: 10.250.100.3:4661 + PublicKey: 02914bca0806f040dd842207c44474ab41ecd29deee7f2d355789c5c78d448ca16 + Role: Miner +- ID: 000003f49592f83d0473bddb70d543f1096b4ffed5e5f942a3117e256b7052b8 + Nonce: + a: 606016 + b: 0 + c: 0 + d: 13835058056920509601 + Addr: 10.250.100.4:4661 + PublicKey: 03ae859eac5b72ee428c7a85f10b2ce748d9de5e480aefbb70f6597dfa8b2175e5 + Role: Miner +- ID: 00eda359cd2aa0920cdd37b083b896cb18cd26b3bd51744d1b4f127830f820f2 + Nonce: + a: 11 + b: 0 + c: 2686176025 + d: 0 + Addr: 10.250.100.5:4661 + PublicKey: 02b0da0b36dec5db1b2cf88b5ddbe2dc433d09ddc9a4401a9624995d2319c1d233 + Role: Miner +- ID: 0017017845ff9f9f7e8599d308652eb8ce480e689fbd49afb6b44cc9726cf84b + Nonce: + a: 60 + b: 3189902350 + c: 0 + d: 0 + Addr: 10.250.100.6:4661 + PublicKey: 03075d6743c22bb79208da88c6324b18f3db418d4089c4bad696296c866a65e0e1 + Role: Miner +- ID: 0075b97519d0a5cf9f7269a61b82bb3e082a5e7d796604e877ee28d08491979a + Nonce: + a: 34 + b: 0 + c: 0 + d: 4246204982 + Addr: 10.250.100.7:4661 + PublicKey: 0306678beed432377133f1dfb83b0bdb534d2b0c44e09f457cbb86762a13e88fe1 + Role: Miner +- ID: 0060bb3394f5185f760af690b0c124a70acbaf952fd79d794a0d394c37d7c0bc + Nonce: + a: 13 + b: 515393120 + c: 0 + d: 0 + Addr: 10.250.100.8:4661 + PublicKey: 0303e066f858f98b473ae6cb342c01f1f328021144621dcafce93a023223cba606 + Role: Miner +- ID: 004e5cf49e88f6e35e344f35d73ffe6232d4ebe93a63a825e171b8f6f2a88859 + Nonce: + a: 17 + b: 4213590245 + c: 0 + d: 0 + Addr: 10.250.100.9:4661 + PublicKey: 0297e8deccd7ada1ace2e1ed5b565abf2d3e8aa64b1bb5b36f485714e0f570adba + Role: Miner diff --git a/test/GNTE/conf/node_miner_10.250.100.5/private.key b/test/GNTE/conf/node_miner_10.250.100.5/private.key new file mode 100644 index 000000000..d221df53f --- /dev/null +++ b/test/GNTE/conf/node_miner_10.250.100.5/private.key @@ -0,0 +1,2 @@ +>Z0t,_ SKs,_ߚd}0C8N`3&Mu 2E# mvv /B+= +zq=DWJa &p \ No newline at end of file diff --git a/test/GNTE/conf/node_miner_10.250.100.6/config.yaml b/test/GNTE/conf/node_miner_10.250.100.6/config.yaml new file mode 100755 index 000000000..7e07f7965 --- /dev/null +++ b/test/GNTE/conf/node_miner_10.250.100.6/config.yaml @@ -0,0 +1,140 @@ +IsTestMode: true +WorkingRoot: "./" +PubKeyStoreFile: "public.keystore" +PrivateKeyFile: "private.key" +DHTFileName: "dht.db" +ListenAddr: "10.250.100.6:4661" +ThisNodeID: "0017017845ff9f9f7e8599d308652eb8ce480e689fbd49afb6b44cc9726cf84b" +ValidDNSKeys: + koPbw9wmYZ7ggcjnQ6ayHyhHaDNMYELKTqT+qRGrZpWSccr/lBcrm10Z1PuQHB3Azhii+sb0PYFkH1ruxLhe5g==: cloudflare.com + mdsswUyr3DPW132mOi8V9xESWE8jTo0dxCjjnopKl+GqJxpVXckHAeF+KkxLbxILfDLUT0rAK9iUzy1L53eKGQ==: cloudflare.com +BlockProducer: + PublicKey: "02c76216704d797c64c58bc11519fb68582e8e63de7e5b3b2dbbbe8733efe5fd24" + NodeID: 00000bef611d346c0cbe1beaa76e7f0ed705a194fdf9ac3a248ec70e9c198bf9 + Nonce: + a: 313283 + b: 0 + c: 0 + d: 0 + ChainFileName: "chain.db" + BPGenesisInfo: + Version: 1 + BlockHash: f745ca6427237aac858dd3c7f2df8e6f3c18d0f1c164e07a1c6b8eebeba6b154 + Producer: 0000000000000000000000000000000000000000000000000000000000000001 + MerkleRoot: 0000000000000000000000000000000000000000000000000000000000000001 + ParentHash: 0000000000000000000000000000000000000000000000000000000000000001 + Timestamp: 2018-08-13T21:59:59.12Z +Miner: + IsTestMode: true + RootDir: "./data" + MaxReqTimeGap: "60s" + MetricCollectInterval: "60s" +KnownNodes: +- ID: 00000bef611d346c0cbe1beaa76e7f0ed705a194fdf9ac3a248ec70e9c198bf9 + Nonce: + a: 313283 + b: 0 + c: 0 + d: 0 + Addr: 10.250.1.2:4661 + PublicKey: "02c76216704d797c64c58bc11519fb68582e8e63de7e5b3b2dbbbe8733efe5fd24" + Role: Leader +- ID: 00000381d46fd6cf7742d7fb94e2422033af989c0e348b5781b3219599a3af35 + Nonce: + a: 478373 + b: 0 + c: 0 + d: 2305843009893772025 + Addr: 10.250.1.3:4661 + PublicKey: "02c76216704d797c64c58bc11519fb68582e8e63de7e5b3b2dbbbe8733efe5fd24" + Role: Follower +- ID: 000000172580063ded88e010556b0aca2851265be8845b1ef397e8fce6ab5582 + Nonce: + a: 259939 + b: 0 + c: 0 + d: 2305843012544226372 + Addr: 10.250.1.4:4661 + PublicKey: "02c76216704d797c64c58bc11519fb68582e8e63de7e5b3b2dbbbe8733efe5fd24" + Role: Follower +- ID: 00000f3b43288fe99831eb533ab77ec455d13e11fc38ec35a42d4edd17aa320d + Nonce: + a: 22403 + b: 0 + c: 0 + d: 0 + Addr: "" + PublicKey: 02ec784ca599f21ef93fe7abdc68d78817ab6c9b31f2324d15ea174d9da498b4c4 + Role: Client +- ID: 000005aa62048f85da4ae9698ed59c14ec0d48a88a07c15a32265634e7e64ade + Nonce: + a: 567323 + b: 0 + c: 0 + d: 3104982049 + Addr: 10.250.100.2:4661 + PublicKey: 0367aa51809a7c1dc0f82c02452fec9557b3e1d10ce7c919d8e73d90048df86d20 + Role: Miner +- ID: 000005f4f22c06f76c43c4f48d5a7ec1309cc94030cbf9ebae814172884ac8b5 + Nonce: + a: 240524 + b: 0 + c: 0 + d: 2305843010430351476 + Addr: 10.250.100.3:4661 + PublicKey: 02914bca0806f040dd842207c44474ab41ecd29deee7f2d355789c5c78d448ca16 + Role: Miner +- ID: 000003f49592f83d0473bddb70d543f1096b4ffed5e5f942a3117e256b7052b8 + Nonce: + a: 606016 + b: 0 + c: 0 + d: 13835058056920509601 + Addr: 10.250.100.4:4661 + PublicKey: 03ae859eac5b72ee428c7a85f10b2ce748d9de5e480aefbb70f6597dfa8b2175e5 + Role: Miner +- ID: 00eda359cd2aa0920cdd37b083b896cb18cd26b3bd51744d1b4f127830f820f2 + Nonce: + a: 11 + b: 0 + c: 2686176025 + d: 0 + Addr: 10.250.100.5:4661 + PublicKey: 02b0da0b36dec5db1b2cf88b5ddbe2dc433d09ddc9a4401a9624995d2319c1d233 + Role: Miner +- ID: 0017017845ff9f9f7e8599d308652eb8ce480e689fbd49afb6b44cc9726cf84b + Nonce: + a: 60 + b: 3189902350 + c: 0 + d: 0 + Addr: 10.250.100.6:4661 + PublicKey: 03075d6743c22bb79208da88c6324b18f3db418d4089c4bad696296c866a65e0e1 + Role: Miner +- ID: 0075b97519d0a5cf9f7269a61b82bb3e082a5e7d796604e877ee28d08491979a + Nonce: + a: 34 + b: 0 + c: 0 + d: 4246204982 + Addr: 10.250.100.7:4661 + PublicKey: 0306678beed432377133f1dfb83b0bdb534d2b0c44e09f457cbb86762a13e88fe1 + Role: Miner +- ID: 0060bb3394f5185f760af690b0c124a70acbaf952fd79d794a0d394c37d7c0bc + Nonce: + a: 13 + b: 515393120 + c: 0 + d: 0 + Addr: 10.250.100.8:4661 + PublicKey: 0303e066f858f98b473ae6cb342c01f1f328021144621dcafce93a023223cba606 + Role: Miner +- ID: 004e5cf49e88f6e35e344f35d73ffe6232d4ebe93a63a825e171b8f6f2a88859 + Nonce: + a: 17 + b: 4213590245 + c: 0 + d: 0 + Addr: 10.250.100.9:4661 + PublicKey: 0297e8deccd7ada1ace2e1ed5b565abf2d3e8aa64b1bb5b36f485714e0f570adba + Role: Miner diff --git a/test/GNTE/conf/node_miner_10.250.100.6/private.key b/test/GNTE/conf/node_miner_10.250.100.6/private.key new file mode 100644 index 000000000..d8705e3c2 --- /dev/null +++ b/test/GNTE/conf/node_miner_10.250.100.6/private.key @@ -0,0 +1 @@ +g1sf:l_t~6 whS\Y-SvX6{+{yvk֛cr>t A8Q \ No newline at end of file diff --git a/test/GNTE/conf/node_miner_10.250.100.7/config.yaml b/test/GNTE/conf/node_miner_10.250.100.7/config.yaml new file mode 100755 index 000000000..3b60c4402 --- /dev/null +++ b/test/GNTE/conf/node_miner_10.250.100.7/config.yaml @@ -0,0 +1,140 @@ +IsTestMode: true +WorkingRoot: "./" +PubKeyStoreFile: "public.keystore" +PrivateKeyFile: "private.key" +DHTFileName: "dht.db" +ListenAddr: "10.250.100.7:4661" +ThisNodeID: "0075b97519d0a5cf9f7269a61b82bb3e082a5e7d796604e877ee28d08491979a" +ValidDNSKeys: + koPbw9wmYZ7ggcjnQ6ayHyhHaDNMYELKTqT+qRGrZpWSccr/lBcrm10Z1PuQHB3Azhii+sb0PYFkH1ruxLhe5g==: cloudflare.com + mdsswUyr3DPW132mOi8V9xESWE8jTo0dxCjjnopKl+GqJxpVXckHAeF+KkxLbxILfDLUT0rAK9iUzy1L53eKGQ==: cloudflare.com +BlockProducer: + PublicKey: "02c76216704d797c64c58bc11519fb68582e8e63de7e5b3b2dbbbe8733efe5fd24" + NodeID: 00000bef611d346c0cbe1beaa76e7f0ed705a194fdf9ac3a248ec70e9c198bf9 + Nonce: + a: 313283 + b: 0 + c: 0 + d: 0 + ChainFileName: "chain.db" + BPGenesisInfo: + Version: 1 + BlockHash: f745ca6427237aac858dd3c7f2df8e6f3c18d0f1c164e07a1c6b8eebeba6b154 + Producer: 0000000000000000000000000000000000000000000000000000000000000001 + MerkleRoot: 0000000000000000000000000000000000000000000000000000000000000001 + ParentHash: 0000000000000000000000000000000000000000000000000000000000000001 + Timestamp: 2018-08-13T21:59:59.12Z +Miner: + IsTestMode: true + RootDir: "./data" + MaxReqTimeGap: "60s" + MetricCollectInterval: "60s" +KnownNodes: +- ID: 00000bef611d346c0cbe1beaa76e7f0ed705a194fdf9ac3a248ec70e9c198bf9 + Nonce: + a: 313283 + b: 0 + c: 0 + d: 0 + Addr: 10.250.1.2:4661 + PublicKey: "02c76216704d797c64c58bc11519fb68582e8e63de7e5b3b2dbbbe8733efe5fd24" + Role: Leader +- ID: 00000381d46fd6cf7742d7fb94e2422033af989c0e348b5781b3219599a3af35 + Nonce: + a: 478373 + b: 0 + c: 0 + d: 2305843009893772025 + Addr: 10.250.1.3:4661 + PublicKey: "02c76216704d797c64c58bc11519fb68582e8e63de7e5b3b2dbbbe8733efe5fd24" + Role: Follower +- ID: 000000172580063ded88e010556b0aca2851265be8845b1ef397e8fce6ab5582 + Nonce: + a: 259939 + b: 0 + c: 0 + d: 2305843012544226372 + Addr: 10.250.1.4:4661 + PublicKey: "02c76216704d797c64c58bc11519fb68582e8e63de7e5b3b2dbbbe8733efe5fd24" + Role: Follower +- ID: 00000f3b43288fe99831eb533ab77ec455d13e11fc38ec35a42d4edd17aa320d + Nonce: + a: 22403 + b: 0 + c: 0 + d: 0 + Addr: "" + PublicKey: 02ec784ca599f21ef93fe7abdc68d78817ab6c9b31f2324d15ea174d9da498b4c4 + Role: Client +- ID: 000005aa62048f85da4ae9698ed59c14ec0d48a88a07c15a32265634e7e64ade + Nonce: + a: 567323 + b: 0 + c: 0 + d: 3104982049 + Addr: 10.250.100.2:4661 + PublicKey: 0367aa51809a7c1dc0f82c02452fec9557b3e1d10ce7c919d8e73d90048df86d20 + Role: Miner +- ID: 000005f4f22c06f76c43c4f48d5a7ec1309cc94030cbf9ebae814172884ac8b5 + Nonce: + a: 240524 + b: 0 + c: 0 + d: 2305843010430351476 + Addr: 10.250.100.3:4661 + PublicKey: 02914bca0806f040dd842207c44474ab41ecd29deee7f2d355789c5c78d448ca16 + Role: Miner +- ID: 000003f49592f83d0473bddb70d543f1096b4ffed5e5f942a3117e256b7052b8 + Nonce: + a: 606016 + b: 0 + c: 0 + d: 13835058056920509601 + Addr: 10.250.100.4:4661 + PublicKey: 03ae859eac5b72ee428c7a85f10b2ce748d9de5e480aefbb70f6597dfa8b2175e5 + Role: Miner +- ID: 00eda359cd2aa0920cdd37b083b896cb18cd26b3bd51744d1b4f127830f820f2 + Nonce: + a: 11 + b: 0 + c: 2686176025 + d: 0 + Addr: 10.250.100.5:4661 + PublicKey: 02b0da0b36dec5db1b2cf88b5ddbe2dc433d09ddc9a4401a9624995d2319c1d233 + Role: Miner +- ID: 0017017845ff9f9f7e8599d308652eb8ce480e689fbd49afb6b44cc9726cf84b + Nonce: + a: 60 + b: 3189902350 + c: 0 + d: 0 + Addr: 10.250.100.6:4661 + PublicKey: 03075d6743c22bb79208da88c6324b18f3db418d4089c4bad696296c866a65e0e1 + Role: Miner +- ID: 0075b97519d0a5cf9f7269a61b82bb3e082a5e7d796604e877ee28d08491979a + Nonce: + a: 34 + b: 0 + c: 0 + d: 4246204982 + Addr: 10.250.100.7:4661 + PublicKey: 0306678beed432377133f1dfb83b0bdb534d2b0c44e09f457cbb86762a13e88fe1 + Role: Miner +- ID: 0060bb3394f5185f760af690b0c124a70acbaf952fd79d794a0d394c37d7c0bc + Nonce: + a: 13 + b: 515393120 + c: 0 + d: 0 + Addr: 10.250.100.8:4661 + PublicKey: 0303e066f858f98b473ae6cb342c01f1f328021144621dcafce93a023223cba606 + Role: Miner +- ID: 004e5cf49e88f6e35e344f35d73ffe6232d4ebe93a63a825e171b8f6f2a88859 + Nonce: + a: 17 + b: 4213590245 + c: 0 + d: 0 + Addr: 10.250.100.9:4661 + PublicKey: 0297e8deccd7ada1ace2e1ed5b565abf2d3e8aa64b1bb5b36f485714e0f570adba + Role: Miner diff --git a/test/GNTE/conf/node_miner_10.250.100.7/private.key b/test/GNTE/conf/node_miner_10.250.100.7/private.key new file mode 100644 index 000000000..724d9a781 --- /dev/null +++ b/test/GNTE/conf/node_miner_10.250.100.7/private.key @@ -0,0 +1,3 @@ +vwJ +|6sU^{]:/ch)VMWN&bioH,~-t~9XEHH/F?h- +i,ނ \ No newline at end of file diff --git a/test/GNTE/conf/node_miner_10.250.100.8/config.yaml b/test/GNTE/conf/node_miner_10.250.100.8/config.yaml new file mode 100755 index 000000000..d81332473 --- /dev/null +++ b/test/GNTE/conf/node_miner_10.250.100.8/config.yaml @@ -0,0 +1,140 @@ +IsTestMode: true +WorkingRoot: "./" +PubKeyStoreFile: "public.keystore" +PrivateKeyFile: "private.key" +DHTFileName: "dht.db" +ListenAddr: "10.250.100.8:4661" +ThisNodeID: "0060bb3394f5185f760af690b0c124a70acbaf952fd79d794a0d394c37d7c0bc" +ValidDNSKeys: + koPbw9wmYZ7ggcjnQ6ayHyhHaDNMYELKTqT+qRGrZpWSccr/lBcrm10Z1PuQHB3Azhii+sb0PYFkH1ruxLhe5g==: cloudflare.com + mdsswUyr3DPW132mOi8V9xESWE8jTo0dxCjjnopKl+GqJxpVXckHAeF+KkxLbxILfDLUT0rAK9iUzy1L53eKGQ==: cloudflare.com +BlockProducer: + PublicKey: "02c76216704d797c64c58bc11519fb68582e8e63de7e5b3b2dbbbe8733efe5fd24" + NodeID: 00000bef611d346c0cbe1beaa76e7f0ed705a194fdf9ac3a248ec70e9c198bf9 + Nonce: + a: 313283 + b: 0 + c: 0 + d: 0 + ChainFileName: "chain.db" + BPGenesisInfo: + Version: 1 + BlockHash: f745ca6427237aac858dd3c7f2df8e6f3c18d0f1c164e07a1c6b8eebeba6b154 + Producer: 0000000000000000000000000000000000000000000000000000000000000001 + MerkleRoot: 0000000000000000000000000000000000000000000000000000000000000001 + ParentHash: 0000000000000000000000000000000000000000000000000000000000000001 + Timestamp: 2018-08-13T21:59:59.12Z +Miner: + IsTestMode: true + RootDir: "./data" + MaxReqTimeGap: "60s" + MetricCollectInterval: "60s" +KnownNodes: +- ID: 00000bef611d346c0cbe1beaa76e7f0ed705a194fdf9ac3a248ec70e9c198bf9 + Nonce: + a: 313283 + b: 0 + c: 0 + d: 0 + Addr: 10.250.1.2:4661 + PublicKey: "02c76216704d797c64c58bc11519fb68582e8e63de7e5b3b2dbbbe8733efe5fd24" + Role: Leader +- ID: 00000381d46fd6cf7742d7fb94e2422033af989c0e348b5781b3219599a3af35 + Nonce: + a: 478373 + b: 0 + c: 0 + d: 2305843009893772025 + Addr: 10.250.1.3:4661 + PublicKey: "02c76216704d797c64c58bc11519fb68582e8e63de7e5b3b2dbbbe8733efe5fd24" + Role: Follower +- ID: 000000172580063ded88e010556b0aca2851265be8845b1ef397e8fce6ab5582 + Nonce: + a: 259939 + b: 0 + c: 0 + d: 2305843012544226372 + Addr: 10.250.1.4:4661 + PublicKey: "02c76216704d797c64c58bc11519fb68582e8e63de7e5b3b2dbbbe8733efe5fd24" + Role: Follower +- ID: 00000f3b43288fe99831eb533ab77ec455d13e11fc38ec35a42d4edd17aa320d + Nonce: + a: 22403 + b: 0 + c: 0 + d: 0 + Addr: "" + PublicKey: 02ec784ca599f21ef93fe7abdc68d78817ab6c9b31f2324d15ea174d9da498b4c4 + Role: Client +- ID: 000005aa62048f85da4ae9698ed59c14ec0d48a88a07c15a32265634e7e64ade + Nonce: + a: 567323 + b: 0 + c: 0 + d: 3104982049 + Addr: 10.250.100.2:4661 + PublicKey: 0367aa51809a7c1dc0f82c02452fec9557b3e1d10ce7c919d8e73d90048df86d20 + Role: Miner +- ID: 000005f4f22c06f76c43c4f48d5a7ec1309cc94030cbf9ebae814172884ac8b5 + Nonce: + a: 240524 + b: 0 + c: 0 + d: 2305843010430351476 + Addr: 10.250.100.3:4661 + PublicKey: 02914bca0806f040dd842207c44474ab41ecd29deee7f2d355789c5c78d448ca16 + Role: Miner +- ID: 000003f49592f83d0473bddb70d543f1096b4ffed5e5f942a3117e256b7052b8 + Nonce: + a: 606016 + b: 0 + c: 0 + d: 13835058056920509601 + Addr: 10.250.100.4:4661 + PublicKey: 03ae859eac5b72ee428c7a85f10b2ce748d9de5e480aefbb70f6597dfa8b2175e5 + Role: Miner +- ID: 00eda359cd2aa0920cdd37b083b896cb18cd26b3bd51744d1b4f127830f820f2 + Nonce: + a: 11 + b: 0 + c: 2686176025 + d: 0 + Addr: 10.250.100.5:4661 + PublicKey: 02b0da0b36dec5db1b2cf88b5ddbe2dc433d09ddc9a4401a9624995d2319c1d233 + Role: Miner +- ID: 0017017845ff9f9f7e8599d308652eb8ce480e689fbd49afb6b44cc9726cf84b + Nonce: + a: 60 + b: 3189902350 + c: 0 + d: 0 + Addr: 10.250.100.6:4661 + PublicKey: 03075d6743c22bb79208da88c6324b18f3db418d4089c4bad696296c866a65e0e1 + Role: Miner +- ID: 0075b97519d0a5cf9f7269a61b82bb3e082a5e7d796604e877ee28d08491979a + Nonce: + a: 34 + b: 0 + c: 0 + d: 4246204982 + Addr: 10.250.100.7:4661 + PublicKey: 0306678beed432377133f1dfb83b0bdb534d2b0c44e09f457cbb86762a13e88fe1 + Role: Miner +- ID: 0060bb3394f5185f760af690b0c124a70acbaf952fd79d794a0d394c37d7c0bc + Nonce: + a: 13 + b: 515393120 + c: 0 + d: 0 + Addr: 10.250.100.8:4661 + PublicKey: 0303e066f858f98b473ae6cb342c01f1f328021144621dcafce93a023223cba606 + Role: Miner +- ID: 004e5cf49e88f6e35e344f35d73ffe6232d4ebe93a63a825e171b8f6f2a88859 + Nonce: + a: 17 + b: 4213590245 + c: 0 + d: 0 + Addr: 10.250.100.9:4661 + PublicKey: 0297e8deccd7ada1ace2e1ed5b565abf2d3e8aa64b1bb5b36f485714e0f570adba + Role: Miner diff --git a/test/GNTE/conf/node_miner_10.250.100.8/private.key b/test/GNTE/conf/node_miner_10.250.100.8/private.key new file mode 100644 index 000000000..b00985df8 Binary files /dev/null and b/test/GNTE/conf/node_miner_10.250.100.8/private.key differ diff --git a/test/GNTE/conf/node_miner_10.250.100.9/config.yaml b/test/GNTE/conf/node_miner_10.250.100.9/config.yaml new file mode 100755 index 000000000..6ca3fae99 --- /dev/null +++ b/test/GNTE/conf/node_miner_10.250.100.9/config.yaml @@ -0,0 +1,140 @@ +IsTestMode: true +WorkingRoot: "./" +PubKeyStoreFile: "public.keystore" +PrivateKeyFile: "private.key" +DHTFileName: "dht.db" +ListenAddr: "10.250.100.9:4661" +ThisNodeID: "004e5cf49e88f6e35e344f35d73ffe6232d4ebe93a63a825e171b8f6f2a88859" +ValidDNSKeys: + koPbw9wmYZ7ggcjnQ6ayHyhHaDNMYELKTqT+qRGrZpWSccr/lBcrm10Z1PuQHB3Azhii+sb0PYFkH1ruxLhe5g==: cloudflare.com + mdsswUyr3DPW132mOi8V9xESWE8jTo0dxCjjnopKl+GqJxpVXckHAeF+KkxLbxILfDLUT0rAK9iUzy1L53eKGQ==: cloudflare.com +BlockProducer: + PublicKey: "02c76216704d797c64c58bc11519fb68582e8e63de7e5b3b2dbbbe8733efe5fd24" + NodeID: 00000bef611d346c0cbe1beaa76e7f0ed705a194fdf9ac3a248ec70e9c198bf9 + Nonce: + a: 313283 + b: 0 + c: 0 + d: 0 + ChainFileName: "chain.db" + BPGenesisInfo: + Version: 1 + BlockHash: f745ca6427237aac858dd3c7f2df8e6f3c18d0f1c164e07a1c6b8eebeba6b154 + Producer: 0000000000000000000000000000000000000000000000000000000000000001 + MerkleRoot: 0000000000000000000000000000000000000000000000000000000000000001 + ParentHash: 0000000000000000000000000000000000000000000000000000000000000001 + Timestamp: 2018-08-13T21:59:59.12Z +Miner: + IsTestMode: true + RootDir: "./data" + MaxReqTimeGap: "60s" + MetricCollectInterval: "60s" +KnownNodes: +- ID: 00000bef611d346c0cbe1beaa76e7f0ed705a194fdf9ac3a248ec70e9c198bf9 + Nonce: + a: 313283 + b: 0 + c: 0 + d: 0 + Addr: 10.250.1.2:4661 + PublicKey: "02c76216704d797c64c58bc11519fb68582e8e63de7e5b3b2dbbbe8733efe5fd24" + Role: Leader +- ID: 00000381d46fd6cf7742d7fb94e2422033af989c0e348b5781b3219599a3af35 + Nonce: + a: 478373 + b: 0 + c: 0 + d: 2305843009893772025 + Addr: 10.250.1.3:4661 + PublicKey: "02c76216704d797c64c58bc11519fb68582e8e63de7e5b3b2dbbbe8733efe5fd24" + Role: Follower +- ID: 000000172580063ded88e010556b0aca2851265be8845b1ef397e8fce6ab5582 + Nonce: + a: 259939 + b: 0 + c: 0 + d: 2305843012544226372 + Addr: 10.250.1.4:4661 + PublicKey: "02c76216704d797c64c58bc11519fb68582e8e63de7e5b3b2dbbbe8733efe5fd24" + Role: Follower +- ID: 00000f3b43288fe99831eb533ab77ec455d13e11fc38ec35a42d4edd17aa320d + Nonce: + a: 22403 + b: 0 + c: 0 + d: 0 + Addr: "" + PublicKey: 02ec784ca599f21ef93fe7abdc68d78817ab6c9b31f2324d15ea174d9da498b4c4 + Role: Client +- ID: 000005aa62048f85da4ae9698ed59c14ec0d48a88a07c15a32265634e7e64ade + Nonce: + a: 567323 + b: 0 + c: 0 + d: 3104982049 + Addr: 10.250.100.2:4661 + PublicKey: 0367aa51809a7c1dc0f82c02452fec9557b3e1d10ce7c919d8e73d90048df86d20 + Role: Miner +- ID: 000005f4f22c06f76c43c4f48d5a7ec1309cc94030cbf9ebae814172884ac8b5 + Nonce: + a: 240524 + b: 0 + c: 0 + d: 2305843010430351476 + Addr: 10.250.100.3:4661 + PublicKey: 02914bca0806f040dd842207c44474ab41ecd29deee7f2d355789c5c78d448ca16 + Role: Miner +- ID: 000003f49592f83d0473bddb70d543f1096b4ffed5e5f942a3117e256b7052b8 + Nonce: + a: 606016 + b: 0 + c: 0 + d: 13835058056920509601 + Addr: 10.250.100.4:4661 + PublicKey: 03ae859eac5b72ee428c7a85f10b2ce748d9de5e480aefbb70f6597dfa8b2175e5 + Role: Miner +- ID: 00eda359cd2aa0920cdd37b083b896cb18cd26b3bd51744d1b4f127830f820f2 + Nonce: + a: 11 + b: 0 + c: 2686176025 + d: 0 + Addr: 10.250.100.5:4661 + PublicKey: 02b0da0b36dec5db1b2cf88b5ddbe2dc433d09ddc9a4401a9624995d2319c1d233 + Role: Miner +- ID: 0017017845ff9f9f7e8599d308652eb8ce480e689fbd49afb6b44cc9726cf84b + Nonce: + a: 60 + b: 3189902350 + c: 0 + d: 0 + Addr: 10.250.100.6:4661 + PublicKey: 03075d6743c22bb79208da88c6324b18f3db418d4089c4bad696296c866a65e0e1 + Role: Miner +- ID: 0075b97519d0a5cf9f7269a61b82bb3e082a5e7d796604e877ee28d08491979a + Nonce: + a: 34 + b: 0 + c: 0 + d: 4246204982 + Addr: 10.250.100.7:4661 + PublicKey: 0306678beed432377133f1dfb83b0bdb534d2b0c44e09f457cbb86762a13e88fe1 + Role: Miner +- ID: 0060bb3394f5185f760af690b0c124a70acbaf952fd79d794a0d394c37d7c0bc + Nonce: + a: 13 + b: 515393120 + c: 0 + d: 0 + Addr: 10.250.100.8:4661 + PublicKey: 0303e066f858f98b473ae6cb342c01f1f328021144621dcafce93a023223cba606 + Role: Miner +- ID: 004e5cf49e88f6e35e344f35d73ffe6232d4ebe93a63a825e171b8f6f2a88859 + Nonce: + a: 17 + b: 4213590245 + c: 0 + d: 0 + Addr: 10.250.100.9:4661 + PublicKey: 0297e8deccd7ada1ace2e1ed5b565abf2d3e8aa64b1bb5b36f485714e0f570adba + Role: Miner diff --git a/test/GNTE/conf/node_miner_10.250.100.9/private.key b/test/GNTE/conf/node_miner_10.250.100.9/private.key new file mode 100644 index 000000000..c1c7fb93b Binary files /dev/null and b/test/GNTE/conf/node_miner_10.250.100.9/private.key differ diff --git a/test/GNTE/run.sh b/test/GNTE/run.sh index ac90a3967..44fc9624c 100755 --- a/test/GNTE/run.sh +++ b/test/GNTE/run.sh @@ -1,10 +1,8 @@ #!/bin/bash -x -BUILD_IMG="covenantsql/build" TEST_WD=$(cd $(dirname $0)/; pwd) PROJECT_DIR=$(cd ${TEST_WD}/../../; pwd) -BENCH_CONTAIN="bench10.250.1.8" echo ${PROJECT_DIR} @@ -24,15 +22,17 @@ cd ${TEST_WD}/GNTE && bash -x ./build.sh cd ${TEST_WD}/GNTE && bash -x ./generate.sh ./scripts/gnte.yaml rm -rf ${TEST_WD}/GNTE/scripts/bin.bak -INSIDE_GOPATH=$(docker run -it --rm ${BUILD_IMG} bash -c 'echo -n "$GOPATH"') -docker run -itd \ - --name ${BENCH_CONTAIN}\ - --net container:client10.250.1.8 \ - -v ${PROJECT_DIR}/../:${INSIDE_GOPATH}/src/github.com/CovenantSQL/ \ - ${BUILD_IMG} tail -f /dev/null - -docker exec -it ${BENCH_CONTAIN} bash -c \ - "cd ${INSIDE_GOPATH}/src/github.com/CovenantSQL/CovenantSQL/client && go test -bench . -run BenchmarkCovenantSQLDriver" - -docker rm -f ${BENCH_CONTAIN} +#BUILD_IMG="covenantsql/build" +#BENCH_CONTAIN="bench10.250.1.8" +#INSIDE_GOPATH=$(docker run -it --rm ${BUILD_IMG} bash -c 'echo -n "$GOPATH"') +#docker run -itd \ +# --name ${BENCH_CONTAIN}\ +# --net container:client10.250.1.8 \ +# -v ${PROJECT_DIR}/../:${INSIDE_GOPATH}/src/github.com/CovenantSQL/ \ +# ${BUILD_IMG} tail -f /dev/null +# +#docker exec -it ${BENCH_CONTAIN} bash -c \ +# "cd ${INSIDE_GOPATH}/src/github.com/CovenantSQL/CovenantSQL/client && go test -bench . -run BenchmarkCovenantSQLDriver" +# +#docker rm -f ${BENCH_CONTAIN} diff --git a/test/node_standalone/config2.yaml b/test/node_standalone/config2.yaml new file mode 100644 index 000000000..7921f4cd1 --- /dev/null +++ b/test/node_standalone/config2.yaml @@ -0,0 +1,45 @@ +IsTestMode: true +WorkingRoot: "./" +PubKeyStoreFile: "public.keystore" +PrivateKeyFile: "private.key" +DHTFileName: "dht.db" +ListenAddr: "127.0.0.1:12230" +ThisNodeID: "00000bef611d346c0cbe1beaa76e7f0ed705a194fdf9ac3a248ec70e9c198bf9" +ValidDNSKeys: + koPbw9wmYZ7ggcjnQ6ayHyhHaDNMYELKTqT+qRGrZpWSccr/lBcrm10Z1PuQHB3Azhii+sb0PYFkH1ruxLhe5g==: cloudflare.com + mdsswUyr3DPW132mOi8V9xESWE8jTo0dxCjjnopKl+GqJxpVXckHAeF+KkxLbxILfDLUT0rAK9iUzy1L53eKGQ==: cloudflare.com +MinNodeIDDifficulty: 2 +DNSSeed: + EnforcedDNSSEC: false + DNSServers: + - 1.1.1.1 + - 202.46.34.74 + - 202.46.34.75 + - 202.46.34.76 + +BlockProducer: + PublicKey: "02c76216704d797c64c58bc11519fb68582e8e63de7e5b3b2dbbbe8733efe5fd24" + NodeID: 00000bef611d346c0cbe1beaa76e7f0ed705a194fdf9ac3a248ec70e9c198bf9 + Nonce: + a: 313283 + b: 0 + c: 0 + d: 0 + ChainFileName: "chain.db" + BPGenesisInfo: + Version: 1 + BlockHash: f745ca6427237aac858dd3c7f2df8e6f3c18d0f1c164e07a1c6b8eebeba6b154 + Producer: 0000000000000000000000000000000000000000000000000000000000000001 + MerkleRoot: 0000000000000000000000000000000000000000000000000000000000000001 + ParentHash: 0000000000000000000000000000000000000000000000000000000000000001 + Timestamp: 2018-08-13T21:59:59.12Z +KnownNodes: +- ID: 00000bef611d346c0cbe1beaa76e7f0ed705a194fdf9ac3a248ec70e9c198bf9 + Nonce: + a: 313283 + b: 0 + c: 0 + d: 0 + Addr: 127.0.0.1:12230 + PublicKey: "02c76216704d797c64c58bc11519fb68582e8e63de7e5b3b2dbbbe8733efe5fd24" + Role: Leader diff --git a/twopc/twopc.go b/twopc/twopc.go index 31d247e7b..3912077d7 100644 --- a/twopc/twopc.go +++ b/twopc/twopc.go @@ -18,11 +18,11 @@ package twopc import ( "context" - "fmt" "sync" "time" "github.com/CovenantSQL/CovenantSQL/utils/log" + "github.com/pkg/errors" ) // Hook are called during 2PC running @@ -98,7 +98,7 @@ func (c *Coordinator) rollback(ctx context.Context, workers []Worker, wb WriteBa } } - return fmt.Errorf("twopc: rollback") + return errors.New("twopc: rollback") } func (c *Coordinator) commit(ctx context.Context, workers []Worker, wb WriteBatch) (err error) { @@ -154,7 +154,7 @@ func (c *Coordinator) Put(workers []Worker, wb WriteBatch) (err error) { for index, err := range errs { if err != nil { returnErr = err - log.Debugf("prepare failed on %v: err = %v", workers[index], err) + log.WithField("worker", workers[index]).WithError(err).Debug("prepare failed") goto ROLLBACK } } @@ -162,7 +162,7 @@ func (c *Coordinator) Put(workers []Worker, wb WriteBatch) (err error) { if c.option.beforeCommit != nil { if err := c.option.beforeCommit(ctx); err != nil { returnErr = err - log.Debugf("before commit failed: err = %v", err) + log.WithError(err).Debug("before commit failed") goto ROLLBACK } } @@ -171,7 +171,7 @@ func (c *Coordinator) Put(workers []Worker, wb WriteBatch) (err error) { if c.option.afterCommit != nil { if err = c.option.afterCommit(ctx); err != nil { - log.Debugf("after commit failed: err = %v", err) + log.WithError(err).Debug("after commit failed") } } diff --git a/twopc/twopc_test.go b/twopc/twopc_test.go index 6525d3b87..dfb3504a8 100644 --- a/twopc/twopc_test.go +++ b/twopc/twopc_test.go @@ -18,16 +18,14 @@ package twopc import ( "context" + "errors" "fmt" + "net" "os" "sync" "testing" "time" - "net" - - "errors" - "github.com/CovenantSQL/CovenantSQL/crypto/etls" "github.com/CovenantSQL/CovenantSQL/rpc" "github.com/CovenantSQL/CovenantSQL/utils/log" @@ -205,13 +203,19 @@ func (r *RaftNodeRPCServer) RPCRollback(req *RaftRollbackReq, resp *RaftRollback } func (r *RaftNode) Prepare(ctx context.Context, wb WriteBatch) (err error) { - log.Debugf("executing 2pc: addr = %s, phase = prepare", r.addr) - defer log.Debugf("2pc result: addr = %s, phase = prepare, result = %v", r.addr, err) + log.WithFields(log.Fields{ + "addr": r.addr, + "phase": "prepare", + }).Debug("executing 2pc") + defer log.WithFields(log.Fields{ + "addr": r.addr, + "phase": "prepare", + }).WithError(err).Debug("2pc result") rwb, ok := wb.(*RaftWriteBatchReq) if !ok { - err = fmt.Errorf("unexpected WriteBatch type") + err = errors.New("unexpected WriteBatch type") return err } @@ -259,7 +263,7 @@ func (r *RaftNode) Commit(ctx context.Context, wb WriteBatch) (err error) { rwb, ok := wb.(*RaftWriteBatchReq) if !ok { - err = fmt.Errorf("unexpected WriteBatch type") + err = errors.New("unexpected WriteBatch type") return err } @@ -307,7 +311,7 @@ func (r *RaftNode) Rollback(ctx context.Context, wb WriteBatch) (err error) { rwb, ok := wb.(*RaftWriteBatchReq) if !ok { - err = fmt.Errorf("unexpected WriteBatch type") + err = errors.New("unexpected WriteBatch type") return err } diff --git a/utils/big.go b/utils/big.go index 0c7e75930..6568671f5 100644 --- a/utils/big.go +++ b/utils/big.go @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// Package math provides integer math utilities. +// Package utils provides integer math utilities. package utils import ( diff --git a/utils/bytes.go b/utils/bytes.go new file mode 100644 index 000000000..5f0b77459 --- /dev/null +++ b/utils/bytes.go @@ -0,0 +1,33 @@ +/* + * Copyright 2018 The CovenantSQL Authors. + * + * 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. + */ + +package utils + +// ConcatAll concatenate several bytes slice into one. +func ConcatAll(args ...[]byte) []byte { + var bLen int + for i := range args { + bLen += len(args[i]) + } + + key := make([]byte, bLen) + position := 0 + for i := range args { + copy(key[position:], args[i]) + position += len(args[i]) + } + return key +} diff --git a/utils/bytes_test.go b/utils/bytes_test.go new file mode 100644 index 000000000..9276681de --- /dev/null +++ b/utils/bytes_test.go @@ -0,0 +1,45 @@ +/* + * Copyright 2018 The CovenantSQL Authors. + * + * 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. + */ + +package utils + +import ( + "testing" + + "github.com/CovenantSQL/CovenantSQL/utils/log" + . "github.com/smartystreets/goconvey/convey" +) + +func TestNewLevelDBKey(t *testing.T) { + Convey("new bytes", t, func() { + log.SetLevel(log.DebugLevel) + So(ConcatAll(nil), ShouldResemble, []byte{}) + So(ConcatAll([]byte{}), ShouldResemble, []byte{}) + So(ConcatAll([]byte{'0'}, []byte{'1'}), ShouldResemble, []byte{'0', '1'}) + So(ConcatAll([]byte{'0'}, nil), ShouldResemble, []byte{'0'}) + So(ConcatAll(nil, []byte{'0'}), ShouldResemble, []byte{'0'}) + So(ConcatAll([]byte{'0', '1', '2', '3'}, []byte{'a', 'b', 'c', 'd', 'e'}, []byte{'x', 'y', 'z'}), + ShouldResemble, []byte{'0', '1', '2', '3', 'a', 'b', 'c', 'd', 'e', 'x', 'y', 'z'}) + So(ConcatAll([]byte{'0', '1', '2', '3'}, nil, []byte{'x', 'y', 'z'}), + ShouldResemble, []byte{'0', '1', '2', '3', 'x', 'y', 'z'}) + So(ConcatAll([]byte{'0', '1', '2', '3'}, []byte{}, []byte{'x', 'y', 'z'}), + ShouldResemble, []byte{'0', '1', '2', '3','x', 'y', 'z'}) + So(ConcatAll(nil, []byte{'0', '1', '2', '3'}, nil, []byte{'x', 'y', 'z'}), + ShouldResemble, []byte{'0', '1', '2', '3', 'x', 'y', 'z'}) + So(ConcatAll([]byte{}, []byte{'0', '1', '2', '3'}, nil, []byte{'x', 'y', 'z'}, nil), + ShouldResemble, []byte{'0', '1', '2', '3', 'x', 'y', 'z'}) + }) +} diff --git a/utils/exec.go b/utils/exec.go index 596bbe5d7..303e000aa 100644 --- a/utils/exec.go +++ b/utils/exec.go @@ -46,15 +46,32 @@ func Build() (err error) { wd := GetProjectSrcDir() err = os.Chdir(wd) if err != nil { - log.Errorf("change working dir failed: %s", err) + log.WithError(err).Error("change working dir failed") return } cmd := exec.Command("./build.sh") output, err := cmd.CombinedOutput() if err != nil { - log.Errorf("build failed: %s", err) + log.WithError(err).Error("build failed") } - log.Debugf("build output info: %s", string(output)) + log.Debugf("build output info: %#v", string(output)) + return +} + +// CleanupDB runs cleanupDB.sh +func CleanupDB() (err error) { + wd := GetProjectSrcDir() + err = os.Chdir(wd) + if err != nil { + log.WithError(err).Error("change working dir failed") + return + } + cmd := exec.Command("./cleanupDB.sh") + output, err := cmd.CombinedOutput() + if err != nil { + log.WithError(err).Error("cleanupDB failed") + } + log.Debugf("cleanupDB output info: %#v", string(output)) return } @@ -63,12 +80,19 @@ func Build() (err error) { func RunCommand(bin string, args []string, processName string, workingDir string, logDir string, toStd bool) (err error) { cmd, err := RunCommandNB(bin, args, processName, workingDir, logDir, toStd) if err != nil { - log.Errorf("start command failed: %v", err) + log.WithFields(log.Fields{ + "bin": bin, + "args": args, + "process": processName, + }).WithError(err).Error("start command failed") return } err = cmd.Cmd.Wait() if err != nil { - log.Errorf("cmd %s args %s failed with %v", cmd.Cmd.Path, cmd.Cmd.Args, err) + log.WithFields(log.Fields{ + "path": cmd.Cmd.Path, + "args": cmd.Cmd.Args, + }).WithError(err).Error("wait command failed") return } return @@ -80,13 +104,13 @@ func RunCommandNB(bin string, args []string, processName string, workingDir stri cmd.LogPath = FJ(logDir, processName+".log") logFD, err := os.Create(cmd.LogPath) if err != nil { - log.Errorf("create log file failed: %s", err) + log.WithField("path", cmd.LogPath).WithError(err).Error("create log file failed") return } err = os.Chdir(workingDir) if err != nil { - log.Errorf("change working dir failed: %s", err) + log.WithField("wd", workingDir).Error("change working dir failed") return } cmd.Cmd = exec.Command(bin, args...) @@ -104,14 +128,14 @@ func RunCommandNB(bin string, args []string, processName string, workingDir stri err = cmd.Cmd.Start() if err != nil { - log.Errorf("cmd.Start() failed with '%v'", err) + log.WithError(err).Error("cmd.Start() failed") return } go func() { _, err := io.Copy(stdout, stdoutIn) if err != nil { - log.Errorf("failed to capture stdout %s", err) + log.WithError(err).Error("failed to capture stdout") return } }() @@ -119,7 +143,7 @@ func RunCommandNB(bin string, args []string, processName string, workingDir stri go func() { _, err := io.Copy(stderr, stderrIn) if err != nil { - log.Errorf("failed to capture stderr %s", err) + log.WithError(err).Error("failed to capture stderr") return } }() diff --git a/utils/exec_test.go b/utils/exec_test.go index f0e37b55e..695b40ee9 100644 --- a/utils/exec_test.go +++ b/utils/exec_test.go @@ -38,6 +38,13 @@ func TestBuild(t *testing.T) { }) } +func TestCleanupDB(t *testing.T) { + Convey("CleanupDB", t, func() { + log.SetLevel(log.DebugLevel) + So(CleanupDB(), ShouldBeNil) + }) +} + func TestRunServer(t *testing.T) { Convey("build", t, func() { log.SetLevel(log.DebugLevel) diff --git a/utils/log/entrylogwrapper.go b/utils/log/entrylogwrapper.go new file mode 100644 index 000000000..125c05b74 --- /dev/null +++ b/utils/log/entrylogwrapper.go @@ -0,0 +1,159 @@ +/* + * Copyright 2018 The CovenantSQL Authors. + * + * 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. + */ + +package log + +import ( + "time" + + "github.com/sirupsen/logrus" +) + +type Entry logrus.Entry + +func NewEntry(logger *Logger) *Entry { + return &Entry{ + Logger: (*logrus.Logger)(logger), + // Default is five fields, give a little extra room + Data: make(logrus.Fields, 5), + } +} + +// Returns the string representation from the reader and ultimately the +// formatter. +func (entry *Entry) String() (string, error) { + return (*logrus.Entry)(entry).String() +} + +// Add an error as single field (using the key defined in ErrorKey) to the Entry. +func (entry *Entry) WithError(err error) *Entry { + return (*Entry)((*logrus.Entry)(entry).WithError(err)) +} + +// Add a single field to the Entry. +func (entry *Entry) WithField(key string, value interface{}) *Entry { + return (*Entry)((*logrus.Entry)(entry).WithField(key, value)) +} + +// Add a map of fields to the Entry. +func (entry *Entry) WithFields(fields Fields) *Entry { + return (*Entry)((*logrus.Entry)(entry).WithFields((logrus.Fields)(fields))) +} + +// Overrides the time of the Entry. +func (entry *Entry) WithTime(t time.Time) *Entry { + return &Entry{Logger: entry.Logger, Data: entry.Data, Time: t} +} + +func (entry *Entry) Debug(args ...interface{}) { + (*logrus.Entry)(entry).Debug(args...) +} + +func (entry *Entry) Print(args ...interface{}) { + (*logrus.Entry)(entry).Print(args...) +} + +func (entry *Entry) Info(args ...interface{}) { + (*logrus.Entry)(entry).Info(args...) +} + +func (entry *Entry) Warn(args ...interface{}) { + (*logrus.Entry)(entry).Warn(args...) +} + +func (entry *Entry) Warning(args ...interface{}) { + (*logrus.Entry)(entry).Warning(args...) +} + +func (entry *Entry) Error(args ...interface{}) { + (*logrus.Entry)(entry).Error(args...) +} + +func (entry *Entry) Fatal(args ...interface{}) { + (*logrus.Entry)(entry).Fatal(args...) +} + +func (entry *Entry) Panic(args ...interface{}) { + (*logrus.Entry)(entry).Panic(args...) +} + +// Entry Printf family functions + +func (entry *Entry) Debugf(format string, args ...interface{}) { + (*logrus.Entry)(entry).Debugf(format, args...) +} + +func (entry *Entry) Infof(format string, args ...interface{}) { + (*logrus.Entry)(entry).Infof(format, args...) +} + +func (entry *Entry) Printf(format string, args ...interface{}) { + (*logrus.Entry)(entry).Printf(format, args...) +} + +func (entry *Entry) Warnf(format string, args ...interface{}) { + (*logrus.Entry)(entry).Warnf(format, args...) +} + +func (entry *Entry) Warningf(format string, args ...interface{}) { + (*logrus.Entry)(entry).Warningf(format, args...) +} + +func (entry *Entry) Errorf(format string, args ...interface{}) { + (*logrus.Entry)(entry).Errorf(format, args...) +} + +func (entry *Entry) Fatalf(format string, args ...interface{}) { + (*logrus.Entry)(entry).Fatalf(format, args...) +} + +func (entry *Entry) Panicf(format string, args ...interface{}) { + (*logrus.Entry)(entry).Panicf(format, args...) +} + +// Entry Println family functions + +func (entry *Entry) Debugln(args ...interface{}) { + (*logrus.Entry)(entry).Debugln(args...) +} + +func (entry *Entry) Infoln(args ...interface{}) { + (*logrus.Entry)(entry).Infoln(args...) +} + +func (entry *Entry) Println(args ...interface{}) { + (*logrus.Entry)(entry).Println(args...) +} + +func (entry *Entry) Warnln(args ...interface{}) { + (*logrus.Entry)(entry).Warnln(args...) +} + +func (entry *Entry) Warningln(args ...interface{}) { + (*logrus.Entry)(entry).Warningln(args...) +} + +func (entry *Entry) Errorln(args ...interface{}) { + (*logrus.Entry)(entry).Errorln(args...) +} + +func (entry *Entry) Fatalln(args ...interface{}) { + (*logrus.Entry)(entry).Fatalln(args...) +} + +func (entry *Entry) Panicln(args ...interface{}) { + (*logrus.Entry)(entry).Panicln(args...) +} diff --git a/utils/log/logwrapper.go b/utils/log/logwrapper.go index a013cfcb4..3c32421f5 100644 --- a/utils/log/logwrapper.go +++ b/utils/log/logwrapper.go @@ -22,6 +22,7 @@ import ( "path/filepath" "runtime" "strings" + "time" "github.com/sirupsen/logrus" ) @@ -49,6 +50,7 @@ const ( // if package name exists and log level is more verbose, the log will be dropped var PkgDebugLogFilter = map[string]logrus.Level{ "metric": InfoLevel, + "rpc": InfoLevel, } // Logger wraps logrus logger type. @@ -58,11 +60,28 @@ type Logger logrus.Logger type Fields logrus.Fields // CallerHook defines caller awareness hook for logrus. -type CallerHook struct{} +type CallerHook struct { + StackLevels []logrus.Level +} + +// NewCallerHook creates new CallerHook +func NewCallerHook(stackLevels []logrus.Level) *CallerHook { + return &CallerHook{ + StackLevels: stackLevels, + } +} + +// StandardCallerHook is a convenience initializer for LogrusStackHook{} with +// default args. +func StandardCallerHook() *CallerHook { + return NewCallerHook( + []logrus.Level{logrus.PanicLevel, logrus.FatalLevel, logrus.ErrorLevel}, + ) +} // Fire defines hook event handler. func (hook *CallerHook) Fire(entry *logrus.Entry) error { - funcDesc, caller := hook.caller() + funcDesc, caller := hook.caller(entry) fields := strings.SplitN(funcDesc, ".", 2) if len(fields) > 0 { level, ok := PkgDebugLogFilter[fields[0]] @@ -89,27 +108,61 @@ func (hook *CallerHook) Levels() []logrus.Level { } } -func (hook *CallerHook) caller() (relFuncName, caller string) { - var ( - file = "unknown" - line = 0 - ok = false - funcName = "unknown" - pc uintptr - ) - pc, file, line, ok = runtime.Caller(10) - details := runtime.FuncForPC(pc) - if ok && details != nil { - funcName = details.Name() +func (hook *CallerHook) caller(entry *logrus.Entry) (relFuncName, caller string) { + var skipFrames int + if len(entry.Data) == 0 { + // When WithField(s) is not used, we have 8 logrus frames to skip. + skipFrames = 8 + } else { + // When WithField(s) is used, we have 6 logrus frames to skip. + skipFrames = 6 } - relFuncName = strings.TrimPrefix(funcName, "github.com/CovenantSQL/CovenantSQL/") - funcLocation := fmt.Sprintf("%s:%d %s", filepath.Base(file), line, relFuncName) - return relFuncName, funcLocation + pcs := make([]uintptr, 12) + stacks := make([]runtime.Frame, 0, 12) + if runtime.Callers(skipFrames, pcs) > 0 { + var foundCaller bool + _frames := runtime.CallersFrames(pcs) + for { + f, more := _frames.Next() + //fmt.Printf("%s:%d %s\n", f.File, f.Line, f.Function) + if !foundCaller && strings.HasSuffix(f.File, "logwrapper.go") && more { + f, _ = _frames.Next() + relFuncName = strings.TrimPrefix(f.Function, "github.com/CovenantSQL/CovenantSQL/") + caller = fmt.Sprintf("%s:%d %s", filepath.Base(f.File), f.Line, relFuncName) + foundCaller = true + } + if foundCaller { + stacks = append(stacks, f) + } + if !more { + break + } + } + } + + if len(stacks) > 0 { + for _, level := range hook.StackLevels { + if entry.Level == level { + stacksStr := make([]string, 0, len(stacks)) + for i, s := range stacks { + if s.Line > 0 { + fName := strings.TrimPrefix(s.Function, "github.com/CovenantSQL/CovenantSQL/") + stackStr := fmt.Sprintf("#%d %s@%s:%d ", i, fName, filepath.Base(s.File), s.Line) + stacksStr = append(stacksStr, stackStr) + } + } + entry.Data["stack"] = stacksStr + break + } + } + } + + return relFuncName, caller } func init() { - AddHook(&CallerHook{}) + AddHook(StandardCallerHook()) } //var ( @@ -148,8 +201,8 @@ func AddHook(hook logrus.Hook) { } // WithError creates an entry from the standard logger and adds an error to it, using the value defined in ErrorKey as key. -func WithError(err error) *logrus.Entry { - return logrus.WithField(logrus.ErrorKey, err) +func WithError(err error) *Entry { + return WithField(logrus.ErrorKey, err) } // WithField creates an entry from the standard logger and adds a field to @@ -157,8 +210,8 @@ func WithError(err error) *logrus.Entry { // // Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal // or Panic on the Entry it returns. -func WithField(key string, value interface{}) *logrus.Entry { - return logrus.WithField(key, value) +func WithField(key string, value interface{}) *Entry { + return (*Entry)(logrus.WithField(key, value)) } // WithFields creates an entry from the standard logger and adds multiple @@ -167,8 +220,12 @@ func WithField(key string, value interface{}) *logrus.Entry { // // Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal // or Panic on the Entry it returns. -func WithFields(fields Fields) *logrus.Entry { - return logrus.WithFields(logrus.Fields(fields)) +func WithFields(fields Fields) *Entry { + return (*Entry)(logrus.WithFields(logrus.Fields(fields))) +} + +func WithTime(t time.Time) *Entry { + return (*Entry)(logrus.WithTime(t)) } // Debug logs a message at level Debug on the standard logger. @@ -219,6 +276,11 @@ func Debugf(format string, args ...interface{}) { logrus.Debugf(format, args...) } +// Printf logs a message at level Info on the standard logger. +func (l *Logger) Printf(format string, args ...interface{}) { + Printf(format, args...) +} + // Printf logs a message at level Info on the standard logger. func Printf(format string, args ...interface{}) { logrus.Printf(format, args...) diff --git a/utils/log/logwrapper_test.go b/utils/log/logwrapper_test.go new file mode 100644 index 000000000..acc6dfc0d --- /dev/null +++ b/utils/log/logwrapper_test.go @@ -0,0 +1,156 @@ +/* + * Copyright 2018 The CovenantSQL Authors. + * + * 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. + */ + +package log + +import ( + "fmt" + "testing" + "time" + + "github.com/pkg/errors" + + "github.com/sirupsen/logrus" +) + +func init() { + AddHook(&CallerHook{}) +} + +func TestStandardLogger(t *testing.T) { + SetLevel(DebugLevel) + if GetLevel() != DebugLevel { + t.Fail() + } + Debug("Debug") + Debugln("Debugln") + Debugf("Debugf %d", 1) + Print("Print") + Println("Println") + Printf("Printf %d", 1) + Info("Info") + Infoln("Infoln") + Infof("Infof %d", 1) + Warning("Warning") + Warningln("Warningln") + Warningf("Warningf %d", 1) + Warn("Warn") + Warnln("Warnln") + Warnln("Warnln") + Warnf("Warnf %d", 1) + Error("Error") + Errorln("Errorln") + Errorf("Errorf %d", 1) + defer func() { + if r := recover(); r != nil { + fmt.Println("Recovered in f", r) + } + defer func() { + if r := recover(); r != nil { + fmt.Println("Recovered in f", r) + } + defer func() { + if r := recover(); r != nil { + fmt.Println("Recovered in f", r) + } + n := NilFormatter{} + a, b := n.Format(&logrus.Entry{}) + if a != nil || b != nil { + t.Fail() + } + }() + Panicf("Panicf %d", 1) + }() + Panicln("Panicln") + + }() + + Panic("Panic") + +} + +func call0() { + call1() +} + +func call1() { + call2() +} + +func call2() { + WithField("k", "v").Error("Error") + Error("call2 error") +} + +func TestWithField(t *testing.T) { + SetLevel(DebugLevel) + if GetLevel() != DebugLevel { + t.Fail() + } + + call0() + + f := new(Fields) + WithError(errors.New("new")).WithFields(*f).WithTime(time.Now()).Debug("Debug") + + WithFields(*f).Debug("Debug") + WithTime(time.Now()).WithError(errors.New("new")).Debug("Debug") + NewEntry(StandardLogger()).WithTime(time.Now()).String() + + WithField("k", "v").Debug("Debug") + WithField("k", "v").Debugln("Debugln") + WithField("k", "v").Debugf("Debugf %d", 1) + WithField("k", "v").Print("Print") + WithField("k", "v").Println("Println") + WithField("k", "v").Printf("Printf %d", 1) + WithField("k", "v").Info("Info") + WithField("k", "v").Infoln("Infoln") + WithField("k", "v").Infof("Infof %d", 1) + WithField("k", "v").Warning("Warning") + WithField("k", "v").Warningln("Warningln") + WithField("k", "v").Warningf("Warningf %d", 1) + WithField("k", "v").Warn("Warn") + WithField("k", "v").Warnln("Warnln") + WithField("k", "v").Warnln("Warnln") + WithField("k", "v").Warnf("Warnf %d", 1) + WithField("k", "v").Error("Error") + WithField("k", "v").Errorln("Errorln") + WithField("k", "v").Errorf("Errorf %d", 1) + defer func() { + if r := recover(); r != nil { + fmt.Println("Recovered in f", r) + } + defer func() { + if r := recover(); r != nil { + fmt.Println("Recovered in f", r) + } + defer func() { + if r := recover(); r != nil { + fmt.Println("Recovered in f", r) + } + n := NilFormatter{} + a, b := n.Format(&logrus.Entry{}) + if a != nil || b != nil { + t.Fail() + } + }() + WithField("k", "v").Panicf("Panicf %d", 1) + }() + WithField("k", "v").Panicln("Panicln") + }() + + WithField("k", "v").Panic("Panic") +} diff --git a/utils/msgpack.go b/utils/msgpack.go index fdaa89b64..f443c9184 100644 --- a/utils/msgpack.go +++ b/utils/msgpack.go @@ -18,39 +18,56 @@ package utils import ( "bytes" + "net" + "net/rpc" + "reflect" "github.com/ugorji/go/codec" ) -// DecodeMsgPack reverses the encode operation on a byte slice input. -func DecodeMsgPack(buf []byte, out interface{}) error { - r := bytes.NewBuffer(buf) - hd := codec.MsgpackHandle{ +var ( + msgPackHandle = &codec.MsgpackHandle{ WriteExt: true, RawToString: true, } - dec := codec.NewDecoder(r, &hd) +) + +// RegisterInterfaceToMsgPack binds interface decode/encode to specified implementation. +func RegisterInterfaceToMsgPack(intf, impl reflect.Type) (err error) { + return msgPackHandle.Intf2Impl(intf, impl) +} + +// DecodeMsgPack reverses the encode operation on a byte slice input. +func DecodeMsgPack(buf []byte, out interface{}) error { + r := bytes.NewBuffer(buf) + dec := codec.NewDecoder(r, msgPackHandle) return dec.Decode(out) } // DecodeMsgPackPlain reverses the encode operation on a byte slice input without RawToString setting. func DecodeMsgPackPlain(buf []byte, out interface{}) error { r := bytes.NewBuffer(buf) - hd := codec.MsgpackHandle{ + hd := &codec.MsgpackHandle{ WriteExt: true, } - dec := codec.NewDecoder(r, &hd) + dec := codec.NewDecoder(r, hd) return dec.Decode(out) } // EncodeMsgPack writes an encoded object to a new bytes buffer. func EncodeMsgPack(in interface{}) (*bytes.Buffer, error) { buf := bytes.NewBuffer(nil) - hd := codec.MsgpackHandle{ - WriteExt: true, - RawToString: true, - } - enc := codec.NewEncoder(buf, &hd) + enc := codec.NewEncoder(buf, msgPackHandle) err := enc.Encode(in) return buf, err } + +// GetMsgPackServerCodec returns msgpack server codec for connection. +func GetMsgPackServerCodec(c net.Conn) rpc.ServerCodec { + return codec.MsgpackSpecRpc.ServerCodec(c, msgPackHandle) +} + +// GetMsgPackClientCodec returns msgpack client codec for connection. +func GetMsgPackClientCodec(c net.Conn) rpc.ClientCodec { + return codec.MsgpackSpecRpc.ClientCodec(c, msgPackHandle) +} diff --git a/utils/net.go b/utils/net.go index bad128d16..40c6d7a48 100644 --- a/utils/net.go +++ b/utils/net.go @@ -24,6 +24,8 @@ import ( "net" "sync" "time" + + "github.com/CovenantSQL/CovenantSQL/utils/log" ) var ( @@ -34,6 +36,17 @@ var ( allocateLock sync.Mutex ) +func testPortConnectable(addr string, timeout time.Duration) bool { + conn, err := net.DialTimeout("tcp", addr, timeout) + if err != nil { + log.Infof("test dial to %s failed", addr) + return false + } else { + conn.Close() + return true + } +} + func testPort(bindAddr string, port int, excludeAllocated bool) bool { addr := net.JoinHostPort(bindAddr, fmt.Sprint(port)) @@ -51,7 +64,27 @@ func testPort(bindAddr string, port int, excludeAllocated bool) bool { return true } -// WaitForPorts returns only when port is ready or canceled by context. +// WaitToConnect returns only when port is ready to connect or canceled by context. +func WaitToConnect(ctx context.Context, bindAddr string, ports []int, interval time.Duration) (err error) { + for { + continueCheckC: + select { + case <-ctx.Done(): + err = ctx.Err() + return + case <-time.After(interval): + for _, port := range ports { + addr := net.JoinHostPort(bindAddr, fmt.Sprint(port)) + if !testPortConnectable(addr, 100*time.Millisecond) { + goto continueCheckC + } + } + return + } + } +} + +// WaitForPorts returns only when port is ready to listen or canceled by context. func WaitForPorts(ctx context.Context, bindAddr string, ports []int, interval time.Duration) (err error) { for { continueCheck: diff --git a/utils/net_test.go b/utils/net_test.go index cf458f123..bf7c82157 100644 --- a/utils/net_test.go +++ b/utils/net_test.go @@ -17,12 +17,10 @@ package utils import ( - "testing" - - "net" - "context" "fmt" + "net" + "testing" "time" . "github.com/smartystreets/goconvey/convey" @@ -87,13 +85,21 @@ func TestWaitForPorts(t *testing.T) { err = WaitForPorts(context.Background(), "127.0.0.1", ports, time.Millisecond*100) So(err, ShouldBeNil) + ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*300) + defer cancel() + err = WaitToConnect(ctx, "127.0.0.1", ports, time.Millisecond*100) + So(err, ShouldNotBeNil) + // listen ln, err := net.Listen("tcp", net.JoinHostPort("127.0.0.1", fmt.Sprint(ports[0]))) So(ln, ShouldNotBeNil) So(err, ShouldBeNil) defer ln.Close() - ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*300) + err = WaitToConnect(context.Background(), "127.0.0.1", ports, time.Millisecond*100) + So(err, ShouldBeNil) + + ctx, cancel = context.WithTimeout(context.Background(), time.Millisecond*300) defer cancel() err = WaitForPorts(ctx, "127.0.0.1", ports, time.Millisecond*100) So(err, ShouldNotBeNil) diff --git a/utils/path_test.go b/utils/path_test.go index c2363a593..b0c4fa8b3 100644 --- a/utils/path_test.go +++ b/utils/path_test.go @@ -17,11 +17,9 @@ package utils import ( - "testing" - "io/ioutil" - "os" + "testing" . "github.com/smartystreets/goconvey/convey" ) diff --git a/utils/profiler.go b/utils/profiler.go index 369355437..013dd3e7c 100644 --- a/utils/profiler.go +++ b/utils/profiler.go @@ -34,10 +34,10 @@ func StartProfile(cpuprofile, memprofile string) error { if cpuprofile != "" { f, err := os.Create(cpuprofile) if err != nil { - log.Errorf("failed to create CPU profile file at %s: %s", cpuprofile, err.Error()) + log.WithField("file", cpuprofile).WithError(err).Error("failed to create CPU profile file") return err } - log.Infof("writing CPU profile to: %s\n", cpuprofile) + log.WithField("file", cpuprofile).Info("writing CPU profiling to file") prof.cpu = f pprof.StartCPUProfile(prof.cpu) } @@ -45,10 +45,10 @@ func StartProfile(cpuprofile, memprofile string) error { if memprofile != "" { f, err := os.Create(memprofile) if err != nil { - log.Errorf("failed to create memory profile file at %s: %s", cpuprofile, err.Error()) + log.WithField("file", memprofile).WithError(err).Error("failed to create memory profile file") return err } - log.Infof("writing memory profile to: %s\n", memprofile) + log.WithField("file", cpuprofile).WithError(err).Info("writing memory profiling to file") prof.mem = f runtime.MemProfileRate = 4096 } @@ -60,11 +60,11 @@ func StopProfile() { if prof.cpu != nil { pprof.StopCPUProfile() prof.cpu.Close() - log.Infof("CPU profiling stopped") + log.Info("CPU profiling stopped") } if prof.mem != nil { pprof.Lookup("heap").WriteTo(prof.mem, 0) prof.mem.Close() - log.Infof("memory profiling stopped") + log.Info("memory profiling stopped") } } diff --git a/utils/profiler_test.go b/utils/profiler_test.go index aeba66718..80bc8b9ee 100644 --- a/utils/profiler_test.go +++ b/utils/profiler_test.go @@ -17,9 +17,8 @@ package utils import ( - "testing" - "os" + "testing" . "github.com/smartystreets/goconvey/convey" ) diff --git a/vendor/github.com/CovenantSQL/sqlparser/sql.go b/vendor/github.com/CovenantSQL/sqlparser/sql.go index 553226726..54f4cdef6 100644 --- a/vendor/github.com/CovenantSQL/sqlparser/sql.go +++ b/vendor/github.com/CovenantSQL/sqlparser/sql.go @@ -135,90 +135,92 @@ const COMMENT = 57389 const NULL = 57390 const TRUE = 57391 const FALSE = 57392 -const OR = 57393 -const AND = 57394 -const NOT = 57395 -const BETWEEN = 57396 -const CASE = 57397 -const WHEN = 57398 -const THEN = 57399 -const ELSE = 57400 -const END = 57401 -const LE = 57402 -const GE = 57403 -const NE = 57404 -const IS = 57405 -const LIKE = 57406 -const REGEXP = 57407 -const IN = 57408 -const NULL_SAFE_NOTEQUAL = 57409 -const SHIFT_LEFT = 57410 -const SHIFT_RIGHT = 57411 -const DIV = 57412 -const MOD = 57413 -const UNARY = 57414 -const INTERVAL = 57415 -const CREATE = 57416 -const ALTER = 57417 -const DROP = 57418 -const RENAME = 57419 -const ADD = 57420 -const TABLE = 57421 -const INDEX = 57422 -const TO = 57423 -const IGNORE = 57424 -const IF = 57425 -const UNIQUE = 57426 -const PRIMARY = 57427 -const COLUMN = 57428 -const CONSTRAINT = 57429 -const FOREIGN = 57430 -const SHOW = 57431 -const DESCRIBE = 57432 -const DATE = 57433 -const ESCAPE = 57434 -const TINYINT = 57435 -const SMALLINT = 57436 -const MEDIUMINT = 57437 -const INT = 57438 -const INTEGER = 57439 -const BIGINT = 57440 -const INTNUM = 57441 -const REAL = 57442 -const DOUBLE = 57443 -const FLOAT_TYPE = 57444 -const DECIMAL = 57445 -const NUMERIC = 57446 -const TIME = 57447 -const TIMESTAMP = 57448 -const DATETIME = 57449 -const YEAR = 57450 -const CHAR = 57451 -const VARCHAR = 57452 -const BOOL = 57453 -const NCHAR = 57454 -const TEXT = 57455 -const TINYTEXT = 57456 -const MEDIUMTEXT = 57457 -const LONGTEXT = 57458 -const BLOB = 57459 -const TINYBLOB = 57460 -const MEDIUMBLOB = 57461 -const LONGBLOB = 57462 -const AUTO_INCREMENT = 57463 -const SIGNED = 57464 -const UNSIGNED = 57465 -const ZEROFILL = 57466 -const TABLES = 57467 -const CURRENT_TIMESTAMP = 57468 -const CURRENT_DATE = 57469 -const CURRENT_TIME = 57470 -const REPLACE = 57471 -const CAST = 57472 -const SUBSTR = 57473 -const GROUP_CONCAT = 57474 -const SEPARATOR = 57475 -const UNUSED = 57476 +const FULL = 57393 +const COLUMNS = 57394 +const OR = 57395 +const AND = 57396 +const NOT = 57397 +const BETWEEN = 57398 +const CASE = 57399 +const WHEN = 57400 +const THEN = 57401 +const ELSE = 57402 +const END = 57403 +const LE = 57404 +const GE = 57405 +const NE = 57406 +const IS = 57407 +const LIKE = 57408 +const REGEXP = 57409 +const IN = 57410 +const NULL_SAFE_NOTEQUAL = 57411 +const SHIFT_LEFT = 57412 +const SHIFT_RIGHT = 57413 +const DIV = 57414 +const MOD = 57415 +const UNARY = 57416 +const INTERVAL = 57417 +const CREATE = 57418 +const ALTER = 57419 +const DROP = 57420 +const RENAME = 57421 +const ADD = 57422 +const TABLE = 57423 +const INDEX = 57424 +const TO = 57425 +const IGNORE = 57426 +const IF = 57427 +const UNIQUE = 57428 +const PRIMARY = 57429 +const COLUMN = 57430 +const CONSTRAINT = 57431 +const FOREIGN = 57432 +const SHOW = 57433 +const DESCRIBE = 57434 +const DATE = 57435 +const ESCAPE = 57436 +const TINYINT = 57437 +const SMALLINT = 57438 +const MEDIUMINT = 57439 +const INT = 57440 +const INTEGER = 57441 +const BIGINT = 57442 +const INTNUM = 57443 +const REAL = 57444 +const DOUBLE = 57445 +const FLOAT_TYPE = 57446 +const DECIMAL = 57447 +const NUMERIC = 57448 +const TIME = 57449 +const TIMESTAMP = 57450 +const DATETIME = 57451 +const YEAR = 57452 +const CHAR = 57453 +const VARCHAR = 57454 +const BOOL = 57455 +const NCHAR = 57456 +const TEXT = 57457 +const TINYTEXT = 57458 +const MEDIUMTEXT = 57459 +const LONGTEXT = 57460 +const BLOB = 57461 +const TINYBLOB = 57462 +const MEDIUMBLOB = 57463 +const LONGBLOB = 57464 +const AUTO_INCREMENT = 57465 +const SIGNED = 57466 +const UNSIGNED = 57467 +const ZEROFILL = 57468 +const TABLES = 57469 +const CURRENT_TIMESTAMP = 57470 +const CURRENT_DATE = 57471 +const CURRENT_TIME = 57472 +const REPLACE = 57473 +const CAST = 57474 +const SUBSTR = 57475 +const GROUP_CONCAT = 57476 +const SEPARATOR = 57477 +const UNUSED = 57478 var yyToknames = [...]string{ "$end", @@ -274,6 +276,8 @@ var yyToknames = [...]string{ "NULL", "TRUE", "FALSE", + "FULL", + "COLUMNS", "OR", "AND", "NOT", @@ -388,400 +392,391 @@ var yyExca = [...]int{ -1, 3, 5, 17, -2, 4, - -1, 113, - 1, 153, - 5, 153, - 11, 153, - 12, 153, - 13, 153, - 14, 153, - 16, 153, - 27, 153, - 30, 153, - 31, 153, - 33, 153, - 35, 153, - 36, 153, - 37, 153, - 38, 153, - 40, 153, - 41, 153, - 152, 153, - -2, 166, - -1, 180, - 90, 353, - -2, 349, - -1, 181, - 90, 354, - -2, 350, - -1, 398, - 5, 17, - -2, 322, - -1, 514, - 90, 356, + -1, 114, + 1, 156, + 5, 156, + 11, 156, + 12, 156, + 13, 156, + 14, 156, + 16, 156, + 27, 156, + 30, 156, + 31, 156, + 33, 156, + 35, 156, + 36, 156, + 37, 156, + 38, 156, + 40, 156, + 41, 156, + 154, 156, + -2, 169, + -1, 183, + 92, 356, -2, 352, - -1, 546, - 5, 18, - -2, 225, - -1, 604, - 5, 18, - -2, 323, - -1, 669, + -1, 184, + 92, 357, + -2, 353, + -1, 402, 5, 17, -2, 325, - -1, 726, + -1, 519, + 92, 359, + -2, 355, + -1, 551, + 5, 18, + -2, 228, + -1, 609, 5, 18, -2, 326, + -1, 672, + 5, 17, + -2, 328, + -1, 732, + 5, 18, + -2, 329, } const yyPrivate = 57344 -const yyLast = 3998 +const yyLast = 4079 var yyAct = [...]int{ - 181, 377, 618, 133, 529, 425, 455, 509, 333, 530, - 139, 98, 31, 582, 426, 424, 484, 402, 521, 46, - 165, 469, 203, 93, 93, 118, 331, 541, 436, 204, - 3, 421, 513, 460, 167, 430, 131, 183, 93, 44, - 144, 207, 194, 451, 401, 30, 110, 709, 135, 561, - 443, 511, 109, 622, 699, 96, 623, 624, 625, 697, - 108, 681, 461, 626, 24, 26, 15, 16, 462, 125, - 86, 122, 106, 461, 438, 88, 87, 255, 635, 84, - 85, 22, 120, 127, 93, 250, 249, 713, 83, 93, - 638, 555, 607, 589, 539, 473, 376, 28, 350, 351, - 352, 353, 354, 355, 356, 349, 93, 130, 136, 184, - 349, 335, 124, 337, 185, 93, 93, 93, 538, 168, - 25, 89, 93, 664, 522, 93, 337, 93, 93, 491, - 522, 93, 596, 186, 146, 440, 248, 682, 680, 438, - 441, 97, 489, 490, 488, 25, 437, 340, 339, 18, - 19, 20, 115, 103, 559, 627, 119, 114, 370, 371, - 372, 373, 374, 256, 21, 23, 258, 684, 477, 479, - 480, 338, 113, 478, 28, 90, 94, 378, 575, 576, - 577, 384, 444, 330, 487, 336, 335, 336, 335, 93, - 394, 190, 683, 93, 93, 93, 93, 393, 126, 564, - 563, 337, 93, 337, 27, 562, 93, 417, 418, 93, - 725, 437, 404, 46, 620, 435, 434, 398, 714, 715, - 591, 677, 676, 25, 352, 353, 354, 355, 356, 349, - 391, 392, 403, 429, 205, 419, 123, 336, 335, 431, - 407, 129, 409, 415, 666, 406, 119, 408, 556, 113, - 420, 507, 457, 337, 336, 335, 93, 246, 189, 134, - 367, 369, 336, 335, 466, 134, 631, 630, 720, 211, - 337, 606, 134, 719, 247, 628, 368, 251, 337, 253, - 254, 515, 134, 24, 463, 375, 453, 454, 379, 380, - 381, 382, 32, 385, 192, 134, 467, 386, 387, 388, - 24, 213, 212, 196, 199, 668, 197, 399, 198, 200, - 542, 543, 114, 114, 114, 114, 28, 422, 466, 191, - 515, 396, 397, 602, 192, 205, 466, 113, 113, 113, - 113, 629, 192, 28, 46, 537, 592, 24, 466, 549, - 113, 400, 389, 28, 474, 475, 537, 481, 482, 445, - 456, 613, 483, 552, 471, 492, 493, 494, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 28, 542, 543, 196, 199, 46, 197, 485, 198, 200, - 452, 516, 458, 40, 12, 545, 412, 411, 378, 517, - 413, 512, 414, 199, 410, 508, 558, 429, 184, 718, - 46, 717, 404, 446, 447, 553, 404, 459, 464, 419, - 252, 202, 514, 132, 448, 449, 450, 404, 102, 519, - 535, 104, 518, 546, 99, 46, 523, 527, 688, 533, - 550, 548, 531, 536, 547, 100, 544, 403, 524, 525, - 526, 528, 32, 687, 35, 429, 348, 347, 357, 358, - 350, 351, 352, 353, 354, 355, 356, 349, 637, 93, - 37, 38, 422, 93, 554, 128, 116, 34, 93, 95, - 36, 46, 29, 1, 617, 433, 423, 486, 117, 39, - 583, 432, 679, 621, 404, 439, 566, 560, 512, 25, - 571, 471, 572, 570, 429, 442, 557, 569, 216, 379, - 579, 580, 581, 217, 568, 578, 574, 215, 219, 514, - 218, 585, 214, 586, 646, 632, 201, 532, 206, 25, - 468, 41, 121, 485, 590, 366, 105, 598, 599, 600, - 601, 597, 674, 534, 390, 182, 603, 604, 605, 595, - 686, 378, 636, 594, 383, 520, 145, 610, 476, 608, - 46, 612, 46, 46, 611, 609, 155, 616, 404, 614, - 429, 152, 587, 154, 153, 615, 46, 142, 395, 341, - 429, 593, 429, 619, 143, 514, 137, 112, 403, 187, - 634, 195, 193, 540, 111, 465, 429, 114, 708, 14, - 46, 643, 33, 639, 641, 642, 644, 107, 11, 10, - 17, 9, 113, 662, 645, 665, 663, 46, 46, 8, - 429, 565, 667, 7, 46, 567, 46, 6, 5, 4, - 673, 550, 166, 486, 101, 13, 2, 671, 672, 0, - 0, 0, 588, 0, 675, 669, 429, 531, 0, 46, - 0, 0, 0, 0, 0, 91, 91, 0, 691, 0, - 692, 690, 0, 645, 0, 0, 404, 695, 0, 429, - 91, 0, 0, 0, 0, 0, 706, 0, 0, 0, - 0, 0, 0, 711, 0, 710, 685, 0, 46, 0, - 716, 0, 0, 0, 0, 633, 0, 0, 0, 0, - 722, 0, 0, 0, 0, 0, 721, 378, 619, 0, - 712, 0, 0, 531, 0, 0, 91, 0, 0, 0, - 0, 91, 724, 0, 46, 46, 726, 0, 723, 0, - 0, 0, 532, 0, 0, 670, 0, 729, 91, 0, - 0, 0, 0, 0, 727, 728, 0, 91, 209, 91, - 0, 0, 0, 0, 91, 0, 0, 91, 0, 91, - 91, 0, 0, 257, 334, 230, 0, 235, 236, 237, - 238, 239, 240, 0, 241, 242, 243, 244, 245, 231, - 232, 233, 234, 220, 221, 0, 0, 222, 223, 224, - 225, 226, 227, 228, 229, 0, 0, 0, 532, 0, - 25, 347, 357, 358, 350, 351, 352, 353, 354, 355, - 356, 349, 678, 0, 0, 0, 0, 0, 0, 0, - 0, 91, 0, 0, 405, 91, 91, 91, 91, 0, - 0, 0, 0, 0, 416, 0, 0, 0, 91, 0, - 693, 209, 694, 0, 696, 0, 698, 0, 700, 701, - 702, 703, 704, 705, 323, 314, 293, 325, 274, 285, - 329, 286, 287, 308, 265, 301, 67, 0, 277, 261, - 283, 262, 275, 295, 298, 273, 316, 327, 59, 297, - 299, 313, 292, 309, 268, 303, 306, 326, 91, 0, - 0, 45, 0, 427, 428, 0, 0, 0, 0, 0, - 305, 322, 284, 307, 260, 304, 0, 264, 266, 328, - 320, 280, 281, 551, 0, 0, 0, 0, 0, 296, - 300, 310, 290, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 278, 0, 302, 0, 0, 0, 294, 0, - 267, 0, 279, 311, 259, 318, 291, 321, 289, 288, - 324, 68, 0, 0, 56, 317, 276, 51, 282, 76, - 71, 63, 57, 58, 47, 0, 69, 54, 55, 53, - 66, 73, 74, 52, 81, 50, 80, 49, 65, 72, - 77, 64, 61, 48, 75, 62, 60, 263, 70, 78, - 82, 319, 271, 269, 270, 312, 0, 272, 0, 315, - 79, 0, 0, 0, 0, 0, 0, 0, 334, 257, - 0, 0, 0, 0, 405, 0, 67, 0, 405, 334, - 334, 334, 0, 0, 0, 0, 0, 0, 59, 405, - 0, 0, 0, 0, 343, 0, 346, 0, 0, 0, - 0, 45, 359, 360, 361, 362, 363, 364, 0, 344, - 345, 342, 365, 348, 347, 357, 358, 350, 351, 352, - 353, 354, 355, 356, 349, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 348, 347, 357, 358, 350, 351, - 352, 353, 354, 355, 356, 349, 0, 0, 0, 0, - 0, 91, 0, 0, 0, 91, 405, 0, 0, 334, - 91, 68, 0, 0, 56, 0, 257, 51, 0, 76, + 184, 381, 623, 136, 534, 429, 459, 514, 337, 535, + 142, 99, 31, 587, 428, 434, 207, 3, 406, 46, + 168, 526, 518, 94, 94, 489, 474, 147, 170, 440, + 405, 206, 119, 464, 546, 430, 335, 455, 94, 44, + 425, 210, 97, 186, 197, 134, 30, 111, 715, 138, + 132, 516, 566, 116, 110, 447, 627, 628, 629, 630, + 705, 122, 703, 466, 631, 684, 465, 123, 465, 109, + 126, 107, 638, 442, 84, 85, 91, 95, 121, 258, + 253, 252, 719, 128, 94, 83, 641, 353, 90, 94, + 560, 352, 351, 361, 362, 354, 355, 356, 357, 358, + 359, 360, 353, 612, 594, 125, 667, 94, 544, 139, + 187, 478, 380, 133, 341, 188, 94, 94, 94, 171, + 25, 189, 543, 94, 527, 588, 94, 86, 94, 94, + 340, 339, 88, 87, 94, 251, 339, 124, 527, 131, + 601, 444, 130, 685, 683, 25, 341, 441, 445, 262, + 344, 341, 448, 104, 496, 442, 260, 115, 632, 98, + 192, 374, 375, 376, 377, 378, 564, 494, 495, 493, + 193, 214, 120, 580, 581, 582, 250, 687, 686, 254, + 382, 256, 257, 249, 388, 569, 334, 24, 26, 15, + 16, 127, 94, 398, 568, 596, 94, 94, 94, 94, + 397, 340, 339, 28, 22, 94, 567, 402, 669, 94, + 421, 422, 94, 492, 731, 408, 46, 341, 720, 721, + 28, 625, 407, 137, 25, 423, 726, 395, 396, 441, + 120, 340, 339, 439, 438, 208, 433, 356, 357, 358, + 359, 360, 353, 561, 411, 404, 413, 341, 419, 435, + 410, 512, 412, 424, 462, 461, 680, 679, 725, 94, + 94, 340, 339, 371, 373, 354, 355, 356, 357, 358, + 359, 360, 353, 633, 18, 19, 20, 341, 471, 137, + 343, 636, 635, 457, 458, 611, 137, 467, 379, 21, + 23, 383, 384, 385, 386, 520, 389, 482, 484, 485, + 390, 391, 392, 342, 483, 520, 137, 195, 137, 607, + 403, 195, 468, 469, 32, 115, 115, 115, 115, 340, + 339, 216, 215, 472, 24, 426, 634, 542, 208, 27, + 597, 471, 554, 393, 194, 341, 199, 202, 46, 200, + 471, 201, 203, 547, 548, 400, 401, 195, 479, 480, + 24, 486, 487, 471, 542, 28, 488, 28, 476, 497, + 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, + 508, 509, 510, 511, 449, 490, 450, 451, 460, 46, + 618, 24, 557, 28, 664, 521, 456, 452, 453, 454, + 547, 548, 382, 522, 40, 570, 519, 418, 202, 513, + 423, 433, 187, 671, 46, 12, 408, 416, 550, 415, + 408, 417, 414, 523, 28, 563, 517, 528, 724, 723, + 538, 408, 558, 463, 540, 255, 205, 551, 407, 46, + 536, 533, 524, 135, 555, 553, 105, 532, 552, 103, + 100, 694, 529, 530, 531, 101, 541, 549, 32, 433, + 651, 693, 660, 661, 662, 659, 426, 663, 640, 259, + 129, 117, 653, 34, 656, 658, 652, 94, 650, 559, + 36, 654, 29, 94, 199, 202, 46, 200, 1, 201, + 203, 655, 657, 89, 622, 437, 427, 118, 408, 39, + 149, 436, 682, 25, 519, 573, 476, 571, 626, 433, + 443, 579, 577, 383, 576, 584, 585, 586, 575, 565, + 446, 574, 562, 219, 517, 220, 590, 218, 591, 583, + 572, 537, 490, 25, 222, 221, 217, 649, 114, 595, + 688, 204, 603, 604, 605, 606, 602, 209, 473, 41, + 370, 608, 609, 610, 106, 677, 382, 600, 539, 394, + 185, 692, 615, 639, 613, 46, 617, 46, 46, 599, + 519, 614, 621, 408, 619, 433, 387, 592, 525, 620, + 407, 94, 148, 481, 158, 433, 598, 433, 624, 155, + 616, 351, 361, 362, 354, 355, 356, 357, 358, 359, + 360, 353, 115, 157, 156, 46, 646, 145, 642, 644, + 645, 647, 399, 345, 146, 140, 114, 113, 665, 190, + 668, 666, 46, 46, 198, 433, 196, 670, 545, 46, + 112, 46, 470, 714, 637, 676, 555, 672, 14, 33, + 648, 108, 674, 675, 11, 372, 536, 593, 46, 678, + 35, 433, 46, 10, 17, 9, 8, 169, 7, 6, + 5, 697, 4, 698, 696, 102, 37, 38, 433, 408, + 701, 13, 433, 2, 0, 96, 691, 713, 137, 712, + 92, 92, 0, 690, 0, 0, 717, 648, 716, 0, + 0, 46, 0, 722, 0, 92, 114, 114, 114, 114, + 718, 0, 0, 0, 0, 0, 728, 0, 0, 114, + 536, 624, 727, 382, 352, 351, 361, 362, 354, 355, + 356, 357, 358, 359, 360, 353, 0, 0, 730, 0, + 46, 46, 732, 0, 729, 0, 0, 537, 0, 0, + 673, 92, 0, 735, 0, 0, 92, 0, 0, 0, + 733, 734, 352, 351, 361, 362, 354, 355, 356, 357, + 358, 359, 360, 353, 92, 0, 0, 689, 0, 0, + 0, 0, 0, 92, 212, 92, 0, 0, 0, 0, + 92, 0, 0, 92, 0, 92, 92, 681, 0, 0, + 0, 261, 338, 137, 0, 0, 0, 0, 0, 0, + 0, 537, 0, 25, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 699, 0, 700, 0, 702, 0, 704, + 0, 706, 707, 708, 709, 710, 711, 0, 0, 352, + 351, 361, 362, 354, 355, 356, 357, 358, 359, 360, + 353, 0, 0, 0, 0, 0, 0, 491, 0, 92, + 643, 0, 409, 92, 92, 92, 92, 0, 0, 0, + 0, 0, 420, 0, 0, 0, 92, 0, 0, 212, + 352, 351, 361, 362, 354, 355, 356, 357, 358, 359, + 360, 353, 361, 362, 354, 355, 356, 357, 358, 359, + 360, 353, 0, 67, 0, 515, 0, 144, 0, 0, + 0, 0, 143, 0, 176, 59, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 28, 92, 92, 183, 160, + 159, 161, 162, 163, 164, 589, 0, 165, 166, 167, + 0, 0, 0, 0, 141, 153, 0, 175, 0, 0, + 0, 0, 0, 0, 0, 352, 351, 361, 362, 354, + 355, 356, 357, 358, 359, 360, 353, 150, 151, 336, + 0, 0, 0, 181, 0, 152, 0, 154, 0, 0, + 0, 0, 0, 114, 0, 0, 0, 0, 180, 0, + 68, 0, 0, 56, 0, 0, 51, 0, 76, 71, + 63, 57, 58, 47, 491, 69, 54, 55, 53, 66, + 73, 74, 52, 81, 50, 80, 49, 65, 72, 77, + 64, 61, 48, 75, 62, 60, 0, 70, 78, 82, + 0, 177, 178, 179, 182, 172, 173, 174, 0, 79, + 0, 0, 0, 0, 0, 0, 0, 338, 261, 0, + 0, 0, 0, 409, 67, 0, 0, 409, 338, 338, + 338, 0, 0, 0, 0, 0, 59, 0, 409, 0, + 0, 233, 0, 238, 239, 240, 241, 242, 243, 45, + 244, 245, 246, 247, 248, 234, 235, 236, 237, 223, + 224, 0, 0, 225, 226, 227, 228, 229, 230, 231, + 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 352, 351, 361, 362, 354, 355, + 356, 357, 358, 359, 360, 353, 0, 0, 0, 0, + 0, 0, 0, 0, 92, 409, 0, 0, 0, 338, + 92, 68, 0, 0, 56, 0, 261, 51, 0, 76, 71, 63, 57, 58, 47, 0, 69, 54, 55, 53, 66, 73, 74, 52, 81, 50, 80, 49, 65, 72, - 77, 64, 61, 48, 75, 62, 60, 640, 70, 78, - 82, 0, 0, 334, 0, 0, 0, 0, 0, 0, - 79, 0, 334, 0, 0, 0, 0, 348, 347, 357, - 358, 350, 351, 352, 353, 354, 355, 356, 349, 0, - 405, 0, 257, 357, 358, 350, 351, 352, 353, 354, - 355, 356, 349, 323, 314, 293, 325, 274, 285, 329, - 286, 287, 308, 265, 301, 67, 0, 277, 261, 283, - 262, 275, 295, 298, 273, 316, 327, 59, 297, 299, - 313, 292, 309, 268, 303, 306, 326, 0, 0, 0, - 45, 334, 427, 428, 0, 0, 0, 0, 0, 305, - 322, 284, 307, 260, 304, 0, 264, 266, 328, 320, - 280, 281, 0, 0, 0, 0, 0, 0, 296, 300, - 310, 290, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 278, 0, 302, 0, 0, 0, 294, 405, 267, - 0, 279, 311, 259, 318, 291, 321, 289, 288, 324, - 68, 0, 0, 56, 317, 276, 51, 282, 76, 71, - 63, 57, 58, 47, 0, 69, 54, 55, 53, 66, - 73, 74, 52, 81, 50, 80, 49, 65, 72, 77, - 64, 61, 48, 75, 62, 60, 263, 70, 78, 82, - 319, 271, 269, 270, 312, 0, 272, 0, 315, 79, - 323, 314, 293, 325, 274, 285, 329, 286, 287, 308, - 265, 301, 67, 0, 277, 261, 283, 262, 275, 295, - 298, 273, 316, 327, 59, 297, 299, 313, 292, 309, - 268, 303, 306, 326, 0, 0, 0, 45, 0, 0, - 0, 0, 0, 0, 0, 0, 305, 322, 284, 307, - 260, 304, 0, 264, 266, 328, 320, 280, 281, 0, - 0, 0, 0, 0, 0, 296, 300, 310, 290, 0, - 0, 0, 0, 0, 0, 0, 689, 0, 278, 0, - 302, 0, 0, 0, 294, 0, 267, 0, 279, 311, - 259, 318, 291, 321, 289, 288, 324, 68, 0, 0, - 56, 317, 276, 51, 282, 76, 71, 63, 57, 58, - 47, 0, 69, 54, 55, 53, 66, 73, 74, 52, - 81, 50, 80, 49, 65, 72, 77, 64, 61, 48, - 75, 62, 60, 263, 70, 78, 82, 319, 271, 269, - 270, 312, 0, 272, 0, 315, 79, 323, 314, 293, - 325, 274, 285, 329, 286, 287, 308, 265, 301, 67, - 0, 277, 261, 283, 262, 275, 295, 298, 273, 316, - 327, 59, 297, 299, 313, 292, 309, 268, 303, 306, - 326, 28, 0, 0, 45, 0, 0, 0, 0, 0, - 0, 0, 0, 305, 322, 284, 307, 260, 304, 0, - 264, 266, 328, 320, 280, 281, 0, 0, 0, 0, - 0, 0, 296, 300, 310, 290, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 278, 0, 302, 0, 0, - 0, 294, 0, 267, 0, 279, 311, 259, 318, 291, - 321, 289, 288, 324, 68, 0, 0, 56, 317, 276, - 51, 282, 76, 71, 63, 57, 58, 47, 0, 69, + 77, 64, 61, 48, 75, 62, 60, 0, 70, 78, + 82, 0, 0, 338, 0, 0, 0, 0, 0, 0, + 79, 0, 338, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 409, 0, 261, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 327, 318, 297, 329, 278, + 289, 333, 290, 291, 312, 269, 305, 67, 92, 281, + 265, 287, 266, 279, 299, 302, 277, 320, 331, 59, + 301, 303, 317, 296, 313, 272, 307, 310, 330, 0, + 0, 338, 45, 0, 431, 432, 0, 0, 0, 0, + 0, 309, 326, 288, 0, 0, 311, 264, 308, 0, + 268, 270, 332, 324, 284, 285, 556, 0, 0, 0, + 0, 0, 300, 304, 314, 294, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 282, 409, 306, 0, 0, + 0, 298, 0, 271, 0, 283, 315, 263, 322, 295, + 325, 293, 292, 328, 68, 0, 0, 56, 321, 280, + 51, 286, 76, 71, 63, 57, 58, 47, 0, 69, 54, 55, 53, 66, 73, 74, 52, 81, 50, 80, 49, 65, 72, 77, 64, 61, 48, 75, 62, 60, - 263, 70, 78, 82, 319, 271, 269, 270, 312, 0, - 272, 0, 315, 79, 323, 314, 293, 325, 274, 285, - 329, 286, 287, 308, 265, 301, 67, 0, 277, 261, - 283, 262, 275, 295, 298, 273, 316, 327, 59, 297, - 299, 313, 292, 309, 268, 303, 306, 326, 0, 0, - 0, 180, 0, 0, 0, 0, 0, 0, 0, 0, - 305, 322, 284, 307, 260, 304, 0, 264, 266, 328, - 320, 280, 281, 0, 0, 0, 0, 0, 0, 296, - 300, 310, 290, 0, 0, 0, 0, 0, 0, 0, - 573, 0, 278, 0, 302, 0, 0, 0, 294, 0, - 267, 0, 279, 311, 259, 318, 291, 321, 289, 288, - 324, 68, 0, 0, 56, 317, 276, 51, 282, 76, - 71, 63, 57, 58, 47, 0, 69, 54, 55, 53, - 66, 73, 74, 52, 81, 50, 80, 49, 65, 72, - 77, 64, 61, 48, 75, 62, 60, 263, 70, 78, - 82, 319, 271, 269, 270, 312, 0, 272, 0, 315, - 79, 323, 314, 293, 325, 274, 285, 329, 286, 287, - 308, 265, 301, 67, 0, 277, 261, 283, 262, 275, - 295, 298, 273, 316, 327, 59, 297, 299, 313, 292, - 309, 268, 303, 306, 326, 0, 0, 0, 45, 0, - 0, 0, 0, 0, 0, 0, 0, 305, 322, 284, - 307, 260, 304, 0, 264, 266, 328, 320, 280, 281, - 0, 0, 0, 0, 0, 0, 296, 300, 310, 290, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 278, - 0, 302, 0, 0, 0, 294, 0, 267, 0, 279, - 311, 259, 318, 291, 321, 289, 288, 324, 68, 0, - 0, 56, 317, 276, 51, 282, 76, 71, 63, 57, - 58, 47, 0, 69, 54, 55, 53, 66, 73, 74, - 52, 81, 50, 80, 49, 65, 72, 77, 64, 61, - 48, 75, 62, 60, 263, 70, 78, 82, 319, 271, - 269, 270, 312, 0, 272, 0, 315, 79, 323, 314, - 293, 325, 274, 285, 329, 286, 287, 308, 265, 301, - 67, 0, 277, 261, 283, 262, 275, 295, 298, 273, - 316, 327, 59, 297, 299, 313, 292, 309, 268, 303, - 306, 326, 0, 0, 0, 180, 0, 0, 0, 0, - 0, 0, 0, 0, 305, 322, 284, 307, 260, 304, - 0, 264, 266, 328, 320, 280, 281, 0, 0, 0, - 0, 0, 0, 296, 300, 310, 290, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 278, 0, 302, 0, - 0, 0, 294, 0, 267, 0, 279, 311, 259, 318, - 291, 321, 289, 288, 324, 68, 0, 0, 56, 317, - 276, 51, 282, 76, 71, 63, 57, 58, 47, 0, - 69, 54, 55, 53, 66, 73, 74, 52, 81, 50, - 80, 49, 65, 72, 77, 64, 61, 48, 75, 62, - 60, 263, 70, 78, 82, 319, 271, 269, 270, 312, - 0, 272, 0, 315, 79, 323, 314, 293, 325, 274, - 285, 329, 286, 287, 308, 265, 301, 67, 0, 277, - 261, 283, 262, 275, 295, 298, 273, 316, 327, 59, - 297, 299, 313, 292, 309, 268, 303, 306, 326, 0, - 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, - 0, 305, 322, 284, 307, 260, 304, 0, 264, 266, - 328, 320, 280, 281, 0, 0, 0, 0, 0, 0, - 296, 300, 310, 290, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 278, 0, 302, 0, 0, 0, 294, - 0, 267, 0, 279, 311, 259, 318, 291, 321, 289, - 288, 324, 68, 0, 0, 56, 317, 276, 51, 282, + 267, 70, 78, 82, 323, 275, 273, 274, 316, 0, + 276, 0, 319, 79, 327, 318, 297, 329, 278, 289, + 333, 290, 291, 312, 269, 305, 67, 0, 281, 265, + 287, 266, 279, 299, 302, 277, 320, 331, 59, 301, + 303, 317, 296, 313, 272, 307, 310, 330, 0, 0, + 0, 45, 0, 431, 432, 0, 0, 0, 0, 0, + 309, 326, 288, 0, 0, 311, 264, 308, 0, 268, + 270, 332, 324, 284, 285, 0, 0, 0, 0, 0, + 0, 300, 304, 314, 294, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 282, 0, 306, 0, 0, 0, + 298, 0, 271, 0, 283, 315, 263, 322, 295, 325, + 293, 292, 328, 68, 0, 0, 56, 321, 280, 51, + 286, 76, 71, 63, 57, 58, 47, 0, 69, 54, + 55, 53, 66, 73, 74, 52, 81, 50, 80, 49, + 65, 72, 77, 64, 61, 48, 75, 62, 60, 267, + 70, 78, 82, 323, 275, 273, 274, 316, 0, 276, + 0, 319, 79, 327, 318, 297, 329, 278, 289, 333, + 290, 291, 312, 269, 305, 67, 0, 281, 265, 287, + 266, 279, 299, 302, 277, 320, 331, 59, 301, 303, + 317, 296, 313, 272, 307, 310, 330, 0, 0, 0, + 45, 0, 0, 0, 0, 0, 0, 0, 0, 309, + 326, 288, 0, 0, 311, 264, 308, 0, 268, 270, + 332, 324, 284, 285, 0, 0, 0, 0, 0, 0, + 300, 304, 314, 294, 0, 0, 0, 0, 0, 0, + 0, 695, 0, 282, 0, 306, 0, 0, 0, 298, + 0, 271, 0, 283, 315, 263, 322, 295, 325, 293, + 292, 328, 68, 0, 0, 56, 321, 280, 51, 286, 76, 71, 63, 57, 58, 47, 0, 69, 54, 55, 53, 66, 73, 74, 52, 81, 50, 80, 49, 65, - 72, 77, 64, 61, 48, 75, 62, 60, 263, 70, - 78, 82, 319, 271, 269, 270, 312, 0, 272, 0, - 315, 79, 67, 0, 510, 0, 141, 0, 0, 0, - 0, 140, 0, 173, 59, 707, 134, 0, 0, 0, - 0, 0, 0, 0, 28, 0, 0, 180, 157, 156, - 158, 159, 160, 161, 0, 0, 162, 163, 164, 0, - 0, 138, 150, 0, 172, 0, 0, 0, 0, 0, - 348, 347, 357, 358, 350, 351, 352, 353, 354, 355, - 356, 349, 0, 0, 147, 148, 332, 0, 0, 0, - 178, 0, 149, 0, 151, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 177, 0, 68, 0, 0, - 56, 0, 0, 51, 0, 76, 71, 63, 57, 58, - 47, 0, 69, 54, 55, 53, 66, 73, 74, 52, - 81, 50, 80, 49, 65, 72, 77, 64, 61, 48, - 75, 62, 60, 0, 70, 78, 82, 0, 174, 175, - 176, 179, 169, 170, 171, 67, 79, 0, 0, 141, - 0, 0, 0, 0, 140, 134, 173, 59, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, - 180, 157, 156, 158, 159, 160, 161, 0, 0, 162, - 163, 164, 0, 0, 138, 150, 0, 172, 0, 348, - 347, 357, 358, 350, 351, 352, 353, 354, 355, 356, - 349, 0, 0, 0, 0, 0, 0, 147, 148, 332, - 0, 0, 0, 178, 0, 149, 0, 151, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 177, 0, - 68, 0, 0, 56, 0, 0, 51, 0, 76, 71, + 72, 77, 64, 61, 48, 75, 62, 60, 267, 70, + 78, 82, 323, 275, 273, 274, 316, 0, 276, 0, + 319, 79, 327, 318, 297, 329, 278, 289, 333, 290, + 291, 312, 269, 305, 67, 0, 281, 265, 287, 266, + 279, 299, 302, 277, 320, 331, 59, 301, 303, 317, + 296, 313, 272, 307, 310, 330, 28, 0, 0, 45, + 0, 0, 0, 0, 0, 0, 0, 0, 309, 326, + 288, 0, 0, 311, 264, 308, 0, 268, 270, 332, + 324, 284, 285, 0, 0, 0, 0, 0, 0, 300, + 304, 314, 294, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 282, 0, 306, 0, 0, 0, 298, 0, + 271, 0, 283, 315, 263, 322, 295, 325, 293, 292, + 328, 68, 0, 0, 56, 321, 280, 51, 286, 76, + 71, 63, 57, 58, 47, 0, 69, 54, 55, 53, + 66, 73, 74, 52, 81, 50, 80, 49, 65, 72, + 77, 64, 61, 48, 75, 62, 60, 267, 70, 78, + 82, 323, 275, 273, 274, 316, 0, 276, 0, 319, + 79, 327, 318, 297, 329, 278, 289, 333, 290, 291, + 312, 269, 305, 67, 0, 281, 265, 287, 266, 279, + 299, 302, 277, 320, 331, 59, 301, 303, 317, 296, + 313, 272, 307, 310, 330, 0, 0, 0, 183, 0, + 0, 0, 0, 0, 0, 0, 0, 309, 326, 288, + 0, 0, 311, 264, 308, 0, 268, 270, 332, 324, + 284, 285, 0, 0, 0, 0, 0, 0, 300, 304, + 314, 294, 0, 0, 0, 0, 0, 0, 0, 578, + 0, 282, 0, 306, 0, 0, 0, 298, 0, 271, + 0, 283, 315, 263, 322, 295, 325, 293, 292, 328, + 68, 0, 0, 56, 321, 280, 51, 286, 76, 71, 63, 57, 58, 47, 0, 69, 54, 55, 53, 66, 73, 74, 52, 81, 50, 80, 49, 65, 72, 77, - 64, 61, 48, 75, 62, 60, 0, 70, 78, 82, - 0, 174, 175, 176, 179, 169, 170, 171, 67, 79, - 0, 0, 141, 0, 0, 0, 0, 140, 0, 173, - 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 28, 584, 134, 180, 157, 156, 158, 159, 160, 161, - 0, 0, 162, 163, 164, 0, 0, 138, 150, 0, - 172, 348, 347, 357, 358, 350, 351, 352, 353, 354, - 355, 356, 349, 0, 0, 0, 0, 0, 0, 0, - 147, 148, 0, 0, 0, 0, 178, 0, 149, 0, - 151, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 177, 0, 68, 0, 0, 56, 0, 0, 51, - 0, 76, 71, 63, 57, 58, 47, 0, 69, 54, - 55, 53, 66, 73, 74, 52, 81, 50, 80, 49, - 65, 72, 77, 64, 61, 48, 75, 62, 60, 0, - 70, 78, 82, 24, 174, 175, 176, 179, 169, 170, - 171, 0, 79, 0, 67, 0, 0, 0, 141, 0, - 0, 0, 0, 140, 0, 173, 59, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 28, 0, 0, 180, - 157, 156, 158, 159, 160, 161, 0, 0, 162, 163, - 164, 0, 0, 138, 150, 0, 172, 348, 347, 357, - 358, 350, 351, 352, 353, 354, 355, 356, 349, 0, - 0, 0, 0, 0, 0, 0, 147, 148, 0, 0, - 0, 0, 178, 0, 149, 0, 151, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 177, 0, 68, - 0, 0, 56, 0, 0, 51, 0, 76, 71, 63, + 64, 61, 48, 75, 62, 60, 267, 70, 78, 82, + 323, 275, 273, 274, 316, 0, 276, 0, 319, 79, + 327, 318, 297, 329, 278, 289, 333, 290, 291, 312, + 269, 305, 67, 0, 281, 265, 287, 266, 279, 299, + 302, 277, 320, 331, 59, 301, 303, 317, 296, 313, + 272, 307, 310, 330, 0, 0, 0, 45, 0, 0, + 0, 0, 0, 0, 0, 0, 309, 326, 288, 0, + 0, 311, 264, 308, 0, 268, 270, 332, 324, 284, + 285, 0, 0, 0, 0, 0, 0, 300, 304, 314, + 294, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 282, 0, 306, 0, 0, 0, 298, 0, 271, 0, + 283, 315, 263, 322, 295, 325, 293, 292, 328, 68, + 0, 0, 56, 321, 280, 51, 286, 76, 71, 63, 57, 58, 47, 0, 69, 54, 55, 53, 66, 73, 74, 52, 81, 50, 80, 49, 65, 72, 77, 64, - 61, 48, 75, 62, 60, 0, 70, 78, 82, 0, - 174, 175, 176, 179, 169, 170, 171, 67, 79, 0, - 0, 141, 0, 0, 0, 0, 140, 0, 173, 59, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, - 0, 0, 180, 157, 156, 158, 159, 160, 161, 0, - 0, 162, 163, 164, 0, 0, 138, 150, 0, 172, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, - 148, 0, 0, 0, 0, 178, 0, 149, 0, 151, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 177, 0, 68, 0, 0, 56, 0, 0, 51, 0, - 76, 71, 63, 57, 58, 47, 0, 69, 54, 55, - 53, 66, 73, 74, 52, 81, 50, 80, 49, 65, - 72, 77, 64, 61, 48, 75, 62, 60, 0, 70, - 78, 82, 67, 174, 175, 176, 179, 169, 170, 171, - 0, 79, 0, 173, 59, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 28, 0, 0, 180, 157, 156, - 158, 159, 160, 161, 0, 0, 162, 163, 164, 0, - 0, 0, 150, 0, 172, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 147, 148, 0, 0, 0, 0, - 178, 0, 149, 661, 151, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 177, 0, 68, 0, 0, - 56, 0, 0, 51, 0, 76, 71, 63, 57, 58, + 61, 48, 75, 62, 60, 267, 70, 78, 82, 323, + 275, 273, 274, 316, 0, 276, 0, 319, 79, 327, + 318, 297, 329, 278, 289, 333, 290, 291, 312, 269, + 305, 67, 0, 281, 265, 287, 266, 279, 299, 302, + 277, 320, 331, 59, 301, 303, 317, 296, 313, 272, + 307, 310, 330, 0, 0, 0, 183, 0, 0, 0, + 0, 0, 0, 0, 0, 309, 326, 288, 0, 0, + 311, 264, 308, 0, 268, 270, 332, 324, 284, 285, + 0, 0, 0, 0, 0, 0, 300, 304, 314, 294, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 282, + 0, 306, 0, 0, 0, 298, 0, 271, 0, 283, + 315, 263, 322, 295, 325, 293, 292, 328, 68, 0, + 0, 56, 321, 280, 51, 286, 76, 71, 63, 57, + 58, 47, 0, 69, 54, 55, 53, 66, 73, 74, + 52, 81, 50, 80, 49, 65, 72, 77, 64, 61, + 48, 75, 62, 60, 267, 70, 78, 82, 323, 275, + 273, 274, 316, 0, 276, 0, 319, 79, 327, 318, + 297, 329, 278, 289, 333, 290, 291, 312, 269, 305, + 67, 0, 281, 265, 287, 266, 279, 299, 302, 277, + 320, 331, 59, 301, 303, 317, 296, 313, 272, 307, + 310, 330, 0, 0, 0, 93, 0, 0, 0, 0, + 0, 0, 0, 0, 309, 326, 288, 0, 0, 311, + 264, 308, 0, 268, 270, 332, 324, 284, 285, 0, + 0, 0, 0, 0, 0, 300, 304, 314, 294, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 282, 0, + 306, 0, 0, 0, 298, 0, 271, 0, 283, 315, + 263, 322, 295, 325, 293, 292, 328, 68, 0, 0, + 56, 321, 280, 51, 286, 76, 71, 63, 57, 58, 47, 0, 69, 54, 55, 53, 66, 73, 74, 52, 81, 50, 80, 49, 65, 72, 77, 64, 61, 48, - 75, 62, 60, 0, 70, 78, 82, 0, 174, 175, - 176, 179, 169, 170, 171, 67, 79, 648, 470, 657, - 658, 659, 656, 0, 660, 0, 0, 59, 0, 650, - 0, 653, 655, 649, 0, 647, 0, 0, 651, 0, - 45, 0, 472, 0, 0, 0, 24, 0, 652, 654, - 0, 0, 336, 335, 0, 0, 0, 67, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 337, 59, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, - 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, + 75, 62, 60, 267, 70, 78, 82, 323, 275, 273, + 274, 316, 0, 276, 67, 319, 79, 0, 144, 0, + 0, 0, 0, 143, 0, 176, 59, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 28, 0, 0, 183, + 160, 159, 161, 162, 163, 164, 0, 0, 165, 166, + 167, 0, 0, 0, 0, 141, 153, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 0, 0, 56, 0, 0, 51, 0, 76, 71, - 63, 57, 58, 47, 0, 69, 54, 55, 53, 66, - 73, 74, 52, 81, 50, 80, 49, 65, 72, 77, - 64, 61, 48, 75, 62, 60, 0, 70, 78, 82, - 0, 0, 68, 0, 0, 56, 0, 0, 51, 79, - 76, 71, 63, 57, 58, 47, 0, 69, 54, 55, - 53, 66, 73, 74, 52, 81, 50, 80, 49, 65, - 72, 77, 64, 61, 48, 75, 62, 60, 24, 70, - 78, 82, 0, 0, 0, 0, 0, 0, 0, 67, - 0, 79, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 59, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 28, 0, 0, 92, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 150, 151, + 336, 0, 0, 0, 181, 0, 152, 0, 154, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, + 0, 68, 0, 0, 56, 0, 0, 51, 0, 76, + 71, 63, 57, 58, 47, 0, 69, 54, 55, 53, + 66, 73, 74, 52, 81, 50, 80, 49, 65, 72, + 77, 64, 61, 48, 75, 62, 60, 0, 70, 78, + 82, 0, 177, 178, 179, 182, 172, 173, 174, 67, + 79, 0, 0, 144, 0, 0, 0, 0, 143, 0, + 176, 59, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 28, 0, 137, 183, 160, 159, 161, 162, 163, + 164, 0, 0, 165, 166, 167, 0, 0, 0, 0, + 141, 153, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 67, 0, 0, 208, 0, 0, 0, 0, 0, - 0, 0, 0, 59, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 92, 0, 210, 0, + 0, 0, 0, 150, 151, 0, 0, 0, 0, 181, + 0, 152, 0, 154, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 180, 0, 68, 0, 0, 56, + 0, 0, 51, 0, 76, 71, 63, 57, 58, 47, + 0, 69, 54, 55, 53, 66, 73, 74, 52, 81, + 50, 80, 49, 65, 72, 77, 64, 61, 48, 75, + 62, 60, 0, 70, 78, 82, 24, 177, 178, 179, + 182, 172, 173, 174, 0, 79, 0, 67, 0, 0, + 0, 144, 0, 0, 0, 0, 143, 0, 176, 59, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, + 0, 0, 183, 160, 159, 161, 162, 163, 164, 0, + 0, 165, 166, 167, 0, 0, 0, 0, 141, 153, + 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 68, 0, 0, 56, 0, 0, + 0, 150, 151, 0, 0, 0, 0, 181, 0, 152, + 0, 154, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 180, 0, 68, 0, 0, 56, 0, 0, 51, 0, 76, 71, 63, 57, 58, 47, 0, 69, 54, 55, 53, 66, 73, 74, 52, 81, 50, 80, 49, 65, 72, 77, 64, 61, 48, 75, 62, 60, - 0, 70, 78, 82, 0, 0, 68, 0, 0, 56, - 0, 0, 51, 79, 76, 71, 63, 57, 58, 47, + 0, 70, 78, 82, 0, 177, 178, 179, 182, 172, + 173, 174, 67, 79, 0, 0, 144, 0, 0, 0, + 0, 143, 0, 176, 59, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 28, 0, 0, 183, 160, 159, + 161, 162, 163, 164, 0, 0, 165, 166, 167, 0, + 0, 0, 0, 141, 153, 0, 175, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 150, 151, 0, 0, + 0, 0, 181, 0, 152, 0, 154, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 180, 0, 68, + 0, 0, 56, 0, 0, 51, 0, 76, 71, 63, + 57, 58, 47, 0, 69, 54, 55, 53, 66, 73, + 74, 52, 81, 50, 80, 49, 65, 72, 77, 64, + 61, 48, 75, 62, 60, 0, 70, 78, 82, 67, + 177, 178, 179, 182, 172, 173, 174, 0, 79, 0, + 176, 59, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 28, 0, 0, 183, 160, 159, 161, 162, 163, + 164, 0, 0, 165, 166, 167, 0, 0, 0, 0, + 0, 153, 0, 175, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 150, 151, 0, 0, 0, 0, 181, + 0, 152, 0, 154, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 180, 0, 68, 0, 0, 56, + 0, 0, 51, 0, 76, 71, 63, 57, 58, 47, 0, 69, 54, 55, 53, 66, 73, 74, 52, 81, 50, 80, 49, 65, 72, 77, 64, 61, 48, 75, - 62, 60, 67, 70, 78, 82, 0, 0, 0, 0, - 0, 0, 0, 0, 59, 79, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, + 62, 60, 0, 70, 78, 82, 0, 177, 178, 179, + 182, 172, 173, 174, 67, 79, 0, 475, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, - 0, 472, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 42, 0, 0, 0, 0, 43, 68, 0, 0, + 0, 477, 0, 0, 0, 24, 0, 0, 0, 0, + 0, 0, 0, 340, 339, 0, 67, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 59, 341, + 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, + 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 68, 0, 0, 56, 0, 0, 51, 0, 76, + 71, 63, 57, 58, 47, 0, 69, 54, 55, 53, + 66, 73, 74, 52, 81, 50, 80, 49, 65, 72, + 77, 64, 61, 48, 75, 62, 60, 0, 70, 78, + 82, 0, 0, 68, 0, 0, 56, 0, 0, 51, + 79, 76, 71, 63, 57, 58, 47, 0, 69, 54, + 55, 53, 66, 73, 74, 52, 81, 50, 80, 49, + 65, 72, 77, 64, 61, 48, 75, 62, 60, 24, + 70, 78, 82, 0, 0, 0, 0, 0, 0, 0, + 67, 0, 79, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 28, 0, 0, 93, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 67, 0, 0, 211, 0, 0, 0, 0, + 0, 0, 0, 0, 59, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 93, 0, 213, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 56, 0, 0, 51, 0, 76, 71, 63, 57, 58, 47, 0, 69, 54, 55, 53, 66, 73, 74, 52, 81, 50, 80, 49, 65, 72, 77, 64, 61, 48, @@ -791,151 +786,169 @@ var yyAct = [...]int{ 74, 52, 81, 50, 80, 49, 65, 72, 77, 64, 61, 48, 75, 62, 60, 67, 70, 78, 82, 0, 0, 0, 0, 0, 0, 0, 0, 59, 79, 0, - 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, - 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 92, 0, 210, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 0, 0, 56, 0, 0, 51, 0, 76, 71, - 63, 57, 58, 47, 0, 69, 54, 55, 53, 66, - 73, 74, 52, 81, 50, 80, 49, 65, 72, 77, - 64, 61, 48, 75, 62, 60, 0, 70, 78, 82, - 0, 0, 68, 0, 0, 56, 0, 0, 51, 79, + 0, 0, 45, 0, 477, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, + 0, 43, 68, 0, 0, 56, 0, 0, 51, 0, 76, 71, 63, 57, 58, 47, 0, 69, 54, 55, 53, 66, 73, 74, 52, 81, 50, 80, 49, 65, - 72, 77, 64, 61, 48, 75, 62, 60, 67, 70, - 78, 82, 0, 0, 0, 188, 0, 0, 0, 0, - 59, 79, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, + 72, 77, 64, 61, 48, 75, 62, 60, 0, 70, + 78, 82, 0, 0, 68, 0, 0, 56, 0, 0, + 51, 79, 76, 71, 63, 57, 58, 47, 0, 69, + 54, 55, 53, 66, 73, 74, 52, 81, 50, 80, + 49, 65, 72, 77, 64, 61, 48, 75, 62, 60, + 67, 70, 78, 82, 0, 0, 0, 0, 0, 0, + 0, 0, 59, 79, 0, 0, 0, 0, 0, 0, + 0, 0, 28, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 45, 0, 0, 0, 0, + 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 59, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 93, 0, 213, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 68, 0, 0, 56, 0, 0, 51, - 0, 76, 71, 63, 57, 58, 47, 0, 69, 54, - 55, 53, 66, 73, 74, 52, 81, 50, 80, 49, - 65, 72, 77, 64, 61, 48, 75, 62, 60, 0, - 70, 78, 82, 0, 0, 68, 0, 0, 56, 0, - 0, 51, 79, 76, 71, 63, 57, 58, 47, 0, - 69, 54, 55, 53, 66, 73, 74, 52, 81, 50, - 80, 49, 65, 72, 77, 64, 61, 48, 75, 62, - 60, 67, 70, 78, 82, 0, 0, 0, 0, 0, - 0, 0, 0, 59, 79, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 180, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, + 56, 0, 0, 51, 0, 76, 71, 63, 57, 58, + 47, 0, 69, 54, 55, 53, 66, 73, 74, 52, + 81, 50, 80, 49, 65, 72, 77, 64, 61, 48, + 75, 62, 60, 0, 70, 78, 82, 0, 0, 68, + 0, 0, 56, 0, 0, 51, 79, 76, 71, 63, + 57, 58, 47, 0, 69, 54, 55, 53, 66, 73, + 74, 52, 81, 50, 80, 49, 65, 72, 77, 64, + 61, 48, 75, 62, 60, 67, 70, 78, 82, 0, + 0, 0, 191, 0, 0, 0, 0, 59, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 59, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 92, 0, + 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 347, 59, + 350, 0, 0, 0, 0, 0, 363, 364, 365, 366, + 367, 368, 45, 348, 349, 346, 369, 352, 351, 361, + 362, 354, 355, 356, 357, 358, 359, 360, 353, 0, + 0, 0, 68, 0, 0, 56, 0, 0, 51, 0, + 76, 71, 63, 57, 58, 47, 0, 69, 54, 55, + 53, 66, 73, 74, 52, 81, 50, 80, 49, 65, + 72, 77, 64, 61, 48, 75, 62, 60, 0, 70, + 78, 82, 0, 0, 68, 0, 0, 56, 0, 0, + 51, 79, 76, 71, 63, 57, 58, 47, 0, 69, + 54, 55, 53, 66, 73, 74, 52, 81, 50, 80, + 49, 65, 72, 77, 64, 61, 48, 75, 62, 60, + 67, 70, 78, 82, 0, 0, 0, 0, 0, 0, + 0, 0, 59, 79, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 183, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 68, 0, 0, 56, - 0, 0, 51, 0, 76, 71, 63, 57, 58, 47, - 0, 69, 54, 55, 53, 66, 73, 74, 52, 81, - 50, 80, 49, 65, 72, 77, 64, 61, 48, 75, - 62, 60, 0, 70, 78, 82, 0, 0, 68, 0, - 0, 56, 0, 0, 51, 79, 76, 71, 63, 57, - 58, 47, 0, 69, 54, 55, 53, 66, 73, 74, - 52, 81, 50, 80, 49, 65, 72, 77, 64, 61, - 48, 75, 62, 60, 0, 70, 78, 82, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 79, + 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 59, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 93, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, + 56, 0, 0, 51, 0, 76, 71, 63, 57, 58, + 47, 0, 69, 54, 55, 53, 66, 73, 74, 52, + 81, 50, 80, 49, 65, 72, 77, 64, 61, 48, + 75, 62, 60, 0, 70, 78, 82, 0, 0, 68, + 0, 0, 56, 0, 0, 51, 79, 76, 71, 63, + 57, 58, 47, 0, 69, 54, 55, 53, 66, 73, + 74, 52, 81, 50, 80, 49, 65, 72, 77, 64, + 61, 48, 75, 62, 60, 0, 70, 78, 82, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 79, } var yyPact = [...]int{ - 58, -1000, -107, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 428, 462, -1000, -1000, -1000, 344, 3315, -8, - -17, -21, 3846, 3846, -1000, 331, 87, -1000, -1000, -1000, - -1000, 408, 420, 331, 403, -27, -1000, 3478, 456, -1000, - 204, -15, -29, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 181, -1000, -108, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 434, 458, -1000, -1000, -1000, 355, 3388, -13, + -24, 34, 3925, 3925, -1000, 344, 103, -1000, -1000, -1000, + -1000, 424, 430, 344, 418, -30, -1000, 3553, 451, -1000, + 188, -21, -35, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 3925, -32, -32, -15, 450, 3925, -5, + -1000, -1000, 21, -1000, -1000, -1000, 414, 182, -99, -1000, + 2785, 2785, 434, -1000, 344, -1000, 3718, -1000, 120, 307, + 444, -1000, -1000, -1000, 406, 3223, 3265, 3925, 281, -1000, + 941, -35, 3925, 77, -16, 3925, 404, 3925, 3925, -19, + -1000, -1000, 449, 2243, 2377, -1000, -1000, -1000, -1000, 263, + -1000, 2785, 3730, 316, 316, -1000, -1000, -1000, -1000, -1000, + 2912, 2912, 2912, 2912, 2912, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 316, 20, + -1000, 2650, 316, 316, 316, 2785, 316, -1000, -1000, -1000, + 316, 316, 316, -1000, -1000, 293, -1000, 205, 424, 182, + 318, 3925, -1000, -1000, 3883, 3553, 3553, 3553, 3553, -1000, + 382, 379, 377, 367, 3925, -1000, 267, 182, 3223, -1000, + -1000, 3595, -1000, -1000, 445, 1349, 130, 90, -87, -1000, + -1000, 335, -1000, 335, 335, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 335, 335, 335, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 347, 347, 347, 339, 339, 212, + -1000, 402, -39, -37, -1000, -1000, -1000, -1000, 3925, 3925, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 3846, -31, -31, -13, 455, 3846, -1000, - -1000, 17, -1000, -1000, -1000, 394, 218, -98, -1000, 2720, - 2720, 428, -1000, 331, -1000, 3641, -1000, 141, 292, 343, - -1000, -1000, -1000, 391, 3152, 3194, 3846, 261, -1000, 647, - 215, 3846, 80, -9, 3846, 389, 3846, 3846, -19, -1000, - 2050, 2318, -1000, -1000, -1000, -1000, 131, -1000, 2720, 968, - 304, 304, -1000, -1000, -1000, -1000, -1000, 2845, 2845, 2845, - 2845, 2845, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 304, 6, -1000, 2587, 304, - 304, 304, 2720, 304, -1000, -1000, -1000, 304, 304, 304, - -1000, -1000, 302, -1000, 208, 408, 218, 294, 3846, -1000, - -1000, 3804, 3478, 3478, 3478, 3478, -1000, 364, 357, 356, - 362, 3846, -1000, 254, 218, 3152, -1000, -1000, 3520, -1000, - -1000, 451, 1168, 114, 84, -90, -1000, -1000, 310, -1000, - 310, 310, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 310, 310, 310, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 341, 341, 341, 311, 311, 345, -1000, 386, -41, - -30, -1000, -1000, -1000, -1000, 3846, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 313, -1000, -1000, 3047, 19, 2785, + 2785, 246, 2785, 2785, 42, 2912, 164, 94, 2912, 2912, + 2912, 2912, 2912, 2912, 2912, 2912, 2912, 2912, 2912, 2912, + 2912, 2912, 2912, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, 209, -1000, 344, -1000, -1000, -1000, -1000, 1017, 866, + 2094, 265, 74, 2650, 2785, 3883, 414, 62, 74, 3883, + 2377, 2377, 2377, 2785, -1000, -1000, -1000, -1000, -1000, -1000, + 3883, 316, -1000, 3089, -1000, 314, -1000, 56, -1000, 16, + 444, 353, 306, -1000, -1000, -1000, -1000, 378, -1000, -1000, + -1000, -1000, -1000, 182, -1000, 434, 2785, 292, 1200, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 343, 397, 48, + 201, -1000, -1000, 389, -1000, 115, -91, -1000, -1000, 161, + -1000, -1000, -1000, -1000, -1000, -1000, 149, -1000, -1000, -1000, + 140, -1000, 358, -1000, 188, -1000, 3925, 3883, -1000, -1000, + 445, 2377, 3553, -1000, -1000, 3430, -1000, -1000, 1796, 42, + 79, -1000, -1000, 122, -1000, -1000, 74, 74, 665, -1000, + -1000, -1000, -1000, 164, 2912, 2912, 2912, 14, 665, 858, + 793, 503, -1000, 154, 154, -1, -1, -1, -1, -1, + 184, 184, 182, -1000, 182, 2377, 291, 316, 12, -1000, + 2785, -1000, 175, 290, 2377, 76, -1000, 2785, 182, 238, + 238, 238, -1000, 287, 269, -1000, -1000, 2512, 182, 245, + 11, 434, 3883, 2785, 2094, -1000, -1000, 2785, 341, -1000, + -1000, -1000, 424, 74, 1349, -1000, 1349, 3760, -1000, 179, + -1000, -1000, -84, 13, -1000, -1000, -1000, 232, 286, 241, + 3925, -1000, -1000, -28, 446, -1000, 271, -1000, -1000, -6, + -1000, -1000, -1000, -1000, 14, 665, 783, -1000, 2912, 2912, + -1000, -1000, 238, 2377, 1945, 74, 340, 2912, 300, 41, + -1000, 2785, 145, -1000, -1000, -1000, -1000, 316, -1000, -1000, + 375, 3760, 3760, 424, -1000, 74, -1000, 74, 3760, -1000, + 1200, -1000, 216, -1000, 335, -1000, 40, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 133, -1000, 132, 1647, 3883, 438, + 426, 1498, -1000, 2912, 665, 665, -1000, 182, -1000, 182, + 335, -1000, 335, 339, 335, -54, 335, -56, 335, 335, + 335, 335, 335, 335, -1000, 627, -104, -1000, 74, 2785, + -1000, 316, -1000, 344, -10, -1000, -1000, 178, -1000, -1000, + 3760, -1000, -1000, 394, -1000, 393, 217, 185, -1000, -1000, + -1000, -1000, -1000, 2785, 2785, -1000, 665, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 286, -1000, -1000, 2978, 5, 2720, 2720, 117, 2720, 2720, - 43, 2845, 135, 71, 2845, 2845, 2845, 2845, 2845, 2845, - 2845, 2845, 2845, 2845, 2845, 2845, 2845, 2845, 2845, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 209, -1000, 331, - -1000, -1000, -1000, -1000, 989, 2185, 1903, 241, 133, 2587, - 2720, 3804, 394, 64, 133, 3804, 2318, 2318, 2318, 2720, - -1000, -1000, -1000, -1000, -1000, -1000, 3804, 304, -1000, 3020, - -1000, 306, -1000, 54, -1000, 4, 343, 334, 273, -1000, - -1000, -1000, -1000, 355, -1000, -1000, -1000, -1000, -1000, 218, - -1000, 428, 2720, 299, 839, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 314, 380, 49, 206, -1000, -1000, 370, - -1000, 103, -92, -1000, -1000, 160, -1000, -1000, -1000, -1000, - -1000, -1000, 155, -1000, -1000, -1000, 154, -1000, 3846, -1000, - 204, -1000, 3846, 3804, -1000, 451, 2318, 3478, -1000, -1000, - 3357, -1000, -1000, 1609, 43, 56, -1000, -1000, 127, -1000, - -1000, 133, 133, 2572, -1000, -1000, -1000, -1000, 135, 2845, - 2845, 2845, 371, 2572, 2436, 1086, 715, -1000, 143, 143, - 24, 24, 24, 24, 24, 19, 19, 218, -1000, 218, - 2318, 298, 304, 3, -1000, 2720, -1000, 200, 296, 2318, - 70, -1000, 2720, 218, 224, 224, 224, -1000, 295, 283, - -1000, -1000, 2451, 218, 231, 2, 428, 3804, 2720, 1903, - -1000, -1000, 2720, 312, -1000, -1000, -1000, 408, 133, 1168, - -1000, 1168, 3683, -1000, 172, -1000, -1000, -85, 12, -1000, - -1000, -1000, 234, 291, 226, 1462, -1000, -1000, -20, 446, - -1000, 284, -1000, -1000, 0, -1000, -1000, -1000, -1000, 371, - 2572, 1072, -1000, 2845, 2845, -1000, -1000, 224, 2318, 1756, - 133, 2889, 2845, 278, 60, -1000, 2720, 183, -1000, -1000, - -1000, -1000, 304, -1000, -1000, 277, 3683, 3683, 408, -1000, - 133, -1000, 133, 3683, -1000, 839, -1000, 181, -1000, 310, - -1000, 36, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 147, - -1000, 122, -1000, -1000, -1000, 3804, 430, 413, 1315, -1000, - 2845, 2572, 2572, -1000, 218, -1000, 218, 310, -1000, 310, - 311, 310, -55, 310, -60, 310, 310, 310, 310, 310, - 310, -1000, 2175, -103, -1000, 133, 2720, -1000, 304, -1000, - 331, -3, -1000, -1000, 178, -1000, -1000, 3683, -1000, -1000, - 376, -1000, 374, 232, 227, -1000, -1000, 2720, 2720, -1000, - 2572, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2845, 218, 166, - 133, 283, 218, 3683, 3683, -1000, -1000, -1000, -1000, -1000, - -1000, 133, 280, 2304, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 2912, 182, 170, 74, 269, 182, 3760, + 3760, -1000, -1000, -1000, -1000, -1000, -1000, 74, 255, 742, + -1000, -1000, -1000, -1000, -1000, -1000, } var yyPgo = [...]int{ - 0, 626, 29, 384, 625, 624, 619, 618, 617, 613, - 609, 601, 600, 599, 598, 444, 597, 592, 589, 36, - 588, 13, 51, 7, 26, 8, 585, 22, 52, 46, - 584, 27, 583, 582, 42, 581, 152, 579, 577, 31, - 576, 574, 569, 568, 567, 10, 564, 563, 561, 556, - 548, 16, 1, 4, 34, 9, 546, 134, 40, 545, - 18, 544, 543, 542, 540, 12, 535, 37, 534, 11, - 533, 532, 44, 17, 526, 525, 112, 522, 521, 35, - 0, 20, 14, 21, 520, 622, 32, 41, 518, 516, - 515, 514, 512, 510, 508, 507, 503, 498, 182, 496, - 495, 487, 43, 6, 485, 483, 482, 25, 481, 28, - 479, 478, 476, 15, 5, 475, 2, 474, 33, 473, - 472, 119, 3, 470, + 0, 663, 16, 405, 661, 655, 652, 650, 649, 648, + 646, 645, 644, 643, 634, 640, 631, 629, 628, 45, + 623, 13, 51, 7, 36, 8, 622, 31, 54, 47, + 620, 34, 618, 616, 44, 614, 53, 609, 607, 40, + 605, 604, 603, 602, 597, 10, 594, 593, 579, 574, + 573, 25, 1, 4, 28, 9, 572, 490, 27, 568, + 21, 566, 559, 553, 551, 12, 550, 43, 549, 11, + 548, 545, 30, 18, 544, 540, 105, 61, 539, 15, + 0, 20, 35, 26, 538, 647, 22, 41, 537, 531, + 530, 527, 526, 525, 524, 517, 515, 513, 152, 512, + 510, 509, 37, 6, 500, 498, 492, 32, 491, 29, + 489, 487, 486, 14, 5, 485, 2, 484, 33, 483, + 478, 472, 119, 3, 470, } var yyR1 = [...]int{ - 0, 119, 120, 120, 1, 1, 1, 1, 1, 1, + 0, 120, 121, 121, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 18, 18, 18, 7, 8, 9, 9, 12, 110, 111, 111, 111, 107, 92, 92, 92, 95, @@ -947,47 +960,48 @@ var yyR1 = [...]int{ 106, 106, 106, 106, 108, 115, 115, 115, 115, 109, 109, 117, 117, 116, 112, 112, 112, 113, 113, 113, 114, 114, 114, 10, 10, 10, 118, 118, 11, 11, - 13, 13, 13, 13, 14, 14, 123, 15, 16, 16, - 17, 17, 19, 19, 23, 23, 22, 22, 24, 24, - 24, 24, 84, 84, 84, 83, 83, 26, 27, 27, - 28, 28, 29, 29, 29, 29, 38, 71, 71, 30, - 30, 30, 31, 31, 32, 32, 89, 89, 88, 88, - 88, 87, 87, 33, 33, 33, 34, 34, 35, 35, - 37, 37, 36, 36, 39, 39, 25, 25, 25, 25, - 25, 25, 25, 75, 75, 41, 41, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 50, 50, 50, - 50, 50, 50, 42, 42, 42, 42, 42, 42, 42, - 21, 21, 51, 51, 51, 57, 52, 52, 45, 45, + 13, 13, 13, 13, 13, 119, 119, 14, 14, 124, + 15, 16, 16, 17, 17, 19, 19, 23, 23, 22, + 22, 24, 24, 24, 24, 84, 84, 84, 83, 83, + 26, 27, 27, 28, 28, 29, 29, 29, 29, 38, + 71, 71, 30, 30, 30, 31, 31, 32, 32, 89, + 89, 88, 88, 88, 87, 87, 33, 33, 33, 34, + 34, 35, 35, 37, 37, 36, 36, 39, 39, 25, + 25, 25, 25, 25, 25, 25, 75, 75, 41, 41, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 50, 50, 50, 50, 50, 50, 42, 42, 42, 42, + 42, 42, 42, 21, 21, 51, 51, 51, 57, 52, + 52, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 48, 48, 48, 46, 46, 46, - 46, 46, 46, 47, 47, 47, 49, 49, 49, 91, - 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, - 91, 91, 91, 91, 91, 91, 61, 61, 20, 20, - 59, 59, 60, 62, 62, 58, 58, 58, 44, 44, - 44, 44, 44, 44, 44, 63, 63, 64, 64, 65, - 65, 66, 66, 67, 68, 68, 68, 69, 69, 69, - 69, 43, 43, 43, 43, 43, 43, 70, 70, 70, - 70, 53, 53, 55, 55, 54, 56, 72, 72, 73, - 76, 76, 77, 77, 74, 74, 78, 78, 78, 81, - 81, 82, 82, 85, 85, 86, 86, 79, 79, 79, + 45, 45, 45, 45, 45, 45, 45, 48, 48, 48, + 46, 46, 46, 46, 46, 46, 47, 47, 47, 49, + 49, 49, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 61, + 61, 20, 20, 59, 59, 60, 62, 62, 58, 58, + 58, 44, 44, 44, 44, 44, 44, 44, 63, 63, + 64, 64, 65, 65, 66, 66, 67, 68, 68, 68, + 69, 69, 69, 69, 43, 43, 43, 43, 43, 43, + 70, 70, 70, 70, 53, 53, 55, 55, 54, 56, + 72, 72, 73, 76, 76, 77, 77, 74, 74, 78, + 78, 78, 81, 81, 82, 82, 85, 85, 86, 86, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 121, 122, 90, 90, 90, + 80, 80, 80, 80, 80, 80, 80, 122, 123, 90, + 90, 90, } var yyR2 = [...]int{ 0, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 5, 8, 4, 1, 3, 1, - 3, 5, 6, 1, 1, 3, 8, 7, 2, 7, + 3, 5, 6, 1, 1, 3, 8, 7, 2, 8, 4, 4, 1, 3, 3, 6, 3, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 1, @@ -997,29 +1011,29 @@ var yyR2 = [...]int{ 2, 1, 2, 1, 4, 2, 3, 2, 2, 1, 1, 1, 3, 2, 0, 1, 3, 1, 2, 3, 1, 1, 1, 6, 6, 8, 0, 1, 4, 4, - 4, 5, 3, 2, 2, 2, 0, 2, 0, 2, - 1, 2, 0, 1, 0, 1, 1, 3, 1, 2, - 3, 5, 0, 1, 2, 1, 1, 2, 1, 3, - 1, 1, 1, 1, 3, 3, 2, 1, 3, 4, - 4, 3, 2, 4, 0, 1, 0, 1, 0, 1, - 2, 1, 1, 1, 2, 2, 2, 3, 2, 2, - 2, 1, 1, 3, 0, 2, 1, 3, 3, 2, - 3, 1, 2, 0, 3, 1, 1, 3, 3, 4, - 4, 5, 3, 4, 5, 6, 2, 1, 2, 1, - 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, - 0, 2, 1, 1, 1, 3, 1, 3, 1, 1, - 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, - 1, 1, 1, 1, 4, 5, 6, 6, 6, 8, - 7, 5, 4, 1, 1, 1, 4, 4, 4, 2, - 1, 2, 2, 2, 1, 2, 2, 1, 2, 2, - 2, 2, 2, 2, 2, 1, 0, 1, 0, 2, - 1, 2, 4, 0, 2, 1, 3, 5, 1, 1, - 1, 1, 1, 1, 1, 0, 3, 0, 2, 0, - 3, 1, 3, 2, 0, 1, 1, 0, 2, 4, - 4, 2, 1, 3, 5, 4, 6, 1, 3, 3, - 5, 1, 3, 1, 2, 3, 1, 1, 3, 3, - 0, 2, 0, 3, 0, 1, 0, 1, 1, 1, + 4, 5, 3, 3, 5, 0, 1, 2, 2, 0, + 2, 0, 2, 1, 2, 0, 1, 0, 1, 1, + 3, 1, 2, 3, 5, 0, 1, 2, 1, 1, + 2, 1, 3, 1, 1, 1, 1, 3, 3, 2, + 1, 3, 4, 4, 3, 2, 4, 0, 1, 0, + 1, 0, 1, 2, 1, 1, 1, 2, 2, 2, + 3, 2, 2, 2, 1, 1, 3, 0, 2, 1, + 3, 3, 2, 3, 1, 2, 0, 3, 1, 1, + 3, 3, 4, 4, 5, 3, 4, 5, 6, 2, + 1, 2, 1, 2, 1, 2, 1, 1, 1, 1, + 1, 1, 1, 0, 2, 1, 1, 1, 3, 1, + 3, 1, 1, 1, 1, 1, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, + 2, 2, 3, 1, 1, 1, 1, 4, 5, 6, + 6, 6, 8, 7, 5, 4, 1, 1, 1, 4, + 4, 4, 2, 1, 2, 2, 2, 1, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 1, 0, + 1, 0, 2, 1, 2, 4, 0, 2, 1, 3, + 5, 1, 1, 1, 1, 1, 1, 1, 0, 3, + 0, 2, 0, 3, 1, 3, 2, 0, 1, 1, + 0, 2, 4, 4, 2, 1, 3, 5, 4, 6, + 1, 3, 3, 5, 1, 3, 1, 2, 3, 1, + 1, 3, 3, 0, 2, 0, 3, 0, 1, 0, 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, @@ -1031,175 +1045,178 @@ var yyR2 = [...]int{ 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, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, } var yyChk = [...]int{ - -1000, -119, -1, -2, -6, -7, -8, -9, -10, -11, - -13, -14, -3, -4, -18, 8, 9, -12, 91, 92, - 93, 106, 23, 107, 6, -121, 7, 146, 39, -120, - 152, -65, 14, -17, 5, -15, -123, -15, -15, -110, - 39, -78, 96, 101, -81, 42, -80, 115, 134, 128, - 126, 108, 124, 120, 118, 119, 105, 113, 114, 29, - 137, 133, 136, 112, 132, 129, 121, 17, 102, 117, - 139, 111, 130, 122, 123, 135, 110, 131, 140, 151, - 127, 125, 141, 96, 96, 97, 91, 97, 96, 142, - -36, -85, 42, -80, -36, -15, -2, 54, -69, 16, - 15, -5, -3, -121, 18, -74, 99, -16, -27, -28, - -29, -30, -38, -57, -121, -36, 10, -111, -107, 42, - 97, -77, 100, -36, -76, 100, -76, 96, 10, -36, - 90, -19, 19, -122, 41, 146, -25, -40, 56, -45, - 26, 21, -44, -41, -58, -56, -57, 79, 80, 87, - 57, 89, -48, -46, -47, -49, 44, 43, 45, 46, - 47, 48, 51, 52, 53, -81, -85, -54, -121, 147, - 148, 149, 59, 28, 143, 144, 145, 100, 85, 146, - 42, -80, -66, -67, -25, -65, -2, -37, 24, -36, - 50, 27, 40, -33, -34, -35, 30, 33, 35, 31, - 36, -89, 20, -27, -2, -121, -88, -87, 20, -85, - 44, -36, 41, 40, -92, -95, -97, -96, -93, -94, - 126, 127, 130, 131, 132, 133, 134, 135, 136, 137, - 108, 122, 123, 124, 125, 110, 111, 112, 113, 114, - 115, 117, 118, 119, 120, 121, 42, -36, 56, 95, - 94, -36, 21, -36, -36, 96, -86, -85, -79, 95, - 55, 20, 22, 138, 58, 15, 59, 91, 35, 144, - 145, 143, 148, 26, 9, 23, 107, 19, 83, 93, - 62, 63, 109, 21, 53, 10, 12, 13, 100, 99, - 73, 97, 33, 7, 89, 24, 70, 30, 25, 31, - 71, 16, 85, 36, 56, 51, 37, 54, 14, 34, - 72, 94, 146, 32, 6, 150, 27, 106, 96, 142, - 61, 98, 52, 5, 101, 8, 38, 28, 60, 11, - -22, -24, 81, -25, -85, 55, 54, 70, 40, 17, - -25, -42, 73, 56, 71, 72, 58, 76, 75, 86, - 79, 80, 81, 82, 83, 84, 85, 77, 78, 64, - 65, 66, 67, 68, 69, 74, -75, -121, -57, -121, - -45, -45, -45, -45, -45, -121, 90, -52, -25, -121, - -121, -121, -121, -61, -25, -121, -121, -121, -121, 40, - -68, 22, 23, -69, -122, -43, 27, 28, -2, -121, - -36, -72, -73, -58, -81, -85, -28, -29, -28, -29, - 30, 30, 30, 34, 30, -34, -85, -122, -122, -2, - -87, -39, 11, -112, -113, -114, -82, 44, 45, -81, - -79, -107, -108, -115, 102, 101, -109, 97, 25, -104, - 51, 56, -100, 140, -98, 39, -98, -98, -98, -98, - -98, -102, 39, -102, -102, -103, 39, -103, 37, 21, - -118, 103, 98, -118, -36, -26, 40, 10, -84, -83, - 20, -81, 44, 90, -25, -25, -50, 51, 56, 52, - 53, -25, -25, -45, -51, -54, -57, 49, 73, 71, - 72, 58, -45, -45, -45, -45, -45, -45, -45, -45, - -45, -45, -45, -45, -45, -45, -45, 42, -81, -23, - 19, -22, -82, -86, -79, 40, -122, -25, -58, -19, - -59, -60, 60, -58, -22, -22, -22, -67, -72, -53, - -55, -54, -121, -2, -70, -81, -39, 40, 64, 90, - -32, -31, 37, 38, -31, 30, -122, -65, -25, 40, - -114, 64, 39, 25, -109, 42, 42, -99, 26, 51, - -101, 141, 45, 45, 45, -36, -107, -36, -58, -39, - -24, -27, -83, 81, -86, 51, 52, 53, -51, -45, - -45, -45, -21, 109, 55, -122, -122, -22, -121, 90, - -25, 20, 40, -22, -62, -60, 62, -25, -122, -122, - -122, -122, 40, -122, -122, -122, 40, 90, -65, -73, - -25, -82, -25, 39, -69, -113, -114, -117, -116, -81, - 42, -105, 138, 44, 45, 46, 51, 143, 41, 40, - 41, 40, -90, -121, -82, 98, -63, 12, 90, -21, - 55, -45, -45, -122, -23, -82, -91, 126, 108, 124, - 120, 129, 139, 122, 140, 123, 113, 110, 111, 112, - 115, 44, -45, -65, 63, -25, 61, -55, 28, -2, - -121, -81, -81, -69, -71, -81, 41, 40, -98, -106, - 102, 25, 101, 45, 45, -58, -64, 13, 15, 81, - -45, -122, -122, -98, -98, -103, -98, 114, -98, 114, - -98, -98, -98, -98, -98, -98, -122, 40, -20, 150, - -25, -53, -2, 90, 40, 41, -116, 25, 25, 41, - 41, -25, -52, -45, -122, 44, -122, -81, -81, -122, + -1000, -120, -1, -2, -6, -7, -8, -9, -10, -11, + -13, -14, -3, -4, -18, 8, 9, -12, 93, 94, + 95, 108, 23, 109, 6, -122, 7, 148, 39, -121, + 154, -65, 14, -17, 5, -15, -124, -15, -15, -110, + 39, -78, 98, 103, -81, 42, -80, 117, 136, 130, + 128, 110, 126, 122, 120, 121, 107, 115, 116, 29, + 139, 135, 138, 114, 134, 131, 123, 17, 104, 119, + 141, 113, 132, 124, 125, 137, 112, 133, 142, 153, + 129, 127, 143, 98, 98, 99, 93, 99, 98, -119, + 54, -36, -85, 42, -80, -36, -15, -2, 56, -69, + 16, 15, -5, -3, -122, 18, -74, 101, -16, -27, + -28, -29, -30, -38, -57, -122, -36, 10, -111, -107, + 42, 99, -77, 102, -36, -76, 102, -76, 98, 10, + -36, 144, 55, 92, -19, 19, -123, 41, 148, -25, + -40, 58, -45, 26, 21, -44, -41, -58, -56, -57, + 81, 82, 89, 59, 91, -48, -46, -47, -49, 44, + 43, 45, 46, 47, 48, 51, 52, 53, -81, -85, + -54, -122, 149, 150, 151, 61, 28, 145, 146, 147, + 102, 87, 148, 42, -80, -66, -67, -25, -65, -2, + -37, 24, -36, 50, 27, 40, -33, -34, -35, 30, + 33, 35, 31, 36, -89, 20, -27, -2, -122, -88, + -87, 20, -85, 44, -36, 41, 40, -92, -95, -97, + -96, -93, -94, 128, 129, 132, 133, 134, 135, 136, + 137, 138, 139, 110, 124, 125, 126, 127, 112, 113, + 114, 115, 116, 117, 119, 120, 121, 122, 123, -77, + -36, 58, 97, 96, -36, 21, -36, -36, 98, 10, + -86, -85, -79, 97, 57, 20, 22, 140, 60, 15, + 61, 93, 35, 146, 147, 145, 150, 26, 9, 23, + 109, 19, 85, 95, 64, 65, 111, 21, 53, 10, + 12, 13, 102, 101, 75, 99, 33, 7, 91, 24, + 72, 30, 25, 31, 73, 16, 87, 36, 58, 51, + 37, 56, 14, 34, 74, 96, 148, 32, 6, 152, + 27, 108, 98, 144, 63, 100, 52, 5, 103, 8, + 38, 28, 62, 11, -22, -24, 83, -25, -85, 57, + 56, 72, 40, 17, -25, -42, 75, 58, 73, 74, + 60, 78, 77, 88, 81, 82, 83, 84, 85, 86, + 87, 79, 80, 66, 67, 68, 69, 70, 71, 76, + -75, -122, -57, -122, -45, -45, -45, -45, -45, -122, + 92, -52, -25, -122, -122, -122, -122, -61, -25, -122, + -122, -122, -122, 40, -68, 22, 23, -69, -123, -43, + 27, 28, -2, -122, -36, -72, -73, -58, -81, -85, + -28, -29, -28, -29, 30, 30, 30, 34, 30, -34, + -85, -123, -123, -2, -87, -39, 11, -112, -113, -114, + -82, 44, 45, -81, -79, -107, -108, -115, 104, 103, + -109, 99, 25, -104, 51, 58, -100, 142, -98, 39, + -98, -98, -98, -98, -98, -102, 39, -102, -102, -103, + 39, -103, 42, 21, -118, 105, 100, -118, -36, -36, + -26, 40, 10, -84, -83, 20, -81, 44, 92, -25, + -25, -50, 51, 58, 52, 53, -25, -25, -45, -51, + -54, -57, 49, 75, 73, 74, 60, -45, -45, -45, + -45, -45, -45, -45, -45, -45, -45, -45, -45, -45, + -45, -45, 42, -81, -23, 19, -22, -82, -86, -79, + 40, -123, -25, -58, -19, -59, -60, 62, -58, -22, + -22, -22, -67, -72, -53, -55, -54, -122, -2, -70, + -81, -39, 40, 66, 92, -32, -31, 37, 38, -31, + 30, -123, -65, -25, 40, -114, 66, 39, 25, -109, + 42, 42, -99, 26, 51, -101, 143, 45, 45, 45, + 37, -107, -36, -58, -39, -24, -27, -83, 83, -86, + 51, 52, 53, -51, -45, -45, -45, -21, 111, 57, + -123, -123, -22, -122, 92, -25, 20, 40, -22, -62, + -60, 64, -25, -123, -123, -123, -123, 40, -123, -123, + -123, 40, 92, -65, -73, -25, -82, -25, 39, -69, + -113, -114, -117, -116, -81, 42, -105, 140, 44, 45, + 46, 51, 145, 41, 40, 41, 40, -36, 100, -63, + 12, 92, -21, 57, -45, -45, -123, -23, -82, -91, + 128, 110, 126, 122, 131, 141, 124, 142, 125, 115, + 112, 113, 114, 117, 44, -45, -65, 65, -25, 63, + -55, 28, -2, -122, -81, -81, -69, -71, -81, 41, + 40, -98, -106, 104, 25, 103, 45, 45, -90, -122, + -82, -58, -64, 13, 15, 83, -45, -123, -123, -98, + -98, -103, -98, 116, -98, 116, -98, -98, -98, -98, + -98, -98, -123, 40, -20, 152, -25, -53, -2, 92, + 40, 41, -116, 25, 25, 41, 41, -25, -52, -45, + -123, 44, -123, -81, -81, -123, } var yyDef = [...]int{ 0, -2, 2, -2, 5, 6, 7, 8, 9, 10, - 11, 12, 309, 0, 126, 126, 126, 0, 346, 0, - 0, 0, 0, 0, 126, 0, 23, 24, 464, 1, - 3, 317, 0, 0, 130, 344, 128, 0, 0, 28, - 0, 0, 342, 347, 348, 349, 350, 428, 429, 430, - 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, - 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, - 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, - 461, 462, 463, 0, 340, 340, 0, 0, 0, 123, - 124, 182, 353, 354, 125, 132, 17, 0, 13, 0, - 0, 309, 19, 0, 131, 0, 345, 127, 0, 148, - 150, 151, 152, -2, 0, 168, 0, 0, 32, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, - 0, 0, 133, 18, 465, 25, 318, 186, 0, 191, - 193, 0, 228, 229, 230, 231, 232, 0, 0, 0, - 0, 0, 250, 251, 252, 253, 298, 299, 300, 301, - 302, 303, 304, 195, 196, 295, 0, 336, 0, 0, - 0, 0, 286, 0, 263, 264, 265, 0, 0, 0, - -2, -2, 310, 311, 314, 317, 17, 0, 0, 181, - 129, 0, 0, 0, 0, 0, 173, 0, 0, 0, - 0, 0, 167, 0, 17, 0, 156, 169, 0, 171, - 172, 184, 104, 0, 78, 74, 37, 38, 67, 40, - 67, 67, 59, 60, 61, 62, 63, 64, 65, 66, - 52, 67, 67, 67, 56, 41, 42, 43, 44, 45, - 46, 69, 69, 69, 71, 71, 0, 30, 0, 116, - 116, 118, 341, 119, 120, 0, 183, 355, 356, 357, - 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, - 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, - 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, - 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, - 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, - 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, - 16, 136, 138, 142, 0, 0, 0, 0, 0, 0, - 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, - 214, 215, 216, 217, 218, 219, 192, 0, 206, 0, - 245, 246, 247, 248, 0, 134, 0, 0, 226, 0, - 0, 0, 132, 0, 287, 0, 0, 0, 0, 0, - 313, 315, 316, 14, 20, 21, 0, 0, -2, 0, - 180, 184, 337, 0, 295, 0, 149, 164, 0, 161, - 174, 175, 176, 0, 178, 179, 154, 155, 225, 17, - 170, 309, 0, 31, 105, 107, 110, 111, 112, 351, - 352, 33, 34, 0, 0, 0, 0, 99, 100, 81, - 79, 0, 76, 75, 39, 0, 57, 58, 53, 54, - 55, 47, 0, 48, 49, 50, 0, 51, 0, 343, - 0, 117, 0, 0, 121, 184, 0, 0, 139, 143, - 0, 145, 146, 0, 187, 188, 190, 207, 0, 209, - 211, 319, 320, 197, 198, 222, 223, 224, 0, 0, - 0, 0, 220, 202, 0, 233, 234, 235, 236, 237, - 238, 239, 240, 241, 242, 243, 244, 0, 249, 0, - 0, 135, 296, 0, -2, 0, 335, 0, 0, 0, - 293, 290, 0, 0, 0, 0, 0, 312, 22, 321, - 331, 333, 0, 17, 0, 327, 309, 0, 0, 0, - 159, 165, 0, 0, 160, 177, -2, 317, 185, 0, - 108, 0, 0, 95, 0, 97, 98, 87, 0, 80, - 36, 77, 0, 0, 0, 466, 113, 114, 0, 305, - 137, 147, 144, 140, 0, 208, 210, 212, 199, 220, - 203, 0, 200, 0, 0, 194, 254, 0, 134, 0, - 227, 0, 0, 309, 0, 291, 0, 0, 262, 266, - 267, 268, 0, 334, -2, 0, 0, 0, 317, 338, - 339, 296, 162, 0, 27, 106, 109, 0, 101, 67, - 96, 89, 88, 82, 83, 84, 85, 86, 68, 0, - 72, 0, 29, 467, 468, 0, 307, 0, 0, 201, - 0, 221, 204, 255, 0, 297, 0, 67, 270, 67, - 71, 67, 274, 67, 277, 67, 67, 67, 67, 67, - 67, 285, 0, 288, 261, 294, 0, 332, 0, -2, - 0, 329, 328, 26, 0, 157, 94, 0, 103, 35, - 0, 91, 93, 0, 0, 115, 15, 0, 0, 141, - 205, 256, 257, 269, 271, 272, 273, 275, 276, 278, - 279, 280, 281, 282, 283, 284, 258, 0, 0, 0, - 292, 324, 17, 0, 0, 163, 102, 90, 92, 70, - 73, 308, 306, 0, 260, 289, -2, 330, 158, 259, + 11, 12, 312, 0, 129, 129, 129, 0, 349, 0, + 0, 125, 0, 0, 129, 0, 23, 24, 467, 1, + 3, 320, 0, 0, 133, 347, 131, 0, 0, 28, + 0, 0, 345, 350, 351, 352, 353, 431, 432, 433, + 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, + 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, + 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, + 464, 465, 466, 0, 343, 343, 0, 0, 0, 0, + 126, 127, 185, 356, 357, 128, 135, 17, 0, 13, + 0, 0, 312, 19, 0, 134, 0, 348, 130, 0, + 151, 153, 154, 155, -2, 0, 171, 0, 0, 32, + 0, 345, 0, 0, 0, 0, 0, 0, 0, 0, + 122, 123, 0, 0, 0, 136, 18, 468, 25, 321, + 189, 0, 194, 196, 0, 231, 232, 233, 234, 235, + 0, 0, 0, 0, 0, 253, 254, 255, 256, 301, + 302, 303, 304, 305, 306, 307, 198, 199, 298, 0, + 339, 0, 0, 0, 0, 289, 0, 266, 267, 268, + 0, 0, 0, -2, -2, 313, 314, 317, 320, 17, + 0, 0, 184, 132, 0, 0, 0, 0, 0, 176, + 0, 0, 0, 0, 0, 170, 0, 17, 0, 159, + 172, 0, 174, 175, 187, 104, 0, 78, 74, 37, + 38, 67, 40, 67, 67, 59, 60, 61, 62, 63, + 64, 65, 66, 52, 67, 67, 67, 56, 41, 42, + 43, 44, 45, 46, 69, 69, 69, 71, 71, 0, + 30, 0, 116, 116, 118, 344, 119, 120, 0, 0, + 186, 358, 359, 360, 361, 362, 363, 364, 365, 366, + 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, + 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, + 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, + 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 430, 16, 139, 141, 145, 0, 0, + 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 216, 217, 218, 219, 220, 221, 222, + 195, 0, 209, 0, 248, 249, 250, 251, 0, 137, + 0, 0, 229, 0, 0, 0, 135, 0, 290, 0, + 0, 0, 0, 0, 316, 318, 319, 14, 20, 21, + 0, 0, -2, 0, 183, 187, 340, 0, 298, 0, + 152, 167, 0, 164, 177, 178, 179, 0, 181, 182, + 157, 158, 228, 17, 173, 312, 0, 31, 105, 107, + 110, 111, 112, 354, 355, 33, 34, 0, 0, 0, + 0, 99, 100, 81, 79, 0, 76, 75, 39, 0, + 57, 58, 53, 54, 55, 47, 0, 48, 49, 50, + 0, 51, 0, 346, 0, 117, 0, 0, 121, 124, + 187, 0, 0, 142, 146, 0, 148, 149, 0, 190, + 191, 193, 210, 0, 212, 214, 322, 323, 200, 201, + 225, 226, 227, 0, 0, 0, 0, 223, 205, 0, + 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, + 246, 247, 0, 252, 0, 0, 138, 299, 0, -2, + 0, 338, 0, 0, 0, 296, 293, 0, 0, 0, + 0, 0, 315, 22, 324, 334, 336, 0, 17, 0, + 330, 312, 0, 0, 0, 162, 168, 0, 0, 163, + 180, -2, 320, 188, 0, 108, 0, 0, 95, 0, + 97, 98, 87, 0, 80, 36, 77, 0, 0, 0, + 0, 113, 114, 0, 308, 140, 150, 147, 143, 0, + 211, 213, 215, 202, 223, 206, 0, 203, 0, 0, + 197, 257, 0, 137, 0, 230, 0, 0, 312, 0, + 294, 0, 0, 265, 269, 270, 271, 0, 337, -2, + 0, 0, 0, 320, 341, 342, 299, 165, 0, 27, + 106, 109, 0, 101, 67, 96, 89, 88, 82, 83, + 84, 85, 86, 68, 0, 72, 0, 469, 0, 310, + 0, 0, 204, 0, 224, 207, 258, 0, 300, 0, + 67, 273, 67, 71, 67, 277, 67, 280, 67, 67, + 67, 67, 67, 67, 288, 0, 291, 264, 297, 0, + 335, 0, -2, 0, 332, 331, 26, 0, 160, 94, + 0, 103, 35, 0, 91, 93, 0, 0, 29, 470, + 471, 115, 15, 0, 0, 144, 208, 259, 260, 272, + 274, 275, 276, 278, 279, 281, 282, 283, 284, 285, + 286, 287, 261, 0, 0, 0, 295, 327, 17, 0, + 0, 166, 102, 90, 92, 70, 73, 311, 309, 0, + 263, 292, -2, 333, 161, 262, } var yyTok1 = [...]int{ 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 57, 3, 3, 3, 84, 76, 3, - 39, 41, 81, 79, 40, 80, 90, 82, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 152, - 65, 64, 66, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 59, 3, 3, 3, 86, 78, 3, + 39, 41, 83, 81, 40, 82, 92, 84, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 154, + 67, 66, 68, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 86, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 88, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 75, 3, 87, + 3, 3, 3, 3, 77, 3, 89, } var yyTok2 = [...]int{ @@ -1208,15 +1225,15 @@ var yyTok2 = [...]int{ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 58, 59, 60, 61, 62, 63, 67, 68, - 69, 70, 71, 72, 73, 74, 77, 78, 83, 85, - 88, 89, 91, 92, 93, 94, 95, 96, 97, 98, + 55, 56, 57, 58, 60, 61, 62, 63, 64, 65, + 69, 70, 71, 72, 73, 74, 75, 76, 79, 80, + 85, 87, 90, 91, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 151, + 149, 150, 151, 152, 153, } var yyTok3 = [...]int{ 0, @@ -1561,29 +1578,29 @@ yydefault: case 1: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:242 + //line sql.y:244 { setParseTree(yylex, yyDollar[1].statement) } case 2: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:247 + //line sql.y:249 { } case 3: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:248 + //line sql.y:250 { } case 4: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:252 + //line sql.y:254 { yyVAL.statement = yyDollar[1].selStmt } case 13: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:266 + //line sql.y:268 { sel := yyDollar[1].selStmt.(*Select) sel.OrderBy = yyDollar[2].orderBy @@ -1592,49 +1609,49 @@ yydefault: } case 14: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:273 + //line sql.y:275 { yyVAL.selStmt = &Union{Type: yyDollar[2].str, Left: yyDollar[1].selStmt, Right: yyDollar[3].selStmt, OrderBy: yyDollar[4].orderBy, Limit: yyDollar[5].limit} } case 15: yyDollar = yyS[yypt-8 : yypt+1] - //line sql.y:280 + //line sql.y:282 { yyVAL.selStmt = &Select{Comments: Comments(yyDollar[2].bytes2), Distinct: yyDollar[3].str, SelectExprs: yyDollar[4].selectExprs, From: yyDollar[5].tableExprs, Where: NewWhere(WhereStr, yyDollar[6].expr), GroupBy: GroupBy(yyDollar[7].exprs), Having: NewWhere(HavingStr, yyDollar[8].expr)} } case 16: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:284 + //line sql.y:286 { yyVAL.selStmt = &Select{Comments: Comments(yyDollar[2].bytes2), Distinct: yyDollar[3].str, SelectExprs: yyDollar[4].selectExprs} } case 17: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:290 + //line sql.y:292 { yyVAL.selStmt = yyDollar[1].selStmt } case 18: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:294 + //line sql.y:296 { yyVAL.selStmt = &ParenSelect{Select: yyDollar[2].selStmt} } case 19: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:300 + //line sql.y:302 { yyVAL.selStmt = yyDollar[1].selStmt } case 20: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:304 + //line sql.y:306 { yyVAL.selStmt = &ParenSelect{Select: yyDollar[2].selStmt} } case 21: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:311 + //line sql.y:313 { // insert_data returns a *Insert pre-filled with Columns & Values ins := yyDollar[5].ins @@ -1646,7 +1663,7 @@ yydefault: } case 22: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:321 + //line sql.y:323 { cols := make(Columns, 0, len(yyDollar[6].updateExprs)) vals := make(ValTuple, 0, len(yyDollar[6].updateExprs)) @@ -1658,84 +1675,84 @@ yydefault: } case 23: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:333 + //line sql.y:335 { yyVAL.str = InsertStr } case 24: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:337 + //line sql.y:339 { yyVAL.str = ReplaceStr } case 25: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:341 + //line sql.y:343 { yyVAL.str = ReplaceStr } case 26: yyDollar = yyS[yypt-8 : yypt+1] - //line sql.y:347 + //line sql.y:349 { yyVAL.statement = &Update{Comments: Comments(yyDollar[2].bytes2), TableExprs: yyDollar[3].tableExprs, Exprs: yyDollar[5].updateExprs, Where: NewWhere(WhereStr, yyDollar[6].expr), OrderBy: yyDollar[7].orderBy, Limit: yyDollar[8].limit} } case 27: yyDollar = yyS[yypt-7 : yypt+1] - //line sql.y:353 + //line sql.y:355 { yyVAL.statement = &Delete{Comments: Comments(yyDollar[2].bytes2), TableExprs: TableExprs{&AliasedTableExpr{Expr: yyDollar[4].tableName}}, Where: NewWhere(WhereStr, yyDollar[5].expr), OrderBy: yyDollar[6].orderBy, Limit: yyDollar[7].limit} } case 28: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:359 + //line sql.y:361 { yyDollar[1].ddl.TableSpec = yyDollar[2].TableSpec yyVAL.statement = yyDollar[1].ddl } case 29: - yyDollar = yyS[yypt-7 : yypt+1] - //line sql.y:364 + yyDollar = yyS[yypt-8 : yypt+1] + //line sql.y:366 { // Change this to an alter statement - yyVAL.statement = &DDL{Action: CreateIndexStr, Table: yyDollar[6].tableName, NewName: yyDollar[6].tableName} + yyVAL.statement = &DDL{Action: CreateIndexStr, Table: yyDollar[7].tableName, NewName: yyDollar[7].tableName} } case 30: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:371 + //line sql.y:373 { yyVAL.ddl = &DDL{Action: CreateStr, NewName: yyDollar[4].tableName} setDDL(yylex, yyVAL.ddl) } case 31: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:378 + //line sql.y:380 { yyVAL.TableSpec = yyDollar[2].TableSpec yyVAL.TableSpec.Options = yyDollar[4].str } case 32: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:385 + //line sql.y:387 { yyVAL.TableSpec = &TableSpec{} yyVAL.TableSpec.AddColumn(yyDollar[1].columnDefinition) } case 33: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:390 + //line sql.y:392 { yyVAL.TableSpec.AddColumn(yyDollar[3].columnDefinition) } case 34: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:394 + //line sql.y:396 { yyVAL.TableSpec.AddIndex(yyDollar[3].indexDefinition) } case 35: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:400 + //line sql.y:402 { yyDollar[2].columnType.NotNull = yyDollar[3].boolVal yyDollar[2].columnType.Default = yyDollar[4].optVal @@ -1745,7 +1762,7 @@ yydefault: } case 36: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:409 + //line sql.y:411 { yyVAL.columnType = yyDollar[1].columnType yyVAL.columnType.Unsigned = yyDollar[2].boolVal @@ -1753,56 +1770,56 @@ yydefault: } case 39: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:419 + //line sql.y:421 { yyVAL.columnType = yyDollar[1].columnType yyVAL.columnType.Length = yyDollar[2].optVal } case 40: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:424 + //line sql.y:426 { yyVAL.columnType = yyDollar[1].columnType } case 41: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:430 + //line sql.y:432 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 42: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:434 + //line sql.y:436 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 43: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:438 + //line sql.y:440 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 44: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:442 + //line sql.y:444 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 45: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:446 + //line sql.y:448 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 46: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:450 + //line sql.y:452 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 47: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:456 + //line sql.y:458 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -1810,7 +1827,7 @@ yydefault: } case 48: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:462 + //line sql.y:464 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -1818,7 +1835,7 @@ yydefault: } case 49: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:468 + //line sql.y:470 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -1826,7 +1843,7 @@ yydefault: } case 50: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:474 + //line sql.y:476 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -1834,7 +1851,7 @@ yydefault: } case 51: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:480 + //line sql.y:482 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -1842,115 +1859,115 @@ yydefault: } case 52: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:488 + //line sql.y:490 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 53: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:492 + //line sql.y:494 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } case 54: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:496 + //line sql.y:498 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } case 55: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:500 + //line sql.y:502 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } case 56: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:504 + //line sql.y:506 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 57: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:510 + //line sql.y:512 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } case 58: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:514 + //line sql.y:516 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } case 59: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:518 + //line sql.y:520 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 60: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:522 + //line sql.y:524 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 61: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:526 + //line sql.y:528 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 62: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:530 + //line sql.y:532 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 63: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:534 + //line sql.y:536 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 64: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:538 + //line sql.y:540 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 65: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:542 + //line sql.y:544 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 66: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:546 + //line sql.y:548 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 67: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:551 + //line sql.y:553 { yyVAL.optVal = nil } case 68: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:555 + //line sql.y:557 { yyVAL.optVal = NewIntVal(yyDollar[2].bytes) } case 69: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:560 + //line sql.y:562 { yyVAL.LengthScaleOption = LengthScaleOption{} } case 70: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:564 + //line sql.y:566 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: NewIntVal(yyDollar[2].bytes), @@ -1959,13 +1976,13 @@ yydefault: } case 71: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:572 + //line sql.y:574 { yyVAL.LengthScaleOption = LengthScaleOption{} } case 72: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:576 + //line sql.y:578 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: NewIntVal(yyDollar[2].bytes), @@ -1973,7 +1990,7 @@ yydefault: } case 73: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:582 + //line sql.y:584 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: NewIntVal(yyDollar[2].bytes), @@ -1982,266 +1999,266 @@ yydefault: } case 74: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:590 + //line sql.y:592 { yyVAL.boolVal = BoolVal(false) } case 75: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:594 + //line sql.y:596 { yyVAL.boolVal = BoolVal(true) } case 76: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:599 + //line sql.y:601 { yyVAL.boolVal = BoolVal(false) } case 77: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:603 + //line sql.y:605 { yyVAL.boolVal = BoolVal(true) } case 78: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:609 + //line sql.y:611 { yyVAL.boolVal = BoolVal(false) } case 79: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:613 + //line sql.y:615 { yyVAL.boolVal = BoolVal(false) } case 80: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:617 + //line sql.y:619 { yyVAL.boolVal = BoolVal(true) } case 81: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:622 + //line sql.y:624 { yyVAL.optVal = nil } case 82: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:626 + //line sql.y:628 { yyVAL.optVal = NewStrVal(yyDollar[2].bytes) } case 83: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:630 + //line sql.y:632 { yyVAL.optVal = NewIntVal(yyDollar[2].bytes) } case 84: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:634 + //line sql.y:636 { yyVAL.optVal = NewFloatVal(yyDollar[2].bytes) } case 85: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:638 + //line sql.y:640 { yyVAL.optVal = NewValArg(yyDollar[2].bytes) } case 86: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:642 + //line sql.y:644 { yyVAL.optVal = NewValArg(yyDollar[2].bytes) } case 87: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:647 + //line sql.y:649 { yyVAL.boolVal = BoolVal(false) } case 88: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:651 + //line sql.y:653 { yyVAL.boolVal = BoolVal(true) } case 89: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:656 + //line sql.y:658 { yyVAL.colKeyOpt = colKeyNone } case 90: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:660 + //line sql.y:662 { yyVAL.colKeyOpt = colKeyPrimary } case 91: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:664 + //line sql.y:666 { yyVAL.colKeyOpt = colKey } case 92: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:668 + //line sql.y:670 { yyVAL.colKeyOpt = colKeyUniqueKey } case 93: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:672 + //line sql.y:674 { yyVAL.colKeyOpt = colKeyUnique } case 94: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:678 + //line sql.y:680 { yyVAL.indexDefinition = &IndexDefinition{Info: yyDollar[1].indexInfo, Columns: yyDollar[3].indexColumns} } case 95: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:684 + //line sql.y:686 { yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes) + " " + string(yyDollar[2].bytes), Name: NewColIdent("PRIMARY"), Primary: true, Unique: true} } case 96: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:688 + //line sql.y:690 { yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes) + " " + string(yyDollar[2].str), Name: NewColIdent(string(yyDollar[3].bytes)), Unique: true} } case 97: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:692 + //line sql.y:694 { yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes), Name: NewColIdent(string(yyDollar[2].bytes)), Unique: true} } case 98: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:696 + //line sql.y:698 { yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].str), Name: NewColIdent(string(yyDollar[2].bytes)), Unique: false} } case 99: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:702 + //line sql.y:704 { yyVAL.str = string(yyDollar[1].bytes) } case 100: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:706 + //line sql.y:708 { yyVAL.str = string(yyDollar[1].bytes) } case 101: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:712 + //line sql.y:714 { yyVAL.indexColumns = []*IndexColumn{yyDollar[1].indexColumn} } case 102: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:716 + //line sql.y:718 { yyVAL.indexColumns = append(yyVAL.indexColumns, yyDollar[3].indexColumn) } case 103: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:722 + //line sql.y:724 { yyVAL.indexColumn = &IndexColumn{Column: yyDollar[1].colIdent, Length: yyDollar[2].optVal} } case 104: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:727 + //line sql.y:729 { yyVAL.str = "" } case 105: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:731 + //line sql.y:733 { yyVAL.str = " " + string(yyDollar[1].str) } case 106: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:735 + //line sql.y:737 { yyVAL.str = string(yyDollar[1].str) + ", " + string(yyDollar[3].str) } case 107: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:743 + //line sql.y:745 { yyVAL.str = yyDollar[1].str } case 108: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:747 + //line sql.y:749 { yyVAL.str = yyDollar[1].str + " " + yyDollar[2].str } case 109: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:751 + //line sql.y:753 { yyVAL.str = yyDollar[1].str + "=" + yyDollar[3].str } case 110: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:757 + //line sql.y:759 { yyVAL.str = yyDollar[1].colIdent.String() } case 111: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:761 + //line sql.y:763 { yyVAL.str = "'" + string(yyDollar[1].bytes) + "'" } case 112: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:765 + //line sql.y:767 { yyVAL.str = string(yyDollar[1].bytes) } case 113: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:771 + //line sql.y:773 { yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[3].tableName, NewName: yyDollar[3].tableName} } case 114: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:775 + //line sql.y:777 { // Change this to a rename statement yyVAL.statement = &DDL{Action: RenameStr, Table: yyDollar[3].tableName, NewName: yyDollar[6].tableName} } case 115: yyDollar = yyS[yypt-8 : yypt+1] - //line sql.y:780 + //line sql.y:782 { // Rename an index can just be an alter yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[3].tableName, NewName: yyDollar[3].tableName} } case 116: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:786 + //line sql.y:788 { } case 118: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:790 + //line sql.y:792 { var exists bool if yyDollar[3].byt != 0 { @@ -2251,7 +2268,7 @@ yydefault: } case 119: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:798 + //line sql.y:800 { var exists bool if yyDollar[3].byt != 0 { @@ -2261,734 +2278,752 @@ yydefault: } case 120: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:808 + //line sql.y:810 { yyVAL.statement = &Show{Type: string(yyDollar[3].bytes), ShowCreate: true, OnTable: yyDollar[4].tableName} } case 121: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:812 + //line sql.y:814 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes), OnTable: yyDollar[5].tableName} } case 122: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:816 + //line sql.y:818 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes), OnTable: yyDollar[3].tableName} } case 123: - yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:820 + yyDollar = yyS[yypt-3 : yypt+1] + //line sql.y:822 { - yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} + yyVAL.statement = &Show{Type: string(yyDollar[3].bytes)} } case 124: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-5 : yypt+1] //line sql.y:826 { - yyVAL.statement = &Show{Type: "table", OnTable: yyDollar[2].tableName} + yyVAL.statement = &Show{Type: "table", OnTable: yyDollar[5].tableName} } case 125: + yyDollar = yyS[yypt-0 : yypt+1] + //line sql.y:831 + { + yyVAL.bytes = nil + } + case 126: + yyDollar = yyS[yypt-1 : yypt+1] + //line sql.y:835 + { + yyVAL.bytes = nil + } + case 127: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:830 + //line sql.y:841 { yyVAL.statement = &Show{Type: "table", OnTable: yyDollar[2].tableName} } - case 126: + case 128: + yyDollar = yyS[yypt-2 : yypt+1] + //line sql.y:845 + { + yyVAL.statement = &Show{Type: "table", OnTable: yyDollar[2].tableName} + } + case 129: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:835 + //line sql.y:850 { setAllowComments(yylex, true) } - case 127: + case 130: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:839 + //line sql.y:854 { yyVAL.bytes2 = yyDollar[2].bytes2 setAllowComments(yylex, false) } - case 128: + case 131: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:845 + //line sql.y:860 { yyVAL.bytes2 = nil } - case 129: + case 132: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:849 + //line sql.y:864 { yyVAL.bytes2 = append(yyDollar[1].bytes2, yyDollar[2].bytes) } - case 130: + case 133: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:855 + //line sql.y:870 { yyVAL.str = UnionStr } - case 131: + case 134: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:859 + //line sql.y:874 { yyVAL.str = UnionAllStr } - case 132: + case 135: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:864 + //line sql.y:879 { yyVAL.str = "" } - case 133: + case 136: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:868 + //line sql.y:883 { yyVAL.str = DistinctStr } - case 134: + case 137: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:873 + //line sql.y:888 { yyVAL.selectExprs = nil } - case 135: + case 138: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:877 + //line sql.y:892 { yyVAL.selectExprs = yyDollar[1].selectExprs } - case 136: + case 139: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:883 + //line sql.y:898 { yyVAL.selectExprs = SelectExprs{yyDollar[1].selectExpr} } - case 137: + case 140: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:887 + //line sql.y:902 { yyVAL.selectExprs = append(yyVAL.selectExprs, yyDollar[3].selectExpr) } - case 138: + case 141: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:893 + //line sql.y:908 { yyVAL.selectExpr = &StarExpr{} } - case 139: + case 142: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:897 + //line sql.y:912 { yyVAL.selectExpr = &AliasedExpr{Expr: yyDollar[1].expr, As: yyDollar[2].colIdent} } - case 140: + case 143: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:901 + //line sql.y:916 { yyVAL.selectExpr = &StarExpr{TableName: TableName{Name: yyDollar[1].tableIdent}} } - case 141: + case 144: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:905 + //line sql.y:920 { yyVAL.selectExpr = &StarExpr{TableName: TableName{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].tableIdent}} } - case 142: + case 145: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:910 + //line sql.y:925 { yyVAL.colIdent = ColIdent{} } - case 143: + case 146: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:914 + //line sql.y:929 { yyVAL.colIdent = yyDollar[1].colIdent } - case 144: + case 147: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:918 + //line sql.y:933 { yyVAL.colIdent = yyDollar[2].colIdent } - case 146: + case 149: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:925 + //line sql.y:940 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } - case 147: + case 150: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:931 + //line sql.y:946 { yyVAL.tableExprs = yyDollar[2].tableExprs } - case 148: + case 151: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:937 + //line sql.y:952 { yyVAL.tableExprs = TableExprs{yyDollar[1].tableExpr} } - case 149: + case 152: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:941 + //line sql.y:956 { yyVAL.tableExprs = append(yyVAL.tableExprs, yyDollar[3].tableExpr) } - case 152: + case 155: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:951 + //line sql.y:966 { yyVAL.tableExpr = yyDollar[1].aliasedTableName } - case 153: + case 156: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:955 + //line sql.y:970 { yyVAL.tableExpr = &AliasedTableExpr{Expr: yyDollar[1].subquery} } - case 154: + case 157: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:959 + //line sql.y:974 { yyVAL.tableExpr = &AliasedTableExpr{Expr: yyDollar[1].subquery, As: yyDollar[3].tableIdent} } - case 155: + case 158: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:963 + //line sql.y:978 { yyVAL.tableExpr = &ParenTableExpr{Exprs: yyDollar[2].tableExprs} } - case 156: + case 159: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:969 + //line sql.y:984 { yyVAL.aliasedTableName = &AliasedTableExpr{Expr: yyDollar[1].tableName, As: yyDollar[2].tableIdent} } - case 157: + case 160: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:975 + //line sql.y:990 { yyVAL.columns = Columns{yyDollar[1].colIdent} } - case 158: + case 161: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:979 + //line sql.y:994 { yyVAL.columns = append(yyVAL.columns, yyDollar[3].colIdent) } - case 159: + case 162: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:985 + //line sql.y:1000 { yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].str, RightExpr: yyDollar[3].tableExpr, Condition: yyDollar[4].joinCondition} } - case 160: + case 163: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:989 + //line sql.y:1004 { yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].str, RightExpr: yyDollar[3].tableExpr, Condition: yyDollar[4].joinCondition} } - case 161: + case 164: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:993 + //line sql.y:1008 { yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].str, RightExpr: yyDollar[3].tableExpr} } - case 162: + case 165: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:999 + //line sql.y:1014 { yyVAL.joinCondition = JoinCondition{On: yyDollar[2].expr} } - case 163: + case 166: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1001 + //line sql.y:1016 { yyVAL.joinCondition = JoinCondition{Using: yyDollar[3].columns} } - case 164: + case 167: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1005 + //line sql.y:1020 { yyVAL.joinCondition = JoinCondition{} } - case 165: + case 168: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1007 + //line sql.y:1022 { yyVAL.joinCondition = yyDollar[1].joinCondition } - case 166: + case 169: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1010 + //line sql.y:1025 { yyVAL.empty = struct{}{} } - case 167: + case 170: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1012 + //line sql.y:1027 { yyVAL.empty = struct{}{} } - case 168: + case 171: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1015 + //line sql.y:1030 { yyVAL.tableIdent = NewTableIdent("") } - case 169: + case 172: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1019 + //line sql.y:1034 { yyVAL.tableIdent = yyDollar[1].tableIdent } - case 170: + case 173: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1023 + //line sql.y:1038 { yyVAL.tableIdent = yyDollar[2].tableIdent } - case 172: + case 175: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1030 + //line sql.y:1045 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } - case 173: + case 176: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1036 + //line sql.y:1051 { yyVAL.str = JoinStr } - case 174: + case 177: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1040 + //line sql.y:1055 { yyVAL.str = InnerJoinStr } - case 175: + case 178: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1044 + //line sql.y:1059 { yyVAL.str = CrossJoinStr } - case 176: + case 179: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1050 + //line sql.y:1065 { yyVAL.str = LeftJoinStr } - case 177: + case 180: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1054 + //line sql.y:1069 { yyVAL.str = LeftJoinStr } - case 178: + case 181: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1060 + //line sql.y:1075 { yyVAL.str = NaturalJoinStr } - case 179: + case 182: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1064 + //line sql.y:1079 { yyVAL.str = NaturalLeftJoinStr } - case 180: + case 183: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1070 + //line sql.y:1085 { yyVAL.tableName = yyDollar[2].tableName } - case 181: + case 184: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1074 + //line sql.y:1089 { yyVAL.tableName = yyDollar[1].tableName } - case 182: + case 185: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1080 + //line sql.y:1095 { yyVAL.tableName = TableName{Name: yyDollar[1].tableIdent} } - case 183: + case 186: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1084 + //line sql.y:1099 { yyVAL.tableName = TableName{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].tableIdent} } - case 184: + case 187: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1089 + //line sql.y:1104 { yyVAL.expr = nil } - case 185: + case 188: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1093 + //line sql.y:1108 { yyVAL.expr = yyDollar[2].expr } - case 186: + case 189: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1099 + //line sql.y:1114 { yyVAL.expr = yyDollar[1].expr } - case 187: + case 190: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1103 + //line sql.y:1118 { yyVAL.expr = &AndExpr{Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 188: + case 191: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1107 + //line sql.y:1122 { yyVAL.expr = &OrExpr{Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 189: + case 192: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1111 + //line sql.y:1126 { yyVAL.expr = &NotExpr{Expr: yyDollar[2].expr} } - case 190: + case 193: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1115 + //line sql.y:1130 { yyVAL.expr = &IsExpr{Operator: yyDollar[3].str, Expr: yyDollar[1].expr} } - case 191: + case 194: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1119 + //line sql.y:1134 { yyVAL.expr = yyDollar[1].expr } - case 192: + case 195: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1123 + //line sql.y:1138 { yyVAL.expr = &Default{ColName: yyDollar[2].str} } - case 193: + case 196: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1129 + //line sql.y:1144 { yyVAL.str = "" } - case 194: + case 197: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1133 + //line sql.y:1148 { yyVAL.str = string(yyDollar[2].bytes) } - case 195: + case 198: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1139 + //line sql.y:1154 { yyVAL.boolVal = BoolVal(true) } - case 196: + case 199: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1143 + //line sql.y:1158 { yyVAL.boolVal = BoolVal(false) } - case 197: + case 200: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1149 + //line sql.y:1164 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: yyDollar[2].str, Right: yyDollar[3].expr} } - case 198: + case 201: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1153 + //line sql.y:1168 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: InStr, Right: yyDollar[3].colTuple} } - case 199: + case 202: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1157 + //line sql.y:1172 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: NotInStr, Right: yyDollar[4].colTuple} } - case 200: + case 203: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1161 + //line sql.y:1176 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: LikeStr, Right: yyDollar[3].expr, Escape: yyDollar[4].expr} } - case 201: + case 204: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:1165 + //line sql.y:1180 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: NotLikeStr, Right: yyDollar[4].expr, Escape: yyDollar[5].expr} } - case 202: + case 205: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1169 + //line sql.y:1184 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: RegexpStr, Right: yyDollar[3].expr} } - case 203: + case 206: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1173 + //line sql.y:1188 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: NotRegexpStr, Right: yyDollar[4].expr} } - case 204: + case 207: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:1177 + //line sql.y:1192 { yyVAL.expr = &RangeCond{Left: yyDollar[1].expr, Operator: BetweenStr, From: yyDollar[3].expr, To: yyDollar[5].expr} } - case 205: + case 208: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:1181 + //line sql.y:1196 { yyVAL.expr = &RangeCond{Left: yyDollar[1].expr, Operator: NotBetweenStr, From: yyDollar[4].expr, To: yyDollar[6].expr} } - case 206: + case 209: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1185 + //line sql.y:1200 { yyVAL.expr = &ExistsExpr{Subquery: yyDollar[2].subquery} } - case 207: + case 210: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1191 + //line sql.y:1206 { yyVAL.str = IsNullStr } - case 208: + case 211: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1195 + //line sql.y:1210 { yyVAL.str = IsNotNullStr } - case 209: + case 212: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1199 + //line sql.y:1214 { yyVAL.str = IsTrueStr } - case 210: + case 213: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1203 + //line sql.y:1218 { yyVAL.str = IsNotTrueStr } - case 211: + case 214: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1207 + //line sql.y:1222 { yyVAL.str = IsFalseStr } - case 212: + case 215: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1211 + //line sql.y:1226 { yyVAL.str = IsNotFalseStr } - case 213: + case 216: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1217 + //line sql.y:1232 { yyVAL.str = EqualStr } - case 214: + case 217: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1221 + //line sql.y:1236 { yyVAL.str = LessThanStr } - case 215: + case 218: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1225 + //line sql.y:1240 { yyVAL.str = GreaterThanStr } - case 216: + case 219: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1229 + //line sql.y:1244 { yyVAL.str = LessEqualStr } - case 217: + case 220: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1233 + //line sql.y:1248 { yyVAL.str = GreaterEqualStr } - case 218: + case 221: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1237 + //line sql.y:1252 { yyVAL.str = NotEqualStr } - case 219: + case 222: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1241 + //line sql.y:1256 { yyVAL.str = NullSafeNotEqualStr } - case 220: + case 223: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1246 + //line sql.y:1261 { yyVAL.expr = nil } - case 221: + case 224: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1250 + //line sql.y:1265 { yyVAL.expr = yyDollar[2].expr } - case 222: + case 225: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1256 + //line sql.y:1271 { yyVAL.colTuple = yyDollar[1].valTuple } - case 223: + case 226: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1260 + //line sql.y:1275 { yyVAL.colTuple = yyDollar[1].subquery } - case 224: + case 227: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1264 + //line sql.y:1279 { yyVAL.colTuple = ListArg(yyDollar[1].bytes) } - case 225: + case 228: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1270 + //line sql.y:1285 { yyVAL.subquery = &Subquery{yyDollar[2].selStmt} } - case 226: + case 229: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1276 + //line sql.y:1291 { yyVAL.exprs = Exprs{yyDollar[1].expr} } - case 227: + case 230: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1280 + //line sql.y:1295 { yyVAL.exprs = append(yyDollar[1].exprs, yyDollar[3].expr) } - case 228: + case 231: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1286 + //line sql.y:1301 { yyVAL.expr = yyDollar[1].expr } - case 229: + case 232: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1290 + //line sql.y:1305 { yyVAL.expr = yyDollar[1].boolVal } - case 230: + case 233: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1294 + //line sql.y:1309 { yyVAL.expr = yyDollar[1].colName } - case 231: + case 234: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1298 + //line sql.y:1313 { yyVAL.expr = yyDollar[1].expr } - case 232: + case 235: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1302 + //line sql.y:1317 { yyVAL.expr = yyDollar[1].subquery } - case 233: + case 236: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1306 + //line sql.y:1321 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: BitAndStr, Right: yyDollar[3].expr} } - case 234: + case 237: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1310 + //line sql.y:1325 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: BitOrStr, Right: yyDollar[3].expr} } - case 235: + case 238: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1314 + //line sql.y:1329 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: BitXorStr, Right: yyDollar[3].expr} } - case 236: + case 239: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1318 + //line sql.y:1333 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: PlusStr, Right: yyDollar[3].expr} } - case 237: + case 240: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1322 + //line sql.y:1337 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: MinusStr, Right: yyDollar[3].expr} } - case 238: + case 241: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1326 + //line sql.y:1341 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: MultStr, Right: yyDollar[3].expr} } - case 239: + case 242: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1330 + //line sql.y:1345 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: DivStr, Right: yyDollar[3].expr} } - case 240: + case 243: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1334 + //line sql.y:1349 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: IntDivStr, Right: yyDollar[3].expr} } - case 241: + case 244: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1338 + //line sql.y:1353 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ModStr, Right: yyDollar[3].expr} } - case 242: + case 245: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1342 + //line sql.y:1357 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ModStr, Right: yyDollar[3].expr} } - case 243: + case 246: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1346 + //line sql.y:1361 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ShiftLeftStr, Right: yyDollar[3].expr} } - case 244: + case 247: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1350 + //line sql.y:1365 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ShiftRightStr, Right: yyDollar[3].expr} } - case 245: + case 248: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1354 + //line sql.y:1369 { if num, ok := yyDollar[2].expr.(*SQLVal); ok && num.Type == IntVal { yyVAL.expr = num @@ -2996,9 +3031,9 @@ yydefault: yyVAL.expr = &UnaryExpr{Operator: UPlusStr, Expr: yyDollar[2].expr} } } - case 246: + case 249: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1362 + //line sql.y:1377 { if num, ok := yyDollar[2].expr.(*SQLVal); ok && num.Type == IntVal { // Handle double negative @@ -3012,21 +3047,21 @@ yydefault: yyVAL.expr = &UnaryExpr{Operator: UMinusStr, Expr: yyDollar[2].expr} } } - case 247: + case 250: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1376 + //line sql.y:1391 { yyVAL.expr = &UnaryExpr{Operator: TildaStr, Expr: yyDollar[2].expr} } - case 248: + case 251: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1380 + //line sql.y:1395 { yyVAL.expr = &UnaryExpr{Operator: BangStr, Expr: yyDollar[2].expr} } - case 249: + case 252: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1384 + //line sql.y:1399 { // This rule prevents the usage of INTERVAL // as a function. If support is needed for that, @@ -3034,505 +3069,505 @@ yydefault: // will be non-trivial because of grammar conflicts. yyVAL.expr = &IntervalExpr{Expr: yyDollar[2].expr, Unit: yyDollar[3].colIdent.String()} } - case 254: + case 257: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1402 + //line sql.y:1417 { yyVAL.expr = &FuncExpr{Name: yyDollar[1].colIdent, Exprs: yyDollar[3].selectExprs} } - case 255: + case 258: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:1406 + //line sql.y:1421 { yyVAL.expr = &FuncExpr{Name: yyDollar[1].colIdent, Distinct: true, Exprs: yyDollar[4].selectExprs} } - case 256: + case 259: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:1410 + //line sql.y:1425 { yyVAL.expr = &FuncExpr{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].colIdent, Exprs: yyDollar[5].selectExprs} } - case 257: + case 260: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:1420 + //line sql.y:1435 { yyVAL.expr = &ConvertExpr{Expr: yyDollar[3].expr, Type: yyDollar[5].convertType} } - case 258: + case 261: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:1424 + //line sql.y:1439 { yyVAL.expr = &SubstrExpr{Name: yyDollar[3].colName, From: yyDollar[5].expr, To: nil} } - case 259: + case 262: yyDollar = yyS[yypt-8 : yypt+1] - //line sql.y:1428 + //line sql.y:1443 { yyVAL.expr = &SubstrExpr{Name: yyDollar[3].colName, From: yyDollar[5].expr, To: yyDollar[7].expr} } - case 260: + case 263: yyDollar = yyS[yypt-7 : yypt+1] - //line sql.y:1432 + //line sql.y:1447 { yyVAL.expr = &GroupConcatExpr{Distinct: yyDollar[3].str, Exprs: yyDollar[4].selectExprs, OrderBy: yyDollar[5].orderBy, Separator: yyDollar[6].str} } - case 261: + case 264: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:1436 + //line sql.y:1451 { yyVAL.expr = &CaseExpr{Expr: yyDollar[2].expr, Whens: yyDollar[3].whens, Else: yyDollar[4].expr} } - case 262: + case 265: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1440 + //line sql.y:1455 { yyVAL.expr = &ValuesFuncExpr{Name: yyDollar[3].colName} } - case 263: + case 266: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1450 + //line sql.y:1465 { yyVAL.expr = &TimeExpr{Expr: NewColIdent("current_timestamp")} } - case 264: + case 267: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1455 + //line sql.y:1470 { yyVAL.expr = &TimeExpr{Expr: NewColIdent("current_date")} } - case 265: + case 268: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1460 + //line sql.y:1475 { yyVAL.expr = &TimeExpr{Expr: NewColIdent("current_time")} } - case 266: + case 269: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1470 + //line sql.y:1485 { yyVAL.expr = &FuncExpr{Name: NewColIdent("if"), Exprs: yyDollar[3].selectExprs} } - case 267: + case 270: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1474 + //line sql.y:1489 { yyVAL.expr = &FuncExpr{Name: NewColIdent("mod"), Exprs: yyDollar[3].selectExprs} } - case 268: + case 271: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1478 + //line sql.y:1493 { yyVAL.expr = &FuncExpr{Name: NewColIdent("replace"), Exprs: yyDollar[3].selectExprs} } - case 269: + case 272: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1484 + //line sql.y:1499 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } - case 270: + case 273: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1488 + //line sql.y:1503 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } - case 271: + case 274: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1492 + //line sql.y:1507 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } - case 272: + case 275: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1496 + //line sql.y:1511 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} yyVAL.convertType.Length = yyDollar[2].LengthScaleOption.Length yyVAL.convertType.Scale = yyDollar[2].LengthScaleOption.Scale } - case 273: + case 276: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1502 + //line sql.y:1517 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } - case 274: + case 277: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1506 + //line sql.y:1521 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } - case 275: + case 278: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1510 + //line sql.y:1525 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } - case 276: + case 279: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1514 + //line sql.y:1529 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } - case 277: + case 280: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1518 + //line sql.y:1533 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } - case 278: + case 281: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1522 + //line sql.y:1537 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } - case 279: + case 282: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1526 + //line sql.y:1541 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } - case 280: + case 283: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1530 + //line sql.y:1545 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } - case 281: + case 284: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1534 + //line sql.y:1549 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } - case 282: + case 285: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1538 + //line sql.y:1553 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } - case 283: + case 286: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1542 + //line sql.y:1557 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } - case 284: + case 287: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1546 + //line sql.y:1561 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].optVal} } - case 285: + case 288: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1550 + //line sql.y:1565 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } - case 286: + case 289: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1555 + //line sql.y:1570 { yyVAL.expr = nil } - case 287: + case 290: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1559 + //line sql.y:1574 { yyVAL.expr = yyDollar[1].expr } - case 288: + case 291: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1564 + //line sql.y:1579 { yyVAL.str = string("") } - case 289: + case 292: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1568 + //line sql.y:1583 { yyVAL.str = " separator '" + string(yyDollar[2].bytes) + "'" } - case 290: + case 293: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1574 + //line sql.y:1589 { yyVAL.whens = []*When{yyDollar[1].when} } - case 291: + case 294: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1578 + //line sql.y:1593 { yyVAL.whens = append(yyDollar[1].whens, yyDollar[2].when) } - case 292: + case 295: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1584 + //line sql.y:1599 { yyVAL.when = &When{Cond: yyDollar[2].expr, Val: yyDollar[4].expr} } - case 293: + case 296: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1589 + //line sql.y:1604 { yyVAL.expr = nil } - case 294: + case 297: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1593 + //line sql.y:1608 { yyVAL.expr = yyDollar[2].expr } - case 295: + case 298: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1599 + //line sql.y:1614 { yyVAL.colName = &ColName{Name: yyDollar[1].colIdent} } - case 296: + case 299: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1603 + //line sql.y:1618 { yyVAL.colName = &ColName{Qualifier: TableName{Name: yyDollar[1].tableIdent}, Name: yyDollar[3].colIdent} } - case 297: + case 300: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:1607 + //line sql.y:1622 { yyVAL.colName = &ColName{Qualifier: TableName{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].tableIdent}, Name: yyDollar[5].colIdent} } - case 298: + case 301: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1613 + //line sql.y:1628 { yyVAL.expr = NewStrVal(yyDollar[1].bytes) } - case 299: + case 302: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1617 + //line sql.y:1632 { yyVAL.expr = NewHexVal(yyDollar[1].bytes) } - case 300: + case 303: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1621 + //line sql.y:1636 { yyVAL.expr = NewIntVal(yyDollar[1].bytes) } - case 301: + case 304: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1625 + //line sql.y:1640 { yyVAL.expr = NewFloatVal(yyDollar[1].bytes) } - case 302: + case 305: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1629 + //line sql.y:1644 { yyVAL.expr = NewHexNum(yyDollar[1].bytes) } - case 303: + case 306: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1633 + //line sql.y:1648 { yyVAL.expr = NewValArg(yyDollar[1].bytes) } - case 304: + case 307: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1637 + //line sql.y:1652 { yyVAL.expr = &NullVal{} } - case 305: + case 308: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1642 + //line sql.y:1657 { yyVAL.exprs = nil } - case 306: + case 309: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1646 + //line sql.y:1661 { yyVAL.exprs = yyDollar[3].exprs } - case 307: + case 310: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1651 + //line sql.y:1666 { yyVAL.expr = nil } - case 308: + case 311: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1655 + //line sql.y:1670 { yyVAL.expr = yyDollar[2].expr } - case 309: + case 312: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1660 + //line sql.y:1675 { yyVAL.orderBy = nil } - case 310: + case 313: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1664 + //line sql.y:1679 { yyVAL.orderBy = yyDollar[3].orderBy } - case 311: + case 314: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1670 + //line sql.y:1685 { yyVAL.orderBy = OrderBy{yyDollar[1].order} } - case 312: + case 315: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1674 + //line sql.y:1689 { yyVAL.orderBy = append(yyDollar[1].orderBy, yyDollar[3].order) } - case 313: + case 316: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1680 + //line sql.y:1695 { yyVAL.order = &Order{Expr: yyDollar[1].expr, Direction: yyDollar[2].str} } - case 314: + case 317: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1685 + //line sql.y:1700 { yyVAL.str = AscScr } - case 315: + case 318: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1689 + //line sql.y:1704 { yyVAL.str = AscScr } - case 316: + case 319: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1693 + //line sql.y:1708 { yyVAL.str = DescScr } - case 317: + case 320: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1698 + //line sql.y:1713 { yyVAL.limit = nil } - case 318: + case 321: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1702 + //line sql.y:1717 { yyVAL.limit = &Limit{Rowcount: yyDollar[2].expr} } - case 319: + case 322: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1706 + //line sql.y:1721 { yyVAL.limit = &Limit{Offset: yyDollar[2].expr, Rowcount: yyDollar[4].expr} } - case 320: + case 323: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1710 + //line sql.y:1725 { yyVAL.limit = &Limit{Offset: yyDollar[4].expr, Rowcount: yyDollar[2].expr} } - case 321: + case 324: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1723 + //line sql.y:1738 { yyVAL.ins = &Insert{Rows: yyDollar[2].values} } - case 322: + case 325: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1727 + //line sql.y:1742 { yyVAL.ins = &Insert{Rows: yyDollar[1].selStmt} } - case 323: + case 326: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1731 + //line sql.y:1746 { // Drop the redundant parenthesis. yyVAL.ins = &Insert{Rows: yyDollar[2].selStmt} } - case 324: + case 327: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:1736 + //line sql.y:1751 { yyVAL.ins = &Insert{Columns: yyDollar[2].columns, Rows: yyDollar[5].values} } - case 325: + case 328: yyDollar = yyS[yypt-4 : yypt+1] - //line sql.y:1740 + //line sql.y:1755 { yyVAL.ins = &Insert{Columns: yyDollar[2].columns, Rows: yyDollar[4].selStmt} } - case 326: + case 329: yyDollar = yyS[yypt-6 : yypt+1] - //line sql.y:1744 + //line sql.y:1759 { // Drop the redundant parenthesis. yyVAL.ins = &Insert{Columns: yyDollar[2].columns, Rows: yyDollar[5].selStmt} } - case 327: + case 330: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1751 + //line sql.y:1766 { yyVAL.columns = Columns{yyDollar[1].colIdent} } - case 328: + case 331: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1755 + //line sql.y:1770 { yyVAL.columns = Columns{yyDollar[3].colIdent} } - case 329: + case 332: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1759 + //line sql.y:1774 { yyVAL.columns = append(yyVAL.columns, yyDollar[3].colIdent) } - case 330: + case 333: yyDollar = yyS[yypt-5 : yypt+1] - //line sql.y:1763 + //line sql.y:1778 { yyVAL.columns = append(yyVAL.columns, yyDollar[5].colIdent) } - case 331: + case 334: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1769 + //line sql.y:1784 { yyVAL.values = Values{yyDollar[1].valTuple} } - case 332: + case 335: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1773 + //line sql.y:1788 { yyVAL.values = append(yyDollar[1].values, yyDollar[3].valTuple) } - case 333: + case 336: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1779 + //line sql.y:1794 { yyVAL.valTuple = yyDollar[1].valTuple } - case 334: + case 337: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1783 + //line sql.y:1798 { yyVAL.valTuple = ValTuple{} } - case 335: + case 338: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1789 + //line sql.y:1804 { yyVAL.valTuple = ValTuple(yyDollar[2].exprs) } - case 336: + case 339: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1795 + //line sql.y:1810 { if len(yyDollar[1].valTuple) == 1 { yyVAL.expr = &ParenExpr{yyDollar[1].valTuple[0]} @@ -3540,144 +3575,144 @@ yydefault: yyVAL.expr = yyDollar[1].valTuple } } - case 337: + case 340: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1805 + //line sql.y:1820 { yyVAL.updateExprs = UpdateExprs{yyDollar[1].updateExpr} } - case 338: + case 341: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1809 + //line sql.y:1824 { yyVAL.updateExprs = append(yyDollar[1].updateExprs, yyDollar[3].updateExpr) } - case 339: + case 342: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1815 + //line sql.y:1830 { yyVAL.updateExpr = &UpdateExpr{Name: yyDollar[1].colName, Expr: yyDollar[3].expr} } - case 340: + case 343: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1820 + //line sql.y:1835 { yyVAL.byt = 0 } - case 341: + case 344: yyDollar = yyS[yypt-2 : yypt+1] - //line sql.y:1822 + //line sql.y:1837 { yyVAL.byt = 1 } - case 342: + case 345: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1825 + //line sql.y:1840 { yyVAL.empty = struct{}{} } - case 343: + case 346: yyDollar = yyS[yypt-3 : yypt+1] - //line sql.y:1827 + //line sql.y:1842 { yyVAL.empty = struct{}{} } - case 344: + case 347: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1830 + //line sql.y:1845 { yyVAL.str = "" } - case 345: + case 348: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1832 + //line sql.y:1847 { yyVAL.str = IgnoreStr } - case 346: + case 349: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:1835 + //line sql.y:1850 { yyVAL.empty = struct{}{} } - case 347: + case 350: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1837 + //line sql.y:1852 { yyVAL.empty = struct{}{} } - case 348: + case 351: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1839 + //line sql.y:1854 { yyVAL.empty = struct{}{} } - case 349: + case 352: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1843 + //line sql.y:1858 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } - case 350: + case 353: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1847 + //line sql.y:1862 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } - case 352: + case 355: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1854 + //line sql.y:1869 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } - case 353: + case 356: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1860 + //line sql.y:1875 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } - case 354: + case 357: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1864 + //line sql.y:1879 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } - case 356: + case 359: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:1871 + //line sql.y:1886 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } - case 464: + case 467: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2004 + //line sql.y:2019 { if incNesting(yylex) { yylex.Error("max nesting level reached") return 1 } } - case 465: + case 468: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2013 + //line sql.y:2028 { decNesting(yylex) } - case 466: + case 469: yyDollar = yyS[yypt-0 : yypt+1] - //line sql.y:2018 + //line sql.y:2033 { forceEOF(yylex) } - case 467: + case 470: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2022 + //line sql.y:2037 { forceEOF(yylex) } - case 468: + case 471: yyDollar = yyS[yypt-1 : yypt+1] - //line sql.y:2026 + //line sql.y:2041 { forceEOF(yylex) } diff --git a/vendor/github.com/CovenantSQL/sqlparser/sql.y b/vendor/github.com/CovenantSQL/sqlparser/sql.y index b0199ec56..6e70d8a16 100644 --- a/vendor/github.com/CovenantSQL/sqlparser/sql.y +++ b/vendor/github.com/CovenantSQL/sqlparser/sql.y @@ -112,6 +112,7 @@ func forceEOF(yylex interface{}) { %token '(' ',' ')' %token ID HEX STRING INTEGRAL FLOAT HEXNUM VALUE_ARG LIST_ARG COMMENT %token NULL TRUE FALSE +%token FULL COLUMNS // Precedence dictated by mysql. But the vitess grammar is simplified. // Some of these operators don't conflict in our situation. Nevertheless, @@ -232,6 +233,7 @@ func forceEOF(yylex interface{}) { %type index_column %type index_column_list %type alter_object_type +%type full_opt %start any_command @@ -360,10 +362,10 @@ create_statement: $1.TableSpec = $2 $$ = $1 } -| CREATE constraint_opt INDEX ID ON table_name ddl_force_eof +| CREATE constraint_opt INDEX not_exists_opt ID ON table_name ddl_force_eof { // Change this to an alter statement - $$ = &DDL{Action: CreateIndexStr, Table: $6, NewName:$6} + $$ = &DDL{Action: CreateIndexStr, Table: $7, NewName:$7} } create_table_prefix: @@ -816,9 +818,22 @@ SHOW CREATE TABLE table_name { $$ = &Show{Type: string($2), OnTable: $3} } -| SHOW TABLES +| SHOW full_opt TABLES { - $$ = &Show{Type: string($2)} + $$ = &Show{Type: string($3)} + } +| SHOW full_opt COLUMNS FROM table_name + { + $$ = &Show{Type: "table", OnTable: $5} + } + +full_opt: + { + $$ = nil + } +| FULL + { + $$ = nil } other_statement: diff --git a/vendor/github.com/CovenantSQL/sqlparser/token.go b/vendor/github.com/CovenantSQL/sqlparser/token.go index 53ec0c9d3..8dfc057fa 100644 --- a/vendor/github.com/CovenantSQL/sqlparser/token.go +++ b/vendor/github.com/CovenantSQL/sqlparser/token.go @@ -107,6 +107,7 @@ var keywords = map[string]int{ "char": CHAR, "check": UNUSED, "column": COLUMN, + "columns": COLUMNS, "condition": UNUSED, "constraint": CONSTRAINT, "continue": UNUSED, @@ -154,6 +155,7 @@ var keywords = map[string]int{ "float8": UNUSED, "foreign": FOREIGN, "from": FROM, + "full": FULL, "generated": UNUSED, "get": UNUSED, "grant": UNUSED, diff --git a/vendor/github.com/cyberdelia/go-metrics-graphite/AUTHORS b/vendor/github.com/cyberdelia/go-metrics-graphite/AUTHORS new file mode 100644 index 000000000..b430b78ea --- /dev/null +++ b/vendor/github.com/cyberdelia/go-metrics-graphite/AUTHORS @@ -0,0 +1,8 @@ +These people have provided bug fixes, new features or improved the documentation. + +* Daniel Garcia +* Peter Teichman +* Phillip Kovalev +* Richard Crowley +* Timothée Peignier +* Tomás Senart diff --git a/vendor/github.com/cyberdelia/go-metrics-graphite/LICENSE b/vendor/github.com/cyberdelia/go-metrics-graphite/LICENSE new file mode 100644 index 000000000..fdfc8abff --- /dev/null +++ b/vendor/github.com/cyberdelia/go-metrics-graphite/LICENSE @@ -0,0 +1,22 @@ +Copyright 2015 Timothée Peignier. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/cyberdelia/go-metrics-graphite/README.md b/vendor/github.com/cyberdelia/go-metrics-graphite/README.md new file mode 100644 index 000000000..96ee1482d --- /dev/null +++ b/vendor/github.com/cyberdelia/go-metrics-graphite/README.md @@ -0,0 +1,19 @@ +This is a reporter for the [go-metrics](https://github.com/rcrowley/go-metrics) +library which will post the metrics to Graphite. It was originally part of the +`go-metrics` library itself, but has been split off to make maintenance of +both the core library and the client easier. + +### Usage + +```go +import "github.com/cyberdelia/go-metrics-graphite" + + +go graphite.Graphite(metrics.DefaultRegistry, + 1*time.Second, "some.prefix", addr) +``` + +### Migrating from `rcrowley/go-metrics` implementation + +Simply modify the import from `"github.com/rcrowley/go-metrics/graphite"` to +`"github.com/cyberdelia/go-metrics-graphite"` and it should Just Work. diff --git a/vendor/github.com/cyberdelia/go-metrics-graphite/graphite.go b/vendor/github.com/cyberdelia/go-metrics-graphite/graphite.go new file mode 100644 index 000000000..4489f0beb --- /dev/null +++ b/vendor/github.com/cyberdelia/go-metrics-graphite/graphite.go @@ -0,0 +1,120 @@ +package graphite + +import ( + "bufio" + "fmt" + "log" + "net" + "strconv" + "strings" + "time" + + "github.com/rcrowley/go-metrics" +) + +// Config provides a container with configuration parameters for +// the Graphite exporter +type Config struct { + Addr *net.TCPAddr // Network address to connect to + Registry metrics.Registry // Registry to be exported + FlushInterval time.Duration // Flush interval + DurationUnit time.Duration // Time conversion unit for durations + Prefix string // Prefix to be prepended to metric names + Percentiles []float64 // Percentiles to export from timers and histograms +} + +// Graphite is a blocking exporter function which reports metrics in r +// to a graphite server located at addr, flushing them every d duration +// and prepending metric names with prefix. +func Graphite(r metrics.Registry, d time.Duration, prefix string, addr *net.TCPAddr) { + WithConfig(Config{ + Addr: addr, + Registry: r, + FlushInterval: d, + DurationUnit: time.Nanosecond, + Prefix: prefix, + Percentiles: []float64{0.5, 0.75, 0.95, 0.99, 0.999}, + }) +} + +// WithConfig is a blocking exporter function just like Graphite, +// but it takes a GraphiteConfig instead. +func WithConfig(c Config) { + for _ = range time.Tick(c.FlushInterval) { + if err := graphite(&c); nil != err { + log.Println(err) + } + } +} + +// Once performs a single submission to Graphite, returning a +// non-nil error on failed connections. This can be used in a loop +// similar to GraphiteWithConfig for custom error handling. +func Once(c Config) error { + return graphite(&c) +} + +func graphite(c *Config) error { + now := time.Now().Unix() + du := float64(c.DurationUnit) + flushSeconds := float64(c.FlushInterval) / float64(time.Second) + conn, err := net.DialTCP("tcp", nil, c.Addr) + if nil != err { + return err + } + defer conn.Close() + w := bufio.NewWriter(conn) + c.Registry.Each(func(name string, i interface{}) { + switch metric := i.(type) { + case metrics.Counter: + count := metric.Count() + fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, count, now) + fmt.Fprintf(w, "%s.%s.count_ps %.2f %d\n", c.Prefix, name, float64(count)/flushSeconds, now) + case metrics.Gauge: + fmt.Fprintf(w, "%s.%s.value %d %d\n", c.Prefix, name, metric.Value(), now) + case metrics.GaugeFloat64: + fmt.Fprintf(w, "%s.%s.value %f %d\n", c.Prefix, name, metric.Value(), now) + case metrics.Histogram: + h := metric.Snapshot() + ps := h.Percentiles(c.Percentiles) + fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, h.Count(), now) + fmt.Fprintf(w, "%s.%s.min %d %d\n", c.Prefix, name, h.Min(), now) + fmt.Fprintf(w, "%s.%s.max %d %d\n", c.Prefix, name, h.Max(), now) + fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, h.Mean(), now) + fmt.Fprintf(w, "%s.%s.std-dev %.2f %d\n", c.Prefix, name, h.StdDev(), now) + for psIdx, psKey := range c.Percentiles { + key := strings.Replace(strconv.FormatFloat(psKey*100.0, 'f', -1, 64), ".", "", 1) + fmt.Fprintf(w, "%s.%s.%s-percentile %.2f %d\n", c.Prefix, name, key, ps[psIdx], now) + } + case metrics.Meter: + m := metric.Snapshot() + fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, m.Count(), now) + fmt.Fprintf(w, "%s.%s.one-minute %.2f %d\n", c.Prefix, name, m.Rate1(), now) + fmt.Fprintf(w, "%s.%s.five-minute %.2f %d\n", c.Prefix, name, m.Rate5(), now) + fmt.Fprintf(w, "%s.%s.fifteen-minute %.2f %d\n", c.Prefix, name, m.Rate15(), now) + fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, m.RateMean(), now) + case metrics.Timer: + t := metric.Snapshot() + ps := t.Percentiles(c.Percentiles) + count := t.Count() + fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, count, now) + fmt.Fprintf(w, "%s.%s.count_ps %.2f %d\n", c.Prefix, name, float64(count)/flushSeconds, now) + fmt.Fprintf(w, "%s.%s.min %d %d\n", c.Prefix, name, t.Min()/int64(du), now) + fmt.Fprintf(w, "%s.%s.max %d %d\n", c.Prefix, name, t.Max()/int64(du), now) + fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, t.Mean()/du, now) + fmt.Fprintf(w, "%s.%s.std-dev %.2f %d\n", c.Prefix, name, t.StdDev()/du, now) + for psIdx, psKey := range c.Percentiles { + key := strings.Replace(strconv.FormatFloat(psKey*100.0, 'f', -1, 64), ".", "", 1) + fmt.Fprintf(w, "%s.%s.%s-percentile %.2f %d\n", c.Prefix, name, key, ps[psIdx]/du, now) + } + fmt.Fprintf(w, "%s.%s.one-minute %.2f %d\n", c.Prefix, name, t.Rate1(), now) + fmt.Fprintf(w, "%s.%s.five-minute %.2f %d\n", c.Prefix, name, t.Rate5(), now) + fmt.Fprintf(w, "%s.%s.fifteen-minute %.2f %d\n", c.Prefix, name, t.Rate15(), now) + fmt.Fprintf(w, "%s.%s.mean-rate %.2f %d\n", c.Prefix, name, t.RateMean(), now) + default: + log.Printf("unable to record metric of type %T\n", i) + } + w.Flush() + }) + return nil +} diff --git a/vendor/github.com/hashicorp/yamux/.gitignore b/vendor/github.com/hashicorp/yamux/.gitignore deleted file mode 100644 index 836562412..000000000 --- a/vendor/github.com/hashicorp/yamux/.gitignore +++ /dev/null @@ -1,23 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test diff --git a/vendor/github.com/hashicorp/yamux/LICENSE b/vendor/github.com/hashicorp/yamux/LICENSE deleted file mode 100644 index f0e5c79e1..000000000 --- a/vendor/github.com/hashicorp/yamux/LICENSE +++ /dev/null @@ -1,362 +0,0 @@ -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. "Contributor" - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. "Contributor Version" - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the terms of - a Secondary License. - -1.6. "Executable Form" - - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - - means a work that combines Covered Software with other material, in a - separate file or files, that is not Covered Software. - -1.8. "License" - - means this document. - -1.9. "Licensable" - - means having the right to grant, to the maximum extent possible, whether - at the time of the initial grant or subsequently, any and all of the - rights conveyed by this License. - -1.10. "Modifications" - - means any of the following: - - a. any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. "Patent Claims" of a Contributor - - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the License, - by the making, using, selling, offering for sale, having made, import, - or transfer of either its Contributions or its Contributor Version. - -1.12. "Secondary License" - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. "Source Code Form" - - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, "control" means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution - become effective for each Contribution on the date the Contributor first - distributes such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under - this License. No additional rights or licenses will be implied from the - distribution or licensing of Covered Software under this License. - Notwithstanding Section 2.1(b) above, no patent license is granted by a - Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of - its Contributions. - - This License does not grant any rights in the trademarks, service marks, - or logos of any Contributor (except as may be necessary to comply with - the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this - License (see Section 10.2) or under the terms of a Secondary License (if - permitted under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its - Contributions are its original creation(s) or it has sufficient rights to - grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under - applicable copyright doctrines of fair use, fair dealing, or other - equivalents. - -2.7. Conditions - - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. - - -3. Responsibilities - -3.1. Distribution of Source Form - - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under - the terms of this License. You must inform recipients that the Source - Code Form of the Covered Software is governed by the terms of this - License, and how they can obtain a copy of this License. You may not - attempt to alter or restrict the recipients' rights in the Source Code - Form. - -3.2. Distribution of Executable Form - - If You distribute Covered Software in Executable Form then: - - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and - - b. You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter the - recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for - the Covered Software. If the Larger Work is a combination of Covered - Software with a work governed by one or more Secondary Licenses, and the - Covered Software is not Incompatible With Secondary Licenses, this - License permits You to additionally distribute such Covered Software - under the terms of such Secondary License(s), so that the recipient of - the Larger Work may, at their option, further distribute the Covered - Software under the terms of either this License or such Secondary - License(s). - -3.4. Notices - - You may not remove or alter the substance of any license notices - (including copyright notices, patent notices, disclaimers of warranty, or - limitations of liability) contained within the Source Code Form of the - Covered Software, except that You may alter any license notices to the - extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on - behalf of any Contributor. You must make it absolutely clear that any - such warranty, support, indemnity, or liability obligation is offered by - You alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - -4. Inability to Comply Due to Statute or Regulation - - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, - judicial order, or regulation then You must: (a) comply with the terms of - this License to the maximum extent possible; and (b) describe the - limitations and the code they affect. Such description must be placed in a - text file included with all distributions of the Covered Software under - this License. Except to the extent prohibited by statute or regulation, - such description must be sufficiently detailed for a recipient of ordinary - skill to be able to understand it. - -5. Termination - -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing - basis, if such Contributor fails to notify You of the non-compliance by - some reasonable means prior to 60 days after You have come back into - compliance. Moreover, Your grants from a particular Contributor are - reinstated on an ongoing basis if such Contributor notifies You of the - non-compliance by some reasonable means, this is the first time You have - received notice of non-compliance with this License from such - Contributor, and You become compliant prior to 30 days after Your receipt - of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, - counter-claims, and cross-claims) alleging that a Contributor Version - directly or indirectly infringes any patent, then the rights granted to - You by any and all Contributors for the Covered Software under Section - 2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. - -6. Disclaimer of Warranty - - Covered Software is provided under this License on an "as is" basis, - without warranty of any kind, either expressed, implied, or statutory, - including, without limitation, warranties that the Covered Software is free - of defects, merchantable, fit for a particular purpose or non-infringing. - The entire risk as to the quality and performance of the Covered Software - is with You. Should any Covered Software prove defective in any respect, - You (not any Contributor) assume the cost of any necessary servicing, - repair, or correction. This disclaimer of warranty constitutes an essential - part of this License. No use of any Covered Software is authorized under - this License except under this disclaimer. - -7. Limitation of Liability - - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from - such party's negligence to the extent applicable law prohibits such - limitation. Some jurisdictions do not allow the exclusion or limitation of - incidental or consequential damages, so this exclusion and limitation may - not apply to You. - -8. Litigation - - Any litigation relating to this License may be brought only in the courts - of a jurisdiction where the defendant maintains its principal place of - business and such litigation shall be governed by laws of that - jurisdiction, without reference to its conflict-of-law provisions. Nothing - in this Section shall prevent a party's ability to bring cross-claims or - counter-claims. - -9. Miscellaneous - - This License represents the complete agreement concerning the subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. Any law or regulation which provides that - the language of a contract shall be construed against the drafter shall not - be used to construe this License against a Contributor. - - -10. Versions of the License - -10.1. New Versions - - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - -10.2. Effect of New Versions - - You may distribute the Covered Software under the terms of the version - of the License under which You originally received the Covered Software, - or under the terms of any subsequent version published by the license - steward. - -10.3. Modified Versions - - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a - modified version of this License if you rename the license and remove - any references to the name of the license steward (except to note that - such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary - Licenses If You choose to distribute Source Code Form that is - Incompatible With Secondary Licenses under the terms of this version of - the License, the notice described in Exhibit B of this License must be - attached. - -Exhibit A - Source Code Form License Notice - - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular file, -then You may include the notice in a location (such as a LICENSE file in a -relevant directory) where a recipient would be likely to look for such a -notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice - - This Source Code Form is "Incompatible - With Secondary Licenses", as defined by - the Mozilla Public License, v. 2.0. \ No newline at end of file diff --git a/vendor/github.com/hashicorp/yamux/README.md b/vendor/github.com/hashicorp/yamux/README.md deleted file mode 100644 index d4db7fc99..000000000 --- a/vendor/github.com/hashicorp/yamux/README.md +++ /dev/null @@ -1,86 +0,0 @@ -# Yamux - -Yamux (Yet another Multiplexer) is a multiplexing library for Golang. -It relies on an underlying connection to provide reliability -and ordering, such as TCP or Unix domain sockets, and provides -stream-oriented multiplexing. It is inspired by SPDY but is not -interoperable with it. - -Yamux features include: - -* Bi-directional streams - * Streams can be opened by either client or server - * Useful for NAT traversal - * Server-side push support -* Flow control - * Avoid starvation - * Back-pressure to prevent overwhelming a receiver -* Keep Alives - * Enables persistent connections over a load balancer -* Efficient - * Enables thousands of logical streams with low overhead - -## Documentation - -For complete documentation, see the associated [Godoc](http://godoc.org/github.com/hashicorp/yamux). - -## Specification - -The full specification for Yamux is provided in the `spec.md` file. -It can be used as a guide to implementors of interoperable libraries. - -## Usage - -Using Yamux is remarkably simple: - -```go - -func client() { - // Get a TCP connection - conn, err := net.Dial(...) - if err != nil { - panic(err) - } - - // Setup client side of yamux - session, err := yamux.Client(conn, nil) - if err != nil { - panic(err) - } - - // Open a new stream - stream, err := session.Open() - if err != nil { - panic(err) - } - - // Stream implements net.Conn - stream.Write([]byte("ping")) -} - -func server() { - // Accept a TCP connection - conn, err := listener.Accept() - if err != nil { - panic(err) - } - - // Setup server side of yamux - session, err := yamux.Server(conn, nil) - if err != nil { - panic(err) - } - - // Accept a stream - stream, err := session.Accept() - if err != nil { - panic(err) - } - - // Listen for a message - buf := make([]byte, 4) - stream.Read(buf) -} - -``` - diff --git a/vendor/github.com/hashicorp/yamux/addr.go b/vendor/github.com/hashicorp/yamux/addr.go deleted file mode 100644 index be6ebca9c..000000000 --- a/vendor/github.com/hashicorp/yamux/addr.go +++ /dev/null @@ -1,60 +0,0 @@ -package yamux - -import ( - "fmt" - "net" -) - -// hasAddr is used to get the address from the underlying connection -type hasAddr interface { - LocalAddr() net.Addr - RemoteAddr() net.Addr -} - -// yamuxAddr is used when we cannot get the underlying address -type yamuxAddr struct { - Addr string -} - -func (*yamuxAddr) Network() string { - return "yamux" -} - -func (y *yamuxAddr) String() string { - return fmt.Sprintf("yamux:%s", y.Addr) -} - -// Addr is used to get the address of the listener. -func (s *Session) Addr() net.Addr { - return s.LocalAddr() -} - -// LocalAddr is used to get the local address of the -// underlying connection. -func (s *Session) LocalAddr() net.Addr { - addr, ok := s.conn.(hasAddr) - if !ok { - return &yamuxAddr{"local"} - } - return addr.LocalAddr() -} - -// RemoteAddr is used to get the address of remote end -// of the underlying connection -func (s *Session) RemoteAddr() net.Addr { - addr, ok := s.conn.(hasAddr) - if !ok { - return &yamuxAddr{"remote"} - } - return addr.RemoteAddr() -} - -// LocalAddr returns the local address -func (s *Stream) LocalAddr() net.Addr { - return s.session.LocalAddr() -} - -// LocalAddr returns the remote address -func (s *Stream) RemoteAddr() net.Addr { - return s.session.RemoteAddr() -} diff --git a/vendor/github.com/hashicorp/yamux/const.go b/vendor/github.com/hashicorp/yamux/const.go deleted file mode 100644 index 4f5293828..000000000 --- a/vendor/github.com/hashicorp/yamux/const.go +++ /dev/null @@ -1,157 +0,0 @@ -package yamux - -import ( - "encoding/binary" - "fmt" -) - -var ( - // ErrInvalidVersion means we received a frame with an - // invalid version - ErrInvalidVersion = fmt.Errorf("invalid protocol version") - - // ErrInvalidMsgType means we received a frame with an - // invalid message type - ErrInvalidMsgType = fmt.Errorf("invalid msg type") - - // ErrSessionShutdown is used if there is a shutdown during - // an operation - ErrSessionShutdown = fmt.Errorf("session shutdown") - - // ErrStreamsExhausted is returned if we have no more - // stream ids to issue - ErrStreamsExhausted = fmt.Errorf("streams exhausted") - - // ErrDuplicateStream is used if a duplicate stream is - // opened inbound - ErrDuplicateStream = fmt.Errorf("duplicate stream initiated") - - // ErrReceiveWindowExceeded indicates the window was exceeded - ErrRecvWindowExceeded = fmt.Errorf("recv window exceeded") - - // ErrTimeout is used when we reach an IO deadline - ErrTimeout = fmt.Errorf("i/o deadline reached") - - // ErrStreamClosed is returned when using a closed stream - ErrStreamClosed = fmt.Errorf("stream closed") - - // ErrUnexpectedFlag is set when we get an unexpected flag - ErrUnexpectedFlag = fmt.Errorf("unexpected flag") - - // ErrRemoteGoAway is used when we get a go away from the other side - ErrRemoteGoAway = fmt.Errorf("remote end is not accepting connections") - - // ErrConnectionReset is sent if a stream is reset. This can happen - // if the backlog is exceeded, or if there was a remote GoAway. - ErrConnectionReset = fmt.Errorf("connection reset") - - // ErrConnectionWriteTimeout indicates that we hit the "safety valve" - // timeout writing to the underlying stream connection. - ErrConnectionWriteTimeout = fmt.Errorf("connection write timeout") - - // ErrKeepAliveTimeout is sent if a missed keepalive caused the stream close - ErrKeepAliveTimeout = fmt.Errorf("keepalive timeout") -) - -const ( - // protoVersion is the only version we support - protoVersion uint8 = 0 -) - -const ( - // Data is used for data frames. They are followed - // by length bytes worth of payload. - typeData uint8 = iota - - // WindowUpdate is used to change the window of - // a given stream. The length indicates the delta - // update to the window. - typeWindowUpdate - - // Ping is sent as a keep-alive or to measure - // the RTT. The StreamID and Length value are echoed - // back in the response. - typePing - - // GoAway is sent to terminate a session. The StreamID - // should be 0 and the length is an error code. - typeGoAway -) - -const ( - // SYN is sent to signal a new stream. May - // be sent with a data payload - flagSYN uint16 = 1 << iota - - // ACK is sent to acknowledge a new stream. May - // be sent with a data payload - flagACK - - // FIN is sent to half-close the given stream. - // May be sent with a data payload. - flagFIN - - // RST is used to hard close a given stream. - flagRST -) - -const ( - // initialStreamWindow is the initial stream window size - initialStreamWindow uint32 = 256 * 1024 -) - -const ( - // goAwayNormal is sent on a normal termination - goAwayNormal uint32 = iota - - // goAwayProtoErr sent on a protocol error - goAwayProtoErr - - // goAwayInternalErr sent on an internal error - goAwayInternalErr -) - -const ( - sizeOfVersion = 1 - sizeOfType = 1 - sizeOfFlags = 2 - sizeOfStreamID = 4 - sizeOfLength = 4 - headerSize = sizeOfVersion + sizeOfType + sizeOfFlags + - sizeOfStreamID + sizeOfLength -) - -type header []byte - -func (h header) Version() uint8 { - return h[0] -} - -func (h header) MsgType() uint8 { - return h[1] -} - -func (h header) Flags() uint16 { - return binary.BigEndian.Uint16(h[2:4]) -} - -func (h header) StreamID() uint32 { - return binary.BigEndian.Uint32(h[4:8]) -} - -func (h header) Length() uint32 { - return binary.BigEndian.Uint32(h[8:12]) -} - -func (h header) String() string { - return fmt.Sprintf("Vsn:%d Type:%d Flags:%d StreamID:%d Length:%d", - h.Version(), h.MsgType(), h.Flags(), h.StreamID(), h.Length()) -} - -func (h header) encode(msgType uint8, flags uint16, streamID uint32, length uint32) { - h[0] = protoVersion - h[1] = msgType - binary.BigEndian.PutUint16(h[2:4], flags) - binary.BigEndian.PutUint32(h[4:8], streamID) - binary.BigEndian.PutUint32(h[8:12], length) -} diff --git a/vendor/github.com/hashicorp/yamux/go.mod b/vendor/github.com/hashicorp/yamux/go.mod deleted file mode 100644 index 672a0e581..000000000 --- a/vendor/github.com/hashicorp/yamux/go.mod +++ /dev/null @@ -1 +0,0 @@ -module github.com/hashicorp/yamux diff --git a/vendor/github.com/hashicorp/yamux/mux.go b/vendor/github.com/hashicorp/yamux/mux.go deleted file mode 100644 index 18a078c8a..000000000 --- a/vendor/github.com/hashicorp/yamux/mux.go +++ /dev/null @@ -1,98 +0,0 @@ -package yamux - -import ( - "fmt" - "io" - "log" - "os" - "time" -) - -// Config is used to tune the Yamux session -type Config struct { - // AcceptBacklog is used to limit how many streams may be - // waiting an accept. - AcceptBacklog int - - // EnableKeepalive is used to do a period keep alive - // messages using a ping. - EnableKeepAlive bool - - // KeepAliveInterval is how often to perform the keep alive - KeepAliveInterval time.Duration - - // ConnectionWriteTimeout is meant to be a "safety valve" timeout after - // we which will suspect a problem with the underlying connection and - // close it. This is only applied to writes, where's there's generally - // an expectation that things will move along quickly. - ConnectionWriteTimeout time.Duration - - // MaxStreamWindowSize is used to control the maximum - // window size that we allow for a stream. - MaxStreamWindowSize uint32 - - // LogOutput is used to control the log destination. Either Logger or - // LogOutput can be set, not both. - LogOutput io.Writer - - // Logger is used to pass in the logger to be used. Either Logger or - // LogOutput can be set, not both. - Logger *log.Logger -} - -// DefaultConfig is used to return a default configuration -func DefaultConfig() *Config { - return &Config{ - AcceptBacklog: 256, - EnableKeepAlive: true, - KeepAliveInterval: 30 * time.Second, - ConnectionWriteTimeout: 10 * time.Second, - MaxStreamWindowSize: initialStreamWindow, - LogOutput: os.Stderr, - } -} - -// VerifyConfig is used to verify the sanity of configuration -func VerifyConfig(config *Config) error { - if config.AcceptBacklog <= 0 { - return fmt.Errorf("backlog must be positive") - } - if config.KeepAliveInterval == 0 { - return fmt.Errorf("keep-alive interval must be positive") - } - if config.MaxStreamWindowSize < initialStreamWindow { - return fmt.Errorf("MaxStreamWindowSize must be larger than %d", initialStreamWindow) - } - if config.LogOutput != nil && config.Logger != nil { - return fmt.Errorf("both Logger and LogOutput may not be set, select one") - } else if config.LogOutput == nil && config.Logger == nil { - return fmt.Errorf("one of Logger or LogOutput must be set, select one") - } - return nil -} - -// Server is used to initialize a new server-side connection. -// There must be at most one server-side connection. If a nil config is -// provided, the DefaultConfiguration will be used. -func Server(conn io.ReadWriteCloser, config *Config) (*Session, error) { - if config == nil { - config = DefaultConfig() - } - if err := VerifyConfig(config); err != nil { - return nil, err - } - return newSession(config, conn, false), nil -} - -// Client is used to initialize a new client-side connection. -// There must be at most one client-side connection. -func Client(conn io.ReadWriteCloser, config *Config) (*Session, error) { - if config == nil { - config = DefaultConfig() - } - - if err := VerifyConfig(config); err != nil { - return nil, err - } - return newSession(config, conn, true), nil -} diff --git a/vendor/github.com/hashicorp/yamux/session.go b/vendor/github.com/hashicorp/yamux/session.go deleted file mode 100644 index a80ddec35..000000000 --- a/vendor/github.com/hashicorp/yamux/session.go +++ /dev/null @@ -1,653 +0,0 @@ -package yamux - -import ( - "bufio" - "fmt" - "io" - "io/ioutil" - "log" - "math" - "net" - "strings" - "sync" - "sync/atomic" - "time" -) - -// Session is used to wrap a reliable ordered connection and to -// multiplex it into multiple streams. -type Session struct { - // remoteGoAway indicates the remote side does - // not want futher connections. Must be first for alignment. - remoteGoAway int32 - - // localGoAway indicates that we should stop - // accepting futher connections. Must be first for alignment. - localGoAway int32 - - // nextStreamID is the next stream we should - // send. This depends if we are a client/server. - nextStreamID uint32 - - // config holds our configuration - config *Config - - // logger is used for our logs - logger *log.Logger - - // conn is the underlying connection - conn io.ReadWriteCloser - - // bufRead is a buffered reader - bufRead *bufio.Reader - - // pings is used to track inflight pings - pings map[uint32]chan struct{} - pingID uint32 - pingLock sync.Mutex - - // streams maps a stream id to a stream, and inflight has an entry - // for any outgoing stream that has not yet been established. Both are - // protected by streamLock. - streams map[uint32]*Stream - inflight map[uint32]struct{} - streamLock sync.Mutex - - // synCh acts like a semaphore. It is sized to the AcceptBacklog which - // is assumed to be symmetric between the client and server. This allows - // the client to avoid exceeding the backlog and instead blocks the open. - synCh chan struct{} - - // acceptCh is used to pass ready streams to the client - acceptCh chan *Stream - - // sendCh is used to mark a stream as ready to send, - // or to send a header out directly. - sendCh chan sendReady - - // recvDoneCh is closed when recv() exits to avoid a race - // between stream registration and stream shutdown - recvDoneCh chan struct{} - - // shutdown is used to safely close a session - shutdown bool - shutdownErr error - shutdownCh chan struct{} - shutdownLock sync.Mutex -} - -// sendReady is used to either mark a stream as ready -// or to directly send a header -type sendReady struct { - Hdr []byte - Body io.Reader - Err chan error -} - -// newSession is used to construct a new session -func newSession(config *Config, conn io.ReadWriteCloser, client bool) *Session { - logger := config.Logger - if logger == nil { - logger = log.New(config.LogOutput, "", log.LstdFlags) - } - - s := &Session{ - config: config, - logger: logger, - conn: conn, - bufRead: bufio.NewReader(conn), - pings: make(map[uint32]chan struct{}), - streams: make(map[uint32]*Stream), - inflight: make(map[uint32]struct{}), - synCh: make(chan struct{}, config.AcceptBacklog), - acceptCh: make(chan *Stream, config.AcceptBacklog), - sendCh: make(chan sendReady, 64), - recvDoneCh: make(chan struct{}), - shutdownCh: make(chan struct{}), - } - if client { - s.nextStreamID = 1 - } else { - s.nextStreamID = 2 - } - go s.recv() - go s.send() - if config.EnableKeepAlive { - go s.keepalive() - } - return s -} - -// IsClosed does a safe check to see if we have shutdown -func (s *Session) IsClosed() bool { - select { - case <-s.shutdownCh: - return true - default: - return false - } -} - -// CloseChan returns a read-only channel which is closed as -// soon as the session is closed. -func (s *Session) CloseChan() <-chan struct{} { - return s.shutdownCh -} - -// NumStreams returns the number of currently open streams -func (s *Session) NumStreams() int { - s.streamLock.Lock() - num := len(s.streams) - s.streamLock.Unlock() - return num -} - -// Open is used to create a new stream as a net.Conn -func (s *Session) Open() (net.Conn, error) { - conn, err := s.OpenStream() - if err != nil { - return nil, err - } - return conn, nil -} - -// OpenStream is used to create a new stream -func (s *Session) OpenStream() (*Stream, error) { - if s.IsClosed() { - return nil, ErrSessionShutdown - } - if atomic.LoadInt32(&s.remoteGoAway) == 1 { - return nil, ErrRemoteGoAway - } - - // Block if we have too many inflight SYNs - select { - case s.synCh <- struct{}{}: - case <-s.shutdownCh: - return nil, ErrSessionShutdown - } - -GET_ID: - // Get an ID, and check for stream exhaustion - id := atomic.LoadUint32(&s.nextStreamID) - if id >= math.MaxUint32-1 { - return nil, ErrStreamsExhausted - } - if !atomic.CompareAndSwapUint32(&s.nextStreamID, id, id+2) { - goto GET_ID - } - - // Register the stream - stream := newStream(s, id, streamInit) - s.streamLock.Lock() - s.streams[id] = stream - s.inflight[id] = struct{}{} - s.streamLock.Unlock() - - // Send the window update to create - if err := stream.sendWindowUpdate(); err != nil { - select { - case <-s.synCh: - default: - s.logger.Printf("[ERR] yamux: aborted stream open without inflight syn semaphore") - } - return nil, err - } - return stream, nil -} - -// Accept is used to block until the next available stream -// is ready to be accepted. -func (s *Session) Accept() (net.Conn, error) { - conn, err := s.AcceptStream() - if err != nil { - return nil, err - } - return conn, err -} - -// AcceptStream is used to block until the next available stream -// is ready to be accepted. -func (s *Session) AcceptStream() (*Stream, error) { - select { - case stream := <-s.acceptCh: - if err := stream.sendWindowUpdate(); err != nil { - return nil, err - } - return stream, nil - case <-s.shutdownCh: - return nil, s.shutdownErr - } -} - -// Close is used to close the session and all streams. -// Attempts to send a GoAway before closing the connection. -func (s *Session) Close() error { - s.shutdownLock.Lock() - defer s.shutdownLock.Unlock() - - if s.shutdown { - return nil - } - s.shutdown = true - if s.shutdownErr == nil { - s.shutdownErr = ErrSessionShutdown - } - close(s.shutdownCh) - s.conn.Close() - <-s.recvDoneCh - - s.streamLock.Lock() - defer s.streamLock.Unlock() - for _, stream := range s.streams { - stream.forceClose() - } - return nil -} - -// exitErr is used to handle an error that is causing the -// session to terminate. -func (s *Session) exitErr(err error) { - s.shutdownLock.Lock() - if s.shutdownErr == nil { - s.shutdownErr = err - } - s.shutdownLock.Unlock() - s.Close() -} - -// GoAway can be used to prevent accepting further -// connections. It does not close the underlying conn. -func (s *Session) GoAway() error { - return s.waitForSend(s.goAway(goAwayNormal), nil) -} - -// goAway is used to send a goAway message -func (s *Session) goAway(reason uint32) header { - atomic.SwapInt32(&s.localGoAway, 1) - hdr := header(make([]byte, headerSize)) - hdr.encode(typeGoAway, 0, 0, reason) - return hdr -} - -// Ping is used to measure the RTT response time -func (s *Session) Ping() (time.Duration, error) { - // Get a channel for the ping - ch := make(chan struct{}) - - // Get a new ping id, mark as pending - s.pingLock.Lock() - id := s.pingID - s.pingID++ - s.pings[id] = ch - s.pingLock.Unlock() - - // Send the ping request - hdr := header(make([]byte, headerSize)) - hdr.encode(typePing, flagSYN, 0, id) - if err := s.waitForSend(hdr, nil); err != nil { - return 0, err - } - - // Wait for a response - start := time.Now() - select { - case <-ch: - case <-time.After(s.config.ConnectionWriteTimeout): - s.pingLock.Lock() - delete(s.pings, id) // Ignore it if a response comes later. - s.pingLock.Unlock() - return 0, ErrTimeout - case <-s.shutdownCh: - return 0, ErrSessionShutdown - } - - // Compute the RTT - return time.Now().Sub(start), nil -} - -// keepalive is a long running goroutine that periodically does -// a ping to keep the connection alive. -func (s *Session) keepalive() { - for { - select { - case <-time.After(s.config.KeepAliveInterval): - _, err := s.Ping() - if err != nil { - if err != ErrSessionShutdown { - s.logger.Printf("[ERR] yamux: keepalive failed: %v", err) - s.exitErr(ErrKeepAliveTimeout) - } - return - } - case <-s.shutdownCh: - return - } - } -} - -// waitForSendErr waits to send a header, checking for a potential shutdown -func (s *Session) waitForSend(hdr header, body io.Reader) error { - errCh := make(chan error, 1) - return s.waitForSendErr(hdr, body, errCh) -} - -// waitForSendErr waits to send a header with optional data, checking for a -// potential shutdown. Since there's the expectation that sends can happen -// in a timely manner, we enforce the connection write timeout here. -func (s *Session) waitForSendErr(hdr header, body io.Reader, errCh chan error) error { - t := timerPool.Get() - timer := t.(*time.Timer) - timer.Reset(s.config.ConnectionWriteTimeout) - defer func() { - timer.Stop() - select { - case <-timer.C: - default: - } - timerPool.Put(t) - }() - - ready := sendReady{Hdr: hdr, Body: body, Err: errCh} - select { - case s.sendCh <- ready: - case <-s.shutdownCh: - return ErrSessionShutdown - case <-timer.C: - return ErrConnectionWriteTimeout - } - - select { - case err := <-errCh: - return err - case <-s.shutdownCh: - return ErrSessionShutdown - case <-timer.C: - return ErrConnectionWriteTimeout - } -} - -// sendNoWait does a send without waiting. Since there's the expectation that -// the send happens right here, we enforce the connection write timeout if we -// can't queue the header to be sent. -func (s *Session) sendNoWait(hdr header) error { - t := timerPool.Get() - timer := t.(*time.Timer) - timer.Reset(s.config.ConnectionWriteTimeout) - defer func() { - timer.Stop() - select { - case <-timer.C: - default: - } - timerPool.Put(t) - }() - - select { - case s.sendCh <- sendReady{Hdr: hdr}: - return nil - case <-s.shutdownCh: - return ErrSessionShutdown - case <-timer.C: - return ErrConnectionWriteTimeout - } -} - -// send is a long running goroutine that sends data -func (s *Session) send() { - for { - select { - case ready := <-s.sendCh: - // Send a header if ready - if ready.Hdr != nil { - sent := 0 - for sent < len(ready.Hdr) { - n, err := s.conn.Write(ready.Hdr[sent:]) - if err != nil { - s.logger.Printf("[ERR] yamux: Failed to write header: %v", err) - asyncSendErr(ready.Err, err) - s.exitErr(err) - return - } - sent += n - } - } - - // Send data from a body if given - if ready.Body != nil { - _, err := io.Copy(s.conn, ready.Body) - if err != nil { - s.logger.Printf("[ERR] yamux: Failed to write body: %v", err) - asyncSendErr(ready.Err, err) - s.exitErr(err) - return - } - } - - // No error, successful send - asyncSendErr(ready.Err, nil) - case <-s.shutdownCh: - return - } - } -} - -// recv is a long running goroutine that accepts new data -func (s *Session) recv() { - if err := s.recvLoop(); err != nil { - s.exitErr(err) - } -} - -// Ensure that the index of the handler (typeData/typeWindowUpdate/etc) matches the message type -var ( - handlers = []func(*Session, header) error{ - typeData: (*Session).handleStreamMessage, - typeWindowUpdate: (*Session).handleStreamMessage, - typePing: (*Session).handlePing, - typeGoAway: (*Session).handleGoAway, - } -) - -// recvLoop continues to receive data until a fatal error is encountered -func (s *Session) recvLoop() error { - defer close(s.recvDoneCh) - hdr := header(make([]byte, headerSize)) - for { - // Read the header - if _, err := io.ReadFull(s.bufRead, hdr); err != nil { - if err != io.EOF && !strings.Contains(err.Error(), "closed") && !strings.Contains(err.Error(), "reset by peer") { - s.logger.Printf("[ERR] yamux: Failed to read header: %v", err) - } - return err - } - - // Verify the version - if hdr.Version() != protoVersion { - s.logger.Printf("[ERR] yamux: Invalid protocol version: %d", hdr.Version()) - return ErrInvalidVersion - } - - mt := hdr.MsgType() - if mt < typeData || mt > typeGoAway { - return ErrInvalidMsgType - } - - if err := handlers[mt](s, hdr); err != nil { - return err - } - } -} - -// handleStreamMessage handles either a data or window update frame -func (s *Session) handleStreamMessage(hdr header) error { - // Check for a new stream creation - id := hdr.StreamID() - flags := hdr.Flags() - if flags&flagSYN == flagSYN { - if err := s.incomingStream(id); err != nil { - return err - } - } - - // Get the stream - s.streamLock.Lock() - stream := s.streams[id] - s.streamLock.Unlock() - - // If we do not have a stream, likely we sent a RST - if stream == nil { - // Drain any data on the wire - if hdr.MsgType() == typeData && hdr.Length() > 0 { - s.logger.Printf("[WARN] yamux: Discarding data for stream: %d", id) - if _, err := io.CopyN(ioutil.Discard, s.bufRead, int64(hdr.Length())); err != nil { - s.logger.Printf("[ERR] yamux: Failed to discard data: %v", err) - return nil - } - } else { - s.logger.Printf("[WARN] yamux: frame for missing stream: %v", hdr) - } - return nil - } - - // Check if this is a window update - if hdr.MsgType() == typeWindowUpdate { - if err := stream.incrSendWindow(hdr, flags); err != nil { - if sendErr := s.sendNoWait(s.goAway(goAwayProtoErr)); sendErr != nil { - s.logger.Printf("[WARN] yamux: failed to send go away: %v", sendErr) - } - return err - } - return nil - } - - // Read the new data - if err := stream.readData(hdr, flags, s.bufRead); err != nil { - if sendErr := s.sendNoWait(s.goAway(goAwayProtoErr)); sendErr != nil { - s.logger.Printf("[WARN] yamux: failed to send go away: %v", sendErr) - } - return err - } - return nil -} - -// handlePing is invokde for a typePing frame -func (s *Session) handlePing(hdr header) error { - flags := hdr.Flags() - pingID := hdr.Length() - - // Check if this is a query, respond back in a separate context so we - // don't interfere with the receiving thread blocking for the write. - if flags&flagSYN == flagSYN { - go func() { - hdr := header(make([]byte, headerSize)) - hdr.encode(typePing, flagACK, 0, pingID) - if err := s.sendNoWait(hdr); err != nil { - s.logger.Printf("[WARN] yamux: failed to send ping reply: %v", err) - } - }() - return nil - } - - // Handle a response - s.pingLock.Lock() - ch := s.pings[pingID] - if ch != nil { - delete(s.pings, pingID) - close(ch) - } - s.pingLock.Unlock() - return nil -} - -// handleGoAway is invokde for a typeGoAway frame -func (s *Session) handleGoAway(hdr header) error { - code := hdr.Length() - switch code { - case goAwayNormal: - atomic.SwapInt32(&s.remoteGoAway, 1) - case goAwayProtoErr: - s.logger.Printf("[ERR] yamux: received protocol error go away") - return fmt.Errorf("yamux protocol error") - case goAwayInternalErr: - s.logger.Printf("[ERR] yamux: received internal error go away") - return fmt.Errorf("remote yamux internal error") - default: - s.logger.Printf("[ERR] yamux: received unexpected go away") - return fmt.Errorf("unexpected go away received") - } - return nil -} - -// incomingStream is used to create a new incoming stream -func (s *Session) incomingStream(id uint32) error { - // Reject immediately if we are doing a go away - if atomic.LoadInt32(&s.localGoAway) == 1 { - hdr := header(make([]byte, headerSize)) - hdr.encode(typeWindowUpdate, flagRST, id, 0) - return s.sendNoWait(hdr) - } - - // Allocate a new stream - stream := newStream(s, id, streamSYNReceived) - - s.streamLock.Lock() - defer s.streamLock.Unlock() - - // Check if stream already exists - if _, ok := s.streams[id]; ok { - s.logger.Printf("[ERR] yamux: duplicate stream declared") - if sendErr := s.sendNoWait(s.goAway(goAwayProtoErr)); sendErr != nil { - s.logger.Printf("[WARN] yamux: failed to send go away: %v", sendErr) - } - return ErrDuplicateStream - } - - // Register the stream - s.streams[id] = stream - - // Check if we've exceeded the backlog - select { - case s.acceptCh <- stream: - return nil - default: - // Backlog exceeded! RST the stream - s.logger.Printf("[WARN] yamux: backlog exceeded, forcing connection reset") - delete(s.streams, id) - stream.sendHdr.encode(typeWindowUpdate, flagRST, id, 0) - return s.sendNoWait(stream.sendHdr) - } -} - -// closeStream is used to close a stream once both sides have -// issued a close. If there was an in-flight SYN and the stream -// was not yet established, then this will give the credit back. -func (s *Session) closeStream(id uint32) { - s.streamLock.Lock() - if _, ok := s.inflight[id]; ok { - select { - case <-s.synCh: - default: - s.logger.Printf("[ERR] yamux: SYN tracking out of sync") - } - } - delete(s.streams, id) - s.streamLock.Unlock() -} - -// establishStream is used to mark a stream that was in the -// SYN Sent state as established. -func (s *Session) establishStream(id uint32) { - s.streamLock.Lock() - if _, ok := s.inflight[id]; ok { - delete(s.inflight, id) - } else { - s.logger.Printf("[ERR] yamux: established stream without inflight SYN (no tracking entry)") - } - select { - case <-s.synCh: - default: - s.logger.Printf("[ERR] yamux: established stream without inflight SYN (didn't have semaphore)") - } - s.streamLock.Unlock() -} diff --git a/vendor/github.com/hashicorp/yamux/spec.md b/vendor/github.com/hashicorp/yamux/spec.md deleted file mode 100644 index 183d797bd..000000000 --- a/vendor/github.com/hashicorp/yamux/spec.md +++ /dev/null @@ -1,140 +0,0 @@ -# Specification - -We use this document to detail the internal specification of Yamux. -This is used both as a guide for implementing Yamux, but also for -alternative interoperable libraries to be built. - -# Framing - -Yamux uses a streaming connection underneath, but imposes a message -framing so that it can be shared between many logical streams. Each -frame contains a header like: - -* Version (8 bits) -* Type (8 bits) -* Flags (16 bits) -* StreamID (32 bits) -* Length (32 bits) - -This means that each header has a 12 byte overhead. -All fields are encoded in network order (big endian). -Each field is described below: - -## Version Field - -The version field is used for future backward compatibility. At the -current time, the field is always set to 0, to indicate the initial -version. - -## Type Field - -The type field is used to switch the frame message type. The following -message types are supported: - -* 0x0 Data - Used to transmit data. May transmit zero length payloads - depending on the flags. - -* 0x1 Window Update - Used to updated the senders receive window size. - This is used to implement per-session flow control. - -* 0x2 Ping - Used to measure RTT. It can also be used to heart-beat - and do keep-alives over TCP. - -* 0x3 Go Away - Used to close a session. - -## Flag Field - -The flags field is used to provide additional information related -to the message type. The following flags are supported: - -* 0x1 SYN - Signals the start of a new stream. May be sent with a data or - window update message. Also sent with a ping to indicate outbound. - -* 0x2 ACK - Acknowledges the start of a new stream. May be sent with a data - or window update message. Also sent with a ping to indicate response. - -* 0x4 FIN - Performs a half-close of a stream. May be sent with a data - message or window update. - -* 0x8 RST - Reset a stream immediately. May be sent with a data or - window update message. - -## StreamID Field - -The StreamID field is used to identify the logical stream the frame -is addressing. The client side should use odd ID's, and the server even. -This prevents any collisions. Additionally, the 0 ID is reserved to represent -the session. - -Both Ping and Go Away messages should always use the 0 StreamID. - -## Length Field - -The meaning of the length field depends on the message type: - -* Data - provides the length of bytes following the header -* Window update - provides a delta update to the window size -* Ping - Contains an opaque value, echoed back -* Go Away - Contains an error code - -# Message Flow - -There is no explicit connection setup, as Yamux relies on an underlying -transport to be provided. However, there is a distinction between client -and server side of the connection. - -## Opening a stream - -To open a stream, an initial data or window update frame is sent -with a new StreamID. The SYN flag should be set to signal a new stream. - -The receiver must then reply with either a data or window update frame -with the StreamID along with the ACK flag to accept the stream or with -the RST flag to reject the stream. - -Because we are relying on the reliable stream underneath, a connection -can begin sending data once the SYN flag is sent. The corresponding -ACK does not need to be received. This is particularly well suited -for an RPC system where a client wants to open a stream and immediately -fire a request without waiting for the RTT of the ACK. - -This does introduce the possibility of a connection being rejected -after data has been sent already. This is a slight semantic difference -from TCP, where the conection cannot be refused after it is opened. -Clients should be prepared to handle this by checking for an error -that indicates a RST was received. - -## Closing a stream - -To close a stream, either side sends a data or window update frame -along with the FIN flag. This does a half-close indicating the sender -will send no further data. - -Once both sides have closed the connection, the stream is closed. - -Alternatively, if an error occurs, the RST flag can be used to -hard close a stream immediately. - -## Flow Control - -When Yamux is initially starts each stream with a 256KB window size. -There is no window size for the session. - -To prevent the streams from stalling, window update frames should be -sent regularly. Yamux can be configured to provide a larger limit for -windows sizes. Both sides assume the initial 256KB window, but can -immediately send a window update as part of the SYN/ACK indicating a -larger window. - -Both sides should track the number of bytes sent in Data frames -only, as only they are tracked as part of the window size. - -## Session termination - -When a session is being terminated, the Go Away message should -be sent. The Length should be set to one of the following to -provide an error code: - -* 0x0 Normal termination -* 0x1 Protocol error -* 0x2 Internal error diff --git a/vendor/github.com/hashicorp/yamux/stream.go b/vendor/github.com/hashicorp/yamux/stream.go deleted file mode 100644 index aa2391973..000000000 --- a/vendor/github.com/hashicorp/yamux/stream.go +++ /dev/null @@ -1,470 +0,0 @@ -package yamux - -import ( - "bytes" - "io" - "sync" - "sync/atomic" - "time" -) - -type streamState int - -const ( - streamInit streamState = iota - streamSYNSent - streamSYNReceived - streamEstablished - streamLocalClose - streamRemoteClose - streamClosed - streamReset -) - -// Stream is used to represent a logical stream -// within a session. -type Stream struct { - recvWindow uint32 - sendWindow uint32 - - id uint32 - session *Session - - state streamState - stateLock sync.Mutex - - recvBuf *bytes.Buffer - recvLock sync.Mutex - - controlHdr header - controlErr chan error - controlHdrLock sync.Mutex - - sendHdr header - sendErr chan error - sendLock sync.Mutex - - recvNotifyCh chan struct{} - sendNotifyCh chan struct{} - - readDeadline atomic.Value // time.Time - writeDeadline atomic.Value // time.Time -} - -// newStream is used to construct a new stream within -// a given session for an ID -func newStream(session *Session, id uint32, state streamState) *Stream { - s := &Stream{ - id: id, - session: session, - state: state, - controlHdr: header(make([]byte, headerSize)), - controlErr: make(chan error, 1), - sendHdr: header(make([]byte, headerSize)), - sendErr: make(chan error, 1), - recvWindow: initialStreamWindow, - sendWindow: initialStreamWindow, - recvNotifyCh: make(chan struct{}, 1), - sendNotifyCh: make(chan struct{}, 1), - } - s.readDeadline.Store(time.Time{}) - s.writeDeadline.Store(time.Time{}) - return s -} - -// Session returns the associated stream session -func (s *Stream) Session() *Session { - return s.session -} - -// StreamID returns the ID of this stream -func (s *Stream) StreamID() uint32 { - return s.id -} - -// Read is used to read from the stream -func (s *Stream) Read(b []byte) (n int, err error) { - defer asyncNotify(s.recvNotifyCh) -START: - s.stateLock.Lock() - switch s.state { - case streamLocalClose: - fallthrough - case streamRemoteClose: - fallthrough - case streamClosed: - s.recvLock.Lock() - if s.recvBuf == nil || s.recvBuf.Len() == 0 { - s.recvLock.Unlock() - s.stateLock.Unlock() - return 0, io.EOF - } - s.recvLock.Unlock() - case streamReset: - s.stateLock.Unlock() - return 0, ErrConnectionReset - } - s.stateLock.Unlock() - - // If there is no data available, block - s.recvLock.Lock() - if s.recvBuf == nil || s.recvBuf.Len() == 0 { - s.recvLock.Unlock() - goto WAIT - } - - // Read any bytes - n, _ = s.recvBuf.Read(b) - s.recvLock.Unlock() - - // Send a window update potentially - err = s.sendWindowUpdate() - return n, err - -WAIT: - var timeout <-chan time.Time - var timer *time.Timer - readDeadline := s.readDeadline.Load().(time.Time) - if !readDeadline.IsZero() { - delay := readDeadline.Sub(time.Now()) - timer = time.NewTimer(delay) - timeout = timer.C - } - select { - case <-s.recvNotifyCh: - if timer != nil { - timer.Stop() - } - goto START - case <-timeout: - return 0, ErrTimeout - } -} - -// Write is used to write to the stream -func (s *Stream) Write(b []byte) (n int, err error) { - s.sendLock.Lock() - defer s.sendLock.Unlock() - total := 0 - for total < len(b) { - n, err := s.write(b[total:]) - total += n - if err != nil { - return total, err - } - } - return total, nil -} - -// write is used to write to the stream, may return on -// a short write. -func (s *Stream) write(b []byte) (n int, err error) { - var flags uint16 - var max uint32 - var body io.Reader -START: - s.stateLock.Lock() - switch s.state { - case streamLocalClose: - fallthrough - case streamClosed: - s.stateLock.Unlock() - return 0, ErrStreamClosed - case streamReset: - s.stateLock.Unlock() - return 0, ErrConnectionReset - } - s.stateLock.Unlock() - - // If there is no data available, block - window := atomic.LoadUint32(&s.sendWindow) - if window == 0 { - goto WAIT - } - - // Determine the flags if any - flags = s.sendFlags() - - // Send up to our send window - max = min(window, uint32(len(b))) - body = bytes.NewReader(b[:max]) - - // Send the header - s.sendHdr.encode(typeData, flags, s.id, max) - if err = s.session.waitForSendErr(s.sendHdr, body, s.sendErr); err != nil { - return 0, err - } - - // Reduce our send window - atomic.AddUint32(&s.sendWindow, ^uint32(max-1)) - - // Unlock - return int(max), err - -WAIT: - var timeout <-chan time.Time - writeDeadline := s.writeDeadline.Load().(time.Time) - if !writeDeadline.IsZero() { - delay := writeDeadline.Sub(time.Now()) - timeout = time.After(delay) - } - select { - case <-s.sendNotifyCh: - goto START - case <-timeout: - return 0, ErrTimeout - } - return 0, nil -} - -// sendFlags determines any flags that are appropriate -// based on the current stream state -func (s *Stream) sendFlags() uint16 { - s.stateLock.Lock() - defer s.stateLock.Unlock() - var flags uint16 - switch s.state { - case streamInit: - flags |= flagSYN - s.state = streamSYNSent - case streamSYNReceived: - flags |= flagACK - s.state = streamEstablished - } - return flags -} - -// sendWindowUpdate potentially sends a window update enabling -// further writes to take place. Must be invoked with the lock. -func (s *Stream) sendWindowUpdate() error { - s.controlHdrLock.Lock() - defer s.controlHdrLock.Unlock() - - // Determine the delta update - max := s.session.config.MaxStreamWindowSize - var bufLen uint32 - s.recvLock.Lock() - if s.recvBuf != nil { - bufLen = uint32(s.recvBuf.Len()) - } - delta := (max - bufLen) - s.recvWindow - - // Determine the flags if any - flags := s.sendFlags() - - // Check if we can omit the update - if delta < (max/2) && flags == 0 { - s.recvLock.Unlock() - return nil - } - - // Update our window - s.recvWindow += delta - s.recvLock.Unlock() - - // Send the header - s.controlHdr.encode(typeWindowUpdate, flags, s.id, delta) - if err := s.session.waitForSendErr(s.controlHdr, nil, s.controlErr); err != nil { - return err - } - return nil -} - -// sendClose is used to send a FIN -func (s *Stream) sendClose() error { - s.controlHdrLock.Lock() - defer s.controlHdrLock.Unlock() - - flags := s.sendFlags() - flags |= flagFIN - s.controlHdr.encode(typeWindowUpdate, flags, s.id, 0) - if err := s.session.waitForSendErr(s.controlHdr, nil, s.controlErr); err != nil { - return err - } - return nil -} - -// Close is used to close the stream -func (s *Stream) Close() error { - closeStream := false - s.stateLock.Lock() - switch s.state { - // Opened means we need to signal a close - case streamSYNSent: - fallthrough - case streamSYNReceived: - fallthrough - case streamEstablished: - s.state = streamLocalClose - goto SEND_CLOSE - - case streamLocalClose: - case streamRemoteClose: - s.state = streamClosed - closeStream = true - goto SEND_CLOSE - - case streamClosed: - case streamReset: - default: - panic("unhandled state") - } - s.stateLock.Unlock() - return nil -SEND_CLOSE: - s.stateLock.Unlock() - s.sendClose() - s.notifyWaiting() - if closeStream { - s.session.closeStream(s.id) - } - return nil -} - -// forceClose is used for when the session is exiting -func (s *Stream) forceClose() { - s.stateLock.Lock() - s.state = streamClosed - s.stateLock.Unlock() - s.notifyWaiting() -} - -// processFlags is used to update the state of the stream -// based on set flags, if any. Lock must be held -func (s *Stream) processFlags(flags uint16) error { - // Close the stream without holding the state lock - closeStream := false - defer func() { - if closeStream { - s.session.closeStream(s.id) - } - }() - - s.stateLock.Lock() - defer s.stateLock.Unlock() - if flags&flagACK == flagACK { - if s.state == streamSYNSent { - s.state = streamEstablished - } - s.session.establishStream(s.id) - } - if flags&flagFIN == flagFIN { - switch s.state { - case streamSYNSent: - fallthrough - case streamSYNReceived: - fallthrough - case streamEstablished: - s.state = streamRemoteClose - s.notifyWaiting() - case streamLocalClose: - s.state = streamClosed - closeStream = true - s.notifyWaiting() - default: - s.session.logger.Printf("[ERR] yamux: unexpected FIN flag in state %d", s.state) - return ErrUnexpectedFlag - } - } - if flags&flagRST == flagRST { - s.state = streamReset - closeStream = true - s.notifyWaiting() - } - return nil -} - -// notifyWaiting notifies all the waiting channels -func (s *Stream) notifyWaiting() { - asyncNotify(s.recvNotifyCh) - asyncNotify(s.sendNotifyCh) -} - -// incrSendWindow updates the size of our send window -func (s *Stream) incrSendWindow(hdr header, flags uint16) error { - if err := s.processFlags(flags); err != nil { - return err - } - - // Increase window, unblock a sender - atomic.AddUint32(&s.sendWindow, hdr.Length()) - asyncNotify(s.sendNotifyCh) - return nil -} - -// readData is used to handle a data frame -func (s *Stream) readData(hdr header, flags uint16, conn io.Reader) error { - if err := s.processFlags(flags); err != nil { - return err - } - - // Check that our recv window is not exceeded - length := hdr.Length() - if length == 0 { - return nil - } - - // Wrap in a limited reader - conn = &io.LimitedReader{R: conn, N: int64(length)} - - // Copy into buffer - s.recvLock.Lock() - - if length > s.recvWindow { - s.session.logger.Printf("[ERR] yamux: receive window exceeded (stream: %d, remain: %d, recv: %d)", s.id, s.recvWindow, length) - return ErrRecvWindowExceeded - } - - if s.recvBuf == nil { - // Allocate the receive buffer just-in-time to fit the full data frame. - // This way we can read in the whole packet without further allocations. - s.recvBuf = bytes.NewBuffer(make([]byte, 0, length)) - } - if _, err := io.Copy(s.recvBuf, conn); err != nil { - s.session.logger.Printf("[ERR] yamux: Failed to read stream data: %v", err) - s.recvLock.Unlock() - return err - } - - // Decrement the receive window - s.recvWindow -= length - s.recvLock.Unlock() - - // Unblock any readers - asyncNotify(s.recvNotifyCh) - return nil -} - -// SetDeadline sets the read and write deadlines -func (s *Stream) SetDeadline(t time.Time) error { - if err := s.SetReadDeadline(t); err != nil { - return err - } - if err := s.SetWriteDeadline(t); err != nil { - return err - } - return nil -} - -// SetReadDeadline sets the deadline for future Read calls. -func (s *Stream) SetReadDeadline(t time.Time) error { - s.readDeadline.Store(t) - return nil -} - -// SetWriteDeadline sets the deadline for future Write calls -func (s *Stream) SetWriteDeadline(t time.Time) error { - s.writeDeadline.Store(t) - return nil -} - -// Shrink is used to compact the amount of buffers utilized -// This is useful when using Yamux in a connection pool to reduce -// the idle memory utilization. -func (s *Stream) Shrink() { - s.recvLock.Lock() - if s.recvBuf != nil && s.recvBuf.Len() == 0 { - s.recvBuf = nil - } - s.recvLock.Unlock() -} diff --git a/vendor/github.com/hashicorp/yamux/util.go b/vendor/github.com/hashicorp/yamux/util.go deleted file mode 100644 index 8a73e9249..000000000 --- a/vendor/github.com/hashicorp/yamux/util.go +++ /dev/null @@ -1,43 +0,0 @@ -package yamux - -import ( - "sync" - "time" -) - -var ( - timerPool = &sync.Pool{ - New: func() interface{} { - timer := time.NewTimer(time.Hour * 1e6) - timer.Stop() - return timer - }, - } -) - -// asyncSendErr is used to try an async send of an error -func asyncSendErr(ch chan error, err error) { - if ch == nil { - return - } - select { - case ch <- err: - default: - } -} - -// asyncNotify is used to signal a waiting goroutine -func asyncNotify(ch chan struct{}) { - select { - case ch <- struct{}{}: - default: - } -} - -// min computes the minimum of two values -func min(a, b uint32) uint32 { - if a < b { - return a - } - return b -} diff --git a/vendor/github.com/miekg/dns/README.md b/vendor/github.com/miekg/dns/README.md index 77874642b..7f1aaa5de 100644 --- a/vendor/github.com/miekg/dns/README.md +++ b/vendor/github.com/miekg/dns/README.md @@ -67,6 +67,7 @@ A not-so-up-to-date-list-that-may-be-actually-current: * https://github.com/xor-gate/sshfp * https://github.com/rs/dnstrace * https://blitiri.com.ar/p/dnss ([github mirror](https://github.com/albertito/dnss)) +* https://github.com/semihalev/sdns Send pull request if you want to be listed here. diff --git a/vendor/github.com/miekg/dns/dnssec_keyscan.go b/vendor/github.com/miekg/dns/dnssec_keyscan.go index 719198659..5e6542230 100644 --- a/vendor/github.com/miekg/dns/dnssec_keyscan.go +++ b/vendor/github.com/miekg/dns/dnssec_keyscan.go @@ -1,6 +1,7 @@ package dns import ( + "bufio" "crypto" "crypto/dsa" "crypto/ecdsa" @@ -194,23 +195,12 @@ func readPrivateKeyED25519(m map[string]string) (ed25519.PrivateKey, error) { // parseKey reads a private key from r. It returns a map[string]string, // with the key-value pairs, or an error when the file is not correct. func parseKey(r io.Reader, file string) (map[string]string, error) { - s, cancel := scanInit(r) m := make(map[string]string) - c := make(chan lex) - k := "" - defer func() { - cancel() - // zlexer can send up to two tokens, the next one and possibly 1 remainders. - // Do a non-blocking read. - _, ok := <-c - _, ok = <-c - if !ok { - // too bad - } - }() - // Start the lexer - go klexer(s, c) - for l := range c { + var k string + + c := newKLexer(r) + + for l, ok := c.Next(); ok; l, ok = c.Next() { // It should alternate switch l.value { case zKey: @@ -219,41 +209,111 @@ func parseKey(r io.Reader, file string) (map[string]string, error) { if k == "" { return nil, &ParseError{file, "no private key seen", l} } - //println("Setting", strings.ToLower(k), "to", l.token, "b") + m[strings.ToLower(k)] = l.token k = "" } } + + // Surface any read errors from r. + if err := c.Err(); err != nil { + return nil, &ParseError{file: file, err: err.Error()} + } + return m, nil } -// klexer scans the sourcefile and returns tokens on the channel c. -func klexer(s *scan, c chan lex) { - var l lex - str := "" // Hold the current read text - commt := false - key := true - x, err := s.tokenText() - defer close(c) - for err == nil { - l.column = s.position.Column - l.line = s.position.Line +type klexer struct { + br io.ByteReader + + readErr error + + line int + column int + + key bool + + eol bool // end-of-line +} + +func newKLexer(r io.Reader) *klexer { + br, ok := r.(io.ByteReader) + if !ok { + br = bufio.NewReaderSize(r, 1024) + } + + return &klexer{ + br: br, + + line: 1, + + key: true, + } +} + +func (kl *klexer) Err() error { + if kl.readErr == io.EOF { + return nil + } + + return kl.readErr +} + +// readByte returns the next byte from the input +func (kl *klexer) readByte() (byte, bool) { + if kl.readErr != nil { + return 0, false + } + + c, err := kl.br.ReadByte() + if err != nil { + kl.readErr = err + return 0, false + } + + // delay the newline handling until the next token is delivered, + // fixes off-by-one errors when reporting a parse error. + if kl.eol { + kl.line++ + kl.column = 0 + kl.eol = false + } + + if c == '\n' { + kl.eol = true + } else { + kl.column++ + } + + return c, true +} + +func (kl *klexer) Next() (lex, bool) { + var ( + l lex + + str strings.Builder + + commt bool + ) + + for x, ok := kl.readByte(); ok; x, ok = kl.readByte() { + l.line, l.column = kl.line, kl.column + switch x { case ':': - if commt { + if commt || !kl.key { break } - l.token = str - if key { - l.value = zKey - c <- l - // Next token is a space, eat it - s.tokenText() - key = false - str = "" - } else { - l.value = zValue - } + + kl.key = false + + // Next token is a space, eat it + kl.readByte() + + l.value = zKey + l.token = str.String() + return l, true case ';': commt = true case '\n': @@ -261,24 +321,32 @@ func klexer(s *scan, c chan lex) { // Reset a comment commt = false } + + kl.key = true + l.value = zValue - l.token = str - c <- l - str = "" - commt = false - key = true + l.token = str.String() + return l, true default: if commt { break } - str += string(x) + + str.WriteByte(x) } - x, err = s.tokenText() } - if len(str) > 0 { + + if kl.readErr != nil && kl.readErr != io.EOF { + // Don't return any tokens after a read error occurs. + return lex{value: zEOF}, false + } + + if str.Len() > 0 { // Send remainder - l.token = str l.value = zValue - c <- l + l.token = str.String() + return l, true } + + return lex{value: zEOF}, false } diff --git a/vendor/github.com/miekg/dns/generate.go b/vendor/github.com/miekg/dns/generate.go index 91d928c83..97bc39f58 100644 --- a/vendor/github.com/miekg/dns/generate.go +++ b/vendor/github.com/miekg/dns/generate.go @@ -2,8 +2,8 @@ package dns import ( "bytes" - "errors" "fmt" + "io" "strconv" "strings" ) @@ -18,154 +18,225 @@ import ( // * rhs (rdata) // But we are lazy here, only the range is parsed *all* occurrences // of $ after that are interpreted. -// Any error are returned as a string value, the empty string signals -// "no error". -func generate(l lex, c chan lex, t chan *Token, o string) string { +func (zp *ZoneParser) generate(l lex) (RR, bool) { + token := l.token step := 1 - if i := strings.IndexAny(l.token, "/"); i != -1 { - if i+1 == len(l.token) { - return "bad step in $GENERATE range" + if i := strings.IndexByte(token, '/'); i >= 0 { + if i+1 == len(token) { + return zp.setParseError("bad step in $GENERATE range", l) } - if s, err := strconv.Atoi(l.token[i+1:]); err == nil { - if s < 0 { - return "bad step in $GENERATE range" - } - step = s - } else { - return "bad step in $GENERATE range" + + s, err := strconv.Atoi(token[i+1:]) + if err != nil || s <= 0 { + return zp.setParseError("bad step in $GENERATE range", l) } - l.token = l.token[:i] + + step = s + token = token[:i] } - sx := strings.SplitN(l.token, "-", 2) + + sx := strings.SplitN(token, "-", 2) if len(sx) != 2 { - return "bad start-stop in $GENERATE range" + return zp.setParseError("bad start-stop in $GENERATE range", l) } + start, err := strconv.Atoi(sx[0]) if err != nil { - return "bad start in $GENERATE range" + return zp.setParseError("bad start in $GENERATE range", l) } + end, err := strconv.Atoi(sx[1]) if err != nil { - return "bad stop in $GENERATE range" + return zp.setParseError("bad stop in $GENERATE range", l) } if end < 0 || start < 0 || end < start { - return "bad range in $GENERATE range" + return zp.setParseError("bad range in $GENERATE range", l) } - <-c // _BLANK + zp.c.Next() // _BLANK + // Create a complete new string, which we then parse again. - s := "" -BuildRR: - l = <-c - if l.value != zNewline && l.value != zEOF { + var s string + for l, ok := zp.c.Next(); ok; l, ok = zp.c.Next() { + if l.err { + return zp.setParseError("bad data in $GENERATE directive", l) + } + if l.value == zNewline { + break + } + s += l.token - goto BuildRR - } - for i := start; i <= end; i += step { - var ( - escape bool - dom bytes.Buffer - mod string - err error - offset int - ) - - for j := 0; j < len(s); j++ { // No 'range' because we need to jump around - switch s[j] { - case '\\': - if escape { - dom.WriteByte('\\') - escape = false - continue - } - escape = true - case '$': - mod = "%d" - offset = 0 - if escape { - dom.WriteByte('$') - escape = false - continue - } - escape = false - if j+1 >= len(s) { // End of the string - dom.WriteString(fmt.Sprintf(mod, i+offset)) - continue - } else { - if s[j+1] == '$' { - dom.WriteByte('$') - j++ - continue - } - } - // Search for { and } - if s[j+1] == '{' { // Modifier block - sep := strings.Index(s[j+2:], "}") - if sep == -1 { - return "bad modifier in $GENERATE" - } - mod, offset, err = modToPrintf(s[j+2 : j+2+sep]) - if err != nil { - return err.Error() - } else if start + offset < 0 || end + offset > 1<<31-1 { - return "bad offset in $GENERATE" - } - j += 2 + sep // Jump to it - } - dom.WriteString(fmt.Sprintf(mod, i+offset)) - default: - if escape { // Pretty useless here - escape = false - continue - } - dom.WriteByte(s[j]) + } + + r := &generateReader{ + s: s, + + cur: start, + start: start, + end: end, + step: step, + + file: zp.file, + lex: &l, + } + zp.sub = NewZoneParser(r, zp.origin, zp.file) + zp.sub.includeDepth, zp.sub.includeAllowed = zp.includeDepth, zp.includeAllowed + zp.sub.SetDefaultTTL(defaultTtl) + return zp.subNext() +} + +type generateReader struct { + s string + si int + + cur int + start int + end int + step int + + mod bytes.Buffer + + escape bool + + eof bool + + file string + lex *lex +} + +func (r *generateReader) parseError(msg string, end int) *ParseError { + r.eof = true // Make errors sticky. + + l := *r.lex + l.token = r.s[r.si-1 : end] + l.column += r.si // l.column starts one zBLANK before r.s + + return &ParseError{r.file, msg, l} +} + +func (r *generateReader) Read(p []byte) (int, error) { + // NewZLexer, through NewZoneParser, should use ReadByte and + // not end up here. + + panic("not implemented") +} + +func (r *generateReader) ReadByte() (byte, error) { + if r.eof { + return 0, io.EOF + } + if r.mod.Len() > 0 { + return r.mod.ReadByte() + } + + if r.si >= len(r.s) { + r.si = 0 + r.cur += r.step + + r.eof = r.cur > r.end || r.cur < 0 + return '\n', nil + } + + si := r.si + r.si++ + + switch r.s[si] { + case '\\': + if r.escape { + r.escape = false + return '\\', nil + } + + r.escape = true + return r.ReadByte() + case '$': + if r.escape { + r.escape = false + return '$', nil + } + + mod := "%d" + + if si >= len(r.s)-1 { + // End of the string + fmt.Fprintf(&r.mod, mod, r.cur) + return r.mod.ReadByte() + } + + if r.s[si+1] == '$' { + r.si++ + return '$', nil + } + + var offset int + + // Search for { and } + if r.s[si+1] == '{' { + // Modifier block + sep := strings.Index(r.s[si+2:], "}") + if sep < 0 { + return 0, r.parseError("bad modifier in $GENERATE", len(r.s)) + } + + var errMsg string + mod, offset, errMsg = modToPrintf(r.s[si+2 : si+2+sep]) + if errMsg != "" { + return 0, r.parseError(errMsg, si+3+sep) } + if r.start+offset < 0 || r.end+offset > 1<<31-1 { + return 0, r.parseError("bad offset in $GENERATE", si+3+sep) + } + + r.si += 2 + sep // Jump to it } - // Re-parse the RR and send it on the current channel t - rx, err := NewRR("$ORIGIN " + o + "\n" + dom.String()) - if err != nil { - return err.Error() + + fmt.Fprintf(&r.mod, mod, r.cur+offset) + return r.mod.ReadByte() + default: + if r.escape { // Pretty useless here + r.escape = false + return r.ReadByte() } - t <- &Token{RR: rx} - // Its more efficient to first built the rrlist and then parse it in - // one go! But is this a problem? + + return r.s[si], nil } - return "" } // Convert a $GENERATE modifier 0,0,d to something Printf can deal with. -func modToPrintf(s string) (string, int, error) { - xs := strings.Split(s, ",") - +func modToPrintf(s string) (string, int, string) { // Modifier is { offset [ ,width [ ,base ] ] } - provide default // values for optional width and type, if necessary. - switch len(xs) { + var offStr, widthStr, base string + switch xs := strings.Split(s, ","); len(xs) { case 1: - xs = append(xs, "0", "d") + offStr, widthStr, base = xs[0], "0", "d" case 2: - xs = append(xs, "d") + offStr, widthStr, base = xs[0], xs[1], "d" case 3: + offStr, widthStr, base = xs[0], xs[1], xs[2] default: - return "", 0, errors.New("bad modifier in $GENERATE") + return "", 0, "bad modifier in $GENERATE" } - // xs[0] is offset, xs[1] is width, xs[2] is base - if xs[2] != "o" && xs[2] != "d" && xs[2] != "x" && xs[2] != "X" { - return "", 0, errors.New("bad base in $GENERATE") + switch base { + case "o", "d", "x", "X": + default: + return "", 0, "bad base in $GENERATE" } - offset, err := strconv.Atoi(xs[0]) + + offset, err := strconv.Atoi(offStr) if err != nil { - return "", 0, errors.New("bad offset in $GENERATE") + return "", 0, "bad offset in $GENERATE" } - width, err := strconv.Atoi(xs[1]) - if err != nil || width > 255 { - return "", offset, errors.New("bad width in $GENERATE") + + width, err := strconv.Atoi(widthStr) + if err != nil || width < 0 || width > 255 { + return "", 0, "bad width in $GENERATE" } - switch { - case width < 0: - return "", offset, errors.New("bad width in $GENERATE") - case width == 0: - return "%" + xs[1] + xs[2], offset, nil + + if width == 0 { + return "%" + base, offset, "" } - return "%0" + xs[1] + xs[2], offset, nil + + return "%0" + widthStr + base, offset, "" } diff --git a/vendor/github.com/miekg/dns/privaterr.go b/vendor/github.com/miekg/dns/privaterr.go index d931da7ef..74544a74e 100644 --- a/vendor/github.com/miekg/dns/privaterr.go +++ b/vendor/github.com/miekg/dns/privaterr.go @@ -105,7 +105,7 @@ func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) return rr, off, err } - setPrivateRR := func(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { + setPrivateRR := func(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := mkPrivateRR(h.Rrtype) rr.Hdr = h @@ -115,7 +115,7 @@ func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) for { // TODO(miek): we could also be returning _QUOTE, this might or might not // be an issue (basically parsing TXT becomes hard) - switch l = <-c; l.value { + switch l, _ = c.Next(); l.value { case zNewline, zEOF: break Fetch case zString: diff --git a/vendor/github.com/miekg/dns/scan.go b/vendor/github.com/miekg/dns/scan.go index a752dbd01..61ace121e 100644 --- a/vendor/github.com/miekg/dns/scan.go +++ b/vendor/github.com/miekg/dns/scan.go @@ -1,6 +1,7 @@ package dns import ( + "bufio" "fmt" "io" "os" @@ -11,6 +12,10 @@ import ( const maxTok = 2048 // Largest token we can return. +// The maximum depth of $INCLUDE directives supported by the +// ZoneParser API. +const maxIncludeDepth = 7 + // Tokinize a RFC 1035 zone file. The tokenizer will normalize it: // * Add ownernames if they are left blank; // * Suppress sequences of spaces; @@ -74,15 +79,13 @@ func (e *ParseError) Error() (s string) { } type lex struct { - token string // text of the token - tokenUpper string // uppercase text of the token - length int // length of the token - err bool // when true, token text has lexer error - value uint8 // value: zString, _BLANK, etc. - torc uint16 // type or class as parsed in the lexer, we only need to look this up in the grammar - line int // line in the file - column int // column in the file - comment string // any comment text seen + token string // text of the token + err bool // when true, token text has lexer error + value uint8 // value: zString, _BLANK, etc. + torc uint16 // type or class as parsed in the lexer, we only need to look this up in the grammar + line int // line in the file + column int // column in the file + comment string // any comment text seen } // Token holds the token that are returned when a zone file is parsed. @@ -102,10 +105,14 @@ type ttlState struct { } // NewRR reads the RR contained in the string s. Only the first RR is -// returned. If s contains no RR, return nil with no error. The class -// defaults to IN and TTL defaults to 3600. The full zone file syntax -// like $TTL, $ORIGIN, etc. is supported. All fields of the returned -// RR are set, except RR.Header().Rdlength which is set to 0. +// returned. If s contains no records, NewRR will return nil with no +// error. +// +// The class defaults to IN and TTL defaults to 3600. The full zone +// file syntax like $TTL, $ORIGIN, etc. is supported. +// +// All fields of the returned RR are set, except RR.Header().Rdlength +// which is set to 0. func NewRR(s string) (RR, error) { if len(s) > 0 && s[len(s)-1] != '\n' { // We need a closing newline return ReadRR(strings.NewReader(s+"\n"), "") @@ -113,28 +120,31 @@ func NewRR(s string) (RR, error) { return ReadRR(strings.NewReader(s), "") } -// ReadRR reads the RR contained in q. +// ReadRR reads the RR contained in r. +// +// The string file is used in error reporting and to resolve relative +// $INCLUDE directives. +// // See NewRR for more documentation. -func ReadRR(q io.Reader, filename string) (RR, error) { - defttl := &ttlState{defaultTtl, false} - r := <-parseZoneHelper(q, ".", filename, defttl, 1) - if r == nil { - return nil, nil - } - - if r.Error != nil { - return nil, r.Error - } - return r.RR, nil +func ReadRR(r io.Reader, file string) (RR, error) { + zp := NewZoneParser(r, ".", file) + zp.SetDefaultTTL(defaultTtl) + zp.SetIncludeAllowed(true) + rr, _ := zp.Next() + return rr, zp.Err() } -// ParseZone reads a RFC 1035 style zonefile from r. It returns *Tokens on the -// returned channel, each consisting of either a parsed RR and optional comment -// or a nil RR and an error. The string file is only used -// in error reporting. The string origin is used as the initial origin, as -// if the file would start with an $ORIGIN directive. -// The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are supported. -// The channel t is closed by ParseZone when the end of r is reached. +// ParseZone reads a RFC 1035 style zonefile from r. It returns +// *Tokens on the returned channel, each consisting of either a +// parsed RR and optional comment or a nil RR and an error. The +// channel is closed by ParseZone when the end of r is reached. +// +// The string file is used in error reporting and to resolve relative +// $INCLUDE directives. The string origin is used as the initial +// origin, as if the file would start with an $ORIGIN directive. +// +// The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are all +// supported. // // Basic usage pattern when reading from a string (z) containing the // zone data: @@ -147,90 +157,246 @@ func ReadRR(q io.Reader, filename string) (RR, error) { // } // } // -// Comments specified after an RR (and on the same line!) are returned too: +// Comments specified after an RR (and on the same line!) are +// returned too: // // foo. IN A 10.0.0.1 ; this is a comment // -// The text "; this is comment" is returned in Token.Comment. Comments inside the -// RR are discarded. Comments on a line by themselves are discarded too. +// The text "; this is comment" is returned in Token.Comment. +// Comments inside the RR are returned concatenated along with the +// RR. Comments on a line by themselves are discarded. +// +// To prevent memory leaks it is important to always fully drain the +// returned channel. If an error occurs, it will always be the last +// Token sent on the channel. +// +// Deprecated: New users should prefer the ZoneParser API. func ParseZone(r io.Reader, origin, file string) chan *Token { - return parseZoneHelper(r, origin, file, nil, 10000) -} - -func parseZoneHelper(r io.Reader, origin, file string, defttl *ttlState, chansize int) chan *Token { - t := make(chan *Token, chansize) - go parseZone(r, origin, file, defttl, t, 0) + t := make(chan *Token, 10000) + go parseZone(r, origin, file, t) return t } -func parseZone(r io.Reader, origin, f string, defttl *ttlState, t chan *Token, include int) { - defer func() { - if include == 0 { - close(t) - } - }() - s, cancel := scanInit(r) - c := make(chan lex) - // Start the lexer - go zlexer(s, c) - - defer func() { - cancel() - // zlexer can send up to three tokens, the next one and possibly 2 remainders. - // Do a non-blocking read. - _, ok := <-c - _, ok = <-c - _, ok = <-c +func parseZone(r io.Reader, origin, file string, t chan *Token) { + defer close(t) + + zp := NewZoneParser(r, origin, file) + zp.SetIncludeAllowed(true) + + for rr, ok := zp.Next(); ok; rr, ok = zp.Next() { + t <- &Token{RR: rr, Comment: zp.Comment()} + } + + if err := zp.Err(); err != nil { + pe, ok := err.(*ParseError) if !ok { - // too bad + pe = &ParseError{file: file, err: err.Error()} } - }() - // 6 possible beginnings of a line, _ is a space - // 0. zRRTYPE -> all omitted until the rrtype - // 1. zOwner _ zRrtype -> class/ttl omitted - // 2. zOwner _ zString _ zRrtype -> class omitted - // 3. zOwner _ zString _ zClass _ zRrtype -> ttl/class - // 4. zOwner _ zClass _ zRrtype -> ttl omitted - // 5. zOwner _ zClass _ zString _ zRrtype -> class/ttl (reversed) - // After detecting these, we know the zRrtype so we can jump to functions - // handling the rdata for each of these types. + t <- &Token{Error: pe} + } +} + +// ZoneParser is a parser for an RFC 1035 style zonefile. +// +// Each parsed RR in the zone is returned sequentially from Next. An +// optional comment can be retrieved with Comment. +// +// The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are all +// supported. Although $INCLUDE is disabled by default. +// +// Basic usage pattern when reading from a string (z) containing the +// zone data: +// +// zp := NewZoneParser(strings.NewReader(z), "", "") +// +// for rr, ok := zp.Next(); ok; rr, ok = zp.Next() { +// // Do something with rr +// } +// +// if err := zp.Err(); err != nil { +// // log.Println(err) +// } +// +// Comments specified after an RR (and on the same line!) are +// returned too: +// +// foo. IN A 10.0.0.1 ; this is a comment +// +// The text "; this is comment" is returned from Comment. Comments inside +// the RR are returned concatenated along with the RR. Comments on a line +// by themselves are discarded. +type ZoneParser struct { + c *zlexer + + parseErr *ParseError + + origin string + file string + + defttl *ttlState + + h RR_Header + + // sub is used to parse $INCLUDE files and $GENERATE directives. + // Next, by calling subNext, forwards the resulting RRs from this + // sub parser to the calling code. + sub *ZoneParser + osFile *os.File + + com string + + includeDepth uint8 + + includeAllowed bool +} + +// NewZoneParser returns an RFC 1035 style zonefile parser that reads +// from r. +// +// The string file is used in error reporting and to resolve relative +// $INCLUDE directives. The string origin is used as the initial +// origin, as if the file would start with an $ORIGIN directive. +func NewZoneParser(r io.Reader, origin, file string) *ZoneParser { + var pe *ParseError if origin != "" { origin = Fqdn(origin) if _, ok := IsDomainName(origin); !ok { - t <- &Token{Error: &ParseError{f, "bad initial origin name", lex{}}} - return + pe = &ParseError{file, "bad initial origin name", lex{}} } } + return &ZoneParser{ + c: newZLexer(r), + + parseErr: pe, + + origin: origin, + file: file, + } +} + +// SetDefaultTTL sets the parsers default TTL to ttl. +func (zp *ZoneParser) SetDefaultTTL(ttl uint32) { + zp.defttl = &ttlState{ttl, false} +} + +// SetIncludeAllowed controls whether $INCLUDE directives are +// allowed. $INCLUDE directives are not supported by default. +// +// The $INCLUDE directive will open and read from a user controlled +// file on the system. Even if the file is not a valid zonefile, the +// contents of the file may be revealed in error messages, such as: +// +// /etc/passwd: dns: not a TTL: "root:x:0:0:root:/root:/bin/bash" at line: 1:31 +// /etc/shadow: dns: not a TTL: "root:$6$::0:99999:7:::" at line: 1:125 +func (zp *ZoneParser) SetIncludeAllowed(v bool) { + zp.includeAllowed = v +} + +// Err returns the first non-EOF error that was encountered by the +// ZoneParser. +func (zp *ZoneParser) Err() error { + if zp.parseErr != nil { + return zp.parseErr + } + + if zp.sub != nil { + if err := zp.sub.Err(); err != nil { + return err + } + } + + return zp.c.Err() +} + +func (zp *ZoneParser) setParseError(err string, l lex) (RR, bool) { + zp.parseErr = &ParseError{zp.file, err, l} + return nil, false +} + +// Comment returns an optional text comment that occurred alongside +// the RR. +func (zp *ZoneParser) Comment() string { + return zp.com +} + +func (zp *ZoneParser) subNext() (RR, bool) { + if rr, ok := zp.sub.Next(); ok { + zp.com = zp.sub.com + return rr, true + } + + if zp.sub.osFile != nil { + zp.sub.osFile.Close() + zp.sub.osFile = nil + } + + if zp.sub.Err() != nil { + // We have errors to surface. + return nil, false + } + + zp.sub = nil + return zp.Next() +} + +// Next advances the parser to the next RR in the zonefile and +// returns the (RR, true). It will return (nil, false) when the +// parsing stops, either by reaching the end of the input or an +// error. After Next returns (nil, false), the Err method will return +// any error that occurred during parsing. +func (zp *ZoneParser) Next() (RR, bool) { + zp.com = "" + + if zp.parseErr != nil { + return nil, false + } + if zp.sub != nil { + return zp.subNext() + } + + // 6 possible beginnings of a line (_ is a space): + // + // 0. zRRTYPE -> all omitted until the rrtype + // 1. zOwner _ zRrtype -> class/ttl omitted + // 2. zOwner _ zString _ zRrtype -> class omitted + // 3. zOwner _ zString _ zClass _ zRrtype -> ttl/class + // 4. zOwner _ zClass _ zRrtype -> ttl omitted + // 5. zOwner _ zClass _ zString _ zRrtype -> class/ttl (reversed) + // + // After detecting these, we know the zRrtype so we can jump to functions + // handling the rdata for each of these types. + st := zExpectOwnerDir // initial state - var h RR_Header - var prevName string - for l := range c { - // Lexer spotted an error already + h := &zp.h + + for l, ok := zp.c.Next(); ok; l, ok = zp.c.Next() { + // zlexer spotted an error already if l.err { - t <- &Token{Error: &ParseError{f, l.token, l}} - return + return zp.setParseError(l.token, l) } + switch st { case zExpectOwnerDir: // We can also expect a directive, like $TTL or $ORIGIN - if defttl != nil { - h.Ttl = defttl.ttl + if zp.defttl != nil { + h.Ttl = zp.defttl.ttl } + h.Class = ClassINET + switch l.value { case zNewline: st = zExpectOwnerDir case zOwner: - h.Name = l.token - name, ok := toAbsoluteName(l.token, origin) + name, ok := toAbsoluteName(l.token, zp.origin) if !ok { - t <- &Token{Error: &ParseError{f, "bad owner name", l}} - return + return zp.setParseError("bad owner name", l) } + h.Name = name - prevName = h.Name + st = zExpectOwnerBl case zDirTTL: st = zExpectDirTTLBl @@ -241,12 +407,12 @@ func parseZone(r io.Reader, origin, f string, defttl *ttlState, t chan *Token, i case zDirGenerate: st = zExpectDirGenerateBl case zRrtpe: - h.Name = prevName h.Rrtype = l.torc + st = zExpectRdata case zClass: - h.Name = prevName h.Class = l.torc + st = zExpectAnyNoClassBl case zBlank: // Discard, can happen when there is nothing on the @@ -254,297 +420,400 @@ func parseZone(r io.Reader, origin, f string, defttl *ttlState, t chan *Token, i case zString: ttl, ok := stringToTTL(l.token) if !ok { - t <- &Token{Error: &ParseError{f, "not a TTL", l}} - return + return zp.setParseError("not a TTL", l) } + h.Ttl = ttl - if defttl == nil || !defttl.isByDirective { - defttl = &ttlState{ttl, false} + + if zp.defttl == nil || !zp.defttl.isByDirective { + zp.defttl = &ttlState{ttl, false} } - st = zExpectAnyNoTTLBl + st = zExpectAnyNoTTLBl default: - t <- &Token{Error: &ParseError{f, "syntax error at beginning", l}} - return + return zp.setParseError("syntax error at beginning", l) } case zExpectDirIncludeBl: if l.value != zBlank { - t <- &Token{Error: &ParseError{f, "no blank after $INCLUDE-directive", l}} - return + return zp.setParseError("no blank after $INCLUDE-directive", l) } + st = zExpectDirInclude case zExpectDirInclude: if l.value != zString { - t <- &Token{Error: &ParseError{f, "expecting $INCLUDE value, not this...", l}} - return + return zp.setParseError("expecting $INCLUDE value, not this...", l) } - neworigin := origin // There may be optionally a new origin set after the filename, if not use current one - switch l := <-c; l.value { + + neworigin := zp.origin // There may be optionally a new origin set after the filename, if not use current one + switch l, _ := zp.c.Next(); l.value { case zBlank: - l := <-c + l, _ := zp.c.Next() if l.value == zString { - name, ok := toAbsoluteName(l.token, origin) + name, ok := toAbsoluteName(l.token, zp.origin) if !ok { - t <- &Token{Error: &ParseError{f, "bad origin name", l}} - return + return zp.setParseError("bad origin name", l) } + neworigin = name } case zNewline, zEOF: // Ok default: - t <- &Token{Error: &ParseError{f, "garbage after $INCLUDE", l}} - return + return zp.setParseError("garbage after $INCLUDE", l) } + + if !zp.includeAllowed { + return zp.setParseError("$INCLUDE directive not allowed", l) + } + if zp.includeDepth >= maxIncludeDepth { + return zp.setParseError("too deeply nested $INCLUDE", l) + } + // Start with the new file includePath := l.token if !filepath.IsAbs(includePath) { - includePath = filepath.Join(filepath.Dir(f), includePath) + includePath = filepath.Join(filepath.Dir(zp.file), includePath) } + r1, e1 := os.Open(includePath) if e1 != nil { - msg := fmt.Sprintf("failed to open `%s'", l.token) + var as string if !filepath.IsAbs(l.token) { - msg += fmt.Sprintf(" as `%s'", includePath) + as = fmt.Sprintf(" as `%s'", includePath) } - t <- &Token{Error: &ParseError{f, msg, l}} - return - } - if include+1 > 7 { - t <- &Token{Error: &ParseError{f, "too deeply nested $INCLUDE", l}} - return + + msg := fmt.Sprintf("failed to open `%s'%s: %v", l.token, as, e1) + return zp.setParseError(msg, l) } - parseZone(r1, neworigin, includePath, defttl, t, include+1) - st = zExpectOwnerDir + + zp.sub = NewZoneParser(r1, neworigin, includePath) + zp.sub.defttl, zp.sub.includeDepth, zp.sub.osFile = zp.defttl, zp.includeDepth+1, r1 + zp.sub.SetIncludeAllowed(true) + return zp.subNext() case zExpectDirTTLBl: if l.value != zBlank { - t <- &Token{Error: &ParseError{f, "no blank after $TTL-directive", l}} - return + return zp.setParseError("no blank after $TTL-directive", l) } + st = zExpectDirTTL case zExpectDirTTL: if l.value != zString { - t <- &Token{Error: &ParseError{f, "expecting $TTL value, not this...", l}} - return + return zp.setParseError("expecting $TTL value, not this...", l) } - if e, _ := slurpRemainder(c, f); e != nil { - t <- &Token{Error: e} - return + + if e, _ := slurpRemainder(zp.c, zp.file); e != nil { + zp.parseErr = e + return nil, false } + ttl, ok := stringToTTL(l.token) if !ok { - t <- &Token{Error: &ParseError{f, "expecting $TTL value, not this...", l}} - return + return zp.setParseError("expecting $TTL value, not this...", l) } - defttl = &ttlState{ttl, true} + + zp.defttl = &ttlState{ttl, true} + st = zExpectOwnerDir case zExpectDirOriginBl: if l.value != zBlank { - t <- &Token{Error: &ParseError{f, "no blank after $ORIGIN-directive", l}} - return + return zp.setParseError("no blank after $ORIGIN-directive", l) } + st = zExpectDirOrigin case zExpectDirOrigin: if l.value != zString { - t <- &Token{Error: &ParseError{f, "expecting $ORIGIN value, not this...", l}} - return + return zp.setParseError("expecting $ORIGIN value, not this...", l) } - if e, _ := slurpRemainder(c, f); e != nil { - t <- &Token{Error: e} + + if e, _ := slurpRemainder(zp.c, zp.file); e != nil { + zp.parseErr = e + return nil, false } - name, ok := toAbsoluteName(l.token, origin) + + name, ok := toAbsoluteName(l.token, zp.origin) if !ok { - t <- &Token{Error: &ParseError{f, "bad origin name", l}} - return + return zp.setParseError("bad origin name", l) } - origin = name + + zp.origin = name + st = zExpectOwnerDir case zExpectDirGenerateBl: if l.value != zBlank { - t <- &Token{Error: &ParseError{f, "no blank after $GENERATE-directive", l}} - return + return zp.setParseError("no blank after $GENERATE-directive", l) } + st = zExpectDirGenerate case zExpectDirGenerate: if l.value != zString { - t <- &Token{Error: &ParseError{f, "expecting $GENERATE value, not this...", l}} - return - } - if errMsg := generate(l, c, t, origin); errMsg != "" { - t <- &Token{Error: &ParseError{f, errMsg, l}} - return + return zp.setParseError("expecting $GENERATE value, not this...", l) } - st = zExpectOwnerDir + + return zp.generate(l) case zExpectOwnerBl: if l.value != zBlank { - t <- &Token{Error: &ParseError{f, "no blank after owner", l}} - return + return zp.setParseError("no blank after owner", l) } + st = zExpectAny case zExpectAny: switch l.value { case zRrtpe: - if defttl == nil { - t <- &Token{Error: &ParseError{f, "missing TTL with no previous value", l}} - return + if zp.defttl == nil { + return zp.setParseError("missing TTL with no previous value", l) } + h.Rrtype = l.torc + st = zExpectRdata case zClass: h.Class = l.torc + st = zExpectAnyNoClassBl case zString: ttl, ok := stringToTTL(l.token) if !ok { - t <- &Token{Error: &ParseError{f, "not a TTL", l}} - return + return zp.setParseError("not a TTL", l) } + h.Ttl = ttl - if defttl == nil || !defttl.isByDirective { - defttl = &ttlState{ttl, false} + + if zp.defttl == nil || !zp.defttl.isByDirective { + zp.defttl = &ttlState{ttl, false} } + st = zExpectAnyNoTTLBl default: - t <- &Token{Error: &ParseError{f, "expecting RR type, TTL or class, not this...", l}} - return + return zp.setParseError("expecting RR type, TTL or class, not this...", l) } case zExpectAnyNoClassBl: if l.value != zBlank { - t <- &Token{Error: &ParseError{f, "no blank before class", l}} - return + return zp.setParseError("no blank before class", l) } + st = zExpectAnyNoClass case zExpectAnyNoTTLBl: if l.value != zBlank { - t <- &Token{Error: &ParseError{f, "no blank before TTL", l}} - return + return zp.setParseError("no blank before TTL", l) } + st = zExpectAnyNoTTL case zExpectAnyNoTTL: switch l.value { case zClass: h.Class = l.torc + st = zExpectRrtypeBl case zRrtpe: h.Rrtype = l.torc + st = zExpectRdata default: - t <- &Token{Error: &ParseError{f, "expecting RR type or class, not this...", l}} - return + return zp.setParseError("expecting RR type or class, not this...", l) } case zExpectAnyNoClass: switch l.value { case zString: ttl, ok := stringToTTL(l.token) if !ok { - t <- &Token{Error: &ParseError{f, "not a TTL", l}} - return + return zp.setParseError("not a TTL", l) } + h.Ttl = ttl - if defttl == nil || !defttl.isByDirective { - defttl = &ttlState{ttl, false} + + if zp.defttl == nil || !zp.defttl.isByDirective { + zp.defttl = &ttlState{ttl, false} } + st = zExpectRrtypeBl case zRrtpe: h.Rrtype = l.torc + st = zExpectRdata default: - t <- &Token{Error: &ParseError{f, "expecting RR type or TTL, not this...", l}} - return + return zp.setParseError("expecting RR type or TTL, not this...", l) } case zExpectRrtypeBl: if l.value != zBlank { - t <- &Token{Error: &ParseError{f, "no blank before RR type", l}} - return + return zp.setParseError("no blank before RR type", l) } + st = zExpectRrtype case zExpectRrtype: if l.value != zRrtpe { - t <- &Token{Error: &ParseError{f, "unknown RR type", l}} - return + return zp.setParseError("unknown RR type", l) } + h.Rrtype = l.torc + st = zExpectRdata case zExpectRdata: - r, e, c1 := setRR(h, c, origin, f) + r, e, c1 := setRR(*h, zp.c, zp.origin, zp.file) if e != nil { // If e.lex is nil than we have encounter a unknown RR type // in that case we substitute our current lex token if e.lex.token == "" && e.lex.value == 0 { e.lex = l // Uh, dirty } - t <- &Token{Error: e} - return + + zp.parseErr = e + return nil, false } - t <- &Token{RR: r, Comment: c1} - st = zExpectOwnerDir + + zp.com = c1 + return r, true } } + // If we get here, we and the h.Rrtype is still zero, we haven't parsed anything, this // is not an error, because an empty zone file is still a zone file. + return nil, false +} + +type zlexer struct { + br io.ByteReader + + readErr error + + line int + column int + + com string + + l lex + + brace int + quote bool + space bool + commt bool + rrtype bool + owner bool + + nextL bool + + eol bool // end-of-line +} + +func newZLexer(r io.Reader) *zlexer { + br, ok := r.(io.ByteReader) + if !ok { + br = bufio.NewReaderSize(r, 1024) + } + + return &zlexer{ + br: br, + + line: 1, + + owner: true, + } +} + +func (zl *zlexer) Err() error { + if zl.readErr == io.EOF { + return nil + } + + return zl.readErr } -// zlexer scans the sourcefile and returns tokens on the channel c. -func zlexer(s *scan, c chan lex) { - var l lex - str := make([]byte, maxTok) // Should be enough for any token - stri := 0 // Offset in str (0 means empty) - com := make([]byte, maxTok) // Hold comment text - comi := 0 - quote := false - escape := false - space := false - commt := false - rrtype := false - owner := true - brace := 0 - x, err := s.tokenText() - defer close(c) - for err == nil { - l.column = s.position.Column - l.line = s.position.Line - if stri >= maxTok { +// readByte returns the next byte from the input +func (zl *zlexer) readByte() (byte, bool) { + if zl.readErr != nil { + return 0, false + } + + c, err := zl.br.ReadByte() + if err != nil { + zl.readErr = err + return 0, false + } + + // delay the newline handling until the next token is delivered, + // fixes off-by-one errors when reporting a parse error. + if zl.eol { + zl.line++ + zl.column = 0 + zl.eol = false + } + + if c == '\n' { + zl.eol = true + } else { + zl.column++ + } + + return c, true +} + +func (zl *zlexer) Next() (lex, bool) { + l := &zl.l + if zl.nextL { + zl.nextL = false + return *l, true + } + if l.err { + // Parsing errors should be sticky. + return lex{value: zEOF}, false + } + + var ( + str [maxTok]byte // Hold string text + com [maxTok]byte // Hold comment text + + stri int // Offset in str (0 means empty) + comi int // Offset in com (0 means empty) + + escape bool + ) + + if zl.com != "" { + comi = copy(com[:], zl.com) + zl.com = "" + } + + for x, ok := zl.readByte(); ok; x, ok = zl.readByte() { + l.line, l.column = zl.line, zl.column + l.comment = "" + + if stri >= len(str) { l.token = "token length insufficient for parsing" l.err = true - c <- l - return + return *l, true } - if comi >= maxTok { + if comi >= len(com) { l.token = "comment length insufficient for parsing" l.err = true - c <- l - return + return *l, true } switch x { case ' ', '\t': - if escape { - escape = false - str[stri] = x - stri++ - break - } - if quote { - // Inside quotes this is legal + if escape || zl.quote { + // Inside quotes or escaped this is legal. str[stri] = x stri++ + + escape = false break } - if commt { + + if zl.commt { com[comi] = x comi++ break } + + var retL lex if stri == 0 { // Space directly in the beginning, handled in the grammar - } else if owner { + } else if zl.owner { // If we have a string and its the first, make it an owner l.value = zOwner l.token = string(str[:stri]) - l.tokenUpper = strings.ToUpper(l.token) - l.length = stri + // escape $... start with a \ not a $, so this will work - switch l.tokenUpper { + switch strings.ToUpper(l.token) { case "$TTL": l.value = zDirTTL case "$ORIGIN": @@ -554,258 +823,316 @@ func zlexer(s *scan, c chan lex) { case "$GENERATE": l.value = zDirGenerate } - c <- l + + retL = *l } else { l.value = zString l.token = string(str[:stri]) - l.tokenUpper = strings.ToUpper(l.token) - l.length = stri - if !rrtype { - if t, ok := StringToType[l.tokenUpper]; ok { + + if !zl.rrtype { + tokenUpper := strings.ToUpper(l.token) + if t, ok := StringToType[tokenUpper]; ok { l.value = zRrtpe l.torc = t - rrtype = true - } else { - if strings.HasPrefix(l.tokenUpper, "TYPE") { - t, ok := typeToInt(l.token) - if !ok { - l.token = "unknown RR type" - l.err = true - c <- l - return - } - l.value = zRrtpe - rrtype = true - l.torc = t + + zl.rrtype = true + } else if strings.HasPrefix(tokenUpper, "TYPE") { + t, ok := typeToInt(l.token) + if !ok { + l.token = "unknown RR type" + l.err = true + return *l, true } + + l.value = zRrtpe + l.torc = t + + zl.rrtype = true } - if t, ok := StringToClass[l.tokenUpper]; ok { + + if t, ok := StringToClass[tokenUpper]; ok { l.value = zClass l.torc = t - } else { - if strings.HasPrefix(l.tokenUpper, "CLASS") { - t, ok := classToInt(l.token) - if !ok { - l.token = "unknown class" - l.err = true - c <- l - return - } - l.value = zClass - l.torc = t + } else if strings.HasPrefix(tokenUpper, "CLASS") { + t, ok := classToInt(l.token) + if !ok { + l.token = "unknown class" + l.err = true + return *l, true } + + l.value = zClass + l.torc = t } } - c <- l + + retL = *l } - stri = 0 - if !space && !commt { + zl.owner = false + + if !zl.space { + zl.space = true + l.value = zBlank l.token = " " - l.length = 1 - c <- l + + if retL == (lex{}) { + return *l, true + } + + zl.nextL = true + } + + if retL != (lex{}) { + return retL, true } - owner = false - space = true case ';': - if escape { - escape = false + if escape || zl.quote { + // Inside quotes or escaped this is legal. str[stri] = x stri++ + + escape = false break } - if quote { - // Inside quotes this is legal - str[stri] = x - stri++ - break + + zl.commt = true + zl.com = "" + + if comi > 1 { + // A newline was previously seen inside a comment that + // was inside braces and we delayed adding it until now. + com[comi] = ' ' // convert newline to space + comi++ } + + com[comi] = ';' + comi++ + if stri > 0 { + zl.com = string(com[:comi]) + l.value = zString l.token = string(str[:stri]) - l.tokenUpper = strings.ToUpper(l.token) - l.length = stri - c <- l - stri = 0 + return *l, true } - commt = true - com[comi] = ';' - comi++ case '\r': escape = false - if quote { + + if zl.quote { str[stri] = x stri++ } + // discard if outside of quotes case '\n': escape = false + // Escaped newline - if quote { + if zl.quote { str[stri] = x stri++ break } - // inside quotes this is legal - if commt { + + if zl.commt { // Reset a comment - commt = false - rrtype = false - stri = 0 + zl.commt = false + zl.rrtype = false + // If not in a brace this ends the comment AND the RR - if brace == 0 { - owner = true - owner = true + if zl.brace == 0 { + zl.owner = true + l.value = zNewline l.token = "\n" - l.tokenUpper = l.token - l.length = 1 l.comment = string(com[:comi]) - c <- l - l.comment = "" - comi = 0 - break + return *l, true } - com[comi] = ' ' // convert newline to space - comi++ + + zl.com = string(com[:comi]) break } - if brace == 0 { + if zl.brace == 0 { // If there is previous text, we should output it here + var retL lex if stri != 0 { l.value = zString l.token = string(str[:stri]) - l.tokenUpper = strings.ToUpper(l.token) - l.length = stri - if !rrtype { - if t, ok := StringToType[l.tokenUpper]; ok { + if !zl.rrtype { + tokenUpper := strings.ToUpper(l.token) + if t, ok := StringToType[tokenUpper]; ok { + zl.rrtype = true + l.value = zRrtpe l.torc = t - rrtype = true } } - c <- l + + retL = *l } + l.value = zNewline l.token = "\n" - l.tokenUpper = l.token - l.length = 1 - c <- l - stri = 0 - commt = false - rrtype = false - owner = true - comi = 0 + l.comment = zl.com + + zl.com = "" + zl.rrtype = false + zl.owner = true + + if retL != (lex{}) { + zl.nextL = true + return retL, true + } + + return *l, true } case '\\': // comments do not get escaped chars, everything is copied - if commt { + if zl.commt { com[comi] = x comi++ break } + // something already escaped must be in string if escape { str[stri] = x stri++ + escape = false break } + // something escaped outside of string gets added to string str[stri] = x stri++ + escape = true case '"': - if commt { + if zl.commt { com[comi] = x comi++ break } + if escape { str[stri] = x stri++ + escape = false break } - space = false + + zl.space = false + // send previous gathered text and the quote + var retL lex if stri != 0 { l.value = zString l.token = string(str[:stri]) - l.tokenUpper = strings.ToUpper(l.token) - l.length = stri - c <- l - stri = 0 + retL = *l } // send quote itself as separate token l.value = zQuote l.token = "\"" - l.tokenUpper = l.token - l.length = 1 - c <- l - quote = !quote + + zl.quote = !zl.quote + + if retL != (lex{}) { + zl.nextL = true + return retL, true + } + + return *l, true case '(', ')': - if commt { + if zl.commt { com[comi] = x comi++ break } - if escape { + + if escape || zl.quote { + // Inside quotes or escaped this is legal. str[stri] = x stri++ + escape = false break } - if quote { - str[stri] = x - stri++ - break - } + switch x { case ')': - brace-- - if brace < 0 { + zl.brace-- + + if zl.brace < 0 { l.token = "extra closing brace" - l.tokenUpper = l.token l.err = true - c <- l - return + return *l, true } case '(': - brace++ + zl.brace++ } default: escape = false - if commt { + + if zl.commt { com[comi] = x comi++ break } + str[stri] = x stri++ - space = false + + zl.space = false } - x, err = s.tokenText() } + + if zl.readErr != nil && zl.readErr != io.EOF { + // Don't return any tokens after a read error occurs. + return lex{value: zEOF}, false + } + + var retL lex if stri > 0 { - // Send remainder - l.token = string(str[:stri]) - l.tokenUpper = strings.ToUpper(l.token) - l.length = stri + // Send remainder of str l.value = zString - c <- l + l.token = string(str[:stri]) + retL = *l + + if comi <= 0 { + return retL, true + } } - if brace != 0 { + + if comi > 0 { + // Send remainder of com + l.value = zNewline + l.token = "\n" + l.comment = string(com[:comi]) + + if retL != (lex{}) { + zl.nextL = true + return retL, true + } + + return *l, true + } + + if zl.brace != 0 { + l.comment = "" // in case there was left over string and comment l.token = "unbalanced brace" - l.tokenUpper = l.token l.err = true - c <- l + return *l, true } + + return lex{value: zEOF}, false } // Extract the class number from CLASSxx @@ -966,12 +1293,12 @@ func locCheckEast(token string, longitude uint32) (uint32, bool) { } // "Eat" the rest of the "line". Return potential comments -func slurpRemainder(c chan lex, f string) (*ParseError, string) { - l := <-c +func slurpRemainder(c *zlexer, f string) (*ParseError, string) { + l, _ := c.Next() com := "" switch l.value { case zBlank: - l = <-c + l, _ = c.Next() com = l.comment if l.value != zNewline && l.value != zEOF { return &ParseError{f, "garbage after rdata", l}, "" diff --git a/vendor/github.com/miekg/dns/scan_rr.go b/vendor/github.com/miekg/dns/scan_rr.go index 67f884b0d..935d22c3f 100644 --- a/vendor/github.com/miekg/dns/scan_rr.go +++ b/vendor/github.com/miekg/dns/scan_rr.go @@ -11,7 +11,7 @@ type parserFunc struct { // Func defines the function that parses the tokens and returns the RR // or an error. The last string contains any comments in the line as // they returned by the lexer as well. - Func func(h RR_Header, c chan lex, origin string, file string) (RR, *ParseError, string) + Func func(h RR_Header, c *zlexer, origin string, file string) (RR, *ParseError, string) // Signals if the RR ending is of variable length, like TXT or records // that have Hexadecimal or Base64 as their last element in the Rdata. Records // that have a fixed ending or for instance A, AAAA, SOA and etc. @@ -23,7 +23,7 @@ type parserFunc struct { // After the rdata there may come a zBlank and then a zNewline // or immediately a zNewline. If this is not the case we flag // an *ParseError: garbage after rdata. -func setRR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setRR(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { parserfunc, ok := typeToparserFunc[h.Rrtype] if ok { r, e, cm := parserfunc.Func(h, c, o, f) @@ -45,9 +45,9 @@ func setRR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { // A remainder of the rdata with embedded spaces, return the parsed string (sans the spaces) // or an error -func endingToString(c chan lex, errstr, f string) (string, *ParseError, string) { +func endingToString(c *zlexer, errstr, f string) (string, *ParseError, string) { s := "" - l := <-c // zString + l, _ := c.Next() // zString for l.value != zNewline && l.value != zEOF { if l.err { return s, &ParseError{f, errstr, l}, "" @@ -59,16 +59,16 @@ func endingToString(c chan lex, errstr, f string) (string, *ParseError, string) default: return "", &ParseError{f, errstr, l}, "" } - l = <-c + l, _ = c.Next() } return s, nil, l.comment } // A remainder of the rdata with embedded spaces, split on unquoted whitespace // and return the parsed string slice or an error -func endingToTxtSlice(c chan lex, errstr, f string) ([]string, *ParseError, string) { +func endingToTxtSlice(c *zlexer, errstr, f string) ([]string, *ParseError, string) { // Get the remaining data until we see a zNewline - l := <-c + l, _ := c.Next() if l.err { return nil, &ParseError{f, errstr, l}, "" } @@ -117,7 +117,7 @@ func endingToTxtSlice(c chan lex, errstr, f string) ([]string, *ParseError, stri default: return nil, &ParseError{f, errstr, l}, "" } - l = <-c + l, _ = c.Next() } if quote { return nil, &ParseError{f, errstr, l}, "" @@ -125,12 +125,12 @@ func endingToTxtSlice(c chan lex, errstr, f string) ([]string, *ParseError, stri return s, nil, l.comment } -func setA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(A) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -141,12 +141,12 @@ func setA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setAAAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setAAAA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(AAAA) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -157,13 +157,13 @@ func setAAAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setNS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setNS(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(NS) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.Ns = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -175,13 +175,13 @@ func setNS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setPTR(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(PTR) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.Ptr = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -193,13 +193,13 @@ func setPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setNSAPPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setNSAPPTR(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(NSAPPTR) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.Ptr = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -211,13 +211,13 @@ func setNSAPPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) return rr, nil, "" } -func setRP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setRP(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(RP) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.Mbox = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -227,8 +227,8 @@ func setRP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Mbox = mbox - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() rr.Txt = l.token txt, txtOk := toAbsoluteName(l.token, o) @@ -240,13 +240,13 @@ func setRP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setMR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setMR(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(MR) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.Mr = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -258,13 +258,13 @@ func setMR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setMB(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setMB(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(MB) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.Mb = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -276,13 +276,13 @@ func setMB(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setMG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setMG(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(MG) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.Mg = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -294,7 +294,7 @@ func setMG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setHINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setHINFO(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(HINFO) rr.Hdr = h @@ -320,13 +320,13 @@ func setHINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setMINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setMINFO(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(MINFO) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.Rmail = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -336,8 +336,8 @@ func setMINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Rmail = rmail - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() rr.Email = l.token email, emailOk := toAbsoluteName(l.token, o) @@ -349,13 +349,13 @@ func setMINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setMF(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setMF(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(MF) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.Mf = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -367,13 +367,13 @@ func setMF(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setMD(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setMD(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(MD) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.Md = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -385,12 +385,12 @@ func setMD(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setMX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setMX(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(MX) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -400,8 +400,8 @@ func setMX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Preference = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString rr.Mx = l.token name, nameOk := toAbsoluteName(l.token, o) @@ -413,12 +413,12 @@ func setMX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setRT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setRT(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(RT) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -428,8 +428,8 @@ func setRT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Preference = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString rr.Host = l.token name, nameOk := toAbsoluteName(l.token, o) @@ -441,12 +441,12 @@ func setRT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setAFSDB(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setAFSDB(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(AFSDB) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -456,8 +456,8 @@ func setAFSDB(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Subtype = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString rr.Hostname = l.token name, nameOk := toAbsoluteName(l.token, o) @@ -468,12 +468,12 @@ func setAFSDB(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setX25(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setX25(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(X25) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -484,12 +484,12 @@ func setX25(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setKX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setKX(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(KX) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -499,8 +499,8 @@ func setKX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Preference = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString rr.Exchanger = l.token name, nameOk := toAbsoluteName(l.token, o) @@ -511,13 +511,13 @@ func setKX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setCNAME(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setCNAME(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(CNAME) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.Target = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -529,13 +529,13 @@ func setCNAME(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setDNAME(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setDNAME(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(DNAME) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.Target = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -547,13 +547,13 @@ func setDNAME(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setSOA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setSOA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(SOA) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.Ns = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -563,8 +563,8 @@ func setSOA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Ns = ns - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() rr.Mbox = l.token mbox, mboxOk := toAbsoluteName(l.token, o) @@ -573,14 +573,14 @@ func setSOA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Mbox = mbox - <-c // zBlank + c.Next() // zBlank var ( v uint32 ok bool ) for i := 0; i < 5; i++ { - l = <-c + l, _ = c.Next() if l.err { return nil, &ParseError{f, "bad SOA zone parameter", l}, "" } @@ -600,16 +600,16 @@ func setSOA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { switch i { case 0: rr.Serial = v - <-c // zBlank + c.Next() // zBlank case 1: rr.Refresh = v - <-c // zBlank + c.Next() // zBlank case 2: rr.Retry = v - <-c // zBlank + c.Next() // zBlank case 3: rr.Expire = v - <-c // zBlank + c.Next() // zBlank case 4: rr.Minttl = v } @@ -617,12 +617,12 @@ func setSOA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setSRV(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setSRV(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(SRV) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -632,24 +632,24 @@ func setSRV(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Priority = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString i, e = strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { return nil, &ParseError{f, "bad SRV Weight", l}, "" } rr.Weight = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString i, e = strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { return nil, &ParseError{f, "bad SRV Port", l}, "" } rr.Port = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString rr.Target = l.token name, nameOk := toAbsoluteName(l.token, o) @@ -660,12 +660,12 @@ func setSRV(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setNAPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setNAPTR(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(NAPTR) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -675,8 +675,8 @@ func setNAPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Order = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString i, e = strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { return nil, &ParseError{f, "bad NAPTR Preference", l}, "" @@ -684,15 +684,15 @@ func setNAPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { rr.Preference = uint16(i) // Flags - <-c // zBlank - l = <-c // _QUOTE + c.Next() // zBlank + l, _ = c.Next() // _QUOTE if l.value != zQuote { return nil, &ParseError{f, "bad NAPTR Flags", l}, "" } - l = <-c // Either String or Quote + l, _ = c.Next() // Either String or Quote if l.value == zString { rr.Flags = l.token - l = <-c // _QUOTE + l, _ = c.Next() // _QUOTE if l.value != zQuote { return nil, &ParseError{f, "bad NAPTR Flags", l}, "" } @@ -703,15 +703,15 @@ func setNAPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } // Service - <-c // zBlank - l = <-c // _QUOTE + c.Next() // zBlank + l, _ = c.Next() // _QUOTE if l.value != zQuote { return nil, &ParseError{f, "bad NAPTR Service", l}, "" } - l = <-c // Either String or Quote + l, _ = c.Next() // Either String or Quote if l.value == zString { rr.Service = l.token - l = <-c // _QUOTE + l, _ = c.Next() // _QUOTE if l.value != zQuote { return nil, &ParseError{f, "bad NAPTR Service", l}, "" } @@ -722,15 +722,15 @@ func setNAPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } // Regexp - <-c // zBlank - l = <-c // _QUOTE + c.Next() // zBlank + l, _ = c.Next() // _QUOTE if l.value != zQuote { return nil, &ParseError{f, "bad NAPTR Regexp", l}, "" } - l = <-c // Either String or Quote + l, _ = c.Next() // Either String or Quote if l.value == zString { rr.Regexp = l.token - l = <-c // _QUOTE + l, _ = c.Next() // _QUOTE if l.value != zQuote { return nil, &ParseError{f, "bad NAPTR Regexp", l}, "" } @@ -741,8 +741,8 @@ func setNAPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } // After quote no space?? - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString rr.Replacement = l.token name, nameOk := toAbsoluteName(l.token, o) @@ -753,13 +753,13 @@ func setNAPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setTALINK(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setTALINK(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(TALINK) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.PreviousName = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -769,8 +769,8 @@ func setTALINK(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.PreviousName = previousName - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() rr.NextName = l.token nextName, nextNameOk := toAbsoluteName(l.token, o) @@ -782,7 +782,7 @@ func setTALINK(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setLOC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setLOC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(LOC) rr.Hdr = h // Non zero defaults for LOC record, see RFC 1876, Section 3. @@ -792,8 +792,8 @@ func setLOC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { ok := false // North - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } i, e := strconv.ParseUint(l.token, 10, 32) @@ -802,9 +802,9 @@ func setLOC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Latitude = 1000 * 60 * 60 * uint32(i) - <-c // zBlank + c.Next() // zBlank // Either number, 'N' or 'S' - l = <-c + l, _ = c.Next() if rr.Latitude, ok = locCheckNorth(l.token, rr.Latitude); ok { goto East } @@ -814,16 +814,16 @@ func setLOC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Latitude += 1000 * 60 * uint32(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() if i, e := strconv.ParseFloat(l.token, 32); e != nil || l.err { return nil, &ParseError{f, "bad LOC Latitude seconds", l}, "" } else { rr.Latitude += uint32(1000 * i) } - <-c // zBlank + c.Next() // zBlank // Either number, 'N' or 'S' - l = <-c + l, _ = c.Next() if rr.Latitude, ok = locCheckNorth(l.token, rr.Latitude); ok { goto East } @@ -832,16 +832,16 @@ func setLOC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { East: // East - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() if i, e := strconv.ParseUint(l.token, 10, 32); e != nil || l.err { return nil, &ParseError{f, "bad LOC Longitude", l}, "" } else { rr.Longitude = 1000 * 60 * 60 * uint32(i) } - <-c // zBlank + c.Next() // zBlank // Either number, 'E' or 'W' - l = <-c + l, _ = c.Next() if rr.Longitude, ok = locCheckEast(l.token, rr.Longitude); ok { goto Altitude } @@ -850,16 +850,16 @@ East: } else { rr.Longitude += 1000 * 60 * uint32(i) } - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() if i, e := strconv.ParseFloat(l.token, 32); e != nil || l.err { return nil, &ParseError{f, "bad LOC Longitude seconds", l}, "" } else { rr.Longitude += uint32(1000 * i) } - <-c // zBlank + c.Next() // zBlank // Either number, 'E' or 'W' - l = <-c + l, _ = c.Next() if rr.Longitude, ok = locCheckEast(l.token, rr.Longitude); ok { goto Altitude } @@ -867,9 +867,9 @@ East: return nil, &ParseError{f, "bad LOC Longitude East/West", l}, "" Altitude: - <-c // zBlank - l = <-c - if l.length == 0 || l.err { + c.Next() // zBlank + l, _ = c.Next() + if len(l.token) == 0 || l.err { return nil, &ParseError{f, "bad LOC Altitude", l}, "" } if l.token[len(l.token)-1] == 'M' || l.token[len(l.token)-1] == 'm' { @@ -882,7 +882,7 @@ Altitude: } // And now optionally the other values - l = <-c + l, _ = c.Next() count := 0 for l.value != zNewline && l.value != zEOF { switch l.value { @@ -913,18 +913,18 @@ Altitude: default: return nil, &ParseError{f, "bad LOC Size, HorizPre or VertPre", l}, "" } - l = <-c + l, _ = c.Next() } return rr, nil, "" } -func setHIP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setHIP(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(HIP) rr.Hdr = h // HitLength is not represented - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, l.comment } @@ -934,24 +934,24 @@ func setHIP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.PublicKeyAlgorithm = uint8(i) - <-c // zBlank - l = <-c // zString - if l.length == 0 || l.err { + c.Next() // zBlank + l, _ = c.Next() // zString + if len(l.token) == 0 || l.err { return nil, &ParseError{f, "bad HIP Hit", l}, "" } rr.Hit = l.token // This can not contain spaces, see RFC 5205 Section 6. rr.HitLength = uint8(len(rr.Hit)) / 2 - <-c // zBlank - l = <-c // zString - if l.length == 0 || l.err { + c.Next() // zBlank + l, _ = c.Next() // zString + if len(l.token) == 0 || l.err { return nil, &ParseError{f, "bad HIP PublicKey", l}, "" } rr.PublicKey = l.token // This cannot contain spaces rr.PublicKeyLength = uint16(base64.StdEncoding.DecodedLen(len(rr.PublicKey))) // RendezvousServers (if any) - l = <-c + l, _ = c.Next() var xs []string for l.value != zNewline && l.value != zEOF { switch l.value { @@ -966,18 +966,18 @@ func setHIP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { default: return nil, &ParseError{f, "bad HIP RendezvousServers", l}, "" } - l = <-c + l, _ = c.Next() } rr.RendezvousServers = xs return rr, nil, l.comment } -func setCERT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setCERT(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(CERT) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, l.comment } @@ -988,15 +988,15 @@ func setCERT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } else { rr.Type = uint16(i) } - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString i, e := strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { return nil, &ParseError{f, "bad CERT KeyTag", l}, "" } rr.KeyTag = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString if v, ok := StringToAlgorithm[l.token]; ok { rr.Algorithm = v } else if i, e := strconv.ParseUint(l.token, 10, 8); e != nil { @@ -1012,7 +1012,7 @@ func setCERT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setOPENPGPKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setOPENPGPKEY(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(OPENPGPKEY) rr.Hdr = h @@ -1024,12 +1024,12 @@ func setOPENPGPKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, strin return rr, nil, c1 } -func setCSYNC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setCSYNC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(CSYNC) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, l.comment } j, e := strconv.ParseUint(l.token, 10, 32) @@ -1039,9 +1039,9 @@ func setCSYNC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Serial = uint32(j) - <-c // zBlank + c.Next() // zBlank - l = <-c + l, _ = c.Next() j, e = strconv.ParseUint(l.token, 10, 16) if e != nil { // Serial must be a number @@ -1054,14 +1054,15 @@ func setCSYNC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { k uint16 ok bool ) - l = <-c + l, _ = c.Next() for l.value != zNewline && l.value != zEOF { switch l.value { case zBlank: // Ok case zString: - if k, ok = StringToType[l.tokenUpper]; !ok { - if k, ok = typeToInt(l.tokenUpper); !ok { + tokenUpper := strings.ToUpper(l.token) + if k, ok = StringToType[tokenUpper]; !ok { + if k, ok = typeToInt(l.token); !ok { return nil, &ParseError{f, "bad CSYNC TypeBitMap", l}, "" } } @@ -1069,12 +1070,12 @@ func setCSYNC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { default: return nil, &ParseError{f, "bad CSYNC TypeBitMap", l}, "" } - l = <-c + l, _ = c.Next() } return rr, nil, l.comment } -func setSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setSIG(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { r, e, s := setRRSIG(h, c, o, f) if r != nil { return &SIG{*r.(*RRSIG)}, e, s @@ -1082,18 +1083,19 @@ func setSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, e, s } -func setRRSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setRRSIG(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(RRSIG) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, l.comment } - if t, ok := StringToType[l.tokenUpper]; !ok { - if strings.HasPrefix(l.tokenUpper, "TYPE") { - t, ok = typeToInt(l.tokenUpper) + tokenUpper := strings.ToUpper(l.token) + if t, ok := StringToType[tokenUpper]; !ok { + if strings.HasPrefix(tokenUpper, "TYPE") { + t, ok = typeToInt(l.token) if !ok { return nil, &ParseError{f, "bad RRSIG Typecovered", l}, "" } @@ -1105,32 +1107,32 @@ func setRRSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { rr.TypeCovered = t } - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, err := strconv.ParseUint(l.token, 10, 8) if err != nil || l.err { return nil, &ParseError{f, "bad RRSIG Algorithm", l}, "" } rr.Algorithm = uint8(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, err = strconv.ParseUint(l.token, 10, 8) if err != nil || l.err { return nil, &ParseError{f, "bad RRSIG Labels", l}, "" } rr.Labels = uint8(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, err = strconv.ParseUint(l.token, 10, 32) if err != nil || l.err { return nil, &ParseError{f, "bad RRSIG OrigTtl", l}, "" } rr.OrigTtl = uint32(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() if i, err := StringToTime(l.token); err != nil { // Try to see if all numeric and use it as epoch if i, err := strconv.ParseInt(l.token, 10, 64); err == nil { @@ -1143,8 +1145,8 @@ func setRRSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { rr.Expiration = i } - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() if i, err := StringToTime(l.token); err != nil { if i, err := strconv.ParseInt(l.token, 10, 64); err == nil { rr.Inception = uint32(i) @@ -1155,16 +1157,16 @@ func setRRSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { rr.Inception = i } - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, err = strconv.ParseUint(l.token, 10, 16) if err != nil || l.err { return nil, &ParseError{f, "bad RRSIG KeyTag", l}, "" } rr.KeyTag = uint16(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() rr.SignerName = l.token name, nameOk := toAbsoluteName(l.token, o) if l.err || !nameOk { @@ -1181,13 +1183,13 @@ func setRRSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setNSEC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setNSEC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(NSEC) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.NextDomain = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, l.comment } @@ -1202,14 +1204,15 @@ func setNSEC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { k uint16 ok bool ) - l = <-c + l, _ = c.Next() for l.value != zNewline && l.value != zEOF { switch l.value { case zBlank: // Ok case zString: - if k, ok = StringToType[l.tokenUpper]; !ok { - if k, ok = typeToInt(l.tokenUpper); !ok { + tokenUpper := strings.ToUpper(l.token) + if k, ok = StringToType[tokenUpper]; !ok { + if k, ok = typeToInt(l.token); !ok { return nil, &ParseError{f, "bad NSEC TypeBitMap", l}, "" } } @@ -1217,17 +1220,17 @@ func setNSEC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { default: return nil, &ParseError{f, "bad NSEC TypeBitMap", l}, "" } - l = <-c + l, _ = c.Next() } return rr, nil, l.comment } -func setNSEC3(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setNSEC3(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(NSEC3) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, l.comment } @@ -1236,22 +1239,22 @@ func setNSEC3(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, &ParseError{f, "bad NSEC3 Hash", l}, "" } rr.Hash = uint8(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { return nil, &ParseError{f, "bad NSEC3 Flags", l}, "" } rr.Flags = uint8(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { return nil, &ParseError{f, "bad NSEC3 Iterations", l}, "" } rr.Iterations = uint16(i) - <-c - l = <-c + c.Next() + l, _ = c.Next() if len(l.token) == 0 || l.err { return nil, &ParseError{f, "bad NSEC3 Salt", l}, "" } @@ -1260,8 +1263,8 @@ func setNSEC3(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { rr.Salt = l.token } - <-c - l = <-c + c.Next() + l, _ = c.Next() if len(l.token) == 0 || l.err { return nil, &ParseError{f, "bad NSEC3 NextDomain", l}, "" } @@ -1273,14 +1276,15 @@ func setNSEC3(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { k uint16 ok bool ) - l = <-c + l, _ = c.Next() for l.value != zNewline && l.value != zEOF { switch l.value { case zBlank: // Ok case zString: - if k, ok = StringToType[l.tokenUpper]; !ok { - if k, ok = typeToInt(l.tokenUpper); !ok { + tokenUpper := strings.ToUpper(l.token) + if k, ok = StringToType[tokenUpper]; !ok { + if k, ok = typeToInt(l.token); !ok { return nil, &ParseError{f, "bad NSEC3 TypeBitMap", l}, "" } } @@ -1288,17 +1292,17 @@ func setNSEC3(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { default: return nil, &ParseError{f, "bad NSEC3 TypeBitMap", l}, "" } - l = <-c + l, _ = c.Next() } return rr, nil, l.comment } -func setNSEC3PARAM(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setNSEC3PARAM(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(NSEC3PARAM) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -1307,22 +1311,22 @@ func setNSEC3PARAM(h RR_Header, c chan lex, o, f string) (RR, *ParseError, strin return nil, &ParseError{f, "bad NSEC3PARAM Hash", l}, "" } rr.Hash = uint8(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { return nil, &ParseError{f, "bad NSEC3PARAM Flags", l}, "" } rr.Flags = uint8(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { return nil, &ParseError{f, "bad NSEC3PARAM Iterations", l}, "" } rr.Iterations = uint16(i) - <-c - l = <-c + c.Next() + l, _ = c.Next() if l.token != "-" { rr.SaltLength = uint8(len(l.token)) rr.Salt = l.token @@ -1330,16 +1334,16 @@ func setNSEC3PARAM(h RR_Header, c chan lex, o, f string) (RR, *ParseError, strin return rr, nil, "" } -func setEUI48(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setEUI48(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(EUI48) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } - if l.length != 17 || l.err { + if len(l.token) != 17 || l.err { return nil, &ParseError{f, "bad EUI48 Address", l}, "" } addr := make([]byte, 12) @@ -1363,16 +1367,16 @@ func setEUI48(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setEUI64(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setEUI64(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(EUI64) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } - if l.length != 23 || l.err { + if len(l.token) != 23 || l.err { return nil, &ParseError{f, "bad EUI64 Address", l}, "" } addr := make([]byte, 16) @@ -1396,12 +1400,12 @@ func setEUI64(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setSSHFP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setSSHFP(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(SSHFP) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -1410,14 +1414,14 @@ func setSSHFP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, &ParseError{f, "bad SSHFP Algorithm", l}, "" } rr.Algorithm = uint8(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { return nil, &ParseError{f, "bad SSHFP Type", l}, "" } rr.Type = uint8(i) - <-c // zBlank + c.Next() // zBlank s, e1, c1 := endingToString(c, "bad SSHFP Fingerprint", f) if e1 != nil { return nil, e1, c1 @@ -1426,12 +1430,12 @@ func setSSHFP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setDNSKEYs(h RR_Header, c chan lex, o, f, typ string) (RR, *ParseError, string) { +func setDNSKEYs(h RR_Header, c *zlexer, o, f, typ string) (RR, *ParseError, string) { rr := new(DNSKEY) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, l.comment } @@ -1440,15 +1444,15 @@ func setDNSKEYs(h RR_Header, c chan lex, o, f, typ string) (RR, *ParseError, str return nil, &ParseError{f, "bad " + typ + " Flags", l}, "" } rr.Flags = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { return nil, &ParseError{f, "bad " + typ + " Protocol", l}, "" } rr.Protocol = uint8(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { return nil, &ParseError{f, "bad " + typ + " Algorithm", l}, "" @@ -1462,7 +1466,7 @@ func setDNSKEYs(h RR_Header, c chan lex, o, f, typ string) (RR, *ParseError, str return rr, nil, c1 } -func setKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setKEY(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { r, e, s := setDNSKEYs(h, c, o, f, "KEY") if r != nil { return &KEY{*r.(*DNSKEY)}, e, s @@ -1470,12 +1474,12 @@ func setKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, e, s } -func setDNSKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setDNSKEY(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { r, e, s := setDNSKEYs(h, c, o, f, "DNSKEY") return r, e, s } -func setCDNSKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setCDNSKEY(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { r, e, s := setDNSKEYs(h, c, o, f, "CDNSKEY") if r != nil { return &CDNSKEY{*r.(*DNSKEY)}, e, s @@ -1483,12 +1487,12 @@ func setCDNSKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) return nil, e, s } -func setRKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setRKEY(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(RKEY) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, l.comment } @@ -1497,15 +1501,15 @@ func setRKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, &ParseError{f, "bad RKEY Flags", l}, "" } rr.Flags = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { return nil, &ParseError{f, "bad RKEY Protocol", l}, "" } rr.Protocol = uint8(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { return nil, &ParseError{f, "bad RKEY Algorithm", l}, "" @@ -1519,7 +1523,7 @@ func setRKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setEID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setEID(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(EID) rr.Hdr = h s, e, c1 := endingToString(c, "bad EID Endpoint", f) @@ -1530,7 +1534,7 @@ func setEID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setNIMLOC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setNIMLOC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(NIMLOC) rr.Hdr = h s, e, c1 := endingToString(c, "bad NIMLOC Locator", f) @@ -1541,12 +1545,12 @@ func setNIMLOC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setGPOS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setGPOS(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(GPOS) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -1555,15 +1559,15 @@ func setGPOS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, &ParseError{f, "bad GPOS Longitude", l}, "" } rr.Longitude = l.token - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() _, e = strconv.ParseFloat(l.token, 64) if e != nil || l.err { return nil, &ParseError{f, "bad GPOS Latitude", l}, "" } rr.Latitude = l.token - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() _, e = strconv.ParseFloat(l.token, 64) if e != nil || l.err { return nil, &ParseError{f, "bad GPOS Altitude", l}, "" @@ -1572,12 +1576,12 @@ func setGPOS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setDSs(h RR_Header, c chan lex, o, f, typ string) (RR, *ParseError, string) { +func setDSs(h RR_Header, c *zlexer, o, f, typ string) (RR, *ParseError, string) { rr := new(DS) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, l.comment } @@ -1586,10 +1590,11 @@ func setDSs(h RR_Header, c chan lex, o, f, typ string) (RR, *ParseError, string) return nil, &ParseError{f, "bad " + typ + " KeyTag", l}, "" } rr.KeyTag = uint16(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() if i, e = strconv.ParseUint(l.token, 10, 8); e != nil { - i, ok := StringToAlgorithm[l.tokenUpper] + tokenUpper := strings.ToUpper(l.token) + i, ok := StringToAlgorithm[tokenUpper] if !ok || l.err { return nil, &ParseError{f, "bad " + typ + " Algorithm", l}, "" } @@ -1597,8 +1602,8 @@ func setDSs(h RR_Header, c chan lex, o, f, typ string) (RR, *ParseError, string) } else { rr.Algorithm = uint8(i) } - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { return nil, &ParseError{f, "bad " + typ + " DigestType", l}, "" @@ -1612,12 +1617,12 @@ func setDSs(h RR_Header, c chan lex, o, f, typ string) (RR, *ParseError, string) return rr, nil, c1 } -func setDS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setDS(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { r, e, s := setDSs(h, c, o, f, "DS") return r, e, s } -func setDLV(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setDLV(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { r, e, s := setDSs(h, c, o, f, "DLV") if r != nil { return &DLV{*r.(*DS)}, e, s @@ -1625,7 +1630,7 @@ func setDLV(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, e, s } -func setCDS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setCDS(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { r, e, s := setDSs(h, c, o, f, "CDS") if r != nil { return &CDS{*r.(*DS)}, e, s @@ -1633,12 +1638,12 @@ func setCDS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, e, s } -func setTA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setTA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(TA) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, l.comment } @@ -1647,10 +1652,11 @@ func setTA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, &ParseError{f, "bad TA KeyTag", l}, "" } rr.KeyTag = uint16(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() if i, e := strconv.ParseUint(l.token, 10, 8); e != nil { - i, ok := StringToAlgorithm[l.tokenUpper] + tokenUpper := strings.ToUpper(l.token) + i, ok := StringToAlgorithm[tokenUpper] if !ok || l.err { return nil, &ParseError{f, "bad TA Algorithm", l}, "" } @@ -1658,8 +1664,8 @@ func setTA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } else { rr.Algorithm = uint8(i) } - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { return nil, &ParseError{f, "bad TA DigestType", l}, "" @@ -1673,12 +1679,12 @@ func setTA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setTLSA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setTLSA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(TLSA) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, l.comment } @@ -1687,15 +1693,15 @@ func setTLSA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, &ParseError{f, "bad TLSA Usage", l}, "" } rr.Usage = uint8(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { return nil, &ParseError{f, "bad TLSA Selector", l}, "" } rr.Selector = uint8(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { return nil, &ParseError{f, "bad TLSA MatchingType", l}, "" @@ -1710,12 +1716,12 @@ func setTLSA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setSMIMEA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setSMIMEA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(SMIMEA) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, l.comment } @@ -1724,15 +1730,15 @@ func setSMIMEA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, &ParseError{f, "bad SMIMEA Usage", l}, "" } rr.Usage = uint8(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { return nil, &ParseError{f, "bad SMIMEA Selector", l}, "" } rr.Selector = uint8(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { return nil, &ParseError{f, "bad SMIMEA MatchingType", l}, "" @@ -1747,17 +1753,17 @@ func setSMIMEA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setRFC3597(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setRFC3597(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(RFC3597) rr.Hdr = h - l := <-c + l, _ := c.Next() if l.token != "\\#" { return nil, &ParseError{f, "bad RFC3597 Rdata", l}, "" } - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() rdlength, e := strconv.Atoi(l.token) if e != nil || l.err { return nil, &ParseError{f, "bad RFC3597 Rdata ", l}, "" @@ -1774,7 +1780,7 @@ func setRFC3597(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) return rr, nil, c1 } -func setSPF(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setSPF(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(SPF) rr.Hdr = h @@ -1786,7 +1792,7 @@ func setSPF(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setAVC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setAVC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(AVC) rr.Hdr = h @@ -1798,7 +1804,7 @@ func setAVC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setTXT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setTXT(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(TXT) rr.Hdr = h @@ -1812,7 +1818,7 @@ func setTXT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } // identical to setTXT -func setNINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setNINFO(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(NINFO) rr.Hdr = h @@ -1824,12 +1830,12 @@ func setNINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setURI(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setURI(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(URI) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -1838,15 +1844,15 @@ func setURI(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, &ParseError{f, "bad URI Priority", l}, "" } rr.Priority = uint16(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { return nil, &ParseError{f, "bad URI Weight", l}, "" } rr.Weight = uint16(i) - <-c // zBlank + c.Next() // zBlank s, err, c1 := endingToTxtSlice(c, "bad URI Target", f) if err != nil { return nil, err, "" @@ -1858,7 +1864,7 @@ func setURI(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setDHCID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setDHCID(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { // awesome record to parse! rr := new(DHCID) rr.Hdr = h @@ -1871,12 +1877,12 @@ func setDHCID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setNID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setNID(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(NID) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -1885,8 +1891,8 @@ func setNID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, &ParseError{f, "bad NID Preference", l}, "" } rr.Preference = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString u, err := stringToNodeID(l) if err != nil || l.err { return nil, err, "" @@ -1895,12 +1901,12 @@ func setNID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setL32(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setL32(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(L32) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -1909,8 +1915,8 @@ func setL32(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, &ParseError{f, "bad L32 Preference", l}, "" } rr.Preference = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString rr.Locator32 = net.ParseIP(l.token) if rr.Locator32 == nil || l.err { return nil, &ParseError{f, "bad L32 Locator", l}, "" @@ -1918,12 +1924,12 @@ func setL32(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setLP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setLP(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(LP) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -1933,8 +1939,8 @@ func setLP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Preference = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString rr.Fqdn = l.token name, nameOk := toAbsoluteName(l.token, o) if l.err || !nameOk { @@ -1945,12 +1951,12 @@ func setLP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setL64(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setL64(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(L64) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -1959,8 +1965,8 @@ func setL64(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, &ParseError{f, "bad L64 Preference", l}, "" } rr.Preference = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString u, err := stringToNodeID(l) if err != nil || l.err { return nil, err, "" @@ -1969,12 +1975,12 @@ func setL64(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setUID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setUID(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(UID) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -1986,12 +1992,12 @@ func setUID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setGID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setGID(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(GID) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -2003,7 +2009,7 @@ func setGID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setUINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setUINFO(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(UINFO) rr.Hdr = h @@ -2018,12 +2024,12 @@ func setUINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setPX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setPX(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(PX) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -2033,8 +2039,8 @@ func setPX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Preference = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString rr.Map822 = l.token map822, map822Ok := toAbsoluteName(l.token, o) if l.err || !map822Ok { @@ -2042,8 +2048,8 @@ func setPX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Map822 = map822 - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString rr.Mapx400 = l.token mapx400, mapx400Ok := toAbsoluteName(l.token, o) if l.err || !mapx400Ok { @@ -2054,12 +2060,12 @@ func setPX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setCAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setCAA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(CAA) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, l.comment } @@ -2069,14 +2075,14 @@ func setCAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Flag = uint8(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString if l.value != zString { return nil, &ParseError{f, "bad CAA Tag", l}, "" } rr.Tag = l.token - <-c // zBlank + c.Next() // zBlank s, e, c1 := endingToTxtSlice(c, "bad CAA Value", f) if e != nil { return nil, e, "" @@ -2088,43 +2094,43 @@ func setCAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setTKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setTKEY(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(TKEY) rr.Hdr = h - l := <-c + l, _ := c.Next() // Algorithm if l.value != zString { return nil, &ParseError{f, "bad TKEY algorithm", l}, "" } rr.Algorithm = l.token - <-c // zBlank + c.Next() // zBlank // Get the key length and key values - l = <-c + l, _ = c.Next() i, err := strconv.ParseUint(l.token, 10, 8) if err != nil || l.err { return nil, &ParseError{f, "bad TKEY key length", l}, "" } rr.KeySize = uint16(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() if l.value != zString { return nil, &ParseError{f, "bad TKEY key", l}, "" } rr.Key = l.token - <-c // zBlank + c.Next() // zBlank // Get the otherdata length and string data - l = <-c + l, _ = c.Next() i, err = strconv.ParseUint(l.token, 10, 8) if err != nil || l.err { return nil, &ParseError{f, "bad TKEY otherdata length", l}, "" } rr.OtherLen = uint16(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() if l.value != zString { return nil, &ParseError{f, "bad TKEY otherday", l}, "" } diff --git a/vendor/github.com/miekg/dns/scanner.go b/vendor/github.com/miekg/dns/scanner.go deleted file mode 100644 index 5b124ec59..000000000 --- a/vendor/github.com/miekg/dns/scanner.go +++ /dev/null @@ -1,56 +0,0 @@ -package dns - -// Implement a simple scanner, return a byte stream from an io reader. - -import ( - "bufio" - "context" - "io" - "text/scanner" -) - -type scan struct { - src *bufio.Reader - position scanner.Position - eof bool // Have we just seen a eof - ctx context.Context -} - -func scanInit(r io.Reader) (*scan, context.CancelFunc) { - s := new(scan) - s.src = bufio.NewReader(r) - s.position.Line = 1 - - ctx, cancel := context.WithCancel(context.Background()) - s.ctx = ctx - - return s, cancel -} - -// tokenText returns the next byte from the input -func (s *scan) tokenText() (byte, error) { - c, err := s.src.ReadByte() - if err != nil { - return c, err - } - select { - case <-s.ctx.Done(): - return c, context.Canceled - default: - break - } - - // delay the newline handling until the next token is delivered, - // fixes off-by-one errors when reporting a parse error. - if s.eof { - s.position.Line++ - s.position.Column = 0 - s.eof = false - } - if c == '\n' { - s.eof = true - return c, nil - } - s.position.Column++ - return c, nil -} diff --git a/vendor/github.com/miekg/dns/version.go b/vendor/github.com/miekg/dns/version.go index 403b9ef97..0b0e9b6d8 100644 --- a/vendor/github.com/miekg/dns/version.go +++ b/vendor/github.com/miekg/dns/version.go @@ -3,7 +3,7 @@ package dns import "fmt" // Version is current version of this library. -var Version = V{1, 0, 13} +var Version = V{1, 0, 14} // V holds the version of this library. type V struct { diff --git a/vendor/github.com/prometheus/client_golang/prometheus/http.go b/vendor/github.com/prometheus/client_golang/prometheus/http.go index 4b8e60273..9f0875bfc 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/http.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/http.go @@ -15,9 +15,7 @@ package prometheus import ( "bufio" - "bytes" "compress/gzip" - "fmt" "io" "net" "net/http" @@ -41,19 +39,10 @@ const ( acceptEncodingHeader = "Accept-Encoding" ) -var bufPool sync.Pool - -func getBuf() *bytes.Buffer { - buf := bufPool.Get() - if buf == nil { - return &bytes.Buffer{} - } - return buf.(*bytes.Buffer) -} - -func giveBuf(buf *bytes.Buffer) { - buf.Reset() - bufPool.Put(buf) +var gzipPool = sync.Pool{ + New: func() interface{} { + return gzip.NewWriter(nil) + }, } // Handler returns an HTTP handler for the DefaultGatherer. It is @@ -71,58 +60,40 @@ func Handler() http.Handler { // Deprecated: Use promhttp.HandlerFor(DefaultGatherer, promhttp.HandlerOpts{}) // instead. See there for further documentation. func UninstrumentedHandler() http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + return http.HandlerFunc(func(rsp http.ResponseWriter, req *http.Request) { mfs, err := DefaultGatherer.Gather() if err != nil { - http.Error(w, "An error has occurred during metrics collection:\n\n"+err.Error(), http.StatusInternalServerError) + httpError(rsp, err) return } contentType := expfmt.Negotiate(req.Header) - buf := getBuf() - defer giveBuf(buf) - writer, encoding := decorateWriter(req, buf) - enc := expfmt.NewEncoder(writer, contentType) - var lastErr error + header := rsp.Header() + header.Set(contentTypeHeader, string(contentType)) + + w := io.Writer(rsp) + if gzipAccepted(req.Header) { + header.Set(contentEncodingHeader, "gzip") + gz := gzipPool.Get().(*gzip.Writer) + defer gzipPool.Put(gz) + + gz.Reset(w) + defer gz.Close() + + w = gz + } + + enc := expfmt.NewEncoder(w, contentType) + for _, mf := range mfs { if err := enc.Encode(mf); err != nil { - lastErr = err - http.Error(w, "An error has occurred during metrics encoding:\n\n"+err.Error(), http.StatusInternalServerError) + httpError(rsp, err) return } } - if closer, ok := writer.(io.Closer); ok { - closer.Close() - } - if lastErr != nil && buf.Len() == 0 { - http.Error(w, "No metrics encoded, last error:\n\n"+lastErr.Error(), http.StatusInternalServerError) - return - } - header := w.Header() - header.Set(contentTypeHeader, string(contentType)) - header.Set(contentLengthHeader, fmt.Sprint(buf.Len())) - if encoding != "" { - header.Set(contentEncodingHeader, encoding) - } - w.Write(buf.Bytes()) }) } -// decorateWriter wraps a writer to handle gzip compression if requested. It -// returns the decorated writer and the appropriate "Content-Encoding" header -// (which is empty if no compression is enabled). -func decorateWriter(request *http.Request, writer io.Writer) (io.Writer, string) { - header := request.Header.Get(acceptEncodingHeader) - parts := strings.Split(header, ",") - for _, part := range parts { - part = strings.TrimSpace(part) - if part == "gzip" || strings.HasPrefix(part, "gzip;") { - return gzip.NewWriter(writer), "gzip" - } - } - return writer, "" -} - var instLabels = []string{"method", "code"} type nower interface { @@ -503,3 +474,31 @@ func sanitizeCode(s int) string { return strconv.Itoa(s) } } + +// gzipAccepted returns whether the client will accept gzip-encoded content. +func gzipAccepted(header http.Header) bool { + a := header.Get(acceptEncodingHeader) + parts := strings.Split(a, ",") + for _, part := range parts { + part = strings.TrimSpace(part) + if part == "gzip" || strings.HasPrefix(part, "gzip;") { + return true + } + } + return false +} + +// httpError removes any content-encoding header and then calls http.Error with +// the provided error and http.StatusInternalServerErrer. Error contents is +// supposed to be uncompressed plain text. However, same as with a plain +// http.Error, any header settings will be void if the header has already been +// sent. The error message will still be written to the writer, but it will +// probably be of limited use. +func httpError(rsp http.ResponseWriter, err error) { + rsp.Header().Del(contentEncodingHeader) + http.Error( + rsp, + "An error has occurred while serving metrics:\n\n"+err.Error(), + http.StatusInternalServerError, + ) +} diff --git a/vendor/github.com/prometheus/common/expfmt/text_create.go b/vendor/github.com/prometheus/common/expfmt/text_create.go index 46b74364e..8e473d0fe 100644 --- a/vendor/github.com/prometheus/common/expfmt/text_create.go +++ b/vendor/github.com/prometheus/common/expfmt/text_create.go @@ -19,6 +19,7 @@ import ( "io" "math" "strconv" + "strings" "sync" "github.com/prometheus/common/model" @@ -43,7 +44,7 @@ const ( var ( bufPool = sync.Pool{ New: func() interface{} { - return bytes.NewBuffer(make([]byte, 0, initialNumBufSize)) + return bytes.NewBuffer(make([]byte, 0, initialBufSize)) }, } numBufPool = sync.Pool{ @@ -416,32 +417,17 @@ func writeLabelPairs( // writeEscapedString replaces '\' by '\\', new line character by '\n', and - if // includeDoubleQuote is true - '"' by '\"'. +var ( + escaper = strings.NewReplacer("\\", `\\`, "\n", `\n`) + quotedEscaper = strings.NewReplacer("\\", `\\`, "\n", `\n`, "\"", `\"`) +) + func writeEscapedString(w enhancedWriter, v string, includeDoubleQuote bool) (int, error) { - var ( - written, n int - err error - ) - for _, r := range v { - switch r { - case '\\': - n, err = w.WriteString(`\\`) - case '\n': - n, err = w.WriteString(`\n`) - case '"': - if includeDoubleQuote { - n, err = w.WriteString(`\"`) - } else { - n, err = w.WriteRune(r) - } - default: - n, err = w.WriteRune(r) - } - written += n - if err != nil { - return written, err - } + if includeDoubleQuote { + return quotedEscaper.WriteString(w, v) + } else { + return escaper.WriteString(w, v) } - return written, nil } // writeFloat is equivalent to fmt.Fprint with a float64 argument but hardcodes diff --git a/vendor/github.com/prometheus/common/model/time.go b/vendor/github.com/prometheus/common/model/time.go index 74ed5a9f7..46259b1f1 100644 --- a/vendor/github.com/prometheus/common/model/time.go +++ b/vendor/github.com/prometheus/common/model/time.go @@ -43,7 +43,7 @@ const ( // (1970-01-01 00:00 UTC) excluding leap seconds. type Time int64 -// Interval describes and interval between two timestamps. +// Interval describes an interval between two timestamps. type Interval struct { Start, End Time } diff --git a/vendor/github.com/rcrowley/go-metrics/LICENSE b/vendor/github.com/rcrowley/go-metrics/LICENSE new file mode 100644 index 000000000..363fa9ee7 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/LICENSE @@ -0,0 +1,29 @@ +Copyright 2012 Richard Crowley. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + +THIS SOFTWARE IS PROVIDED BY RICHARD CROWLEY ``AS IS'' AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL RICHARD CROWLEY OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation +are those of the authors and should not be interpreted as representing +official policies, either expressed or implied, of Richard Crowley. diff --git a/vendor/github.com/rcrowley/go-metrics/README.md b/vendor/github.com/rcrowley/go-metrics/README.md new file mode 100644 index 000000000..b7356b5fc --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/README.md @@ -0,0 +1,168 @@ +go-metrics +========== + +![travis build status](https://travis-ci.org/rcrowley/go-metrics.svg?branch=master) + +Go port of Coda Hale's Metrics library: . + +Documentation: . + +Usage +----- + +Create and update metrics: + +```go +c := metrics.NewCounter() +metrics.Register("foo", c) +c.Inc(47) + +g := metrics.NewGauge() +metrics.Register("bar", g) +g.Update(47) + +r := NewRegistry() +g := metrics.NewRegisteredFunctionalGauge("cache-evictions", r, func() int64 { return cache.getEvictionsCount() }) + +s := metrics.NewExpDecaySample(1028, 0.015) // or metrics.NewUniformSample(1028) +h := metrics.NewHistogram(s) +metrics.Register("baz", h) +h.Update(47) + +m := metrics.NewMeter() +metrics.Register("quux", m) +m.Mark(47) + +t := metrics.NewTimer() +metrics.Register("bang", t) +t.Time(func() {}) +t.Update(47) +``` + +Register() is not threadsafe. For threadsafe metric registration use +GetOrRegister: + +```go +t := metrics.GetOrRegisterTimer("account.create.latency", nil) +t.Time(func() {}) +t.Update(47) +``` + +**NOTE:** Be sure to unregister short-lived meters and timers otherwise they will +leak memory: + +```go +// Will call Stop() on the Meter to allow for garbage collection +metrics.Unregister("quux") +// Or similarly for a Timer that embeds a Meter +metrics.Unregister("bang") +``` + +Periodically log every metric in human-readable form to standard error: + +```go +go metrics.Log(metrics.DefaultRegistry, 5 * time.Second, log.New(os.Stderr, "metrics: ", log.Lmicroseconds)) +``` + +Periodically log every metric in slightly-more-parseable form to syslog: + +```go +w, _ := syslog.Dial("unixgram", "/dev/log", syslog.LOG_INFO, "metrics") +go metrics.Syslog(metrics.DefaultRegistry, 60e9, w) +``` + +Periodically emit every metric to Graphite using the [Graphite client](https://github.com/cyberdelia/go-metrics-graphite): + +```go + +import "github.com/cyberdelia/go-metrics-graphite" + +addr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:2003") +go graphite.Graphite(metrics.DefaultRegistry, 10e9, "metrics", addr) +``` + +Periodically emit every metric into InfluxDB: + +**NOTE:** this has been pulled out of the library due to constant fluctuations +in the InfluxDB API. In fact, all client libraries are on their way out. see +issues [#121](https://github.com/rcrowley/go-metrics/issues/121) and +[#124](https://github.com/rcrowley/go-metrics/issues/124) for progress and details. + +```go +import "github.com/vrischmann/go-metrics-influxdb" + +go influxdb.InfluxDB(metrics.DefaultRegistry, + 10e9, + "127.0.0.1:8086", + "database-name", + "username", + "password" +) +``` + +Periodically upload every metric to Librato using the [Librato client](https://github.com/mihasya/go-metrics-librato): + +**Note**: the client included with this repository under the `librato` package +has been deprecated and moved to the repository linked above. + +```go +import "github.com/mihasya/go-metrics-librato" + +go librato.Librato(metrics.DefaultRegistry, + 10e9, // interval + "example@example.com", // account owner email address + "token", // Librato API token + "hostname", // source + []float64{0.95}, // percentiles to send + time.Millisecond, // time unit +) +``` + +Periodically emit every metric to StatHat: + +```go +import "github.com/rcrowley/go-metrics/stathat" + +go stathat.Stathat(metrics.DefaultRegistry, 10e9, "example@example.com") +``` + +Maintain all metrics along with expvars at `/debug/metrics`: + +This uses the same mechanism as [the official expvar](http://golang.org/pkg/expvar/) +but exposed under `/debug/metrics`, which shows a json representation of all your usual expvars +as well as all your go-metrics. + + +```go +import "github.com/rcrowley/go-metrics/exp" + +exp.Exp(metrics.DefaultRegistry) +``` + +Installation +------------ + +```sh +go get github.com/rcrowley/go-metrics +``` + +StatHat support additionally requires their Go client: + +```sh +go get github.com/stathat/go +``` + +Publishing Metrics +------------------ + +Clients are available for the following destinations: + +* Librato - https://github.com/mihasya/go-metrics-librato +* Graphite - https://github.com/cyberdelia/go-metrics-graphite +* InfluxDB - https://github.com/vrischmann/go-metrics-influxdb +* Ganglia - https://github.com/appscode/metlia +* Prometheus - https://github.com/deathowl/go-metrics-prometheus +* DataDog - https://github.com/syntaqx/go-metrics-datadog +* SignalFX - https://github.com/pascallouisperez/go-metrics-signalfx +* Honeycomb - https://github.com/getspine/go-metrics-honeycomb +* Wavefront - https://github.com/wavefrontHQ/go-metrics-wavefront diff --git a/vendor/github.com/rcrowley/go-metrics/counter.go b/vendor/github.com/rcrowley/go-metrics/counter.go new file mode 100644 index 000000000..bb7b039cb --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/counter.go @@ -0,0 +1,112 @@ +package metrics + +import "sync/atomic" + +// Counters hold an int64 value that can be incremented and decremented. +type Counter interface { + Clear() + Count() int64 + Dec(int64) + Inc(int64) + Snapshot() Counter +} + +// GetOrRegisterCounter returns an existing Counter or constructs and registers +// a new StandardCounter. +func GetOrRegisterCounter(name string, r Registry) Counter { + if nil == r { + r = DefaultRegistry + } + return r.GetOrRegister(name, NewCounter).(Counter) +} + +// NewCounter constructs a new StandardCounter. +func NewCounter() Counter { + if UseNilMetrics { + return NilCounter{} + } + return &StandardCounter{0} +} + +// NewRegisteredCounter constructs and registers a new StandardCounter. +func NewRegisteredCounter(name string, r Registry) Counter { + c := NewCounter() + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// CounterSnapshot is a read-only copy of another Counter. +type CounterSnapshot int64 + +// Clear panics. +func (CounterSnapshot) Clear() { + panic("Clear called on a CounterSnapshot") +} + +// Count returns the count at the time the snapshot was taken. +func (c CounterSnapshot) Count() int64 { return int64(c) } + +// Dec panics. +func (CounterSnapshot) Dec(int64) { + panic("Dec called on a CounterSnapshot") +} + +// Inc panics. +func (CounterSnapshot) Inc(int64) { + panic("Inc called on a CounterSnapshot") +} + +// Snapshot returns the snapshot. +func (c CounterSnapshot) Snapshot() Counter { return c } + +// NilCounter is a no-op Counter. +type NilCounter struct{} + +// Clear is a no-op. +func (NilCounter) Clear() {} + +// Count is a no-op. +func (NilCounter) Count() int64 { return 0 } + +// Dec is a no-op. +func (NilCounter) Dec(i int64) {} + +// Inc is a no-op. +func (NilCounter) Inc(i int64) {} + +// Snapshot is a no-op. +func (NilCounter) Snapshot() Counter { return NilCounter{} } + +// StandardCounter is the standard implementation of a Counter and uses the +// sync/atomic package to manage a single int64 value. +type StandardCounter struct { + count int64 +} + +// Clear sets the counter to zero. +func (c *StandardCounter) Clear() { + atomic.StoreInt64(&c.count, 0) +} + +// Count returns the current count. +func (c *StandardCounter) Count() int64 { + return atomic.LoadInt64(&c.count) +} + +// Dec decrements the counter by the given amount. +func (c *StandardCounter) Dec(i int64) { + atomic.AddInt64(&c.count, -i) +} + +// Inc increments the counter by the given amount. +func (c *StandardCounter) Inc(i int64) { + atomic.AddInt64(&c.count, i) +} + +// Snapshot returns a read-only copy of the counter. +func (c *StandardCounter) Snapshot() Counter { + return CounterSnapshot(c.Count()) +} diff --git a/vendor/github.com/rcrowley/go-metrics/debug.go b/vendor/github.com/rcrowley/go-metrics/debug.go new file mode 100644 index 000000000..043ccefab --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/debug.go @@ -0,0 +1,76 @@ +package metrics + +import ( + "runtime/debug" + "time" +) + +var ( + debugMetrics struct { + GCStats struct { + LastGC Gauge + NumGC Gauge + Pause Histogram + //PauseQuantiles Histogram + PauseTotal Gauge + } + ReadGCStats Timer + } + gcStats debug.GCStats +) + +// Capture new values for the Go garbage collector statistics exported in +// debug.GCStats. This is designed to be called as a goroutine. +func CaptureDebugGCStats(r Registry, d time.Duration) { + for _ = range time.Tick(d) { + CaptureDebugGCStatsOnce(r) + } +} + +// Capture new values for the Go garbage collector statistics exported in +// debug.GCStats. This is designed to be called in a background goroutine. +// Giving a registry which has not been given to RegisterDebugGCStats will +// panic. +// +// Be careful (but much less so) with this because debug.ReadGCStats calls +// the C function runtime·lock(runtime·mheap) which, while not a stop-the-world +// operation, isn't something you want to be doing all the time. +func CaptureDebugGCStatsOnce(r Registry) { + lastGC := gcStats.LastGC + t := time.Now() + debug.ReadGCStats(&gcStats) + debugMetrics.ReadGCStats.UpdateSince(t) + + debugMetrics.GCStats.LastGC.Update(int64(gcStats.LastGC.UnixNano())) + debugMetrics.GCStats.NumGC.Update(int64(gcStats.NumGC)) + if lastGC != gcStats.LastGC && 0 < len(gcStats.Pause) { + debugMetrics.GCStats.Pause.Update(int64(gcStats.Pause[0])) + } + //debugMetrics.GCStats.PauseQuantiles.Update(gcStats.PauseQuantiles) + debugMetrics.GCStats.PauseTotal.Update(int64(gcStats.PauseTotal)) +} + +// Register metrics for the Go garbage collector statistics exported in +// debug.GCStats. The metrics are named by their fully-qualified Go symbols, +// i.e. debug.GCStats.PauseTotal. +func RegisterDebugGCStats(r Registry) { + debugMetrics.GCStats.LastGC = NewGauge() + debugMetrics.GCStats.NumGC = NewGauge() + debugMetrics.GCStats.Pause = NewHistogram(NewExpDecaySample(1028, 0.015)) + //debugMetrics.GCStats.PauseQuantiles = NewHistogram(NewExpDecaySample(1028, 0.015)) + debugMetrics.GCStats.PauseTotal = NewGauge() + debugMetrics.ReadGCStats = NewTimer() + + r.Register("debug.GCStats.LastGC", debugMetrics.GCStats.LastGC) + r.Register("debug.GCStats.NumGC", debugMetrics.GCStats.NumGC) + r.Register("debug.GCStats.Pause", debugMetrics.GCStats.Pause) + //r.Register("debug.GCStats.PauseQuantiles", debugMetrics.GCStats.PauseQuantiles) + r.Register("debug.GCStats.PauseTotal", debugMetrics.GCStats.PauseTotal) + r.Register("debug.ReadGCStats", debugMetrics.ReadGCStats) +} + +// Allocate an initial slice for gcStats.Pause to avoid allocations during +// normal operation. +func init() { + gcStats.Pause = make([]time.Duration, 11) +} diff --git a/vendor/github.com/rcrowley/go-metrics/ewma.go b/vendor/github.com/rcrowley/go-metrics/ewma.go new file mode 100644 index 000000000..a8183dd7e --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/ewma.go @@ -0,0 +1,138 @@ +package metrics + +import ( + "math" + "sync" + "sync/atomic" +) + +// EWMAs continuously calculate an exponentially-weighted moving average +// based on an outside source of clock ticks. +type EWMA interface { + Rate() float64 + Snapshot() EWMA + Tick() + Update(int64) +} + +// NewEWMA constructs a new EWMA with the given alpha. +func NewEWMA(alpha float64) EWMA { + if UseNilMetrics { + return NilEWMA{} + } + return &StandardEWMA{alpha: alpha} +} + +// NewEWMA1 constructs a new EWMA for a one-minute moving average. +func NewEWMA1() EWMA { + return NewEWMA(1 - math.Exp(-5.0/60.0/1)) +} + +// NewEWMA5 constructs a new EWMA for a five-minute moving average. +func NewEWMA5() EWMA { + return NewEWMA(1 - math.Exp(-5.0/60.0/5)) +} + +// NewEWMA15 constructs a new EWMA for a fifteen-minute moving average. +func NewEWMA15() EWMA { + return NewEWMA(1 - math.Exp(-5.0/60.0/15)) +} + +// EWMASnapshot is a read-only copy of another EWMA. +type EWMASnapshot float64 + +// Rate returns the rate of events per second at the time the snapshot was +// taken. +func (a EWMASnapshot) Rate() float64 { return float64(a) } + +// Snapshot returns the snapshot. +func (a EWMASnapshot) Snapshot() EWMA { return a } + +// Tick panics. +func (EWMASnapshot) Tick() { + panic("Tick called on an EWMASnapshot") +} + +// Update panics. +func (EWMASnapshot) Update(int64) { + panic("Update called on an EWMASnapshot") +} + +// NilEWMA is a no-op EWMA. +type NilEWMA struct{} + +// Rate is a no-op. +func (NilEWMA) Rate() float64 { return 0.0 } + +// Snapshot is a no-op. +func (NilEWMA) Snapshot() EWMA { return NilEWMA{} } + +// Tick is a no-op. +func (NilEWMA) Tick() {} + +// Update is a no-op. +func (NilEWMA) Update(n int64) {} + +// StandardEWMA is the standard implementation of an EWMA and tracks the number +// of uncounted events and processes them on each tick. It uses the +// sync/atomic package to manage uncounted events. +type StandardEWMA struct { + uncounted int64 // /!\ this should be the first member to ensure 64-bit alignment + alpha float64 + rate uint64 + init uint32 + mutex sync.Mutex +} + +// Rate returns the moving average rate of events per second. +func (a *StandardEWMA) Rate() float64 { + currentRate := math.Float64frombits(atomic.LoadUint64(&a.rate)) * float64(1e9) + return currentRate +} + +// Snapshot returns a read-only copy of the EWMA. +func (a *StandardEWMA) Snapshot() EWMA { + return EWMASnapshot(a.Rate()) +} + +// Tick ticks the clock to update the moving average. It assumes it is called +// every five seconds. +func (a *StandardEWMA) Tick() { + // Optimization to avoid mutex locking in the hot-path. + if atomic.LoadUint32(&a.init) == 1 { + a.updateRate(a.fetchInstantRate()) + } else { + // Slow-path: this is only needed on the first Tick() and preserves transactional updating + // of init and rate in the else block. The first conditional is needed below because + // a different thread could have set a.init = 1 between the time of the first atomic load and when + // the lock was acquired. + a.mutex.Lock() + if atomic.LoadUint32(&a.init) == 1 { + // The fetchInstantRate() uses atomic loading, which is unecessary in this critical section + // but again, this section is only invoked on the first successful Tick() operation. + a.updateRate(a.fetchInstantRate()) + } else { + atomic.StoreUint32(&a.init, 1) + atomic.StoreUint64(&a.rate, math.Float64bits(a.fetchInstantRate())) + } + a.mutex.Unlock() + } +} + +func (a *StandardEWMA) fetchInstantRate() float64 { + count := atomic.LoadInt64(&a.uncounted) + atomic.AddInt64(&a.uncounted, -count) + instantRate := float64(count) / float64(5e9) + return instantRate +} + +func (a *StandardEWMA) updateRate(instantRate float64) { + currentRate := math.Float64frombits(atomic.LoadUint64(&a.rate)) + currentRate += a.alpha * (instantRate - currentRate) + atomic.StoreUint64(&a.rate, math.Float64bits(currentRate)) +} + +// Update adds n uncounted events. +func (a *StandardEWMA) Update(n int64) { + atomic.AddInt64(&a.uncounted, n) +} diff --git a/vendor/github.com/rcrowley/go-metrics/gauge.go b/vendor/github.com/rcrowley/go-metrics/gauge.go new file mode 100644 index 000000000..cb57a9388 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/gauge.go @@ -0,0 +1,120 @@ +package metrics + +import "sync/atomic" + +// Gauges hold an int64 value that can be set arbitrarily. +type Gauge interface { + Snapshot() Gauge + Update(int64) + Value() int64 +} + +// GetOrRegisterGauge returns an existing Gauge or constructs and registers a +// new StandardGauge. +func GetOrRegisterGauge(name string, r Registry) Gauge { + if nil == r { + r = DefaultRegistry + } + return r.GetOrRegister(name, NewGauge).(Gauge) +} + +// NewGauge constructs a new StandardGauge. +func NewGauge() Gauge { + if UseNilMetrics { + return NilGauge{} + } + return &StandardGauge{0} +} + +// NewRegisteredGauge constructs and registers a new StandardGauge. +func NewRegisteredGauge(name string, r Registry) Gauge { + c := NewGauge() + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// NewFunctionalGauge constructs a new FunctionalGauge. +func NewFunctionalGauge(f func() int64) Gauge { + if UseNilMetrics { + return NilGauge{} + } + return &FunctionalGauge{value: f} +} + +// NewRegisteredFunctionalGauge constructs and registers a new StandardGauge. +func NewRegisteredFunctionalGauge(name string, r Registry, f func() int64) Gauge { + c := NewFunctionalGauge(f) + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// GaugeSnapshot is a read-only copy of another Gauge. +type GaugeSnapshot int64 + +// Snapshot returns the snapshot. +func (g GaugeSnapshot) Snapshot() Gauge { return g } + +// Update panics. +func (GaugeSnapshot) Update(int64) { + panic("Update called on a GaugeSnapshot") +} + +// Value returns the value at the time the snapshot was taken. +func (g GaugeSnapshot) Value() int64 { return int64(g) } + +// NilGauge is a no-op Gauge. +type NilGauge struct{} + +// Snapshot is a no-op. +func (NilGauge) Snapshot() Gauge { return NilGauge{} } + +// Update is a no-op. +func (NilGauge) Update(v int64) {} + +// Value is a no-op. +func (NilGauge) Value() int64 { return 0 } + +// StandardGauge is the standard implementation of a Gauge and uses the +// sync/atomic package to manage a single int64 value. +type StandardGauge struct { + value int64 +} + +// Snapshot returns a read-only copy of the gauge. +func (g *StandardGauge) Snapshot() Gauge { + return GaugeSnapshot(g.Value()) +} + +// Update updates the gauge's value. +func (g *StandardGauge) Update(v int64) { + atomic.StoreInt64(&g.value, v) +} + +// Value returns the gauge's current value. +func (g *StandardGauge) Value() int64 { + return atomic.LoadInt64(&g.value) +} + +// FunctionalGauge returns value from given function +type FunctionalGauge struct { + value func() int64 +} + +// Value returns the gauge's current value. +func (g FunctionalGauge) Value() int64 { + return g.value() +} + +// Snapshot returns the snapshot. +func (g FunctionalGauge) Snapshot() Gauge { return GaugeSnapshot(g.Value()) } + +// Update panics. +func (FunctionalGauge) Update(int64) { + panic("Update called on a FunctionalGauge") +} diff --git a/vendor/github.com/rcrowley/go-metrics/gauge_float64.go b/vendor/github.com/rcrowley/go-metrics/gauge_float64.go new file mode 100644 index 000000000..3962e6db0 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/gauge_float64.go @@ -0,0 +1,125 @@ +package metrics + +import ( + "math" + "sync/atomic" +) + +// GaugeFloat64s hold a float64 value that can be set arbitrarily. +type GaugeFloat64 interface { + Snapshot() GaugeFloat64 + Update(float64) + Value() float64 +} + +// GetOrRegisterGaugeFloat64 returns an existing GaugeFloat64 or constructs and registers a +// new StandardGaugeFloat64. +func GetOrRegisterGaugeFloat64(name string, r Registry) GaugeFloat64 { + if nil == r { + r = DefaultRegistry + } + return r.GetOrRegister(name, NewGaugeFloat64()).(GaugeFloat64) +} + +// NewGaugeFloat64 constructs a new StandardGaugeFloat64. +func NewGaugeFloat64() GaugeFloat64 { + if UseNilMetrics { + return NilGaugeFloat64{} + } + return &StandardGaugeFloat64{ + value: 0.0, + } +} + +// NewRegisteredGaugeFloat64 constructs and registers a new StandardGaugeFloat64. +func NewRegisteredGaugeFloat64(name string, r Registry) GaugeFloat64 { + c := NewGaugeFloat64() + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// NewFunctionalGauge constructs a new FunctionalGauge. +func NewFunctionalGaugeFloat64(f func() float64) GaugeFloat64 { + if UseNilMetrics { + return NilGaugeFloat64{} + } + return &FunctionalGaugeFloat64{value: f} +} + +// NewRegisteredFunctionalGauge constructs and registers a new StandardGauge. +func NewRegisteredFunctionalGaugeFloat64(name string, r Registry, f func() float64) GaugeFloat64 { + c := NewFunctionalGaugeFloat64(f) + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// GaugeFloat64Snapshot is a read-only copy of another GaugeFloat64. +type GaugeFloat64Snapshot float64 + +// Snapshot returns the snapshot. +func (g GaugeFloat64Snapshot) Snapshot() GaugeFloat64 { return g } + +// Update panics. +func (GaugeFloat64Snapshot) Update(float64) { + panic("Update called on a GaugeFloat64Snapshot") +} + +// Value returns the value at the time the snapshot was taken. +func (g GaugeFloat64Snapshot) Value() float64 { return float64(g) } + +// NilGauge is a no-op Gauge. +type NilGaugeFloat64 struct{} + +// Snapshot is a no-op. +func (NilGaugeFloat64) Snapshot() GaugeFloat64 { return NilGaugeFloat64{} } + +// Update is a no-op. +func (NilGaugeFloat64) Update(v float64) {} + +// Value is a no-op. +func (NilGaugeFloat64) Value() float64 { return 0.0 } + +// StandardGaugeFloat64 is the standard implementation of a GaugeFloat64 and uses +// sync.Mutex to manage a single float64 value. +type StandardGaugeFloat64 struct { + value uint64 +} + +// Snapshot returns a read-only copy of the gauge. +func (g *StandardGaugeFloat64) Snapshot() GaugeFloat64 { + return GaugeFloat64Snapshot(g.Value()) +} + +// Update updates the gauge's value. +func (g *StandardGaugeFloat64) Update(v float64) { + atomic.StoreUint64(&g.value, math.Float64bits(v)) +} + +// Value returns the gauge's current value. +func (g *StandardGaugeFloat64) Value() float64 { + return math.Float64frombits(atomic.LoadUint64(&g.value)) +} + +// FunctionalGaugeFloat64 returns value from given function +type FunctionalGaugeFloat64 struct { + value func() float64 +} + +// Value returns the gauge's current value. +func (g FunctionalGaugeFloat64) Value() float64 { + return g.value() +} + +// Snapshot returns the snapshot. +func (g FunctionalGaugeFloat64) Snapshot() GaugeFloat64 { return GaugeFloat64Snapshot(g.Value()) } + +// Update panics. +func (FunctionalGaugeFloat64) Update(float64) { + panic("Update called on a FunctionalGaugeFloat64") +} diff --git a/vendor/github.com/rcrowley/go-metrics/graphite.go b/vendor/github.com/rcrowley/go-metrics/graphite.go new file mode 100644 index 000000000..abd0a7d29 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/graphite.go @@ -0,0 +1,113 @@ +package metrics + +import ( + "bufio" + "fmt" + "log" + "net" + "strconv" + "strings" + "time" +) + +// GraphiteConfig provides a container with configuration parameters for +// the Graphite exporter +type GraphiteConfig struct { + Addr *net.TCPAddr // Network address to connect to + Registry Registry // Registry to be exported + FlushInterval time.Duration // Flush interval + DurationUnit time.Duration // Time conversion unit for durations + Prefix string // Prefix to be prepended to metric names + Percentiles []float64 // Percentiles to export from timers and histograms +} + +// Graphite is a blocking exporter function which reports metrics in r +// to a graphite server located at addr, flushing them every d duration +// and prepending metric names with prefix. +func Graphite(r Registry, d time.Duration, prefix string, addr *net.TCPAddr) { + GraphiteWithConfig(GraphiteConfig{ + Addr: addr, + Registry: r, + FlushInterval: d, + DurationUnit: time.Nanosecond, + Prefix: prefix, + Percentiles: []float64{0.5, 0.75, 0.95, 0.99, 0.999}, + }) +} + +// GraphiteWithConfig is a blocking exporter function just like Graphite, +// but it takes a GraphiteConfig instead. +func GraphiteWithConfig(c GraphiteConfig) { + log.Printf("WARNING: This go-metrics client has been DEPRECATED! It has been moved to https://github.com/cyberdelia/go-metrics-graphite and will be removed from rcrowley/go-metrics on August 12th 2015") + for _ = range time.Tick(c.FlushInterval) { + if err := graphite(&c); nil != err { + log.Println(err) + } + } +} + +// GraphiteOnce performs a single submission to Graphite, returning a +// non-nil error on failed connections. This can be used in a loop +// similar to GraphiteWithConfig for custom error handling. +func GraphiteOnce(c GraphiteConfig) error { + log.Printf("WARNING: This go-metrics client has been DEPRECATED! It has been moved to https://github.com/cyberdelia/go-metrics-graphite and will be removed from rcrowley/go-metrics on August 12th 2015") + return graphite(&c) +} + +func graphite(c *GraphiteConfig) error { + now := time.Now().Unix() + du := float64(c.DurationUnit) + conn, err := net.DialTCP("tcp", nil, c.Addr) + if nil != err { + return err + } + defer conn.Close() + w := bufio.NewWriter(conn) + c.Registry.Each(func(name string, i interface{}) { + switch metric := i.(type) { + case Counter: + fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, metric.Count(), now) + case Gauge: + fmt.Fprintf(w, "%s.%s.value %d %d\n", c.Prefix, name, metric.Value(), now) + case GaugeFloat64: + fmt.Fprintf(w, "%s.%s.value %f %d\n", c.Prefix, name, metric.Value(), now) + case Histogram: + h := metric.Snapshot() + ps := h.Percentiles(c.Percentiles) + fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, h.Count(), now) + fmt.Fprintf(w, "%s.%s.min %d %d\n", c.Prefix, name, h.Min(), now) + fmt.Fprintf(w, "%s.%s.max %d %d\n", c.Prefix, name, h.Max(), now) + fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, h.Mean(), now) + fmt.Fprintf(w, "%s.%s.std-dev %.2f %d\n", c.Prefix, name, h.StdDev(), now) + for psIdx, psKey := range c.Percentiles { + key := strings.Replace(strconv.FormatFloat(psKey*100.0, 'f', -1, 64), ".", "", 1) + fmt.Fprintf(w, "%s.%s.%s-percentile %.2f %d\n", c.Prefix, name, key, ps[psIdx], now) + } + case Meter: + m := metric.Snapshot() + fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, m.Count(), now) + fmt.Fprintf(w, "%s.%s.one-minute %.2f %d\n", c.Prefix, name, m.Rate1(), now) + fmt.Fprintf(w, "%s.%s.five-minute %.2f %d\n", c.Prefix, name, m.Rate5(), now) + fmt.Fprintf(w, "%s.%s.fifteen-minute %.2f %d\n", c.Prefix, name, m.Rate15(), now) + fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, m.RateMean(), now) + case Timer: + t := metric.Snapshot() + ps := t.Percentiles(c.Percentiles) + fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, t.Count(), now) + fmt.Fprintf(w, "%s.%s.min %d %d\n", c.Prefix, name, t.Min()/int64(du), now) + fmt.Fprintf(w, "%s.%s.max %d %d\n", c.Prefix, name, t.Max()/int64(du), now) + fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, t.Mean()/du, now) + fmt.Fprintf(w, "%s.%s.std-dev %.2f %d\n", c.Prefix, name, t.StdDev()/du, now) + for psIdx, psKey := range c.Percentiles { + key := strings.Replace(strconv.FormatFloat(psKey*100.0, 'f', -1, 64), ".", "", 1) + fmt.Fprintf(w, "%s.%s.%s-percentile %.2f %d\n", c.Prefix, name, key, ps[psIdx], now) + } + fmt.Fprintf(w, "%s.%s.one-minute %.2f %d\n", c.Prefix, name, t.Rate1(), now) + fmt.Fprintf(w, "%s.%s.five-minute %.2f %d\n", c.Prefix, name, t.Rate5(), now) + fmt.Fprintf(w, "%s.%s.fifteen-minute %.2f %d\n", c.Prefix, name, t.Rate15(), now) + fmt.Fprintf(w, "%s.%s.mean-rate %.2f %d\n", c.Prefix, name, t.RateMean(), now) + } + w.Flush() + }) + return nil +} diff --git a/vendor/github.com/rcrowley/go-metrics/healthcheck.go b/vendor/github.com/rcrowley/go-metrics/healthcheck.go new file mode 100644 index 000000000..445131cae --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/healthcheck.go @@ -0,0 +1,61 @@ +package metrics + +// Healthchecks hold an error value describing an arbitrary up/down status. +type Healthcheck interface { + Check() + Error() error + Healthy() + Unhealthy(error) +} + +// NewHealthcheck constructs a new Healthcheck which will use the given +// function to update its status. +func NewHealthcheck(f func(Healthcheck)) Healthcheck { + if UseNilMetrics { + return NilHealthcheck{} + } + return &StandardHealthcheck{nil, f} +} + +// NilHealthcheck is a no-op. +type NilHealthcheck struct{} + +// Check is a no-op. +func (NilHealthcheck) Check() {} + +// Error is a no-op. +func (NilHealthcheck) Error() error { return nil } + +// Healthy is a no-op. +func (NilHealthcheck) Healthy() {} + +// Unhealthy is a no-op. +func (NilHealthcheck) Unhealthy(error) {} + +// StandardHealthcheck is the standard implementation of a Healthcheck and +// stores the status and a function to call to update the status. +type StandardHealthcheck struct { + err error + f func(Healthcheck) +} + +// Check runs the healthcheck function to update the healthcheck's status. +func (h *StandardHealthcheck) Check() { + h.f(h) +} + +// Error returns the healthcheck's status, which will be nil if it is healthy. +func (h *StandardHealthcheck) Error() error { + return h.err +} + +// Healthy marks the healthcheck as healthy. +func (h *StandardHealthcheck) Healthy() { + h.err = nil +} + +// Unhealthy marks the healthcheck as unhealthy. The error is stored and +// may be retrieved by the Error method. +func (h *StandardHealthcheck) Unhealthy(err error) { + h.err = err +} diff --git a/vendor/github.com/rcrowley/go-metrics/histogram.go b/vendor/github.com/rcrowley/go-metrics/histogram.go new file mode 100644 index 000000000..dbc837fe4 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/histogram.go @@ -0,0 +1,202 @@ +package metrics + +// Histograms calculate distribution statistics from a series of int64 values. +type Histogram interface { + Clear() + Count() int64 + Max() int64 + Mean() float64 + Min() int64 + Percentile(float64) float64 + Percentiles([]float64) []float64 + Sample() Sample + Snapshot() Histogram + StdDev() float64 + Sum() int64 + Update(int64) + Variance() float64 +} + +// GetOrRegisterHistogram returns an existing Histogram or constructs and +// registers a new StandardHistogram. +func GetOrRegisterHistogram(name string, r Registry, s Sample) Histogram { + if nil == r { + r = DefaultRegistry + } + return r.GetOrRegister(name, func() Histogram { return NewHistogram(s) }).(Histogram) +} + +// NewHistogram constructs a new StandardHistogram from a Sample. +func NewHistogram(s Sample) Histogram { + if UseNilMetrics { + return NilHistogram{} + } + return &StandardHistogram{sample: s} +} + +// NewRegisteredHistogram constructs and registers a new StandardHistogram from +// a Sample. +func NewRegisteredHistogram(name string, r Registry, s Sample) Histogram { + c := NewHistogram(s) + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// HistogramSnapshot is a read-only copy of another Histogram. +type HistogramSnapshot struct { + sample *SampleSnapshot +} + +// Clear panics. +func (*HistogramSnapshot) Clear() { + panic("Clear called on a HistogramSnapshot") +} + +// Count returns the number of samples recorded at the time the snapshot was +// taken. +func (h *HistogramSnapshot) Count() int64 { return h.sample.Count() } + +// Max returns the maximum value in the sample at the time the snapshot was +// taken. +func (h *HistogramSnapshot) Max() int64 { return h.sample.Max() } + +// Mean returns the mean of the values in the sample at the time the snapshot +// was taken. +func (h *HistogramSnapshot) Mean() float64 { return h.sample.Mean() } + +// Min returns the minimum value in the sample at the time the snapshot was +// taken. +func (h *HistogramSnapshot) Min() int64 { return h.sample.Min() } + +// Percentile returns an arbitrary percentile of values in the sample at the +// time the snapshot was taken. +func (h *HistogramSnapshot) Percentile(p float64) float64 { + return h.sample.Percentile(p) +} + +// Percentiles returns a slice of arbitrary percentiles of values in the sample +// at the time the snapshot was taken. +func (h *HistogramSnapshot) Percentiles(ps []float64) []float64 { + return h.sample.Percentiles(ps) +} + +// Sample returns the Sample underlying the histogram. +func (h *HistogramSnapshot) Sample() Sample { return h.sample } + +// Snapshot returns the snapshot. +func (h *HistogramSnapshot) Snapshot() Histogram { return h } + +// StdDev returns the standard deviation of the values in the sample at the +// time the snapshot was taken. +func (h *HistogramSnapshot) StdDev() float64 { return h.sample.StdDev() } + +// Sum returns the sum in the sample at the time the snapshot was taken. +func (h *HistogramSnapshot) Sum() int64 { return h.sample.Sum() } + +// Update panics. +func (*HistogramSnapshot) Update(int64) { + panic("Update called on a HistogramSnapshot") +} + +// Variance returns the variance of inputs at the time the snapshot was taken. +func (h *HistogramSnapshot) Variance() float64 { return h.sample.Variance() } + +// NilHistogram is a no-op Histogram. +type NilHistogram struct{} + +// Clear is a no-op. +func (NilHistogram) Clear() {} + +// Count is a no-op. +func (NilHistogram) Count() int64 { return 0 } + +// Max is a no-op. +func (NilHistogram) Max() int64 { return 0 } + +// Mean is a no-op. +func (NilHistogram) Mean() float64 { return 0.0 } + +// Min is a no-op. +func (NilHistogram) Min() int64 { return 0 } + +// Percentile is a no-op. +func (NilHistogram) Percentile(p float64) float64 { return 0.0 } + +// Percentiles is a no-op. +func (NilHistogram) Percentiles(ps []float64) []float64 { + return make([]float64, len(ps)) +} + +// Sample is a no-op. +func (NilHistogram) Sample() Sample { return NilSample{} } + +// Snapshot is a no-op. +func (NilHistogram) Snapshot() Histogram { return NilHistogram{} } + +// StdDev is a no-op. +func (NilHistogram) StdDev() float64 { return 0.0 } + +// Sum is a no-op. +func (NilHistogram) Sum() int64 { return 0 } + +// Update is a no-op. +func (NilHistogram) Update(v int64) {} + +// Variance is a no-op. +func (NilHistogram) Variance() float64 { return 0.0 } + +// StandardHistogram is the standard implementation of a Histogram and uses a +// Sample to bound its memory use. +type StandardHistogram struct { + sample Sample +} + +// Clear clears the histogram and its sample. +func (h *StandardHistogram) Clear() { h.sample.Clear() } + +// Count returns the number of samples recorded since the histogram was last +// cleared. +func (h *StandardHistogram) Count() int64 { return h.sample.Count() } + +// Max returns the maximum value in the sample. +func (h *StandardHistogram) Max() int64 { return h.sample.Max() } + +// Mean returns the mean of the values in the sample. +func (h *StandardHistogram) Mean() float64 { return h.sample.Mean() } + +// Min returns the minimum value in the sample. +func (h *StandardHistogram) Min() int64 { return h.sample.Min() } + +// Percentile returns an arbitrary percentile of the values in the sample. +func (h *StandardHistogram) Percentile(p float64) float64 { + return h.sample.Percentile(p) +} + +// Percentiles returns a slice of arbitrary percentiles of the values in the +// sample. +func (h *StandardHistogram) Percentiles(ps []float64) []float64 { + return h.sample.Percentiles(ps) +} + +// Sample returns the Sample underlying the histogram. +func (h *StandardHistogram) Sample() Sample { return h.sample } + +// Snapshot returns a read-only copy of the histogram. +func (h *StandardHistogram) Snapshot() Histogram { + return &HistogramSnapshot{sample: h.sample.Snapshot().(*SampleSnapshot)} +} + +// StdDev returns the standard deviation of the values in the sample. +func (h *StandardHistogram) StdDev() float64 { return h.sample.StdDev() } + +// Sum returns the sum in the sample. +func (h *StandardHistogram) Sum() int64 { return h.sample.Sum() } + +// Update samples a new value. +func (h *StandardHistogram) Update(v int64) { h.sample.Update(v) } + +// Variance returns the variance of the values in the sample. +func (h *StandardHistogram) Variance() float64 { return h.sample.Variance() } diff --git a/vendor/github.com/rcrowley/go-metrics/json.go b/vendor/github.com/rcrowley/go-metrics/json.go new file mode 100644 index 000000000..174b9477e --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/json.go @@ -0,0 +1,31 @@ +package metrics + +import ( + "encoding/json" + "io" + "time" +) + +// MarshalJSON returns a byte slice containing a JSON representation of all +// the metrics in the Registry. +func (r *StandardRegistry) MarshalJSON() ([]byte, error) { + return json.Marshal(r.GetAll()) +} + +// WriteJSON writes metrics from the given registry periodically to the +// specified io.Writer as JSON. +func WriteJSON(r Registry, d time.Duration, w io.Writer) { + for _ = range time.Tick(d) { + WriteJSONOnce(r, w) + } +} + +// WriteJSONOnce writes metrics from the given registry to the specified +// io.Writer as JSON. +func WriteJSONOnce(r Registry, w io.Writer) { + json.NewEncoder(w).Encode(r) +} + +func (p *PrefixedRegistry) MarshalJSON() ([]byte, error) { + return json.Marshal(p.GetAll()) +} diff --git a/vendor/github.com/rcrowley/go-metrics/log.go b/vendor/github.com/rcrowley/go-metrics/log.go new file mode 100644 index 000000000..f8074c045 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/log.go @@ -0,0 +1,80 @@ +package metrics + +import ( + "time" +) + +type Logger interface { + Printf(format string, v ...interface{}) +} + +func Log(r Registry, freq time.Duration, l Logger) { + LogScaled(r, freq, time.Nanosecond, l) +} + +// Output each metric in the given registry periodically using the given +// logger. Print timings in `scale` units (eg time.Millisecond) rather than nanos. +func LogScaled(r Registry, freq time.Duration, scale time.Duration, l Logger) { + du := float64(scale) + duSuffix := scale.String()[1:] + + for _ = range time.Tick(freq) { + r.Each(func(name string, i interface{}) { + switch metric := i.(type) { + case Counter: + l.Printf("counter %s\n", name) + l.Printf(" count: %9d\n", metric.Count()) + case Gauge: + l.Printf("gauge %s\n", name) + l.Printf(" value: %9d\n", metric.Value()) + case GaugeFloat64: + l.Printf("gauge %s\n", name) + l.Printf(" value: %f\n", metric.Value()) + case Healthcheck: + metric.Check() + l.Printf("healthcheck %s\n", name) + l.Printf(" error: %v\n", metric.Error()) + case Histogram: + h := metric.Snapshot() + ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + l.Printf("histogram %s\n", name) + l.Printf(" count: %9d\n", h.Count()) + l.Printf(" min: %9d\n", h.Min()) + l.Printf(" max: %9d\n", h.Max()) + l.Printf(" mean: %12.2f\n", h.Mean()) + l.Printf(" stddev: %12.2f\n", h.StdDev()) + l.Printf(" median: %12.2f\n", ps[0]) + l.Printf(" 75%%: %12.2f\n", ps[1]) + l.Printf(" 95%%: %12.2f\n", ps[2]) + l.Printf(" 99%%: %12.2f\n", ps[3]) + l.Printf(" 99.9%%: %12.2f\n", ps[4]) + case Meter: + m := metric.Snapshot() + l.Printf("meter %s\n", name) + l.Printf(" count: %9d\n", m.Count()) + l.Printf(" 1-min rate: %12.2f\n", m.Rate1()) + l.Printf(" 5-min rate: %12.2f\n", m.Rate5()) + l.Printf(" 15-min rate: %12.2f\n", m.Rate15()) + l.Printf(" mean rate: %12.2f\n", m.RateMean()) + case Timer: + t := metric.Snapshot() + ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + l.Printf("timer %s\n", name) + l.Printf(" count: %9d\n", t.Count()) + l.Printf(" min: %12.2f%s\n", float64(t.Min())/du, duSuffix) + l.Printf(" max: %12.2f%s\n", float64(t.Max())/du, duSuffix) + l.Printf(" mean: %12.2f%s\n", t.Mean()/du, duSuffix) + l.Printf(" stddev: %12.2f%s\n", t.StdDev()/du, duSuffix) + l.Printf(" median: %12.2f%s\n", ps[0]/du, duSuffix) + l.Printf(" 75%%: %12.2f%s\n", ps[1]/du, duSuffix) + l.Printf(" 95%%: %12.2f%s\n", ps[2]/du, duSuffix) + l.Printf(" 99%%: %12.2f%s\n", ps[3]/du, duSuffix) + l.Printf(" 99.9%%: %12.2f%s\n", ps[4]/du, duSuffix) + l.Printf(" 1-min rate: %12.2f\n", t.Rate1()) + l.Printf(" 5-min rate: %12.2f\n", t.Rate5()) + l.Printf(" 15-min rate: %12.2f\n", t.Rate15()) + l.Printf(" mean rate: %12.2f\n", t.RateMean()) + } + }) + } +} diff --git a/vendor/github.com/rcrowley/go-metrics/memory.md b/vendor/github.com/rcrowley/go-metrics/memory.md new file mode 100644 index 000000000..47454f54b --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/memory.md @@ -0,0 +1,285 @@ +Memory usage +============ + +(Highly unscientific.) + +Command used to gather static memory usage: + +```sh +grep ^Vm "/proc/$(ps fax | grep [m]etrics-bench | awk '{print $1}')/status" +``` + +Program used to gather baseline memory usage: + +```go +package main + +import "time" + +func main() { + time.Sleep(600e9) +} +``` + +Baseline +-------- + +``` +VmPeak: 42604 kB +VmSize: 42604 kB +VmLck: 0 kB +VmHWM: 1120 kB +VmRSS: 1120 kB +VmData: 35460 kB +VmStk: 136 kB +VmExe: 1020 kB +VmLib: 1848 kB +VmPTE: 36 kB +VmSwap: 0 kB +``` + +Program used to gather metric memory usage (with other metrics being similar): + +```go +package main + +import ( + "fmt" + "metrics" + "time" +) + +func main() { + fmt.Sprintf("foo") + metrics.NewRegistry() + time.Sleep(600e9) +} +``` + +1000 counters registered +------------------------ + +``` +VmPeak: 44016 kB +VmSize: 44016 kB +VmLck: 0 kB +VmHWM: 1928 kB +VmRSS: 1928 kB +VmData: 36868 kB +VmStk: 136 kB +VmExe: 1024 kB +VmLib: 1848 kB +VmPTE: 40 kB +VmSwap: 0 kB +``` + +**1.412 kB virtual, TODO 0.808 kB resident per counter.** + +100000 counters registered +-------------------------- + +``` +VmPeak: 55024 kB +VmSize: 55024 kB +VmLck: 0 kB +VmHWM: 12440 kB +VmRSS: 12440 kB +VmData: 47876 kB +VmStk: 136 kB +VmExe: 1024 kB +VmLib: 1848 kB +VmPTE: 64 kB +VmSwap: 0 kB +``` + +**0.1242 kB virtual, 0.1132 kB resident per counter.** + +1000 gauges registered +---------------------- + +``` +VmPeak: 44012 kB +VmSize: 44012 kB +VmLck: 0 kB +VmHWM: 1928 kB +VmRSS: 1928 kB +VmData: 36868 kB +VmStk: 136 kB +VmExe: 1020 kB +VmLib: 1848 kB +VmPTE: 40 kB +VmSwap: 0 kB +``` + +**1.408 kB virtual, 0.808 kB resident per counter.** + +100000 gauges registered +------------------------ + +``` +VmPeak: 55020 kB +VmSize: 55020 kB +VmLck: 0 kB +VmHWM: 12432 kB +VmRSS: 12432 kB +VmData: 47876 kB +VmStk: 136 kB +VmExe: 1020 kB +VmLib: 1848 kB +VmPTE: 60 kB +VmSwap: 0 kB +``` + +**0.12416 kB virtual, 0.11312 resident per gauge.** + +1000 histograms with a uniform sample size of 1028 +-------------------------------------------------- + +``` +VmPeak: 72272 kB +VmSize: 72272 kB +VmLck: 0 kB +VmHWM: 16204 kB +VmRSS: 16204 kB +VmData: 65100 kB +VmStk: 136 kB +VmExe: 1048 kB +VmLib: 1848 kB +VmPTE: 80 kB +VmSwap: 0 kB +``` + +**29.668 kB virtual, TODO 15.084 resident per histogram.** + +10000 histograms with a uniform sample size of 1028 +--------------------------------------------------- + +``` +VmPeak: 256912 kB +VmSize: 256912 kB +VmLck: 0 kB +VmHWM: 146204 kB +VmRSS: 146204 kB +VmData: 249740 kB +VmStk: 136 kB +VmExe: 1048 kB +VmLib: 1848 kB +VmPTE: 448 kB +VmSwap: 0 kB +``` + +**21.4308 kB virtual, 14.5084 kB resident per histogram.** + +50000 histograms with a uniform sample size of 1028 +--------------------------------------------------- + +``` +VmPeak: 908112 kB +VmSize: 908112 kB +VmLck: 0 kB +VmHWM: 645832 kB +VmRSS: 645588 kB +VmData: 900940 kB +VmStk: 136 kB +VmExe: 1048 kB +VmLib: 1848 kB +VmPTE: 1716 kB +VmSwap: 1544 kB +``` + +**17.31016 kB virtual, 12.88936 kB resident per histogram.** + +1000 histograms with an exponentially-decaying sample size of 1028 and alpha of 0.015 +------------------------------------------------------------------------------------- + +``` +VmPeak: 62480 kB +VmSize: 62480 kB +VmLck: 0 kB +VmHWM: 11572 kB +VmRSS: 11572 kB +VmData: 55308 kB +VmStk: 136 kB +VmExe: 1048 kB +VmLib: 1848 kB +VmPTE: 64 kB +VmSwap: 0 kB +``` + +**19.876 kB virtual, 10.452 kB resident per histogram.** + +10000 histograms with an exponentially-decaying sample size of 1028 and alpha of 0.015 +-------------------------------------------------------------------------------------- + +``` +VmPeak: 153296 kB +VmSize: 153296 kB +VmLck: 0 kB +VmHWM: 101176 kB +VmRSS: 101176 kB +VmData: 146124 kB +VmStk: 136 kB +VmExe: 1048 kB +VmLib: 1848 kB +VmPTE: 240 kB +VmSwap: 0 kB +``` + +**11.0692 kB virtual, 10.0056 kB resident per histogram.** + +50000 histograms with an exponentially-decaying sample size of 1028 and alpha of 0.015 +-------------------------------------------------------------------------------------- + +``` +VmPeak: 557264 kB +VmSize: 557264 kB +VmLck: 0 kB +VmHWM: 501056 kB +VmRSS: 501056 kB +VmData: 550092 kB +VmStk: 136 kB +VmExe: 1048 kB +VmLib: 1848 kB +VmPTE: 1032 kB +VmSwap: 0 kB +``` + +**10.2932 kB virtual, 9.99872 kB resident per histogram.** + +1000 meters +----------- + +``` +VmPeak: 74504 kB +VmSize: 74504 kB +VmLck: 0 kB +VmHWM: 24124 kB +VmRSS: 24124 kB +VmData: 67340 kB +VmStk: 136 kB +VmExe: 1040 kB +VmLib: 1848 kB +VmPTE: 92 kB +VmSwap: 0 kB +``` + +**31.9 kB virtual, 23.004 kB resident per meter.** + +10000 meters +------------ + +``` +VmPeak: 278920 kB +VmSize: 278920 kB +VmLck: 0 kB +VmHWM: 227300 kB +VmRSS: 227300 kB +VmData: 271756 kB +VmStk: 136 kB +VmExe: 1040 kB +VmLib: 1848 kB +VmPTE: 488 kB +VmSwap: 0 kB +``` + +**23.6316 kB virtual, 22.618 kB resident per meter.** diff --git a/vendor/github.com/rcrowley/go-metrics/meter.go b/vendor/github.com/rcrowley/go-metrics/meter.go new file mode 100644 index 000000000..223669bcb --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/meter.go @@ -0,0 +1,251 @@ +package metrics + +import ( + "math" + "sync" + "sync/atomic" + "time" +) + +// Meters count events to produce exponentially-weighted moving average rates +// at one-, five-, and fifteen-minutes and a mean rate. +type Meter interface { + Count() int64 + Mark(int64) + Rate1() float64 + Rate5() float64 + Rate15() float64 + RateMean() float64 + Snapshot() Meter + Stop() +} + +// GetOrRegisterMeter returns an existing Meter or constructs and registers a +// new StandardMeter. +// Be sure to unregister the meter from the registry once it is of no use to +// allow for garbage collection. +func GetOrRegisterMeter(name string, r Registry) Meter { + if nil == r { + r = DefaultRegistry + } + return r.GetOrRegister(name, NewMeter).(Meter) +} + +// NewMeter constructs a new StandardMeter and launches a goroutine. +// Be sure to call Stop() once the meter is of no use to allow for garbage collection. +func NewMeter() Meter { + if UseNilMetrics { + return NilMeter{} + } + m := newStandardMeter() + arbiter.Lock() + defer arbiter.Unlock() + arbiter.meters[m] = struct{}{} + if !arbiter.started { + arbiter.started = true + go arbiter.tick() + } + return m +} + +// NewMeter constructs and registers a new StandardMeter and launches a +// goroutine. +// Be sure to unregister the meter from the registry once it is of no use to +// allow for garbage collection. +func NewRegisteredMeter(name string, r Registry) Meter { + c := NewMeter() + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// MeterSnapshot is a read-only copy of another Meter. +type MeterSnapshot struct { + count int64 + rate1, rate5, rate15, rateMean uint64 +} + +// Count returns the count of events at the time the snapshot was taken. +func (m *MeterSnapshot) Count() int64 { return m.count } + +// Mark panics. +func (*MeterSnapshot) Mark(n int64) { + panic("Mark called on a MeterSnapshot") +} + +// Rate1 returns the one-minute moving average rate of events per second at the +// time the snapshot was taken. +func (m *MeterSnapshot) Rate1() float64 { return math.Float64frombits(m.rate1) } + +// Rate5 returns the five-minute moving average rate of events per second at +// the time the snapshot was taken. +func (m *MeterSnapshot) Rate5() float64 { return math.Float64frombits(m.rate5) } + +// Rate15 returns the fifteen-minute moving average rate of events per second +// at the time the snapshot was taken. +func (m *MeterSnapshot) Rate15() float64 { return math.Float64frombits(m.rate15) } + +// RateMean returns the meter's mean rate of events per second at the time the +// snapshot was taken. +func (m *MeterSnapshot) RateMean() float64 { return math.Float64frombits(m.rateMean) } + +// Snapshot returns the snapshot. +func (m *MeterSnapshot) Snapshot() Meter { return m } + +// Stop is a no-op. +func (m *MeterSnapshot) Stop() {} + +// NilMeter is a no-op Meter. +type NilMeter struct{} + +// Count is a no-op. +func (NilMeter) Count() int64 { return 0 } + +// Mark is a no-op. +func (NilMeter) Mark(n int64) {} + +// Rate1 is a no-op. +func (NilMeter) Rate1() float64 { return 0.0 } + +// Rate5 is a no-op. +func (NilMeter) Rate5() float64 { return 0.0 } + +// Rate15is a no-op. +func (NilMeter) Rate15() float64 { return 0.0 } + +// RateMean is a no-op. +func (NilMeter) RateMean() float64 { return 0.0 } + +// Snapshot is a no-op. +func (NilMeter) Snapshot() Meter { return NilMeter{} } + +// Stop is a no-op. +func (NilMeter) Stop() {} + +// StandardMeter is the standard implementation of a Meter. +type StandardMeter struct { + snapshot *MeterSnapshot + a1, a5, a15 EWMA + startTime time.Time + stopped uint32 +} + +func newStandardMeter() *StandardMeter { + return &StandardMeter{ + snapshot: &MeterSnapshot{}, + a1: NewEWMA1(), + a5: NewEWMA5(), + a15: NewEWMA15(), + startTime: time.Now(), + } +} + +// Stop stops the meter, Mark() will be a no-op if you use it after being stopped. +func (m *StandardMeter) Stop() { + if atomic.CompareAndSwapUint32(&m.stopped, 0, 1) { + arbiter.Lock() + delete(arbiter.meters, m) + arbiter.Unlock() + } +} + +// Count returns the number of events recorded. +func (m *StandardMeter) Count() int64 { + return atomic.LoadInt64(&m.snapshot.count) +} + +// Mark records the occurance of n events. +func (m *StandardMeter) Mark(n int64) { + if atomic.LoadUint32(&m.stopped) == 1 { + return + } + + atomic.AddInt64(&m.snapshot.count, n) + + m.a1.Update(n) + m.a5.Update(n) + m.a15.Update(n) + m.updateSnapshot() +} + +// Rate1 returns the one-minute moving average rate of events per second. +func (m *StandardMeter) Rate1() float64 { + return math.Float64frombits(atomic.LoadUint64(&m.snapshot.rate1)) +} + +// Rate5 returns the five-minute moving average rate of events per second. +func (m *StandardMeter) Rate5() float64 { + return math.Float64frombits(atomic.LoadUint64(&m.snapshot.rate5)) +} + +// Rate15 returns the fifteen-minute moving average rate of events per second. +func (m *StandardMeter) Rate15() float64 { + return math.Float64frombits(atomic.LoadUint64(&m.snapshot.rate15)) +} + +// RateMean returns the meter's mean rate of events per second. +func (m *StandardMeter) RateMean() float64 { + return math.Float64frombits(atomic.LoadUint64(&m.snapshot.rateMean)) +} + +// Snapshot returns a read-only copy of the meter. +func (m *StandardMeter) Snapshot() Meter { + copiedSnapshot := MeterSnapshot{ + count: atomic.LoadInt64(&m.snapshot.count), + rate1: atomic.LoadUint64(&m.snapshot.rate1), + rate5: atomic.LoadUint64(&m.snapshot.rate5), + rate15: atomic.LoadUint64(&m.snapshot.rate15), + rateMean: atomic.LoadUint64(&m.snapshot.rateMean), + } + return &copiedSnapshot +} + +func (m *StandardMeter) updateSnapshot() { + rate1 := math.Float64bits(m.a1.Rate()) + rate5 := math.Float64bits(m.a5.Rate()) + rate15 := math.Float64bits(m.a15.Rate()) + rateMean := math.Float64bits(float64(m.Count()) / time.Since(m.startTime).Seconds()) + + atomic.StoreUint64(&m.snapshot.rate1, rate1) + atomic.StoreUint64(&m.snapshot.rate5, rate5) + atomic.StoreUint64(&m.snapshot.rate15, rate15) + atomic.StoreUint64(&m.snapshot.rateMean, rateMean) +} + +func (m *StandardMeter) tick() { + m.a1.Tick() + m.a5.Tick() + m.a15.Tick() + m.updateSnapshot() +} + +// meterArbiter ticks meters every 5s from a single goroutine. +// meters are references in a set for future stopping. +type meterArbiter struct { + sync.RWMutex + started bool + meters map[*StandardMeter]struct{} + ticker *time.Ticker +} + +var arbiter = meterArbiter{ticker: time.NewTicker(5e9), meters: make(map[*StandardMeter]struct{})} + +// Ticks meters on the scheduled interval +func (ma *meterArbiter) tick() { + for { + select { + case <-ma.ticker.C: + ma.tickMeters() + } + } +} + +func (ma *meterArbiter) tickMeters() { + ma.RLock() + defer ma.RUnlock() + for meter := range ma.meters { + meter.tick() + } +} diff --git a/vendor/github.com/rcrowley/go-metrics/metrics.go b/vendor/github.com/rcrowley/go-metrics/metrics.go new file mode 100644 index 000000000..b97a49ed1 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/metrics.go @@ -0,0 +1,13 @@ +// Go port of Coda Hale's Metrics library +// +// +// +// Coda Hale's original work: +package metrics + +// UseNilMetrics is checked by the constructor functions for all of the +// standard metrics. If it is true, the metric returned is a stub. +// +// This global kill-switch helps quantify the observer effect and makes +// for less cluttered pprof profiles. +var UseNilMetrics bool = false diff --git a/vendor/github.com/rcrowley/go-metrics/opentsdb.go b/vendor/github.com/rcrowley/go-metrics/opentsdb.go new file mode 100644 index 000000000..266b6c93d --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/opentsdb.go @@ -0,0 +1,119 @@ +package metrics + +import ( + "bufio" + "fmt" + "log" + "net" + "os" + "strings" + "time" +) + +var shortHostName string = "" + +// OpenTSDBConfig provides a container with configuration parameters for +// the OpenTSDB exporter +type OpenTSDBConfig struct { + Addr *net.TCPAddr // Network address to connect to + Registry Registry // Registry to be exported + FlushInterval time.Duration // Flush interval + DurationUnit time.Duration // Time conversion unit for durations + Prefix string // Prefix to be prepended to metric names +} + +// OpenTSDB is a blocking exporter function which reports metrics in r +// to a TSDB server located at addr, flushing them every d duration +// and prepending metric names with prefix. +func OpenTSDB(r Registry, d time.Duration, prefix string, addr *net.TCPAddr) { + OpenTSDBWithConfig(OpenTSDBConfig{ + Addr: addr, + Registry: r, + FlushInterval: d, + DurationUnit: time.Nanosecond, + Prefix: prefix, + }) +} + +// OpenTSDBWithConfig is a blocking exporter function just like OpenTSDB, +// but it takes a OpenTSDBConfig instead. +func OpenTSDBWithConfig(c OpenTSDBConfig) { + for _ = range time.Tick(c.FlushInterval) { + if err := openTSDB(&c); nil != err { + log.Println(err) + } + } +} + +func getShortHostname() string { + if shortHostName == "" { + host, _ := os.Hostname() + if index := strings.Index(host, "."); index > 0 { + shortHostName = host[:index] + } else { + shortHostName = host + } + } + return shortHostName +} + +func openTSDB(c *OpenTSDBConfig) error { + shortHostname := getShortHostname() + now := time.Now().Unix() + du := float64(c.DurationUnit) + conn, err := net.DialTCP("tcp", nil, c.Addr) + if nil != err { + return err + } + defer conn.Close() + w := bufio.NewWriter(conn) + c.Registry.Each(func(name string, i interface{}) { + switch metric := i.(type) { + case Counter: + fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, metric.Count(), shortHostname) + case Gauge: + fmt.Fprintf(w, "put %s.%s.value %d %d host=%s\n", c.Prefix, name, now, metric.Value(), shortHostname) + case GaugeFloat64: + fmt.Fprintf(w, "put %s.%s.value %d %f host=%s\n", c.Prefix, name, now, metric.Value(), shortHostname) + case Histogram: + h := metric.Snapshot() + ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, h.Count(), shortHostname) + fmt.Fprintf(w, "put %s.%s.min %d %d host=%s\n", c.Prefix, name, now, h.Min(), shortHostname) + fmt.Fprintf(w, "put %s.%s.max %d %d host=%s\n", c.Prefix, name, now, h.Max(), shortHostname) + fmt.Fprintf(w, "put %s.%s.mean %d %.2f host=%s\n", c.Prefix, name, now, h.Mean(), shortHostname) + fmt.Fprintf(w, "put %s.%s.std-dev %d %.2f host=%s\n", c.Prefix, name, now, h.StdDev(), shortHostname) + fmt.Fprintf(w, "put %s.%s.50-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[0], shortHostname) + fmt.Fprintf(w, "put %s.%s.75-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[1], shortHostname) + fmt.Fprintf(w, "put %s.%s.95-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[2], shortHostname) + fmt.Fprintf(w, "put %s.%s.99-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[3], shortHostname) + fmt.Fprintf(w, "put %s.%s.999-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[4], shortHostname) + case Meter: + m := metric.Snapshot() + fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, m.Count(), shortHostname) + fmt.Fprintf(w, "put %s.%s.one-minute %d %.2f host=%s\n", c.Prefix, name, now, m.Rate1(), shortHostname) + fmt.Fprintf(w, "put %s.%s.five-minute %d %.2f host=%s\n", c.Prefix, name, now, m.Rate5(), shortHostname) + fmt.Fprintf(w, "put %s.%s.fifteen-minute %d %.2f host=%s\n", c.Prefix, name, now, m.Rate15(), shortHostname) + fmt.Fprintf(w, "put %s.%s.mean %d %.2f host=%s\n", c.Prefix, name, now, m.RateMean(), shortHostname) + case Timer: + t := metric.Snapshot() + ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, t.Count(), shortHostname) + fmt.Fprintf(w, "put %s.%s.min %d %d host=%s\n", c.Prefix, name, now, t.Min()/int64(du), shortHostname) + fmt.Fprintf(w, "put %s.%s.max %d %d host=%s\n", c.Prefix, name, now, t.Max()/int64(du), shortHostname) + fmt.Fprintf(w, "put %s.%s.mean %d %.2f host=%s\n", c.Prefix, name, now, t.Mean()/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.std-dev %d %.2f host=%s\n", c.Prefix, name, now, t.StdDev()/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.50-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[0]/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.75-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[1]/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.95-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[2]/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.99-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[3]/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.999-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[4]/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.one-minute %d %.2f host=%s\n", c.Prefix, name, now, t.Rate1(), shortHostname) + fmt.Fprintf(w, "put %s.%s.five-minute %d %.2f host=%s\n", c.Prefix, name, now, t.Rate5(), shortHostname) + fmt.Fprintf(w, "put %s.%s.fifteen-minute %d %.2f host=%s\n", c.Prefix, name, now, t.Rate15(), shortHostname) + fmt.Fprintf(w, "put %s.%s.mean-rate %d %.2f host=%s\n", c.Prefix, name, now, t.RateMean(), shortHostname) + } + w.Flush() + }) + return nil +} diff --git a/vendor/github.com/rcrowley/go-metrics/registry.go b/vendor/github.com/rcrowley/go-metrics/registry.go new file mode 100644 index 000000000..b3bab64e1 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/registry.go @@ -0,0 +1,363 @@ +package metrics + +import ( + "fmt" + "reflect" + "strings" + "sync" +) + +// DuplicateMetric is the error returned by Registry.Register when a metric +// already exists. If you mean to Register that metric you must first +// Unregister the existing metric. +type DuplicateMetric string + +func (err DuplicateMetric) Error() string { + return fmt.Sprintf("duplicate metric: %s", string(err)) +} + +// A Registry holds references to a set of metrics by name and can iterate +// over them, calling callback functions provided by the user. +// +// This is an interface so as to encourage other structs to implement +// the Registry API as appropriate. +type Registry interface { + + // Call the given function for each registered metric. + Each(func(string, interface{})) + + // Get the metric by the given name or nil if none is registered. + Get(string) interface{} + + // GetAll metrics in the Registry. + GetAll() map[string]map[string]interface{} + + // Gets an existing metric or registers the given one. + // The interface can be the metric to register if not found in registry, + // or a function returning the metric for lazy instantiation. + GetOrRegister(string, interface{}) interface{} + + // Register the given metric under the given name. + Register(string, interface{}) error + + // Run all registered healthchecks. + RunHealthchecks() + + // Unregister the metric with the given name. + Unregister(string) + + // Unregister all metrics. (Mostly for testing.) + UnregisterAll() +} + +// The standard implementation of a Registry is a mutex-protected map +// of names to metrics. +type StandardRegistry struct { + metrics map[string]interface{} + mutex sync.RWMutex +} + +// Create a new registry. +func NewRegistry() Registry { + return &StandardRegistry{metrics: make(map[string]interface{})} +} + +// Call the given function for each registered metric. +func (r *StandardRegistry) Each(f func(string, interface{})) { + for name, i := range r.registered() { + f(name, i) + } +} + +// Get the metric by the given name or nil if none is registered. +func (r *StandardRegistry) Get(name string) interface{} { + r.mutex.RLock() + defer r.mutex.RUnlock() + return r.metrics[name] +} + +// Gets an existing metric or creates and registers a new one. Threadsafe +// alternative to calling Get and Register on failure. +// The interface can be the metric to register if not found in registry, +// or a function returning the metric for lazy instantiation. +func (r *StandardRegistry) GetOrRegister(name string, i interface{}) interface{} { + // access the read lock first which should be re-entrant + r.mutex.RLock() + metric, ok := r.metrics[name] + r.mutex.RUnlock() + if ok { + return metric + } + + // only take the write lock if we'll be modifying the metrics map + r.mutex.Lock() + defer r.mutex.Unlock() + if metric, ok := r.metrics[name]; ok { + return metric + } + if v := reflect.ValueOf(i); v.Kind() == reflect.Func { + i = v.Call(nil)[0].Interface() + } + r.register(name, i) + return i +} + +// Register the given metric under the given name. Returns a DuplicateMetric +// if a metric by the given name is already registered. +func (r *StandardRegistry) Register(name string, i interface{}) error { + r.mutex.Lock() + defer r.mutex.Unlock() + return r.register(name, i) +} + +// Run all registered healthchecks. +func (r *StandardRegistry) RunHealthchecks() { + r.mutex.RLock() + defer r.mutex.RUnlock() + for _, i := range r.metrics { + if h, ok := i.(Healthcheck); ok { + h.Check() + } + } +} + +// GetAll metrics in the Registry +func (r *StandardRegistry) GetAll() map[string]map[string]interface{} { + data := make(map[string]map[string]interface{}) + r.Each(func(name string, i interface{}) { + values := make(map[string]interface{}) + switch metric := i.(type) { + case Counter: + values["count"] = metric.Count() + case Gauge: + values["value"] = metric.Value() + case GaugeFloat64: + values["value"] = metric.Value() + case Healthcheck: + values["error"] = nil + metric.Check() + if err := metric.Error(); nil != err { + values["error"] = metric.Error().Error() + } + case Histogram: + h := metric.Snapshot() + ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + values["count"] = h.Count() + values["min"] = h.Min() + values["max"] = h.Max() + values["mean"] = h.Mean() + values["stddev"] = h.StdDev() + values["median"] = ps[0] + values["75%"] = ps[1] + values["95%"] = ps[2] + values["99%"] = ps[3] + values["99.9%"] = ps[4] + case Meter: + m := metric.Snapshot() + values["count"] = m.Count() + values["1m.rate"] = m.Rate1() + values["5m.rate"] = m.Rate5() + values["15m.rate"] = m.Rate15() + values["mean.rate"] = m.RateMean() + case Timer: + t := metric.Snapshot() + ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + values["count"] = t.Count() + values["min"] = t.Min() + values["max"] = t.Max() + values["mean"] = t.Mean() + values["stddev"] = t.StdDev() + values["median"] = ps[0] + values["75%"] = ps[1] + values["95%"] = ps[2] + values["99%"] = ps[3] + values["99.9%"] = ps[4] + values["1m.rate"] = t.Rate1() + values["5m.rate"] = t.Rate5() + values["15m.rate"] = t.Rate15() + values["mean.rate"] = t.RateMean() + } + data[name] = values + }) + return data +} + +// Unregister the metric with the given name. +func (r *StandardRegistry) Unregister(name string) { + r.mutex.Lock() + defer r.mutex.Unlock() + r.stop(name) + delete(r.metrics, name) +} + +// Unregister all metrics. (Mostly for testing.) +func (r *StandardRegistry) UnregisterAll() { + r.mutex.Lock() + defer r.mutex.Unlock() + for name, _ := range r.metrics { + r.stop(name) + delete(r.metrics, name) + } +} + +func (r *StandardRegistry) register(name string, i interface{}) error { + if _, ok := r.metrics[name]; ok { + return DuplicateMetric(name) + } + switch i.(type) { + case Counter, Gauge, GaugeFloat64, Healthcheck, Histogram, Meter, Timer: + r.metrics[name] = i + } + return nil +} + +func (r *StandardRegistry) registered() map[string]interface{} { + r.mutex.Lock() + defer r.mutex.Unlock() + metrics := make(map[string]interface{}, len(r.metrics)) + for name, i := range r.metrics { + metrics[name] = i + } + return metrics +} + +func (r *StandardRegistry) stop(name string) { + if i, ok := r.metrics[name]; ok { + if s, ok := i.(Stoppable); ok { + s.Stop() + } + } +} + +// Stoppable defines the metrics which has to be stopped. +type Stoppable interface { + Stop() +} + +type PrefixedRegistry struct { + underlying Registry + prefix string +} + +func NewPrefixedRegistry(prefix string) Registry { + return &PrefixedRegistry{ + underlying: NewRegistry(), + prefix: prefix, + } +} + +func NewPrefixedChildRegistry(parent Registry, prefix string) Registry { + return &PrefixedRegistry{ + underlying: parent, + prefix: prefix, + } +} + +// Call the given function for each registered metric. +func (r *PrefixedRegistry) Each(fn func(string, interface{})) { + wrappedFn := func(prefix string) func(string, interface{}) { + return func(name string, iface interface{}) { + if strings.HasPrefix(name, prefix) { + fn(name, iface) + } else { + return + } + } + } + + baseRegistry, prefix := findPrefix(r, "") + baseRegistry.Each(wrappedFn(prefix)) +} + +func findPrefix(registry Registry, prefix string) (Registry, string) { + switch r := registry.(type) { + case *PrefixedRegistry: + return findPrefix(r.underlying, r.prefix+prefix) + case *StandardRegistry: + return r, prefix + } + return nil, "" +} + +// Get the metric by the given name or nil if none is registered. +func (r *PrefixedRegistry) Get(name string) interface{} { + realName := r.prefix + name + return r.underlying.Get(realName) +} + +// Gets an existing metric or registers the given one. +// The interface can be the metric to register if not found in registry, +// or a function returning the metric for lazy instantiation. +func (r *PrefixedRegistry) GetOrRegister(name string, metric interface{}) interface{} { + realName := r.prefix + name + return r.underlying.GetOrRegister(realName, metric) +} + +// Register the given metric under the given name. The name will be prefixed. +func (r *PrefixedRegistry) Register(name string, metric interface{}) error { + realName := r.prefix + name + return r.underlying.Register(realName, metric) +} + +// Run all registered healthchecks. +func (r *PrefixedRegistry) RunHealthchecks() { + r.underlying.RunHealthchecks() +} + +// GetAll metrics in the Registry +func (r *PrefixedRegistry) GetAll() map[string]map[string]interface{} { + return r.underlying.GetAll() +} + +// Unregister the metric with the given name. The name will be prefixed. +func (r *PrefixedRegistry) Unregister(name string) { + realName := r.prefix + name + r.underlying.Unregister(realName) +} + +// Unregister all metrics. (Mostly for testing.) +func (r *PrefixedRegistry) UnregisterAll() { + r.underlying.UnregisterAll() +} + +var DefaultRegistry Registry = NewRegistry() + +// Call the given function for each registered metric. +func Each(f func(string, interface{})) { + DefaultRegistry.Each(f) +} + +// Get the metric by the given name or nil if none is registered. +func Get(name string) interface{} { + return DefaultRegistry.Get(name) +} + +// Gets an existing metric or creates and registers a new one. Threadsafe +// alternative to calling Get and Register on failure. +func GetOrRegister(name string, i interface{}) interface{} { + return DefaultRegistry.GetOrRegister(name, i) +} + +// Register the given metric under the given name. Returns a DuplicateMetric +// if a metric by the given name is already registered. +func Register(name string, i interface{}) error { + return DefaultRegistry.Register(name, i) +} + +// Register the given metric under the given name. Panics if a metric by the +// given name is already registered. +func MustRegister(name string, i interface{}) { + if err := Register(name, i); err != nil { + panic(err) + } +} + +// Run all registered healthchecks. +func RunHealthchecks() { + DefaultRegistry.RunHealthchecks() +} + +// Unregister the metric with the given name. +func Unregister(name string) { + DefaultRegistry.Unregister(name) +} diff --git a/vendor/github.com/rcrowley/go-metrics/runtime.go b/vendor/github.com/rcrowley/go-metrics/runtime.go new file mode 100644 index 000000000..11c6b785a --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/runtime.go @@ -0,0 +1,212 @@ +package metrics + +import ( + "runtime" + "runtime/pprof" + "time" +) + +var ( + memStats runtime.MemStats + runtimeMetrics struct { + MemStats struct { + Alloc Gauge + BuckHashSys Gauge + DebugGC Gauge + EnableGC Gauge + Frees Gauge + HeapAlloc Gauge + HeapIdle Gauge + HeapInuse Gauge + HeapObjects Gauge + HeapReleased Gauge + HeapSys Gauge + LastGC Gauge + Lookups Gauge + Mallocs Gauge + MCacheInuse Gauge + MCacheSys Gauge + MSpanInuse Gauge + MSpanSys Gauge + NextGC Gauge + NumGC Gauge + GCCPUFraction GaugeFloat64 + PauseNs Histogram + PauseTotalNs Gauge + StackInuse Gauge + StackSys Gauge + Sys Gauge + TotalAlloc Gauge + } + NumCgoCall Gauge + NumGoroutine Gauge + NumThread Gauge + ReadMemStats Timer + } + frees uint64 + lookups uint64 + mallocs uint64 + numGC uint32 + numCgoCalls int64 + + threadCreateProfile = pprof.Lookup("threadcreate") +) + +// Capture new values for the Go runtime statistics exported in +// runtime.MemStats. This is designed to be called as a goroutine. +func CaptureRuntimeMemStats(r Registry, d time.Duration) { + for _ = range time.Tick(d) { + CaptureRuntimeMemStatsOnce(r) + } +} + +// Capture new values for the Go runtime statistics exported in +// runtime.MemStats. This is designed to be called in a background +// goroutine. Giving a registry which has not been given to +// RegisterRuntimeMemStats will panic. +// +// Be very careful with this because runtime.ReadMemStats calls the C +// functions runtime·semacquire(&runtime·worldsema) and runtime·stoptheworld() +// and that last one does what it says on the tin. +func CaptureRuntimeMemStatsOnce(r Registry) { + t := time.Now() + runtime.ReadMemStats(&memStats) // This takes 50-200us. + runtimeMetrics.ReadMemStats.UpdateSince(t) + + runtimeMetrics.MemStats.Alloc.Update(int64(memStats.Alloc)) + runtimeMetrics.MemStats.BuckHashSys.Update(int64(memStats.BuckHashSys)) + if memStats.DebugGC { + runtimeMetrics.MemStats.DebugGC.Update(1) + } else { + runtimeMetrics.MemStats.DebugGC.Update(0) + } + if memStats.EnableGC { + runtimeMetrics.MemStats.EnableGC.Update(1) + } else { + runtimeMetrics.MemStats.EnableGC.Update(0) + } + + runtimeMetrics.MemStats.Frees.Update(int64(memStats.Frees - frees)) + runtimeMetrics.MemStats.HeapAlloc.Update(int64(memStats.HeapAlloc)) + runtimeMetrics.MemStats.HeapIdle.Update(int64(memStats.HeapIdle)) + runtimeMetrics.MemStats.HeapInuse.Update(int64(memStats.HeapInuse)) + runtimeMetrics.MemStats.HeapObjects.Update(int64(memStats.HeapObjects)) + runtimeMetrics.MemStats.HeapReleased.Update(int64(memStats.HeapReleased)) + runtimeMetrics.MemStats.HeapSys.Update(int64(memStats.HeapSys)) + runtimeMetrics.MemStats.LastGC.Update(int64(memStats.LastGC)) + runtimeMetrics.MemStats.Lookups.Update(int64(memStats.Lookups - lookups)) + runtimeMetrics.MemStats.Mallocs.Update(int64(memStats.Mallocs - mallocs)) + runtimeMetrics.MemStats.MCacheInuse.Update(int64(memStats.MCacheInuse)) + runtimeMetrics.MemStats.MCacheSys.Update(int64(memStats.MCacheSys)) + runtimeMetrics.MemStats.MSpanInuse.Update(int64(memStats.MSpanInuse)) + runtimeMetrics.MemStats.MSpanSys.Update(int64(memStats.MSpanSys)) + runtimeMetrics.MemStats.NextGC.Update(int64(memStats.NextGC)) + runtimeMetrics.MemStats.NumGC.Update(int64(memStats.NumGC - numGC)) + runtimeMetrics.MemStats.GCCPUFraction.Update(gcCPUFraction(&memStats)) + + // + i := numGC % uint32(len(memStats.PauseNs)) + ii := memStats.NumGC % uint32(len(memStats.PauseNs)) + if memStats.NumGC-numGC >= uint32(len(memStats.PauseNs)) { + for i = 0; i < uint32(len(memStats.PauseNs)); i++ { + runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i])) + } + } else { + if i > ii { + for ; i < uint32(len(memStats.PauseNs)); i++ { + runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i])) + } + i = 0 + } + for ; i < ii; i++ { + runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i])) + } + } + frees = memStats.Frees + lookups = memStats.Lookups + mallocs = memStats.Mallocs + numGC = memStats.NumGC + + runtimeMetrics.MemStats.PauseTotalNs.Update(int64(memStats.PauseTotalNs)) + runtimeMetrics.MemStats.StackInuse.Update(int64(memStats.StackInuse)) + runtimeMetrics.MemStats.StackSys.Update(int64(memStats.StackSys)) + runtimeMetrics.MemStats.Sys.Update(int64(memStats.Sys)) + runtimeMetrics.MemStats.TotalAlloc.Update(int64(memStats.TotalAlloc)) + + currentNumCgoCalls := numCgoCall() + runtimeMetrics.NumCgoCall.Update(currentNumCgoCalls - numCgoCalls) + numCgoCalls = currentNumCgoCalls + + runtimeMetrics.NumGoroutine.Update(int64(runtime.NumGoroutine())) + + runtimeMetrics.NumThread.Update(int64(threadCreateProfile.Count())) +} + +// Register runtimeMetrics for the Go runtime statistics exported in runtime and +// specifically runtime.MemStats. The runtimeMetrics are named by their +// fully-qualified Go symbols, i.e. runtime.MemStats.Alloc. +func RegisterRuntimeMemStats(r Registry) { + runtimeMetrics.MemStats.Alloc = NewGauge() + runtimeMetrics.MemStats.BuckHashSys = NewGauge() + runtimeMetrics.MemStats.DebugGC = NewGauge() + runtimeMetrics.MemStats.EnableGC = NewGauge() + runtimeMetrics.MemStats.Frees = NewGauge() + runtimeMetrics.MemStats.HeapAlloc = NewGauge() + runtimeMetrics.MemStats.HeapIdle = NewGauge() + runtimeMetrics.MemStats.HeapInuse = NewGauge() + runtimeMetrics.MemStats.HeapObjects = NewGauge() + runtimeMetrics.MemStats.HeapReleased = NewGauge() + runtimeMetrics.MemStats.HeapSys = NewGauge() + runtimeMetrics.MemStats.LastGC = NewGauge() + runtimeMetrics.MemStats.Lookups = NewGauge() + runtimeMetrics.MemStats.Mallocs = NewGauge() + runtimeMetrics.MemStats.MCacheInuse = NewGauge() + runtimeMetrics.MemStats.MCacheSys = NewGauge() + runtimeMetrics.MemStats.MSpanInuse = NewGauge() + runtimeMetrics.MemStats.MSpanSys = NewGauge() + runtimeMetrics.MemStats.NextGC = NewGauge() + runtimeMetrics.MemStats.NumGC = NewGauge() + runtimeMetrics.MemStats.GCCPUFraction = NewGaugeFloat64() + runtimeMetrics.MemStats.PauseNs = NewHistogram(NewExpDecaySample(1028, 0.015)) + runtimeMetrics.MemStats.PauseTotalNs = NewGauge() + runtimeMetrics.MemStats.StackInuse = NewGauge() + runtimeMetrics.MemStats.StackSys = NewGauge() + runtimeMetrics.MemStats.Sys = NewGauge() + runtimeMetrics.MemStats.TotalAlloc = NewGauge() + runtimeMetrics.NumCgoCall = NewGauge() + runtimeMetrics.NumGoroutine = NewGauge() + runtimeMetrics.NumThread = NewGauge() + runtimeMetrics.ReadMemStats = NewTimer() + + r.Register("runtime.MemStats.Alloc", runtimeMetrics.MemStats.Alloc) + r.Register("runtime.MemStats.BuckHashSys", runtimeMetrics.MemStats.BuckHashSys) + r.Register("runtime.MemStats.DebugGC", runtimeMetrics.MemStats.DebugGC) + r.Register("runtime.MemStats.EnableGC", runtimeMetrics.MemStats.EnableGC) + r.Register("runtime.MemStats.Frees", runtimeMetrics.MemStats.Frees) + r.Register("runtime.MemStats.HeapAlloc", runtimeMetrics.MemStats.HeapAlloc) + r.Register("runtime.MemStats.HeapIdle", runtimeMetrics.MemStats.HeapIdle) + r.Register("runtime.MemStats.HeapInuse", runtimeMetrics.MemStats.HeapInuse) + r.Register("runtime.MemStats.HeapObjects", runtimeMetrics.MemStats.HeapObjects) + r.Register("runtime.MemStats.HeapReleased", runtimeMetrics.MemStats.HeapReleased) + r.Register("runtime.MemStats.HeapSys", runtimeMetrics.MemStats.HeapSys) + r.Register("runtime.MemStats.LastGC", runtimeMetrics.MemStats.LastGC) + r.Register("runtime.MemStats.Lookups", runtimeMetrics.MemStats.Lookups) + r.Register("runtime.MemStats.Mallocs", runtimeMetrics.MemStats.Mallocs) + r.Register("runtime.MemStats.MCacheInuse", runtimeMetrics.MemStats.MCacheInuse) + r.Register("runtime.MemStats.MCacheSys", runtimeMetrics.MemStats.MCacheSys) + r.Register("runtime.MemStats.MSpanInuse", runtimeMetrics.MemStats.MSpanInuse) + r.Register("runtime.MemStats.MSpanSys", runtimeMetrics.MemStats.MSpanSys) + r.Register("runtime.MemStats.NextGC", runtimeMetrics.MemStats.NextGC) + r.Register("runtime.MemStats.NumGC", runtimeMetrics.MemStats.NumGC) + r.Register("runtime.MemStats.GCCPUFraction", runtimeMetrics.MemStats.GCCPUFraction) + r.Register("runtime.MemStats.PauseNs", runtimeMetrics.MemStats.PauseNs) + r.Register("runtime.MemStats.PauseTotalNs", runtimeMetrics.MemStats.PauseTotalNs) + r.Register("runtime.MemStats.StackInuse", runtimeMetrics.MemStats.StackInuse) + r.Register("runtime.MemStats.StackSys", runtimeMetrics.MemStats.StackSys) + r.Register("runtime.MemStats.Sys", runtimeMetrics.MemStats.Sys) + r.Register("runtime.MemStats.TotalAlloc", runtimeMetrics.MemStats.TotalAlloc) + r.Register("runtime.NumCgoCall", runtimeMetrics.NumCgoCall) + r.Register("runtime.NumGoroutine", runtimeMetrics.NumGoroutine) + r.Register("runtime.NumThread", runtimeMetrics.NumThread) + r.Register("runtime.ReadMemStats", runtimeMetrics.ReadMemStats) +} diff --git a/vendor/github.com/rcrowley/go-metrics/runtime_cgo.go b/vendor/github.com/rcrowley/go-metrics/runtime_cgo.go new file mode 100644 index 000000000..e3391f4e8 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/runtime_cgo.go @@ -0,0 +1,10 @@ +// +build cgo +// +build !appengine + +package metrics + +import "runtime" + +func numCgoCall() int64 { + return runtime.NumCgoCall() +} diff --git a/vendor/github.com/rcrowley/go-metrics/runtime_gccpufraction.go b/vendor/github.com/rcrowley/go-metrics/runtime_gccpufraction.go new file mode 100644 index 000000000..ca12c05ba --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/runtime_gccpufraction.go @@ -0,0 +1,9 @@ +// +build go1.5 + +package metrics + +import "runtime" + +func gcCPUFraction(memStats *runtime.MemStats) float64 { + return memStats.GCCPUFraction +} diff --git a/vendor/github.com/rcrowley/go-metrics/runtime_no_cgo.go b/vendor/github.com/rcrowley/go-metrics/runtime_no_cgo.go new file mode 100644 index 000000000..616a3b475 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/runtime_no_cgo.go @@ -0,0 +1,7 @@ +// +build !cgo appengine + +package metrics + +func numCgoCall() int64 { + return 0 +} diff --git a/vendor/github.com/rcrowley/go-metrics/runtime_no_gccpufraction.go b/vendor/github.com/rcrowley/go-metrics/runtime_no_gccpufraction.go new file mode 100644 index 000000000..be96aa6f1 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/runtime_no_gccpufraction.go @@ -0,0 +1,9 @@ +// +build !go1.5 + +package metrics + +import "runtime" + +func gcCPUFraction(memStats *runtime.MemStats) float64 { + return 0 +} diff --git a/vendor/github.com/rcrowley/go-metrics/sample.go b/vendor/github.com/rcrowley/go-metrics/sample.go new file mode 100644 index 000000000..fecee5ef6 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/sample.go @@ -0,0 +1,616 @@ +package metrics + +import ( + "math" + "math/rand" + "sort" + "sync" + "time" +) + +const rescaleThreshold = time.Hour + +// Samples maintain a statistically-significant selection of values from +// a stream. +type Sample interface { + Clear() + Count() int64 + Max() int64 + Mean() float64 + Min() int64 + Percentile(float64) float64 + Percentiles([]float64) []float64 + Size() int + Snapshot() Sample + StdDev() float64 + Sum() int64 + Update(int64) + Values() []int64 + Variance() float64 +} + +// ExpDecaySample is an exponentially-decaying sample using a forward-decaying +// priority reservoir. See Cormode et al's "Forward Decay: A Practical Time +// Decay Model for Streaming Systems". +// +// +type ExpDecaySample struct { + alpha float64 + count int64 + mutex sync.Mutex + reservoirSize int + t0, t1 time.Time + values *expDecaySampleHeap +} + +// NewExpDecaySample constructs a new exponentially-decaying sample with the +// given reservoir size and alpha. +func NewExpDecaySample(reservoirSize int, alpha float64) Sample { + if UseNilMetrics { + return NilSample{} + } + s := &ExpDecaySample{ + alpha: alpha, + reservoirSize: reservoirSize, + t0: time.Now(), + values: newExpDecaySampleHeap(reservoirSize), + } + s.t1 = s.t0.Add(rescaleThreshold) + return s +} + +// Clear clears all samples. +func (s *ExpDecaySample) Clear() { + s.mutex.Lock() + defer s.mutex.Unlock() + s.count = 0 + s.t0 = time.Now() + s.t1 = s.t0.Add(rescaleThreshold) + s.values.Clear() +} + +// Count returns the number of samples recorded, which may exceed the +// reservoir size. +func (s *ExpDecaySample) Count() int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return s.count +} + +// Max returns the maximum value in the sample, which may not be the maximum +// value ever to be part of the sample. +func (s *ExpDecaySample) Max() int64 { + return SampleMax(s.Values()) +} + +// Mean returns the mean of the values in the sample. +func (s *ExpDecaySample) Mean() float64 { + return SampleMean(s.Values()) +} + +// Min returns the minimum value in the sample, which may not be the minimum +// value ever to be part of the sample. +func (s *ExpDecaySample) Min() int64 { + return SampleMin(s.Values()) +} + +// Percentile returns an arbitrary percentile of values in the sample. +func (s *ExpDecaySample) Percentile(p float64) float64 { + return SamplePercentile(s.Values(), p) +} + +// Percentiles returns a slice of arbitrary percentiles of values in the +// sample. +func (s *ExpDecaySample) Percentiles(ps []float64) []float64 { + return SamplePercentiles(s.Values(), ps) +} + +// Size returns the size of the sample, which is at most the reservoir size. +func (s *ExpDecaySample) Size() int { + s.mutex.Lock() + defer s.mutex.Unlock() + return s.values.Size() +} + +// Snapshot returns a read-only copy of the sample. +func (s *ExpDecaySample) Snapshot() Sample { + s.mutex.Lock() + defer s.mutex.Unlock() + vals := s.values.Values() + values := make([]int64, len(vals)) + for i, v := range vals { + values[i] = v.v + } + return &SampleSnapshot{ + count: s.count, + values: values, + } +} + +// StdDev returns the standard deviation of the values in the sample. +func (s *ExpDecaySample) StdDev() float64 { + return SampleStdDev(s.Values()) +} + +// Sum returns the sum of the values in the sample. +func (s *ExpDecaySample) Sum() int64 { + return SampleSum(s.Values()) +} + +// Update samples a new value. +func (s *ExpDecaySample) Update(v int64) { + s.update(time.Now(), v) +} + +// Values returns a copy of the values in the sample. +func (s *ExpDecaySample) Values() []int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + vals := s.values.Values() + values := make([]int64, len(vals)) + for i, v := range vals { + values[i] = v.v + } + return values +} + +// Variance returns the variance of the values in the sample. +func (s *ExpDecaySample) Variance() float64 { + return SampleVariance(s.Values()) +} + +// update samples a new value at a particular timestamp. This is a method all +// its own to facilitate testing. +func (s *ExpDecaySample) update(t time.Time, v int64) { + s.mutex.Lock() + defer s.mutex.Unlock() + s.count++ + if s.values.Size() == s.reservoirSize { + s.values.Pop() + } + s.values.Push(expDecaySample{ + k: math.Exp(t.Sub(s.t0).Seconds()*s.alpha) / rand.Float64(), + v: v, + }) + if t.After(s.t1) { + values := s.values.Values() + t0 := s.t0 + s.values.Clear() + s.t0 = t + s.t1 = s.t0.Add(rescaleThreshold) + for _, v := range values { + v.k = v.k * math.Exp(-s.alpha*s.t0.Sub(t0).Seconds()) + s.values.Push(v) + } + } +} + +// NilSample is a no-op Sample. +type NilSample struct{} + +// Clear is a no-op. +func (NilSample) Clear() {} + +// Count is a no-op. +func (NilSample) Count() int64 { return 0 } + +// Max is a no-op. +func (NilSample) Max() int64 { return 0 } + +// Mean is a no-op. +func (NilSample) Mean() float64 { return 0.0 } + +// Min is a no-op. +func (NilSample) Min() int64 { return 0 } + +// Percentile is a no-op. +func (NilSample) Percentile(p float64) float64 { return 0.0 } + +// Percentiles is a no-op. +func (NilSample) Percentiles(ps []float64) []float64 { + return make([]float64, len(ps)) +} + +// Size is a no-op. +func (NilSample) Size() int { return 0 } + +// Sample is a no-op. +func (NilSample) Snapshot() Sample { return NilSample{} } + +// StdDev is a no-op. +func (NilSample) StdDev() float64 { return 0.0 } + +// Sum is a no-op. +func (NilSample) Sum() int64 { return 0 } + +// Update is a no-op. +func (NilSample) Update(v int64) {} + +// Values is a no-op. +func (NilSample) Values() []int64 { return []int64{} } + +// Variance is a no-op. +func (NilSample) Variance() float64 { return 0.0 } + +// SampleMax returns the maximum value of the slice of int64. +func SampleMax(values []int64) int64 { + if 0 == len(values) { + return 0 + } + var max int64 = math.MinInt64 + for _, v := range values { + if max < v { + max = v + } + } + return max +} + +// SampleMean returns the mean value of the slice of int64. +func SampleMean(values []int64) float64 { + if 0 == len(values) { + return 0.0 + } + return float64(SampleSum(values)) / float64(len(values)) +} + +// SampleMin returns the minimum value of the slice of int64. +func SampleMin(values []int64) int64 { + if 0 == len(values) { + return 0 + } + var min int64 = math.MaxInt64 + for _, v := range values { + if min > v { + min = v + } + } + return min +} + +// SamplePercentiles returns an arbitrary percentile of the slice of int64. +func SamplePercentile(values int64Slice, p float64) float64 { + return SamplePercentiles(values, []float64{p})[0] +} + +// SamplePercentiles returns a slice of arbitrary percentiles of the slice of +// int64. +func SamplePercentiles(values int64Slice, ps []float64) []float64 { + scores := make([]float64, len(ps)) + size := len(values) + if size > 0 { + sort.Sort(values) + for i, p := range ps { + pos := p * float64(size+1) + if pos < 1.0 { + scores[i] = float64(values[0]) + } else if pos >= float64(size) { + scores[i] = float64(values[size-1]) + } else { + lower := float64(values[int(pos)-1]) + upper := float64(values[int(pos)]) + scores[i] = lower + (pos-math.Floor(pos))*(upper-lower) + } + } + } + return scores +} + +// SampleSnapshot is a read-only copy of another Sample. +type SampleSnapshot struct { + count int64 + values []int64 +} + +func NewSampleSnapshot(count int64, values []int64) *SampleSnapshot { + return &SampleSnapshot{ + count: count, + values: values, + } +} + +// Clear panics. +func (*SampleSnapshot) Clear() { + panic("Clear called on a SampleSnapshot") +} + +// Count returns the count of inputs at the time the snapshot was taken. +func (s *SampleSnapshot) Count() int64 { return s.count } + +// Max returns the maximal value at the time the snapshot was taken. +func (s *SampleSnapshot) Max() int64 { return SampleMax(s.values) } + +// Mean returns the mean value at the time the snapshot was taken. +func (s *SampleSnapshot) Mean() float64 { return SampleMean(s.values) } + +// Min returns the minimal value at the time the snapshot was taken. +func (s *SampleSnapshot) Min() int64 { return SampleMin(s.values) } + +// Percentile returns an arbitrary percentile of values at the time the +// snapshot was taken. +func (s *SampleSnapshot) Percentile(p float64) float64 { + return SamplePercentile(s.values, p) +} + +// Percentiles returns a slice of arbitrary percentiles of values at the time +// the snapshot was taken. +func (s *SampleSnapshot) Percentiles(ps []float64) []float64 { + return SamplePercentiles(s.values, ps) +} + +// Size returns the size of the sample at the time the snapshot was taken. +func (s *SampleSnapshot) Size() int { return len(s.values) } + +// Snapshot returns the snapshot. +func (s *SampleSnapshot) Snapshot() Sample { return s } + +// StdDev returns the standard deviation of values at the time the snapshot was +// taken. +func (s *SampleSnapshot) StdDev() float64 { return SampleStdDev(s.values) } + +// Sum returns the sum of values at the time the snapshot was taken. +func (s *SampleSnapshot) Sum() int64 { return SampleSum(s.values) } + +// Update panics. +func (*SampleSnapshot) Update(int64) { + panic("Update called on a SampleSnapshot") +} + +// Values returns a copy of the values in the sample. +func (s *SampleSnapshot) Values() []int64 { + values := make([]int64, len(s.values)) + copy(values, s.values) + return values +} + +// Variance returns the variance of values at the time the snapshot was taken. +func (s *SampleSnapshot) Variance() float64 { return SampleVariance(s.values) } + +// SampleStdDev returns the standard deviation of the slice of int64. +func SampleStdDev(values []int64) float64 { + return math.Sqrt(SampleVariance(values)) +} + +// SampleSum returns the sum of the slice of int64. +func SampleSum(values []int64) int64 { + var sum int64 + for _, v := range values { + sum += v + } + return sum +} + +// SampleVariance returns the variance of the slice of int64. +func SampleVariance(values []int64) float64 { + if 0 == len(values) { + return 0.0 + } + m := SampleMean(values) + var sum float64 + for _, v := range values { + d := float64(v) - m + sum += d * d + } + return sum / float64(len(values)) +} + +// A uniform sample using Vitter's Algorithm R. +// +// +type UniformSample struct { + count int64 + mutex sync.Mutex + reservoirSize int + values []int64 +} + +// NewUniformSample constructs a new uniform sample with the given reservoir +// size. +func NewUniformSample(reservoirSize int) Sample { + if UseNilMetrics { + return NilSample{} + } + return &UniformSample{ + reservoirSize: reservoirSize, + values: make([]int64, 0, reservoirSize), + } +} + +// Clear clears all samples. +func (s *UniformSample) Clear() { + s.mutex.Lock() + defer s.mutex.Unlock() + s.count = 0 + s.values = make([]int64, 0, s.reservoirSize) +} + +// Count returns the number of samples recorded, which may exceed the +// reservoir size. +func (s *UniformSample) Count() int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return s.count +} + +// Max returns the maximum value in the sample, which may not be the maximum +// value ever to be part of the sample. +func (s *UniformSample) Max() int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleMax(s.values) +} + +// Mean returns the mean of the values in the sample. +func (s *UniformSample) Mean() float64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleMean(s.values) +} + +// Min returns the minimum value in the sample, which may not be the minimum +// value ever to be part of the sample. +func (s *UniformSample) Min() int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleMin(s.values) +} + +// Percentile returns an arbitrary percentile of values in the sample. +func (s *UniformSample) Percentile(p float64) float64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SamplePercentile(s.values, p) +} + +// Percentiles returns a slice of arbitrary percentiles of values in the +// sample. +func (s *UniformSample) Percentiles(ps []float64) []float64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SamplePercentiles(s.values, ps) +} + +// Size returns the size of the sample, which is at most the reservoir size. +func (s *UniformSample) Size() int { + s.mutex.Lock() + defer s.mutex.Unlock() + return len(s.values) +} + +// Snapshot returns a read-only copy of the sample. +func (s *UniformSample) Snapshot() Sample { + s.mutex.Lock() + defer s.mutex.Unlock() + values := make([]int64, len(s.values)) + copy(values, s.values) + return &SampleSnapshot{ + count: s.count, + values: values, + } +} + +// StdDev returns the standard deviation of the values in the sample. +func (s *UniformSample) StdDev() float64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleStdDev(s.values) +} + +// Sum returns the sum of the values in the sample. +func (s *UniformSample) Sum() int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleSum(s.values) +} + +// Update samples a new value. +func (s *UniformSample) Update(v int64) { + s.mutex.Lock() + defer s.mutex.Unlock() + s.count++ + if len(s.values) < s.reservoirSize { + s.values = append(s.values, v) + } else { + r := rand.Int63n(s.count) + if r < int64(len(s.values)) { + s.values[int(r)] = v + } + } +} + +// Values returns a copy of the values in the sample. +func (s *UniformSample) Values() []int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + values := make([]int64, len(s.values)) + copy(values, s.values) + return values +} + +// Variance returns the variance of the values in the sample. +func (s *UniformSample) Variance() float64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleVariance(s.values) +} + +// expDecaySample represents an individual sample in a heap. +type expDecaySample struct { + k float64 + v int64 +} + +func newExpDecaySampleHeap(reservoirSize int) *expDecaySampleHeap { + return &expDecaySampleHeap{make([]expDecaySample, 0, reservoirSize)} +} + +// expDecaySampleHeap is a min-heap of expDecaySamples. +// The internal implementation is copied from the standard library's container/heap +type expDecaySampleHeap struct { + s []expDecaySample +} + +func (h *expDecaySampleHeap) Clear() { + h.s = h.s[:0] +} + +func (h *expDecaySampleHeap) Push(s expDecaySample) { + n := len(h.s) + h.s = h.s[0 : n+1] + h.s[n] = s + h.up(n) +} + +func (h *expDecaySampleHeap) Pop() expDecaySample { + n := len(h.s) - 1 + h.s[0], h.s[n] = h.s[n], h.s[0] + h.down(0, n) + + n = len(h.s) + s := h.s[n-1] + h.s = h.s[0 : n-1] + return s +} + +func (h *expDecaySampleHeap) Size() int { + return len(h.s) +} + +func (h *expDecaySampleHeap) Values() []expDecaySample { + return h.s +} + +func (h *expDecaySampleHeap) up(j int) { + for { + i := (j - 1) / 2 // parent + if i == j || !(h.s[j].k < h.s[i].k) { + break + } + h.s[i], h.s[j] = h.s[j], h.s[i] + j = i + } +} + +func (h *expDecaySampleHeap) down(i, n int) { + for { + j1 := 2*i + 1 + if j1 >= n || j1 < 0 { // j1 < 0 after int overflow + break + } + j := j1 // left child + if j2 := j1 + 1; j2 < n && !(h.s[j1].k < h.s[j2].k) { + j = j2 // = 2*i + 2 // right child + } + if !(h.s[j].k < h.s[i].k) { + break + } + h.s[i], h.s[j] = h.s[j], h.s[i] + i = j + } +} + +type int64Slice []int64 + +func (p int64Slice) Len() int { return len(p) } +func (p int64Slice) Less(i, j int) bool { return p[i] < p[j] } +func (p int64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } diff --git a/vendor/github.com/rcrowley/go-metrics/syslog.go b/vendor/github.com/rcrowley/go-metrics/syslog.go new file mode 100644 index 000000000..693f19085 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/syslog.go @@ -0,0 +1,78 @@ +// +build !windows + +package metrics + +import ( + "fmt" + "log/syslog" + "time" +) + +// Output each metric in the given registry to syslog periodically using +// the given syslogger. +func Syslog(r Registry, d time.Duration, w *syslog.Writer) { + for _ = range time.Tick(d) { + r.Each(func(name string, i interface{}) { + switch metric := i.(type) { + case Counter: + w.Info(fmt.Sprintf("counter %s: count: %d", name, metric.Count())) + case Gauge: + w.Info(fmt.Sprintf("gauge %s: value: %d", name, metric.Value())) + case GaugeFloat64: + w.Info(fmt.Sprintf("gauge %s: value: %f", name, metric.Value())) + case Healthcheck: + metric.Check() + w.Info(fmt.Sprintf("healthcheck %s: error: %v", name, metric.Error())) + case Histogram: + h := metric.Snapshot() + ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + w.Info(fmt.Sprintf( + "histogram %s: count: %d min: %d max: %d mean: %.2f stddev: %.2f median: %.2f 75%%: %.2f 95%%: %.2f 99%%: %.2f 99.9%%: %.2f", + name, + h.Count(), + h.Min(), + h.Max(), + h.Mean(), + h.StdDev(), + ps[0], + ps[1], + ps[2], + ps[3], + ps[4], + )) + case Meter: + m := metric.Snapshot() + w.Info(fmt.Sprintf( + "meter %s: count: %d 1-min: %.2f 5-min: %.2f 15-min: %.2f mean: %.2f", + name, + m.Count(), + m.Rate1(), + m.Rate5(), + m.Rate15(), + m.RateMean(), + )) + case Timer: + t := metric.Snapshot() + ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + w.Info(fmt.Sprintf( + "timer %s: count: %d min: %d max: %d mean: %.2f stddev: %.2f median: %.2f 75%%: %.2f 95%%: %.2f 99%%: %.2f 99.9%%: %.2f 1-min: %.2f 5-min: %.2f 15-min: %.2f mean-rate: %.2f", + name, + t.Count(), + t.Min(), + t.Max(), + t.Mean(), + t.StdDev(), + ps[0], + ps[1], + ps[2], + ps[3], + ps[4], + t.Rate1(), + t.Rate5(), + t.Rate15(), + t.RateMean(), + )) + } + }) + } +} diff --git a/vendor/github.com/rcrowley/go-metrics/timer.go b/vendor/github.com/rcrowley/go-metrics/timer.go new file mode 100644 index 000000000..d6ec4c626 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/timer.go @@ -0,0 +1,329 @@ +package metrics + +import ( + "sync" + "time" +) + +// Timers capture the duration and rate of events. +type Timer interface { + Count() int64 + Max() int64 + Mean() float64 + Min() int64 + Percentile(float64) float64 + Percentiles([]float64) []float64 + Rate1() float64 + Rate5() float64 + Rate15() float64 + RateMean() float64 + Snapshot() Timer + StdDev() float64 + Stop() + Sum() int64 + Time(func()) + Update(time.Duration) + UpdateSince(time.Time) + Variance() float64 +} + +// GetOrRegisterTimer returns an existing Timer or constructs and registers a +// new StandardTimer. +// Be sure to unregister the meter from the registry once it is of no use to +// allow for garbage collection. +func GetOrRegisterTimer(name string, r Registry) Timer { + if nil == r { + r = DefaultRegistry + } + return r.GetOrRegister(name, NewTimer).(Timer) +} + +// NewCustomTimer constructs a new StandardTimer from a Histogram and a Meter. +// Be sure to call Stop() once the timer is of no use to allow for garbage collection. +func NewCustomTimer(h Histogram, m Meter) Timer { + if UseNilMetrics { + return NilTimer{} + } + return &StandardTimer{ + histogram: h, + meter: m, + } +} + +// NewRegisteredTimer constructs and registers a new StandardTimer. +// Be sure to unregister the meter from the registry once it is of no use to +// allow for garbage collection. +func NewRegisteredTimer(name string, r Registry) Timer { + c := NewTimer() + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// NewTimer constructs a new StandardTimer using an exponentially-decaying +// sample with the same reservoir size and alpha as UNIX load averages. +// Be sure to call Stop() once the timer is of no use to allow for garbage collection. +func NewTimer() Timer { + if UseNilMetrics { + return NilTimer{} + } + return &StandardTimer{ + histogram: NewHistogram(NewExpDecaySample(1028, 0.015)), + meter: NewMeter(), + } +} + +// NilTimer is a no-op Timer. +type NilTimer struct { + h Histogram + m Meter +} + +// Count is a no-op. +func (NilTimer) Count() int64 { return 0 } + +// Max is a no-op. +func (NilTimer) Max() int64 { return 0 } + +// Mean is a no-op. +func (NilTimer) Mean() float64 { return 0.0 } + +// Min is a no-op. +func (NilTimer) Min() int64 { return 0 } + +// Percentile is a no-op. +func (NilTimer) Percentile(p float64) float64 { return 0.0 } + +// Percentiles is a no-op. +func (NilTimer) Percentiles(ps []float64) []float64 { + return make([]float64, len(ps)) +} + +// Rate1 is a no-op. +func (NilTimer) Rate1() float64 { return 0.0 } + +// Rate5 is a no-op. +func (NilTimer) Rate5() float64 { return 0.0 } + +// Rate15 is a no-op. +func (NilTimer) Rate15() float64 { return 0.0 } + +// RateMean is a no-op. +func (NilTimer) RateMean() float64 { return 0.0 } + +// Snapshot is a no-op. +func (NilTimer) Snapshot() Timer { return NilTimer{} } + +// StdDev is a no-op. +func (NilTimer) StdDev() float64 { return 0.0 } + +// Stop is a no-op. +func (NilTimer) Stop() {} + +// Sum is a no-op. +func (NilTimer) Sum() int64 { return 0 } + +// Time is a no-op. +func (NilTimer) Time(func()) {} + +// Update is a no-op. +func (NilTimer) Update(time.Duration) {} + +// UpdateSince is a no-op. +func (NilTimer) UpdateSince(time.Time) {} + +// Variance is a no-op. +func (NilTimer) Variance() float64 { return 0.0 } + +// StandardTimer is the standard implementation of a Timer and uses a Histogram +// and Meter. +type StandardTimer struct { + histogram Histogram + meter Meter + mutex sync.Mutex +} + +// Count returns the number of events recorded. +func (t *StandardTimer) Count() int64 { + return t.histogram.Count() +} + +// Max returns the maximum value in the sample. +func (t *StandardTimer) Max() int64 { + return t.histogram.Max() +} + +// Mean returns the mean of the values in the sample. +func (t *StandardTimer) Mean() float64 { + return t.histogram.Mean() +} + +// Min returns the minimum value in the sample. +func (t *StandardTimer) Min() int64 { + return t.histogram.Min() +} + +// Percentile returns an arbitrary percentile of the values in the sample. +func (t *StandardTimer) Percentile(p float64) float64 { + return t.histogram.Percentile(p) +} + +// Percentiles returns a slice of arbitrary percentiles of the values in the +// sample. +func (t *StandardTimer) Percentiles(ps []float64) []float64 { + return t.histogram.Percentiles(ps) +} + +// Rate1 returns the one-minute moving average rate of events per second. +func (t *StandardTimer) Rate1() float64 { + return t.meter.Rate1() +} + +// Rate5 returns the five-minute moving average rate of events per second. +func (t *StandardTimer) Rate5() float64 { + return t.meter.Rate5() +} + +// Rate15 returns the fifteen-minute moving average rate of events per second. +func (t *StandardTimer) Rate15() float64 { + return t.meter.Rate15() +} + +// RateMean returns the meter's mean rate of events per second. +func (t *StandardTimer) RateMean() float64 { + return t.meter.RateMean() +} + +// Snapshot returns a read-only copy of the timer. +func (t *StandardTimer) Snapshot() Timer { + t.mutex.Lock() + defer t.mutex.Unlock() + return &TimerSnapshot{ + histogram: t.histogram.Snapshot().(*HistogramSnapshot), + meter: t.meter.Snapshot().(*MeterSnapshot), + } +} + +// StdDev returns the standard deviation of the values in the sample. +func (t *StandardTimer) StdDev() float64 { + return t.histogram.StdDev() +} + +// Stop stops the meter. +func (t *StandardTimer) Stop() { + t.meter.Stop() +} + +// Sum returns the sum in the sample. +func (t *StandardTimer) Sum() int64 { + return t.histogram.Sum() +} + +// Record the duration of the execution of the given function. +func (t *StandardTimer) Time(f func()) { + ts := time.Now() + f() + t.Update(time.Since(ts)) +} + +// Record the duration of an event. +func (t *StandardTimer) Update(d time.Duration) { + t.mutex.Lock() + defer t.mutex.Unlock() + t.histogram.Update(int64(d)) + t.meter.Mark(1) +} + +// Record the duration of an event that started at a time and ends now. +func (t *StandardTimer) UpdateSince(ts time.Time) { + t.mutex.Lock() + defer t.mutex.Unlock() + t.histogram.Update(int64(time.Since(ts))) + t.meter.Mark(1) +} + +// Variance returns the variance of the values in the sample. +func (t *StandardTimer) Variance() float64 { + return t.histogram.Variance() +} + +// TimerSnapshot is a read-only copy of another Timer. +type TimerSnapshot struct { + histogram *HistogramSnapshot + meter *MeterSnapshot +} + +// Count returns the number of events recorded at the time the snapshot was +// taken. +func (t *TimerSnapshot) Count() int64 { return t.histogram.Count() } + +// Max returns the maximum value at the time the snapshot was taken. +func (t *TimerSnapshot) Max() int64 { return t.histogram.Max() } + +// Mean returns the mean value at the time the snapshot was taken. +func (t *TimerSnapshot) Mean() float64 { return t.histogram.Mean() } + +// Min returns the minimum value at the time the snapshot was taken. +func (t *TimerSnapshot) Min() int64 { return t.histogram.Min() } + +// Percentile returns an arbitrary percentile of sampled values at the time the +// snapshot was taken. +func (t *TimerSnapshot) Percentile(p float64) float64 { + return t.histogram.Percentile(p) +} + +// Percentiles returns a slice of arbitrary percentiles of sampled values at +// the time the snapshot was taken. +func (t *TimerSnapshot) Percentiles(ps []float64) []float64 { + return t.histogram.Percentiles(ps) +} + +// Rate1 returns the one-minute moving average rate of events per second at the +// time the snapshot was taken. +func (t *TimerSnapshot) Rate1() float64 { return t.meter.Rate1() } + +// Rate5 returns the five-minute moving average rate of events per second at +// the time the snapshot was taken. +func (t *TimerSnapshot) Rate5() float64 { return t.meter.Rate5() } + +// Rate15 returns the fifteen-minute moving average rate of events per second +// at the time the snapshot was taken. +func (t *TimerSnapshot) Rate15() float64 { return t.meter.Rate15() } + +// RateMean returns the meter's mean rate of events per second at the time the +// snapshot was taken. +func (t *TimerSnapshot) RateMean() float64 { return t.meter.RateMean() } + +// Snapshot returns the snapshot. +func (t *TimerSnapshot) Snapshot() Timer { return t } + +// StdDev returns the standard deviation of the values at the time the snapshot +// was taken. +func (t *TimerSnapshot) StdDev() float64 { return t.histogram.StdDev() } + +// Stop is a no-op. +func (t *TimerSnapshot) Stop() {} + +// Sum returns the sum at the time the snapshot was taken. +func (t *TimerSnapshot) Sum() int64 { return t.histogram.Sum() } + +// Time panics. +func (*TimerSnapshot) Time(func()) { + panic("Time called on a TimerSnapshot") +} + +// Update panics. +func (*TimerSnapshot) Update(time.Duration) { + panic("Update called on a TimerSnapshot") +} + +// UpdateSince panics. +func (*TimerSnapshot) UpdateSince(time.Time) { + panic("UpdateSince called on a TimerSnapshot") +} + +// Variance returns the variance of the values at the time the snapshot was +// taken. +func (t *TimerSnapshot) Variance() float64 { return t.histogram.Variance() } diff --git a/vendor/github.com/rcrowley/go-metrics/validate.sh b/vendor/github.com/rcrowley/go-metrics/validate.sh new file mode 100755 index 000000000..c4ae91e64 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/validate.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +set -e + +# check there are no formatting issues +GOFMT_LINES=`gofmt -l . | wc -l | xargs` +test $GOFMT_LINES -eq 0 || echo "gofmt needs to be run, ${GOFMT_LINES} files have issues" + +# run the tests for the root package +go test -race . diff --git a/vendor/github.com/rcrowley/go-metrics/writer.go b/vendor/github.com/rcrowley/go-metrics/writer.go new file mode 100644 index 000000000..091e971d2 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/writer.go @@ -0,0 +1,100 @@ +package metrics + +import ( + "fmt" + "io" + "sort" + "time" +) + +// Write sorts writes each metric in the given registry periodically to the +// given io.Writer. +func Write(r Registry, d time.Duration, w io.Writer) { + for _ = range time.Tick(d) { + WriteOnce(r, w) + } +} + +// WriteOnce sorts and writes metrics in the given registry to the given +// io.Writer. +func WriteOnce(r Registry, w io.Writer) { + var namedMetrics namedMetricSlice + r.Each(func(name string, i interface{}) { + namedMetrics = append(namedMetrics, namedMetric{name, i}) + }) + + sort.Sort(namedMetrics) + for _, namedMetric := range namedMetrics { + switch metric := namedMetric.m.(type) { + case Counter: + fmt.Fprintf(w, "counter %s\n", namedMetric.name) + fmt.Fprintf(w, " count: %9d\n", metric.Count()) + case Gauge: + fmt.Fprintf(w, "gauge %s\n", namedMetric.name) + fmt.Fprintf(w, " value: %9d\n", metric.Value()) + case GaugeFloat64: + fmt.Fprintf(w, "gauge %s\n", namedMetric.name) + fmt.Fprintf(w, " value: %f\n", metric.Value()) + case Healthcheck: + metric.Check() + fmt.Fprintf(w, "healthcheck %s\n", namedMetric.name) + fmt.Fprintf(w, " error: %v\n", metric.Error()) + case Histogram: + h := metric.Snapshot() + ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + fmt.Fprintf(w, "histogram %s\n", namedMetric.name) + fmt.Fprintf(w, " count: %9d\n", h.Count()) + fmt.Fprintf(w, " min: %9d\n", h.Min()) + fmt.Fprintf(w, " max: %9d\n", h.Max()) + fmt.Fprintf(w, " mean: %12.2f\n", h.Mean()) + fmt.Fprintf(w, " stddev: %12.2f\n", h.StdDev()) + fmt.Fprintf(w, " median: %12.2f\n", ps[0]) + fmt.Fprintf(w, " 75%%: %12.2f\n", ps[1]) + fmt.Fprintf(w, " 95%%: %12.2f\n", ps[2]) + fmt.Fprintf(w, " 99%%: %12.2f\n", ps[3]) + fmt.Fprintf(w, " 99.9%%: %12.2f\n", ps[4]) + case Meter: + m := metric.Snapshot() + fmt.Fprintf(w, "meter %s\n", namedMetric.name) + fmt.Fprintf(w, " count: %9d\n", m.Count()) + fmt.Fprintf(w, " 1-min rate: %12.2f\n", m.Rate1()) + fmt.Fprintf(w, " 5-min rate: %12.2f\n", m.Rate5()) + fmt.Fprintf(w, " 15-min rate: %12.2f\n", m.Rate15()) + fmt.Fprintf(w, " mean rate: %12.2f\n", m.RateMean()) + case Timer: + t := metric.Snapshot() + ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + fmt.Fprintf(w, "timer %s\n", namedMetric.name) + fmt.Fprintf(w, " count: %9d\n", t.Count()) + fmt.Fprintf(w, " min: %9d\n", t.Min()) + fmt.Fprintf(w, " max: %9d\n", t.Max()) + fmt.Fprintf(w, " mean: %12.2f\n", t.Mean()) + fmt.Fprintf(w, " stddev: %12.2f\n", t.StdDev()) + fmt.Fprintf(w, " median: %12.2f\n", ps[0]) + fmt.Fprintf(w, " 75%%: %12.2f\n", ps[1]) + fmt.Fprintf(w, " 95%%: %12.2f\n", ps[2]) + fmt.Fprintf(w, " 99%%: %12.2f\n", ps[3]) + fmt.Fprintf(w, " 99.9%%: %12.2f\n", ps[4]) + fmt.Fprintf(w, " 1-min rate: %12.2f\n", t.Rate1()) + fmt.Fprintf(w, " 5-min rate: %12.2f\n", t.Rate5()) + fmt.Fprintf(w, " 15-min rate: %12.2f\n", t.Rate15()) + fmt.Fprintf(w, " mean rate: %12.2f\n", t.RateMean()) + } + } +} + +type namedMetric struct { + name string + m interface{} +} + +// namedMetricSlice is a slice of namedMetrics that implements sort.Interface. +type namedMetricSlice []namedMetric + +func (nms namedMetricSlice) Len() int { return len(nms) } + +func (nms namedMetricSlice) Swap(i, j int) { nms[i], nms[j] = nms[j], nms[i] } + +func (nms namedMetricSlice) Less(i, j int) bool { + return nms[i].name < nms[j].name +} diff --git a/vendor/github.com/satori/go.uuid/README.md b/vendor/github.com/satori/go.uuid/README.md index 770284969..362b27067 100644 --- a/vendor/github.com/satori/go.uuid/README.md +++ b/vendor/github.com/satori/go.uuid/README.md @@ -23,7 +23,7 @@ Use the `go` command: ## Requirements -UUID package requires Go >= 1.2. +UUID package tested against Go >= 1.6. ## Example @@ -53,6 +53,7 @@ func main() { u2, err := uuid.FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8") if err != nil { fmt.Printf("Something went wrong: %s", err) + return } fmt.Printf("Successfully parsed: %s", u2) } diff --git a/vendor/github.com/satori/go.uuid/generator.go b/vendor/github.com/satori/go.uuid/generator.go index 499dc35fb..c50d33cab 100644 --- a/vendor/github.com/satori/go.uuid/generator.go +++ b/vendor/github.com/satori/go.uuid/generator.go @@ -165,7 +165,7 @@ func (g *rfc4122Generator) NewV3(ns UUID, name string) UUID { // NewV4 returns random generated UUID. func (g *rfc4122Generator) NewV4() (UUID, error) { u := UUID{} - if _, err := g.rand.Read(u[:]); err != nil { + if _, err := io.ReadFull(g.rand, u[:]); err != nil { return Nil, err } u.SetVersion(V4) @@ -188,7 +188,7 @@ func (g *rfc4122Generator) getClockSequence() (uint64, uint16, error) { var err error g.clockSequenceOnce.Do(func() { buf := make([]byte, 2) - if _, err = g.rand.Read(buf); err != nil { + if _, err = io.ReadFull(g.rand, buf); err != nil { return } g.clockSequence = binary.BigEndian.Uint16(buf) @@ -222,7 +222,7 @@ func (g *rfc4122Generator) getHardwareAddr() ([]byte, error) { // Initialize hardwareAddr randomly in case // of real network interfaces absence. - if _, err = g.rand.Read(g.hardwareAddr[:]); err != nil { + if _, err = io.ReadFull(g.rand, g.hardwareAddr[:]); err != nil { return } // Set multicast bit as recommended by RFC 4122 diff --git a/vendor/github.com/siddontang/go-mysql/mysql/util.go b/vendor/github.com/siddontang/go-mysql/mysql/util.go index 7fe41fa21..1e74246fa 100644 --- a/vendor/github.com/siddontang/go-mysql/mysql/util.go +++ b/vendor/github.com/siddontang/go-mysql/mysql/util.go @@ -1,11 +1,11 @@ package mysql import ( - "crypto/rand" "crypto/sha1" "encoding/binary" "fmt" "io" + "math/rand" "runtime" "strings" @@ -48,17 +48,14 @@ func CalcPassword(scramble, password []byte) []byte { return scramble } +// Copy from github.com/pingcap/tidb mysql/util.go +// See https://github.com/mysql/mysql-server/blob/5.7/mysys_ssl/crypt_genhash_impl.cc#L435 func RandomBuf(size int) ([]byte, error) { buf := make([]byte, size) - - if _, err := io.ReadFull(rand.Reader, buf); err != nil { - return nil, errors.Trace(err) - } - - // avoid to generate '\0' - for i, b := range buf { - if uint8(b) == 0 { - buf[i] = '0' + for i := 0; i < size; i++ { + buf[i] = byte(rand.Intn(127)) + if buf[i] == 0 || buf[i] == byte('$') { + buf[i]++ } } diff --git a/vendor/github.com/siddontang/go-mysql/server/auth.go b/vendor/github.com/siddontang/go-mysql/server/auth.go index b66ea4e0c..cb6ca160f 100644 --- a/vendor/github.com/siddontang/go-mysql/server/auth.go +++ b/vendor/github.com/siddontang/go-mysql/server/auth.go @@ -89,20 +89,37 @@ func (c *Conn) readHandshakeResponse(password string) error { return NewDefaultError(ER_NO_SUCH_USER, user, c.RemoteAddr().String()) } - //auth length and auth - authLen := int(data[pos]) - pos++ - auth := data[pos : pos+authLen] + var auth []byte + + if c.capability&CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA > 0 { + // Fix from github.com/pingcap/tidb + // MySQL client sets the wrong capability, it will set this bit even server doesn't + // support ClientPluginAuthLenencClientData. + // https://github.com/mysql/mysql-server/blob/5.7/sql-common/client.c#L3478 + num, null, off := LengthEncodedInt(data[pos:]) + pos += off + if !null { + auth = data[pos : pos+int(num)] + pos += int(num) + } + } else if c.capability&CLIENT_SECURE_CONNECTION > 0 { + //auth length and auth + authLen := int(data[pos]) + pos++ + auth = data[pos : pos+authLen] + pos += authLen + } else { + auth = data[pos : pos+bytes.IndexByte(data[pos:], 0)] + pos += len(auth) + 1 + } checkAuth := CalcPassword(c.salt, []byte(password)) if !bytes.Equal(auth, checkAuth) { - return NewDefaultError(ER_ACCESS_DENIED_ERROR, c.RemoteAddr().String(), c.user, "Yes") + return NewDefaultError(ER_ACCESS_DENIED_ERROR, c.user, c.RemoteAddr().String(), "Yes") } - pos += authLen - - if c.capability|CLIENT_CONNECT_WITH_DB > 0 { + if c.capability&CLIENT_CONNECT_WITH_DB > 0 { if len(data[pos:]) == 0 { return nil } diff --git a/vendor/github.com/xo/tblfmt/go.mod b/vendor/github.com/xo/tblfmt/go.mod index b8dc613f2..f66af95c8 100644 --- a/vendor/github.com/xo/tblfmt/go.mod +++ b/vendor/github.com/xo/tblfmt/go.mod @@ -1,3 +1,6 @@ module github.com/xo/tblfmt -require github.com/mattn/go-runewidth v0.0.3 +require ( + github.com/mattn/go-runewidth v0.0.3 + github.com/xo/dburl v0.0.0-20180921222126-e33971d4c132 +) diff --git a/vendor/github.com/xo/tblfmt/go.sum b/vendor/github.com/xo/tblfmt/go.sum index 1c1891604..977b1d669 100644 --- a/vendor/github.com/xo/tblfmt/go.sum +++ b/vendor/github.com/xo/tblfmt/go.sum @@ -1,2 +1,4 @@ github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8BzLR4= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/xo/dburl v0.0.0-20180921222126-e33971d4c132 h1:cRKJ4yZeCZbCEXJmjZMa9s2z+3eavo2a4qu/usvVopI= +github.com/xo/dburl v0.0.0-20180921222126-e33971d4c132/go.mod h1:g6rdekR8vgfVZrkLWfobLTm0kVez7GAN23mWtkGCJ14= diff --git a/vendor/github.com/xo/usql/stmt/parse.go b/vendor/github.com/xo/usql/stmt/parse.go index f804bf5f2..2da055830 100644 --- a/vendor/github.com/xo/usql/stmt/parse.go +++ b/vendor/github.com/xo/usql/stmt/parse.go @@ -310,7 +310,7 @@ loop: // add space when remaining runes begin with space, and previous // captured word did not - if sl := len(s); sl != 0 && IsSpace(r[0]) && !IsSpace(s[sl-1]) { + if sl := len(s); sl != 0 && len(r) > 0 && IsSpace(r[0]) && !IsSpace(s[sl-1]) { s = append(s, ' ') } diff --git a/vendor/github.com/xtaci/smux/LICENSE b/vendor/github.com/xtaci/smux/LICENSE new file mode 100644 index 000000000..eed41acb1 --- /dev/null +++ b/vendor/github.com/xtaci/smux/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016-2017 Daniel Fu + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/xtaci/smux/README.md b/vendor/github.com/xtaci/smux/README.md new file mode 100644 index 000000000..c01c346ee --- /dev/null +++ b/vendor/github.com/xtaci/smux/README.md @@ -0,0 +1,99 @@ +smux + +[![GoDoc][1]][2] [![MIT licensed][3]][4] [![Build Status][5]][6] [![Go Report Card][7]][8] [![Coverage Statusd][9]][10] + +smux + +[1]: https://godoc.org/github.com/xtaci/smux?status.svg +[2]: https://godoc.org/github.com/xtaci/smux +[3]: https://img.shields.io/badge/license-MIT-blue.svg +[4]: LICENSE +[5]: https://travis-ci.org/xtaci/smux.svg?branch=master +[6]: https://travis-ci.org/xtaci/smux +[7]: https://goreportcard.com/badge/github.com/xtaci/smux +[8]: https://goreportcard.com/report/github.com/xtaci/smux +[9]: https://codecov.io/gh/xtaci/smux/branch/master/graph/badge.svg +[10]: https://codecov.io/gh/xtaci/smux + +## Introduction + +Smux ( **S**imple **MU**ltiple**X**ing) is a multiplexing library for Golang. It relies on an underlying connection to provide reliability and ordering, such as TCP or [KCP](https://github.com/xtaci/kcp-go), and provides stream-oriented multiplexing. The original intention of this library is to power the connection management for [kcp-go](https://github.com/xtaci/kcp-go). + +## Features + +1. Tiny, less than 600 LOC. +2. ***Token bucket*** controlled receiving, which provides smoother bandwidth graph(see picture below). +3. Session-wide receive buffer, shared among streams, tightly controlled overall memory usage. +4. Minimized header(8Bytes), maximized payload. +5. Well-tested on millions of devices in [kcptun](https://github.com/xtaci/kcptun). + +![smooth bandwidth curve](curve.jpg) + +## Documentation + +For complete documentation, see the associated [Godoc](https://godoc.org/github.com/xtaci/smux). + +## Specification + +``` +VERSION(1B) | CMD(1B) | LENGTH(2B) | STREAMID(4B) | DATA(LENGTH) +``` + +## Usage + +The API of smux are mostly taken from [yamux](https://github.com/hashicorp/yamux) + +```go + +func client() { + // Get a TCP connection + conn, err := net.Dial(...) + if err != nil { + panic(err) + } + + // Setup client side of smux + session, err := smux.Client(conn, nil) + if err != nil { + panic(err) + } + + // Open a new stream + stream, err := session.OpenStream() + if err != nil { + panic(err) + } + + // Stream implements io.ReadWriteCloser + stream.Write([]byte("ping")) +} + +func server() { + // Accept a TCP connection + conn, err := listener.Accept() + if err != nil { + panic(err) + } + + // Setup server side of smux + session, err := smux.Server(conn, nil) + if err != nil { + panic(err) + } + + // Accept a stream + stream, err := session.AcceptStream() + if err != nil { + panic(err) + } + + // Listen for a message + buf := make([]byte, 4) + stream.Read(buf) +} + +``` + +## Status + +Stable diff --git a/vendor/github.com/xtaci/smux/curve.jpg b/vendor/github.com/xtaci/smux/curve.jpg new file mode 100644 index 000000000..3fc4863f4 Binary files /dev/null and b/vendor/github.com/xtaci/smux/curve.jpg differ diff --git a/vendor/github.com/xtaci/smux/frame.go b/vendor/github.com/xtaci/smux/frame.go new file mode 100644 index 000000000..71d3d44a3 --- /dev/null +++ b/vendor/github.com/xtaci/smux/frame.go @@ -0,0 +1,60 @@ +package smux + +import ( + "encoding/binary" + "fmt" +) + +const ( + version = 1 +) + +const ( // cmds + cmdSYN byte = iota // stream open + cmdFIN // stream close, a.k.a EOF mark + cmdPSH // data push + cmdNOP // no operation +) + +const ( + sizeOfVer = 1 + sizeOfCmd = 1 + sizeOfLength = 2 + sizeOfSid = 4 + headerSize = sizeOfVer + sizeOfCmd + sizeOfSid + sizeOfLength +) + +// Frame defines a packet from or to be multiplexed into a single connection +type Frame struct { + ver byte + cmd byte + sid uint32 + data []byte +} + +func newFrame(cmd byte, sid uint32) Frame { + return Frame{ver: version, cmd: cmd, sid: sid} +} + +type rawHeader [headerSize]byte + +func (h rawHeader) Version() byte { + return h[0] +} + +func (h rawHeader) Cmd() byte { + return h[1] +} + +func (h rawHeader) Length() uint16 { + return binary.LittleEndian.Uint16(h[2:]) +} + +func (h rawHeader) StreamID() uint32 { + return binary.LittleEndian.Uint32(h[4:]) +} + +func (h rawHeader) String() string { + return fmt.Sprintf("Version:%d Cmd:%d StreamID:%d Length:%d", + h.Version(), h.Cmd(), h.StreamID(), h.Length()) +} diff --git a/vendor/github.com/xtaci/smux/mux.go b/vendor/github.com/xtaci/smux/mux.go new file mode 100644 index 000000000..3cc8f114f --- /dev/null +++ b/vendor/github.com/xtaci/smux/mux.go @@ -0,0 +1,80 @@ +package smux + +import ( + "fmt" + "io" + "time" + + "github.com/pkg/errors" +) + +// Config is used to tune the Smux session +type Config struct { + // KeepAliveInterval is how often to send a NOP command to the remote + KeepAliveInterval time.Duration + + // KeepAliveTimeout is how long the session + // will be closed if no data has arrived + KeepAliveTimeout time.Duration + + // MaxFrameSize is used to control the maximum + // frame size to sent to the remote + MaxFrameSize int + + // MaxReceiveBuffer is used to control the maximum + // number of data in the buffer pool + MaxReceiveBuffer int +} + +// DefaultConfig is used to return a default configuration +func DefaultConfig() *Config { + return &Config{ + KeepAliveInterval: 10 * time.Second, + KeepAliveTimeout: 30 * time.Second, + MaxFrameSize: 32768, + MaxReceiveBuffer: 4194304, + } +} + +// VerifyConfig is used to verify the sanity of configuration +func VerifyConfig(config *Config) error { + if config.KeepAliveInterval == 0 { + return errors.New("keep-alive interval must be positive") + } + if config.KeepAliveTimeout < config.KeepAliveInterval { + return fmt.Errorf("keep-alive timeout must be larger than keep-alive interval") + } + if config.MaxFrameSize <= 0 { + return errors.New("max frame size must be positive") + } + if config.MaxFrameSize > 65535 { + return errors.New("max frame size must not be larger than 65535") + } + if config.MaxReceiveBuffer <= 0 { + return errors.New("max receive buffer must be positive") + } + return nil +} + +// Server is used to initialize a new server-side connection. +func Server(conn io.ReadWriteCloser, config *Config) (*Session, error) { + if config == nil { + config = DefaultConfig() + } + if err := VerifyConfig(config); err != nil { + return nil, err + } + return newSession(config, conn, false), nil +} + +// Client is used to initialize a new client-side connection. +func Client(conn io.ReadWriteCloser, config *Config) (*Session, error) { + if config == nil { + config = DefaultConfig() + } + + if err := VerifyConfig(config); err != nil { + return nil, err + } + return newSession(config, conn, true), nil +} diff --git a/vendor/github.com/xtaci/smux/mux.jpg b/vendor/github.com/xtaci/smux/mux.jpg new file mode 100644 index 000000000..dde2e11aa Binary files /dev/null and b/vendor/github.com/xtaci/smux/mux.jpg differ diff --git a/vendor/github.com/xtaci/smux/session.go b/vendor/github.com/xtaci/smux/session.go new file mode 100644 index 000000000..c29634e21 --- /dev/null +++ b/vendor/github.com/xtaci/smux/session.go @@ -0,0 +1,350 @@ +package smux + +import ( + "encoding/binary" + "io" + "sync" + "sync/atomic" + "time" + + "github.com/pkg/errors" +) + +const ( + defaultAcceptBacklog = 1024 +) + +const ( + errBrokenPipe = "broken pipe" + errInvalidProtocol = "invalid protocol version" + errGoAway = "stream id overflows, should start a new connection" +) + +type writeRequest struct { + frame Frame + result chan writeResult +} + +type writeResult struct { + n int + err error +} + +// Session defines a multiplexed connection for streams +type Session struct { + conn io.ReadWriteCloser + + config *Config + nextStreamID uint32 // next stream identifier + nextStreamIDLock sync.Mutex + + bucket int32 // token bucket + bucketNotify chan struct{} // used for waiting for tokens + + streams map[uint32]*Stream // all streams in this session + streamLock sync.Mutex // locks streams + + die chan struct{} // flag session has died + dieLock sync.Mutex + chAccepts chan *Stream + + dataReady int32 // flag data has arrived + + goAway int32 // flag id exhausted + + deadline atomic.Value + + writes chan writeRequest +} + +func newSession(config *Config, conn io.ReadWriteCloser, client bool) *Session { + s := new(Session) + s.die = make(chan struct{}) + s.conn = conn + s.config = config + s.streams = make(map[uint32]*Stream) + s.chAccepts = make(chan *Stream, defaultAcceptBacklog) + s.bucket = int32(config.MaxReceiveBuffer) + s.bucketNotify = make(chan struct{}, 1) + s.writes = make(chan writeRequest) + + if client { + s.nextStreamID = 1 + } else { + s.nextStreamID = 0 + } + go s.recvLoop() + go s.sendLoop() + go s.keepalive() + return s +} + +// OpenStream is used to create a new stream +func (s *Session) OpenStream() (*Stream, error) { + if s.IsClosed() { + return nil, errors.New(errBrokenPipe) + } + + // generate stream id + s.nextStreamIDLock.Lock() + if s.goAway > 0 { + s.nextStreamIDLock.Unlock() + return nil, errors.New(errGoAway) + } + + s.nextStreamID += 2 + sid := s.nextStreamID + if sid == sid%2 { // stream-id overflows + s.goAway = 1 + s.nextStreamIDLock.Unlock() + return nil, errors.New(errGoAway) + } + s.nextStreamIDLock.Unlock() + + stream := newStream(sid, s.config.MaxFrameSize, s) + + if _, err := s.writeFrame(newFrame(cmdSYN, sid)); err != nil { + return nil, errors.Wrap(err, "writeFrame") + } + + s.streamLock.Lock() + s.streams[sid] = stream + s.streamLock.Unlock() + return stream, nil +} + +// AcceptStream is used to block until the next available stream +// is ready to be accepted. +func (s *Session) AcceptStream() (*Stream, error) { + var deadline <-chan time.Time + if d, ok := s.deadline.Load().(time.Time); ok && !d.IsZero() { + timer := time.NewTimer(time.Until(d)) + defer timer.Stop() + deadline = timer.C + } + select { + case stream := <-s.chAccepts: + return stream, nil + case <-deadline: + return nil, errTimeout + case <-s.die: + return nil, errors.New(errBrokenPipe) + } +} + +// Close is used to close the session and all streams. +func (s *Session) Close() (err error) { + s.dieLock.Lock() + + select { + case <-s.die: + s.dieLock.Unlock() + return errors.New(errBrokenPipe) + default: + close(s.die) + s.dieLock.Unlock() + s.streamLock.Lock() + for k := range s.streams { + s.streams[k].sessionClose() + } + s.streamLock.Unlock() + s.notifyBucket() + return s.conn.Close() + } +} + +// notifyBucket notifies recvLoop that bucket is available +func (s *Session) notifyBucket() { + select { + case s.bucketNotify <- struct{}{}: + default: + } +} + +// IsClosed does a safe check to see if we have shutdown +func (s *Session) IsClosed() bool { + select { + case <-s.die: + return true + default: + return false + } +} + +// NumStreams returns the number of currently open streams +func (s *Session) NumStreams() int { + if s.IsClosed() { + return 0 + } + s.streamLock.Lock() + defer s.streamLock.Unlock() + return len(s.streams) +} + +// SetDeadline sets a deadline used by Accept* calls. +// A zero time value disables the deadline. +func (s *Session) SetDeadline(t time.Time) error { + s.deadline.Store(t) + return nil +} + +// notify the session that a stream has closed +func (s *Session) streamClosed(sid uint32) { + s.streamLock.Lock() + if n := s.streams[sid].recycleTokens(); n > 0 { // return remaining tokens to the bucket + if atomic.AddInt32(&s.bucket, int32(n)) > 0 { + s.notifyBucket() + } + } + delete(s.streams, sid) + s.streamLock.Unlock() +} + +// returnTokens is called by stream to return token after read +func (s *Session) returnTokens(n int) { + if atomic.AddInt32(&s.bucket, int32(n)) > 0 { + s.notifyBucket() + } +} + +// session read a frame from underlying connection +// it's data is pointed to the input buffer +func (s *Session) readFrame(buffer []byte) (f Frame, err error) { + var hdr rawHeader + if _, err := io.ReadFull(s.conn, hdr[:]); err != nil { + return f, errors.Wrap(err, "readFrame") + } + + if hdr.Version() != version { + return f, errors.New(errInvalidProtocol) + } + + f.ver = hdr.Version() + f.cmd = hdr.Cmd() + f.sid = hdr.StreamID() + if length := hdr.Length(); length > 0 { + f.data = buffer[:length] + if _, err := io.ReadFull(s.conn, f.data); err != nil { + return f, errors.Wrap(err, "readFrame") + } + } + return f, nil +} + +// recvLoop keeps on reading from underlying connection if tokens are available +func (s *Session) recvLoop() { + buffer := make([]byte, 1<<16) + for { + for atomic.LoadInt32(&s.bucket) <= 0 && !s.IsClosed() { + <-s.bucketNotify + } + + if f, err := s.readFrame(buffer); err == nil { + atomic.StoreInt32(&s.dataReady, 1) + + switch f.cmd { + case cmdNOP: + case cmdSYN: + s.streamLock.Lock() + if _, ok := s.streams[f.sid]; !ok { + stream := newStream(f.sid, s.config.MaxFrameSize, s) + s.streams[f.sid] = stream + select { + case s.chAccepts <- stream: + case <-s.die: + } + } + s.streamLock.Unlock() + case cmdFIN: + s.streamLock.Lock() + if stream, ok := s.streams[f.sid]; ok { + stream.markRST() + stream.notifyReadEvent() + } + s.streamLock.Unlock() + case cmdPSH: + s.streamLock.Lock() + if stream, ok := s.streams[f.sid]; ok { + atomic.AddInt32(&s.bucket, -int32(len(f.data))) + stream.pushBytes(f.data) + stream.notifyReadEvent() + } + s.streamLock.Unlock() + default: + s.Close() + return + } + } else { + s.Close() + return + } + } +} + +func (s *Session) keepalive() { + tickerPing := time.NewTicker(s.config.KeepAliveInterval) + tickerTimeout := time.NewTicker(s.config.KeepAliveTimeout) + defer tickerPing.Stop() + defer tickerTimeout.Stop() + for { + select { + case <-tickerPing.C: + s.writeFrame(newFrame(cmdNOP, 0)) + s.notifyBucket() // force a signal to the recvLoop + case <-tickerTimeout.C: + if !atomic.CompareAndSwapInt32(&s.dataReady, 1, 0) { + s.Close() + return + } + case <-s.die: + return + } + } +} + +func (s *Session) sendLoop() { + buf := make([]byte, (1<<16)+headerSize) + for { + select { + case <-s.die: + return + case request := <-s.writes: + buf[0] = request.frame.ver + buf[1] = request.frame.cmd + binary.LittleEndian.PutUint16(buf[2:], uint16(len(request.frame.data))) + binary.LittleEndian.PutUint32(buf[4:], request.frame.sid) + copy(buf[headerSize:], request.frame.data) + n, err := s.conn.Write(buf[:headerSize+len(request.frame.data)]) + + n -= headerSize + if n < 0 { + n = 0 + } + + result := writeResult{ + n: n, + err: err, + } + + request.result <- result + close(request.result) + } + } +} + +// writeFrame writes the frame to the underlying connection +// and returns the number of bytes written if successful +func (s *Session) writeFrame(f Frame) (n int, err error) { + req := writeRequest{ + frame: f, + result: make(chan writeResult, 1), + } + select { + case <-s.die: + return 0, errors.New(errBrokenPipe) + case s.writes <- req: + } + + result := <-req.result + return result.n, result.err +} diff --git a/vendor/github.com/xtaci/smux/smux.png b/vendor/github.com/xtaci/smux/smux.png new file mode 100644 index 000000000..26aba3b72 Binary files /dev/null and b/vendor/github.com/xtaci/smux/smux.png differ diff --git a/vendor/github.com/xtaci/smux/stream.go b/vendor/github.com/xtaci/smux/stream.go new file mode 100644 index 000000000..2ce00d2d9 --- /dev/null +++ b/vendor/github.com/xtaci/smux/stream.go @@ -0,0 +1,262 @@ +package smux + +import ( + "bytes" + "io" + "net" + "sync" + "sync/atomic" + "time" + + "github.com/pkg/errors" +) + +// Stream implements net.Conn +type Stream struct { + id uint32 + rstflag int32 + sess *Session + buffer bytes.Buffer + bufferLock sync.Mutex + frameSize int + chReadEvent chan struct{} // notify a read event + die chan struct{} // flag the stream has closed + dieLock sync.Mutex + readDeadline atomic.Value + writeDeadline atomic.Value +} + +// newStream initiates a Stream struct +func newStream(id uint32, frameSize int, sess *Session) *Stream { + s := new(Stream) + s.id = id + s.chReadEvent = make(chan struct{}, 1) + s.frameSize = frameSize + s.sess = sess + s.die = make(chan struct{}) + return s +} + +// ID returns the unique stream ID. +func (s *Stream) ID() uint32 { + return s.id +} + +// Read implements net.Conn +func (s *Stream) Read(b []byte) (n int, err error) { + if len(b) == 0 { + select { + case <-s.die: + return 0, errors.New(errBrokenPipe) + default: + return 0, nil + } + } + + var deadline <-chan time.Time + if d, ok := s.readDeadline.Load().(time.Time); ok && !d.IsZero() { + timer := time.NewTimer(time.Until(d)) + defer timer.Stop() + deadline = timer.C + } + +READ: + s.bufferLock.Lock() + n, _ = s.buffer.Read(b) + s.bufferLock.Unlock() + + if n > 0 { + s.sess.returnTokens(n) + return n, nil + } else if atomic.LoadInt32(&s.rstflag) == 1 { + _ = s.Close() + return 0, io.EOF + } + + select { + case <-s.chReadEvent: + goto READ + case <-deadline: + return n, errTimeout + case <-s.die: + return 0, errors.New(errBrokenPipe) + } +} + +// Write implements net.Conn +func (s *Stream) Write(b []byte) (n int, err error) { + var deadline <-chan time.Time + if d, ok := s.writeDeadline.Load().(time.Time); ok && !d.IsZero() { + timer := time.NewTimer(time.Until(d)) + defer timer.Stop() + deadline = timer.C + } + + select { + case <-s.die: + return 0, errors.New(errBrokenPipe) + default: + } + + frames := s.split(b, cmdPSH, s.id) + sent := 0 + for k := range frames { + req := writeRequest{ + frame: frames[k], + result: make(chan writeResult, 1), + } + + select { + case s.sess.writes <- req: + case <-s.die: + return sent, errors.New(errBrokenPipe) + case <-deadline: + return sent, errTimeout + } + + select { + case result := <-req.result: + sent += result.n + if result.err != nil { + return sent, result.err + } + case <-s.die: + return sent, errors.New(errBrokenPipe) + case <-deadline: + return sent, errTimeout + } + } + return sent, nil +} + +// Close implements net.Conn +func (s *Stream) Close() error { + s.dieLock.Lock() + + select { + case <-s.die: + s.dieLock.Unlock() + return errors.New(errBrokenPipe) + default: + close(s.die) + s.dieLock.Unlock() + s.sess.streamClosed(s.id) + _, err := s.sess.writeFrame(newFrame(cmdFIN, s.id)) + return err + } +} + +// SetReadDeadline sets the read deadline as defined by +// net.Conn.SetReadDeadline. +// A zero time value disables the deadline. +func (s *Stream) SetReadDeadline(t time.Time) error { + s.readDeadline.Store(t) + return nil +} + +// SetWriteDeadline sets the write deadline as defined by +// net.Conn.SetWriteDeadline. +// A zero time value disables the deadline. +func (s *Stream) SetWriteDeadline(t time.Time) error { + s.writeDeadline.Store(t) + return nil +} + +// SetDeadline sets both read and write deadlines as defined by +// net.Conn.SetDeadline. +// A zero time value disables the deadlines. +func (s *Stream) SetDeadline(t time.Time) error { + if err := s.SetReadDeadline(t); err != nil { + return err + } + if err := s.SetWriteDeadline(t); err != nil { + return err + } + return nil +} + +// session closes the stream +func (s *Stream) sessionClose() { + s.dieLock.Lock() + defer s.dieLock.Unlock() + + select { + case <-s.die: + default: + close(s.die) + } +} + +// LocalAddr satisfies net.Conn interface +func (s *Stream) LocalAddr() net.Addr { + if ts, ok := s.sess.conn.(interface { + LocalAddr() net.Addr + }); ok { + return ts.LocalAddr() + } + return nil +} + +// RemoteAddr satisfies net.Conn interface +func (s *Stream) RemoteAddr() net.Addr { + if ts, ok := s.sess.conn.(interface { + RemoteAddr() net.Addr + }); ok { + return ts.RemoteAddr() + } + return nil +} + +// pushBytes a slice into buffer +func (s *Stream) pushBytes(p []byte) { + s.bufferLock.Lock() + s.buffer.Write(p) + s.bufferLock.Unlock() +} + +// recycleTokens transform remaining bytes to tokens(will truncate buffer) +func (s *Stream) recycleTokens() (n int) { + s.bufferLock.Lock() + n = s.buffer.Len() + s.buffer.Reset() + s.bufferLock.Unlock() + return +} + +// split large byte buffer into smaller frames, reference only +func (s *Stream) split(bts []byte, cmd byte, sid uint32) []Frame { + frames := make([]Frame, 0, len(bts)/s.frameSize+1) + for len(bts) > s.frameSize { + frame := newFrame(cmd, sid) + frame.data = bts[:s.frameSize] + bts = bts[s.frameSize:] + frames = append(frames, frame) + } + if len(bts) > 0 { + frame := newFrame(cmd, sid) + frame.data = bts + frames = append(frames, frame) + } + return frames +} + +// notify read event +func (s *Stream) notifyReadEvent() { + select { + case s.chReadEvent <- struct{}{}: + default: + } +} + +// mark this stream has been reset +func (s *Stream) markRST() { + atomic.StoreInt32(&s.rstflag, 1) +} + +var errTimeout error = &timeoutError{} + +type timeoutError struct{} + +func (e *timeoutError) Error() string { return "i/o timeout" } +func (e *timeoutError) Timeout() bool { return true } +func (e *timeoutError) Temporary() bool { return true } diff --git a/vendor/golang.org/x/sys/unix/asm_aix_ppc64.s b/vendor/golang.org/x/sys/unix/asm_aix_ppc64.s new file mode 100644 index 000000000..06f84b855 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/asm_aix_ppc64.s @@ -0,0 +1,17 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !gccgo + +#include "textflag.h" + +// +// System calls for ppc64, AIX are implemented in runtime/syscall_aix.go +// + +TEXT ·syscall6(SB),NOSPLIT,$0-88 + JMP syscall·syscall6(SB) + +TEXT ·rawSyscall6(SB),NOSPLIT,$0-88 + JMP syscall·rawSyscall6(SB) diff --git a/vendor/golang.org/x/sys/unix/mkall.sh b/vendor/golang.org/x/sys/unix/mkall.sh index edb176f16..9b76ad669 100755 --- a/vendor/golang.org/x/sys/unix/mkall.sh +++ b/vendor/golang.org/x/sys/unix/mkall.sh @@ -61,12 +61,12 @@ _* | *_ | _) ;; aix_ppc) mkerrors="$mkerrors -maix32" - mksyscall="perl mksyscall_aix.pl -aix" + mksyscall="./mksyscall_aix_ppc.pl -aix" mktypes="GOARCH=$GOARCH go tool cgo -godefs" ;; aix_ppc64) mkerrors="$mkerrors -maix64" - mksyscall="perl mksyscall_aix.pl -aix" + mksyscall="./mksyscall_aix_ppc64.pl -aix" mktypes="GOARCH=$GOARCH go tool cgo -godefs" ;; darwin_386) @@ -187,8 +187,14 @@ esac syscall_goos="syscall_bsd.go $syscall_goos" ;; esac - if [ -n "$mksyscall" ]; then echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go"; fi - ;; + if [ -n "$mksyscall" ]; then + if [ "$GOOSARCH" == "aix_ppc64" ]; then + # aix/ppc64 script generates files instead of writing to stdin. + echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in && gofmt -w zsyscall_$GOOSARCH.go && gofmt -w zsyscall_"$GOOSARCH"_gccgo.go && gofmt -w zsyscall_"$GOOSARCH"_gc.go " ; + else + echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go"; + fi + fi esac if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi if [ -n "$mksysnum" ]; then echo "$mksysnum |gofmt >zsysnum_$GOOSARCH.go"; fi diff --git a/vendor/golang.org/x/sys/unix/mkerrors.sh b/vendor/golang.org/x/sys/unix/mkerrors.sh index 7943853ff..73e179a89 100755 --- a/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -197,6 +197,7 @@ struct ltchars { #include #include #include +#include #include #include #include @@ -449,6 +450,7 @@ ccflags="$@" $2 ~ /^KEXEC_/ || $2 ~ /^LINUX_REBOOT_CMD_/ || $2 ~ /^LINUX_REBOOT_MAGIC[12]$/ || + $2 ~ /^MODULE_INIT_/ || $2 !~ "NLA_TYPE_MASK" && $2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ || $2 ~ /^SIOC/ || diff --git a/vendor/golang.org/x/sys/unix/mksyscall_aix.pl b/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.pl old mode 100644 new mode 100755 similarity index 98% rename from vendor/golang.org/x/sys/unix/mksyscall_aix.pl rename to vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.pl index c9b3954ba..c44de8d31 --- a/vendor/golang.org/x/sys/unix/mksyscall_aix.pl +++ b/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.pl @@ -19,7 +19,7 @@ use strict; -my $cmdline = "mksyscall_aix.pl " . join(' ', @ARGV); +my $cmdline = "mksyscall_aix_ppc.pl " . join(' ', @ARGV); my $errors = 0; my $_32bit = ""; my $tags = ""; # build tags @@ -72,7 +72,7 @@ ($) my $package = ""; my $text = ""; -my $c_extern = "/*\n#include \n"; +my $c_extern = "/*\n#include \n#include \n"; my @vars = (); while(<>) { chomp; @@ -369,7 +369,6 @@ package $package import "C" import ( "unsafe" - "syscall" ) diff --git a/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.pl b/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.pl new file mode 100755 index 000000000..53df26bb9 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.pl @@ -0,0 +1,579 @@ +#!/usr/bin/env perl +# Copyright 2018 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +# This program reads a file containing function prototypes +# (like syscall_aix.go) and generates system call bodies. +# The prototypes are marked by lines beginning with "//sys" +# and read like func declarations if //sys is replaced by func, but: +# * The parameter lists must give a name for each argument. +# This includes return parameters. +# * The parameter lists must give a type for each argument: +# the (x, y, z int) shorthand is not allowed. +# * If the return parameter is an error number, it must be named err. +# * If go func name needs to be different than its libc name, +# * or the function is not in libc, name could be specified +# * at the end, after "=" sign, like +# //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt + +# This program will generate three files and handle both gc and gccgo implementation: +# - zsyscall_aix_ppc64.go: the common part of each implementation (error handler, pointer creation) +# - zsyscall_aix_ppc64_gc.go: gc part with //go_cgo_import_dynamic and a call to syscall6 +# - zsyscall_aix_ppc64_gccgo.go: gccgo part with C function and conversion to C type. + +# The generated code looks like this +# +# zsyscall_aix_ppc64.go +# func asyscall(...) (n int, err error) { +# // Pointer Creation +# r1, e1 := callasyscall(...) +# // Type Conversion +# // Error Handler +# return +# } +# +# zsyscall_aix_ppc64_gc.go +# //go:cgo_import_dynamic libc_asyscall asyscall "libc.a/shr_64.o" +# //go:linkname libc_asyscall libc_asyscall +# var asyscall syscallFunc +# +# func callasyscall(...) (r1 uintptr, e1 Errno) { +# r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_asyscall)), "nb_args", ... ) +# return +# } +# +# zsyscall_aix_ppc64_ggcgo.go +# /* +# int asyscall(...) +# +# */ +# import "C" +# +# func callasyscall(...) (r1 uintptr, e1 Errno) { +# r1 = uintptr(C.asyscall(...)) +# e1 = syscall.GetErrno() +# return +# } + + + +use strict; + +my $cmdline = "mksyscall_aix_ppc64.pl " . join(' ', @ARGV); +my $errors = 0; +my $_32bit = ""; +my $tags = ""; # build tags +my $aix = 0; +my $solaris = 0; + +binmode STDOUT; + +if($ARGV[0] eq "-b32") { + $_32bit = "big-endian"; + shift; +} elsif($ARGV[0] eq "-l32") { + $_32bit = "little-endian"; + shift; +} +if($ARGV[0] eq "-aix") { + $aix = 1; + shift; +} +if($ARGV[0] eq "-tags") { + shift; + $tags = $ARGV[0]; + shift; +} + +if($ARGV[0] =~ /^-/) { + print STDERR "usage: mksyscall_aix.pl [-b32 | -l32] [-tags x,y] [file ...]\n"; + exit 1; +} + +sub parseparamlist($) { + my ($list) = @_; + $list =~ s/^\s*//; + $list =~ s/\s*$//; + if($list eq "") { + return (); + } + return split(/\s*,\s*/, $list); +} + +sub parseparam($) { + my ($p) = @_; + if($p !~ /^(\S*) (\S*)$/) { + print STDERR "$ARGV:$.: malformed parameter: $p\n"; + $errors = 1; + return ("xx", "int"); + } + return ($1, $2); +} + +my $package = ""; +# GCCGO +my $textgccgo = ""; +my $c_extern = "/*\n#include \n"; +# GC +my $textgc = ""; +my $dynimports = ""; +my $linknames = ""; +my @vars = (); +# COMMUN +my $textcommon = ""; + +while(<>) { + chomp; + s/\s+/ /g; + s/^\s+//; + s/\s+$//; + $package = $1 if !$package && /^package (\S+)$/; + my $nonblock = /^\/\/sysnb /; + next if !/^\/\/sys / && !$nonblock; + + # Line must be of the form + # func Open(path string, mode int, perm int) (fd int, err error) + # Split into name, in params, out params. + if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$/) { + print STDERR "$ARGV:$.: malformed //sys declaration\n"; + $errors = 1; + next; + } + my ($nb, $func, $in, $out, $modname, $sysname) = ($1, $2, $3, $4, $5, $6); + + # Split argument lists on comma. + my @in = parseparamlist($in); + my @out = parseparamlist($out); + + $in = join(', ', @in); + $out = join(', ', @out); + + if($sysname eq "") { + $sysname = "$func"; + } + + my $onlyCommon = 0; + if ($func eq "readlen" || $func eq "writelen" || $func eq "FcntlInt" || $func eq "FcntlFlock") { + # This function call another syscall which is already implemented. + # Therefore, the gc and gccgo part must not be generated. + $onlyCommon = 1 + } + + # Try in vain to keep people from editing this file. + # The theory is that they jump into the middle of the file + # without reading the header. + + $textcommon .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"; + if (!$onlyCommon) { + $textgccgo .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"; + $textgc .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"; + } + + + # Check if value return, err return available + my $errvar = ""; + my $retvar = ""; + my $rettype = ""; + foreach my $p (@out) { + my ($name, $type) = parseparam($p); + if($type eq "error") { + $errvar = $name; + } else { + $retvar = $name; + $rettype = $type; + } + } + + + $sysname =~ s/([a-z])([A-Z])/${1}_$2/g; + $sysname =~ y/A-Z/a-z/; # All libc functions are lowercase. + + # GCCGO Prototype return type + my $C_rettype = ""; + if($rettype eq "unsafe.Pointer") { + $C_rettype = "uintptr_t"; + } elsif($rettype eq "uintptr") { + $C_rettype = "uintptr_t"; + } elsif($rettype =~ /^_/) { + $C_rettype = "uintptr_t"; + } elsif($rettype eq "int") { + $C_rettype = "int"; + } elsif($rettype eq "int32") { + $C_rettype = "int"; + } elsif($rettype eq "int64") { + $C_rettype = "long long"; + } elsif($rettype eq "uint32") { + $C_rettype = "unsigned int"; + } elsif($rettype eq "uint64") { + $C_rettype = "unsigned long long"; + } else { + $C_rettype = "int"; + } + if($sysname eq "exit") { + $C_rettype = "void"; + } + + # GCCGO Prototype arguments type + my @c_in = (); + foreach my $i (0 .. $#in) { + my ($name, $type) = parseparam($in[$i]); + if($type =~ /^\*/) { + push @c_in, "uintptr_t"; + } elsif($type eq "string") { + push @c_in, "uintptr_t"; + } elsif($type =~ /^\[\](.*)/) { + push @c_in, "uintptr_t", "size_t"; + } elsif($type eq "unsafe.Pointer") { + push @c_in, "uintptr_t"; + } elsif($type eq "uintptr") { + push @c_in, "uintptr_t"; + } elsif($type =~ /^_/) { + push @c_in, "uintptr_t"; + } elsif($type eq "int") { + if (($i == 0 || $i == 2) && $func eq "fcntl"){ + # These fcntl arguments needs to be uintptr to be able to call FcntlInt and FcntlFlock + push @c_in, "uintptr_t"; + } else { + push @c_in, "int"; + } + } elsif($type eq "int32") { + push @c_in, "int"; + } elsif($type eq "int64") { + push @c_in, "long long"; + } elsif($type eq "uint32") { + push @c_in, "unsigned int"; + } elsif($type eq "uint64") { + push @c_in, "unsigned long long"; + } else { + push @c_in, "int"; + } + } + + if (!$onlyCommon){ + # GCCGO Prototype Generation + # Imports of system calls from libc + $c_extern .= "$C_rettype $sysname"; + my $c_in = join(', ', @c_in); + $c_extern .= "($c_in);\n"; + } + + # GC Library name + if($modname eq "") { + $modname = "libc.a/shr_64.o"; + } else { + print STDERR "$func: only syscall using libc are available\n"; + $errors = 1; + next; + } + my $sysvarname = "libc_${sysname}"; + + if (!$onlyCommon){ + # GC Runtime import of function to allow cross-platform builds. + $dynimports .= "//go:cgo_import_dynamic ${sysvarname} ${sysname} \"$modname\"\n"; + # GC Link symbol to proc address variable. + $linknames .= "//go:linkname ${sysvarname} ${sysvarname}\n"; + # GC Library proc address variable. + push @vars, $sysvarname; + } + + my $strconvfunc ="BytePtrFromString"; + my $strconvtype = "*byte"; + + # Go function header. + if($out ne "") { + $out = " ($out)"; + } + if($textcommon ne "") { + $textcommon .= "\n" + } + + $textcommon .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out ; + + # Prepare arguments to call. + my @argscommun = (); # Arguments in the commun part + my @argscall = (); # Arguments for call prototype + my @argsgc = (); # Arguments for gc call (with syscall6) + my @argsgccgo = (); # Arguments for gccgo call (with C.name_of_syscall) + my $n = 0; + my $arg_n = 0; + foreach my $p (@in) { + my ($name, $type) = parseparam($p); + if($type =~ /^\*/) { + push @argscommun, "uintptr(unsafe.Pointer($name))"; + push @argscall, "$name uintptr"; + push @argsgc, "$name"; + push @argsgccgo, "C.uintptr_t($name)"; + } elsif($type eq "string" && $errvar ne "") { + $textcommon .= "\tvar _p$n $strconvtype\n"; + $textcommon .= "\t_p$n, $errvar = $strconvfunc($name)\n"; + $textcommon .= "\tif $errvar != nil {\n\t\treturn\n\t}\n"; + + push @argscommun, "uintptr(unsafe.Pointer(_p$n))"; + push @argscall, "_p$n uintptr "; + push @argsgc, "_p$n"; + push @argsgccgo, "C.uintptr_t(_p$n)"; + $n++; + } elsif($type eq "string") { + print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n"; + $textcommon .= "\tvar _p$n $strconvtype\n"; + $textcommon .= "\t_p$n, $errvar = $strconvfunc($name)\n"; + $textcommon .= "\tif $errvar != nil {\n\t\treturn\n\t}\n"; + + push @argscommun, "uintptr(unsafe.Pointer(_p$n))"; + push @argscall, "_p$n uintptr"; + push @argsgc, "_p$n"; + push @argsgccgo, "C.uintptr_t(_p$n)"; + $n++; + } elsif($type =~ /^\[\](.*)/) { + # Convert slice into pointer, length. + # Have to be careful not to take address of &a[0] if len == 0: + # pass nil in that case. + $textcommon .= "\tvar _p$n *$1\n"; + $textcommon .= "\tif len($name) > 0 {\n\t\t_p$n = \&$name\[0]\n\t}\n"; + push @argscommun, "uintptr(unsafe.Pointer(_p$n))", "len($name)"; + push @argscall, "_p$n uintptr", "_lenp$n int"; + push @argsgc, "_p$n", "uintptr(_lenp$n)"; + push @argsgccgo, "C.uintptr_t(_p$n)", "C.size_t(_lenp$n)"; + $n++; + } elsif($type eq "int64" && $_32bit ne "") { + print STDERR "$ARGV:$.: $func uses int64 with 32 bits mode. Case not yet implemented\n"; + # if($_32bit eq "big-endian") { + # push @args, "uintptr($name >> 32)", "uintptr($name)"; + # } else { + # push @args, "uintptr($name)", "uintptr($name >> 32)"; + # } + # $n++; + } elsif($type eq "bool") { + print STDERR "$ARGV:$.: $func uses bool. Case not yet implemented\n"; + # $text .= "\tvar _p$n uint32\n"; + # $text .= "\tif $name {\n\t\t_p$n = 1\n\t} else {\n\t\t_p$n = 0\n\t}\n"; + # push @args, "_p$n"; + # $n++; + } elsif($type =~ /^_/ ||$type eq "unsafe.Pointer") { + push @argscommun, "uintptr($name)"; + push @argscall, "$name uintptr"; + push @argsgc, "$name"; + push @argsgccgo, "C.uintptr_t($name)"; + } elsif($type eq "int") { + if (($arg_n == 0 || $arg_n == 2) && ($func eq "fcntl" || $func eq "FcntlInt" || $func eq "FcntlFlock")) { + # These fcntl arguments need to be uintptr to be able to call FcntlInt and FcntlFlock + push @argscommun, "uintptr($name)"; + push @argscall, "$name uintptr"; + push @argsgc, "$name"; + push @argsgccgo, "C.uintptr_t($name)"; + } else { + push @argscommun, "$name"; + push @argscall, "$name int"; + push @argsgc, "uintptr($name)"; + push @argsgccgo, "C.int($name)"; + } + } elsif($type eq "int32") { + push @argscommun, "$name"; + push @argscall, "$name int32"; + push @argsgc, "uintptr($name)"; + push @argsgccgo, "C.int($name)"; + } elsif($type eq "int64") { + push @argscommun, "$name"; + push @argscall, "$name int64"; + push @argsgc, "uintptr($name)"; + push @argsgccgo, "C.longlong($name)"; + } elsif($type eq "uint32") { + push @argscommun, "$name"; + push @argscall, "$name uint32"; + push @argsgc, "uintptr($name)"; + push @argsgccgo, "C.uint($name)"; + } elsif($type eq "uint64") { + push @argscommun, "$name"; + push @argscall, "$name uint64"; + push @argsgc, "uintptr($name)"; + push @argsgccgo, "C.ulonglong($name)"; + } elsif($type eq "uintptr") { + push @argscommun, "$name"; + push @argscall, "$name uintptr"; + push @argsgc, "$name"; + push @argsgccgo, "C.uintptr_t($name)"; + } else { + push @argscommun, "int($name)"; + push @argscall, "$name int"; + push @argsgc, "uintptr($name)"; + push @argsgccgo, "C.int($name)"; + } + $arg_n++; + } + my $nargs = @argsgc; + + # COMMUN function generation + my $argscommun = join(', ', @argscommun); + my $callcommun = "call$sysname($argscommun)"; + my @ret = ("_", "_"); + my $body = ""; + my $do_errno = 0; + for(my $i=0; $i<@out; $i++) { + my $p = $out[$i]; + my ($name, $type) = parseparam($p); + my $reg = ""; + if($name eq "err") { + $reg = "e1"; + $ret[1] = $reg; + $do_errno = 1; + } else { + $reg = "r0"; + $ret[0] = $reg; + } + if($type eq "bool") { + $reg = "$reg != 0"; + } + if($reg ne "e1") { + $body .= "\t$name = $type($reg)\n"; + } + } + if ($ret[0] eq "_" && $ret[1] eq "_") { + $textcommon .= "\t$callcommun\n"; + } else { + $textcommon .= "\t$ret[0], $ret[1] := $callcommun\n"; + } + $textcommon .= $body; + + if ($do_errno) { + $textcommon .= "\tif e1 != 0 {\n"; + $textcommon .= "\t\terr = errnoErr(e1)\n"; + $textcommon .= "\t}\n"; + } + $textcommon .= "\treturn\n"; + $textcommon .= "}\n"; + + if ($onlyCommon){ + next + } + # CALL Prototype + my $callProto = sprintf "func call%s(%s) (r1 uintptr, e1 Errno) {\n", $sysname, join(', ', @argscall); + + # GC function generation + my $asm = "syscall6"; + if ($nonblock) { + $asm = "rawSyscall6"; + } + + if(@argsgc <= 6) { + while(@argsgc < 6) { + push @argsgc, "0"; + } + } else { + print STDERR "$ARGV:$.: too many arguments to system call\n"; + } + my $argsgc = join(', ', @argsgc); + my $callgc = "$asm(uintptr(unsafe.Pointer(&$sysvarname)), $nargs, $argsgc)"; + + $textgc .= $callProto; + $textgc .= "\tr1, _, e1 = $callgc\n"; + $textgc .= "\treturn\n}\n"; + + # GCCGO function generation + my $argsgccgo = join(', ', @argsgccgo); + my $callgccgo = "C.$sysname($argsgccgo)"; + $textgccgo .= $callProto; + $textgccgo .= "\tr1 = uintptr($callgccgo)\n"; + $textgccgo .= "\te1 = syscall.GetErrno()\n"; + $textgccgo .= "\treturn\n}\n"; +} + +if($errors) { + exit 1; +} + +# Print zsyscall_aix_ppc64.go +open(my $fcommun, '>', 'zsyscall_aix_ppc64.go'); +my $tofcommun = <', 'zsyscall_aix_ppc64_gc.go'); +my $tofgc = <', 'zsyscall_aix_ppc64_gccgo.go'); +my $tofgccgo = <>8) & 0xFF + return Signal(w>>8) & 0xFF } func (w WaitStatus) Exited() bool { return w&0xFF == 0 } @@ -321,11 +321,11 @@ func (w WaitStatus) ExitStatus() int { } func (w WaitStatus) Signaled() bool { return w&0x40 == 0 && w&0xFF != 0 } -func (w WaitStatus) Signal() syscall.Signal { +func (w WaitStatus) Signal() Signal { if !w.Signaled() { return -1 } - return syscall.Signal(w>>16) & 0xFF + return Signal(w>>16) & 0xFF } func (w WaitStatus) Continued() bool { return w&0x01000000 != 0 } @@ -383,6 +383,8 @@ func IoctlGetTermios(fd int, req uint) (*Termios, error) { // FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command. //sys FcntlFlock(fd uintptr, cmd int, lk *Flock_t) (err error) = fcntl +//sys fcntl(fd int, cmd int, arg int) (val int, err error) + func Flock(fd int, how int) (err error) { return syscall.Flock(fd, how) } @@ -396,15 +398,12 @@ func Flock(fd int, how int) (err error) { //sys Chroot(path string) (err error) //sys Close(fd int) (err error) //sys Dup(oldfd int) (fd int, err error) -//sys Dup3(oldfd int, newfd int, flags int) (err error) //sys Exit(code int) //sys Faccessat(dirfd int, path string, mode uint32, flags int) (err error) -//sys Fallocate(fd int, mode uint32, off int64, len int64) (err error) //sys Fchdir(fd int) (err error) //sys Fchmod(fd int, mode uint32) (err error) //sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) //sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) -//sys fcntl(fd int, cmd int, arg int) (val int, err error) //sys Fdatasync(fd int) (err error) //sys Fsync(fd int) (err error) // readdir_r @@ -417,7 +416,7 @@ func Flock(fd int, how int) (err error) { //sys Getpriority(which int, who int) (prio int, err error) //sysnb Getrusage(who int, rusage *Rusage) (err error) //sysnb Getsid(pid int) (sid int, err error) -//sysnb Kill(pid int, sig syscall.Signal) (err error) +//sysnb Kill(pid int, sig Signal) (err error) //sys Klogctl(typ int, buf []byte) (n int, err error) = syslog //sys Mkdir(dirfd int, path string, mode uint32) (err error) //sys Mkdirat(dirfd int, path string, mode uint32) (err error) @@ -429,7 +428,6 @@ func Flock(fd int, how int) (err error) { //sys Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) //sys read(fd int, p []byte) (n int, err error) //sys Readlink(path string, buf []byte) (n int, err error) -//sys Removexattr(path string, attr string) (err error) //sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) //sys Setdomainname(p []byte) (err error) //sys Sethostname(p []byte) (err error) @@ -443,7 +441,6 @@ func Flock(fd int, how int) (err error) { //sys Setpriority(which int, who int, prio int) (err error) //sys Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error) //sys Sync() -//sys Tee(rfd int, wfd int, len int, flags int) (n int64, err error) //sysnb Times(tms *Tms) (ticks uintptr, err error) //sysnb Umask(mask int) (oldmask int) //sysnb Uname(buf *Utsname) (err error) @@ -451,7 +448,6 @@ func Flock(fd int, how int) (err error) { // //sys Unmount(target string, flags int) (err error) = umount //sys Unlink(path string) (err error) //sys Unlinkat(dirfd int, path string, flags int) (err error) -//sys Unshare(flags int) (err error) //sys Ustat(dev int, ubuf *Ustat_t) (err error) //sys write(fd int, p []byte) (n int, err error) //sys readlen(fd int, p *byte, np int) (n int, err error) = read @@ -537,19 +533,6 @@ func Pipe(p []int) (err error) { return } -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - //sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) func Poll(fds []PollFd, timeout int) (n int, err error) { diff --git a/vendor/golang.org/x/sys/unix/syscall_dragonfly.go b/vendor/golang.org/x/sys/unix/syscall_dragonfly.go index 79d125b30..6401e3a29 100644 --- a/vendor/golang.org/x/sys/unix/syscall_dragonfly.go +++ b/vendor/golang.org/x/sys/unix/syscall_dragonfly.go @@ -287,6 +287,7 @@ func Uname(uname *Utsname) error { //sys Mknod(path string, mode uint32, dev int) (err error) //sys Nanosleep(time *Timespec, leftover *Timespec) (err error) //sys Open(path string, mode int, perm uint32) (fd int, err error) +//sys Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) //sys Pathconf(path string, name int) (val int, err error) //sys read(fd int, p []byte) (n int, err error) //sys Readlink(path string, buf []byte) (n int, err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd.go b/vendor/golang.org/x/sys/unix/syscall_freebsd.go index 77a634c76..085a808cc 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd.go @@ -13,9 +13,34 @@ package unix import ( + "sync" "unsafe" ) +const ( + SYS_FSTAT_FREEBSD12 = 551 // { int fstat(int fd, _Out_ struct stat *sb); } + SYS_FSTATAT_FREEBSD12 = 552 // { int fstatat(int fd, _In_z_ char *path, \ + SYS_GETDIRENTRIES_FREEBSD12 = 554 // { ssize_t getdirentries(int fd, \ + SYS_STATFS_FREEBSD12 = 555 // { int statfs(_In_z_ char *path, \ + SYS_FSTATFS_FREEBSD12 = 556 // { int fstatfs(int fd, \ + SYS_GETFSSTAT_FREEBSD12 = 557 // { int getfsstat( \ + SYS_MKNODAT_FREEBSD12 = 559 // { int mknodat(int fd, _In_z_ char *path, \ +) + +// See https://www.freebsd.org/doc/en_US.ISO8859-1/books/porters-handbook/versions.html. +var ( + osreldateOnce sync.Once + osreldate uint32 +) + +// INO64_FIRST from /usr/src/lib/libc/sys/compat-ino64.h +const _ino64First = 1200031 + +func supportsABI(ver uint32) bool { + osreldateOnce.Do(func() { osreldate, _ = SysctlUint32("kern.osreldate") }) + return osreldate >= ver +} + // SockaddrDatalink implements the Sockaddr interface for AF_LINK type sockets. type SockaddrDatalink struct { Len uint8 @@ -121,17 +146,39 @@ func Getwd() (string, error) { } func Getfsstat(buf []Statfs_t, flags int) (n int, err error) { - var _p0 unsafe.Pointer - var bufsize uintptr + var ( + _p0 unsafe.Pointer + bufsize uintptr + oldBuf []statfs_freebsd11_t + needsConvert bool + ) + if len(buf) > 0 { - _p0 = unsafe.Pointer(&buf[0]) - bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf)) + if supportsABI(_ino64First) { + _p0 = unsafe.Pointer(&buf[0]) + bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf)) + } else { + n := len(buf) + oldBuf = make([]statfs_freebsd11_t, n) + _p0 = unsafe.Pointer(&oldBuf[0]) + bufsize = unsafe.Sizeof(statfs_freebsd11_t{}) * uintptr(n) + needsConvert = true + } } - r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags)) + var sysno uintptr = SYS_GETFSSTAT + if supportsABI(_ino64First) { + sysno = SYS_GETFSSTAT_FREEBSD12 + } + r0, _, e1 := Syscall(sysno, uintptr(_p0), bufsize, uintptr(flags)) n = int(r0) if e1 != 0 { err = e1 } + if e1 == 0 && needsConvert { + for i := range oldBuf { + buf[i].convertFrom(&oldBuf[i]) + } + } return } @@ -225,6 +272,234 @@ func Uname(uname *Utsname) error { return nil } +func Stat(path string, st *Stat_t) (err error) { + var oldStat stat_freebsd11_t + if supportsABI(_ino64First) { + return fstatat_freebsd12(AT_FDCWD, path, st, 0) + } + err = stat(path, &oldStat) + if err != nil { + return err + } + + st.convertFrom(&oldStat) + return nil +} + +func Lstat(path string, st *Stat_t) (err error) { + var oldStat stat_freebsd11_t + if supportsABI(_ino64First) { + return fstatat_freebsd12(AT_FDCWD, path, st, AT_SYMLINK_NOFOLLOW) + } + err = lstat(path, &oldStat) + if err != nil { + return err + } + + st.convertFrom(&oldStat) + return nil +} + +func Fstat(fd int, st *Stat_t) (err error) { + var oldStat stat_freebsd11_t + if supportsABI(_ino64First) { + return fstat_freebsd12(fd, st) + } + err = fstat(fd, &oldStat) + if err != nil { + return err + } + + st.convertFrom(&oldStat) + return nil +} + +func Fstatat(fd int, path string, st *Stat_t, flags int) (err error) { + var oldStat stat_freebsd11_t + if supportsABI(_ino64First) { + return fstatat_freebsd12(fd, path, st, flags) + } + err = fstatat(fd, path, &oldStat, flags) + if err != nil { + return err + } + + st.convertFrom(&oldStat) + return nil +} + +func Statfs(path string, st *Statfs_t) (err error) { + var oldStatfs statfs_freebsd11_t + if supportsABI(_ino64First) { + return statfs_freebsd12(path, st) + } + err = statfs(path, &oldStatfs) + if err != nil { + return err + } + + st.convertFrom(&oldStatfs) + return nil +} + +func Fstatfs(fd int, st *Statfs_t) (err error) { + var oldStatfs statfs_freebsd11_t + if supportsABI(_ino64First) { + return fstatfs_freebsd12(fd, st) + } + err = fstatfs(fd, &oldStatfs) + if err != nil { + return err + } + + st.convertFrom(&oldStatfs) + return nil +} + +func Getdents(fd int, buf []byte) (n int, err error) { + return Getdirentries(fd, buf, nil) +} + +func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { + if supportsABI(_ino64First) { + return getdirentries_freebsd12(fd, buf, basep) + } + + // The old syscall entries are smaller than the new. Use 1/4 of the original + // buffer size rounded up to DIRBLKSIZ (see /usr/src/lib/libc/sys/getdirentries.c). + oldBufLen := roundup(len(buf)/4, _dirblksiz) + oldBuf := make([]byte, oldBufLen) + n, err = getdirentries(fd, oldBuf, basep) + if err == nil && n > 0 { + n = convertFromDirents11(buf, oldBuf[:n]) + } + return +} + +func Mknod(path string, mode uint32, dev uint64) (err error) { + var oldDev int + if supportsABI(_ino64First) { + return mknodat_freebsd12(AT_FDCWD, path, mode, dev) + } + oldDev = int(dev) + return mknod(path, mode, oldDev) +} + +func Mknodat(fd int, path string, mode uint32, dev uint64) (err error) { + var oldDev int + if supportsABI(_ino64First) { + return mknodat_freebsd12(fd, path, mode, dev) + } + oldDev = int(dev) + return mknodat(fd, path, mode, oldDev) +} + +// round x to the nearest multiple of y, larger or equal to x. +// +// from /usr/include/sys/param.h Macros for counting and rounding. +// #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) +func roundup(x, y int) int { + return ((x + y - 1) / y) * y +} + +func (s *Stat_t) convertFrom(old *stat_freebsd11_t) { + *s = Stat_t{ + Dev: uint64(old.Dev), + Ino: uint64(old.Ino), + Nlink: uint64(old.Nlink), + Mode: old.Mode, + Uid: old.Uid, + Gid: old.Gid, + Rdev: uint64(old.Rdev), + Atim: old.Atim, + Mtim: old.Mtim, + Ctim: old.Ctim, + Birthtim: old.Birthtim, + Size: old.Size, + Blocks: old.Blocks, + Blksize: old.Blksize, + Flags: old.Flags, + Gen: uint64(old.Gen), + } +} + +func (s *Statfs_t) convertFrom(old *statfs_freebsd11_t) { + *s = Statfs_t{ + Version: _statfsVersion, + Type: old.Type, + Flags: old.Flags, + Bsize: old.Bsize, + Iosize: old.Iosize, + Blocks: old.Blocks, + Bfree: old.Bfree, + Bavail: old.Bavail, + Files: old.Files, + Ffree: old.Ffree, + Syncwrites: old.Syncwrites, + Asyncwrites: old.Asyncwrites, + Syncreads: old.Syncreads, + Asyncreads: old.Asyncreads, + // Spare + Namemax: old.Namemax, + Owner: old.Owner, + Fsid: old.Fsid, + // Charspare + // Fstypename + // Mntfromname + // Mntonname + } + + sl := old.Fstypename[:] + n := clen(*(*[]byte)(unsafe.Pointer(&sl))) + copy(s.Fstypename[:], old.Fstypename[:n]) + + sl = old.Mntfromname[:] + n = clen(*(*[]byte)(unsafe.Pointer(&sl))) + copy(s.Mntfromname[:], old.Mntfromname[:n]) + + sl = old.Mntonname[:] + n = clen(*(*[]byte)(unsafe.Pointer(&sl))) + copy(s.Mntonname[:], old.Mntonname[:n]) +} + +func convertFromDirents11(buf []byte, old []byte) int { + const ( + fixedSize = int(unsafe.Offsetof(Dirent{}.Name)) + oldFixedSize = int(unsafe.Offsetof(dirent_freebsd11{}.Name)) + ) + + dstPos := 0 + srcPos := 0 + for dstPos+fixedSize < len(buf) && srcPos+oldFixedSize < len(old) { + dstDirent := (*Dirent)(unsafe.Pointer(&buf[dstPos])) + srcDirent := (*dirent_freebsd11)(unsafe.Pointer(&old[srcPos])) + + reclen := roundup(fixedSize+int(srcDirent.Namlen)+1, 8) + if dstPos+reclen > len(buf) { + break + } + + dstDirent.Fileno = uint64(srcDirent.Fileno) + dstDirent.Off = 0 + dstDirent.Reclen = uint16(reclen) + dstDirent.Type = srcDirent.Type + dstDirent.Pad0 = 0 + dstDirent.Namlen = uint16(srcDirent.Namlen) + dstDirent.Pad1 = 0 + + copy(dstDirent.Name[:], srcDirent.Name[:srcDirent.Namlen]) + padding := buf[dstPos+fixedSize+int(dstDirent.Namlen) : dstPos+reclen] + for i := range padding { + padding[i] = 0 + } + + dstPos += int(dstDirent.Reclen) + srcPos += int(srcDirent.Reclen) + } + + return dstPos +} + /* * Exposed directly */ @@ -264,13 +539,16 @@ func Uname(uname *Utsname) error { //sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) //sys Flock(fd int, how int) (err error) //sys Fpathconf(fd int, name int) (val int, err error) -//sys Fstat(fd int, stat *Stat_t) (err error) -//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) -//sys Fstatfs(fd int, stat *Statfs_t) (err error) +//sys fstat(fd int, stat *stat_freebsd11_t) (err error) +//sys fstat_freebsd12(fd int, stat *Stat_t) (err error) +//sys fstatat(fd int, path string, stat *stat_freebsd11_t, flags int) (err error) +//sys fstatat_freebsd12(fd int, path string, stat *Stat_t, flags int) (err error) +//sys fstatfs(fd int, stat *statfs_freebsd11_t) (err error) +//sys fstatfs_freebsd12(fd int, stat *Statfs_t) (err error) //sys Fsync(fd int) (err error) //sys Ftruncate(fd int, length int64) (err error) -//sys Getdents(fd int, buf []byte) (n int, err error) -//sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) +//sys getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) +//sys getdirentries_freebsd12(fd int, buf []byte, basep *uintptr) (n int, err error) //sys Getdtablesize() (size int) //sysnb Getegid() (egid int) //sysnb Geteuid() (uid int) @@ -292,11 +570,13 @@ func Uname(uname *Utsname) error { //sys Link(path string, link string) (err error) //sys Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error) //sys Listen(s int, backlog int) (err error) -//sys Lstat(path string, stat *Stat_t) (err error) +//sys lstat(path string, stat *stat_freebsd11_t) (err error) //sys Mkdir(path string, mode uint32) (err error) //sys Mkdirat(dirfd int, path string, mode uint32) (err error) //sys Mkfifo(path string, mode uint32) (err error) -//sys Mknod(path string, mode uint32, dev int) (err error) +//sys mknod(path string, mode uint32, dev int) (err error) +//sys mknodat(fd int, path string, mode uint32, dev int) (err error) +//sys mknodat_freebsd12(fd int, path string, mode uint32, dev uint64) (err error) //sys Nanosleep(time *Timespec, leftover *Timespec) (err error) //sys Open(path string, mode int, perm uint32) (fd int, err error) //sys Openat(fdat int, path string, mode int, perm uint32) (fd int, err error) @@ -326,8 +606,9 @@ func Uname(uname *Utsname) error { //sysnb Setsid() (pid int, err error) //sysnb Settimeofday(tp *Timeval) (err error) //sysnb Setuid(uid int) (err error) -//sys Stat(path string, stat *Stat_t) (err error) -//sys Statfs(path string, stat *Statfs_t) (err error) +//sys stat(path string, stat *stat_freebsd11_t) (err error) +//sys statfs(path string, stat *statfs_freebsd11_t) (err error) +//sys statfs_freebsd12(path string, stat *Statfs_t) (err error) //sys Symlink(path string, link string) (err error) //sys Symlinkat(oldpath string, newdirfd int, newpath string) (err error) //sys Sync() (err error) @@ -382,6 +663,7 @@ func Uname(uname *Utsname) error { // Kqueue_portset // Getattrlist // Setattrlist +// Getdents // Getdirentriesattr // Searchfs // Delete diff --git a/vendor/golang.org/x/sys/unix/syscall_linux.go b/vendor/golang.org/x/sys/unix/syscall_linux.go index bfa20a971..84aa8ea03 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -1304,6 +1304,7 @@ func Mount(source string, target string, fstype string, flags uintptr, data stri //sys ClockGettime(clockid int32, time *Timespec) (err error) //sys Close(fd int) (err error) //sys CopyFileRange(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error) +//sys DeleteModule(name string, flags int) (err error) //sys Dup(oldfd int) (fd int, err error) //sys Dup3(oldfd int, newfd int, flags int) (err error) //sysnb EpollCreate1(flag int) (fd int, err error) @@ -1317,6 +1318,7 @@ func Mount(source string, target string, fstype string, flags uintptr, data stri //sys fcntl(fd int, cmd int, arg int) (val int, err error) //sys Fdatasync(fd int) (err error) //sys Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) +//sys FinitModule(fd int, params string, flags int) (err error) //sys Flistxattr(fd int, dest []byte) (sz int, err error) //sys Flock(fd int, how int) (err error) //sys Fremovexattr(fd int, attr string) (err error) @@ -1338,6 +1340,7 @@ func Getpgrp() (pid int) { //sysnb Getsid(pid int) (sid int, err error) //sysnb Gettid() (tid int) //sys Getxattr(path string, attr string, dest []byte) (sz int, err error) +//sys InitModule(moduleImage []byte, params string) (err error) //sys InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) //sysnb InotifyInit1(flags int) (fd int, err error) //sysnb InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) @@ -1527,8 +1530,6 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { // ClockNanosleep // ClockSettime // Clone -// CreateModule -// DeleteModule // EpollCtlOld // EpollPwait // EpollWaitOld @@ -1572,7 +1573,6 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { // Pselect6 // Ptrace // Putpmsg -// QueryModule // Quotactl // Readahead // Readv diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go b/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go index 646f295ad..fa5a9a6f6 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go @@ -191,12 +191,9 @@ func Dup2(oldfd int, newfd int) (err error) { return Dup3(oldfd, newfd, 0) } -func Pause() (err error) { - _, _, e1 := Syscall6(SYS_PPOLL, 0, 0, 0, 0, 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return +func Pause() error { + _, err := ppoll(nil, 0, nil, nil) + return err } func Poll(fds []PollFd, timeout int) (n int, err error) { diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go b/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go index 512077fe8..44aa1227a 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go @@ -191,12 +191,9 @@ func Dup2(oldfd int, newfd int) (err error) { return Dup3(oldfd, newfd, 0) } -func Pause() (err error) { - _, _, e1 := Syscall6(SYS_PPOLL, 0, 0, 0, 0, 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return +func Pause() error { + _, err := ppoll(nil, 0, nil, nil) + return err } func Poll(fds []PollFd, timeout int) (n int, err error) { diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd.go b/vendor/golang.org/x/sys/unix/syscall_netbsd.go index 206ce2af8..871fe65c3 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd.go @@ -300,6 +300,7 @@ func Uname(uname *Utsname) error { //sys Mknod(path string, mode uint32, dev int) (err error) //sys Nanosleep(time *Timespec, leftover *Timespec) (err error) //sys Open(path string, mode int, perm uint32) (fd int, err error) +//sys Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) //sys Pathconf(path string, name int) (val int, err error) //sys Pread(fd int, p []byte, offset int64) (n int, err error) //sys Pwrite(fd int, p []byte, offset int64) (n int, err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd.go b/vendor/golang.org/x/sys/unix/syscall_openbsd.go index 2c674a5c8..2b9f26a63 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd.go @@ -158,6 +158,15 @@ func IoctlGetTermios(fd int, req uint) (*Termios, error) { return &value, err } +//sys ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) + +func Ppoll(fds []PollFd, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { + if len(fds) == 0 { + return ppoll(nil, 0, timeout, sigmask) + } + return ppoll(&fds[0], len(fds), timeout, sigmask) +} + func Uname(uname *Utsname) error { mib := []_C_int{CTL_KERN, KERN_OSTYPE} n := unsafe.Sizeof(uname.Sysname) @@ -257,6 +266,7 @@ func Uname(uname *Utsname) error { //sys Mknod(path string, mode uint32, dev int) (err error) //sys Nanosleep(time *Timespec, leftover *Timespec) (err error) //sys Open(path string, mode int, perm uint32) (fd int, err error) +//sys Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) //sys Pathconf(path string, name int) (val int, err error) //sys Pread(fd int, p []byte, offset int64) (n int, err error) //sys Pwrite(fd int, p []byte, offset int64) (n int, err error) @@ -347,7 +357,6 @@ func Uname(uname *Utsname) error { // msgsnd // nfssvc // nnpfspioctl -// openat // preadv // profil // pwritev diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_386.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_386.go index 994964a91..d62da60d1 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_386.go @@ -31,3 +31,7 @@ func (msghdr *Msghdr) SetControllen(length int) { func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } + +// SYS___SYSCTL is used by syscall_bsd.go for all BSDs, but in modern versions +// of openbsd/386 the syscall is called sysctl instead of __sysctl. +const SYS___SYSCTL = SYS_SYSCTL diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go index 59844f504..5d812aaea 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go @@ -31,3 +31,7 @@ func (msghdr *Msghdr) SetControllen(length int) { func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } + +// SYS___SYSCTL is used by syscall_bsd.go for all BSDs, but in modern versions +// of openbsd/arm the syscall is called sysctl instead of __sysctl. +const SYS___SYSCTL = SYS_SYSCTL diff --git a/vendor/golang.org/x/sys/unix/types_freebsd.go b/vendor/golang.org/x/sys/unix/types_freebsd.go index a0a5843b9..8421ccf1c 100644 --- a/vendor/golang.org/x/sys/unix/types_freebsd.go +++ b/vendor/golang.org/x/sys/unix/types_freebsd.go @@ -14,7 +14,11 @@ Input to cgo -godefs. See README.md package unix /* -#define KERNEL +#define _WANT_FREEBSD11_STAT 1 +#define _WANT_FREEBSD11_STATFS 1 +#define _WANT_FREEBSD11_DIRENT 1 +#define _WANT_FREEBSD11_KEVENT 1 + #include #include #include @@ -63,50 +67,6 @@ struct sockaddr_any { char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; }; -// This structure is a duplicate of stat on FreeBSD 8-STABLE. -// See /usr/include/sys/stat.h. -struct stat8 { -#undef st_atimespec st_atim -#undef st_mtimespec st_mtim -#undef st_ctimespec st_ctim -#undef st_birthtimespec st_birthtim - __dev_t st_dev; - ino_t st_ino; - mode_t st_mode; - nlink_t st_nlink; - uid_t st_uid; - gid_t st_gid; - __dev_t st_rdev; -#if __BSD_VISIBLE - struct timespec st_atimespec; - struct timespec st_mtimespec; - struct timespec st_ctimespec; -#else - time_t st_atime; - long __st_atimensec; - time_t st_mtime; - long __st_mtimensec; - time_t st_ctime; - long __st_ctimensec; -#endif - off_t st_size; - blkcnt_t st_blocks; - blksize_t st_blksize; - fflags_t st_flags; - __uint32_t st_gen; - __int32_t st_lspare; -#if __BSD_VISIBLE - struct timespec st_birthtimespec; - unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec)); - unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec)); -#else - time_t st_birthtime; - long st_birthtimensec; - unsigned int :(8 / 2) * (16 - (int)sizeof(struct __timespec)); - unsigned int :(8 / 2) * (16 - (int)sizeof(struct __timespec)); -#endif -}; - // This structure is a duplicate of if_data on FreeBSD 8-STABLE. // See /usr/include/net/if.h. struct if_data8 { @@ -189,14 +149,25 @@ type _Gid_t C.gid_t // Files -type Stat_t C.struct_stat8 +const ( + _statfsVersion = C.STATFS_VERSION + _dirblksiz = C.DIRBLKSIZ +) + +type Stat_t C.struct_stat + +type stat_freebsd11_t C.struct_freebsd11_stat type Statfs_t C.struct_statfs +type statfs_freebsd11_t C.struct_freebsd11_statfs + type Flock_t C.struct_flock type Dirent C.struct_dirent +type dirent_freebsd11 C.struct_freebsd11_dirent + type Fsid C.struct_fsid // File system limits @@ -279,7 +250,7 @@ const ( // Events (kqueue, kevent) -type Kevent_t C.struct_kevent +type Kevent_t C.struct_kevent_freebsd11 // Select diff --git a/vendor/golang.org/x/sys/unix/types_openbsd.go b/vendor/golang.org/x/sys/unix/types_openbsd.go index 297e40d37..4e5e57f9a 100644 --- a/vendor/golang.org/x/sys/unix/types_openbsd.go +++ b/vendor/golang.org/x/sys/unix/types_openbsd.go @@ -261,6 +261,10 @@ const ( POLLWRNORM = C.POLLWRNORM ) +// Signal Sets + +type Sigset_t C.sigset_t + // Uname type Utsname C.struct_utsname diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index 86b980a5a..673152b94 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -1008,7 +1008,9 @@ const ( MFD_HUGE_256MB = 0x70000000 MFD_HUGE_2GB = 0x7c000000 MFD_HUGE_2MB = 0x54000000 + MFD_HUGE_32MB = 0x64000000 MFD_HUGE_512KB = 0x4c000000 + MFD_HUGE_512MB = 0x74000000 MFD_HUGE_64KB = 0x40000000 MFD_HUGE_8MB = 0x5c000000 MFD_HUGE_MASK = 0x3f @@ -1021,6 +1023,8 @@ const ( MNT_DETACH = 0x2 MNT_EXPIRE = 0x4 MNT_FORCE = 0x1 + MODULE_INIT_IGNORE_MODVERSIONS = 0x1 + MODULE_INIT_IGNORE_VERMAGIC = 0x2 MSDOS_SUPER_MAGIC = 0x4d44 MSG_BATCH = 0x40000 MSG_CMSG_CLOEXEC = 0x40000000 @@ -1584,6 +1588,7 @@ const ( RTM_DELACTION = 0x31 RTM_DELADDR = 0x15 RTM_DELADDRLABEL = 0x49 + RTM_DELCHAIN = 0x65 RTM_DELLINK = 0x11 RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d @@ -1604,6 +1609,7 @@ const ( RTM_GETADDR = 0x16 RTM_GETADDRLABEL = 0x4a RTM_GETANYCAST = 0x3e + RTM_GETCHAIN = 0x66 RTM_GETDCB = 0x4e RTM_GETLINK = 0x12 RTM_GETMDB = 0x56 @@ -1618,11 +1624,12 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x63 + RTM_MAX = 0x67 RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 RTM_NEWCACHEREPORT = 0x60 + RTM_NEWCHAIN = 0x64 RTM_NEWLINK = 0x10 RTM_NEWMDB = 0x54 RTM_NEWNDUSEROPT = 0x44 @@ -1637,8 +1644,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x15 - RTM_NR_MSGTYPES = 0x54 + RTM_NR_FAMILIES = 0x16 + RTM_NR_MSGTYPES = 0x58 RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1687,6 +1694,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_MODE_DISABLED = 0x0 SECCOMP_MODE_FILTER = 0x2 @@ -1891,6 +1899,7 @@ const ( SO_TIMESTAMP = 0x1d SO_TIMESTAMPING = 0x25 SO_TIMESTAMPNS = 0x23 + SO_TXTIME = 0x3d SO_TYPE = 0x3 SO_VM_SOCKETS_BUFFER_MAX_SIZE = 0x2 SO_VM_SOCKETS_BUFFER_MIN_SIZE = 0x1 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index 286311572..5735bcf3c 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -1008,7 +1008,9 @@ const ( MFD_HUGE_256MB = 0x70000000 MFD_HUGE_2GB = 0x7c000000 MFD_HUGE_2MB = 0x54000000 + MFD_HUGE_32MB = 0x64000000 MFD_HUGE_512KB = 0x4c000000 + MFD_HUGE_512MB = 0x74000000 MFD_HUGE_64KB = 0x40000000 MFD_HUGE_8MB = 0x5c000000 MFD_HUGE_MASK = 0x3f @@ -1021,6 +1023,8 @@ const ( MNT_DETACH = 0x2 MNT_EXPIRE = 0x4 MNT_FORCE = 0x1 + MODULE_INIT_IGNORE_MODVERSIONS = 0x1 + MODULE_INIT_IGNORE_VERMAGIC = 0x2 MSDOS_SUPER_MAGIC = 0x4d44 MSG_BATCH = 0x40000 MSG_CMSG_CLOEXEC = 0x40000000 @@ -1585,6 +1589,7 @@ const ( RTM_DELACTION = 0x31 RTM_DELADDR = 0x15 RTM_DELADDRLABEL = 0x49 + RTM_DELCHAIN = 0x65 RTM_DELLINK = 0x11 RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d @@ -1605,6 +1610,7 @@ const ( RTM_GETADDR = 0x16 RTM_GETADDRLABEL = 0x4a RTM_GETANYCAST = 0x3e + RTM_GETCHAIN = 0x66 RTM_GETDCB = 0x4e RTM_GETLINK = 0x12 RTM_GETMDB = 0x56 @@ -1619,11 +1625,12 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x63 + RTM_MAX = 0x67 RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 RTM_NEWCACHEREPORT = 0x60 + RTM_NEWCHAIN = 0x64 RTM_NEWLINK = 0x10 RTM_NEWMDB = 0x54 RTM_NEWNDUSEROPT = 0x44 @@ -1638,8 +1645,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x15 - RTM_NR_MSGTYPES = 0x54 + RTM_NR_FAMILIES = 0x16 + RTM_NR_MSGTYPES = 0x58 RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1688,6 +1695,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_MODE_DISABLED = 0x0 SECCOMP_MODE_FILTER = 0x2 @@ -1892,6 +1900,7 @@ const ( SO_TIMESTAMP = 0x1d SO_TIMESTAMPING = 0x25 SO_TIMESTAMPNS = 0x23 + SO_TXTIME = 0x3d SO_TYPE = 0x3 SO_VM_SOCKETS_BUFFER_MAX_SIZE = 0x2 SO_VM_SOCKETS_BUFFER_MIN_SIZE = 0x1 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index 1b58da1e7..d8e8442e5 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -1006,7 +1006,9 @@ const ( MFD_HUGE_256MB = 0x70000000 MFD_HUGE_2GB = 0x7c000000 MFD_HUGE_2MB = 0x54000000 + MFD_HUGE_32MB = 0x64000000 MFD_HUGE_512KB = 0x4c000000 + MFD_HUGE_512MB = 0x74000000 MFD_HUGE_64KB = 0x40000000 MFD_HUGE_8MB = 0x5c000000 MFD_HUGE_MASK = 0x3f @@ -1019,6 +1021,8 @@ const ( MNT_DETACH = 0x2 MNT_EXPIRE = 0x4 MNT_FORCE = 0x1 + MODULE_INIT_IGNORE_MODVERSIONS = 0x1 + MODULE_INIT_IGNORE_VERMAGIC = 0x2 MSDOS_SUPER_MAGIC = 0x4d44 MSG_BATCH = 0x40000 MSG_CMSG_CLOEXEC = 0x40000000 @@ -1591,6 +1595,7 @@ const ( RTM_DELACTION = 0x31 RTM_DELADDR = 0x15 RTM_DELADDRLABEL = 0x49 + RTM_DELCHAIN = 0x65 RTM_DELLINK = 0x11 RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d @@ -1611,6 +1616,7 @@ const ( RTM_GETADDR = 0x16 RTM_GETADDRLABEL = 0x4a RTM_GETANYCAST = 0x3e + RTM_GETCHAIN = 0x66 RTM_GETDCB = 0x4e RTM_GETLINK = 0x12 RTM_GETMDB = 0x56 @@ -1625,11 +1631,12 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x63 + RTM_MAX = 0x67 RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 RTM_NEWCACHEREPORT = 0x60 + RTM_NEWCHAIN = 0x64 RTM_NEWLINK = 0x10 RTM_NEWMDB = 0x54 RTM_NEWNDUSEROPT = 0x44 @@ -1644,8 +1651,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x15 - RTM_NR_MSGTYPES = 0x54 + RTM_NR_FAMILIES = 0x16 + RTM_NR_MSGTYPES = 0x58 RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1694,6 +1701,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_MODE_DISABLED = 0x0 SECCOMP_MODE_FILTER = 0x2 @@ -1898,6 +1906,7 @@ const ( SO_TIMESTAMP = 0x1d SO_TIMESTAMPING = 0x25 SO_TIMESTAMPNS = 0x23 + SO_TXTIME = 0x3d SO_TYPE = 0x3 SO_VM_SOCKETS_BUFFER_MAX_SIZE = 0x2 SO_VM_SOCKETS_BUFFER_MIN_SIZE = 0x1 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index 08377eb4f..5d79b789b 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -1009,7 +1009,9 @@ const ( MFD_HUGE_256MB = 0x70000000 MFD_HUGE_2GB = 0x7c000000 MFD_HUGE_2MB = 0x54000000 + MFD_HUGE_32MB = 0x64000000 MFD_HUGE_512KB = 0x4c000000 + MFD_HUGE_512MB = 0x74000000 MFD_HUGE_64KB = 0x40000000 MFD_HUGE_8MB = 0x5c000000 MFD_HUGE_MASK = 0x3f @@ -1022,6 +1024,8 @@ const ( MNT_DETACH = 0x2 MNT_EXPIRE = 0x4 MNT_FORCE = 0x1 + MODULE_INIT_IGNORE_MODVERSIONS = 0x1 + MODULE_INIT_IGNORE_VERMAGIC = 0x2 MSDOS_SUPER_MAGIC = 0x4d44 MSG_BATCH = 0x40000 MSG_CMSG_CLOEXEC = 0x40000000 @@ -1575,6 +1579,7 @@ const ( RTM_DELACTION = 0x31 RTM_DELADDR = 0x15 RTM_DELADDRLABEL = 0x49 + RTM_DELCHAIN = 0x65 RTM_DELLINK = 0x11 RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d @@ -1595,6 +1600,7 @@ const ( RTM_GETADDR = 0x16 RTM_GETADDRLABEL = 0x4a RTM_GETANYCAST = 0x3e + RTM_GETCHAIN = 0x66 RTM_GETDCB = 0x4e RTM_GETLINK = 0x12 RTM_GETMDB = 0x56 @@ -1609,11 +1615,12 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x63 + RTM_MAX = 0x67 RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 RTM_NEWCACHEREPORT = 0x60 + RTM_NEWCHAIN = 0x64 RTM_NEWLINK = 0x10 RTM_NEWMDB = 0x54 RTM_NEWNDUSEROPT = 0x44 @@ -1628,8 +1635,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x15 - RTM_NR_MSGTYPES = 0x54 + RTM_NR_FAMILIES = 0x16 + RTM_NR_MSGTYPES = 0x58 RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1678,6 +1685,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_MODE_DISABLED = 0x0 SECCOMP_MODE_FILTER = 0x2 @@ -1882,6 +1890,7 @@ const ( SO_TIMESTAMP = 0x1d SO_TIMESTAMPING = 0x25 SO_TIMESTAMPNS = 0x23 + SO_TXTIME = 0x3d SO_TYPE = 0x3 SO_VM_SOCKETS_BUFFER_MAX_SIZE = 0x2 SO_VM_SOCKETS_BUFFER_MIN_SIZE = 0x1 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index 5de2c7aa4..3c91615c8 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -1006,7 +1006,9 @@ const ( MFD_HUGE_256MB = 0x70000000 MFD_HUGE_2GB = 0x7c000000 MFD_HUGE_2MB = 0x54000000 + MFD_HUGE_32MB = 0x64000000 MFD_HUGE_512KB = 0x4c000000 + MFD_HUGE_512MB = 0x74000000 MFD_HUGE_64KB = 0x40000000 MFD_HUGE_8MB = 0x5c000000 MFD_HUGE_MASK = 0x3f @@ -1019,6 +1021,8 @@ const ( MNT_DETACH = 0x2 MNT_EXPIRE = 0x4 MNT_FORCE = 0x1 + MODULE_INIT_IGNORE_MODVERSIONS = 0x1 + MODULE_INIT_IGNORE_VERMAGIC = 0x2 MSDOS_SUPER_MAGIC = 0x4d44 MSG_BATCH = 0x40000 MSG_CMSG_CLOEXEC = 0x40000000 @@ -1584,6 +1588,7 @@ const ( RTM_DELACTION = 0x31 RTM_DELADDR = 0x15 RTM_DELADDRLABEL = 0x49 + RTM_DELCHAIN = 0x65 RTM_DELLINK = 0x11 RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d @@ -1604,6 +1609,7 @@ const ( RTM_GETADDR = 0x16 RTM_GETADDRLABEL = 0x4a RTM_GETANYCAST = 0x3e + RTM_GETCHAIN = 0x66 RTM_GETDCB = 0x4e RTM_GETLINK = 0x12 RTM_GETMDB = 0x56 @@ -1618,11 +1624,12 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x63 + RTM_MAX = 0x67 RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 RTM_NEWCACHEREPORT = 0x60 + RTM_NEWCHAIN = 0x64 RTM_NEWLINK = 0x10 RTM_NEWMDB = 0x54 RTM_NEWNDUSEROPT = 0x44 @@ -1637,8 +1644,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x15 - RTM_NR_MSGTYPES = 0x54 + RTM_NR_FAMILIES = 0x16 + RTM_NR_MSGTYPES = 0x58 RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1687,6 +1694,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_MODE_DISABLED = 0x0 SECCOMP_MODE_FILTER = 0x2 @@ -1892,6 +1900,7 @@ const ( SO_TIMESTAMP = 0x1d SO_TIMESTAMPING = 0x25 SO_TIMESTAMPNS = 0x23 + SO_TXTIME = 0x3d SO_TYPE = 0x1008 SO_VM_SOCKETS_BUFFER_MAX_SIZE = 0x2 SO_VM_SOCKETS_BUFFER_MIN_SIZE = 0x1 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index 51015f354..e1f86c1cd 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -1006,7 +1006,9 @@ const ( MFD_HUGE_256MB = 0x70000000 MFD_HUGE_2GB = 0x7c000000 MFD_HUGE_2MB = 0x54000000 + MFD_HUGE_32MB = 0x64000000 MFD_HUGE_512KB = 0x4c000000 + MFD_HUGE_512MB = 0x74000000 MFD_HUGE_64KB = 0x40000000 MFD_HUGE_8MB = 0x5c000000 MFD_HUGE_MASK = 0x3f @@ -1019,6 +1021,8 @@ const ( MNT_DETACH = 0x2 MNT_EXPIRE = 0x4 MNT_FORCE = 0x1 + MODULE_INIT_IGNORE_MODVERSIONS = 0x1 + MODULE_INIT_IGNORE_VERMAGIC = 0x2 MSDOS_SUPER_MAGIC = 0x4d44 MSG_BATCH = 0x40000 MSG_CMSG_CLOEXEC = 0x40000000 @@ -1584,6 +1588,7 @@ const ( RTM_DELACTION = 0x31 RTM_DELADDR = 0x15 RTM_DELADDRLABEL = 0x49 + RTM_DELCHAIN = 0x65 RTM_DELLINK = 0x11 RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d @@ -1604,6 +1609,7 @@ const ( RTM_GETADDR = 0x16 RTM_GETADDRLABEL = 0x4a RTM_GETANYCAST = 0x3e + RTM_GETCHAIN = 0x66 RTM_GETDCB = 0x4e RTM_GETLINK = 0x12 RTM_GETMDB = 0x56 @@ -1618,11 +1624,12 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x63 + RTM_MAX = 0x67 RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 RTM_NEWCACHEREPORT = 0x60 + RTM_NEWCHAIN = 0x64 RTM_NEWLINK = 0x10 RTM_NEWMDB = 0x54 RTM_NEWNDUSEROPT = 0x44 @@ -1637,8 +1644,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x15 - RTM_NR_MSGTYPES = 0x54 + RTM_NR_FAMILIES = 0x16 + RTM_NR_MSGTYPES = 0x58 RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1687,6 +1694,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_MODE_DISABLED = 0x0 SECCOMP_MODE_FILTER = 0x2 @@ -1892,6 +1900,7 @@ const ( SO_TIMESTAMP = 0x1d SO_TIMESTAMPING = 0x25 SO_TIMESTAMPNS = 0x23 + SO_TXTIME = 0x3d SO_TYPE = 0x1008 SO_VM_SOCKETS_BUFFER_MAX_SIZE = 0x2 SO_VM_SOCKETS_BUFFER_MIN_SIZE = 0x1 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index fdd388deb..d09e3b68b 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -1006,7 +1006,9 @@ const ( MFD_HUGE_256MB = 0x70000000 MFD_HUGE_2GB = 0x7c000000 MFD_HUGE_2MB = 0x54000000 + MFD_HUGE_32MB = 0x64000000 MFD_HUGE_512KB = 0x4c000000 + MFD_HUGE_512MB = 0x74000000 MFD_HUGE_64KB = 0x40000000 MFD_HUGE_8MB = 0x5c000000 MFD_HUGE_MASK = 0x3f @@ -1019,6 +1021,8 @@ const ( MNT_DETACH = 0x2 MNT_EXPIRE = 0x4 MNT_FORCE = 0x1 + MODULE_INIT_IGNORE_MODVERSIONS = 0x1 + MODULE_INIT_IGNORE_VERMAGIC = 0x2 MSDOS_SUPER_MAGIC = 0x4d44 MSG_BATCH = 0x40000 MSG_CMSG_CLOEXEC = 0x40000000 @@ -1584,6 +1588,7 @@ const ( RTM_DELACTION = 0x31 RTM_DELADDR = 0x15 RTM_DELADDRLABEL = 0x49 + RTM_DELCHAIN = 0x65 RTM_DELLINK = 0x11 RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d @@ -1604,6 +1609,7 @@ const ( RTM_GETADDR = 0x16 RTM_GETADDRLABEL = 0x4a RTM_GETANYCAST = 0x3e + RTM_GETCHAIN = 0x66 RTM_GETDCB = 0x4e RTM_GETLINK = 0x12 RTM_GETMDB = 0x56 @@ -1618,11 +1624,12 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x63 + RTM_MAX = 0x67 RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 RTM_NEWCACHEREPORT = 0x60 + RTM_NEWCHAIN = 0x64 RTM_NEWLINK = 0x10 RTM_NEWMDB = 0x54 RTM_NEWNDUSEROPT = 0x44 @@ -1637,8 +1644,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x15 - RTM_NR_MSGTYPES = 0x54 + RTM_NR_FAMILIES = 0x16 + RTM_NR_MSGTYPES = 0x58 RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1687,6 +1694,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_MODE_DISABLED = 0x0 SECCOMP_MODE_FILTER = 0x2 @@ -1892,6 +1900,7 @@ const ( SO_TIMESTAMP = 0x1d SO_TIMESTAMPING = 0x25 SO_TIMESTAMPNS = 0x23 + SO_TXTIME = 0x3d SO_TYPE = 0x1008 SO_VM_SOCKETS_BUFFER_MAX_SIZE = 0x2 SO_VM_SOCKETS_BUFFER_MIN_SIZE = 0x1 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index 2d1504612..f78108dfb 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -1006,7 +1006,9 @@ const ( MFD_HUGE_256MB = 0x70000000 MFD_HUGE_2GB = 0x7c000000 MFD_HUGE_2MB = 0x54000000 + MFD_HUGE_32MB = 0x64000000 MFD_HUGE_512KB = 0x4c000000 + MFD_HUGE_512MB = 0x74000000 MFD_HUGE_64KB = 0x40000000 MFD_HUGE_8MB = 0x5c000000 MFD_HUGE_MASK = 0x3f @@ -1019,6 +1021,8 @@ const ( MNT_DETACH = 0x2 MNT_EXPIRE = 0x4 MNT_FORCE = 0x1 + MODULE_INIT_IGNORE_MODVERSIONS = 0x1 + MODULE_INIT_IGNORE_VERMAGIC = 0x2 MSDOS_SUPER_MAGIC = 0x4d44 MSG_BATCH = 0x40000 MSG_CMSG_CLOEXEC = 0x40000000 @@ -1584,6 +1588,7 @@ const ( RTM_DELACTION = 0x31 RTM_DELADDR = 0x15 RTM_DELADDRLABEL = 0x49 + RTM_DELCHAIN = 0x65 RTM_DELLINK = 0x11 RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d @@ -1604,6 +1609,7 @@ const ( RTM_GETADDR = 0x16 RTM_GETADDRLABEL = 0x4a RTM_GETANYCAST = 0x3e + RTM_GETCHAIN = 0x66 RTM_GETDCB = 0x4e RTM_GETLINK = 0x12 RTM_GETMDB = 0x56 @@ -1618,11 +1624,12 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x63 + RTM_MAX = 0x67 RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 RTM_NEWCACHEREPORT = 0x60 + RTM_NEWCHAIN = 0x64 RTM_NEWLINK = 0x10 RTM_NEWMDB = 0x54 RTM_NEWNDUSEROPT = 0x44 @@ -1637,8 +1644,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x15 - RTM_NR_MSGTYPES = 0x54 + RTM_NR_FAMILIES = 0x16 + RTM_NR_MSGTYPES = 0x58 RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1687,6 +1694,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_MODE_DISABLED = 0x0 SECCOMP_MODE_FILTER = 0x2 @@ -1892,6 +1900,7 @@ const ( SO_TIMESTAMP = 0x1d SO_TIMESTAMPING = 0x25 SO_TIMESTAMPNS = 0x23 + SO_TXTIME = 0x3d SO_TYPE = 0x1008 SO_VM_SOCKETS_BUFFER_MAX_SIZE = 0x2 SO_VM_SOCKETS_BUFFER_MIN_SIZE = 0x1 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index cd8fcd35c..8da57a99c 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -1005,7 +1005,9 @@ const ( MFD_HUGE_256MB = 0x70000000 MFD_HUGE_2GB = 0x7c000000 MFD_HUGE_2MB = 0x54000000 + MFD_HUGE_32MB = 0x64000000 MFD_HUGE_512KB = 0x4c000000 + MFD_HUGE_512MB = 0x74000000 MFD_HUGE_64KB = 0x40000000 MFD_HUGE_8MB = 0x5c000000 MFD_HUGE_MASK = 0x3f @@ -1018,6 +1020,8 @@ const ( MNT_DETACH = 0x2 MNT_EXPIRE = 0x4 MNT_FORCE = 0x1 + MODULE_INIT_IGNORE_MODVERSIONS = 0x1 + MODULE_INIT_IGNORE_VERMAGIC = 0x2 MSDOS_SUPER_MAGIC = 0x4d44 MSG_BATCH = 0x40000 MSG_CMSG_CLOEXEC = 0x40000000 @@ -1640,6 +1644,7 @@ const ( RTM_DELACTION = 0x31 RTM_DELADDR = 0x15 RTM_DELADDRLABEL = 0x49 + RTM_DELCHAIN = 0x65 RTM_DELLINK = 0x11 RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d @@ -1660,6 +1665,7 @@ const ( RTM_GETADDR = 0x16 RTM_GETADDRLABEL = 0x4a RTM_GETANYCAST = 0x3e + RTM_GETCHAIN = 0x66 RTM_GETDCB = 0x4e RTM_GETLINK = 0x12 RTM_GETMDB = 0x56 @@ -1674,11 +1680,12 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x63 + RTM_MAX = 0x67 RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 RTM_NEWCACHEREPORT = 0x60 + RTM_NEWCHAIN = 0x64 RTM_NEWLINK = 0x10 RTM_NEWMDB = 0x54 RTM_NEWNDUSEROPT = 0x44 @@ -1693,8 +1700,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x15 - RTM_NR_MSGTYPES = 0x54 + RTM_NR_FAMILIES = 0x16 + RTM_NR_MSGTYPES = 0x58 RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1743,6 +1750,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_MODE_DISABLED = 0x0 SECCOMP_MODE_FILTER = 0x2 @@ -1947,6 +1955,7 @@ const ( SO_TIMESTAMP = 0x1d SO_TIMESTAMPING = 0x25 SO_TIMESTAMPNS = 0x23 + SO_TXTIME = 0x3d SO_TYPE = 0x3 SO_VM_SOCKETS_BUFFER_MAX_SIZE = 0x2 SO_VM_SOCKETS_BUFFER_MIN_SIZE = 0x1 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index cdb608876..1832c0a7c 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -1005,7 +1005,9 @@ const ( MFD_HUGE_256MB = 0x70000000 MFD_HUGE_2GB = 0x7c000000 MFD_HUGE_2MB = 0x54000000 + MFD_HUGE_32MB = 0x64000000 MFD_HUGE_512KB = 0x4c000000 + MFD_HUGE_512MB = 0x74000000 MFD_HUGE_64KB = 0x40000000 MFD_HUGE_8MB = 0x5c000000 MFD_HUGE_MASK = 0x3f @@ -1018,6 +1020,8 @@ const ( MNT_DETACH = 0x2 MNT_EXPIRE = 0x4 MNT_FORCE = 0x1 + MODULE_INIT_IGNORE_MODVERSIONS = 0x1 + MODULE_INIT_IGNORE_VERMAGIC = 0x2 MSDOS_SUPER_MAGIC = 0x4d44 MSG_BATCH = 0x40000 MSG_CMSG_CLOEXEC = 0x40000000 @@ -1640,6 +1644,7 @@ const ( RTM_DELACTION = 0x31 RTM_DELADDR = 0x15 RTM_DELADDRLABEL = 0x49 + RTM_DELCHAIN = 0x65 RTM_DELLINK = 0x11 RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d @@ -1660,6 +1665,7 @@ const ( RTM_GETADDR = 0x16 RTM_GETADDRLABEL = 0x4a RTM_GETANYCAST = 0x3e + RTM_GETCHAIN = 0x66 RTM_GETDCB = 0x4e RTM_GETLINK = 0x12 RTM_GETMDB = 0x56 @@ -1674,11 +1680,12 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x63 + RTM_MAX = 0x67 RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 RTM_NEWCACHEREPORT = 0x60 + RTM_NEWCHAIN = 0x64 RTM_NEWLINK = 0x10 RTM_NEWMDB = 0x54 RTM_NEWNDUSEROPT = 0x44 @@ -1693,8 +1700,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x15 - RTM_NR_MSGTYPES = 0x54 + RTM_NR_FAMILIES = 0x16 + RTM_NR_MSGTYPES = 0x58 RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1743,6 +1750,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_MODE_DISABLED = 0x0 SECCOMP_MODE_FILTER = 0x2 @@ -1947,6 +1955,7 @@ const ( SO_TIMESTAMP = 0x1d SO_TIMESTAMPING = 0x25 SO_TIMESTAMPNS = 0x23 + SO_TXTIME = 0x3d SO_TYPE = 0x3 SO_VM_SOCKETS_BUFFER_MAX_SIZE = 0x2 SO_VM_SOCKETS_BUFFER_MIN_SIZE = 0x1 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go index 9e9472bec..c6bd4efff 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go @@ -1006,7 +1006,9 @@ const ( MFD_HUGE_256MB = 0x70000000 MFD_HUGE_2GB = 0x7c000000 MFD_HUGE_2MB = 0x54000000 + MFD_HUGE_32MB = 0x64000000 MFD_HUGE_512KB = 0x4c000000 + MFD_HUGE_512MB = 0x74000000 MFD_HUGE_64KB = 0x40000000 MFD_HUGE_8MB = 0x5c000000 MFD_HUGE_MASK = 0x3f @@ -1019,6 +1021,8 @@ const ( MNT_DETACH = 0x2 MNT_EXPIRE = 0x4 MNT_FORCE = 0x1 + MODULE_INIT_IGNORE_MODVERSIONS = 0x1 + MODULE_INIT_IGNORE_VERMAGIC = 0x2 MSDOS_SUPER_MAGIC = 0x4d44 MSG_BATCH = 0x40000 MSG_CMSG_CLOEXEC = 0x40000000 @@ -1572,6 +1576,7 @@ const ( RTM_DELACTION = 0x31 RTM_DELADDR = 0x15 RTM_DELADDRLABEL = 0x49 + RTM_DELCHAIN = 0x65 RTM_DELLINK = 0x11 RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d @@ -1592,6 +1597,7 @@ const ( RTM_GETADDR = 0x16 RTM_GETADDRLABEL = 0x4a RTM_GETANYCAST = 0x3e + RTM_GETCHAIN = 0x66 RTM_GETDCB = 0x4e RTM_GETLINK = 0x12 RTM_GETMDB = 0x56 @@ -1606,11 +1612,12 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x63 + RTM_MAX = 0x67 RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 RTM_NEWCACHEREPORT = 0x60 + RTM_NEWCHAIN = 0x64 RTM_NEWLINK = 0x10 RTM_NEWMDB = 0x54 RTM_NEWNDUSEROPT = 0x44 @@ -1625,8 +1632,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x15 - RTM_NR_MSGTYPES = 0x54 + RTM_NR_FAMILIES = 0x16 + RTM_NR_MSGTYPES = 0x58 RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1675,6 +1682,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_MODE_DISABLED = 0x0 SECCOMP_MODE_FILTER = 0x2 @@ -1879,6 +1887,7 @@ const ( SO_TIMESTAMP = 0x1d SO_TIMESTAMPING = 0x25 SO_TIMESTAMPNS = 0x23 + SO_TXTIME = 0x3d SO_TYPE = 0x3 SO_VM_SOCKETS_BUFFER_MAX_SIZE = 0x2 SO_VM_SOCKETS_BUFFER_MIN_SIZE = 0x1 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index f33d031ad..8cdf353dc 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -1006,7 +1006,9 @@ const ( MFD_HUGE_256MB = 0x70000000 MFD_HUGE_2GB = 0x7c000000 MFD_HUGE_2MB = 0x54000000 + MFD_HUGE_32MB = 0x64000000 MFD_HUGE_512KB = 0x4c000000 + MFD_HUGE_512MB = 0x74000000 MFD_HUGE_64KB = 0x40000000 MFD_HUGE_8MB = 0x5c000000 MFD_HUGE_MASK = 0x3f @@ -1019,6 +1021,8 @@ const ( MNT_DETACH = 0x2 MNT_EXPIRE = 0x4 MNT_FORCE = 0x1 + MODULE_INIT_IGNORE_MODVERSIONS = 0x1 + MODULE_INIT_IGNORE_VERMAGIC = 0x2 MSDOS_SUPER_MAGIC = 0x4d44 MSG_BATCH = 0x40000 MSG_CMSG_CLOEXEC = 0x40000000 @@ -1645,6 +1649,7 @@ const ( RTM_DELACTION = 0x31 RTM_DELADDR = 0x15 RTM_DELADDRLABEL = 0x49 + RTM_DELCHAIN = 0x65 RTM_DELLINK = 0x11 RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d @@ -1665,6 +1670,7 @@ const ( RTM_GETADDR = 0x16 RTM_GETADDRLABEL = 0x4a RTM_GETANYCAST = 0x3e + RTM_GETCHAIN = 0x66 RTM_GETDCB = 0x4e RTM_GETLINK = 0x12 RTM_GETMDB = 0x56 @@ -1679,11 +1685,12 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x63 + RTM_MAX = 0x67 RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 RTM_NEWCACHEREPORT = 0x60 + RTM_NEWCHAIN = 0x64 RTM_NEWLINK = 0x10 RTM_NEWMDB = 0x54 RTM_NEWNDUSEROPT = 0x44 @@ -1698,8 +1705,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x15 - RTM_NR_MSGTYPES = 0x54 + RTM_NR_FAMILIES = 0x16 + RTM_NR_MSGTYPES = 0x58 RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1748,6 +1755,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_MODE_DISABLED = 0x0 SECCOMP_MODE_FILTER = 0x2 @@ -1952,6 +1960,7 @@ const ( SO_TIMESTAMP = 0x1d SO_TIMESTAMPING = 0x25 SO_TIMESTAMPNS = 0x23 + SO_TXTIME = 0x3d SO_TYPE = 0x3 SO_VM_SOCKETS_BUFFER_MAX_SIZE = 0x2 SO_VM_SOCKETS_BUFFER_MIN_SIZE = 0x1 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc.go b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc.go index ab2f76122..6bae21e5d 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc.go @@ -1,4 +1,4 @@ -// mksyscall_aix.pl -aix -tags aix,ppc syscall_aix.go syscall_aix_ppc.go +// mksyscall_aix_ppc.pl -aix -tags aix,ppc syscall_aix.go syscall_aix_ppc.go // Code generated by the command above; see README.md. DO NOT EDIT. // +build aix,ppc @@ -7,6 +7,7 @@ package unix /* #include +#include int utimes(uintptr_t, uintptr_t); int utimensat(int, uintptr_t, uintptr_t, int); int getcwd(uintptr_t, size_t); @@ -20,10 +21,8 @@ int chdir(uintptr_t); int chroot(uintptr_t); int close(int); int dup(int); -int dup3(int, int, int); void exit(int); int faccessat(int, uintptr_t, unsigned int, int); -int fallocate(int, unsigned int, long long, long long); int fchdir(int); int fchmod(int, unsigned int); int fchmodat(int, uintptr_t, unsigned int, int); @@ -49,7 +48,6 @@ int open64(uintptr_t, int, unsigned int); int openat(int, uintptr_t, int, unsigned int); int read(int, uintptr_t, size_t); int readlink(uintptr_t, uintptr_t, size_t); -int removexattr(uintptr_t, uintptr_t); int renameat(int, uintptr_t, int, uintptr_t); int setdomainname(uintptr_t, size_t); int sethostname(uintptr_t, size_t); @@ -61,13 +59,11 @@ int setgid(int); int setpriority(int, int, int); int statx(int, uintptr_t, int, int, uintptr_t); int sync(); -long long tee(int, int, int, int); uintptr_t times(uintptr_t); int umask(int); int uname(uintptr_t); int unlink(uintptr_t); int unlinkat(int, uintptr_t, int); -int unshare(int); int ustat(int, uintptr_t); int write(int, uintptr_t, size_t); int dup2(int, int); @@ -118,7 +114,6 @@ int msync(uintptr_t, size_t, int); int munlock(uintptr_t, size_t); int munlockall(); int pipe(uintptr_t); -int pipe2(uintptr_t, int); int poll(uintptr_t, int, int); int gettimeofday(uintptr_t, uintptr_t); int time(uintptr_t); @@ -131,7 +126,6 @@ uintptr_t mmap(uintptr_t, uintptr_t, int, int, int, long long); */ import "C" import ( - "syscall" "unsafe" ) @@ -245,6 +239,17 @@ func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fcntl(fd int, cmd int, arg int) (val int, err error) { + r0, er := C.fcntl(C.uintptr_t(fd), C.int(cmd), C.uintptr_t(arg)) + val = int(r0) + if r0 == -1 && er != nil { + err = er + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Acct(path string) (err error) { _p0 := uintptr(unsafe.Pointer(C.CString(path))) r0, er := C.acct(C.uintptr_t(_p0)) @@ -299,16 +304,6 @@ func Dup(oldfd int) (fd int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Dup3(oldfd int, newfd int, flags int) (err error) { - r0, er := C.dup3(C.int(oldfd), C.int(newfd), C.int(flags)) - if r0 == -1 && er != nil { - err = er - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Exit(code int) { C.exit(C.int(code)) return @@ -327,16 +322,6 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Fallocate(fd int, mode uint32, off int64, len int64) (err error) { - r0, er := C.fallocate(C.int(fd), C.uint(mode), C.longlong(off), C.longlong(len)) - if r0 == -1 && er != nil { - err = er - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Fchdir(fd int) (err error) { r0, er := C.fchdir(C.int(fd)) if r0 == -1 && er != nil { @@ -379,17 +364,6 @@ func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func fcntl(fd int, cmd int, arg int) (val int, err error) { - r0, er := C.fcntl(C.uintptr_t(fd), C.int(cmd), C.uintptr_t(arg)) - val = int(r0) - if r0 == -1 && er != nil { - err = er - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Fdatasync(fd int) (err error) { r0, er := C.fdatasync(C.int(fd)) if r0 == -1 && er != nil { @@ -477,7 +451,7 @@ func Getsid(pid int) (sid int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Kill(pid int, sig syscall.Signal) (err error) { +func Kill(pid int, sig Signal) (err error) { r0, er := C.kill(C.int(pid), C.int(sig)) if r0 == -1 && er != nil { err = er @@ -628,18 +602,6 @@ func Readlink(path string, buf []byte) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Removexattr(path string, attr string) (err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - _p1 := uintptr(unsafe.Pointer(C.CString(attr))) - r0, er := C.removexattr(C.uintptr_t(_p0), C.uintptr_t(_p1)) - if r0 == -1 && er != nil { - err = er - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) { _p0 := uintptr(unsafe.Pointer(C.CString(oldpath))) _p1 := uintptr(unsafe.Pointer(C.CString(newpath))) @@ -763,17 +725,6 @@ func Sync() { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { - r0, er := C.tee(C.int(rfd), C.int(wfd), C.int(len), C.int(flags)) - n = int64(r0) - if r0 == -1 && er != nil { - err = er - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Times(tms *Tms) (ticks uintptr, err error) { r0, er := C.times(C.uintptr_t(uintptr(unsafe.Pointer(tms)))) ticks = uintptr(r0) @@ -825,16 +776,6 @@ func Unlinkat(dirfd int, path string, flags int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Unshare(flags int) (err error) { - r0, er := C.unshare(C.int(flags)) - if r0 == -1 && er != nil { - err = er - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Ustat(dev int, ubuf *Ustat_t) (err error) { r0, er := C.ustat(C.int(dev), C.uintptr_t(uintptr(unsafe.Pointer(ubuf)))) if r0 == -1 && er != nil { @@ -1425,16 +1366,6 @@ func pipe(p *[2]_C_int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe2(p *[2]_C_int, flags int) (err error) { - r0, er := C.pipe2(C.uintptr_t(uintptr(unsafe.Pointer(p))), C.int(flags)) - if r0 == -1 && er != nil { - err = er - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { r0, er := C.poll(C.uintptr_t(uintptr(unsafe.Pointer(fds))), C.int(nfds), C.int(timeout)) n = int(r0) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64.go b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64.go index 2e4f93fb1..3e929e520 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64.go @@ -1,147 +1,25 @@ -// mksyscall_aix.pl -aix -tags aix,ppc64 syscall_aix.go syscall_aix_ppc64.go +// mksyscall_aix_ppc64.pl -aix -tags aix,ppc64 syscall_aix.go syscall_aix_ppc64.go // Code generated by the command above; see README.md. DO NOT EDIT. // +build aix,ppc64 package unix -/* -#include -int utimes(uintptr_t, uintptr_t); -int utimensat(int, uintptr_t, uintptr_t, int); -int getcwd(uintptr_t, size_t); -int accept(int, uintptr_t, uintptr_t); -int getdirent(int, uintptr_t, size_t); -int wait4(int, uintptr_t, int, uintptr_t); -int ioctl(int, int, uintptr_t); -int fcntl(uintptr_t, int, uintptr_t); -int acct(uintptr_t); -int chdir(uintptr_t); -int chroot(uintptr_t); -int close(int); -int dup(int); -int dup3(int, int, int); -void exit(int); -int faccessat(int, uintptr_t, unsigned int, int); -int fallocate(int, unsigned int, long long, long long); -int fchdir(int); -int fchmod(int, unsigned int); -int fchmodat(int, uintptr_t, unsigned int, int); -int fchownat(int, uintptr_t, int, int, int); -int fdatasync(int); -int fsync(int); -int getpgid(int); -int getpgrp(); -int getpid(); -int getppid(); -int getpriority(int, int); -int getrusage(int, uintptr_t); -int getsid(int); -int kill(int, int); -int syslog(int, uintptr_t, size_t); -int mkdir(int, uintptr_t, unsigned int); -int mkdirat(int, uintptr_t, unsigned int); -int mkfifo(uintptr_t, unsigned int); -int mknod(uintptr_t, unsigned int, int); -int mknodat(int, uintptr_t, unsigned int, int); -int nanosleep(uintptr_t, uintptr_t); -int open64(uintptr_t, int, unsigned int); -int openat(int, uintptr_t, int, unsigned int); -int read(int, uintptr_t, size_t); -int readlink(uintptr_t, uintptr_t, size_t); -int removexattr(uintptr_t, uintptr_t); -int renameat(int, uintptr_t, int, uintptr_t); -int setdomainname(uintptr_t, size_t); -int sethostname(uintptr_t, size_t); -int setpgid(int, int); -int setsid(); -int settimeofday(uintptr_t); -int setuid(int); -int setgid(int); -int setpriority(int, int, int); -int statx(int, uintptr_t, int, int, uintptr_t); -int sync(); -long long tee(int, int, int, int); -uintptr_t times(uintptr_t); -int umask(int); -int uname(uintptr_t); -int unlink(uintptr_t); -int unlinkat(int, uintptr_t, int); -int unshare(int); -int ustat(int, uintptr_t); -int write(int, uintptr_t, size_t); -int dup2(int, int); -int posix_fadvise64(int, long long, long long, int); -int fchown(int, int, int); -int fstat(int, uintptr_t); -int fstatat(int, uintptr_t, uintptr_t, int); -int fstatfs(int, uintptr_t); -int ftruncate(int, long long); -int getegid(); -int geteuid(); -int getgid(); -int getuid(); -int lchown(uintptr_t, int, int); -int listen(int, int); -int lstat(uintptr_t, uintptr_t); -int pause(); -int pread64(int, uintptr_t, size_t, long long); -int pwrite64(int, uintptr_t, size_t, long long); -int pselect(int, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); -int setregid(int, int); -int setreuid(int, int); -int shutdown(int, int); -long long splice(int, uintptr_t, int, uintptr_t, int, int); -int stat(uintptr_t, uintptr_t); -int statfs(uintptr_t, uintptr_t); -int truncate(uintptr_t, long long); -int bind(int, uintptr_t, uintptr_t); -int connect(int, uintptr_t, uintptr_t); -int getgroups(int, uintptr_t); -int setgroups(int, uintptr_t); -int getsockopt(int, int, int, uintptr_t, uintptr_t); -int setsockopt(int, int, int, uintptr_t, uintptr_t); -int socket(int, int, int); -int socketpair(int, int, int, uintptr_t); -int getpeername(int, uintptr_t, uintptr_t); -int getsockname(int, uintptr_t, uintptr_t); -int recvfrom(int, uintptr_t, size_t, int, uintptr_t, uintptr_t); -int sendto(int, uintptr_t, size_t, int, uintptr_t, uintptr_t); -int recvmsg(int, uintptr_t, int); -int sendmsg(int, uintptr_t, int); -int munmap(uintptr_t, uintptr_t); -int madvise(uintptr_t, size_t, int); -int mprotect(uintptr_t, size_t, int); -int mlock(uintptr_t, size_t); -int mlockall(int); -int msync(uintptr_t, size_t, int); -int munlock(uintptr_t, size_t); -int munlockall(); -int pipe(uintptr_t); -int pipe2(uintptr_t, int); -int poll(uintptr_t, int, int); -int gettimeofday(uintptr_t, uintptr_t); -int time(uintptr_t); -int utime(uintptr_t, uintptr_t); -int getrlimit(int, uintptr_t); -int setrlimit(int, uintptr_t); -long long lseek(int, long long, int); -uintptr_t mmap64(uintptr_t, uintptr_t, int, int, int, long long); - -*/ -import "C" import ( - "syscall" "unsafe" ) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func utimes(path string, times *[2]Timeval) (err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - r0, er := C.utimes(C.uintptr_t(_p0), C.uintptr_t(uintptr(unsafe.Pointer(times)))) - if r0 == -1 && er != nil { - err = er + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, e1 := callutimes(uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times))) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -149,10 +27,14 @@ func utimes(path string, times *[2]Timeval) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func utimensat(dirfd int, path string, times *[2]Timespec, flag int) (err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - r0, er := C.utimensat(C.int(dirfd), C.uintptr_t(_p0), C.uintptr_t(uintptr(unsafe.Pointer(times))), C.int(flag)) - if r0 == -1 && er != nil { - err = er + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, e1 := callutimensat(dirfd, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), flag) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -164,11 +46,9 @@ func getcwd(buf []byte) (err error) { if len(buf) > 0 { _p0 = &buf[0] } - var _p1 int - _p1 = len(buf) - r0, er := C.getcwd(C.uintptr_t(uintptr(unsafe.Pointer(_p0))), C.size_t(_p1)) - if r0 == -1 && er != nil { - err = er + _, e1 := callgetcwd(uintptr(unsafe.Pointer(_p0)), len(buf)) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -176,10 +56,10 @@ func getcwd(buf []byte) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, er := C.accept(C.int(s), C.uintptr_t(uintptr(unsafe.Pointer(rsa))), C.uintptr_t(uintptr(unsafe.Pointer(addrlen)))) + r0, e1 := callaccept(s, uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) fd = int(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -191,12 +71,10 @@ func getdirent(fd int, buf []byte) (n int, err error) { if len(buf) > 0 { _p0 = &buf[0] } - var _p1 int - _p1 = len(buf) - r0, er := C.getdirent(C.int(fd), C.uintptr_t(uintptr(unsafe.Pointer(_p0))), C.size_t(_p1)) + r0, e1 := callgetdirent(fd, uintptr(unsafe.Pointer(_p0)), len(buf)) n = int(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -204,10 +82,10 @@ func getdirent(fd int, buf []byte) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func wait4(pid Pid_t, status *_C_int, options int, rusage *Rusage) (wpid Pid_t, err error) { - r0, er := C.wait4(C.int(pid), C.uintptr_t(uintptr(unsafe.Pointer(status))), C.int(options), C.uintptr_t(uintptr(unsafe.Pointer(rusage)))) + r0, e1 := callwait4(int(pid), uintptr(unsafe.Pointer(status)), options, uintptr(unsafe.Pointer(rusage))) wpid = Pid_t(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -215,9 +93,9 @@ func wait4(pid Pid_t, status *_C_int, options int, rusage *Rusage) (wpid Pid_t, // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func ioctl(fd int, req uint, arg uintptr) (err error) { - r0, er := C.ioctl(C.int(fd), C.int(req), C.uintptr_t(arg)) - if r0 == -1 && er != nil { - err = er + _, e1 := callioctl(fd, int(req), arg) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -225,10 +103,10 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func FcntlInt(fd uintptr, cmd int, arg int) (r int, err error) { - r0, er := C.fcntl(C.uintptr_t(fd), C.int(cmd), C.uintptr_t(arg)) + r0, e1 := callfcntl(fd, cmd, uintptr(arg)) r = int(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -236,73 +114,86 @@ func FcntlInt(fd uintptr, cmd int, arg int) (r int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) (err error) { - r0, er := C.fcntl(C.uintptr_t(fd), C.int(cmd), C.uintptr_t(uintptr(unsafe.Pointer(lk)))) - if r0 == -1 && er != nil { - err = er + _, e1 := callfcntl(fd, cmd, uintptr(unsafe.Pointer(lk))) + if e1 != 0 { + err = errnoErr(e1) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Acct(path string) (err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - r0, er := C.acct(C.uintptr_t(_p0)) - if r0 == -1 && er != nil { - err = er +func fcntl(fd int, cmd int, arg int) (val int, err error) { + r0, e1 := callfcntl(uintptr(fd), cmd, uintptr(arg)) + val = int(r0) + if e1 != 0 { + err = errnoErr(e1) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Chdir(path string) (err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - r0, er := C.chdir(C.uintptr_t(_p0)) - if r0 == -1 && er != nil { - err = er +func Acct(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, e1 := callacct(uintptr(unsafe.Pointer(_p0))) + if e1 != 0 { + err = errnoErr(e1) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Chroot(path string) (err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - r0, er := C.chroot(C.uintptr_t(_p0)) - if r0 == -1 && er != nil { - err = er +func Chdir(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, e1 := callchdir(uintptr(unsafe.Pointer(_p0))) + if e1 != 0 { + err = errnoErr(e1) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Close(fd int) (err error) { - r0, er := C.close(C.int(fd)) - if r0 == -1 && er != nil { - err = er +func Chroot(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, e1 := callchroot(uintptr(unsafe.Pointer(_p0))) + if e1 != 0 { + err = errnoErr(e1) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Dup(oldfd int) (fd int, err error) { - r0, er := C.dup(C.int(oldfd)) - fd = int(r0) - if r0 == -1 && er != nil { - err = er +func Close(fd int) (err error) { + _, e1 := callclose(fd) + if e1 != 0 { + err = errnoErr(e1) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Dup3(oldfd int, newfd int, flags int) (err error) { - r0, er := C.dup3(C.int(oldfd), C.int(newfd), C.int(flags)) - if r0 == -1 && er != nil { - err = er +func Dup(oldfd int) (fd int, err error) { + r0, e1 := calldup(oldfd) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -310,27 +201,21 @@ func Dup3(oldfd int, newfd int, flags int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Exit(code int) { - C.exit(C.int(code)) + callexit(code) return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - r0, er := C.faccessat(C.int(dirfd), C.uintptr_t(_p0), C.uint(mode), C.int(flags)) - if r0 == -1 && er != nil { - err = er + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fallocate(fd int, mode uint32, off int64, len int64) (err error) { - r0, er := C.fallocate(C.int(fd), C.uint(mode), C.longlong(off), C.longlong(len)) - if r0 == -1 && er != nil { - err = er + _, e1 := callfaccessat(dirfd, uintptr(unsafe.Pointer(_p0)), mode, flags) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -338,9 +223,9 @@ func Fallocate(fd int, mode uint32, off int64, len int64) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchdir(fd int) (err error) { - r0, er := C.fchdir(C.int(fd)) - if r0 == -1 && er != nil { - err = er + _, e1 := callfchdir(fd) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -348,9 +233,9 @@ func Fchdir(fd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchmod(fd int, mode uint32) (err error) { - r0, er := C.fchmod(C.int(fd), C.uint(mode)) - if r0 == -1 && er != nil { - err = er + _, e1 := callfchmod(fd, mode) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -358,10 +243,14 @@ func Fchmod(fd int, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - r0, er := C.fchmodat(C.int(dirfd), C.uintptr_t(_p0), C.uint(mode), C.int(flags)) - if r0 == -1 && er != nil { - err = er + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, e1 := callfchmodat(dirfd, uintptr(unsafe.Pointer(_p0)), mode, flags) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -369,21 +258,14 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - r0, er := C.fchownat(C.int(dirfd), C.uintptr_t(_p0), C.int(uid), C.int(gid), C.int(flags)) - if r0 == -1 && er != nil { - err = er + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fcntl(fd int, cmd int, arg int) (val int, err error) { - r0, er := C.fcntl(C.uintptr_t(fd), C.int(cmd), C.uintptr_t(arg)) - val = int(r0) - if r0 == -1 && er != nil { - err = er + _, e1 := callfchownat(dirfd, uintptr(unsafe.Pointer(_p0)), uid, gid, flags) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -391,9 +273,9 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fdatasync(fd int) (err error) { - r0, er := C.fdatasync(C.int(fd)) - if r0 == -1 && er != nil { - err = er + _, e1 := callfdatasync(fd) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -401,9 +283,9 @@ func Fdatasync(fd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fsync(fd int) (err error) { - r0, er := C.fsync(C.int(fd)) - if r0 == -1 && er != nil { - err = er + _, e1 := callfsync(fd) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -411,10 +293,10 @@ func Fsync(fd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpgid(pid int) (pgid int, err error) { - r0, er := C.getpgid(C.int(pid)) + r0, e1 := callgetpgid(pid) pgid = int(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -422,7 +304,7 @@ func Getpgid(pid int) (pgid int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpgrp() (pid int) { - r0, _ := C.getpgrp() + r0, _ := callgetpgrp() pid = int(r0) return } @@ -430,7 +312,7 @@ func Getpgrp() (pid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpid() (pid int) { - r0, _ := C.getpid() + r0, _ := callgetpid() pid = int(r0) return } @@ -438,7 +320,7 @@ func Getpid() (pid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getppid() (ppid int) { - r0, _ := C.getppid() + r0, _ := callgetppid() ppid = int(r0) return } @@ -446,10 +328,10 @@ func Getppid() (ppid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpriority(which int, who int) (prio int, err error) { - r0, er := C.getpriority(C.int(which), C.int(who)) + r0, e1 := callgetpriority(which, who) prio = int(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -457,9 +339,9 @@ func Getpriority(which int, who int) (prio int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getrusage(who int, rusage *Rusage) (err error) { - r0, er := C.getrusage(C.int(who), C.uintptr_t(uintptr(unsafe.Pointer(rusage)))) - if r0 == -1 && er != nil { - err = er + _, e1 := callgetrusage(who, uintptr(unsafe.Pointer(rusage))) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -467,20 +349,20 @@ func Getrusage(who int, rusage *Rusage) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getsid(pid int) (sid int, err error) { - r0, er := C.getsid(C.int(pid)) + r0, e1 := callgetsid(pid) sid = int(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Kill(pid int, sig syscall.Signal) (err error) { - r0, er := C.kill(C.int(pid), C.int(sig)) - if r0 == -1 && er != nil { - err = er +func Kill(pid int, sig Signal) (err error) { + _, e1 := callkill(pid, int(sig)) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -492,12 +374,10 @@ func Klogctl(typ int, buf []byte) (n int, err error) { if len(buf) > 0 { _p0 = &buf[0] } - var _p1 int - _p1 = len(buf) - r0, er := C.syslog(C.int(typ), C.uintptr_t(uintptr(unsafe.Pointer(_p0))), C.size_t(_p1)) + r0, e1 := callsyslog(typ, uintptr(unsafe.Pointer(_p0)), len(buf)) n = int(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -505,10 +385,14 @@ func Klogctl(typ int, buf []byte) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mkdir(dirfd int, path string, mode uint32) (err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - r0, er := C.mkdir(C.int(dirfd), C.uintptr_t(_p0), C.uint(mode)) - if r0 == -1 && er != nil { - err = er + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, e1 := callmkdir(dirfd, uintptr(unsafe.Pointer(_p0)), mode) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -516,10 +400,14 @@ func Mkdir(dirfd int, path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mkdirat(dirfd int, path string, mode uint32) (err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - r0, er := C.mkdirat(C.int(dirfd), C.uintptr_t(_p0), C.uint(mode)) - if r0 == -1 && er != nil { - err = er + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, e1 := callmkdirat(dirfd, uintptr(unsafe.Pointer(_p0)), mode) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -527,10 +415,14 @@ func Mkdirat(dirfd int, path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mkfifo(path string, mode uint32) (err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - r0, er := C.mkfifo(C.uintptr_t(_p0), C.uint(mode)) - if r0 == -1 && er != nil { - err = er + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, e1 := callmkfifo(uintptr(unsafe.Pointer(_p0)), mode) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -538,10 +430,14 @@ func Mkfifo(path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mknod(path string, mode uint32, dev int) (err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - r0, er := C.mknod(C.uintptr_t(_p0), C.uint(mode), C.int(dev)) - if r0 == -1 && er != nil { - err = er + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, e1 := callmknod(uintptr(unsafe.Pointer(_p0)), mode, dev) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -549,10 +445,14 @@ func Mknod(path string, mode uint32, dev int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - r0, er := C.mknodat(C.int(dirfd), C.uintptr_t(_p0), C.uint(mode), C.int(dev)) - if r0 == -1 && er != nil { - err = er + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, e1 := callmknodat(dirfd, uintptr(unsafe.Pointer(_p0)), mode, dev) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -560,9 +460,9 @@ func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Nanosleep(time *Timespec, leftover *Timespec) (err error) { - r0, er := C.nanosleep(C.uintptr_t(uintptr(unsafe.Pointer(time))), C.uintptr_t(uintptr(unsafe.Pointer(leftover)))) - if r0 == -1 && er != nil { - err = er + _, e1 := callnanosleep(uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover))) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -570,11 +470,15 @@ func Nanosleep(time *Timespec, leftover *Timespec) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Open(path string, mode int, perm uint32) (fd int, err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - r0, er := C.open64(C.uintptr_t(_p0), C.int(mode), C.uint(perm)) + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, e1 := callopen64(uintptr(unsafe.Pointer(_p0)), mode, perm) fd = int(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -582,11 +486,15 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - r0, er := C.openat(C.int(dirfd), C.uintptr_t(_p0), C.int(flags), C.uint(mode)) + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, e1 := callopenat(dirfd, uintptr(unsafe.Pointer(_p0)), flags, mode) fd = int(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -598,12 +506,10 @@ func read(fd int, p []byte) (n int, err error) { if len(p) > 0 { _p0 = &p[0] } - var _p1 int - _p1 = len(p) - r0, er := C.read(C.int(fd), C.uintptr_t(uintptr(unsafe.Pointer(_p0))), C.size_t(_p1)) + r0, e1 := callread(fd, uintptr(unsafe.Pointer(_p0)), len(p)) n = int(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -611,29 +517,19 @@ func read(fd int, p []byte) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Readlink(path string, buf []byte) (n int, err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } var _p1 *byte if len(buf) > 0 { _p1 = &buf[0] } - var _p2 int - _p2 = len(buf) - r0, er := C.readlink(C.uintptr_t(_p0), C.uintptr_t(uintptr(unsafe.Pointer(_p1))), C.size_t(_p2)) + r0, e1 := callreadlink(uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), len(buf)) n = int(r0) - if r0 == -1 && er != nil { - err = er - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Removexattr(path string, attr string) (err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - _p1 := uintptr(unsafe.Pointer(C.CString(attr))) - r0, er := C.removexattr(C.uintptr_t(_p0), C.uintptr_t(_p1)) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -641,11 +537,19 @@ func Removexattr(path string, attr string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(oldpath))) - _p1 := uintptr(unsafe.Pointer(C.CString(newpath))) - r0, er := C.renameat(C.int(olddirfd), C.uintptr_t(_p0), C.int(newdirfd), C.uintptr_t(_p1)) - if r0 == -1 && er != nil { - err = er + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + _, e1 := callrenameat(olddirfd, uintptr(unsafe.Pointer(_p0)), newdirfd, uintptr(unsafe.Pointer(_p1))) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -657,11 +561,9 @@ func Setdomainname(p []byte) (err error) { if len(p) > 0 { _p0 = &p[0] } - var _p1 int - _p1 = len(p) - r0, er := C.setdomainname(C.uintptr_t(uintptr(unsafe.Pointer(_p0))), C.size_t(_p1)) - if r0 == -1 && er != nil { - err = er + _, e1 := callsetdomainname(uintptr(unsafe.Pointer(_p0)), len(p)) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -673,11 +575,9 @@ func Sethostname(p []byte) (err error) { if len(p) > 0 { _p0 = &p[0] } - var _p1 int - _p1 = len(p) - r0, er := C.sethostname(C.uintptr_t(uintptr(unsafe.Pointer(_p0))), C.size_t(_p1)) - if r0 == -1 && er != nil { - err = er + _, e1 := callsethostname(uintptr(unsafe.Pointer(_p0)), len(p)) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -685,9 +585,9 @@ func Sethostname(p []byte) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setpgid(pid int, pgid int) (err error) { - r0, er := C.setpgid(C.int(pid), C.int(pgid)) - if r0 == -1 && er != nil { - err = er + _, e1 := callsetpgid(pid, pgid) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -695,10 +595,10 @@ func Setpgid(pid int, pgid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setsid() (pid int, err error) { - r0, er := C.setsid() + r0, e1 := callsetsid() pid = int(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -706,9 +606,9 @@ func Setsid() (pid int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Settimeofday(tv *Timeval) (err error) { - r0, er := C.settimeofday(C.uintptr_t(uintptr(unsafe.Pointer(tv)))) - if r0 == -1 && er != nil { - err = er + _, e1 := callsettimeofday(uintptr(unsafe.Pointer(tv))) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -716,9 +616,9 @@ func Settimeofday(tv *Timeval) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setuid(uid int) (err error) { - r0, er := C.setuid(C.int(uid)) - if r0 == -1 && er != nil { - err = er + _, e1 := callsetuid(uid) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -726,9 +626,9 @@ func Setuid(uid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setgid(uid int) (err error) { - r0, er := C.setgid(C.int(uid)) - if r0 == -1 && er != nil { - err = er + _, e1 := callsetgid(uid) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -736,9 +636,9 @@ func Setgid(uid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setpriority(which int, who int, prio int) (err error) { - r0, er := C.setpriority(C.int(which), C.int(who), C.int(prio)) - if r0 == -1 && er != nil { - err = er + _, e1 := callsetpriority(which, who, prio) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -746,10 +646,14 @@ func Setpriority(which int, who int, prio int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - r0, er := C.statx(C.int(dirfd), C.uintptr_t(_p0), C.int(flags), C.int(mask), C.uintptr_t(uintptr(unsafe.Pointer(stat)))) - if r0 == -1 && er != nil { - err = er + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, e1 := callstatx(dirfd, uintptr(unsafe.Pointer(_p0)), flags, mask, uintptr(unsafe.Pointer(stat))) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -757,28 +661,17 @@ func Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err erro // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Sync() { - C.sync() - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { - r0, er := C.tee(C.int(rfd), C.int(wfd), C.int(len), C.int(flags)) - n = int64(r0) - if r0 == -1 && er != nil { - err = er - } + callsync() return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Times(tms *Tms) (ticks uintptr, err error) { - r0, er := C.times(C.uintptr_t(uintptr(unsafe.Pointer(tms)))) + r0, e1 := calltimes(uintptr(unsafe.Pointer(tms))) ticks = uintptr(r0) - if uintptr(r0) == ^uintptr(0) && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -786,7 +679,7 @@ func Times(tms *Tms) (ticks uintptr, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Umask(mask int) (oldmask int) { - r0, _ := C.umask(C.int(mask)) + r0, _ := callumask(mask) oldmask = int(r0) return } @@ -794,9 +687,9 @@ func Umask(mask int) (oldmask int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Uname(buf *Utsname) (err error) { - r0, er := C.uname(C.uintptr_t(uintptr(unsafe.Pointer(buf)))) - if r0 == -1 && er != nil { - err = er + _, e1 := calluname(uintptr(unsafe.Pointer(buf))) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -804,10 +697,14 @@ func Uname(buf *Utsname) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Unlink(path string) (err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - r0, er := C.unlink(C.uintptr_t(_p0)) - if r0 == -1 && er != nil { - err = er + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, e1 := callunlink(uintptr(unsafe.Pointer(_p0))) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -815,20 +712,14 @@ func Unlink(path string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Unlinkat(dirfd int, path string, flags int) (err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - r0, er := C.unlinkat(C.int(dirfd), C.uintptr_t(_p0), C.int(flags)) - if r0 == -1 && er != nil { - err = er + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Unshare(flags int) (err error) { - r0, er := C.unshare(C.int(flags)) - if r0 == -1 && er != nil { - err = er + _, e1 := callunlinkat(dirfd, uintptr(unsafe.Pointer(_p0)), flags) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -836,9 +727,9 @@ func Unshare(flags int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Ustat(dev int, ubuf *Ustat_t) (err error) { - r0, er := C.ustat(C.int(dev), C.uintptr_t(uintptr(unsafe.Pointer(ubuf)))) - if r0 == -1 && er != nil { - err = er + _, e1 := callustat(dev, uintptr(unsafe.Pointer(ubuf))) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -850,12 +741,10 @@ func write(fd int, p []byte) (n int, err error) { if len(p) > 0 { _p0 = &p[0] } - var _p1 int - _p1 = len(p) - r0, er := C.write(C.int(fd), C.uintptr_t(uintptr(unsafe.Pointer(_p0))), C.size_t(_p1)) + r0, e1 := callwrite(fd, uintptr(unsafe.Pointer(_p0)), len(p)) n = int(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -863,10 +752,10 @@ func write(fd int, p []byte) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func readlen(fd int, p *byte, np int) (n int, err error) { - r0, er := C.read(C.int(fd), C.uintptr_t(uintptr(unsafe.Pointer(p))), C.size_t(np)) + r0, e1 := callread(fd, uintptr(unsafe.Pointer(p)), np) n = int(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -874,10 +763,10 @@ func readlen(fd int, p *byte, np int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func writelen(fd int, p *byte, np int) (n int, err error) { - r0, er := C.write(C.int(fd), C.uintptr_t(uintptr(unsafe.Pointer(p))), C.size_t(np)) + r0, e1 := callwrite(fd, uintptr(unsafe.Pointer(p)), np) n = int(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -885,9 +774,9 @@ func writelen(fd int, p *byte, np int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Dup2(oldfd int, newfd int) (err error) { - r0, er := C.dup2(C.int(oldfd), C.int(newfd)) - if r0 == -1 && er != nil { - err = er + _, e1 := calldup2(oldfd, newfd) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -895,9 +784,9 @@ func Dup2(oldfd int, newfd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fadvise(fd int, offset int64, length int64, advice int) (err error) { - r0, er := C.posix_fadvise64(C.int(fd), C.longlong(offset), C.longlong(length), C.int(advice)) - if r0 == -1 && er != nil { - err = er + _, e1 := callposix_fadvise64(fd, offset, length, advice) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -905,9 +794,9 @@ func Fadvise(fd int, offset int64, length int64, advice int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchown(fd int, uid int, gid int) (err error) { - r0, er := C.fchown(C.int(fd), C.int(uid), C.int(gid)) - if r0 == -1 && er != nil { - err = er + _, e1 := callfchown(fd, uid, gid) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -915,9 +804,9 @@ func Fchown(fd int, uid int, gid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fstat(fd int, stat *Stat_t) (err error) { - r0, er := C.fstat(C.int(fd), C.uintptr_t(uintptr(unsafe.Pointer(stat)))) - if r0 == -1 && er != nil { - err = er + _, e1 := callfstat(fd, uintptr(unsafe.Pointer(stat))) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -925,10 +814,14 @@ func Fstat(fd int, stat *Stat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - r0, er := C.fstatat(C.int(dirfd), C.uintptr_t(_p0), C.uintptr_t(uintptr(unsafe.Pointer(stat))), C.int(flags)) - if r0 == -1 && er != nil { - err = er + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, e1 := callfstatat(dirfd, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), flags) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -936,9 +829,9 @@ func Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fstatfs(fd int, buf *Statfs_t) (err error) { - r0, er := C.fstatfs(C.int(fd), C.uintptr_t(uintptr(unsafe.Pointer(buf)))) - if r0 == -1 && er != nil { - err = er + _, e1 := callfstatfs(fd, uintptr(unsafe.Pointer(buf))) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -946,9 +839,9 @@ func Fstatfs(fd int, buf *Statfs_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Ftruncate(fd int, length int64) (err error) { - r0, er := C.ftruncate(C.int(fd), C.longlong(length)) - if r0 == -1 && er != nil { - err = er + _, e1 := callftruncate(fd, length) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -956,7 +849,7 @@ func Ftruncate(fd int, length int64) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getegid() (egid int) { - r0, _ := C.getegid() + r0, _ := callgetegid() egid = int(r0) return } @@ -964,7 +857,7 @@ func Getegid() (egid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Geteuid() (euid int) { - r0, _ := C.geteuid() + r0, _ := callgeteuid() euid = int(r0) return } @@ -972,7 +865,7 @@ func Geteuid() (euid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getgid() (gid int) { - r0, _ := C.getgid() + r0, _ := callgetgid() gid = int(r0) return } @@ -980,7 +873,7 @@ func Getgid() (gid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getuid() (uid int) { - r0, _ := C.getuid() + r0, _ := callgetuid() uid = int(r0) return } @@ -988,10 +881,14 @@ func Getuid() (uid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Lchown(path string, uid int, gid int) (err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - r0, er := C.lchown(C.uintptr_t(_p0), C.int(uid), C.int(gid)) - if r0 == -1 && er != nil { - err = er + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, e1 := calllchown(uintptr(unsafe.Pointer(_p0)), uid, gid) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -999,9 +896,9 @@ func Lchown(path string, uid int, gid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Listen(s int, n int) (err error) { - r0, er := C.listen(C.int(s), C.int(n)) - if r0 == -1 && er != nil { - err = er + _, e1 := calllisten(s, n) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1009,10 +906,14 @@ func Listen(s int, n int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Lstat(path string, stat *Stat_t) (err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - r0, er := C.lstat(C.uintptr_t(_p0), C.uintptr_t(uintptr(unsafe.Pointer(stat)))) - if r0 == -1 && er != nil { - err = er + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, e1 := calllstat(uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat))) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1020,9 +921,9 @@ func Lstat(path string, stat *Stat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Pause() (err error) { - r0, er := C.pause() - if r0 == -1 && er != nil { - err = er + _, e1 := callpause() + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1034,12 +935,10 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { if len(p) > 0 { _p0 = &p[0] } - var _p1 int - _p1 = len(p) - r0, er := C.pread64(C.int(fd), C.uintptr_t(uintptr(unsafe.Pointer(_p0))), C.size_t(_p1), C.longlong(offset)) + r0, e1 := callpread64(fd, uintptr(unsafe.Pointer(_p0)), len(p), offset) n = int(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1051,12 +950,10 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) { if len(p) > 0 { _p0 = &p[0] } - var _p1 int - _p1 = len(p) - r0, er := C.pwrite64(C.int(fd), C.uintptr_t(uintptr(unsafe.Pointer(_p0))), C.size_t(_p1), C.longlong(offset)) + r0, e1 := callpwrite64(fd, uintptr(unsafe.Pointer(_p0)), len(p), offset) n = int(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1064,10 +961,10 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { - r0, er := C.pselect(C.int(nfd), C.uintptr_t(uintptr(unsafe.Pointer(r))), C.uintptr_t(uintptr(unsafe.Pointer(w))), C.uintptr_t(uintptr(unsafe.Pointer(e))), C.uintptr_t(uintptr(unsafe.Pointer(timeout))), C.uintptr_t(uintptr(unsafe.Pointer(sigmask)))) + r0, e1 := callpselect(nfd, uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask))) n = int(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1075,9 +972,9 @@ func Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask * // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setregid(rgid int, egid int) (err error) { - r0, er := C.setregid(C.int(rgid), C.int(egid)) - if r0 == -1 && er != nil { - err = er + _, e1 := callsetregid(rgid, egid) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1085,9 +982,9 @@ func Setregid(rgid int, egid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setreuid(ruid int, euid int) (err error) { - r0, er := C.setreuid(C.int(ruid), C.int(euid)) - if r0 == -1 && er != nil { - err = er + _, e1 := callsetreuid(ruid, euid) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1095,9 +992,9 @@ func Setreuid(ruid int, euid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Shutdown(fd int, how int) (err error) { - r0, er := C.shutdown(C.int(fd), C.int(how)) - if r0 == -1 && er != nil { - err = er + _, e1 := callshutdown(fd, how) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1105,10 +1002,10 @@ func Shutdown(fd int, how int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) { - r0, er := C.splice(C.int(rfd), C.uintptr_t(uintptr(unsafe.Pointer(roff))), C.int(wfd), C.uintptr_t(uintptr(unsafe.Pointer(woff))), C.int(len), C.int(flags)) + r0, e1 := callsplice(rfd, uintptr(unsafe.Pointer(roff)), wfd, uintptr(unsafe.Pointer(woff)), len, flags) n = int64(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1116,10 +1013,14 @@ func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n i // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Stat(path string, stat *Stat_t) (err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - r0, er := C.stat(C.uintptr_t(_p0), C.uintptr_t(uintptr(unsafe.Pointer(stat)))) - if r0 == -1 && er != nil { - err = er + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, e1 := callstat(uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat))) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1127,10 +1028,14 @@ func Stat(path string, stat *Stat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Statfs(path string, buf *Statfs_t) (err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - r0, er := C.statfs(C.uintptr_t(_p0), C.uintptr_t(uintptr(unsafe.Pointer(buf)))) - if r0 == -1 && er != nil { - err = er + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, e1 := callstatfs(uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf))) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1138,10 +1043,14 @@ func Statfs(path string, buf *Statfs_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Truncate(path string, length int64) (err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - r0, er := C.truncate(C.uintptr_t(_p0), C.longlong(length)) - if r0 == -1 && er != nil { - err = er + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, e1 := calltruncate(uintptr(unsafe.Pointer(_p0)), length) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1149,9 +1058,9 @@ func Truncate(path string, length int64) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - r0, er := C.bind(C.int(s), C.uintptr_t(uintptr(addr)), C.uintptr_t(uintptr(addrlen))) - if r0 == -1 && er != nil { - err = er + _, e1 := callbind(s, uintptr(addr), uintptr(addrlen)) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1159,9 +1068,9 @@ func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - r0, er := C.connect(C.int(s), C.uintptr_t(uintptr(addr)), C.uintptr_t(uintptr(addrlen))) - if r0 == -1 && er != nil { - err = er + _, e1 := callconnect(s, uintptr(addr), uintptr(addrlen)) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1169,10 +1078,10 @@ func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getgroups(n int, list *_Gid_t) (nn int, err error) { - r0, er := C.getgroups(C.int(n), C.uintptr_t(uintptr(unsafe.Pointer(list)))) + r0, e1 := callgetgroups(n, uintptr(unsafe.Pointer(list))) nn = int(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1180,9 +1089,9 @@ func getgroups(n int, list *_Gid_t) (nn int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func setgroups(n int, list *_Gid_t) (err error) { - r0, er := C.setgroups(C.int(n), C.uintptr_t(uintptr(unsafe.Pointer(list)))) - if r0 == -1 && er != nil { - err = er + _, e1 := callsetgroups(n, uintptr(unsafe.Pointer(list))) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1190,9 +1099,9 @@ func setgroups(n int, list *_Gid_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) { - r0, er := C.getsockopt(C.int(s), C.int(level), C.int(name), C.uintptr_t(uintptr(val)), C.uintptr_t(uintptr(unsafe.Pointer(vallen)))) - if r0 == -1 && er != nil { - err = er + _, e1 := callgetsockopt(s, level, name, uintptr(val), uintptr(unsafe.Pointer(vallen))) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1200,9 +1109,9 @@ func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) { - r0, er := C.setsockopt(C.int(s), C.int(level), C.int(name), C.uintptr_t(uintptr(val)), C.uintptr_t(vallen)) - if r0 == -1 && er != nil { - err = er + _, e1 := callsetsockopt(s, level, name, uintptr(val), vallen) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1210,10 +1119,10 @@ func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func socket(domain int, typ int, proto int) (fd int, err error) { - r0, er := C.socket(C.int(domain), C.int(typ), C.int(proto)) + r0, e1 := callsocket(domain, typ, proto) fd = int(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1221,9 +1130,9 @@ func socket(domain int, typ int, proto int) (fd int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { - r0, er := C.socketpair(C.int(domain), C.int(typ), C.int(proto), C.uintptr_t(uintptr(unsafe.Pointer(fd)))) - if r0 == -1 && er != nil { - err = er + _, e1 := callsocketpair(domain, typ, proto, uintptr(unsafe.Pointer(fd))) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1231,9 +1140,9 @@ func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - r0, er := C.getpeername(C.int(fd), C.uintptr_t(uintptr(unsafe.Pointer(rsa))), C.uintptr_t(uintptr(unsafe.Pointer(addrlen)))) - if r0 == -1 && er != nil { - err = er + _, e1 := callgetpeername(fd, uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1241,9 +1150,9 @@ func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - r0, er := C.getsockname(C.int(fd), C.uintptr_t(uintptr(unsafe.Pointer(rsa))), C.uintptr_t(uintptr(unsafe.Pointer(addrlen)))) - if r0 == -1 && er != nil { - err = er + _, e1 := callgetsockname(fd, uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1255,12 +1164,10 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl if len(p) > 0 { _p0 = &p[0] } - var _p1 int - _p1 = len(p) - r0, er := C.recvfrom(C.int(fd), C.uintptr_t(uintptr(unsafe.Pointer(_p0))), C.size_t(_p1), C.int(flags), C.uintptr_t(uintptr(unsafe.Pointer(from))), C.uintptr_t(uintptr(unsafe.Pointer(fromlen)))) + r0, e1 := callrecvfrom(fd, uintptr(unsafe.Pointer(_p0)), len(p), flags, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) n = int(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1272,11 +1179,9 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) ( if len(buf) > 0 { _p0 = &buf[0] } - var _p1 int - _p1 = len(buf) - r0, er := C.sendto(C.int(s), C.uintptr_t(uintptr(unsafe.Pointer(_p0))), C.size_t(_p1), C.int(flags), C.uintptr_t(uintptr(to)), C.uintptr_t(uintptr(addrlen))) - if r0 == -1 && er != nil { - err = er + _, e1 := callsendto(s, uintptr(unsafe.Pointer(_p0)), len(buf), flags, uintptr(to), uintptr(addrlen)) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1284,10 +1189,10 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) ( // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, er := C.recvmsg(C.int(s), C.uintptr_t(uintptr(unsafe.Pointer(msg))), C.int(flags)) + r0, e1 := callrecvmsg(s, uintptr(unsafe.Pointer(msg)), flags) n = int(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1295,10 +1200,10 @@ func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, er := C.sendmsg(C.int(s), C.uintptr_t(uintptr(unsafe.Pointer(msg))), C.int(flags)) + r0, e1 := callsendmsg(s, uintptr(unsafe.Pointer(msg)), flags) n = int(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1306,9 +1211,9 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func munmap(addr uintptr, length uintptr) (err error) { - r0, er := C.munmap(C.uintptr_t(addr), C.uintptr_t(length)) - if r0 == -1 && er != nil { - err = er + _, e1 := callmunmap(addr, length) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1320,11 +1225,9 @@ func Madvise(b []byte, advice int) (err error) { if len(b) > 0 { _p0 = &b[0] } - var _p1 int - _p1 = len(b) - r0, er := C.madvise(C.uintptr_t(uintptr(unsafe.Pointer(_p0))), C.size_t(_p1), C.int(advice)) - if r0 == -1 && er != nil { - err = er + _, e1 := callmadvise(uintptr(unsafe.Pointer(_p0)), len(b), advice) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1336,11 +1239,9 @@ func Mprotect(b []byte, prot int) (err error) { if len(b) > 0 { _p0 = &b[0] } - var _p1 int - _p1 = len(b) - r0, er := C.mprotect(C.uintptr_t(uintptr(unsafe.Pointer(_p0))), C.size_t(_p1), C.int(prot)) - if r0 == -1 && er != nil { - err = er + _, e1 := callmprotect(uintptr(unsafe.Pointer(_p0)), len(b), prot) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1352,11 +1253,9 @@ func Mlock(b []byte) (err error) { if len(b) > 0 { _p0 = &b[0] } - var _p1 int - _p1 = len(b) - r0, er := C.mlock(C.uintptr_t(uintptr(unsafe.Pointer(_p0))), C.size_t(_p1)) - if r0 == -1 && er != nil { - err = er + _, e1 := callmlock(uintptr(unsafe.Pointer(_p0)), len(b)) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1364,9 +1263,9 @@ func Mlock(b []byte) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mlockall(flags int) (err error) { - r0, er := C.mlockall(C.int(flags)) - if r0 == -1 && er != nil { - err = er + _, e1 := callmlockall(flags) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1378,11 +1277,9 @@ func Msync(b []byte, flags int) (err error) { if len(b) > 0 { _p0 = &b[0] } - var _p1 int - _p1 = len(b) - r0, er := C.msync(C.uintptr_t(uintptr(unsafe.Pointer(_p0))), C.size_t(_p1), C.int(flags)) - if r0 == -1 && er != nil { - err = er + _, e1 := callmsync(uintptr(unsafe.Pointer(_p0)), len(b), flags) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1394,11 +1291,9 @@ func Munlock(b []byte) (err error) { if len(b) > 0 { _p0 = &b[0] } - var _p1 int - _p1 = len(b) - r0, er := C.munlock(C.uintptr_t(uintptr(unsafe.Pointer(_p0))), C.size_t(_p1)) - if r0 == -1 && er != nil { - err = er + _, e1 := callmunlock(uintptr(unsafe.Pointer(_p0)), len(b)) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1406,9 +1301,9 @@ func Munlock(b []byte) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Munlockall() (err error) { - r0, er := C.munlockall() - if r0 == -1 && er != nil { - err = er + _, e1 := callmunlockall() + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1416,19 +1311,9 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func pipe(p *[2]_C_int) (err error) { - r0, er := C.pipe(C.uintptr_t(uintptr(unsafe.Pointer(p)))) - if r0 == -1 && er != nil { - err = er - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func pipe2(p *[2]_C_int, flags int) (err error) { - r0, er := C.pipe2(C.uintptr_t(uintptr(unsafe.Pointer(p))), C.int(flags)) - if r0 == -1 && er != nil { - err = er + _, e1 := callpipe(uintptr(unsafe.Pointer(p))) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1436,10 +1321,10 @@ func pipe2(p *[2]_C_int, flags int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, er := C.poll(C.uintptr_t(uintptr(unsafe.Pointer(fds))), C.int(nfds), C.int(timeout)) + r0, e1 := callpoll(uintptr(unsafe.Pointer(fds)), nfds, timeout) n = int(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1447,9 +1332,9 @@ func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func gettimeofday(tv *Timeval, tzp *Timezone) (err error) { - r0, er := C.gettimeofday(C.uintptr_t(uintptr(unsafe.Pointer(tv))), C.uintptr_t(uintptr(unsafe.Pointer(tzp)))) - if r0 == -1 && er != nil { - err = er + _, e1 := callgettimeofday(uintptr(unsafe.Pointer(tv)), uintptr(unsafe.Pointer(tzp))) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1457,10 +1342,10 @@ func gettimeofday(tv *Timeval, tzp *Timezone) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Time(t *Time_t) (tt Time_t, err error) { - r0, er := C.time(C.uintptr_t(uintptr(unsafe.Pointer(t)))) + r0, e1 := calltime(uintptr(unsafe.Pointer(t))) tt = Time_t(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1468,10 +1353,14 @@ func Time(t *Time_t) (tt Time_t, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Utime(path string, buf *Utimbuf) (err error) { - _p0 := uintptr(unsafe.Pointer(C.CString(path))) - r0, er := C.utime(C.uintptr_t(_p0), C.uintptr_t(uintptr(unsafe.Pointer(buf)))) - if r0 == -1 && er != nil { - err = er + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, e1 := callutime(uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf))) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1479,9 +1368,9 @@ func Utime(path string, buf *Utimbuf) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getrlimit(resource int, rlim *Rlimit) (err error) { - r0, er := C.getrlimit(C.int(resource), C.uintptr_t(uintptr(unsafe.Pointer(rlim)))) - if r0 == -1 && er != nil { - err = er + _, e1 := callgetrlimit(resource, uintptr(unsafe.Pointer(rlim))) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1489,9 +1378,9 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setrlimit(resource int, rlim *Rlimit) (err error) { - r0, er := C.setrlimit(C.int(resource), C.uintptr_t(uintptr(unsafe.Pointer(rlim)))) - if r0 == -1 && er != nil { - err = er + _, e1 := callsetrlimit(resource, uintptr(unsafe.Pointer(rlim))) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1499,10 +1388,10 @@ func Setrlimit(resource int, rlim *Rlimit) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Seek(fd int, offset int64, whence int) (off int64, err error) { - r0, er := C.lseek(C.int(fd), C.longlong(offset), C.int(whence)) + r0, e1 := calllseek(fd, offset, whence) off = int64(r0) - if r0 == -1 && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1510,10 +1399,10 @@ func Seek(fd int, offset int64, whence int) (off int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) { - r0, er := C.mmap64(C.uintptr_t(addr), C.uintptr_t(length), C.int(prot), C.int(flags), C.int(fd), C.longlong(offset)) + r0, e1 := callmmap64(addr, length, prot, flags, fd, offset) xaddr = uintptr(r0) - if uintptr(r0) == ^uintptr(0) && er != nil { - err = er + if e1 != 0 { + err = errnoErr(e1) } return } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go new file mode 100644 index 000000000..a185ee842 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go @@ -0,0 +1,1162 @@ +// mksyscall_aix_ppc64.pl -aix -tags aix,ppc64 syscall_aix.go syscall_aix_ppc64.go +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build aix,ppc64 +// +build !gccgo + +package unix + +import ( + "unsafe" +) + +//go:cgo_import_dynamic libc_utimes utimes "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_utimensat utimensat "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_getcwd getcwd "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_accept accept "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_getdirent getdirent "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_wait4 wait4 "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_ioctl ioctl "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_fcntl fcntl "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_acct acct "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_chdir chdir "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_chroot chroot "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_close close "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_dup dup "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_exit exit "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_faccessat faccessat "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_fchdir fchdir "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_fchmod fchmod "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_fchmodat fchmodat "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_fchownat fchownat "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_fdatasync fdatasync "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_fsync fsync "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_getpgid getpgid "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_getpgrp getpgrp "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_getpid getpid "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_getppid getppid "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_getpriority getpriority "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_getrusage getrusage "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_getsid getsid "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_kill kill "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_syslog syslog "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_mkdir mkdir "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_mkdirat mkdirat "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_mkfifo mkfifo "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_mknod mknod "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_mknodat mknodat "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_nanosleep nanosleep "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_open64 open64 "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_openat openat "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_read read "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_readlink readlink "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_renameat renameat "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_setdomainname setdomainname "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_sethostname sethostname "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_setpgid setpgid "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_setsid setsid "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_settimeofday settimeofday "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_setuid setuid "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_setgid setgid "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_setpriority setpriority "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_statx statx "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_sync sync "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_times times "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_umask umask "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_uname uname "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_unlink unlink "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_unlinkat unlinkat "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_ustat ustat "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_write write "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_dup2 dup2 "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_posix_fadvise64 posix_fadvise64 "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_fchown fchown "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_fstat fstat "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_fstatat fstatat "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_fstatfs fstatfs "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_ftruncate ftruncate "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_getegid getegid "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_geteuid geteuid "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_getgid getgid "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_getuid getuid "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_lchown lchown "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_listen listen "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_lstat lstat "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_pause pause "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_pread64 pread64 "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_pwrite64 pwrite64 "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_pselect pselect "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_setregid setregid "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_setreuid setreuid "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_shutdown shutdown "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_splice splice "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_stat stat "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_statfs statfs "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_truncate truncate "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_bind bind "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_connect connect "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_getgroups getgroups "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_setgroups setgroups "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_getsockopt getsockopt "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_setsockopt setsockopt "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_socket socket "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_socketpair socketpair "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_getpeername getpeername "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_getsockname getsockname "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_recvfrom recvfrom "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_sendto sendto "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_recvmsg recvmsg "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_sendmsg sendmsg "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_munmap munmap "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_madvise madvise "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_mprotect mprotect "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_mlock mlock "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_mlockall mlockall "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_msync msync "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_munlock munlock "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_munlockall munlockall "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_pipe pipe "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_poll poll "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_gettimeofday gettimeofday "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_time time "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_utime utime "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_getrlimit getrlimit "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_setrlimit setrlimit "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_lseek lseek "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_mmap64 mmap64 "libc.a/shr_64.o" + +//go:linkname libc_utimes libc_utimes +//go:linkname libc_utimensat libc_utimensat +//go:linkname libc_getcwd libc_getcwd +//go:linkname libc_accept libc_accept +//go:linkname libc_getdirent libc_getdirent +//go:linkname libc_wait4 libc_wait4 +//go:linkname libc_ioctl libc_ioctl +//go:linkname libc_fcntl libc_fcntl +//go:linkname libc_acct libc_acct +//go:linkname libc_chdir libc_chdir +//go:linkname libc_chroot libc_chroot +//go:linkname libc_close libc_close +//go:linkname libc_dup libc_dup +//go:linkname libc_exit libc_exit +//go:linkname libc_faccessat libc_faccessat +//go:linkname libc_fchdir libc_fchdir +//go:linkname libc_fchmod libc_fchmod +//go:linkname libc_fchmodat libc_fchmodat +//go:linkname libc_fchownat libc_fchownat +//go:linkname libc_fdatasync libc_fdatasync +//go:linkname libc_fsync libc_fsync +//go:linkname libc_getpgid libc_getpgid +//go:linkname libc_getpgrp libc_getpgrp +//go:linkname libc_getpid libc_getpid +//go:linkname libc_getppid libc_getppid +//go:linkname libc_getpriority libc_getpriority +//go:linkname libc_getrusage libc_getrusage +//go:linkname libc_getsid libc_getsid +//go:linkname libc_kill libc_kill +//go:linkname libc_syslog libc_syslog +//go:linkname libc_mkdir libc_mkdir +//go:linkname libc_mkdirat libc_mkdirat +//go:linkname libc_mkfifo libc_mkfifo +//go:linkname libc_mknod libc_mknod +//go:linkname libc_mknodat libc_mknodat +//go:linkname libc_nanosleep libc_nanosleep +//go:linkname libc_open64 libc_open64 +//go:linkname libc_openat libc_openat +//go:linkname libc_read libc_read +//go:linkname libc_readlink libc_readlink +//go:linkname libc_renameat libc_renameat +//go:linkname libc_setdomainname libc_setdomainname +//go:linkname libc_sethostname libc_sethostname +//go:linkname libc_setpgid libc_setpgid +//go:linkname libc_setsid libc_setsid +//go:linkname libc_settimeofday libc_settimeofday +//go:linkname libc_setuid libc_setuid +//go:linkname libc_setgid libc_setgid +//go:linkname libc_setpriority libc_setpriority +//go:linkname libc_statx libc_statx +//go:linkname libc_sync libc_sync +//go:linkname libc_times libc_times +//go:linkname libc_umask libc_umask +//go:linkname libc_uname libc_uname +//go:linkname libc_unlink libc_unlink +//go:linkname libc_unlinkat libc_unlinkat +//go:linkname libc_ustat libc_ustat +//go:linkname libc_write libc_write +//go:linkname libc_dup2 libc_dup2 +//go:linkname libc_posix_fadvise64 libc_posix_fadvise64 +//go:linkname libc_fchown libc_fchown +//go:linkname libc_fstat libc_fstat +//go:linkname libc_fstatat libc_fstatat +//go:linkname libc_fstatfs libc_fstatfs +//go:linkname libc_ftruncate libc_ftruncate +//go:linkname libc_getegid libc_getegid +//go:linkname libc_geteuid libc_geteuid +//go:linkname libc_getgid libc_getgid +//go:linkname libc_getuid libc_getuid +//go:linkname libc_lchown libc_lchown +//go:linkname libc_listen libc_listen +//go:linkname libc_lstat libc_lstat +//go:linkname libc_pause libc_pause +//go:linkname libc_pread64 libc_pread64 +//go:linkname libc_pwrite64 libc_pwrite64 +//go:linkname libc_pselect libc_pselect +//go:linkname libc_setregid libc_setregid +//go:linkname libc_setreuid libc_setreuid +//go:linkname libc_shutdown libc_shutdown +//go:linkname libc_splice libc_splice +//go:linkname libc_stat libc_stat +//go:linkname libc_statfs libc_statfs +//go:linkname libc_truncate libc_truncate +//go:linkname libc_bind libc_bind +//go:linkname libc_connect libc_connect +//go:linkname libc_getgroups libc_getgroups +//go:linkname libc_setgroups libc_setgroups +//go:linkname libc_getsockopt libc_getsockopt +//go:linkname libc_setsockopt libc_setsockopt +//go:linkname libc_socket libc_socket +//go:linkname libc_socketpair libc_socketpair +//go:linkname libc_getpeername libc_getpeername +//go:linkname libc_getsockname libc_getsockname +//go:linkname libc_recvfrom libc_recvfrom +//go:linkname libc_sendto libc_sendto +//go:linkname libc_recvmsg libc_recvmsg +//go:linkname libc_sendmsg libc_sendmsg +//go:linkname libc_munmap libc_munmap +//go:linkname libc_madvise libc_madvise +//go:linkname libc_mprotect libc_mprotect +//go:linkname libc_mlock libc_mlock +//go:linkname libc_mlockall libc_mlockall +//go:linkname libc_msync libc_msync +//go:linkname libc_munlock libc_munlock +//go:linkname libc_munlockall libc_munlockall +//go:linkname libc_pipe libc_pipe +//go:linkname libc_poll libc_poll +//go:linkname libc_gettimeofday libc_gettimeofday +//go:linkname libc_time libc_time +//go:linkname libc_utime libc_utime +//go:linkname libc_getrlimit libc_getrlimit +//go:linkname libc_setrlimit libc_setrlimit +//go:linkname libc_lseek libc_lseek +//go:linkname libc_mmap64 libc_mmap64 + +type syscallFunc uintptr + +var ( + libc_utimes, + libc_utimensat, + libc_getcwd, + libc_accept, + libc_getdirent, + libc_wait4, + libc_ioctl, + libc_fcntl, + libc_acct, + libc_chdir, + libc_chroot, + libc_close, + libc_dup, + libc_exit, + libc_faccessat, + libc_fchdir, + libc_fchmod, + libc_fchmodat, + libc_fchownat, + libc_fdatasync, + libc_fsync, + libc_getpgid, + libc_getpgrp, + libc_getpid, + libc_getppid, + libc_getpriority, + libc_getrusage, + libc_getsid, + libc_kill, + libc_syslog, + libc_mkdir, + libc_mkdirat, + libc_mkfifo, + libc_mknod, + libc_mknodat, + libc_nanosleep, + libc_open64, + libc_openat, + libc_read, + libc_readlink, + libc_renameat, + libc_setdomainname, + libc_sethostname, + libc_setpgid, + libc_setsid, + libc_settimeofday, + libc_setuid, + libc_setgid, + libc_setpriority, + libc_statx, + libc_sync, + libc_times, + libc_umask, + libc_uname, + libc_unlink, + libc_unlinkat, + libc_ustat, + libc_write, + libc_dup2, + libc_posix_fadvise64, + libc_fchown, + libc_fstat, + libc_fstatat, + libc_fstatfs, + libc_ftruncate, + libc_getegid, + libc_geteuid, + libc_getgid, + libc_getuid, + libc_lchown, + libc_listen, + libc_lstat, + libc_pause, + libc_pread64, + libc_pwrite64, + libc_pselect, + libc_setregid, + libc_setreuid, + libc_shutdown, + libc_splice, + libc_stat, + libc_statfs, + libc_truncate, + libc_bind, + libc_connect, + libc_getgroups, + libc_setgroups, + libc_getsockopt, + libc_setsockopt, + libc_socket, + libc_socketpair, + libc_getpeername, + libc_getsockname, + libc_recvfrom, + libc_sendto, + libc_recvmsg, + libc_sendmsg, + libc_munmap, + libc_madvise, + libc_mprotect, + libc_mlock, + libc_mlockall, + libc_msync, + libc_munlock, + libc_munlockall, + libc_pipe, + libc_poll, + libc_gettimeofday, + libc_time, + libc_utime, + libc_getrlimit, + libc_setrlimit, + libc_lseek, + libc_mmap64 syscallFunc +) + +// Implemented in runtime/syscall_aix.go. +func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) +func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callutimes(_p0 uintptr, times uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_utimes)), 2, _p0, times, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callutimensat(dirfd int, _p0 uintptr, times uintptr, flag int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_utimensat)), 4, uintptr(dirfd), _p0, times, uintptr(flag), 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetcwd(_p0 uintptr, _lenp0 int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_getcwd)), 2, _p0, uintptr(_lenp0), 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callaccept(s int, rsa uintptr, addrlen uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_accept)), 3, uintptr(s), rsa, addrlen, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetdirent(fd int, _p0 uintptr, _lenp0 int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_getdirent)), 3, uintptr(fd), _p0, uintptr(_lenp0), 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callwait4(pid int, status uintptr, options int, rusage uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_wait4)), 4, uintptr(pid), status, uintptr(options), rusage, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callioctl(fd int, req int, arg uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_ioctl)), 3, uintptr(fd), uintptr(req), arg, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callfcntl(fd uintptr, cmd int, arg uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_fcntl)), 3, fd, uintptr(cmd), arg, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callacct(_p0 uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_acct)), 1, _p0, 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callchdir(_p0 uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_chdir)), 1, _p0, 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callchroot(_p0 uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_chroot)), 1, _p0, 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callclose(fd int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_close)), 1, uintptr(fd), 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func calldup(oldfd int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_dup)), 1, uintptr(oldfd), 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callexit(code int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_exit)), 1, uintptr(code), 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callfaccessat(dirfd int, _p0 uintptr, mode uint32, flags int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_faccessat)), 4, uintptr(dirfd), _p0, uintptr(mode), uintptr(flags), 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callfchdir(fd int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_fchdir)), 1, uintptr(fd), 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callfchmod(fd int, mode uint32) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_fchmod)), 2, uintptr(fd), uintptr(mode), 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callfchmodat(dirfd int, _p0 uintptr, mode uint32, flags int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_fchmodat)), 4, uintptr(dirfd), _p0, uintptr(mode), uintptr(flags), 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callfchownat(dirfd int, _p0 uintptr, uid int, gid int, flags int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_fchownat)), 5, uintptr(dirfd), _p0, uintptr(uid), uintptr(gid), uintptr(flags), 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callfdatasync(fd int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_fdatasync)), 1, uintptr(fd), 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callfsync(fd int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_fsync)), 1, uintptr(fd), 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetpgid(pid int) (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_getpgid)), 1, uintptr(pid), 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetpgrp() (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_getpgrp)), 0, 0, 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetpid() (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_getpid)), 0, 0, 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetppid() (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_getppid)), 0, 0, 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetpriority(which int, who int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_getpriority)), 2, uintptr(which), uintptr(who), 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetrusage(who int, rusage uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_getrusage)), 2, uintptr(who), rusage, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetsid(pid int) (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_getsid)), 1, uintptr(pid), 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callkill(pid int, sig int) (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_kill)), 2, uintptr(pid), uintptr(sig), 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsyslog(typ int, _p0 uintptr, _lenp0 int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_syslog)), 3, uintptr(typ), _p0, uintptr(_lenp0), 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmkdir(dirfd int, _p0 uintptr, mode uint32) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_mkdir)), 3, uintptr(dirfd), _p0, uintptr(mode), 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmkdirat(dirfd int, _p0 uintptr, mode uint32) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_mkdirat)), 3, uintptr(dirfd), _p0, uintptr(mode), 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmkfifo(_p0 uintptr, mode uint32) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_mkfifo)), 2, _p0, uintptr(mode), 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmknod(_p0 uintptr, mode uint32, dev int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_mknod)), 3, _p0, uintptr(mode), uintptr(dev), 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmknodat(dirfd int, _p0 uintptr, mode uint32, dev int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_mknodat)), 4, uintptr(dirfd), _p0, uintptr(mode), uintptr(dev), 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callnanosleep(time uintptr, leftover uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_nanosleep)), 2, time, leftover, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callopen64(_p0 uintptr, mode int, perm uint32) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_open64)), 3, _p0, uintptr(mode), uintptr(perm), 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callopenat(dirfd int, _p0 uintptr, flags int, mode uint32) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_openat)), 4, uintptr(dirfd), _p0, uintptr(flags), uintptr(mode), 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callread(fd int, _p0 uintptr, _lenp0 int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_read)), 3, uintptr(fd), _p0, uintptr(_lenp0), 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callreadlink(_p0 uintptr, _p1 uintptr, _lenp1 int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_readlink)), 3, _p0, _p1, uintptr(_lenp1), 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callrenameat(olddirfd int, _p0 uintptr, newdirfd int, _p1 uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_renameat)), 4, uintptr(olddirfd), _p0, uintptr(newdirfd), _p1, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsetdomainname(_p0 uintptr, _lenp0 int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_setdomainname)), 2, _p0, uintptr(_lenp0), 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsethostname(_p0 uintptr, _lenp0 int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_sethostname)), 2, _p0, uintptr(_lenp0), 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsetpgid(pid int, pgid int) (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_setpgid)), 2, uintptr(pid), uintptr(pgid), 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsetsid() (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_setsid)), 0, 0, 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsettimeofday(tv uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_settimeofday)), 1, tv, 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsetuid(uid int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_setuid)), 1, uintptr(uid), 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsetgid(uid int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_setgid)), 1, uintptr(uid), 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsetpriority(which int, who int, prio int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_setpriority)), 3, uintptr(which), uintptr(who), uintptr(prio), 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callstatx(dirfd int, _p0 uintptr, flags int, mask int, stat uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_statx)), 5, uintptr(dirfd), _p0, uintptr(flags), uintptr(mask), stat, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsync() (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_sync)), 0, 0, 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func calltimes(tms uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_times)), 1, tms, 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callumask(mask int) (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_umask)), 1, uintptr(mask), 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func calluname(buf uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_uname)), 1, buf, 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callunlink(_p0 uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_unlink)), 1, _p0, 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callunlinkat(dirfd int, _p0 uintptr, flags int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_unlinkat)), 3, uintptr(dirfd), _p0, uintptr(flags), 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callustat(dev int, ubuf uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_ustat)), 2, uintptr(dev), ubuf, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callwrite(fd int, _p0 uintptr, _lenp0 int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_write)), 3, uintptr(fd), _p0, uintptr(_lenp0), 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func calldup2(oldfd int, newfd int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_dup2)), 2, uintptr(oldfd), uintptr(newfd), 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callposix_fadvise64(fd int, offset int64, length int64, advice int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_posix_fadvise64)), 4, uintptr(fd), uintptr(offset), uintptr(length), uintptr(advice), 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callfchown(fd int, uid int, gid int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_fchown)), 3, uintptr(fd), uintptr(uid), uintptr(gid), 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callfstat(fd int, stat uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_fstat)), 2, uintptr(fd), stat, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callfstatat(dirfd int, _p0 uintptr, stat uintptr, flags int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_fstatat)), 4, uintptr(dirfd), _p0, stat, uintptr(flags), 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callfstatfs(fd int, buf uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_fstatfs)), 2, uintptr(fd), buf, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callftruncate(fd int, length int64) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_ftruncate)), 2, uintptr(fd), uintptr(length), 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetegid() (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_getegid)), 0, 0, 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgeteuid() (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_geteuid)), 0, 0, 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetgid() (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_getgid)), 0, 0, 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetuid() (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_getuid)), 0, 0, 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func calllchown(_p0 uintptr, uid int, gid int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_lchown)), 3, _p0, uintptr(uid), uintptr(gid), 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func calllisten(s int, n int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_listen)), 2, uintptr(s), uintptr(n), 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func calllstat(_p0 uintptr, stat uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_lstat)), 2, _p0, stat, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callpause() (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_pause)), 0, 0, 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callpread64(fd int, _p0 uintptr, _lenp0 int, offset int64) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_pread64)), 4, uintptr(fd), _p0, uintptr(_lenp0), uintptr(offset), 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callpwrite64(fd int, _p0 uintptr, _lenp0 int, offset int64) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_pwrite64)), 4, uintptr(fd), _p0, uintptr(_lenp0), uintptr(offset), 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callpselect(nfd int, r uintptr, w uintptr, e uintptr, timeout uintptr, sigmask uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_pselect)), 6, uintptr(nfd), r, w, e, timeout, sigmask) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsetregid(rgid int, egid int) (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_setregid)), 2, uintptr(rgid), uintptr(egid), 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsetreuid(ruid int, euid int) (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_setreuid)), 2, uintptr(ruid), uintptr(euid), 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callshutdown(fd int, how int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_shutdown)), 2, uintptr(fd), uintptr(how), 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsplice(rfd int, roff uintptr, wfd int, woff uintptr, len int, flags int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_splice)), 6, uintptr(rfd), roff, uintptr(wfd), woff, uintptr(len), uintptr(flags)) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callstat(_p0 uintptr, stat uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_stat)), 2, _p0, stat, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callstatfs(_p0 uintptr, buf uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_statfs)), 2, _p0, buf, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func calltruncate(_p0 uintptr, length int64) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_truncate)), 2, _p0, uintptr(length), 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callbind(s int, addr uintptr, addrlen uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_bind)), 3, uintptr(s), addr, addrlen, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callconnect(s int, addr uintptr, addrlen uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_connect)), 3, uintptr(s), addr, addrlen, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetgroups(n int, list uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_getgroups)), 2, uintptr(n), list, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsetgroups(n int, list uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_setgroups)), 2, uintptr(n), list, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetsockopt(s int, level int, name int, val uintptr, vallen uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_getsockopt)), 5, uintptr(s), uintptr(level), uintptr(name), val, vallen, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsetsockopt(s int, level int, name int, val uintptr, vallen uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_setsockopt)), 5, uintptr(s), uintptr(level), uintptr(name), val, vallen, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsocket(domain int, typ int, proto int) (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_socket)), 3, uintptr(domain), uintptr(typ), uintptr(proto), 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsocketpair(domain int, typ int, proto int, fd uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_socketpair)), 4, uintptr(domain), uintptr(typ), uintptr(proto), fd, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetpeername(fd int, rsa uintptr, addrlen uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_getpeername)), 3, uintptr(fd), rsa, addrlen, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetsockname(fd int, rsa uintptr, addrlen uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_getsockname)), 3, uintptr(fd), rsa, addrlen, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callrecvfrom(fd int, _p0 uintptr, _lenp0 int, flags int, from uintptr, fromlen uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_recvfrom)), 6, uintptr(fd), _p0, uintptr(_lenp0), uintptr(flags), from, fromlen) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsendto(s int, _p0 uintptr, _lenp0 int, flags int, to uintptr, addrlen uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_sendto)), 6, uintptr(s), _p0, uintptr(_lenp0), uintptr(flags), to, addrlen) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callrecvmsg(s int, msg uintptr, flags int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_recvmsg)), 3, uintptr(s), msg, uintptr(flags), 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsendmsg(s int, msg uintptr, flags int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_sendmsg)), 3, uintptr(s), msg, uintptr(flags), 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmunmap(addr uintptr, length uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_munmap)), 2, addr, length, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmadvise(_p0 uintptr, _lenp0 int, advice int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_madvise)), 3, _p0, uintptr(_lenp0), uintptr(advice), 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmprotect(_p0 uintptr, _lenp0 int, prot int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_mprotect)), 3, _p0, uintptr(_lenp0), uintptr(prot), 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmlock(_p0 uintptr, _lenp0 int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_mlock)), 2, _p0, uintptr(_lenp0), 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmlockall(flags int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_mlockall)), 1, uintptr(flags), 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmsync(_p0 uintptr, _lenp0 int, flags int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_msync)), 3, _p0, uintptr(_lenp0), uintptr(flags), 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmunlock(_p0 uintptr, _lenp0 int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_munlock)), 2, _p0, uintptr(_lenp0), 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmunlockall() (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_munlockall)), 0, 0, 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callpipe(p uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_pipe)), 1, p, 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callpoll(fds uintptr, nfds int, timeout int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_poll)), 3, fds, uintptr(nfds), uintptr(timeout), 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgettimeofday(tv uintptr, tzp uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_gettimeofday)), 2, tv, tzp, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func calltime(t uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_time)), 1, t, 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callutime(_p0 uintptr, buf uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_utime)), 2, _p0, buf, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetrlimit(resource int, rlim uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_getrlimit)), 2, uintptr(resource), rlim, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsetrlimit(resource int, rlim uintptr) (r1 uintptr, e1 Errno) { + r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_setrlimit)), 2, uintptr(resource), rlim, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func calllseek(fd int, offset int64, whence int) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_lseek)), 3, uintptr(fd), uintptr(offset), uintptr(whence), 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmmap64(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_mmap64)), 6, addr, length, uintptr(prot), uintptr(flags), uintptr(fd), uintptr(offset)) + return +} diff --git a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gccgo.go b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gccgo.go new file mode 100644 index 000000000..aef7c0e78 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gccgo.go @@ -0,0 +1,1042 @@ +// mksyscall_aix_ppc64.pl -aix -tags aix,ppc64 syscall_aix.go syscall_aix_ppc64.go +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build aix,ppc64 +// +build gccgo + +package unix + +/* +#include +int utimes(uintptr_t, uintptr_t); +int utimensat(int, uintptr_t, uintptr_t, int); +int getcwd(uintptr_t, size_t); +int accept(int, uintptr_t, uintptr_t); +int getdirent(int, uintptr_t, size_t); +int wait4(int, uintptr_t, int, uintptr_t); +int ioctl(int, int, uintptr_t); +int fcntl(uintptr_t, int, uintptr_t); +int acct(uintptr_t); +int chdir(uintptr_t); +int chroot(uintptr_t); +int close(int); +int dup(int); +void exit(int); +int faccessat(int, uintptr_t, unsigned int, int); +int fchdir(int); +int fchmod(int, unsigned int); +int fchmodat(int, uintptr_t, unsigned int, int); +int fchownat(int, uintptr_t, int, int, int); +int fdatasync(int); +int fsync(int); +int getpgid(int); +int getpgrp(); +int getpid(); +int getppid(); +int getpriority(int, int); +int getrusage(int, uintptr_t); +int getsid(int); +int kill(int, int); +int syslog(int, uintptr_t, size_t); +int mkdir(int, uintptr_t, unsigned int); +int mkdirat(int, uintptr_t, unsigned int); +int mkfifo(uintptr_t, unsigned int); +int mknod(uintptr_t, unsigned int, int); +int mknodat(int, uintptr_t, unsigned int, int); +int nanosleep(uintptr_t, uintptr_t); +int open64(uintptr_t, int, unsigned int); +int openat(int, uintptr_t, int, unsigned int); +int read(int, uintptr_t, size_t); +int readlink(uintptr_t, uintptr_t, size_t); +int renameat(int, uintptr_t, int, uintptr_t); +int setdomainname(uintptr_t, size_t); +int sethostname(uintptr_t, size_t); +int setpgid(int, int); +int setsid(); +int settimeofday(uintptr_t); +int setuid(int); +int setgid(int); +int setpriority(int, int, int); +int statx(int, uintptr_t, int, int, uintptr_t); +int sync(); +uintptr_t times(uintptr_t); +int umask(int); +int uname(uintptr_t); +int unlink(uintptr_t); +int unlinkat(int, uintptr_t, int); +int ustat(int, uintptr_t); +int write(int, uintptr_t, size_t); +int dup2(int, int); +int posix_fadvise64(int, long long, long long, int); +int fchown(int, int, int); +int fstat(int, uintptr_t); +int fstatat(int, uintptr_t, uintptr_t, int); +int fstatfs(int, uintptr_t); +int ftruncate(int, long long); +int getegid(); +int geteuid(); +int getgid(); +int getuid(); +int lchown(uintptr_t, int, int); +int listen(int, int); +int lstat(uintptr_t, uintptr_t); +int pause(); +int pread64(int, uintptr_t, size_t, long long); +int pwrite64(int, uintptr_t, size_t, long long); +int pselect(int, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); +int setregid(int, int); +int setreuid(int, int); +int shutdown(int, int); +long long splice(int, uintptr_t, int, uintptr_t, int, int); +int stat(uintptr_t, uintptr_t); +int statfs(uintptr_t, uintptr_t); +int truncate(uintptr_t, long long); +int bind(int, uintptr_t, uintptr_t); +int connect(int, uintptr_t, uintptr_t); +int getgroups(int, uintptr_t); +int setgroups(int, uintptr_t); +int getsockopt(int, int, int, uintptr_t, uintptr_t); +int setsockopt(int, int, int, uintptr_t, uintptr_t); +int socket(int, int, int); +int socketpair(int, int, int, uintptr_t); +int getpeername(int, uintptr_t, uintptr_t); +int getsockname(int, uintptr_t, uintptr_t); +int recvfrom(int, uintptr_t, size_t, int, uintptr_t, uintptr_t); +int sendto(int, uintptr_t, size_t, int, uintptr_t, uintptr_t); +int recvmsg(int, uintptr_t, int); +int sendmsg(int, uintptr_t, int); +int munmap(uintptr_t, uintptr_t); +int madvise(uintptr_t, size_t, int); +int mprotect(uintptr_t, size_t, int); +int mlock(uintptr_t, size_t); +int mlockall(int); +int msync(uintptr_t, size_t, int); +int munlock(uintptr_t, size_t); +int munlockall(); +int pipe(uintptr_t); +int poll(uintptr_t, int, int); +int gettimeofday(uintptr_t, uintptr_t); +int time(uintptr_t); +int utime(uintptr_t, uintptr_t); +int getrlimit(int, uintptr_t); +int setrlimit(int, uintptr_t); +long long lseek(int, long long, int); +uintptr_t mmap64(uintptr_t, uintptr_t, int, int, int, long long); + +*/ +import "C" +import ( + "syscall" +) + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callutimes(_p0 uintptr, times uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.utimes(C.uintptr_t(_p0), C.uintptr_t(times))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callutimensat(dirfd int, _p0 uintptr, times uintptr, flag int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.utimensat(C.int(dirfd), C.uintptr_t(_p0), C.uintptr_t(times), C.int(flag))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetcwd(_p0 uintptr, _lenp0 int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.getcwd(C.uintptr_t(_p0), C.size_t(_lenp0))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callaccept(s int, rsa uintptr, addrlen uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.accept(C.int(s), C.uintptr_t(rsa), C.uintptr_t(addrlen))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetdirent(fd int, _p0 uintptr, _lenp0 int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.getdirent(C.int(fd), C.uintptr_t(_p0), C.size_t(_lenp0))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callwait4(pid int, status uintptr, options int, rusage uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.wait4(C.int(pid), C.uintptr_t(status), C.int(options), C.uintptr_t(rusage))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callioctl(fd int, req int, arg uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.ioctl(C.int(fd), C.int(req), C.uintptr_t(arg))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callfcntl(fd uintptr, cmd int, arg uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.fcntl(C.uintptr_t(fd), C.int(cmd), C.uintptr_t(arg))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callacct(_p0 uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.acct(C.uintptr_t(_p0))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callchdir(_p0 uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.chdir(C.uintptr_t(_p0))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callchroot(_p0 uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.chroot(C.uintptr_t(_p0))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callclose(fd int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.close(C.int(fd))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func calldup(oldfd int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.dup(C.int(oldfd))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callexit(code int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.exit(C.int(code))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callfaccessat(dirfd int, _p0 uintptr, mode uint32, flags int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.faccessat(C.int(dirfd), C.uintptr_t(_p0), C.uint(mode), C.int(flags))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callfchdir(fd int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.fchdir(C.int(fd))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callfchmod(fd int, mode uint32) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.fchmod(C.int(fd), C.uint(mode))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callfchmodat(dirfd int, _p0 uintptr, mode uint32, flags int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.fchmodat(C.int(dirfd), C.uintptr_t(_p0), C.uint(mode), C.int(flags))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callfchownat(dirfd int, _p0 uintptr, uid int, gid int, flags int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.fchownat(C.int(dirfd), C.uintptr_t(_p0), C.int(uid), C.int(gid), C.int(flags))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callfdatasync(fd int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.fdatasync(C.int(fd))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callfsync(fd int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.fsync(C.int(fd))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetpgid(pid int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.getpgid(C.int(pid))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetpgrp() (r1 uintptr, e1 Errno) { + r1 = uintptr(C.getpgrp()) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetpid() (r1 uintptr, e1 Errno) { + r1 = uintptr(C.getpid()) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetppid() (r1 uintptr, e1 Errno) { + r1 = uintptr(C.getppid()) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetpriority(which int, who int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.getpriority(C.int(which), C.int(who))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetrusage(who int, rusage uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.getrusage(C.int(who), C.uintptr_t(rusage))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetsid(pid int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.getsid(C.int(pid))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callkill(pid int, sig int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.kill(C.int(pid), C.int(sig))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsyslog(typ int, _p0 uintptr, _lenp0 int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.syslog(C.int(typ), C.uintptr_t(_p0), C.size_t(_lenp0))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmkdir(dirfd int, _p0 uintptr, mode uint32) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.mkdir(C.int(dirfd), C.uintptr_t(_p0), C.uint(mode))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmkdirat(dirfd int, _p0 uintptr, mode uint32) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.mkdirat(C.int(dirfd), C.uintptr_t(_p0), C.uint(mode))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmkfifo(_p0 uintptr, mode uint32) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.mkfifo(C.uintptr_t(_p0), C.uint(mode))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmknod(_p0 uintptr, mode uint32, dev int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.mknod(C.uintptr_t(_p0), C.uint(mode), C.int(dev))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmknodat(dirfd int, _p0 uintptr, mode uint32, dev int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.mknodat(C.int(dirfd), C.uintptr_t(_p0), C.uint(mode), C.int(dev))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callnanosleep(time uintptr, leftover uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.nanosleep(C.uintptr_t(time), C.uintptr_t(leftover))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callopen64(_p0 uintptr, mode int, perm uint32) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.open64(C.uintptr_t(_p0), C.int(mode), C.uint(perm))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callopenat(dirfd int, _p0 uintptr, flags int, mode uint32) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.openat(C.int(dirfd), C.uintptr_t(_p0), C.int(flags), C.uint(mode))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callread(fd int, _p0 uintptr, _lenp0 int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.read(C.int(fd), C.uintptr_t(_p0), C.size_t(_lenp0))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callreadlink(_p0 uintptr, _p1 uintptr, _lenp1 int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.readlink(C.uintptr_t(_p0), C.uintptr_t(_p1), C.size_t(_lenp1))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callrenameat(olddirfd int, _p0 uintptr, newdirfd int, _p1 uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.renameat(C.int(olddirfd), C.uintptr_t(_p0), C.int(newdirfd), C.uintptr_t(_p1))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsetdomainname(_p0 uintptr, _lenp0 int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.setdomainname(C.uintptr_t(_p0), C.size_t(_lenp0))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsethostname(_p0 uintptr, _lenp0 int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.sethostname(C.uintptr_t(_p0), C.size_t(_lenp0))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsetpgid(pid int, pgid int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.setpgid(C.int(pid), C.int(pgid))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsetsid() (r1 uintptr, e1 Errno) { + r1 = uintptr(C.setsid()) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsettimeofday(tv uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.settimeofday(C.uintptr_t(tv))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsetuid(uid int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.setuid(C.int(uid))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsetgid(uid int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.setgid(C.int(uid))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsetpriority(which int, who int, prio int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.setpriority(C.int(which), C.int(who), C.int(prio))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callstatx(dirfd int, _p0 uintptr, flags int, mask int, stat uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.statx(C.int(dirfd), C.uintptr_t(_p0), C.int(flags), C.int(mask), C.uintptr_t(stat))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsync() (r1 uintptr, e1 Errno) { + r1 = uintptr(C.sync()) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func calltimes(tms uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.times(C.uintptr_t(tms))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callumask(mask int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.umask(C.int(mask))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func calluname(buf uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.uname(C.uintptr_t(buf))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callunlink(_p0 uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.unlink(C.uintptr_t(_p0))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callunlinkat(dirfd int, _p0 uintptr, flags int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.unlinkat(C.int(dirfd), C.uintptr_t(_p0), C.int(flags))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callustat(dev int, ubuf uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.ustat(C.int(dev), C.uintptr_t(ubuf))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callwrite(fd int, _p0 uintptr, _lenp0 int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.write(C.int(fd), C.uintptr_t(_p0), C.size_t(_lenp0))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func calldup2(oldfd int, newfd int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.dup2(C.int(oldfd), C.int(newfd))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callposix_fadvise64(fd int, offset int64, length int64, advice int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.posix_fadvise64(C.int(fd), C.longlong(offset), C.longlong(length), C.int(advice))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callfchown(fd int, uid int, gid int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.fchown(C.int(fd), C.int(uid), C.int(gid))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callfstat(fd int, stat uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.fstat(C.int(fd), C.uintptr_t(stat))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callfstatat(dirfd int, _p0 uintptr, stat uintptr, flags int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.fstatat(C.int(dirfd), C.uintptr_t(_p0), C.uintptr_t(stat), C.int(flags))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callfstatfs(fd int, buf uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.fstatfs(C.int(fd), C.uintptr_t(buf))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callftruncate(fd int, length int64) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.ftruncate(C.int(fd), C.longlong(length))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetegid() (r1 uintptr, e1 Errno) { + r1 = uintptr(C.getegid()) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgeteuid() (r1 uintptr, e1 Errno) { + r1 = uintptr(C.geteuid()) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetgid() (r1 uintptr, e1 Errno) { + r1 = uintptr(C.getgid()) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetuid() (r1 uintptr, e1 Errno) { + r1 = uintptr(C.getuid()) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func calllchown(_p0 uintptr, uid int, gid int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.lchown(C.uintptr_t(_p0), C.int(uid), C.int(gid))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func calllisten(s int, n int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.listen(C.int(s), C.int(n))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func calllstat(_p0 uintptr, stat uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.lstat(C.uintptr_t(_p0), C.uintptr_t(stat))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callpause() (r1 uintptr, e1 Errno) { + r1 = uintptr(C.pause()) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callpread64(fd int, _p0 uintptr, _lenp0 int, offset int64) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.pread64(C.int(fd), C.uintptr_t(_p0), C.size_t(_lenp0), C.longlong(offset))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callpwrite64(fd int, _p0 uintptr, _lenp0 int, offset int64) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.pwrite64(C.int(fd), C.uintptr_t(_p0), C.size_t(_lenp0), C.longlong(offset))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callpselect(nfd int, r uintptr, w uintptr, e uintptr, timeout uintptr, sigmask uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.pselect(C.int(nfd), C.uintptr_t(r), C.uintptr_t(w), C.uintptr_t(e), C.uintptr_t(timeout), C.uintptr_t(sigmask))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsetregid(rgid int, egid int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.setregid(C.int(rgid), C.int(egid))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsetreuid(ruid int, euid int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.setreuid(C.int(ruid), C.int(euid))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callshutdown(fd int, how int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.shutdown(C.int(fd), C.int(how))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsplice(rfd int, roff uintptr, wfd int, woff uintptr, len int, flags int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.splice(C.int(rfd), C.uintptr_t(roff), C.int(wfd), C.uintptr_t(woff), C.int(len), C.int(flags))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callstat(_p0 uintptr, stat uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.stat(C.uintptr_t(_p0), C.uintptr_t(stat))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callstatfs(_p0 uintptr, buf uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.statfs(C.uintptr_t(_p0), C.uintptr_t(buf))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func calltruncate(_p0 uintptr, length int64) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.truncate(C.uintptr_t(_p0), C.longlong(length))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callbind(s int, addr uintptr, addrlen uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.bind(C.int(s), C.uintptr_t(addr), C.uintptr_t(addrlen))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callconnect(s int, addr uintptr, addrlen uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.connect(C.int(s), C.uintptr_t(addr), C.uintptr_t(addrlen))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetgroups(n int, list uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.getgroups(C.int(n), C.uintptr_t(list))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsetgroups(n int, list uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.setgroups(C.int(n), C.uintptr_t(list))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetsockopt(s int, level int, name int, val uintptr, vallen uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.getsockopt(C.int(s), C.int(level), C.int(name), C.uintptr_t(val), C.uintptr_t(vallen))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsetsockopt(s int, level int, name int, val uintptr, vallen uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.setsockopt(C.int(s), C.int(level), C.int(name), C.uintptr_t(val), C.uintptr_t(vallen))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsocket(domain int, typ int, proto int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.socket(C.int(domain), C.int(typ), C.int(proto))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsocketpair(domain int, typ int, proto int, fd uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.socketpair(C.int(domain), C.int(typ), C.int(proto), C.uintptr_t(fd))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetpeername(fd int, rsa uintptr, addrlen uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.getpeername(C.int(fd), C.uintptr_t(rsa), C.uintptr_t(addrlen))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetsockname(fd int, rsa uintptr, addrlen uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.getsockname(C.int(fd), C.uintptr_t(rsa), C.uintptr_t(addrlen))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callrecvfrom(fd int, _p0 uintptr, _lenp0 int, flags int, from uintptr, fromlen uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.recvfrom(C.int(fd), C.uintptr_t(_p0), C.size_t(_lenp0), C.int(flags), C.uintptr_t(from), C.uintptr_t(fromlen))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsendto(s int, _p0 uintptr, _lenp0 int, flags int, to uintptr, addrlen uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.sendto(C.int(s), C.uintptr_t(_p0), C.size_t(_lenp0), C.int(flags), C.uintptr_t(to), C.uintptr_t(addrlen))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callrecvmsg(s int, msg uintptr, flags int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.recvmsg(C.int(s), C.uintptr_t(msg), C.int(flags))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsendmsg(s int, msg uintptr, flags int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.sendmsg(C.int(s), C.uintptr_t(msg), C.int(flags))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmunmap(addr uintptr, length uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.munmap(C.uintptr_t(addr), C.uintptr_t(length))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmadvise(_p0 uintptr, _lenp0 int, advice int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.madvise(C.uintptr_t(_p0), C.size_t(_lenp0), C.int(advice))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmprotect(_p0 uintptr, _lenp0 int, prot int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.mprotect(C.uintptr_t(_p0), C.size_t(_lenp0), C.int(prot))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmlock(_p0 uintptr, _lenp0 int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.mlock(C.uintptr_t(_p0), C.size_t(_lenp0))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmlockall(flags int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.mlockall(C.int(flags))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmsync(_p0 uintptr, _lenp0 int, flags int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.msync(C.uintptr_t(_p0), C.size_t(_lenp0), C.int(flags))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmunlock(_p0 uintptr, _lenp0 int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.munlock(C.uintptr_t(_p0), C.size_t(_lenp0))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmunlockall() (r1 uintptr, e1 Errno) { + r1 = uintptr(C.munlockall()) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callpipe(p uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.pipe(C.uintptr_t(p))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callpoll(fds uintptr, nfds int, timeout int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.poll(C.uintptr_t(fds), C.int(nfds), C.int(timeout))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgettimeofday(tv uintptr, tzp uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.gettimeofday(C.uintptr_t(tv), C.uintptr_t(tzp))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func calltime(t uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.time(C.uintptr_t(t))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callutime(_p0 uintptr, buf uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.utime(C.uintptr_t(_p0), C.uintptr_t(buf))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callgetrlimit(resource int, rlim uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.getrlimit(C.int(resource), C.uintptr_t(rlim))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callsetrlimit(resource int, rlim uintptr) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.setrlimit(C.int(resource), C.uintptr_t(rlim))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func calllseek(fd int, offset int64, whence int) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.lseek(C.int(fd), C.longlong(offset), C.int(whence))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func callmmap64(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.mmap64(C.uintptr_t(addr), C.uintptr_t(length), C.int(prot), C.int(flags), C.int(fd), C.longlong(offset))) + e1 = syscall.GetErrno() + return +} diff --git a/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go index 91f36e9ec..12da7b41f 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go @@ -1023,6 +1023,22 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Pathconf(path string, name int) (val int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go index ad77882b8..9bbbf9662 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go @@ -912,7 +912,7 @@ func Fpathconf(fd int, name int) (val int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Fstat(fd int, stat *Stat_t) (err error) { +func fstat(fd int, stat *stat_freebsd11_t) (err error) { _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) @@ -922,7 +922,17 @@ func Fstat(fd int, stat *Stat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { +func fstat_freebsd12(fd int, stat *Stat_t) (err error) { + _, _, e1 := Syscall(SYS_FSTAT_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fstatat(fd int, path string, stat *stat_freebsd11_t, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { @@ -937,7 +947,22 @@ func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Fstatfs(fd int, stat *Statfs_t) (err error) { +func fstatat_freebsd12(fd int, path string, stat *Stat_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FSTATAT_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fstatfs(fd int, stat *statfs_freebsd11_t) (err error) { _, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) @@ -947,6 +972,16 @@ func Fstatfs(fd int, stat *Statfs_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fstatfs_freebsd12(fd int, stat *Statfs_t) (err error) { + _, _, e1 := Syscall(SYS_FSTATFS_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fsync(fd int) (err error) { _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) if e1 != 0 { @@ -967,14 +1002,14 @@ func Ftruncate(fd int, length int64) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Getdents(fd int, buf []byte) (n int, err error) { +func getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { var _p0 unsafe.Pointer if len(buf) > 0 { _p0 = unsafe.Pointer(&buf[0]) } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall(SYS_GETDENTS, uintptr(fd), uintptr(_p0), uintptr(len(buf))) + r0, _, e1 := Syscall6(SYS_GETDIRENTRIES, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -984,14 +1019,14 @@ func Getdents(fd int, buf []byte) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { +func getdirentries_freebsd12(fd int, buf []byte, basep *uintptr) (n int, err error) { var _p0 unsafe.Pointer if len(buf) > 0 { _p0 = unsafe.Pointer(&buf[0]) } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall6(SYS_GETDIRENTRIES, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0) + r0, _, e1 := Syscall6(SYS_GETDIRENTRIES_FREEBSD12, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1222,7 +1257,7 @@ func Listen(s int, backlog int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Lstat(path string, stat *Stat_t) (err error) { +func lstat(path string, stat *stat_freebsd11_t) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { @@ -1282,7 +1317,7 @@ func Mkfifo(path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Mknod(path string, mode uint32, dev int) (err error) { +func mknod(path string, mode uint32, dev int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { @@ -1297,6 +1332,36 @@ func Mknod(path string, mode uint32, dev int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func mknodat(fd int, path string, mode uint32, dev int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_MKNODAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func mknodat_freebsd12(fd int, path string, mode uint32, dev uint64) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_MKNODAT_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { @@ -1687,7 +1752,7 @@ func Setuid(uid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Stat(path string, stat *Stat_t) (err error) { +func stat(path string, stat *stat_freebsd11_t) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { @@ -1702,7 +1767,7 @@ func Stat(path string, stat *Stat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Statfs(path string, stat *Statfs_t) (err error) { +func statfs(path string, stat *statfs_freebsd11_t) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { @@ -1717,6 +1782,21 @@ func Statfs(path string, stat *Statfs_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func statfs_freebsd12(path string, stat *Statfs_t) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_STATFS_FREEBSD12, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Symlink(path string, link string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go index d3ba6c46f..ee7090ff4 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go @@ -912,7 +912,7 @@ func Fpathconf(fd int, name int) (val int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Fstat(fd int, stat *Stat_t) (err error) { +func fstat(fd int, stat *stat_freebsd11_t) (err error) { _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) @@ -922,7 +922,17 @@ func Fstat(fd int, stat *Stat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { +func fstat_freebsd12(fd int, stat *Stat_t) (err error) { + _, _, e1 := Syscall(SYS_FSTAT_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fstatat(fd int, path string, stat *stat_freebsd11_t, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { @@ -937,7 +947,22 @@ func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Fstatfs(fd int, stat *Statfs_t) (err error) { +func fstatat_freebsd12(fd int, path string, stat *Stat_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FSTATAT_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fstatfs(fd int, stat *statfs_freebsd11_t) (err error) { _, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) @@ -947,6 +972,16 @@ func Fstatfs(fd int, stat *Statfs_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fstatfs_freebsd12(fd int, stat *Statfs_t) (err error) { + _, _, e1 := Syscall(SYS_FSTATFS_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fsync(fd int) (err error) { _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) if e1 != 0 { @@ -967,14 +1002,14 @@ func Ftruncate(fd int, length int64) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Getdents(fd int, buf []byte) (n int, err error) { +func getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { var _p0 unsafe.Pointer if len(buf) > 0 { _p0 = unsafe.Pointer(&buf[0]) } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall(SYS_GETDENTS, uintptr(fd), uintptr(_p0), uintptr(len(buf))) + r0, _, e1 := Syscall6(SYS_GETDIRENTRIES, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -984,14 +1019,14 @@ func Getdents(fd int, buf []byte) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { +func getdirentries_freebsd12(fd int, buf []byte, basep *uintptr) (n int, err error) { var _p0 unsafe.Pointer if len(buf) > 0 { _p0 = unsafe.Pointer(&buf[0]) } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall6(SYS_GETDIRENTRIES, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0) + r0, _, e1 := Syscall6(SYS_GETDIRENTRIES_FREEBSD12, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1222,7 +1257,7 @@ func Listen(s int, backlog int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Lstat(path string, stat *Stat_t) (err error) { +func lstat(path string, stat *stat_freebsd11_t) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { @@ -1282,7 +1317,7 @@ func Mkfifo(path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Mknod(path string, mode uint32, dev int) (err error) { +func mknod(path string, mode uint32, dev int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { @@ -1297,6 +1332,36 @@ func Mknod(path string, mode uint32, dev int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func mknodat(fd int, path string, mode uint32, dev int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_MKNODAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func mknodat_freebsd12(fd int, path string, mode uint32, dev uint64) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_MKNODAT_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { @@ -1687,7 +1752,7 @@ func Setuid(uid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Stat(path string, stat *Stat_t) (err error) { +func stat(path string, stat *stat_freebsd11_t) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { @@ -1702,7 +1767,7 @@ func Stat(path string, stat *Stat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Statfs(path string, stat *Statfs_t) (err error) { +func statfs(path string, stat *statfs_freebsd11_t) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { @@ -1717,6 +1782,21 @@ func Statfs(path string, stat *Statfs_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func statfs_freebsd12(path string, stat *Statfs_t) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_STATFS_FREEBSD12, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Symlink(path string, link string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go index 9dfd77b62..9aeff5131 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go @@ -912,7 +912,7 @@ func Fpathconf(fd int, name int) (val int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Fstat(fd int, stat *Stat_t) (err error) { +func fstat(fd int, stat *stat_freebsd11_t) (err error) { _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) @@ -922,7 +922,17 @@ func Fstat(fd int, stat *Stat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { +func fstat_freebsd12(fd int, stat *Stat_t) (err error) { + _, _, e1 := Syscall(SYS_FSTAT_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fstatat(fd int, path string, stat *stat_freebsd11_t, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { @@ -937,7 +947,22 @@ func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Fstatfs(fd int, stat *Statfs_t) (err error) { +func fstatat_freebsd12(fd int, path string, stat *Stat_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FSTATAT_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fstatfs(fd int, stat *statfs_freebsd11_t) (err error) { _, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) @@ -947,6 +972,16 @@ func Fstatfs(fd int, stat *Statfs_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fstatfs_freebsd12(fd int, stat *Statfs_t) (err error) { + _, _, e1 := Syscall(SYS_FSTATFS_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fsync(fd int) (err error) { _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) if e1 != 0 { @@ -967,14 +1002,14 @@ func Ftruncate(fd int, length int64) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Getdents(fd int, buf []byte) (n int, err error) { +func getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { var _p0 unsafe.Pointer if len(buf) > 0 { _p0 = unsafe.Pointer(&buf[0]) } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall(SYS_GETDENTS, uintptr(fd), uintptr(_p0), uintptr(len(buf))) + r0, _, e1 := Syscall6(SYS_GETDIRENTRIES, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -984,14 +1019,14 @@ func Getdents(fd int, buf []byte) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { +func getdirentries_freebsd12(fd int, buf []byte, basep *uintptr) (n int, err error) { var _p0 unsafe.Pointer if len(buf) > 0 { _p0 = unsafe.Pointer(&buf[0]) } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall6(SYS_GETDIRENTRIES, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0) + r0, _, e1 := Syscall6(SYS_GETDIRENTRIES_FREEBSD12, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1222,7 +1257,7 @@ func Listen(s int, backlog int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Lstat(path string, stat *Stat_t) (err error) { +func lstat(path string, stat *stat_freebsd11_t) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { @@ -1282,7 +1317,7 @@ func Mkfifo(path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Mknod(path string, mode uint32, dev int) (err error) { +func mknod(path string, mode uint32, dev int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { @@ -1297,6 +1332,36 @@ func Mknod(path string, mode uint32, dev int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func mknodat(fd int, path string, mode uint32, dev int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_MKNODAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func mknodat_freebsd12(fd int, path string, mode uint32, dev uint64) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_MKNODAT_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { @@ -1687,7 +1752,7 @@ func Setuid(uid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Stat(path string, stat *Stat_t) (err error) { +func stat(path string, stat *stat_freebsd11_t) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { @@ -1702,7 +1767,7 @@ func Stat(path string, stat *Stat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Statfs(path string, stat *Statfs_t) (err error) { +func statfs(path string, stat *statfs_freebsd11_t) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { @@ -1717,6 +1782,21 @@ func Statfs(path string, stat *Statfs_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func statfs_freebsd12(path string, stat *Statfs_t) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_STATFS_FREEBSD12, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Symlink(path string, link string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go index 35b155a02..cd94680d1 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go @@ -458,6 +458,21 @@ func CopyFileRange(rfd int, roff *int64, wfd int, woff *int64, len int, flags in // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func DeleteModule(name string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(name) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_DELETE_MODULE, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Dup(oldfd int) (fd int, err error) { r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), 0, 0) fd = int(r0) @@ -606,6 +621,21 @@ func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func FinitModule(fd int, params string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(params) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FINIT_MODULE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flistxattr(fd int, dest []byte) (sz int, err error) { var _p0 unsafe.Pointer if len(dest) > 0 { @@ -807,6 +837,27 @@ func Getxattr(path string, attr string, dest []byte) (sz int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func InitModule(moduleImage []byte, params string) (err error) { + var _p0 unsafe.Pointer + if len(moduleImage) > 0 { + _p0 = unsafe.Pointer(&moduleImage[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + var _p1 *byte + _p1, err = BytePtrFromString(params) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_INIT_MODULE, uintptr(_p0), uintptr(len(moduleImage)), uintptr(unsafe.Pointer(_p1))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) { var _p0 *byte _p0, err = BytePtrFromString(pathname) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go index 46e9ddfb5..96e9df7da 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go @@ -458,6 +458,21 @@ func CopyFileRange(rfd int, roff *int64, wfd int, woff *int64, len int, flags in // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func DeleteModule(name string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(name) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_DELETE_MODULE, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Dup(oldfd int) (fd int, err error) { r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), 0, 0) fd = int(r0) @@ -606,6 +621,21 @@ func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func FinitModule(fd int, params string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(params) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FINIT_MODULE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flistxattr(fd int, dest []byte) (sz int, err error) { var _p0 unsafe.Pointer if len(dest) > 0 { @@ -807,6 +837,27 @@ func Getxattr(path string, attr string, dest []byte) (sz int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func InitModule(moduleImage []byte, params string) (err error) { + var _p0 unsafe.Pointer + if len(moduleImage) > 0 { + _p0 = unsafe.Pointer(&moduleImage[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + var _p1 *byte + _p1, err = BytePtrFromString(params) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_INIT_MODULE, uintptr(_p0), uintptr(len(moduleImage)), uintptr(unsafe.Pointer(_p1))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) { var _p0 *byte _p0, err = BytePtrFromString(pathname) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go index 914f25f06..e8d82d14c 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go @@ -458,6 +458,21 @@ func CopyFileRange(rfd int, roff *int64, wfd int, woff *int64, len int, flags in // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func DeleteModule(name string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(name) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_DELETE_MODULE, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Dup(oldfd int) (fd int, err error) { r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), 0, 0) fd = int(r0) @@ -606,6 +621,21 @@ func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func FinitModule(fd int, params string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(params) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FINIT_MODULE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flistxattr(fd int, dest []byte) (sz int, err error) { var _p0 unsafe.Pointer if len(dest) > 0 { @@ -807,6 +837,27 @@ func Getxattr(path string, attr string, dest []byte) (sz int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func InitModule(moduleImage []byte, params string) (err error) { + var _p0 unsafe.Pointer + if len(moduleImage) > 0 { + _p0 = unsafe.Pointer(&moduleImage[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + var _p1 *byte + _p1, err = BytePtrFromString(params) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_INIT_MODULE, uintptr(_p0), uintptr(len(moduleImage)), uintptr(unsafe.Pointer(_p1))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) { var _p0 *byte _p0, err = BytePtrFromString(pathname) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go index 1d6c55628..41f2d0cf0 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go @@ -458,6 +458,21 @@ func CopyFileRange(rfd int, roff *int64, wfd int, woff *int64, len int, flags in // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func DeleteModule(name string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(name) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_DELETE_MODULE, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Dup(oldfd int) (fd int, err error) { r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), 0, 0) fd = int(r0) @@ -606,6 +621,21 @@ func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func FinitModule(fd int, params string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(params) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FINIT_MODULE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flistxattr(fd int, dest []byte) (sz int, err error) { var _p0 unsafe.Pointer if len(dest) > 0 { @@ -807,6 +837,27 @@ func Getxattr(path string, attr string, dest []byte) (sz int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func InitModule(moduleImage []byte, params string) (err error) { + var _p0 unsafe.Pointer + if len(moduleImage) > 0 { + _p0 = unsafe.Pointer(&moduleImage[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + var _p1 *byte + _p1, err = BytePtrFromString(params) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_INIT_MODULE, uintptr(_p0), uintptr(len(moduleImage)), uintptr(unsafe.Pointer(_p1))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) { var _p0 *byte _p0, err = BytePtrFromString(pathname) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go index 260631d14..7e65fe0b7 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go @@ -458,6 +458,21 @@ func CopyFileRange(rfd int, roff *int64, wfd int, woff *int64, len int, flags in // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func DeleteModule(name string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(name) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_DELETE_MODULE, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Dup(oldfd int) (fd int, err error) { r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), 0, 0) fd = int(r0) @@ -606,6 +621,21 @@ func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func FinitModule(fd int, params string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(params) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FINIT_MODULE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flistxattr(fd int, dest []byte) (sz int, err error) { var _p0 unsafe.Pointer if len(dest) > 0 { @@ -807,6 +837,27 @@ func Getxattr(path string, attr string, dest []byte) (sz int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func InitModule(moduleImage []byte, params string) (err error) { + var _p0 unsafe.Pointer + if len(moduleImage) > 0 { + _p0 = unsafe.Pointer(&moduleImage[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + var _p1 *byte + _p1, err = BytePtrFromString(params) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_INIT_MODULE, uintptr(_p0), uintptr(len(moduleImage)), uintptr(unsafe.Pointer(_p1))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) { var _p0 *byte _p0, err = BytePtrFromString(pathname) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go index ff2d84fb9..fd06fb890 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go @@ -458,6 +458,21 @@ func CopyFileRange(rfd int, roff *int64, wfd int, woff *int64, len int, flags in // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func DeleteModule(name string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(name) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_DELETE_MODULE, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Dup(oldfd int) (fd int, err error) { r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), 0, 0) fd = int(r0) @@ -606,6 +621,21 @@ func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func FinitModule(fd int, params string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(params) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FINIT_MODULE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flistxattr(fd int, dest []byte) (sz int, err error) { var _p0 unsafe.Pointer if len(dest) > 0 { @@ -807,6 +837,27 @@ func Getxattr(path string, attr string, dest []byte) (sz int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func InitModule(moduleImage []byte, params string) (err error) { + var _p0 unsafe.Pointer + if len(moduleImage) > 0 { + _p0 = unsafe.Pointer(&moduleImage[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + var _p1 *byte + _p1, err = BytePtrFromString(params) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_INIT_MODULE, uintptr(_p0), uintptr(len(moduleImage)), uintptr(unsafe.Pointer(_p1))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) { var _p0 *byte _p0, err = BytePtrFromString(pathname) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go index 48d14e607..9e8ec28c9 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go @@ -458,6 +458,21 @@ func CopyFileRange(rfd int, roff *int64, wfd int, woff *int64, len int, flags in // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func DeleteModule(name string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(name) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_DELETE_MODULE, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Dup(oldfd int) (fd int, err error) { r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), 0, 0) fd = int(r0) @@ -606,6 +621,21 @@ func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func FinitModule(fd int, params string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(params) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FINIT_MODULE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flistxattr(fd int, dest []byte) (sz int, err error) { var _p0 unsafe.Pointer if len(dest) > 0 { @@ -807,6 +837,27 @@ func Getxattr(path string, attr string, dest []byte) (sz int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func InitModule(moduleImage []byte, params string) (err error) { + var _p0 unsafe.Pointer + if len(moduleImage) > 0 { + _p0 = unsafe.Pointer(&moduleImage[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + var _p1 *byte + _p1, err = BytePtrFromString(params) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_INIT_MODULE, uintptr(_p0), uintptr(len(moduleImage)), uintptr(unsafe.Pointer(_p1))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) { var _p0 *byte _p0, err = BytePtrFromString(pathname) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go index 12c17a92b..b4d2ccbb0 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go @@ -458,6 +458,21 @@ func CopyFileRange(rfd int, roff *int64, wfd int, woff *int64, len int, flags in // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func DeleteModule(name string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(name) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_DELETE_MODULE, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Dup(oldfd int) (fd int, err error) { r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), 0, 0) fd = int(r0) @@ -606,6 +621,21 @@ func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func FinitModule(fd int, params string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(params) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FINIT_MODULE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flistxattr(fd int, dest []byte) (sz int, err error) { var _p0 unsafe.Pointer if len(dest) > 0 { @@ -807,6 +837,27 @@ func Getxattr(path string, attr string, dest []byte) (sz int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func InitModule(moduleImage []byte, params string) (err error) { + var _p0 unsafe.Pointer + if len(moduleImage) > 0 { + _p0 = unsafe.Pointer(&moduleImage[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + var _p1 *byte + _p1, err = BytePtrFromString(params) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_INIT_MODULE, uintptr(_p0), uintptr(len(moduleImage)), uintptr(unsafe.Pointer(_p1))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) { var _p0 *byte _p0, err = BytePtrFromString(pathname) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go index c8ca4279e..bca3d2536 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go @@ -458,6 +458,21 @@ func CopyFileRange(rfd int, roff *int64, wfd int, woff *int64, len int, flags in // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func DeleteModule(name string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(name) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_DELETE_MODULE, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Dup(oldfd int) (fd int, err error) { r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), 0, 0) fd = int(r0) @@ -606,6 +621,21 @@ func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func FinitModule(fd int, params string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(params) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FINIT_MODULE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flistxattr(fd int, dest []byte) (sz int, err error) { var _p0 unsafe.Pointer if len(dest) > 0 { @@ -807,6 +837,27 @@ func Getxattr(path string, attr string, dest []byte) (sz int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func InitModule(moduleImage []byte, params string) (err error) { + var _p0 unsafe.Pointer + if len(moduleImage) > 0 { + _p0 = unsafe.Pointer(&moduleImage[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + var _p1 *byte + _p1, err = BytePtrFromString(params) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_INIT_MODULE, uintptr(_p0), uintptr(len(moduleImage)), uintptr(unsafe.Pointer(_p1))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) { var _p0 *byte _p0, err = BytePtrFromString(pathname) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go index 870c8f6db..e34089c66 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go @@ -458,6 +458,21 @@ func CopyFileRange(rfd int, roff *int64, wfd int, woff *int64, len int, flags in // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func DeleteModule(name string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(name) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_DELETE_MODULE, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Dup(oldfd int) (fd int, err error) { r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), 0, 0) fd = int(r0) @@ -606,6 +621,21 @@ func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func FinitModule(fd int, params string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(params) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FINIT_MODULE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flistxattr(fd int, dest []byte) (sz int, err error) { var _p0 unsafe.Pointer if len(dest) > 0 { @@ -807,6 +837,27 @@ func Getxattr(path string, attr string, dest []byte) (sz int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func InitModule(moduleImage []byte, params string) (err error) { + var _p0 unsafe.Pointer + if len(moduleImage) > 0 { + _p0 = unsafe.Pointer(&moduleImage[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + var _p1 *byte + _p1, err = BytePtrFromString(params) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_INIT_MODULE, uintptr(_p0), uintptr(len(moduleImage)), uintptr(unsafe.Pointer(_p1))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) { var _p0 *byte _p0, err = BytePtrFromString(pathname) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go index 542f3a3a3..312b2afaf 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go @@ -458,6 +458,21 @@ func CopyFileRange(rfd int, roff *int64, wfd int, woff *int64, len int, flags in // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func DeleteModule(name string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(name) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_DELETE_MODULE, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Dup(oldfd int) (fd int, err error) { r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), 0, 0) fd = int(r0) @@ -606,6 +621,21 @@ func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func FinitModule(fd int, params string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(params) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FINIT_MODULE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flistxattr(fd int, dest []byte) (sz int, err error) { var _p0 unsafe.Pointer if len(dest) > 0 { @@ -807,6 +837,27 @@ func Getxattr(path string, attr string, dest []byte) (sz int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func InitModule(moduleImage []byte, params string) (err error) { + var _p0 unsafe.Pointer + if len(moduleImage) > 0 { + _p0 = unsafe.Pointer(&moduleImage[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + var _p1 *byte + _p1, err = BytePtrFromString(params) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_INIT_MODULE, uintptr(_p0), uintptr(len(moduleImage)), uintptr(unsafe.Pointer(_p1))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) { var _p0 *byte _p0, err = BytePtrFromString(pathname) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go index 55e79d640..04ec8befe 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go @@ -458,6 +458,21 @@ func CopyFileRange(rfd int, roff *int64, wfd int, woff *int64, len int, flags in // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func DeleteModule(name string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(name) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_DELETE_MODULE, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Dup(oldfd int) (fd int, err error) { r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), 0, 0) fd = int(r0) @@ -606,6 +621,21 @@ func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func FinitModule(fd int, params string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(params) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FINIT_MODULE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flistxattr(fd int, dest []byte) (sz int, err error) { var _p0 unsafe.Pointer if len(dest) > 0 { @@ -807,6 +837,27 @@ func Getxattr(path string, attr string, dest []byte) (sz int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func InitModule(moduleImage []byte, params string) (err error) { + var _p0 unsafe.Pointer + if len(moduleImage) > 0 { + _p0 = unsafe.Pointer(&moduleImage[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + var _p1 *byte + _p1, err = BytePtrFromString(params) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_INIT_MODULE, uintptr(_p0), uintptr(len(moduleImage)), uintptr(unsafe.Pointer(_p1))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) { var _p0 *byte _p0, err = BytePtrFromString(pathname) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go index f1874d5a1..c0d856c55 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go @@ -1210,6 +1210,22 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Pathconf(path string, name int) (val int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go index eb8028397..1466a8ca1 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go @@ -1210,6 +1210,22 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Pathconf(path string, name int) (val int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go index 7b36499d5..2ca54f029 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go @@ -1210,6 +1210,22 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Pathconf(path string, name int) (val int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go index 1942049b0..082235681 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go @@ -431,6 +431,17 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { + r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Access(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1005,6 +1016,22 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Pathconf(path string, name int) (val int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go index d351c72cb..3d0bae427 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go @@ -431,6 +431,17 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { + r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Access(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1005,6 +1016,22 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Pathconf(path string, name int) (val int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go index 617d47f0f..6422c4605 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go @@ -431,6 +431,17 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { + r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Access(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1005,6 +1016,22 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Pathconf(path string, name int) (val int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go index a1db143f8..6e281d6b3 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go @@ -360,4 +360,5 @@ const ( SYS_PKEY_FREE = 396 SYS_STATX = 397 SYS_RSEQ = 398 + SYS_IO_PGETEVENTS = 399 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go index 2e4cee70d..f9157e192 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go @@ -284,4 +284,5 @@ const ( SYS_PKEY_FREE = 290 SYS_STATX = 291 SYS_IO_PGETEVENTS = 292 + SYS_RSEQ = 293 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go index 41e4fd1d3..a5d991915 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go @@ -283,4 +283,5 @@ const ( SYS_PKEY_FREE = 290 SYS_STATX = 291 SYS_IO_PGETEVENTS = 292 + SYS_RSEQ = 293 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_386.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_386.go index 07787301f..f93f391d2 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_386.go @@ -1,5 +1,5 @@ // mksysnum_openbsd.pl -// Code generated by the command above; DO NOT EDIT. +// Code generated by the command above; see README.md. DO NOT EDIT. // +build 386,openbsd @@ -12,6 +12,7 @@ const ( SYS_WRITE = 4 // { ssize_t sys_write(int fd, const void *buf, \ SYS_OPEN = 5 // { int sys_open(const char *path, \ SYS_CLOSE = 6 // { int sys_close(int fd); } + SYS_GETENTROPY = 7 // { int sys_getentropy(void *buf, size_t nbyte); } SYS___TFORK = 8 // { int sys___tfork(const struct __tfork *param, \ SYS_LINK = 9 // { int sys_link(const char *path, const char *link); } SYS_UNLINK = 10 // { int sys_unlink(const char *path); } @@ -37,11 +38,10 @@ const ( SYS_ACCEPT = 30 // { int sys_accept(int s, struct sockaddr *name, \ SYS_GETPEERNAME = 31 // { int sys_getpeername(int fdes, struct sockaddr *asa, \ SYS_GETSOCKNAME = 32 // { int sys_getsockname(int fdes, struct sockaddr *asa, \ - SYS_ACCESS = 33 // { int sys_access(const char *path, int flags); } + SYS_ACCESS = 33 // { int sys_access(const char *path, int amode); } SYS_CHFLAGS = 34 // { int sys_chflags(const char *path, u_int flags); } SYS_FCHFLAGS = 35 // { int sys_fchflags(int fd, u_int flags); } SYS_SYNC = 36 // { void sys_sync(void); } - SYS_KILL = 37 // { int sys_kill(int pid, int signum); } SYS_STAT = 38 // { int sys_stat(const char *path, struct stat *ub); } SYS_GETPPID = 39 // { pid_t sys_getppid(void); } SYS_LSTAT = 40 // { int sys_lstat(const char *path, struct stat *ub); } @@ -53,7 +53,6 @@ const ( SYS_SIGACTION = 46 // { int sys_sigaction(int signum, \ SYS_GETGID = 47 // { gid_t sys_getgid(void); } SYS_SIGPROCMASK = 48 // { int sys_sigprocmask(int how, sigset_t mask); } - SYS_GETLOGIN = 49 // { int sys_getlogin(char *namebuf, u_int namelen); } SYS_SETLOGIN = 50 // { int sys_setlogin(const char *namebuf); } SYS_ACCT = 51 // { int sys_acct(const char *path); } SYS_SIGPENDING = 52 // { int sys_sigpending(void); } @@ -62,7 +61,7 @@ const ( SYS_REBOOT = 55 // { int sys_reboot(int opt); } SYS_REVOKE = 56 // { int sys_revoke(const char *path); } SYS_SYMLINK = 57 // { int sys_symlink(const char *path, \ - SYS_READLINK = 58 // { int sys_readlink(const char *path, char *buf, \ + SYS_READLINK = 58 // { ssize_t sys_readlink(const char *path, \ SYS_EXECVE = 59 // { int sys_execve(const char *path, \ SYS_UMASK = 60 // { mode_t sys_umask(mode_t newmask); } SYS_CHROOT = 61 // { int sys_chroot(const char *path); } @@ -86,15 +85,18 @@ const ( SYS_GETGROUPS = 79 // { int sys_getgroups(int gidsetsize, \ SYS_SETGROUPS = 80 // { int sys_setgroups(int gidsetsize, \ SYS_GETPGRP = 81 // { int sys_getpgrp(void); } - SYS_SETPGID = 82 // { int sys_setpgid(pid_t pid, int pgid); } + SYS_SETPGID = 82 // { int sys_setpgid(pid_t pid, pid_t pgid); } + SYS_FUTEX = 83 // { int sys_futex(uint32_t *f, int op, int val, \ SYS_UTIMENSAT = 84 // { int sys_utimensat(int fd, const char *path, \ SYS_FUTIMENS = 85 // { int sys_futimens(int fd, \ + SYS_KBIND = 86 // { int sys_kbind(const struct __kbind *param, \ SYS_CLOCK_GETTIME = 87 // { int sys_clock_gettime(clockid_t clock_id, \ SYS_CLOCK_SETTIME = 88 // { int sys_clock_settime(clockid_t clock_id, \ SYS_CLOCK_GETRES = 89 // { int sys_clock_getres(clockid_t clock_id, \ SYS_DUP2 = 90 // { int sys_dup2(int from, int to); } SYS_NANOSLEEP = 91 // { int sys_nanosleep(const struct timespec *rqtp, \ SYS_FCNTL = 92 // { int sys_fcntl(int fd, int cmd, ... void *arg); } + SYS_ACCEPT4 = 93 // { int sys_accept4(int s, struct sockaddr *name, \ SYS___THRSLEEP = 94 // { int sys___thrsleep(const volatile void *ident, \ SYS_FSYNC = 95 // { int sys_fsync(int fd); } SYS_SETPRIORITY = 96 // { int sys_setpriority(int which, id_t who, int prio); } @@ -102,16 +104,24 @@ const ( SYS_CONNECT = 98 // { int sys_connect(int s, const struct sockaddr *name, \ SYS_GETDENTS = 99 // { int sys_getdents(int fd, void *buf, size_t buflen); } SYS_GETPRIORITY = 100 // { int sys_getpriority(int which, id_t who); } + SYS_PIPE2 = 101 // { int sys_pipe2(int *fdp, int flags); } + SYS_DUP3 = 102 // { int sys_dup3(int from, int to, int flags); } SYS_SIGRETURN = 103 // { int sys_sigreturn(struct sigcontext *sigcntxp); } SYS_BIND = 104 // { int sys_bind(int s, const struct sockaddr *name, \ SYS_SETSOCKOPT = 105 // { int sys_setsockopt(int s, int level, int name, \ SYS_LISTEN = 106 // { int sys_listen(int s, int backlog); } + SYS_CHFLAGSAT = 107 // { int sys_chflagsat(int fd, const char *path, \ + SYS_PLEDGE = 108 // { int sys_pledge(const char *promises, \ SYS_PPOLL = 109 // { int sys_ppoll(struct pollfd *fds, \ SYS_PSELECT = 110 // { int sys_pselect(int nd, fd_set *in, fd_set *ou, \ SYS_SIGSUSPEND = 111 // { int sys_sigsuspend(int mask); } + SYS_SENDSYSLOG = 112 // { int sys_sendsyslog(const char *buf, size_t nbyte, \ + SYS_UNVEIL = 114 // { int sys_unveil(const char *path, \ SYS_GETSOCKOPT = 118 // { int sys_getsockopt(int s, int level, int name, \ + SYS_THRKILL = 119 // { int sys_thrkill(pid_t tid, int signum, void *tcb); } SYS_READV = 120 // { ssize_t sys_readv(int fd, \ SYS_WRITEV = 121 // { ssize_t sys_writev(int fd, \ + SYS_KILL = 122 // { int sys_kill(int pid, int signum); } SYS_FCHOWN = 123 // { int sys_fchown(int fd, uid_t uid, gid_t gid); } SYS_FCHMOD = 124 // { int sys_fchmod(int fd, mode_t mode); } SYS_SETREUID = 126 // { int sys_setreuid(uid_t ruid, uid_t euid); } @@ -125,6 +135,7 @@ const ( SYS_MKDIR = 136 // { int sys_mkdir(const char *path, mode_t mode); } SYS_RMDIR = 137 // { int sys_rmdir(const char *path); } SYS_ADJTIME = 140 // { int sys_adjtime(const struct timeval *delta, \ + SYS_GETLOGIN_R = 141 // { int sys_getlogin_r(char *namebuf, u_int namelen); } SYS_SETSID = 147 // { int sys_setsid(void); } SYS_QUOTACTL = 148 // { int sys_quotactl(const char *path, int cmd, \ SYS_NFSSVC = 155 // { int sys_nfssvc(int flag, void *argp); } @@ -144,7 +155,7 @@ const ( SYS_LSEEK = 199 // { off_t sys_lseek(int fd, int pad, off_t offset, \ SYS_TRUNCATE = 200 // { int sys_truncate(const char *path, int pad, \ SYS_FTRUNCATE = 201 // { int sys_ftruncate(int fd, int pad, off_t length); } - SYS___SYSCTL = 202 // { int sys___sysctl(const int *name, u_int namelen, \ + SYS_SYSCTL = 202 // { int sys_sysctl(const int *name, u_int namelen, \ SYS_MLOCK = 203 // { int sys_mlock(const void *addr, size_t len); } SYS_MUNLOCK = 204 // { int sys_munlock(const void *addr, size_t len); } SYS_GETPGID = 207 // { pid_t sys_getpgid(pid_t pid); } diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm.go index 7a1693acb..be1198d91 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm.go @@ -1,5 +1,5 @@ // mksysnum_openbsd.pl -// Code generated by the command above; DO NOT EDIT. +// Code generated by the command above; see README.md. DO NOT EDIT. // +build arm,openbsd @@ -53,7 +53,6 @@ const ( SYS_SIGACTION = 46 // { int sys_sigaction(int signum, \ SYS_GETGID = 47 // { gid_t sys_getgid(void); } SYS_SIGPROCMASK = 48 // { int sys_sigprocmask(int how, sigset_t mask); } - SYS_GETLOGIN = 49 // { int sys_getlogin(char *namebuf, u_int namelen); } SYS_SETLOGIN = 50 // { int sys_setlogin(const char *namebuf); } SYS_ACCT = 51 // { int sys_acct(const char *path); } SYS_SIGPENDING = 52 // { int sys_sigpending(void); } @@ -87,9 +86,10 @@ const ( SYS_SETGROUPS = 80 // { int sys_setgroups(int gidsetsize, \ SYS_GETPGRP = 81 // { int sys_getpgrp(void); } SYS_SETPGID = 82 // { int sys_setpgid(pid_t pid, pid_t pgid); } - SYS_SENDSYSLOG = 83 // { int sys_sendsyslog(const void *buf, size_t nbyte); } + SYS_FUTEX = 83 // { int sys_futex(uint32_t *f, int op, int val, \ SYS_UTIMENSAT = 84 // { int sys_utimensat(int fd, const char *path, \ SYS_FUTIMENS = 85 // { int sys_futimens(int fd, \ + SYS_KBIND = 86 // { int sys_kbind(const struct __kbind *param, \ SYS_CLOCK_GETTIME = 87 // { int sys_clock_gettime(clockid_t clock_id, \ SYS_CLOCK_SETTIME = 88 // { int sys_clock_settime(clockid_t clock_id, \ SYS_CLOCK_GETRES = 89 // { int sys_clock_getres(clockid_t clock_id, \ @@ -111,10 +111,14 @@ const ( SYS_SETSOCKOPT = 105 // { int sys_setsockopt(int s, int level, int name, \ SYS_LISTEN = 106 // { int sys_listen(int s, int backlog); } SYS_CHFLAGSAT = 107 // { int sys_chflagsat(int fd, const char *path, \ + SYS_PLEDGE = 108 // { int sys_pledge(const char *promises, \ SYS_PPOLL = 109 // { int sys_ppoll(struct pollfd *fds, \ SYS_PSELECT = 110 // { int sys_pselect(int nd, fd_set *in, fd_set *ou, \ SYS_SIGSUSPEND = 111 // { int sys_sigsuspend(int mask); } + SYS_SENDSYSLOG = 112 // { int sys_sendsyslog(const char *buf, size_t nbyte, \ + SYS_UNVEIL = 114 // { int sys_unveil(const char *path, \ SYS_GETSOCKOPT = 118 // { int sys_getsockopt(int s, int level, int name, \ + SYS_THRKILL = 119 // { int sys_thrkill(pid_t tid, int signum, void *tcb); } SYS_READV = 120 // { ssize_t sys_readv(int fd, \ SYS_WRITEV = 121 // { ssize_t sys_writev(int fd, \ SYS_KILL = 122 // { int sys_kill(int pid, int signum); } @@ -131,6 +135,7 @@ const ( SYS_MKDIR = 136 // { int sys_mkdir(const char *path, mode_t mode); } SYS_RMDIR = 137 // { int sys_rmdir(const char *path); } SYS_ADJTIME = 140 // { int sys_adjtime(const struct timeval *delta, \ + SYS_GETLOGIN_R = 141 // { int sys_getlogin_r(char *namebuf, u_int namelen); } SYS_SETSID = 147 // { int sys_setsid(void); } SYS_QUOTACTL = 148 // { int sys_quotactl(const char *path, int cmd, \ SYS_NFSSVC = 155 // { int sys_nfssvc(int flag, void *argp); } @@ -150,7 +155,7 @@ const ( SYS_LSEEK = 199 // { off_t sys_lseek(int fd, int pad, off_t offset, \ SYS_TRUNCATE = 200 // { int sys_truncate(const char *path, int pad, \ SYS_FTRUNCATE = 201 // { int sys_ftruncate(int fd, int pad, off_t length); } - SYS___SYSCTL = 202 // { int sys___sysctl(const int *name, u_int namelen, \ + SYS_SYSCTL = 202 // { int sys_sysctl(const int *name, u_int namelen, \ SYS_MLOCK = 203 // { int sys_mlock(const void *addr, size_t len); } SYS_MUNLOCK = 204 // { int sys_munlock(const void *addr, size_t len); } SYS_GETPGID = 207 // { pid_t sys_getpgid(pid_t pid); } diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go index 11380294a..28ef5242f 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go @@ -56,28 +56,84 @@ type Rlimit struct { type _Gid_t uint32 +const ( + _statfsVersion = 0x20140518 + _dirblksiz = 0x400 +) + type Stat_t struct { - Dev uint32 - Ino uint32 - Mode uint16 - Nlink uint16 - Uid uint32 - Gid uint32 - Rdev uint32 - Atimespec Timespec - Mtimespec Timespec - Ctimespec Timespec - Size int64 - Blocks int64 - Blksize int32 - Flags uint32 - Gen uint32 - Lspare int32 - Birthtimespec Timespec - Pad_cgo_0 [8]byte + Dev uint64 + Ino uint64 + Nlink uint64 + Mode uint16 + _0 int16 + Uid uint32 + Gid uint32 + _1 int32 + Rdev uint64 + Atim_ext int32 + Atim Timespec + Mtim_ext int32 + Mtim Timespec + Ctim_ext int32 + Ctim Timespec + Btim_ext int32 + Birthtim Timespec + Size int64 + Blocks int64 + Blksize int32 + Flags uint32 + Gen uint64 + Spare [10]uint64 +} + +type stat_freebsd11_t struct { + Dev uint32 + Ino uint32 + Mode uint16 + Nlink uint16 + Uid uint32 + Gid uint32 + Rdev uint32 + Atim Timespec + Mtim Timespec + Ctim Timespec + Size int64 + Blocks int64 + Blksize int32 + Flags uint32 + Gen uint32 + Lspare int32 + Birthtim Timespec + _ [8]byte } type Statfs_t struct { + Version uint32 + Type uint32 + Flags uint64 + Bsize uint64 + Iosize uint64 + Blocks uint64 + Bfree uint64 + Bavail int64 + Files uint64 + Ffree int64 + Syncwrites uint64 + Asyncwrites uint64 + Syncreads uint64 + Asyncreads uint64 + Spare [10]uint64 + Namemax uint32 + Owner uint32 + Fsid Fsid + Charspare [80]int8 + Fstypename [16]int8 + Mntfromname [1024]int8 + Mntonname [1024]int8 +} + +type statfs_freebsd11_t struct { Version uint32 Type uint32 Flags uint64 @@ -112,6 +168,17 @@ type Flock_t struct { } type Dirent struct { + Fileno uint64 + Off int64 + Reclen uint16 + Type uint8 + Pad0 uint8 + Namlen uint16 + Pad1 uint16 + Name [256]int8 +} + +type dirent_freebsd11 struct { Fileno uint32 Reclen uint16 Type uint8 @@ -272,7 +339,7 @@ type Kevent_t struct { } type FdSet struct { - X__fds_bits [32]uint32 + _ [32]uint32 } const ( @@ -288,53 +355,53 @@ const ( ) type ifMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte - Data ifData + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte + Data ifData } type IfMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte - Data IfData + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte + Data IfData } type ifData struct { - Type uint8 - Physical uint8 - Addrlen uint8 - Hdrlen uint8 - Link_state uint8 - Vhid uint8 - Datalen uint16 - Mtu uint32 - Metric uint32 - Baudrate uint64 - Ipackets uint64 - Ierrors uint64 - Opackets uint64 - Oerrors uint64 - Collisions uint64 - Ibytes uint64 - Obytes uint64 - Imcasts uint64 - Omcasts uint64 - Iqdrops uint64 - Oqdrops uint64 - Noproto uint64 - Hwassist uint64 - X__ifi_epoch [8]byte - X__ifi_lastchange [16]byte + Type uint8 + Physical uint8 + Addrlen uint8 + Hdrlen uint8 + Link_state uint8 + Vhid uint8 + Datalen uint16 + Mtu uint32 + Metric uint32 + Baudrate uint64 + Ipackets uint64 + Ierrors uint64 + Opackets uint64 + Oerrors uint64 + Collisions uint64 + Ibytes uint64 + Obytes uint64 + Imcasts uint64 + Omcasts uint64 + Iqdrops uint64 + Oqdrops uint64 + Noproto uint64 + Hwassist uint64 + _ [8]byte + _ [16]byte } type IfData struct { @@ -366,24 +433,24 @@ type IfData struct { } type IfaMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte - Metric int32 + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte + Metric int32 } type IfmaMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte } type IfAnnounceMsghdr struct { @@ -396,19 +463,19 @@ type IfAnnounceMsghdr struct { } type RtMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Index uint16 - Pad_cgo_0 [2]byte - Flags int32 - Addrs int32 - Pid int32 - Seq int32 - Errno int32 - Fmask int32 - Inits uint32 - Rmx RtMetrics + Msglen uint16 + Version uint8 + Type uint8 + Index uint16 + _ [2]byte + Flags int32 + Addrs int32 + Pid int32 + Seq int32 + Errno int32 + Fmask int32 + Inits uint32 + Rmx RtMetrics } type RtMetrics struct { @@ -465,18 +532,18 @@ type BpfInsn struct { } type BpfHdr struct { - Tstamp Timeval - Caplen uint32 - Datalen uint32 - Hdrlen uint16 - Pad_cgo_0 [2]byte + Tstamp Timeval + Caplen uint32 + Datalen uint32 + Hdrlen uint16 + _ [2]byte } type BpfZbufHeader struct { Kernel_gen uint32 Kernel_len uint32 User_gen uint32 - X_bzh_pad [5]uint32 + _ [5]uint32 } type Termios struct { diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go index a6fc12718..e2d984a48 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go @@ -56,27 +56,79 @@ type Rlimit struct { type _Gid_t uint32 +const ( + _statfsVersion = 0x20140518 + _dirblksiz = 0x400 +) + type Stat_t struct { - Dev uint32 - Ino uint32 - Mode uint16 - Nlink uint16 - Uid uint32 - Gid uint32 - Rdev uint32 - Atimespec Timespec - Mtimespec Timespec - Ctimespec Timespec - Size int64 - Blocks int64 - Blksize int32 - Flags uint32 - Gen uint32 - Lspare int32 - Birthtimespec Timespec + Dev uint64 + Ino uint64 + Nlink uint64 + Mode uint16 + _0 int16 + Uid uint32 + Gid uint32 + _1 int32 + Rdev uint64 + Atim Timespec + Mtim Timespec + Ctim Timespec + Birthtim Timespec + Size int64 + Blocks int64 + Blksize int32 + Flags uint32 + Gen uint64 + Spare [10]uint64 +} + +type stat_freebsd11_t struct { + Dev uint32 + Ino uint32 + Mode uint16 + Nlink uint16 + Uid uint32 + Gid uint32 + Rdev uint32 + Atim Timespec + Mtim Timespec + Ctim Timespec + Size int64 + Blocks int64 + Blksize int32 + Flags uint32 + Gen uint32 + Lspare int32 + Birthtim Timespec } type Statfs_t struct { + Version uint32 + Type uint32 + Flags uint64 + Bsize uint64 + Iosize uint64 + Blocks uint64 + Bfree uint64 + Bavail int64 + Files uint64 + Ffree int64 + Syncwrites uint64 + Asyncwrites uint64 + Syncreads uint64 + Asyncreads uint64 + Spare [10]uint64 + Namemax uint32 + Owner uint32 + Fsid Fsid + Charspare [80]int8 + Fstypename [16]int8 + Mntfromname [1024]int8 + Mntonname [1024]int8 +} + +type statfs_freebsd11_t struct { Version uint32 Type uint32 Flags uint64 @@ -102,16 +154,27 @@ type Statfs_t struct { } type Flock_t struct { - Start int64 - Len int64 - Pid int32 - Type int16 - Whence int16 - Sysid int32 - Pad_cgo_0 [4]byte + Start int64 + Len int64 + Pid int32 + Type int16 + Whence int16 + Sysid int32 + _ [4]byte } type Dirent struct { + Fileno uint64 + Off int64 + Reclen uint16 + Type uint8 + Pad0 uint8 + Namlen uint16 + Pad1 uint16 + Name [256]int8 +} + +type dirent_freebsd11 struct { Fileno uint32 Reclen uint16 Type uint8 @@ -212,10 +275,10 @@ type IPv6Mreq struct { type Msghdr struct { Name *byte Namelen uint32 - Pad_cgo_0 [4]byte + _ [4]byte Iov *Iovec Iovlen int32 - Pad_cgo_1 [4]byte + _ [4]byte Control *byte Controllen uint32 Flags int32 @@ -274,7 +337,7 @@ type Kevent_t struct { } type FdSet struct { - X__fds_bits [16]uint64 + _ [16]uint64 } const ( @@ -290,53 +353,53 @@ const ( ) type ifMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte - Data ifData + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte + Data ifData } type IfMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte - Data IfData + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte + Data IfData } type ifData struct { - Type uint8 - Physical uint8 - Addrlen uint8 - Hdrlen uint8 - Link_state uint8 - Vhid uint8 - Datalen uint16 - Mtu uint32 - Metric uint32 - Baudrate uint64 - Ipackets uint64 - Ierrors uint64 - Opackets uint64 - Oerrors uint64 - Collisions uint64 - Ibytes uint64 - Obytes uint64 - Imcasts uint64 - Omcasts uint64 - Iqdrops uint64 - Oqdrops uint64 - Noproto uint64 - Hwassist uint64 - X__ifi_epoch [8]byte - X__ifi_lastchange [16]byte + Type uint8 + Physical uint8 + Addrlen uint8 + Hdrlen uint8 + Link_state uint8 + Vhid uint8 + Datalen uint16 + Mtu uint32 + Metric uint32 + Baudrate uint64 + Ipackets uint64 + Ierrors uint64 + Opackets uint64 + Oerrors uint64 + Collisions uint64 + Ibytes uint64 + Obytes uint64 + Imcasts uint64 + Omcasts uint64 + Iqdrops uint64 + Oqdrops uint64 + Noproto uint64 + Hwassist uint64 + _ [8]byte + _ [16]byte } type IfData struct { @@ -368,24 +431,24 @@ type IfData struct { } type IfaMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte - Metric int32 + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte + Metric int32 } type IfmaMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte } type IfAnnounceMsghdr struct { @@ -398,19 +461,19 @@ type IfAnnounceMsghdr struct { } type RtMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Index uint16 - Pad_cgo_0 [2]byte - Flags int32 - Addrs int32 - Pid int32 - Seq int32 - Errno int32 - Fmask int32 - Inits uint64 - Rmx RtMetrics + Msglen uint16 + Version uint8 + Type uint8 + Index uint16 + _ [2]byte + Flags int32 + Addrs int32 + Pid int32 + Seq int32 + Errno int32 + Fmask int32 + Inits uint64 + Rmx RtMetrics } type RtMetrics struct { @@ -455,9 +518,9 @@ type BpfZbuf struct { } type BpfProgram struct { - Len uint32 - Pad_cgo_0 [4]byte - Insns *BpfInsn + Len uint32 + _ [4]byte + Insns *BpfInsn } type BpfInsn struct { @@ -468,18 +531,18 @@ type BpfInsn struct { } type BpfHdr struct { - Tstamp Timeval - Caplen uint32 - Datalen uint32 - Hdrlen uint16 - Pad_cgo_0 [6]byte + Tstamp Timeval + Caplen uint32 + Datalen uint32 + Hdrlen uint16 + _ [6]byte } type BpfZbufHeader struct { Kernel_gen uint32 Kernel_len uint32 User_gen uint32 - X_bzh_pad [5]uint32 + _ [5]uint32 } type Termios struct { diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go index 6b3006d6b..9b415aba4 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go @@ -21,15 +21,15 @@ type ( ) type Timespec struct { - Sec int64 - Nsec int32 - Pad_cgo_0 [4]byte + Sec int64 + Nsec int32 + _ [4]byte } type Timeval struct { - Sec int64 - Usec int32 - Pad_cgo_0 [4]byte + Sec int64 + Usec int32 + _ [4]byte } type Rusage struct { @@ -58,27 +58,79 @@ type Rlimit struct { type _Gid_t uint32 +const ( + _statfsVersion = 0x20140518 + _dirblksiz = 0x400 +) + type Stat_t struct { - Dev uint32 - Ino uint32 - Mode uint16 - Nlink uint16 - Uid uint32 - Gid uint32 - Rdev uint32 - Atimespec Timespec - Mtimespec Timespec - Ctimespec Timespec - Size int64 - Blocks int64 - Blksize int32 - Flags uint32 - Gen uint32 - Lspare int32 - Birthtimespec Timespec + Dev uint64 + Ino uint64 + Nlink uint64 + Mode uint16 + _0 int16 + Uid uint32 + Gid uint32 + _1 int32 + Rdev uint64 + Atim Timespec + Mtim Timespec + Ctim Timespec + Birthtim Timespec + Size int64 + Blocks int64 + Blksize int32 + Flags uint32 + Gen uint64 + Spare [10]uint64 +} + +type stat_freebsd11_t struct { + Dev uint32 + Ino uint32 + Mode uint16 + Nlink uint16 + Uid uint32 + Gid uint32 + Rdev uint32 + Atim Timespec + Mtim Timespec + Ctim Timespec + Size int64 + Blocks int64 + Blksize int32 + Flags uint32 + Gen uint32 + Lspare int32 + Birthtim Timespec } type Statfs_t struct { + Version uint32 + Type uint32 + Flags uint64 + Bsize uint64 + Iosize uint64 + Blocks uint64 + Bfree uint64 + Bavail int64 + Files uint64 + Ffree int64 + Syncwrites uint64 + Asyncwrites uint64 + Syncreads uint64 + Asyncreads uint64 + Spare [10]uint64 + Namemax uint32 + Owner uint32 + Fsid Fsid + Charspare [80]int8 + Fstypename [16]int8 + Mntfromname [1024]int8 + Mntonname [1024]int8 +} + +type statfs_freebsd11_t struct { Version uint32 Type uint32 Flags uint64 @@ -104,16 +156,27 @@ type Statfs_t struct { } type Flock_t struct { - Start int64 - Len int64 - Pid int32 - Type int16 - Whence int16 - Sysid int32 - Pad_cgo_0 [4]byte + Start int64 + Len int64 + Pid int32 + Type int16 + Whence int16 + Sysid int32 + _ [4]byte } type Dirent struct { + Fileno uint64 + Off int64 + Reclen uint16 + Type uint8 + Pad0 uint8 + Namlen uint16 + Pad1 uint16 + Name [256]int8 +} + +type dirent_freebsd11 struct { Fileno uint32 Reclen uint16 Type uint8 @@ -274,7 +337,7 @@ type Kevent_t struct { } type FdSet struct { - X__fds_bits [32]uint32 + _ [32]uint32 } const ( @@ -290,53 +353,53 @@ const ( ) type ifMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte - Data ifData + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte + Data ifData } type IfMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte - Data IfData + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte + Data IfData } type ifData struct { - Type uint8 - Physical uint8 - Addrlen uint8 - Hdrlen uint8 - Link_state uint8 - Vhid uint8 - Datalen uint16 - Mtu uint32 - Metric uint32 - Baudrate uint64 - Ipackets uint64 - Ierrors uint64 - Opackets uint64 - Oerrors uint64 - Collisions uint64 - Ibytes uint64 - Obytes uint64 - Imcasts uint64 - Omcasts uint64 - Iqdrops uint64 - Oqdrops uint64 - Noproto uint64 - Hwassist uint64 - X__ifi_epoch [8]byte - X__ifi_lastchange [16]byte + Type uint8 + Physical uint8 + Addrlen uint8 + Hdrlen uint8 + Link_state uint8 + Vhid uint8 + Datalen uint16 + Mtu uint32 + Metric uint32 + Baudrate uint64 + Ipackets uint64 + Ierrors uint64 + Opackets uint64 + Oerrors uint64 + Collisions uint64 + Ibytes uint64 + Obytes uint64 + Imcasts uint64 + Omcasts uint64 + Iqdrops uint64 + Oqdrops uint64 + Noproto uint64 + Hwassist uint64 + _ [8]byte + _ [16]byte } type IfData struct { @@ -363,30 +426,30 @@ type IfData struct { Iqdrops uint32 Noproto uint32 Hwassist uint32 - Pad_cgo_0 [4]byte + _ [4]byte Epoch int64 Lastchange Timeval } type IfaMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte - Metric int32 + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte + Metric int32 } type IfmaMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte } type IfAnnounceMsghdr struct { @@ -399,19 +462,19 @@ type IfAnnounceMsghdr struct { } type RtMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Index uint16 - Pad_cgo_0 [2]byte - Flags int32 - Addrs int32 - Pid int32 - Seq int32 - Errno int32 - Fmask int32 - Inits uint32 - Rmx RtMetrics + Msglen uint16 + Version uint8 + Type uint8 + Index uint16 + _ [2]byte + Flags int32 + Addrs int32 + Pid int32 + Seq int32 + Errno int32 + Fmask int32 + Inits uint32 + Rmx RtMetrics } type RtMetrics struct { @@ -468,18 +531,18 @@ type BpfInsn struct { } type BpfHdr struct { - Tstamp Timeval - Caplen uint32 - Datalen uint32 - Hdrlen uint16 - Pad_cgo_0 [6]byte + Tstamp Timeval + Caplen uint32 + Datalen uint32 + Hdrlen uint16 + _ [6]byte } type BpfZbufHeader struct { Kernel_gen uint32 Kernel_len uint32 User_gen uint32 - X_bzh_pad [5]uint32 + _ [5]uint32 } type Termios struct { diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index 3879002a9..5f8f03492 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -494,7 +494,7 @@ const ( IFLA_EVENT = 0x2c IFLA_NEW_NETNSID = 0x2d IFLA_IF_NETNSID = 0x2e - IFLA_MAX = 0x31 + IFLA_MAX = 0x33 RT_SCOPE_UNIVERSE = 0x0 RT_SCOPE_SITE = 0xc8 RT_SCOPE_LINK = 0xfd @@ -1965,3 +1965,24 @@ const ( NCSI_CHANNEL_ATTR_VLAN_LIST = 0x9 NCSI_CHANNEL_ATTR_VLAN_ID = 0xa ) + +const ( + SOF_TIMESTAMPING_TX_HARDWARE = 0x1 + SOF_TIMESTAMPING_TX_SOFTWARE = 0x2 + SOF_TIMESTAMPING_RX_HARDWARE = 0x4 + SOF_TIMESTAMPING_RX_SOFTWARE = 0x8 + SOF_TIMESTAMPING_SOFTWARE = 0x10 + SOF_TIMESTAMPING_SYS_HARDWARE = 0x20 + SOF_TIMESTAMPING_RAW_HARDWARE = 0x40 + SOF_TIMESTAMPING_OPT_ID = 0x80 + SOF_TIMESTAMPING_TX_SCHED = 0x100 + SOF_TIMESTAMPING_TX_ACK = 0x200 + SOF_TIMESTAMPING_OPT_CMSG = 0x400 + SOF_TIMESTAMPING_OPT_TSONLY = 0x800 + SOF_TIMESTAMPING_OPT_STATS = 0x1000 + SOF_TIMESTAMPING_OPT_PKTINFO = 0x2000 + SOF_TIMESTAMPING_OPT_TX_SWHW = 0x4000 + + SOF_TIMESTAMPING_LAST = 0x4000 + SOF_TIMESTAMPING_MASK = 0x7fff +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index cbc2c7d07..aa52a439d 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -498,7 +498,7 @@ const ( IFLA_EVENT = 0x2c IFLA_NEW_NETNSID = 0x2d IFLA_IF_NETNSID = 0x2e - IFLA_MAX = 0x31 + IFLA_MAX = 0x33 RT_SCOPE_UNIVERSE = 0x0 RT_SCOPE_SITE = 0xc8 RT_SCOPE_LINK = 0xfd @@ -1987,3 +1987,24 @@ const ( NCSI_CHANNEL_ATTR_VLAN_LIST = 0x9 NCSI_CHANNEL_ATTR_VLAN_ID = 0xa ) + +const ( + SOF_TIMESTAMPING_TX_HARDWARE = 0x1 + SOF_TIMESTAMPING_TX_SOFTWARE = 0x2 + SOF_TIMESTAMPING_RX_HARDWARE = 0x4 + SOF_TIMESTAMPING_RX_SOFTWARE = 0x8 + SOF_TIMESTAMPING_SOFTWARE = 0x10 + SOF_TIMESTAMPING_SYS_HARDWARE = 0x20 + SOF_TIMESTAMPING_RAW_HARDWARE = 0x40 + SOF_TIMESTAMPING_OPT_ID = 0x80 + SOF_TIMESTAMPING_TX_SCHED = 0x100 + SOF_TIMESTAMPING_TX_ACK = 0x200 + SOF_TIMESTAMPING_OPT_CMSG = 0x400 + SOF_TIMESTAMPING_OPT_TSONLY = 0x800 + SOF_TIMESTAMPING_OPT_STATS = 0x1000 + SOF_TIMESTAMPING_OPT_PKTINFO = 0x2000 + SOF_TIMESTAMPING_OPT_TX_SWHW = 0x4000 + + SOF_TIMESTAMPING_LAST = 0x4000 + SOF_TIMESTAMPING_MASK = 0x7fff +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index 6ed804fa3..23c8438be 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -497,7 +497,7 @@ const ( IFLA_EVENT = 0x2c IFLA_NEW_NETNSID = 0x2d IFLA_IF_NETNSID = 0x2e - IFLA_MAX = 0x31 + IFLA_MAX = 0x33 RT_SCOPE_UNIVERSE = 0x0 RT_SCOPE_SITE = 0xc8 RT_SCOPE_LINK = 0xfd @@ -1955,3 +1955,24 @@ const ( NCSI_CHANNEL_ATTR_VLAN_LIST = 0x9 NCSI_CHANNEL_ATTR_VLAN_ID = 0xa ) + +const ( + SOF_TIMESTAMPING_TX_HARDWARE = 0x1 + SOF_TIMESTAMPING_TX_SOFTWARE = 0x2 + SOF_TIMESTAMPING_RX_HARDWARE = 0x4 + SOF_TIMESTAMPING_RX_SOFTWARE = 0x8 + SOF_TIMESTAMPING_SOFTWARE = 0x10 + SOF_TIMESTAMPING_SYS_HARDWARE = 0x20 + SOF_TIMESTAMPING_RAW_HARDWARE = 0x40 + SOF_TIMESTAMPING_OPT_ID = 0x80 + SOF_TIMESTAMPING_TX_SCHED = 0x100 + SOF_TIMESTAMPING_TX_ACK = 0x200 + SOF_TIMESTAMPING_OPT_CMSG = 0x400 + SOF_TIMESTAMPING_OPT_TSONLY = 0x800 + SOF_TIMESTAMPING_OPT_STATS = 0x1000 + SOF_TIMESTAMPING_OPT_PKTINFO = 0x2000 + SOF_TIMESTAMPING_OPT_TX_SWHW = 0x4000 + + SOF_TIMESTAMPING_LAST = 0x4000 + SOF_TIMESTAMPING_MASK = 0x7fff +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index b5fe7ddf7..d7a993e25 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -499,7 +499,7 @@ const ( IFLA_EVENT = 0x2c IFLA_NEW_NETNSID = 0x2d IFLA_IF_NETNSID = 0x2e - IFLA_MAX = 0x31 + IFLA_MAX = 0x33 RT_SCOPE_UNIVERSE = 0x0 RT_SCOPE_SITE = 0xc8 RT_SCOPE_LINK = 0xfd @@ -1966,3 +1966,24 @@ const ( NCSI_CHANNEL_ATTR_VLAN_LIST = 0x9 NCSI_CHANNEL_ATTR_VLAN_ID = 0xa ) + +const ( + SOF_TIMESTAMPING_TX_HARDWARE = 0x1 + SOF_TIMESTAMPING_TX_SOFTWARE = 0x2 + SOF_TIMESTAMPING_RX_HARDWARE = 0x4 + SOF_TIMESTAMPING_RX_SOFTWARE = 0x8 + SOF_TIMESTAMPING_SOFTWARE = 0x10 + SOF_TIMESTAMPING_SYS_HARDWARE = 0x20 + SOF_TIMESTAMPING_RAW_HARDWARE = 0x40 + SOF_TIMESTAMPING_OPT_ID = 0x80 + SOF_TIMESTAMPING_TX_SCHED = 0x100 + SOF_TIMESTAMPING_TX_ACK = 0x200 + SOF_TIMESTAMPING_OPT_CMSG = 0x400 + SOF_TIMESTAMPING_OPT_TSONLY = 0x800 + SOF_TIMESTAMPING_OPT_STATS = 0x1000 + SOF_TIMESTAMPING_OPT_PKTINFO = 0x2000 + SOF_TIMESTAMPING_OPT_TX_SWHW = 0x4000 + + SOF_TIMESTAMPING_LAST = 0x4000 + SOF_TIMESTAMPING_MASK = 0x7fff +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index 7379ad2d8..b8c3d0a4d 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -495,7 +495,7 @@ const ( IFLA_EVENT = 0x2c IFLA_NEW_NETNSID = 0x2d IFLA_IF_NETNSID = 0x2e - IFLA_MAX = 0x31 + IFLA_MAX = 0x33 RT_SCOPE_UNIVERSE = 0x0 RT_SCOPE_SITE = 0xc8 RT_SCOPE_LINK = 0xfd @@ -1960,3 +1960,24 @@ const ( NCSI_CHANNEL_ATTR_VLAN_LIST = 0x9 NCSI_CHANNEL_ATTR_VLAN_ID = 0xa ) + +const ( + SOF_TIMESTAMPING_TX_HARDWARE = 0x1 + SOF_TIMESTAMPING_TX_SOFTWARE = 0x2 + SOF_TIMESTAMPING_RX_HARDWARE = 0x4 + SOF_TIMESTAMPING_RX_SOFTWARE = 0x8 + SOF_TIMESTAMPING_SOFTWARE = 0x10 + SOF_TIMESTAMPING_SYS_HARDWARE = 0x20 + SOF_TIMESTAMPING_RAW_HARDWARE = 0x40 + SOF_TIMESTAMPING_OPT_ID = 0x80 + SOF_TIMESTAMPING_TX_SCHED = 0x100 + SOF_TIMESTAMPING_TX_ACK = 0x200 + SOF_TIMESTAMPING_OPT_CMSG = 0x400 + SOF_TIMESTAMPING_OPT_TSONLY = 0x800 + SOF_TIMESTAMPING_OPT_STATS = 0x1000 + SOF_TIMESTAMPING_OPT_PKTINFO = 0x2000 + SOF_TIMESTAMPING_OPT_TX_SWHW = 0x4000 + + SOF_TIMESTAMPING_LAST = 0x4000 + SOF_TIMESTAMPING_MASK = 0x7fff +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index 0b131a24e..a6f76149a 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -499,7 +499,7 @@ const ( IFLA_EVENT = 0x2c IFLA_NEW_NETNSID = 0x2d IFLA_IF_NETNSID = 0x2e - IFLA_MAX = 0x31 + IFLA_MAX = 0x33 RT_SCOPE_UNIVERSE = 0x0 RT_SCOPE_SITE = 0xc8 RT_SCOPE_LINK = 0xfd @@ -1968,3 +1968,24 @@ const ( NCSI_CHANNEL_ATTR_VLAN_LIST = 0x9 NCSI_CHANNEL_ATTR_VLAN_ID = 0xa ) + +const ( + SOF_TIMESTAMPING_TX_HARDWARE = 0x1 + SOF_TIMESTAMPING_TX_SOFTWARE = 0x2 + SOF_TIMESTAMPING_RX_HARDWARE = 0x4 + SOF_TIMESTAMPING_RX_SOFTWARE = 0x8 + SOF_TIMESTAMPING_SOFTWARE = 0x10 + SOF_TIMESTAMPING_SYS_HARDWARE = 0x20 + SOF_TIMESTAMPING_RAW_HARDWARE = 0x40 + SOF_TIMESTAMPING_OPT_ID = 0x80 + SOF_TIMESTAMPING_TX_SCHED = 0x100 + SOF_TIMESTAMPING_TX_ACK = 0x200 + SOF_TIMESTAMPING_OPT_CMSG = 0x400 + SOF_TIMESTAMPING_OPT_TSONLY = 0x800 + SOF_TIMESTAMPING_OPT_STATS = 0x1000 + SOF_TIMESTAMPING_OPT_PKTINFO = 0x2000 + SOF_TIMESTAMPING_OPT_TX_SWHW = 0x4000 + + SOF_TIMESTAMPING_LAST = 0x4000 + SOF_TIMESTAMPING_MASK = 0x7fff +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index 9191020cc..3dd194176 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -499,7 +499,7 @@ const ( IFLA_EVENT = 0x2c IFLA_NEW_NETNSID = 0x2d IFLA_IF_NETNSID = 0x2e - IFLA_MAX = 0x31 + IFLA_MAX = 0x33 RT_SCOPE_UNIVERSE = 0x0 RT_SCOPE_SITE = 0xc8 RT_SCOPE_LINK = 0xfd @@ -1968,3 +1968,24 @@ const ( NCSI_CHANNEL_ATTR_VLAN_LIST = 0x9 NCSI_CHANNEL_ATTR_VLAN_ID = 0xa ) + +const ( + SOF_TIMESTAMPING_TX_HARDWARE = 0x1 + SOF_TIMESTAMPING_TX_SOFTWARE = 0x2 + SOF_TIMESTAMPING_RX_HARDWARE = 0x4 + SOF_TIMESTAMPING_RX_SOFTWARE = 0x8 + SOF_TIMESTAMPING_SOFTWARE = 0x10 + SOF_TIMESTAMPING_SYS_HARDWARE = 0x20 + SOF_TIMESTAMPING_RAW_HARDWARE = 0x40 + SOF_TIMESTAMPING_OPT_ID = 0x80 + SOF_TIMESTAMPING_TX_SCHED = 0x100 + SOF_TIMESTAMPING_TX_ACK = 0x200 + SOF_TIMESTAMPING_OPT_CMSG = 0x400 + SOF_TIMESTAMPING_OPT_TSONLY = 0x800 + SOF_TIMESTAMPING_OPT_STATS = 0x1000 + SOF_TIMESTAMPING_OPT_PKTINFO = 0x2000 + SOF_TIMESTAMPING_OPT_TX_SWHW = 0x4000 + + SOF_TIMESTAMPING_LAST = 0x4000 + SOF_TIMESTAMPING_MASK = 0x7fff +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index 8fcad32bf..210de76cc 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -495,7 +495,7 @@ const ( IFLA_EVENT = 0x2c IFLA_NEW_NETNSID = 0x2d IFLA_IF_NETNSID = 0x2e - IFLA_MAX = 0x31 + IFLA_MAX = 0x33 RT_SCOPE_UNIVERSE = 0x0 RT_SCOPE_SITE = 0xc8 RT_SCOPE_LINK = 0xfd @@ -1960,3 +1960,24 @@ const ( NCSI_CHANNEL_ATTR_VLAN_LIST = 0x9 NCSI_CHANNEL_ATTR_VLAN_ID = 0xa ) + +const ( + SOF_TIMESTAMPING_TX_HARDWARE = 0x1 + SOF_TIMESTAMPING_TX_SOFTWARE = 0x2 + SOF_TIMESTAMPING_RX_HARDWARE = 0x4 + SOF_TIMESTAMPING_RX_SOFTWARE = 0x8 + SOF_TIMESTAMPING_SOFTWARE = 0x10 + SOF_TIMESTAMPING_SYS_HARDWARE = 0x20 + SOF_TIMESTAMPING_RAW_HARDWARE = 0x40 + SOF_TIMESTAMPING_OPT_ID = 0x80 + SOF_TIMESTAMPING_TX_SCHED = 0x100 + SOF_TIMESTAMPING_TX_ACK = 0x200 + SOF_TIMESTAMPING_OPT_CMSG = 0x400 + SOF_TIMESTAMPING_OPT_TSONLY = 0x800 + SOF_TIMESTAMPING_OPT_STATS = 0x1000 + SOF_TIMESTAMPING_OPT_PKTINFO = 0x2000 + SOF_TIMESTAMPING_OPT_TX_SWHW = 0x4000 + + SOF_TIMESTAMPING_LAST = 0x4000 + SOF_TIMESTAMPING_MASK = 0x7fff +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index a9d1b6c9f..b46d54e37 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -500,7 +500,7 @@ const ( IFLA_EVENT = 0x2c IFLA_NEW_NETNSID = 0x2d IFLA_IF_NETNSID = 0x2e - IFLA_MAX = 0x31 + IFLA_MAX = 0x33 RT_SCOPE_UNIVERSE = 0x0 RT_SCOPE_SITE = 0xc8 RT_SCOPE_LINK = 0xfd @@ -1976,3 +1976,24 @@ const ( NCSI_CHANNEL_ATTR_VLAN_LIST = 0x9 NCSI_CHANNEL_ATTR_VLAN_ID = 0xa ) + +const ( + SOF_TIMESTAMPING_TX_HARDWARE = 0x1 + SOF_TIMESTAMPING_TX_SOFTWARE = 0x2 + SOF_TIMESTAMPING_RX_HARDWARE = 0x4 + SOF_TIMESTAMPING_RX_SOFTWARE = 0x8 + SOF_TIMESTAMPING_SOFTWARE = 0x10 + SOF_TIMESTAMPING_SYS_HARDWARE = 0x20 + SOF_TIMESTAMPING_RAW_HARDWARE = 0x40 + SOF_TIMESTAMPING_OPT_ID = 0x80 + SOF_TIMESTAMPING_TX_SCHED = 0x100 + SOF_TIMESTAMPING_TX_ACK = 0x200 + SOF_TIMESTAMPING_OPT_CMSG = 0x400 + SOF_TIMESTAMPING_OPT_TSONLY = 0x800 + SOF_TIMESTAMPING_OPT_STATS = 0x1000 + SOF_TIMESTAMPING_OPT_PKTINFO = 0x2000 + SOF_TIMESTAMPING_OPT_TX_SWHW = 0x4000 + + SOF_TIMESTAMPING_LAST = 0x4000 + SOF_TIMESTAMPING_MASK = 0x7fff +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index f0f5214a5..6ee799cef 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -500,7 +500,7 @@ const ( IFLA_EVENT = 0x2c IFLA_NEW_NETNSID = 0x2d IFLA_IF_NETNSID = 0x2e - IFLA_MAX = 0x31 + IFLA_MAX = 0x33 RT_SCOPE_UNIVERSE = 0x0 RT_SCOPE_SITE = 0xc8 RT_SCOPE_LINK = 0xfd @@ -1976,3 +1976,24 @@ const ( NCSI_CHANNEL_ATTR_VLAN_LIST = 0x9 NCSI_CHANNEL_ATTR_VLAN_ID = 0xa ) + +const ( + SOF_TIMESTAMPING_TX_HARDWARE = 0x1 + SOF_TIMESTAMPING_TX_SOFTWARE = 0x2 + SOF_TIMESTAMPING_RX_HARDWARE = 0x4 + SOF_TIMESTAMPING_RX_SOFTWARE = 0x8 + SOF_TIMESTAMPING_SOFTWARE = 0x10 + SOF_TIMESTAMPING_SYS_HARDWARE = 0x20 + SOF_TIMESTAMPING_RAW_HARDWARE = 0x40 + SOF_TIMESTAMPING_OPT_ID = 0x80 + SOF_TIMESTAMPING_TX_SCHED = 0x100 + SOF_TIMESTAMPING_TX_ACK = 0x200 + SOF_TIMESTAMPING_OPT_CMSG = 0x400 + SOF_TIMESTAMPING_OPT_TSONLY = 0x800 + SOF_TIMESTAMPING_OPT_STATS = 0x1000 + SOF_TIMESTAMPING_OPT_PKTINFO = 0x2000 + SOF_TIMESTAMPING_OPT_TX_SWHW = 0x4000 + + SOF_TIMESTAMPING_LAST = 0x4000 + SOF_TIMESTAMPING_MASK = 0x7fff +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go index 09c905866..60ae71e62 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go @@ -499,7 +499,7 @@ const ( IFLA_EVENT = 0x2c IFLA_NEW_NETNSID = 0x2d IFLA_IF_NETNSID = 0x2e - IFLA_MAX = 0x31 + IFLA_MAX = 0x33 RT_SCOPE_UNIVERSE = 0x0 RT_SCOPE_SITE = 0xc8 RT_SCOPE_LINK = 0xfd @@ -1993,3 +1993,24 @@ const ( NCSI_CHANNEL_ATTR_VLAN_LIST = 0x9 NCSI_CHANNEL_ATTR_VLAN_ID = 0xa ) + +const ( + SOF_TIMESTAMPING_TX_HARDWARE = 0x1 + SOF_TIMESTAMPING_TX_SOFTWARE = 0x2 + SOF_TIMESTAMPING_RX_HARDWARE = 0x4 + SOF_TIMESTAMPING_RX_SOFTWARE = 0x8 + SOF_TIMESTAMPING_SOFTWARE = 0x10 + SOF_TIMESTAMPING_SYS_HARDWARE = 0x20 + SOF_TIMESTAMPING_RAW_HARDWARE = 0x40 + SOF_TIMESTAMPING_OPT_ID = 0x80 + SOF_TIMESTAMPING_TX_SCHED = 0x100 + SOF_TIMESTAMPING_TX_ACK = 0x200 + SOF_TIMESTAMPING_OPT_CMSG = 0x400 + SOF_TIMESTAMPING_OPT_TSONLY = 0x800 + SOF_TIMESTAMPING_OPT_STATS = 0x1000 + SOF_TIMESTAMPING_OPT_PKTINFO = 0x2000 + SOF_TIMESTAMPING_OPT_TX_SWHW = 0x4000 + + SOF_TIMESTAMPING_LAST = 0x4000 + SOF_TIMESTAMPING_MASK = 0x7fff +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index 5e86e496c..dea88f7bb 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -498,7 +498,7 @@ const ( IFLA_EVENT = 0x2c IFLA_NEW_NETNSID = 0x2d IFLA_IF_NETNSID = 0x2e - IFLA_MAX = 0x31 + IFLA_MAX = 0x33 RT_SCOPE_UNIVERSE = 0x0 RT_SCOPE_SITE = 0xc8 RT_SCOPE_LINK = 0xfd @@ -1993,3 +1993,24 @@ const ( NCSI_CHANNEL_ATTR_VLAN_LIST = 0x9 NCSI_CHANNEL_ATTR_VLAN_ID = 0xa ) + +const ( + SOF_TIMESTAMPING_TX_HARDWARE = 0x1 + SOF_TIMESTAMPING_TX_SOFTWARE = 0x2 + SOF_TIMESTAMPING_RX_HARDWARE = 0x4 + SOF_TIMESTAMPING_RX_SOFTWARE = 0x8 + SOF_TIMESTAMPING_SOFTWARE = 0x10 + SOF_TIMESTAMPING_SYS_HARDWARE = 0x20 + SOF_TIMESTAMPING_RAW_HARDWARE = 0x40 + SOF_TIMESTAMPING_OPT_ID = 0x80 + SOF_TIMESTAMPING_TX_SCHED = 0x100 + SOF_TIMESTAMPING_TX_ACK = 0x200 + SOF_TIMESTAMPING_OPT_CMSG = 0x400 + SOF_TIMESTAMPING_OPT_TSONLY = 0x800 + SOF_TIMESTAMPING_OPT_STATS = 0x1000 + SOF_TIMESTAMPING_OPT_PKTINFO = 0x2000 + SOF_TIMESTAMPING_OPT_TX_SWHW = 0x4000 + + SOF_TIMESTAMPING_LAST = 0x4000 + SOF_TIMESTAMPING_MASK = 0x7fff +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go b/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go index c8509bf0e..8b37d8399 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go @@ -458,6 +458,8 @@ const ( POLLWRNORM = 0x4 ) +type Sigset_t uint32 + type Utsname struct { Sysname [256]byte Nodename [256]byte diff --git a/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go index 200575d94..6efea4635 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go @@ -458,6 +458,8 @@ const ( POLLWRNORM = 0x4 ) +type Sigset_t uint32 + type Utsname struct { Sysname [256]byte Nodename [256]byte diff --git a/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go b/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go index 3e20cdf09..87a637e3f 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go @@ -451,6 +451,8 @@ const ( POLLWRNORM = 0x4 ) +type Sigset_t uint32 + type Utsname struct { Sysname [256]byte Nodename [256]byte diff --git a/worker/db.go b/worker/db.go index dd2478eb4..a49209bb8 100644 --- a/worker/db.go +++ b/worker/db.go @@ -22,6 +22,7 @@ import ( "io" "os" "path/filepath" + "runtime/trace" "strings" "sync" "time" @@ -180,9 +181,10 @@ func (db *Database) UpdatePeers(peers *kayak.Peers) (err error) { // Query defines database query interface. func (db *Database) Query(request *wt.Request) (response *wt.Response, err error) { - if err = request.Verify(); err != nil { - return - } + // Just need to verify signature in db.saveAck + //if err = request.Verify(); err != nil { + // return + //} switch request.Header.QueryType { case wt.ReadQuery: @@ -197,9 +199,10 @@ func (db *Database) Query(request *wt.Request) (response *wt.Response, err error // Ack defines client response ack interface. func (db *Database) Ack(ack *wt.Ack) (err error) { - if err = ack.Verify(); err != nil { - return - } + // Just need to verify signature in db.saveAck + //if err = ack.Verify(); err != nil { + // return + //} return db.saveAck(&ack.Header) } @@ -255,6 +258,11 @@ func (db *Database) Destroy() (err error) { } func (db *Database) writeQuery(request *wt.Request) (response *wt.Response, err error) { + ctx := context.Background() + ctx, task := trace.NewTask(ctx, "writeQuery") + defer task.End() + defer trace.StartRegion(ctx, "writeQueryRegion").End() + // check database size first, wal/kayak/chain database size is not included if db.cfg.SpaceLimit > 0 { path := filepath.Join(db.cfg.DataDir, StorageFileName) @@ -319,9 +327,6 @@ func (db *Database) buildQueryResponse(request *wt.Request, offset uint64, response.Header.LogOffset = offset response.Header.Timestamp = getLocalTime() response.Header.RowCount = uint64(len(data)) - if response.Header.Signee, err = getLocalPubKey(); err != nil { - return - } // set payload response.Payload.Columns = columns @@ -358,10 +363,6 @@ func getLocalTime() time.Time { return time.Now().UTC() } -func getLocalPubKey() (pubKey *asymmetric.PublicKey, err error) { - return kms.GetLocalPublicKey() -} - func getLocalPrivateKey() (privateKey *asymmetric.PrivateKey, err error) { return kms.GetLocalPrivateKey() } @@ -409,7 +410,10 @@ func convertAndSanitizeQuery(inQuery []wt.Query) (outQuery []storage.Query, err query = "SELECT name FROM sqlite_master WHERE type = \"table\"" } - log.Debugf("translated query from %v to %v", origQuery, query) + log.WithFields(log.Fields{ + "from": origQuery, + "to": query, + }).Debug("query translated") } originalQueries = append(originalQueries, query) diff --git a/worker/db_test.go b/worker/db_test.go index 31e4afe0b..4e576bc5c 100644 --- a/worker/db_test.go +++ b/worker/db_test.go @@ -44,6 +44,7 @@ import ( "github.com/CovenantSQL/CovenantSQL/sqlchain" ct "github.com/CovenantSQL/CovenantSQL/sqlchain/types" "github.com/CovenantSQL/CovenantSQL/utils" + "github.com/CovenantSQL/CovenantSQL/utils/log" wt "github.com/CovenantSQL/CovenantSQL/worker/types" "github.com/fortytw2/leaktest" . "github.com/smartystreets/goconvey/convey" @@ -54,6 +55,7 @@ var rootHash = hash.Hash{} const PubKeyStorePath = "./public.keystore" func TestSingleDatabase(t *testing.T) { + log.SetLevel(log.DebugLevel) // init as single node database Convey("test database", t, func() { var err error @@ -125,8 +127,24 @@ func TestSingleDatabase(t *testing.T) { So(res.Payload.Rows[0].Values, ShouldNotBeEmpty) So(res.Payload.Rows[0].Values[0], ShouldResemble, []byte("test")) - // test show create table + // test show full tables query readQuery, err = buildQuery(wt.ReadQuery, 1, 3, []string{ + "show full tables", + }) + So(err, ShouldBeNil) + + res, err = db.Query(readQuery) + So(err, ShouldBeNil) + err = res.Verify() + So(err, ShouldBeNil) + + So(res.Header.RowCount, ShouldEqual, uint64(1)) + So(res.Payload.Rows, ShouldNotBeEmpty) + So(res.Payload.Rows[0].Values, ShouldNotBeEmpty) + So(res.Payload.Rows[0].Values[0], ShouldResemble, []byte("test")) + + // test show create table + readQuery, err = buildQuery(wt.ReadQuery, 1, 4, []string{ "show create table test", }) So(err, ShouldBeNil) @@ -144,7 +162,7 @@ func TestSingleDatabase(t *testing.T) { So(strings.ToUpper(string(byteStr)), ShouldContainSubstring, "CREATE") // test show table - readQuery, err = buildQuery(wt.ReadQuery, 1, 4, []string{ + readQuery, err = buildQuery(wt.ReadQuery, 1, 5, []string{ "show table test", }) So(err, ShouldBeNil) @@ -162,7 +180,7 @@ func TestSingleDatabase(t *testing.T) { So(res.Payload.Rows[1].Values[1], ShouldResemble, []byte("col2")) // test desc table - readQuery, err = buildQuery(wt.ReadQuery, 1, 5, []string{ + readQuery, err = buildQuery(wt.ReadQuery, 1, 6, []string{ "desc test", }) So(err, ShouldBeNil) @@ -180,7 +198,7 @@ func TestSingleDatabase(t *testing.T) { So(res.Payload.Rows[1].Values[1], ShouldResemble, []byte("col2")) // test show index from table - readQuery, err = buildQuery(wt.ReadQuery, 1, 6, []string{ + readQuery, err = buildQuery(wt.ReadQuery, 1, 7, []string{ "show index from table test", }) So(err, ShouldBeNil) @@ -533,10 +551,9 @@ func buildAck(res *wt.Response) (ack *wt.Ack, err error) { } // get private/public key - var pubKey *asymmetric.PublicKey var privateKey *asymmetric.PrivateKey - if privateKey, pubKey, err = getKeys(); err != nil { + if privateKey, _, err = getKeys(); err != nil { return } @@ -547,11 +564,10 @@ func buildAck(res *wt.Response) (ack *wt.Ack, err error) { NodeID: nodeID, Timestamp: getLocalTime(), }, - Signee: pubKey, }, } - err = ack.Sign(privateKey) + err = ack.Sign(privateKey, true) return } @@ -576,10 +592,9 @@ func buildQueryEx(queryType wt.QueryType, connID uint64, seqNo uint64, timeShift } // get private/public key - var pubKey *asymmetric.PublicKey var privateKey *asymmetric.PrivateKey - if privateKey, pubKey, err = getKeys(); err != nil { + if privateKey, _, err = getKeys(); err != nil { return } @@ -603,7 +618,6 @@ func buildQueryEx(queryType wt.QueryType, connID uint64, seqNo uint64, timeShift SeqNo: seqNo, Timestamp: tm, }, - Signee: pubKey, }, Payload: wt.RequestPayload{ Queries: realQueries, @@ -693,12 +707,12 @@ func initNode() (cleanupFunc func(), server *rpc.Server, err error) { } // init rpc - if server, err = rpc.NewServerWithService(rpc.ServiceMap{"DHT": dht}); err != nil { + if server, err = rpc.NewServerWithService(rpc.ServiceMap{route.DHTRPCName: dht}); err != nil { return } // register bpdb service - if err = server.RegisterService(bp.DBServiceName, &stubBPDBService{}); err != nil { + if err = server.RegisterService(route.BPDBRPCName, &stubBPDBService{}); err != nil { return } @@ -743,8 +757,6 @@ func createRandomBlock(parent hash.Hash, isGenesis bool) (b *ct.Block, err error ParentHash: parent, Timestamp: time.Now().UTC(), }, - Signee: pub, - Signature: nil, }, Queries: make([]*hash.Hash, rand.Intn(10)+10), } diff --git a/worker/dbms.go b/worker/dbms.go index e945d5b88..4eb6ff748 100644 --- a/worker/dbms.go +++ b/worker/dbms.go @@ -23,6 +23,8 @@ import ( "path/filepath" "sync" + "github.com/pkg/errors" + ka "github.com/CovenantSQL/CovenantSQL/kayak/api" kt "github.com/CovenantSQL/CovenantSQL/kayak/transport" "github.com/CovenantSQL/CovenantSQL/proto" @@ -38,12 +40,6 @@ const ( // DBKayakRPCName defines rpc service name of database internal consensus. DBKayakRPCName = "DBC" // aka. database consensus - // SQLChainRPCName defines rpc service name of sql-chain internal consensus. - SQLChainRPCName = "SQLC" - - // DBServiceRPCName defines rpc service name of database external query api. - DBServiceRPCName = "DBS" // aka. database service - // DBMetaFileName defines dbms meta file name. DBMetaFileName = "db.meta" ) @@ -67,10 +63,10 @@ func NewDBMS(cfg *DBMSConfig) (dbms *DBMS, err error) { dbms.kayakMux = ka.NewMuxService(DBKayakRPCName, cfg.Server) // init sql-chain rpc mux - dbms.chainMux = sqlchain.NewMuxService(SQLChainRPCName, cfg.Server) + dbms.chainMux = sqlchain.NewMuxService(route.SQLChainRPCName, cfg.Server) // init service - dbms.rpc = NewDBMSRPCService(DBServiceRPCName, cfg.Server, dbms) + dbms.rpc = NewDBMSRPCService(route.DBRPCName, cfg.Server, dbms) return } @@ -127,17 +123,20 @@ func (dbms *DBMS) Init() (err error) { // read meta var localMeta *DBMSMeta if localMeta, err = dbms.readMeta(); err != nil { + err = errors.Wrap(err, "read dbms meta failed") return } // load current peers info from block producer var dbMapping []wt.ServiceInstance if dbMapping, err = dbms.getMappedInstances(); err != nil { + err = errors.Wrap(err, "get mapped instances failed") return } // init database if err = dbms.initDatabases(localMeta, dbMapping); err != nil { + err = errors.Wrap(err, "init databases with meta failed") return } @@ -364,7 +363,7 @@ func (dbms *DBMS) Shutdown() (err error) { db := rawDB.(*Database) if err = db.Shutdown(); err != nil { - log.Errorf("shutdown database failed: %v", err) + log.WithError(err).Error("shutdown database failed") } return true diff --git a/worker/dbms_rpc.go b/worker/dbms_rpc.go index 20c74eb87..b75cc9407 100644 --- a/worker/dbms_rpc.go +++ b/worker/dbms_rpc.go @@ -17,9 +17,18 @@ package worker import ( + "context" + "runtime/trace" + "github.com/CovenantSQL/CovenantSQL/route" "github.com/CovenantSQL/CovenantSQL/rpc" wt "github.com/CovenantSQL/CovenantSQL/worker/types" + "github.com/rcrowley/go-metrics" +) + +var ( + dbQuerySuccCounter metrics.Meter + dbQueryFailCounter metrics.Meter ) // DBMSRPCService is the rpc endpoint of database management. @@ -34,39 +43,55 @@ func NewDBMSRPCService(serviceName string, server *rpc.Server, dbms *DBMS) (serv } server.RegisterService(serviceName, service) + dbQuerySuccCounter = metrics.NewMeter() + metrics.Register("db-query-succ", dbQuerySuccCounter) + dbQueryFailCounter = metrics.NewMeter() + metrics.Register("db-query-fail", dbQueryFailCounter) + return } // Query rpc, called by client to issue read/write query. func (rpc *DBMSRPCService) Query(req *wt.Request, res *wt.Response) (err error) { - // verify checksum/signature - if err = req.Verify(); err != nil { - return - } - + // Just need to verify signature in db.saveAck + //if err = req.Verify(); err != nil { + // dbQueryFailCounter.Mark(1) + // return + //} + ctx := context.Background() + ctx, task := trace.NewTask(ctx, "Query") + defer task.End() + defer trace.StartRegion(ctx, "QueryRegion").End() // verify query is sent from the request node if req.Envelope.NodeID.String() != string(req.Header.NodeID) { // node id mismatch err = ErrInvalidRequest + dbQueryFailCounter.Mark(1) return } var r *wt.Response if r, err = rpc.dbms.Query(req); err != nil { + dbQueryFailCounter.Mark(1) return } *res = *r + dbQuerySuccCounter.Mark(1) return } // Ack rpc, called by client to confirm read request. func (rpc *DBMSRPCService) Ack(ack *wt.Ack, _ *wt.AckResponse) (err error) { - // verify checksum/signature - if err = ack.Verify(); err != nil { - return - } + // Just need to verify signature in db.saveAck + //if err = ack.Verify(); err != nil { + // return + //} + ctx := context.Background() + ctx, task := trace.NewTask(ctx, "Ack") + defer task.End() + defer trace.StartRegion(ctx, "AckRegion").End() // verify if ack node is the original ack node if ack.Envelope.NodeID.String() != string(ack.Header.Response.Request.NodeID) { diff --git a/worker/dbms_test.go b/worker/dbms_test.go index f04d48554..a0f2875ae 100644 --- a/worker/dbms_test.go +++ b/worker/dbms_test.go @@ -41,9 +41,6 @@ func TestDBMS(t *testing.T) { cleanup, server, err = initNode() So(err, ShouldBeNil) - var pubKey *asymmetric.PublicKey - pubKey, err = kms.GetLocalPublicKey() - So(err, ShouldBeNil) var privateKey *asymmetric.PrivateKey privateKey, err = kms.GetLocalPrivateKey() So(err, ShouldBeNil) @@ -90,7 +87,6 @@ func TestDBMS(t *testing.T) { Peers: peers, GenesisBlock: block, } - req.Header.Signee = pubKey err = req.Sign(privateKey) So(err, ShouldBeNil) @@ -179,7 +175,6 @@ func TestDBMS(t *testing.T) { DatabaseID: dbID, Peers: peers, } - req.Header.Signee = pubKey err = req.Sign(privateKey) So(err, ShouldBeNil) @@ -194,7 +189,6 @@ func TestDBMS(t *testing.T) { req.Header.Instance = wt.ServiceInstance{ DatabaseID: dbID, } - req.Header.Signee = pubKey err = req.Sign(privateKey) So(err, ShouldBeNil) diff --git a/worker/types/ack_type.go b/worker/types/ack_type.go index a5deb68b7..564c70cf4 100644 --- a/worker/types/ack_type.go +++ b/worker/types/ack_type.go @@ -30,23 +30,23 @@ import ( // AckHeader defines client ack entity. type AckHeader struct { - Response SignedResponseHeader - NodeID proto.NodeID // ack node id - Timestamp time.Time // time in UTC zone + Response SignedResponseHeader `json:"r"` + NodeID proto.NodeID `json:"i"` // ack node id + Timestamp time.Time `json:"t"` // time in UTC zone } // SignedAckHeader defines client signed ack entity. type SignedAckHeader struct { AckHeader - HeaderHash hash.Hash - Signee *asymmetric.PublicKey - Signature *asymmetric.Signature + HeaderHash hash.Hash `json:"hh"` + Signee *asymmetric.PublicKey `json:"e"` + Signature *asymmetric.Signature `json:"s"` } // Ack defines a whole client ack request entity. type Ack struct { proto.Envelope - Header SignedAckHeader + Header SignedAckHeader `json:"h"` } // AckResponse defines client ack response entity. @@ -109,10 +109,13 @@ func (sh *SignedAckHeader) Verify() (err error) { } // Sign the request. -func (sh *SignedAckHeader) Sign(signer *asymmetric.PrivateKey) (err error) { - // check original header signature - if err = sh.Response.Verify(); err != nil { - return +func (sh *SignedAckHeader) Sign(signer *asymmetric.PrivateKey, verifyReqHeader bool) (err error) { + // Only used by ack worker, and ack.Header is verified before build ack + if verifyReqHeader { + // check original header signature + if err = sh.Response.Verify(); err != nil { + return + } } // build hash @@ -120,6 +123,7 @@ func (sh *SignedAckHeader) Sign(signer *asymmetric.PrivateKey) (err error) { // sign sh.Signature, err = signer.Sign(sh.HeaderHash[:]) + sh.Signee = signer.PubKey() return } @@ -139,9 +143,9 @@ func (a *Ack) Verify() error { } // Sign the request. -func (a *Ack) Sign(signer *asymmetric.PrivateKey) (err error) { +func (a *Ack) Sign(signer *asymmetric.PrivateKey, verifyReqHeader bool) (err error) { // sign - return a.Header.Sign(signer) + return a.Header.Sign(signer, verifyReqHeader) } // ResponseHeaderHash returns the deep shadowed Response HeaderHash field. diff --git a/worker/types/init_service_type.go b/worker/types/init_service_type.go index cc87a6c51..8c97f1c5e 100644 --- a/worker/types/init_service_type.go +++ b/worker/types/init_service_type.go @@ -166,6 +166,7 @@ func (sh *SignedInitServiceResponseHeader) Sign(signer *asymmetric.PrivateKey) ( // sign sh.Signature, err = signer.Sign(sh.HeaderHash[:]) + sh.Signee = signer.PubKey() return } diff --git a/worker/types/no_ack_report_type.go b/worker/types/no_ack_report_type.go index 5d67eece1..aa163176e 100644 --- a/worker/types/no_ack_report_type.go +++ b/worker/types/no_ack_report_type.go @@ -141,6 +141,7 @@ func (sh *SignedNoAckReportHeader) Sign(signer *asymmetric.PrivateKey) (err erro // sign sh.Signature, err = signer.Sign(sh.HeaderHash[:]) + sh.Signee = signer.PubKey() return } @@ -240,6 +241,7 @@ func (sh *SignedAggrNoAckReportHeader) Sign(signer *asymmetric.PrivateKey) (err // verify signature sh.Signature, err = signer.Sign(sh.HeaderHash[:]) + sh.Signee = signer.PubKey() return } diff --git a/worker/types/request_type.go b/worker/types/request_type.go index c58095973..26101475b 100644 --- a/worker/types/request_type.go +++ b/worker/types/request_type.go @@ -60,41 +60,41 @@ func (t QueryType) String() string { // RequestPayload defines a queries payload. type RequestPayload struct { - Queries []Query + Queries []Query `json:"qs"` } // RequestHeader defines a query request header. type RequestHeader struct { - QueryType QueryType - NodeID proto.NodeID // request node id - DatabaseID proto.DatabaseID // request database id - ConnectionID uint64 - SeqNo uint64 - Timestamp time.Time // time in UTC zone - BatchCount uint64 // query count in this request - QueriesHash hash.Hash // hash of query payload + QueryType QueryType `json:"qt"` + NodeID proto.NodeID `json:"id"` // request node id + DatabaseID proto.DatabaseID `json:"dbid"` // request database id + ConnectionID uint64 `json:"cid"` + SeqNo uint64 `json:"seq"` + Timestamp time.Time `json:"t"` // time in UTC zone + BatchCount uint64 `json:"bc"` // query count in this request + QueriesHash hash.Hash `json:"qh"` // hash of query payload } // QueryKey defines an unique query key of a request. type QueryKey struct { - NodeID proto.NodeID - ConnectionID uint64 - SeqNo uint64 + NodeID proto.NodeID `json:"id"` + ConnectionID uint64 `json:"cid"` + SeqNo uint64 `json:"seq"` } // SignedRequestHeader defines a signed query request header. type SignedRequestHeader struct { RequestHeader - HeaderHash hash.Hash - Signee *asymmetric.PublicKey - Signature *asymmetric.Signature + HeaderHash hash.Hash `json:"hh"` + Signee *asymmetric.PublicKey `json:"e"` + Signature *asymmetric.Signature `json:"s"` } // Request defines a complete query request. type Request struct { proto.Envelope - Header SignedRequestHeader - Payload RequestPayload + Header SignedRequestHeader `json:"h"` + Payload RequestPayload `json:"p"` } // Serialize returns byte based binary form of struct. @@ -168,12 +168,13 @@ func (sh *SignedRequestHeader) Sign(signer *asymmetric.PrivateKey) (err error) { // compute hash buildHash(&sh.RequestHeader, &sh.HeaderHash) - if sh.Signee == nil || signer == nil { + if signer == nil { return ErrSignRequest } // sign sh.Signature, err = signer.Sign(sh.HeaderHash[:]) + sh.Signee = signer.PubKey() return } diff --git a/worker/types/response_type.go b/worker/types/response_type.go index e2a28abac..1f0d3ee77 100644 --- a/worker/types/response_type.go +++ b/worker/types/response_type.go @@ -37,33 +37,33 @@ type ResponseRow struct { // ResponsePayload defines column names and rows of query response. type ResponsePayload struct { - Columns []string - DeclTypes []string - Rows []ResponseRow + Columns []string `json:"c"` + DeclTypes []string `json:"t"` + Rows []ResponseRow `json:"r"` } // ResponseHeader defines a query response header. type ResponseHeader struct { - Request SignedRequestHeader - NodeID proto.NodeID // response node id - Timestamp time.Time // time in UTC zone - RowCount uint64 // response row count of payload - LogOffset uint64 // request log offset - DataHash hash.Hash // hash of query response + Request SignedRequestHeader `json:"r"` + NodeID proto.NodeID `json:"id"` // response node id + Timestamp time.Time `json:"t"` // time in UTC zone + RowCount uint64 `json:"c"` // response row count of payload + LogOffset uint64 `json:"o"` // request log offset + DataHash hash.Hash `json:"dh"` // hash of query response } // SignedResponseHeader defines a signed query response header. type SignedResponseHeader struct { ResponseHeader - HeaderHash hash.Hash - Signee *asymmetric.PublicKey - Signature *asymmetric.Signature + HeaderHash hash.Hash `json:"h"` + Signee *asymmetric.PublicKey `json:"e"` + Signature *asymmetric.Signature `json:"s"` } // Response defines a complete query response. type Response struct { - Header SignedResponseHeader - Payload ResponsePayload + Header SignedResponseHeader `json:"h"` + Payload ResponsePayload `json:"p"` } // Serialize structure to bytes. @@ -174,6 +174,7 @@ func (sh *SignedResponseHeader) Sign(signer *asymmetric.PrivateKey) (err error) // sign sh.Signature, err = signer.Sign(sh.HeaderHash[:]) + sh.Signee = signer.PubKey() return } diff --git a/worker/types/response_type_gen.go b/worker/types/response_type_gen.go index 3126d6e1c..8ce0f4c36 100644 --- a/worker/types/response_type_gen.go +++ b/worker/types/response_type_gen.go @@ -36,35 +36,37 @@ func (z *Response) Msgsize() (s int) { func (z *ResponseHeader) MarshalHash() (o []byte, err error) { var b []byte o = hsp.Require(b, z.Msgsize()) - // map header, size 5 - o = append(o, 0x85, 0x85) + // map header, size 6 + o = append(o, 0x86, 0x86) if oTemp, err := z.Request.MarshalHash(); err != nil { return nil, err } else { o = hsp.AppendBytes(o, oTemp) } - o = append(o, 0x85) + o = append(o, 0x86) if oTemp, err := z.DataHash.MarshalHash(); err != nil { return nil, err } else { o = hsp.AppendBytes(o, oTemp) } - o = append(o, 0x85) + o = append(o, 0x86) if oTemp, err := z.NodeID.MarshalHash(); err != nil { return nil, err } else { o = hsp.AppendBytes(o, oTemp) } - o = append(o, 0x85) + o = append(o, 0x86) o = hsp.AppendTime(o, z.Timestamp) - o = append(o, 0x85) + o = append(o, 0x86) o = hsp.AppendUint64(o, z.RowCount) + o = append(o, 0x86) + o = hsp.AppendUint64(o, z.LogOffset) return } // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message func (z *ResponseHeader) Msgsize() (s int) { - s = 1 + 8 + z.Request.Msgsize() + 9 + z.DataHash.Msgsize() + 7 + z.NodeID.Msgsize() + 10 + hsp.TimeSize + 9 + hsp.Uint64Size + s = 1 + 8 + z.Request.Msgsize() + 9 + z.DataHash.Msgsize() + 7 + z.NodeID.Msgsize() + 10 + hsp.TimeSize + 9 + hsp.Uint64Size + 10 + hsp.Uint64Size return } diff --git a/worker/types/types_test.go b/worker/types/types_test.go index 67316cb43..9df73ff44 100644 --- a/worker/types/types_test.go +++ b/worker/types/types_test.go @@ -71,7 +71,7 @@ func Test_buildHash(t *testing.T) { } func TestSignedRequestHeader_Sign(t *testing.T) { - privKey, pubKey := getCommKeys() + privKey, _ := getCommKeys() Convey("sign", t, func() { req := &SignedRequestHeader{ @@ -87,11 +87,6 @@ func TestSignedRequestHeader_Sign(t *testing.T) { var err error - // without signee - err = req.Sign(privKey) - So(err, ShouldNotBeNil) - - req.Signee = pubKey err = req.Sign(privKey) So(err, ShouldBeNil) @@ -113,7 +108,7 @@ func TestSignedRequestHeader_Sign(t *testing.T) { } func TestRequest_Sign(t *testing.T) { - privKey, pubKey := getCommKeys() + privKey, _ := getCommKeys() Convey("sign", t, func() { req := &Request{ @@ -126,7 +121,6 @@ func TestRequest_Sign(t *testing.T) { SeqNo: uint64(2), Timestamp: time.Now().UTC(), }, - Signee: pubKey, }, Payload: RequestPayload{ Queries: []Query{ @@ -218,7 +212,7 @@ func TestRequest_Sign(t *testing.T) { } func TestResponse_Sign(t *testing.T) { - privKey, pubKey := getCommKeys() + privKey, _ := getCommKeys() Convey("sign", t, func() { res := &Response{ @@ -227,19 +221,17 @@ func TestResponse_Sign(t *testing.T) { Request: SignedRequestHeader{ RequestHeader: RequestHeader{ QueryType: WriteQuery, - NodeID: proto.NodeID("node1"), + NodeID: proto.NodeID("0000000000000000000000000000000000000000000000000000000000001111"), DatabaseID: proto.DatabaseID("db1"), ConnectionID: uint64(1), SeqNo: uint64(2), Timestamp: time.Now().UTC(), }, - Signee: pubKey, }, - NodeID: proto.NodeID("node2"), + NodeID: proto.NodeID("0000000000000000000000000000000000000000000000000000000000002222"), Timestamp: time.Now().UTC(), RowCount: uint64(1), }, - Signee: pubKey, }, Payload: ResponsePayload{ Columns: []string{ @@ -364,7 +356,7 @@ func TestResponse_Sign(t *testing.T) { } func TestAck_Sign(t *testing.T) { - privKey, pubKey := getCommKeys() + privKey, _ := getCommKeys() Convey("sign", t, func() { ack := &Ack{ @@ -375,24 +367,21 @@ func TestAck_Sign(t *testing.T) { Request: SignedRequestHeader{ RequestHeader: RequestHeader{ QueryType: WriteQuery, - NodeID: proto.NodeID("node1"), + NodeID: proto.NodeID("0000000000000000000000000000000000000000000000000000000000001111"), DatabaseID: proto.DatabaseID("db1"), ConnectionID: uint64(1), SeqNo: uint64(2), Timestamp: time.Now().UTC(), }, - Signee: pubKey, }, - NodeID: proto.NodeID("node2"), + NodeID: proto.NodeID("0000000000000000000000000000000000000000000000000000000000002222"), Timestamp: time.Now().UTC(), RowCount: uint64(1), }, - Signee: pubKey, }, - NodeID: proto.NodeID("node1"), + NodeID: proto.NodeID("0000000000000000000000000000000000000000000000000000000000001111"), Timestamp: time.Now().UTC(), }, - Signee: pubKey, }, } @@ -408,7 +397,9 @@ func TestAck_Sign(t *testing.T) { }) // sign directly, embedded original response is not filled - err = ack.Sign(privKey) + err = ack.Sign(privKey, false) + So(err, ShouldBeNil) + err = ack.Sign(privKey, true) So(err, ShouldNotBeNil) So(err, ShouldBeIn, []error{ ErrSignVerification, @@ -422,7 +413,7 @@ func TestAck_Sign(t *testing.T) { So(err, ShouldBeNil) err = ack.Header.Response.Sign(privKey) So(err, ShouldBeNil) - err = ack.Sign(privKey) + err = ack.Sign(privKey, true) So(err, ShouldBeNil) Convey("serialize", func() { @@ -487,35 +478,32 @@ func TestAck_Sign(t *testing.T) { } func TestNoAckReport_Sign(t *testing.T) { - privKey, pubKey := getCommKeys() + privKey, _ := getCommKeys() Convey("sign", t, func() { noAck := &NoAckReport{ Header: SignedNoAckReportHeader{ NoAckReportHeader: NoAckReportHeader{ - NodeID: proto.NodeID("node2"), + NodeID: proto.NodeID("0000000000000000000000000000000000000000000000000000000000002222"), Timestamp: time.Now().UTC(), Response: SignedResponseHeader{ ResponseHeader: ResponseHeader{ Request: SignedRequestHeader{ RequestHeader: RequestHeader{ QueryType: WriteQuery, - NodeID: proto.NodeID("node1"), + NodeID: proto.NodeID("0000000000000000000000000000000000000000000000000000000000001111"), DatabaseID: proto.DatabaseID("db1"), ConnectionID: uint64(1), SeqNo: uint64(2), Timestamp: time.Now().UTC(), }, - Signee: pubKey, }, - NodeID: proto.NodeID("node2"), + NodeID: proto.NodeID("0000000000000000000000000000000000000000000000000000000000002222"), Timestamp: time.Now().UTC(), RowCount: uint64(1), }, - Signee: pubKey, }, }, - Signee: pubKey, }, } @@ -596,87 +584,80 @@ func TestNoAckReport_Sign(t *testing.T) { } func TestAggrNoAckReport_Sign(t *testing.T) { - privKey, pubKey := getCommKeys() + privKey, _ := getCommKeys() Convey("sign", t, func() { aggrNoAck := &AggrNoAckReport{ Header: SignedAggrNoAckReportHeader{ AggrNoAckReportHeader: AggrNoAckReportHeader{ - NodeID: proto.NodeID("node3"), + NodeID: proto.NodeID("0000000000000000000000000000000000000000000000000000000000003333"), Timestamp: time.Now().UTC(), Reports: []SignedNoAckReportHeader{ { NoAckReportHeader: NoAckReportHeader{ - NodeID: proto.NodeID("node2"), + NodeID: proto.NodeID("0000000000000000000000000000000000000000000000000000000000002222"), Timestamp: time.Now().UTC(), Response: SignedResponseHeader{ ResponseHeader: ResponseHeader{ Request: SignedRequestHeader{ RequestHeader: RequestHeader{ QueryType: WriteQuery, - NodeID: proto.NodeID("node1"), + NodeID: proto.NodeID("0000000000000000000000000000000000000000000000000000000000001111"), DatabaseID: proto.DatabaseID("db1"), ConnectionID: uint64(1), SeqNo: uint64(2), Timestamp: time.Now().UTC(), }, - Signee: pubKey, }, - NodeID: proto.NodeID("node2"), + NodeID: proto.NodeID("0000000000000000000000000000000000000000000000000000000000002222"), Timestamp: time.Now().UTC(), RowCount: uint64(1), }, - Signee: pubKey, }, }, - Signee: pubKey, }, { NoAckReportHeader: NoAckReportHeader{ - NodeID: proto.NodeID("node3"), + NodeID: proto.NodeID("0000000000000000000000000000000000000000000000000000000000003333"), Timestamp: time.Now().UTC(), Response: SignedResponseHeader{ ResponseHeader: ResponseHeader{ Request: SignedRequestHeader{ RequestHeader: RequestHeader{ QueryType: WriteQuery, - NodeID: proto.NodeID("node1"), + NodeID: proto.NodeID("0000000000000000000000000000000000000000000000000000000000001111"), DatabaseID: proto.DatabaseID("db1"), ConnectionID: uint64(1), SeqNo: uint64(2), Timestamp: time.Now().UTC(), }, - Signee: pubKey, }, - NodeID: proto.NodeID("node3"), + NodeID: proto.NodeID("0000000000000000000000000000000000000000000000000000000000003333"), Timestamp: time.Now().UTC(), RowCount: uint64(1), }, - Signee: pubKey, }, }, - Signee: pubKey, }, }, Peers: &kayak.Peers{ Term: uint64(1), Leader: &kayak.Server{ Role: proto.Leader, - ID: proto.NodeID("node3"), + ID: proto.NodeID("0000000000000000000000000000000000000000000000000000000000003333"), }, Servers: []*kayak.Server{ { Role: proto.Leader, - ID: proto.NodeID("node3"), + ID: proto.NodeID("0000000000000000000000000000000000000000000000000000000000003333"), }, { Role: proto.Follower, - ID: proto.NodeID("node2"), + ID: proto.NodeID("0000000000000000000000000000000000000000000000000000000000002222"), }, }, }, }, - Signee: pubKey, }, } @@ -787,16 +768,16 @@ func TestInitServiceResponse_Sign(t *testing.T) { Term: uint64(1), Leader: &kayak.Server{ Role: proto.Leader, - ID: proto.NodeID("node3"), + ID: proto.NodeID("0000000000000000000000000000000000000000000000000000000000003333"), }, Servers: []*kayak.Server{ { Role: proto.Leader, - ID: proto.NodeID("node3"), + ID: proto.NodeID("0000000000000000000000000000000000000000000000000000000000003333"), }, { Role: proto.Follower, - ID: proto.NodeID("node2"), + ID: proto.NodeID("0000000000000000000000000000000000000000000000000000000000002222"), }, }, PubKey: pubKey, @@ -807,7 +788,6 @@ func TestInitServiceResponse_Sign(t *testing.T) { }, }, }, - Signee: pubKey, }, } @@ -879,16 +859,16 @@ func TestUpdateService_Sign(t *testing.T) { Term: uint64(1), Leader: &kayak.Server{ Role: proto.Leader, - ID: proto.NodeID("node3"), + ID: proto.NodeID("0000000000000000000000000000000000000000000000000000000000003333"), }, Servers: []*kayak.Server{ { Role: proto.Leader, - ID: proto.NodeID("node3"), + ID: proto.NodeID("0000000000000000000000000000000000000000000000000000000000003333"), }, { Role: proto.Follower, - ID: proto.NodeID("node2"), + ID: proto.NodeID("0000000000000000000000000000000000000000000000000000000000002222"), }, }, PubKey: pubKey, @@ -898,8 +878,6 @@ func TestUpdateService_Sign(t *testing.T) { GenesisBlock: nil, }, }, - - Signee: pubKey, }, } diff --git a/worker/types/update_service_type.go b/worker/types/update_service_type.go index 470e39f24..ccea45e27 100644 --- a/worker/types/update_service_type.go +++ b/worker/types/update_service_type.go @@ -120,6 +120,7 @@ func (sh *SignedUpdateServiceHeader) Sign(signer *asymmetric.PrivateKey) (err er // sign sh.Signature, err = signer.Sign(sh.HeaderHash[:]) + sh.Signee = signer.PubKey() return }