diff --git a/go.mod b/go.mod index 8e77dd5c0..1a428ded4 100644 --- a/go.mod +++ b/go.mod @@ -12,12 +12,9 @@ require ( github.com/golang-jwt/jwt v3.2.2+incompatible github.com/golang/protobuf v1.5.2 github.com/gorilla/websocket v1.4.2 - github.com/hashicorp/consul/api v1.12.0 github.com/json-iterator/go v1.1.12 - github.com/mitchellh/hashstructure v1.1.0 github.com/modern-go/reflect2 v1.0.2 github.com/nacos-group/nacos-sdk-go v1.0.8 - github.com/natefinch/lumberjack v2.0.0+incompatible github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 github.com/robfig/cron/v3 v3.0.1 github.com/rs/xid v1.3.0 @@ -31,7 +28,7 @@ require ( github.com/ugorji/go/codec v1.2.7 github.com/valyala/fastrand v1.1.0 go.mongodb.org/mongo-driver v1.5.1 - go.uber.org/zap v1.21.0 + go.uber.org/multierr v1.6.0 golang.org/x/net v0.0.0-20220407224826-aac1ed45d8e3 google.golang.org/protobuf v1.28.0 gopkg.in/yaml.v2 v2.4.0 @@ -39,11 +36,9 @@ require ( require ( github.com/akutz/memconn v0.1.0 // indirect - github.com/aliyun/alibaba-cloud-sdk-go v1.61.885 // indirect github.com/apache/thrift v0.16.0 // indirect github.com/armon/go-metrics v0.3.10 // indirect github.com/aws/aws-sdk-go v1.34.28 // indirect - github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23 // indirect github.com/cenk/backoff v2.2.1+incompatible // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect @@ -54,7 +49,6 @@ require ( github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a // indirect github.com/fatih/color v1.13.0 // indirect github.com/fsnotify/fsnotify v1.5.1 // indirect - github.com/go-errors/errors v1.0.1 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 // indirect @@ -67,6 +61,7 @@ require ( github.com/golang/snappy v0.0.4 // indirect github.com/google/uuid v1.3.0 // indirect github.com/grandcat/zeroconf v1.0.0 // indirect + github.com/hashicorp/consul/api v1.12.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-hclog v1.2.0 // indirect @@ -113,7 +108,6 @@ require ( github.com/tidwall/pretty v1.2.0 // indirect github.com/tinylib/msgp v1.1.6 // indirect github.com/tjfoc/gmsm v1.4.1 // indirect - github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect @@ -125,7 +119,7 @@ require ( go.opentelemetry.io/otel v1.6.3 // indirect go.opentelemetry.io/otel/trace v1.6.3 // indirect go.uber.org/atomic v1.7.0 // indirect - go.uber.org/multierr v1.6.0 // indirect + go.uber.org/zap v1.21.0 // indirect golang.org/x/crypto v0.0.0-20220408190544-5352b0902921 // indirect golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect @@ -133,8 +127,6 @@ require ( golang.org/x/text v0.3.7 // indirect golang.org/x/tools v0.1.10 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect - gopkg.in/ini.v1 v1.62.0 // indirect - gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect ) diff --git a/go.sum b/go.sum index 5130790b0..1e25c2a58 100644 --- a/go.sum +++ b/go.sum @@ -44,7 +44,6 @@ dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBr dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ChimeraCoder/gojson v1.1.0/go.mod h1:nYbTQlu6hv8PETM15J927yM0zGj3njIldp72UT1MqSw= @@ -58,8 +57,6 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/aliyun/alibaba-cloud-sdk-go v1.61.18/go.mod h1:v8ESoHo4SyHmuB4b1tJqDHxfTGEciD+yhvOU/5s1Rfk= -github.com/aliyun/alibaba-cloud-sdk-go v1.61.885 h1:H7Mq9zsKIMvBaw7rEmbWULvSTF2UI/9lFvvm4d/NZdk= -github.com/aliyun/alibaba-cloud-sdk-go v1.61.885/go.mod h1:pUKYbK5JQ+1Dfxk80P0qxGqe5dkxDoabbZS7zOcouyA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/thrift v0.16.0 h1:qEy6UW60iVOlUy+b9ZR0d5WzUWYGOo4HfopoyBaNmoY= @@ -83,7 +80,6 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= -github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23 h1:D21IyuvjDCshj1/qq+pCNd3VZOAEI9jy6Bi131YlXgI= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/cenk/backoff v2.2.1+incompatible h1:djdFT7f4gF2ttuzRKPbMOWgZajgesItGLwG5FTQKmmE= github.com/cenk/backoff v2.2.1+incompatible/go.mod h1:7FtoeaSnHoZnmZzz47cM35Y9nSW7tNyaidugnHTaFDE= @@ -146,7 +142,6 @@ github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWp github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -292,7 +287,6 @@ github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -385,7 +379,6 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/juju/ratelimit v1.0.1 h1:+7AIFJVQ0EQgq/K9+0Krm7m530Du7tIz0METWzN0RgY= github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk= @@ -476,8 +469,6 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/hashstructure v1.1.0 h1:P6P1hdjqAAknpY/M1CGipelZgp+4y9ja9kmUZPXP+H0= -github.com/mitchellh/hashstructure v1.1.0/go.mod h1:xUDAozZz0Wmdiufv0uyhnHkUTN6/6d8ulp4AwfLKrmA= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= @@ -495,8 +486,6 @@ github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nacos-group/nacos-sdk-go v1.0.8 h1:8pEm05Cdav9sQgJSv5kyvlgfz0SzFUUGI3pWX6SiSnM= github.com/nacos-group/nacos-sdk-go v1.0.8/go.mod h1:hlAPn3UdzlxIlSILAyOXKxjFSvDJ9oLzTJ9hLAK1KzA= -github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM= -github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -617,10 +606,8 @@ github.com/smallnest/quick v0.0.0-20220103065406-780def6371e6 h1:J8xk0QMMrqfDLqU github.com/smallnest/quick v0.0.0-20220103065406-780def6371e6/go.mod h1:h+J5yoLzf3XMKtM9l4vOaUtS4e+si6T3sKDtheJ15wc= github.com/smallnest/rpcx v1.7.4 h1:u6ADk/Ep8BqtAoJZO7LbniWsP+nqeAtcbaPm2D4eOXg= github.com/smallnest/rpcx v1.7.4/go.mod h1:TSciUoPlm8MYxnC7ErCz5ZymOFxOTbhN9cRgEI6Degs= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= @@ -668,7 +655,6 @@ github.com/tinylib/msgp v1.1.6 h1:i+SbKraHhnrf9M5MYmvQhFnbLhAXSDWF8WWsuyRdocw= github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw= github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho= github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE= -github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3 h1:kF/7m/ZU+0D4Jj5eZ41Zm3IH/J8OElK1Qtd7tVKAwLk= github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3/go.mod h1:QDlpd3qS71vYtakd2hmdpqhJ9nwv6mD6A30bQ1BPBFE= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= @@ -1167,10 +1153,7 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/lego/base/rpcx/service.go b/lego/base/rpcx/service.go index 8db9babb8..c8896742b 100644 --- a/lego/base/rpcx/service.go +++ b/lego/base/rpcx/service.go @@ -8,7 +8,6 @@ import ( "go_dreamfactory/lego/base" "go_dreamfactory/lego/core" "go_dreamfactory/lego/core/cbase" - "go_dreamfactory/lego/sys/codec" "go_dreamfactory/lego/sys/event" "go_dreamfactory/lego/sys/log" "go_dreamfactory/lego/sys/rpcx" @@ -85,12 +84,6 @@ func (this *RPCXService) InitSys() { } else { log.Infof("Sys event Init success !") } - //初始化编码Codec - if err := codec.OnInit(this.opts.Setting.Sys["codec"]); err != nil { - log.Panicf(fmt.Sprintf("Sys codec Init err:%v", err)) - } else { - log.Infof("Sys codec Init success !") - } //初始化rpcx系统 if err := rpcx.OnInit(this.opts.Setting.Sys["rpcx"], rpcx.SetServiceTag(this.GetTag()), rpcx.SetServiceId(this.GetId()), rpcx.SetServiceType(this.GetType()), rpcx.SetServiceVersion(this.GetVersion()), rpcx.SetServiceAddr(fmt.Sprintf("%s:%d", this.GetIp(), this.GetPort()))); err != nil { log.Panicf(fmt.Sprintf("Sys rpcx Init err:%v", err)) diff --git a/lego/sys/blockcache/cache.go b/lego/sys/blockcache/cache.go deleted file mode 100644 index 44a3c0934..000000000 --- a/lego/sys/blockcache/cache.go +++ /dev/null @@ -1,134 +0,0 @@ -package blockcache - -import ( - "sync" - "sync/atomic" - "unsafe" - - "go_dreamfactory/lego/utils/container" -) - -func newSys(options Options) (sys *Cache, err error) { - sys = &Cache{ - options: options, - inpip: make(chan interface{}), - outpip: make(chan interface{}), - outnotic: make(chan struct{}), - element: container.NewLKQueue(), - free: options.CacheMaxSzie, - } - go sys.run() - return -} - -type Item struct { - Size int64 - Value interface{} -} - -type Cache struct { - options Options - inpip chan interface{} - outpip chan interface{} - outnotic chan struct{} - instate int32 - outruning int32 - element *container.LKQueue - free int64 - close int32 - wg sync.WaitGroup -} - -func (this *Cache) In() chan<- interface{} { - return this.inpip -} - -func (this *Cache) Out() <-chan interface{} { - return this.outpip -} - -func (this *Cache) Close() { - atomic.StoreInt32(&this.close, 1) - close(this.inpip) - close(this.outnotic) - this.wg.Wait() - close(this.outpip) -} - -func (this *Cache) run() { - for v := range this.inpip { - siez := int64(unsafe.Sizeof(v)) - if siez > this.options.CacheMaxSzie { //异常数据 - this.Errorf("item size:%d large CacheMaxSzie:%d", siez, this.options.CacheMaxSzie) - continue - } else if siez > atomic.LoadInt64(&this.free) { //空间不足 - atomic.StoreInt32(&this.instate, 1) - locp: - for _ = range this.outnotic { - if siez > atomic.LoadInt64(&this.free) { - atomic.StoreInt32(&this.instate, 1) - } else { - this.element.Enqueue(&Item{Size: siez, Value: v}) - atomic.AddInt64(&this.free, -1*siez) - break locp - } - } - } else { - this.element.Enqueue(&Item{Size: siez, Value: v}) - atomic.AddInt64(&this.free, -1*siez) - } - if atomic.CompareAndSwapInt32(&this.outruning, 0, 1) { - this.wg.Add(1) - go func() { - locp: - for { - v := this.element.Dequeue() - if v != nil && atomic.LoadInt32(&this.close) == 0 { - item := v.(*Item) - atomic.AddInt64(&this.free, item.Size) - if atomic.CompareAndSwapInt32(&this.instate, 1, 0) { - this.outnotic <- struct{}{} - } - this.outpip <- item.Value - } else { - break locp - } - } - atomic.StoreInt32(&this.outruning, 0) - this.wg.Done() - }() - } - } -} - -///日志*********************************************************************** -func (this *Cache) Debugf(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Debugf("[SYS BlockCache] "+format, a) - } -} -func (this *Cache) Infof(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Infof("[SYS BlockCache] "+format, a) - } -} -func (this *Cache) Warnf(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Warnf("[SYS BlockCache] "+format, a) - } -} -func (this *Cache) Errorf(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Errorf("[SYS BlockCache] "+format, a) - } -} -func (this *Cache) Panicf(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Panicf("[SYS BlockCache] "+format, a) - } -} -func (this *Cache) Fatalf(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Fatalf("[SYS BlockCache] "+format, a) - } -} diff --git a/lego/sys/blockcache/core.go b/lego/sys/blockcache/core.go deleted file mode 100644 index 657f94e4b..000000000 --- a/lego/sys/blockcache/core.go +++ /dev/null @@ -1,44 +0,0 @@ -package blockcache - -/* -限容堵塞缓冲池系统 -设置最大内存大小 当缓存区为存满是直接写入 写满后进入堵塞状态 等待缓存区释放 -*/ - -type ( - ISys interface { - In() chan<- interface{} - Out() <-chan interface{} - Close() - } -) - -var ( - defsys ISys -) - -func OnInit(config map[string]interface{}, option ...Option) (err error) { - if defsys, err = newSys(newOptions(config, option...)); err == nil { - - } - return -} - -func NewSys(option ...Option) (sys ISys, err error) { - if sys, err = newSys(newOptionsByOption(option...)); err == nil { - - } - return -} - -func In() chan<- interface{} { - return defsys.In() -} - -func Out() <-chan interface{} { - return defsys.Out() -} - -func Close() { - defsys.Close() -} diff --git a/lego/sys/blockcache/options.go b/lego/sys/blockcache/options.go deleted file mode 100644 index babd4519e..000000000 --- a/lego/sys/blockcache/options.go +++ /dev/null @@ -1,57 +0,0 @@ -package blockcache - -import ( - "go_dreamfactory/lego/sys/log" - "go_dreamfactory/lego/utils/mapstructure" -) - -type Option func(*Options) -type Options struct { - CacheMaxSzie int64 - Debug bool //日志是否开启 - Log log.ILog -} - -func SetCacheMaxSzie(v int64) Option { - return func(o *Options) { - o.CacheMaxSzie = v - } -} - -func SetDebug(v bool) Option { - return func(o *Options) { - o.Debug = v - } -} -func SetLog(v log.ILog) Option { - return func(o *Options) { - o.Log = v - } -} - -func newOptions(config map[string]interface{}, opts ...Option) Options { - options := Options{ - CacheMaxSzie: 1024 * 1024 * 100, - Debug: true, - Log: log.Clone(log.SetLoglayer(2)), - } - if config != nil { - mapstructure.Decode(config, &options) - } - for _, o := range opts { - o(&options) - } - return options -} - -func newOptionsByOption(opts ...Option) Options { - options := Options{ - CacheMaxSzie: 1024 * 1024 * 100, - Debug: true, - Log: log.Clone(log.SetLoglayer(2)), - } - for _, o := range opts { - o(&options) - } - return options -} diff --git a/lego/sys/blockcache/sys_test.go b/lego/sys/blockcache/sys_test.go deleted file mode 100644 index e46c6b9d4..000000000 --- a/lego/sys/blockcache/sys_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package blockcache_test - -import ( - "fmt" - "os" - "os/signal" - "syscall" - "testing" - "time" - - "go_dreamfactory/lego/sys/blockcache" - "go_dreamfactory/lego/sys/log" -) - -func Test_sys(t *testing.T) { - if err := log.OnInit(nil, log.SetLoglevel(log.DebugLevel), log.SetDebugMode(true)); err != nil { - fmt.Printf("log init err:%v", err) - return - } - log.Debugf("log init succ") - if sys, err := blockcache.NewSys(blockcache.SetCacheMaxSzie(100)); err != nil { - log.Debugf("livego init err:%v", err) - return - } else { - closeSignal := make(chan struct{}) - go func() { - locp: - for { - select { - case <-closeSignal: - break locp - default: - sys.In() <- "liwei1dao" - log.Debugf("In:liwei1dao") - } - } - log.Debugf("In:End") - }() - go func() { - for v := range sys.Out() { - log.Debugf("Out:%v", v) - time.Sleep(time.Second) - } - log.Debugf("Out:End") - }() - go func() { - time.Sleep(time.Second * 3) - closeSignal <- struct{}{} - sys.Close() - }() - } - sigterm := make(chan os.Signal, 1) - signal.Notify(sigterm, syscall.SIGINT, syscall.SIGTERM) - select { - case <-sigterm: - fmt.Printf("terminating: via signal\n") - } -} diff --git a/lego/sys/cachego/cache.go b/lego/sys/cachego/cache.go deleted file mode 100644 index 865ac7240..000000000 --- a/lego/sys/cachego/cache.go +++ /dev/null @@ -1,820 +0,0 @@ -package cachego - -import ( - "encoding/gob" - "fmt" - "io" - "os" - "time" -) - -func (this *CacheGo) SetDefault(k string, x interface{}) { - this.Set(k, x, this.options.Expiration) -} - -func (this *CacheGo) Replace(k string, x interface{}, d time.Duration) error { - this.mu.Lock() - _, found := this.get(k) - if !found { - this.mu.Unlock() - return fmt.Errorf("Item %s doesn't exist", k) - } - this.set(k, x, d) - this.mu.Unlock() - return nil -} - -func (this *CacheGo) GetWithExpiration(k string) (interface{}, time.Time, bool) { - this.mu.RLock() - // "Inlining" of get and Expired - item, found := this.items[k] - if !found { - this.mu.RUnlock() - return nil, time.Time{}, false - } - - if item.Expiration > 0 { - if time.Now().UnixNano() > item.Expiration { - this.mu.RUnlock() - return nil, time.Time{}, false - } - - // Return the item and the expiration time - this.mu.RUnlock() - return item.Object, time.Unix(0, item.Expiration), true - } - - // If expiration <= 0 (i.e. no expiration time set) then return the item - // and a zeroed time.Time - this.mu.RUnlock() - return item.Object, time.Time{}, true -} - -func (this *CacheGo) Increment(k string, n int64) error { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return fmt.Errorf("Item %s not found", k) - } - switch v.Object.(type) { - case int: - v.Object = v.Object.(int) + int(n) - case int8: - v.Object = v.Object.(int8) + int8(n) - case int16: - v.Object = v.Object.(int16) + int16(n) - case int32: - v.Object = v.Object.(int32) + int32(n) - case int64: - v.Object = v.Object.(int64) + n - case uint: - v.Object = v.Object.(uint) + uint(n) - case uintptr: - v.Object = v.Object.(uintptr) + uintptr(n) - case uint8: - v.Object = v.Object.(uint8) + uint8(n) - case uint16: - v.Object = v.Object.(uint16) + uint16(n) - case uint32: - v.Object = v.Object.(uint32) + uint32(n) - case uint64: - v.Object = v.Object.(uint64) + uint64(n) - case float32: - v.Object = v.Object.(float32) + float32(n) - case float64: - v.Object = v.Object.(float64) + float64(n) - default: - this.mu.Unlock() - return fmt.Errorf("The value for %s is not an integer", k) - } - this.items[k] = v - this.mu.Unlock() - return nil -} - -func (this *CacheGo) IncrementFloat(k string, n float64) error { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return fmt.Errorf("Item %s not found", k) - } - switch v.Object.(type) { - case float32: - v.Object = v.Object.(float32) + float32(n) - case float64: - v.Object = v.Object.(float64) + n - default: - this.mu.Unlock() - return fmt.Errorf("The value for %s does not have type float32 or float64", k) - } - this.items[k] = v - this.mu.Unlock() - return nil -} - -func (this *CacheGo) IncrementInt(k string, n int) (int, error) { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return 0, fmt.Errorf("Item %s not found", k) - } - rv, ok := v.Object.(int) - if !ok { - this.mu.Unlock() - return 0, fmt.Errorf("The value for %s is not an int", k) - } - nv := rv + n - v.Object = nv - this.items[k] = v - this.mu.Unlock() - return nv, nil -} - -func (this *CacheGo) IncrementInt8(k string, n int8) (int8, error) { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return 0, fmt.Errorf("Item %s not found", k) - } - rv, ok := v.Object.(int8) - if !ok { - this.mu.Unlock() - return 0, fmt.Errorf("The value for %s is not an int8", k) - } - nv := rv + n - v.Object = nv - this.items[k] = v - this.mu.Unlock() - return nv, nil -} - -func (this *CacheGo) IncrementInt16(k string, n int16) (int16, error) { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return 0, fmt.Errorf("Item %s not found", k) - } - rv, ok := v.Object.(int16) - if !ok { - this.mu.Unlock() - return 0, fmt.Errorf("The value for %s is not an int16", k) - } - nv := rv + n - v.Object = nv - this.items[k] = v - this.mu.Unlock() - return nv, nil -} - -func (this *CacheGo) IncrementInt32(k string, n int32) (int32, error) { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return 0, fmt.Errorf("Item %s not found", k) - } - rv, ok := v.Object.(int32) - if !ok { - this.mu.Unlock() - return 0, fmt.Errorf("The value for %s is not an int32", k) - } - nv := rv + n - v.Object = nv - this.items[k] = v - this.mu.Unlock() - return nv, nil -} - -func (this *CacheGo) IncrementInt64(k string, n int64) (int64, error) { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return 0, fmt.Errorf("Item %s not found", k) - } - rv, ok := v.Object.(int64) - if !ok { - this.mu.Unlock() - return 0, fmt.Errorf("The value for %s is not an int64", k) - } - nv := rv + n - v.Object = nv - this.items[k] = v - this.mu.Unlock() - return nv, nil -} - -func (this *CacheGo) IncrementUint(k string, n uint) (uint, error) { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return 0, fmt.Errorf("Item %s not found", k) - } - rv, ok := v.Object.(uint) - if !ok { - this.mu.Unlock() - return 0, fmt.Errorf("The value for %s is not an uint", k) - } - nv := rv + n - v.Object = nv - this.items[k] = v - this.mu.Unlock() - return nv, nil -} - -func (this *CacheGo) IncrementUintptr(k string, n uintptr) (uintptr, error) { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return 0, fmt.Errorf("Item %s not found", k) - } - rv, ok := v.Object.(uintptr) - if !ok { - this.mu.Unlock() - return 0, fmt.Errorf("The value for %s is not an uintptr", k) - } - nv := rv + n - v.Object = nv - this.items[k] = v - this.mu.Unlock() - return nv, nil -} - -func (this *CacheGo) IncrementUint8(k string, n uint8) (uint8, error) { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return 0, fmt.Errorf("Item %s not found", k) - } - rv, ok := v.Object.(uint8) - if !ok { - this.mu.Unlock() - return 0, fmt.Errorf("The value for %s is not an uint8", k) - } - nv := rv + n - v.Object = nv - this.items[k] = v - this.mu.Unlock() - return nv, nil -} - -func (this *CacheGo) IncrementUint16(k string, n uint16) (uint16, error) { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return 0, fmt.Errorf("Item %s not found", k) - } - rv, ok := v.Object.(uint16) - if !ok { - this.mu.Unlock() - return 0, fmt.Errorf("The value for %s is not an uint16", k) - } - nv := rv + n - v.Object = nv - this.items[k] = v - this.mu.Unlock() - return nv, nil -} - -func (this *CacheGo) IncrementUint32(k string, n uint32) (uint32, error) { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return 0, fmt.Errorf("Item %s not found", k) - } - rv, ok := v.Object.(uint32) - if !ok { - this.mu.Unlock() - return 0, fmt.Errorf("The value for %s is not an uint32", k) - } - nv := rv + n - v.Object = nv - this.items[k] = v - this.mu.Unlock() - return nv, nil -} - -func (this *CacheGo) IncrementUint64(k string, n uint64) (uint64, error) { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return 0, fmt.Errorf("Item %s not found", k) - } - rv, ok := v.Object.(uint64) - if !ok { - this.mu.Unlock() - return 0, fmt.Errorf("The value for %s is not an uint64", k) - } - nv := rv + n - v.Object = nv - this.items[k] = v - this.mu.Unlock() - return nv, nil -} - -func (this *CacheGo) IncrementFloat32(k string, n float32) (float32, error) { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return 0, fmt.Errorf("Item %s not found", k) - } - rv, ok := v.Object.(float32) - if !ok { - this.mu.Unlock() - return 0, fmt.Errorf("The value for %s is not an float32", k) - } - nv := rv + n - v.Object = nv - this.items[k] = v - this.mu.Unlock() - return nv, nil -} - -func (this *CacheGo) IncrementFloat64(k string, n float64) (float64, error) { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return 0, fmt.Errorf("Item %s not found", k) - } - rv, ok := v.Object.(float64) - if !ok { - this.mu.Unlock() - return 0, fmt.Errorf("The value for %s is not an float64", k) - } - nv := rv + n - v.Object = nv - this.items[k] = v - this.mu.Unlock() - return nv, nil -} - -func (this *CacheGo) Decrement(k string, n int64) error { - // TODO: Implement Increment and Decrement more cleanly. - // (Cannot do Increment(k, n*-1) for uints.) - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return fmt.Errorf("Item not found") - } - switch v.Object.(type) { - case int: - v.Object = v.Object.(int) - int(n) - case int8: - v.Object = v.Object.(int8) - int8(n) - case int16: - v.Object = v.Object.(int16) - int16(n) - case int32: - v.Object = v.Object.(int32) - int32(n) - case int64: - v.Object = v.Object.(int64) - n - case uint: - v.Object = v.Object.(uint) - uint(n) - case uintptr: - v.Object = v.Object.(uintptr) - uintptr(n) - case uint8: - v.Object = v.Object.(uint8) - uint8(n) - case uint16: - v.Object = v.Object.(uint16) - uint16(n) - case uint32: - v.Object = v.Object.(uint32) - uint32(n) - case uint64: - v.Object = v.Object.(uint64) - uint64(n) - case float32: - v.Object = v.Object.(float32) - float32(n) - case float64: - v.Object = v.Object.(float64) - float64(n) - default: - this.mu.Unlock() - return fmt.Errorf("The value for %s is not an integer", k) - } - this.items[k] = v - this.mu.Unlock() - return nil -} - -func (this *CacheGo) DecrementFloat(k string, n float64) error { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return fmt.Errorf("Item %s not found", k) - } - switch v.Object.(type) { - case float32: - v.Object = v.Object.(float32) - float32(n) - case float64: - v.Object = v.Object.(float64) - n - default: - this.mu.Unlock() - return fmt.Errorf("The value for %s does not have type float32 or float64", k) - } - this.items[k] = v - this.mu.Unlock() - return nil -} - -func (this *CacheGo) DecrementInt(k string, n int) (int, error) { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return 0, fmt.Errorf("Item %s not found", k) - } - rv, ok := v.Object.(int) - if !ok { - this.mu.Unlock() - return 0, fmt.Errorf("The value for %s is not an int", k) - } - nv := rv - n - v.Object = nv - this.items[k] = v - this.mu.Unlock() - return nv, nil -} - -func (this *CacheGo) DecrementInt8(k string, n int8) (int8, error) { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return 0, fmt.Errorf("Item %s not found", k) - } - rv, ok := v.Object.(int8) - if !ok { - this.mu.Unlock() - return 0, fmt.Errorf("The value for %s is not an int8", k) - } - nv := rv - n - v.Object = nv - this.items[k] = v - this.mu.Unlock() - return nv, nil -} -func (this *CacheGo) DecrementInt16(k string, n int16) (int16, error) { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return 0, fmt.Errorf("Item %s not found", k) - } - rv, ok := v.Object.(int16) - if !ok { - this.mu.Unlock() - return 0, fmt.Errorf("The value for %s is not an int16", k) - } - nv := rv - n - v.Object = nv - this.items[k] = v - this.mu.Unlock() - return nv, nil -} - -func (this *CacheGo) DecrementInt32(k string, n int32) (int32, error) { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return 0, fmt.Errorf("Item %s not found", k) - } - rv, ok := v.Object.(int32) - if !ok { - this.mu.Unlock() - return 0, fmt.Errorf("The value for %s is not an int32", k) - } - nv := rv - n - v.Object = nv - this.items[k] = v - this.mu.Unlock() - return nv, nil -} - -func (this *CacheGo) DecrementInt64(k string, n int64) (int64, error) { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return 0, fmt.Errorf("Item %s not found", k) - } - rv, ok := v.Object.(int64) - if !ok { - this.mu.Unlock() - return 0, fmt.Errorf("The value for %s is not an int64", k) - } - nv := rv - n - v.Object = nv - this.items[k] = v - this.mu.Unlock() - return nv, nil -} -func (this *CacheGo) DecrementUint(k string, n uint) (uint, error) { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return 0, fmt.Errorf("Item %s not found", k) - } - rv, ok := v.Object.(uint) - if !ok { - this.mu.Unlock() - return 0, fmt.Errorf("The value for %s is not an uint", k) - } - nv := rv - n - v.Object = nv - this.items[k] = v - this.mu.Unlock() - return nv, nil -} - -func (this *CacheGo) DecrementUintptr(k string, n uintptr) (uintptr, error) { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return 0, fmt.Errorf("Item %s not found", k) - } - rv, ok := v.Object.(uintptr) - if !ok { - this.mu.Unlock() - return 0, fmt.Errorf("The value for %s is not an uintptr", k) - } - nv := rv - n - v.Object = nv - this.items[k] = v - this.mu.Unlock() - return nv, nil -} - -func (this *CacheGo) DecrementUint8(k string, n uint8) (uint8, error) { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return 0, fmt.Errorf("Item %s not found", k) - } - rv, ok := v.Object.(uint8) - if !ok { - this.mu.Unlock() - return 0, fmt.Errorf("The value for %s is not an uint8", k) - } - nv := rv - n - v.Object = nv - this.items[k] = v - this.mu.Unlock() - return nv, nil -} -func (this *CacheGo) DecrementUint16(k string, n uint16) (uint16, error) { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return 0, fmt.Errorf("Item %s not found", k) - } - rv, ok := v.Object.(uint16) - if !ok { - this.mu.Unlock() - return 0, fmt.Errorf("The value for %s is not an uint16", k) - } - nv := rv - n - v.Object = nv - this.items[k] = v - this.mu.Unlock() - return nv, nil -} - -func (this *CacheGo) DecrementUint32(k string, n uint32) (uint32, error) { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return 0, fmt.Errorf("Item %s not found", k) - } - rv, ok := v.Object.(uint32) - if !ok { - this.mu.Unlock() - return 0, fmt.Errorf("The value for %s is not an uint32", k) - } - nv := rv - n - v.Object = nv - this.items[k] = v - this.mu.Unlock() - return nv, nil -} - -func (this *CacheGo) DecrementUint64(k string, n uint64) (uint64, error) { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return 0, fmt.Errorf("Item %s not found", k) - } - rv, ok := v.Object.(uint64) - if !ok { - this.mu.Unlock() - return 0, fmt.Errorf("The value for %s is not an uint64", k) - } - nv := rv - n - v.Object = nv - this.items[k] = v - this.mu.Unlock() - return nv, nil -} -func (this *CacheGo) DecrementFloat32(k string, n float32) (float32, error) { - this.mu.Lock() - v, found := this.items[k] - if !found || v.Expired() { - this.mu.Unlock() - return 0, fmt.Errorf("Item %s not found", k) - } - rv, ok := v.Object.(float32) - if !ok { - this.mu.Unlock() - return 0, fmt.Errorf("The value for %s is not an float32", k) - } - nv := rv - n - v.Object = nv - this.items[k] = v - this.mu.Unlock() - return nv, nil -} -func (this *CacheGo) OnEvicted(f func(string, interface{})) { - this.mu.Lock() - this.onEvicted = f - this.mu.Unlock() -} -func (this *CacheGo) Set(k string, x interface{}, d time.Duration) { - var e int64 - if d > 0 { - e = time.Now().Add(d).UnixNano() - } - this.mu.Lock() - this.items[k] = Item{ - Object: x, - Expiration: e, - } - this.mu.Unlock() -} -func (this *CacheGo) Add(k string, x interface{}, d time.Duration) error { - this.mu.Lock() - _, found := this.get(k) - if found { - this.mu.Unlock() - return fmt.Errorf("Item %s already exists", k) - } - this.set(k, x, d) - this.mu.Unlock() - return nil -} -func (this *CacheGo) DeleteExpired() { - var evictedItems []keyAndValue - now := time.Now().UnixNano() - this.mu.Lock() - for k, v := range this.items { - // "Inlining" of expired - if v.Expiration > 0 && now > v.Expiration { - ov, evicted := this.delete(k) - if evicted { - evictedItems = append(evictedItems, keyAndValue{k, ov}) - } - } - } - this.mu.Unlock() - for _, v := range evictedItems { - this.onEvicted(v.key, v.value) - } -} - -func (this *CacheGo) SaveFile(fname string) error { - fp, err := os.Create(fname) - if err != nil { - return err - } - err = this.Save(fp) - if err != nil { - fp.Close() - return err - } - return fp.Close() -} - -func (this *CacheGo) Save(w io.Writer) (err error) { - enc := gob.NewEncoder(w) - defer func() { - if x := recover(); x != nil { - err = fmt.Errorf("Error registering item types with Gob library") - } - }() - this.mu.RLock() - defer this.mu.RUnlock() - for _, v := range this.items { - gob.Register(v.Object) - } - err = enc.Encode(&this.items) - return -} - -func (this *CacheGo) Load(r io.Reader) error { - dec := gob.NewDecoder(r) - items := map[string]Item{} - err := dec.Decode(&items) - if err == nil { - this.mu.Lock() - defer this.mu.Unlock() - for k, v := range items { - ov, found := this.items[k] - if !found || ov.Expired() { - this.items[k] = v - } - } - } - return err -} - -func (this *CacheGo) LoadFile(fname string) error { - fp, err := os.Open(fname) - if err != nil { - return err - } - err = this.Load(fp) - if err != nil { - fp.Close() - return err - } - return fp.Close() -} - -func (this *CacheGo) Items() map[string]Item { - this.mu.RLock() - defer this.mu.RUnlock() - m := make(map[string]Item, len(this.items)) - now := time.Now().UnixNano() - for k, v := range this.items { - if v.Expiration > 0 { - if now > v.Expiration { - continue - } - } - m[k] = v - } - return m -} - -func (this *CacheGo) ItemCount() int { - this.mu.RLock() - n := len(this.items) - this.mu.RUnlock() - return n -} - -func (this *CacheGo) Flush() { - this.mu.Lock() - this.items = map[string]Item{} - this.mu.Unlock() -} - -func (this *CacheGo) get(k string) (interface{}, bool) { - item, found := this.items[k] - if !found { - return nil, false - } - // "Inlining" of Expired - if item.Expiration > 0 { - if time.Now().UnixNano() > item.Expiration { - return nil, false - } - } - return item.Object, true -} -func (this *CacheGo) set(k string, x interface{}, d time.Duration) { - var e int64 - if d > 0 { - e = time.Now().Add(d).UnixNano() - } - this.items[k] = Item{ - Object: x, - Expiration: e, - } -} -func (this *CacheGo) delete(k string) (interface{}, bool) { - if this.onEvicted != nil { - if v, found := this.items[k]; found { - delete(this.items, k) - return v.Object, true - } - } - delete(this.items, k) - return nil, false -} diff --git a/lego/sys/cachego/cachego.go b/lego/sys/cachego/cachego.go deleted file mode 100644 index c1f445fe8..000000000 --- a/lego/sys/cachego/cachego.go +++ /dev/null @@ -1,47 +0,0 @@ -package cachego - -import ( - "sync" - "time" -) - -func newSys(options Options) (sys *CacheGo, err error) { - sys = &CacheGo{ - options: options, - items: make(map[string]Item), - } - err = sys.init() - return -} - -type CacheGo struct { - options Options - items map[string]Item - mu sync.RWMutex - onEvicted func(string, interface{}) - stop chan bool -} - -func (this *CacheGo) init() (err error) { - if this.options.CleanupInterval > 0 { - go this.run() - } - return -} - -func (this *CacheGo) run() { - ticker := time.NewTicker(time.Duration(this.options.CleanupInterval) * time.Second) - for { - select { - case <-ticker.C: - this.DeleteExpired() - case <-this.stop: - ticker.Stop() - return - } - } -} - -func (this *CacheGo) Clsoe() { - this.stop <- true -} diff --git a/lego/sys/cachego/core.go b/lego/sys/cachego/core.go deleted file mode 100644 index b0390161c..000000000 --- a/lego/sys/cachego/core.go +++ /dev/null @@ -1,187 +0,0 @@ -package cachego - -/* -本地缓存系统 -*/ -import ( - "io" - "time" -) - -type ( - ISys interface { - Flush() - ItemCount() int - Items() map[string]Item - SaveFile(fname string) error - Save(w io.Writer) (err error) - Load(r io.Reader) error - LoadFile(fname string) error - Add(k string, x interface{}, d time.Duration) error - Set(k string, x interface{}, d time.Duration) - OnEvicted(f func(string, interface{})) - Increment(k string, n int64) error - IncrementFloat(k string, n float64) error - IncrementInt(k string, n int) (int, error) - IncrementInt8(k string, n int8) (int8, error) - IncrementInt16(k string, n int16) (int16, error) - IncrementInt32(k string, n int32) (int32, error) - IncrementInt64(k string, n int64) (int64, error) - IncrementUint(k string, n uint) (uint, error) - IncrementUintptr(k string, n uintptr) (uintptr, error) - IncrementUint8(k string, n uint8) (uint8, error) - IncrementUint16(k string, n uint16) (uint16, error) - IncrementUint32(k string, n uint32) (uint32, error) - IncrementUint64(k string, n uint64) (uint64, error) - IncrementFloat32(k string, n float32) (float32, error) - IncrementFloat64(k string, n float64) (float64, error) - Decrement(k string, n int64) error - DecrementFloat(k string, n float64) error - DecrementInt(k string, n int) (int, error) - DecrementInt8(k string, n int8) (int8, error) - DecrementInt16(k string, n int16) (int16, error) - DecrementInt32(k string, n int32) (int32, error) - DecrementInt64(k string, n int64) (int64, error) - DecrementUint(k string, n uint) (uint, error) - DecrementUintptr(k string, n uintptr) (uintptr, error) - DecrementUint8(k string, n uint8) (uint8, error) - DecrementUint16(k string, n uint16) (uint16, error) - DecrementUint32(k string, n uint32) (uint32, error) - DecrementUint64(k string, n uint64) (uint64, error) - DecrementFloat32(k string, n float32) (float32, error) - } -) - -var ( - defsys ISys -) - -func OnInit(config map[string]interface{}, option ...Option) (err error) { - if defsys, err = newSys(newOptions(config, option...)); err == nil { - } - return -} - -func NewSys(option ...Option) (sys ISys, err error) { - if sys, err = newSys(newOptionsByOption(option...)); err == nil { - } - return -} - -func Flush() { - defsys.Flush() -} -func ItemCount() int { - return defsys.ItemCount() -} -func Items() map[string]Item { - return defsys.Items() -} -func SaveFile(fname string) error { - return defsys.SaveFile(fname) -} -func Save(w io.Writer) (err error) { - return defsys.Save(w) -} -func Load(r io.Reader) error { - return defsys.Load(r) -} -func LoadFile(fname string) error { - return defsys.LoadFile(fname) -} -func Add(k string, x interface{}, d time.Duration) error { - return defsys.Add(k, x, d) -} -func Set(k string, x interface{}, d time.Duration) { - defsys.Set(k, x, d) -} -func OnEvicted(f func(string, interface{})) { - defsys.OnEvicted(f) -} -func Increment(k string, n int64) error { - return defsys.Increment(k, n) -} -func IncrementFloat(k string, n float64) error { - return defsys.IncrementFloat(k, n) -} -func IncrementInt(k string, n int) (int, error) { - return defsys.IncrementInt(k, n) -} -func IncrementInt8(k string, n int8) (int8, error) { - return defsys.IncrementInt8(k, n) -} -func IncrementInt16(k string, n int16) (int16, error) { - return defsys.IncrementInt16(k, n) -} -func IncrementInt32(k string, n int32) (int32, error) { - return defsys.IncrementInt32(k, n) -} -func IncrementInt64(k string, n int64) (int64, error) { - return defsys.IncrementInt64(k, n) -} -func IncrementUint(k string, n uint) (uint, error) { - return defsys.IncrementUint(k, n) -} -func IncrementUintptr(k string, n uintptr) (uintptr, error) { - return defsys.IncrementUintptr(k, n) -} -func IncrementUint8(k string, n uint8) (uint8, error) { - return defsys.IncrementUint8(k, n) -} -func IncrementUint16(k string, n uint16) (uint16, error) { - return defsys.IncrementUint16(k, n) -} -func IncrementUint32(k string, n uint32) (uint32, error) { - return defsys.IncrementUint32(k, n) -} -func IncrementUint64(k string, n uint64) (uint64, error) { - return defsys.IncrementUint64(k, n) -} -func IncrementFloat32(k string, n float32) (float32, error) { - return defsys.IncrementFloat32(k, n) -} -func IncrementFloat64(k string, n float64) (float64, error) { - return defsys.IncrementFloat64(k, n) -} -func Decrement(k string, n int64) error { - return defsys.Decrement(k, n) -} -func DecrementFloat(k string, n float64) error { - return defsys.DecrementFloat(k, n) -} -func DecrementInt(k string, n int) (int, error) { - return defsys.DecrementInt(k, n) -} -func DecrementInt8(k string, n int8) (int8, error) { - return defsys.DecrementInt8(k, n) -} -func DecrementInt16(k string, n int16) (int16, error) { - return defsys.DecrementInt16(k, n) -} -func DecrementInt32(k string, n int32) (int32, error) { - return defsys.DecrementInt32(k, n) -} -func DecrementInt64(k string, n int64) (int64, error) { - return defsys.DecrementInt64(k, n) -} -func DecrementUint(k string, n uint) (uint, error) { - return defsys.DecrementUint(k, n) -} -func DecrementUintptr(k string, n uintptr) (uintptr, error) { - return defsys.DecrementUintptr(k, n) -} -func DecrementUint8(k string, n uint8) (uint8, error) { - return defsys.DecrementUint8(k, n) -} -func DecrementUint16(k string, n uint16) (uint16, error) { - return defsys.DecrementUint16(k, n) -} -func DecrementUint32(k string, n uint32) (uint32, error) { - return defsys.DecrementUint32(k, n) -} -func DecrementUint64(k string, n uint64) (uint64, error) { - return defsys.DecrementUint64(k, n) -} -func DecrementFloat32(k string, n float32) (float32, error) { - return defsys.DecrementFloat32(k, n) -} diff --git a/lego/sys/cachego/item.go b/lego/sys/cachego/item.go deleted file mode 100644 index 6468b46a5..000000000 --- a/lego/sys/cachego/item.go +++ /dev/null @@ -1,19 +0,0 @@ -package cachego - -import "time" - -type keyAndValue struct { - key string - value interface{} -} -type Item struct { - Object interface{} - Expiration int64 -} - -func (item Item) Expired() bool { - if item.Expiration == 0 { - return false - } - return time.Now().UnixNano() > item.Expiration -} diff --git a/lego/sys/cachego/options.go b/lego/sys/cachego/options.go deleted file mode 100644 index a9b39825f..000000000 --- a/lego/sys/cachego/options.go +++ /dev/null @@ -1,38 +0,0 @@ -package cachego - -import ( - "time" - - "go_dreamfactory/lego/utils/mapstructure" -) - -type Option func(*Options) -type Options struct { - Expiration time.Duration - CleanupInterval time.Duration -} - -func newOptions(config map[string]interface{}, opts ...Option) Options { - options := Options{ - Expiration: -1, - CleanupInterval: 0, - } - if config != nil { - mapstructure.Decode(config, &options) - } - for _, o := range opts { - o(&options) - } - return options -} - -func newOptionsByOption(opts ...Option) Options { - options := Options{ - Expiration: -1, - CleanupInterval: 0, - } - for _, o := range opts { - o(&options) - } - return options -} diff --git a/lego/sys/codec/codec.go b/lego/sys/codec/codec.go deleted file mode 100644 index 3fa30b128..000000000 --- a/lego/sys/codec/codec.go +++ /dev/null @@ -1,273 +0,0 @@ -package codec - -import ( - "errors" - "fmt" - "reflect" - "sync" - - "go_dreamfactory/lego/sys/codec/core" - "go_dreamfactory/lego/sys/codec/factory" - "go_dreamfactory/lego/sys/codec/render" - - "github.com/modern-go/reflect2" -) - -func newSys(options core.Options) (sys *Codec, err error) { - sys = &Codec{ - options: &options, - decoderCache: new(sync.Map), - encoderCache: new(sync.Map), - streamPool: &sync.Pool{ - New: func() interface{} { - return render.NewStream(sys, 512) - }, - }, - extraPool: &sync.Pool{ - New: func() interface{} { - return render.NewExtractor(sys) - }, - }, - } - return -} - -type Codec struct { - options *core.Options - decoderCache *sync.Map - encoderCache *sync.Map - streamPool *sync.Pool - extraPool *sync.Pool -} - -func (this *Codec) Options() *core.Options { - return this.options -} - -func (this *Codec) addDecoderToCache(cacheKey uintptr, decoder core.IDecoder) { - this.decoderCache.Store(cacheKey, decoder) -} -func (this *Codec) addEncoderToCache(cacheKey uintptr, encoder core.IEncoder) { - this.encoderCache.Store(cacheKey, encoder) -} - -func (this *Codec) GetEncoderFromCache(cacheKey uintptr) core.IEncoder { - encoder, found := this.encoderCache.Load(cacheKey) - if found { - return encoder.(core.IEncoder) - } - return nil -} - -func (this *Codec) GetDecoderFromCache(cacheKey uintptr) core.IDecoder { - decoder, found := this.decoderCache.Load(cacheKey) - if found { - return decoder.(core.IDecoder) - } - return nil -} - -func (this *Codec) EncoderOf(typ reflect2.Type) core.IEncoder { - cacheKey := typ.RType() - encoder := this.GetEncoderFromCache(cacheKey) - if encoder != nil { - return encoder - } - ctx := &core.Ctx{ - ICodec: this, - Prefix: "", - Decoders: map[reflect2.Type]core.IDecoder{}, - Encoders: map[reflect2.Type]core.IEncoder{}, - } - encoder = factory.EncoderOfType(ctx, typ) - if typ.LikePtr() { - encoder = factory.NewonePtrEncoder(encoder) - } - this.addEncoderToCache(cacheKey, encoder) - return encoder -} - -func (this *Codec) DecoderOf(typ reflect2.Type) core.IDecoder { - cacheKey := typ.RType() - decoder := this.GetDecoderFromCache(cacheKey) - if decoder != nil { - return decoder - } - ctx := &core.Ctx{ - ICodec: this, - Prefix: "", - Decoders: map[reflect2.Type]core.IDecoder{}, - Encoders: map[reflect2.Type]core.IEncoder{}, - } - ptrType := typ.(*reflect2.UnsafePtrType) - decoder = factory.DecoderOfType(ctx, ptrType.Elem()) - this.addDecoderToCache(cacheKey, decoder) - return decoder -} - -func (this *Codec) BorrowStream() core.IStream { - stream := this.streamPool.Get().(core.IStream) - return stream -} - -func (this *Codec) ReturnStream(stream core.IStream) { - this.streamPool.Put(stream) -} - -func (this *Codec) BorrowExtractor(buf []byte) core.IExtractor { - extra := this.extraPool.Get().(core.IExtractor) - extra.ResetBytes(buf) - return extra -} - -func (this *Codec) ReturnExtractor(extra core.IExtractor) { - this.extraPool.Put(extra) -} - -//编码对象到json -func (this *Codec) MarshalJson(val interface{}, option ...core.ExecuteOption) (buf []byte, err error) { - stream := this.BorrowStream() - defer this.ReturnStream(stream) - stream.WriteVal(val) - if stream.Error() != nil { - return nil, stream.Error() - } - result := stream.Buffer() - copied := make([]byte, len(result)) - copy(copied, result) - return copied, nil -} - -//解码json到对象 -func (this *Codec) UnmarshalJson(data []byte, v interface{}, option ...core.ExecuteOption) error { - extra := this.BorrowExtractor(data) - defer this.ReturnExtractor(extra) - extra.ReadVal(v) - return extra.Error() -} - -//编码对象到mapjson -func (this *Codec) MarshalMapJson(val interface{}, option ...core.ExecuteOption) (ret map[string]string, err error) { - if nil == val { - err = errors.New("val is null") - return - } - cacheKey := reflect2.RTypeOf(val) - encoder := this.GetEncoderFromCache(cacheKey) - if encoder == nil { - typ := reflect2.TypeOf(val) - encoder = this.EncoderOf(typ) - } - if encoderMapJson, ok := encoder.(core.IEncoderMapJson); !ok { - err = fmt.Errorf("val type:%T not support MarshalMapJson", val) - } else { - ret, err = encoderMapJson.EncodeToMapJson(reflect2.PtrOf(val)) - } - return -} - -//解码mapjson到对象 -func (this *Codec) UnmarshalMapJson(data map[string]string, val interface{}, option ...core.ExecuteOption) (err error) { - cacheKey := reflect2.RTypeOf(val) - decoder := this.GetDecoderFromCache(cacheKey) - if decoder == nil { - typ := reflect2.TypeOf(val) - if typ == nil || typ.Kind() != reflect.Ptr { - err = errors.New("can only unmarshal into pointer") - return - } - decoder = this.DecoderOf(typ) - } - ptr := reflect2.PtrOf(val) - if ptr == nil { - err = errors.New("can not read into nil pointer") - return - } - if decoderMapJson, ok := decoder.(core.IDecoderMapJson); !ok { - err = fmt.Errorf("val type:%T not support MarshalMapJson", val) - } else { - err = decoderMapJson.DecodeForMapJson(ptr, data) - } - return -} - -//编码对象到sliceJson -func (this *Codec) MarshalSliceJson(val interface{}, option ...core.ExecuteOption) (ret []string, err error) { - if nil == val { - err = errors.New("val is null") - return - } - cacheKey := reflect2.RTypeOf(val) - encoder := this.GetEncoderFromCache(cacheKey) - if encoder == nil { - typ := reflect2.TypeOf(val) - encoder = this.EncoderOf(typ) - } - if encoderMapJson, ok := encoder.(core.IEncoderSliceJson); !ok { - err = fmt.Errorf("val type:%T not support MarshalMapJson", val) - } else { - ret, err = encoderMapJson.EncodeToSliceJson(reflect2.PtrOf(val)) - } - return -} - -//解码sliceJson到对象 -func (this *Codec) UnmarshalSliceJson(data []string, val interface{}, option ...core.ExecuteOption) (err error) { - cacheKey := reflect2.RTypeOf(val) - decoder := this.GetDecoderFromCache(cacheKey) - if decoder == nil { - typ := reflect2.TypeOf(val) - if typ == nil || typ.Kind() != reflect.Ptr { - err = errors.New("can only unmarshal into pointer") - return - } - decoder = this.DecoderOf(typ) - } - ptr := reflect2.PtrOf(val) - if ptr == nil { - err = errors.New("can not read into nil pointer") - return - } - if decoderMapJson, ok := decoder.(core.IDecoderSliceJson); !ok { - err = fmt.Errorf("val type:%T not support UnmarshalSliceJson", val) - } else { - err = decoderMapJson.DecodeForSliceJson(ptr, data) - } - return -} - -///日志*********************************************************************** -func (this *Codec) Debug() bool { - return this.options.Debug -} - -func (this *Codec) Debugf(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Debugf("[SYS Codec] "+format, a...) - } -} -func (this *Codec) Infof(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Infof("[SYS Codec] "+format, a...) - } -} -func (this *Codec) Warnf(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Warnf("[SYS Codec] "+format, a...) - } -} -func (this *Codec) Errorf(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Errorf("[SYS Codec] "+format, a...) - } -} -func (this *Codec) Panicf(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Panicf("[SYS Codec] "+format, a...) - } -} -func (this *Codec) Fatalf(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Fatalf("[SYS Codec] "+format, a...) - } -} diff --git a/lego/sys/codec/core.go b/lego/sys/codec/core.go deleted file mode 100644 index b83970fa9..000000000 --- a/lego/sys/codec/core.go +++ /dev/null @@ -1,56 +0,0 @@ -package codec - -import ( - "go_dreamfactory/lego/sys/codec/core" - - "github.com/modern-go/reflect2" -) - -type ( - ISys interface { - DecoderOf(typ reflect2.Type) core.IDecoder - EncoderOf(typ reflect2.Type) core.IEncoder - MarshalJson(v interface{}, option ...core.ExecuteOption) ([]byte, error) - UnmarshalJson(data []byte, v interface{}, option ...core.ExecuteOption) error - MarshalMapJson(val interface{}, option ...core.ExecuteOption) (ret map[string]string, err error) - UnmarshalMapJson(data map[string]string, val interface{}, option ...core.ExecuteOption) (err error) - MarshalSliceJson(val interface{}, option ...core.ExecuteOption) (ret []string, err error) - UnmarshalSliceJson(data []string, val interface{}, option ...core.ExecuteOption) (err error) - } -) - -var defsys ISys - -func OnInit(config map[string]interface{}, option ...core.Option) (err error) { - defsys, err = newSys(newOptions(config, option...)) - return -} - -func NewSys(option ...core.Option) (sys ISys, err error) { - sys, err = newSys(newOptionsByOption(option...)) - return -} -func DecoderOf(typ reflect2.Type) core.IDecoder { - return defsys.DecoderOf(typ) -} -func EncoderOf(typ reflect2.Type) core.IEncoder { - return defsys.EncoderOf(typ) -} -func MarshalJson(v interface{}, option ...core.ExecuteOption) ([]byte, error) { - return defsys.MarshalJson(v, option...) -} -func UnmarshalJson(data []byte, v interface{}, option ...core.ExecuteOption) error { - return defsys.UnmarshalJson(data, v, option...) -} -func MarshalMapJson(val interface{}, option ...core.ExecuteOption) (ret map[string]string, err error) { - return defsys.MarshalMapJson(val, option...) -} -func UnmarshalMapJson(data map[string]string, val interface{}, option ...core.ExecuteOption) (err error) { - return defsys.UnmarshalMapJson(data, val, option...) -} -func MarshalSliceJson(val interface{}, option ...core.ExecuteOption) (ret []string, err error) { - return defsys.MarshalSliceJson(val, option...) -} -func UnmarshalSliceJson(data []string, val interface{}, option ...core.ExecuteOption) (err error) { - return defsys.UnmarshalSliceJson(data, val) -} diff --git a/lego/sys/codec/core/options.go b/lego/sys/codec/core/options.go deleted file mode 100644 index 1524d0ddb..000000000 --- a/lego/sys/codec/core/options.go +++ /dev/null @@ -1,30 +0,0 @@ -package core - -import ( - "go_dreamfactory/lego/sys/log" -) - -type Option func(*Options) -type Options struct { - IndentionStep int //缩进步骤 - ObjectFieldMustBeSimpleString bool //对象字段必须是简单字符串 - OnlyTaggedField bool //仅仅处理标签字段 - DisallowUnknownFields bool //禁止未知字段 - CaseSensitive bool //是否区分大小写 - TagKey string //标签 - Debug bool //日志是否开启 - Log log.ILog -} - -//执行选项 -type ExecuteOption func(*ExecuteOptions) -type ExecuteOptions struct { -} - -func NewExecuteOptions(opts ...ExecuteOption) ExecuteOptions { - options := ExecuteOptions{} - for _, o := range opts { - o(&options) - } - return options -} diff --git a/lego/sys/codec/options.go b/lego/sys/codec/options.go deleted file mode 100644 index 86567c3ff..000000000 --- a/lego/sys/codec/options.go +++ /dev/null @@ -1,38 +0,0 @@ -package codec - -import ( - "go_dreamfactory/lego/sys/codec/core" - "go_dreamfactory/lego/sys/log" - "go_dreamfactory/lego/utils/mapstructure" -) - -func newOptions(config map[string]interface{}, opts ...core.Option) core.Options { - options := core.Options{ - IndentionStep: 2, - TagKey: "json", - } - if config != nil { - mapstructure.Decode(config, &options) - } - for _, o := range opts { - o(&options) - } - if options.Debug && options.Log == nil { - options.Log = log.Clone() - } - return options -} - -func newOptionsByOption(opts ...core.Option) core.Options { - options := core.Options{ - IndentionStep: 2, - TagKey: "json", - } - for _, o := range opts { - o(&options) - } - if options.Debug && options.Log == nil { - options.Log = log.Clone() - } - return options -} diff --git a/lego/sys/codec/render/core.go b/lego/sys/codec/render/core.go deleted file mode 100644 index a62153d14..000000000 --- a/lego/sys/codec/render/core.go +++ /dev/null @@ -1,45 +0,0 @@ -package render - -import "go_dreamfactory/lego/sys/codec/core" - -const maxDepth = 10000 - -var hexDigits []byte -var valueTypes []core.ValueType - -func init() { - hexDigits = make([]byte, 256) - for i := 0; i < len(hexDigits); i++ { - hexDigits[i] = 255 - } - for i := '0'; i <= '9'; i++ { - hexDigits[i] = byte(i - '0') - } - for i := 'a'; i <= 'f'; i++ { - hexDigits[i] = byte((i - 'a') + 10) - } - for i := 'A'; i <= 'F'; i++ { - hexDigits[i] = byte((i - 'A') + 10) - } - valueTypes = make([]core.ValueType, 256) - for i := 0; i < len(valueTypes); i++ { - valueTypes[i] = core.InvalidValue - } - valueTypes['"'] = core.StringValue - valueTypes['-'] = core.NumberValue - valueTypes['0'] = core.NumberValue - valueTypes['1'] = core.NumberValue - valueTypes['2'] = core.NumberValue - valueTypes['3'] = core.NumberValue - valueTypes['4'] = core.NumberValue - valueTypes['5'] = core.NumberValue - valueTypes['6'] = core.NumberValue - valueTypes['7'] = core.NumberValue - valueTypes['8'] = core.NumberValue - valueTypes['9'] = core.NumberValue - valueTypes['t'] = core.BoolValue - valueTypes['f'] = core.BoolValue - valueTypes['n'] = core.NilValue - valueTypes['['] = core.ArrayValue - valueTypes['{'] = core.ObjectValue -} diff --git a/lego/sys/codec/render/json_stream.go b/lego/sys/codec/render/json_stream.go deleted file mode 100644 index 4fa115f40..000000000 --- a/lego/sys/codec/render/json_stream.go +++ /dev/null @@ -1,206 +0,0 @@ -package render - -import ( - "go_dreamfactory/lego/sys/codec/core" - "go_dreamfactory/lego/sys/codec/utils" - - "github.com/modern-go/reflect2" -) - -func NewStream(codec core.ICodec, bufSize int) *JsonStream { - return &JsonStream{ - codec: codec, - buf: make([]byte, 0, bufSize), - err: nil, - indention: 0, - } -} - -type JsonStream struct { - codec core.ICodec - err error - buf []byte - indention int -} - -//写入对象 -func (this *JsonStream) WriteVal(val interface{}) { - if nil == val { - this.WriteNil() - return - } - cacheKey := reflect2.RTypeOf(val) - encoder := this.codec.GetEncoderFromCache(cacheKey) - if encoder == nil { - typ := reflect2.TypeOf(val) - encoder = this.codec.EncoderOf(typ) - } - encoder.Encode(reflect2.PtrOf(val), this) -} - -func (this *JsonStream) WriteNil() { - this.writeFourBytes('n', 'u', 'l', 'l') -} -func (this *JsonStream) WriteEmptyArray() { - this.writeTwoBytes('[', ']') -} -func (this *JsonStream) WriteArrayStart() { - this.indention += this.codec.Options().IndentionStep - this.writeByte('[') - this.writeIndention(0) -} -func (this *JsonStream) WriteArrayEnd() { - this.writeIndention(this.codec.Options().IndentionStep) - this.indention -= this.codec.Options().IndentionStep - this.writeByte(']') -} -func (this *JsonStream) WriteEmptyObject() { - this.writeTwoBytes('{', '}') -} -func (this *JsonStream) WriteObjectStart() { - this.indention += this.codec.Options().IndentionStep - this.writeByte('{') - this.writeIndention(0) -} -func (this *JsonStream) WriteObjectEnd() { - this.writeIndention(this.codec.Options().IndentionStep) - this.indention -= this.codec.Options().IndentionStep - this.writeByte('}') -} -func (this *JsonStream) WriteMemberSplit() { - this.writeByte(',') - this.writeIndention(0) -} -func (this *JsonStream) WriteKVSplit() { - this.writeByte(':') -} -func (this *JsonStream) WriteKeyStart() { - this.writeByte('"') -} -func (this *JsonStream) WriteKeyEnd() { - this.writeByte('"') -} -func (this *JsonStream) WriteObjectFieldName(val string) { - this.WriteString(val) - if this.indention > 0 { - this.writeTwoBytes(':', ' ') - } else { - this.writeByte(':') - } -} -func (this *JsonStream) WriteBool(val bool) { - if val { - this.writeTrue() - } else { - this.writeFalse() - } -} -func (this *JsonStream) WriteInt8(val int8) { - utils.WriteInt8ToString(&this.buf, val) -} -func (this *JsonStream) WriteInt16(val int16) { - utils.WriteInt16ToString(&this.buf, val) -} -func (this *JsonStream) WriteInt32(val int32) { - utils.WriteInt32ToString(&this.buf, val) -} -func (this *JsonStream) WriteInt64(val int64) { - utils.WriteInt64ToString(&this.buf, val) -} -func (this *JsonStream) WriteUint8(val uint8) { - utils.WriteUint8ToString(&this.buf, val) -} -func (this *JsonStream) WriteUint16(val uint16) { - utils.WriteUint16ToString(&this.buf, val) -} -func (this *JsonStream) WriteUint32(val uint32) { - utils.WriteUint32ToString(&this.buf, val) -} -func (this *JsonStream) WriteUint64(val uint64) { - utils.WriteUint64ToString(&this.buf, val) -} -func (this *JsonStream) WriteFloat32(val float32) { - utils.WriteFloat32ToString(&this.buf, val) -} -func (this *JsonStream) WriteFloat64(val float64) { - utils.WriteFloat64ToString(&this.buf, val) -} -func (this *JsonStream) WriteString(val string) { - valLen := len(val) - this.buf = append(this.buf, '"') - i := 0 - for ; i < valLen; i++ { - c := val[i] - if c > 31 && c != '"' && c != '\\' { - this.buf = append(this.buf, c) - } else { - break - } - } - if i == valLen { - this.buf = append(this.buf, '"') - return - } - utils.WriteStringSlowPath(&this.buf, i, val, valLen) -} -func (this *JsonStream) WriteBytes(val []byte) { - this.buf = append(this.buf, val...) -} -func (this *JsonStream) Reset(bufSize int) { - this.buf = make([]byte, 0, bufSize) - this.err = nil - this.indention = 0 - return -} -func (this *JsonStream) Buffer() []byte { - return this.buf -} -func (this *JsonStream) Error() error { - return this.err -} -func (this *JsonStream) SetErr(err error) { - this.err = err -} - -//------------------------------------------------------------------------------------------------------------------------------------------------------------------- - -// WriteTrue write true to stream -func (stream *JsonStream) writeTrue() { - stream.writeFourBytes('t', 'r', 'u', 'e') -} - -// WriteFalse write false to stream -func (stream *JsonStream) writeFalse() { - stream.writeFiveBytes('f', 'a', 'l', 's', 'e') -} - -func (this *JsonStream) writeByte(c byte) { - this.buf = append(this.buf, c) -} - -func (this *JsonStream) writeTwoBytes(c1 byte, c2 byte) { - this.buf = append(this.buf, c1, c2) -} - -func (this *JsonStream) writeThreeBytes(c1 byte, c2 byte, c3 byte) { - this.buf = append(this.buf, c1, c2, c3) -} - -func (this *JsonStream) writeFourBytes(c1 byte, c2 byte, c3 byte, c4 byte) { - this.buf = append(this.buf, c1, c2, c3, c4) -} - -func (this *JsonStream) writeFiveBytes(c1 byte, c2 byte, c3 byte, c4 byte, c5 byte) { - this.buf = append(this.buf, c1, c2, c3, c4, c5) -} - -func (stream *JsonStream) writeIndention(delta int) { - if stream.indention == 0 { - return - } - stream.writeByte('\n') - toWrite := stream.indention - delta - for i := 0; i < toWrite; i++ { - stream.buf = append(stream.buf, ' ') - } -} diff --git a/lego/sys/codec/sys_test.go b/lego/sys/codec/sys_test.go deleted file mode 100644 index 321e593e4..000000000 --- a/lego/sys/codec/sys_test.go +++ /dev/null @@ -1,106 +0,0 @@ -package codec_test - -import ( - "fmt" - "reflect" - "testing" - - "go_dreamfactory/lego/sys/codec" - "go_dreamfactory/lego/sys/log" - - "github.com/modern-go/reflect2" -) - -type TestData struct { - Name string - Value int - Array []interface{} - Data map[string]interface{} -} -type Test1Data struct { - Name string - Value int -} - -func Test_sys_slice(t *testing.T) { - if err := log.OnInit(nil); err != nil { - fmt.Printf("log init err:%v", err) - return - } - if sys, err := codec.NewSys(); err != nil { - fmt.Printf("gin init err:%v", err) - } else { - data := []*Test1Data{{"liwe", 1}, {"liwe2", 2}} - d, err := sys.MarshalJson(data) - fmt.Printf("codec Marshal d:%s err:%v", d, err) - data = []*Test1Data{} - err = sys.UnmarshalJson(d, &data) - fmt.Printf("codec UnmarshalJson data:%v err:%v", data, err) - } -} -func Test_sys_json(t *testing.T) { - if err := log.OnInit(nil); err != nil { - fmt.Printf("log init err:%v", err) - return - } - if sys, err := codec.NewSys(); err != nil { - fmt.Printf("gin init err:%v", err) - } else { - d, err := sys.MarshalJson(&TestData{Name: "http://liwei1dao.com?asd=1&dd=1", Value: 10, Array: []interface{}{1, "dajiahao", &Test1Data{Name: "liwe1dao", Value: 123}}, Data: map[string]interface{}{"hah": 1, "asd": 999}}) - fmt.Printf("codec Marshal d:%s err:%v", d, err) - data := &TestData{} - err = sys.UnmarshalJson(d, data) - fmt.Printf("codec UnmarshalJson data:%v err:%v", data, err) - } -} - -func Test_sys_mapjson(t *testing.T) { - if err := log.OnInit(nil); err != nil { - fmt.Printf("log init err:%v", err) - return - } - if sys, err := codec.NewSys(); err != nil { - fmt.Printf("gin init err:%v", err) - } else { - m := map[string]interface{}{"liwe": 123, "aasd": "123"} - fmt.Printf("codec Marshal m:%s err:%v", m, err) - d, err := sys.MarshalMapJson(&TestData{Name: "http://liwei1dao.com?asd=1&dd=1", Value: 10, Array: []interface{}{1, "dajiahao", &Test1Data{Name: "liwe1dao", Value: 123}}, Data: map[string]interface{}{"hah": 1, "asd": 999}}) - fmt.Printf("codec Marshal d:%s err:%v", d, err) - data := &TestData{} - err = sys.UnmarshalMapJson(d, data) - fmt.Printf("codec UnmarshalJson data:%v err:%v", data, err) - } -} - -func Test_sys_reflect2(t *testing.T) { - data := []*Test1Data{} - ptr := reflect2.TypeOf(&data) - kind := ptr.Kind() - switch kind { - case reflect.Interface: - return - case reflect.Struct: - return - case reflect.Array: - return - case reflect.Slice: - return - case reflect.Map: - return - case reflect.Ptr: - ptrType := ptr.(*reflect2.UnsafePtrType) - elemType := ptrType.Elem() - kind = elemType.Kind() - if kind == reflect.Slice { - sliceelem := elemType.(*reflect2.UnsafeSliceType).Elem() - sliceelemkind := sliceelem.Kind() - if sliceelemkind == reflect.Ptr { - return - } - return - } - return - default: - return - } -} diff --git a/lego/sys/gin/core.go b/lego/sys/gin/core.go index c35264623..253d2ec6c 100644 --- a/lego/sys/gin/core.go +++ b/lego/sys/gin/core.go @@ -18,13 +18,21 @@ type ISys interface { var defsys ISys -func OnInit(config map[string]interface{}, option ...Option) (err error) { - defsys, err = newSys(newOptions(config, option...)) +func OnInit(config map[string]interface{}, opt ...Option) (err error) { + var option *Options + if option, err = newOptions(config, opt...); err != nil { + return + } + defsys, err = newSys(option) return } -func NewSys(option ...Option) (sys ISys, err error) { - sys, err = newSys(newOptionsByOption(option...)) +func NewSys(opt ...Option) (sys ISys, err error) { + var option *Options + if option, err = newOptionsByOption(opt...); err != nil { + return + } + sys, err = newSys(option) return } diff --git a/lego/sys/gin/engine/context.go b/lego/sys/gin/engine/context.go index c01369042..20c94ea03 100644 --- a/lego/sys/gin/engine/context.go +++ b/lego/sys/gin/engine/context.go @@ -16,6 +16,7 @@ import ( "go_dreamfactory/lego/sys/gin/binding" "go_dreamfactory/lego/sys/gin/render" + "go_dreamfactory/lego/sys/log" ) const ( @@ -30,17 +31,17 @@ const ( ) const abortIndex int8 = math.MaxInt8 >> 1 -func newContext(sys ISys, engine *Engine, params *Params, skippedNodes *[]skippedNode) *Context { +func newContext(log log.ILogger, engine *Engine, params *Params, skippedNodes *[]skippedNode) *Context { return &Context{ engine: engine, params: params, skippedNodes: skippedNodes, - writermem: ResponseWriter{log: sys}, + writermem: ResponseWriter{log: log}, } } type Context struct { - Sys ISys + Log log.ILogger engine *Engine writermem ResponseWriter Request *http.Request @@ -351,7 +352,7 @@ func (this *Context) initFormCache() { req := this.Request if err := req.ParseMultipartForm(this.engine.MaxMultipartMemory); err != nil { if !errors.Is(err, http.ErrNotMultipart) { - this.Sys.Errorf("error on parse multipart form array: %v", err) + this.Log.Errorf("error on parse multipart form array: %v", err) } } this.formCache = req.PostForm diff --git a/lego/sys/gin/engine/core.go b/lego/sys/gin/engine/core.go index 0e67b2542..a94b96f15 100644 --- a/lego/sys/gin/engine/core.go +++ b/lego/sys/gin/engine/core.go @@ -2,8 +2,6 @@ package engine import ( "net/http" - - "go_dreamfactory/lego/sys/log" ) type HandlerFunc func(*Context) @@ -25,11 +23,6 @@ type RouteInfo struct { type RoutesInfo []RouteInfo -type ISys interface { - log.Ilogf - Debug() bool -} - type IRoutes interface { Group(relativePath string, handlers ...HandlerFunc) IRoutes Use(...HandlerFunc) IRoutes diff --git a/lego/sys/gin/engine/engine.go b/lego/sys/gin/engine/engine.go index ebe61d14c..91a106d3e 100644 --- a/lego/sys/gin/engine/engine.go +++ b/lego/sys/gin/engine/engine.go @@ -9,6 +9,7 @@ import ( "sync" "go_dreamfactory/lego/sys/gin/render" + "go_dreamfactory/lego/sys/log" "go_dreamfactory/lego/utils/codec" "golang.org/x/net/http2" @@ -33,14 +34,14 @@ var defaultTrustedCIDRs = []*net.IPNet{ }, } -func NewEngine(sys ISys) (engine *Engine) { +func NewEngine(log log.ILogger) (engine *Engine) { engine = &Engine{ RouterGroup: RouterGroup{ Handlers: nil, basePath: "/", root: true, }, - sys: sys, + log: log, FuncMap: template.FuncMap{}, RedirectTrailingSlash: true, RedirectFixedPath: false, @@ -72,7 +73,7 @@ var mimePlain = []string{MIMEPlain} type Engine struct { RouterGroup - sys ISys + log log.ILogger UseRawPath bool /* 如果启用,路由器尝试修复当前请求路径,如果没有 @@ -194,7 +195,7 @@ func (this *Engine) LoadHTMLGlob(pattern string) { right := this.delims.Right templ := template.Must(template.New("").Delims(left, right).Funcs(this.FuncMap).ParseGlob(pattern)) - if this.sys.Debug() { + if this.log.Enabled(log.DebugLevel) { this.debugPrintLoadTemplate(templ) this.HTMLRender = render.HTMLDebug{Glob: pattern, FuncMap: this.FuncMap, Delims: this.delims} return @@ -208,7 +209,7 @@ LoadHTMLFiles 加载一段 HTML 文件 并将结果与 HTML 渲染器相关联。 */ func (this *Engine) LoadHTMLFiles(files ...string) { - if this.sys.Debug() { + if this.log.Enabled(log.DebugLevel) { this.HTMLRender = render.HTMLDebug{Files: files, FuncMap: this.FuncMap, Delims: this.delims} return } @@ -218,7 +219,7 @@ func (this *Engine) LoadHTMLFiles(files ...string) { func (this *Engine) SetHTMLTemplate(templ *template.Template) { if len(this.trees) > 0 { - this.sys.Warnf(`Since SetHTMLTemplate() is NOT thread-safe. It should only be called + this.log.Warnf(`Since SetHTMLTemplate() is NOT thread-safe. It should only be called at initialization. ie. before any route is registered or the router is listening in a socket: router := gin.Default() router.SetHTMLTemplate(template) // << good place @@ -270,10 +271,10 @@ func (this *Engine) addRoute(method, path string, handlers HandlersChain) { assert1(path[0] == '/', "path must begin with '/'") assert1(method != "", "HTTP method can not be empty") assert1(len(handlers) > 0, "there must be at least one handler") - if this.sys.Debug() { + if this.log.Enabled(log.DebugLevel) { nuHandlers := len(handlers) handlerName := nameOfFunction(handlers.Last()) - this.sys.Debugf("%s:%s --> %s handlers:%d", method, path, handlerName, nuHandlers) + this.log.Debugf("%s:%s --> %s handlers:%d", method, path, handlerName, nuHandlers) } root := this.trees.get(method) if root == nil { @@ -406,7 +407,7 @@ func (this *Engine) serveError(c *Context, code int, defaultMessage []byte) { c.writermem.Header()["Content-Type"] = mimePlain _, err := c.Writer.Write(defaultMessage) if err != nil { - this.sys.Errorf("[SYS-Gin] cannot write message to writer during serve error: %v", err) + this.log.Errorf("[SYS-Gin] cannot write message to writer during serve error: %v", err) } return } @@ -447,7 +448,7 @@ func (this *Engine) redirectRequest(c *Context) { if req.Method != http.MethodGet { code = http.StatusTemporaryRedirect } - this.sys.Debugf("redirecting request %d: %s --> %s", code, rPath, rURL) + this.log.Debugf("redirecting request %d: %s --> %s", code, rPath, rURL) http.Redirect(c.Writer, req, rURL, code) c.writermem.WriteHeaderNow() } @@ -490,22 +491,21 @@ func (this *Engine) prepareTrustedCIDRs() ([]*net.IPNet, error) { func (this *Engine) allocateContext() *Context { v := make(Params, 0, this.maxParams) skippedNodes := make([]skippedNode, 0, this.maxSections) - return &Context{Sys: this.sys, engine: this, params: &v, skippedNodes: &skippedNodes} + return &Context{Log: this.log, engine: this, params: &v, skippedNodes: &skippedNodes} } //日志接口------------------------------------------------------------- func (this *Engine) debugPrintLoadTemplate(tmpl *template.Template) { - if this.sys.Debug() { - var buf strings.Builder - for _, tmpl := range tmpl.Templates() { - buf.WriteString("\t- ") - buf.WriteString(tmpl.Name()) - buf.WriteString("\n") - } - format := "Loaded HTML Templates (%d): \n%s\n" - if !strings.HasSuffix(format, "\n") { - format += "\n" - } - this.sys.Debugf(format, len(tmpl.Templates()), buf.String()) + var buf strings.Builder + for _, tmpl := range tmpl.Templates() { + buf.WriteString("\t- ") + buf.WriteString(tmpl.Name()) + buf.WriteString("\n") } + format := "Loaded HTML Templates (%d): \n%s\n" + if !strings.HasSuffix(format, "\n") { + format += "\n" + } + this.log.Debugf(format, len(tmpl.Templates()), buf.String()) + } diff --git a/lego/sys/gin/engine/response_writer.go b/lego/sys/gin/engine/response_writer.go index 1b420c165..296a7a3d7 100644 --- a/lego/sys/gin/engine/response_writer.go +++ b/lego/sys/gin/engine/response_writer.go @@ -33,7 +33,7 @@ type IResponseWriter interface { } type ResponseWriter struct { http.ResponseWriter - log log.Ilogf + log log.ILogger size int status int } diff --git a/lego/sys/gin/gin.go b/lego/sys/gin/gin.go index 30c21eea3..6b224e12c 100644 --- a/lego/sys/gin/gin.go +++ b/lego/sys/gin/gin.go @@ -12,11 +12,11 @@ import ( "go_dreamfactory/lego/sys/gin/middleware/recovery" ) -func newSys(options Options) (sys *Gin, err error) { +func newSys(options *Options) (sys *Gin, err error) { sys = &Gin{ options: options, } - sys.engine = engine.NewEngine(sys) + sys.engine = engine.NewEngine(options.Log) ///添加基础中间件 sys.engine.Use(logger.Logger([]string{}), recovery.Recovery()) if options.CertFile != "" && options.KeyFile != "" { @@ -28,7 +28,7 @@ func newSys(options Options) (sys *Gin, err error) { } type Gin struct { - options Options + options *Options server *http.Server engine *engine.Engine } @@ -36,7 +36,7 @@ type Gin struct { func (this *Gin) Run(listenPort int) (err error) { defer func() { if err != nil { - this.Errorf("Run err:%v", err) + this.options.Log.Errorf("Run err:%v", err) } }() // if this.engine.IsUnsafeTrustedProxies() { @@ -44,14 +44,14 @@ func (this *Gin) Run(listenPort int) (err error) { // "Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.") // } - this.Debugf("Listening and serving HTTP on:%d", listenPort) + this.options.Log.Debugf("Listening and serving HTTP on:%d", listenPort) this.server = &http.Server{ Addr: fmt.Sprintf(":%d", listenPort), Handler: this.engine.Handler(), } go func() { if err := this.server.ListenAndServe(); err != nil && errors.Is(err, http.ErrServerClosed) { - this.Errorf("Run err:%v", err) + this.options.Log.Errorln(err) } }() // err = http.ListenAndServe(fmt.Sprintf(":%d", this.options.ListenPort), this.Handler()) @@ -59,10 +59,10 @@ func (this *Gin) Run(listenPort int) (err error) { } func (this *Gin) RunTLS(listenPort int, certFile, keyFile string) (err error) { - this.Debugf("Listening and serving HTTPS on :%d", listenPort) + this.options.Log.Debugf("Listening and serving HTTPS on :%d", listenPort) defer func() { if err != nil { - this.Errorf("RunTLS err:%v", err) + this.options.Log.Errorln(err) } }() @@ -76,7 +76,7 @@ func (this *Gin) RunTLS(listenPort int, certFile, keyFile string) (err error) { } go func() { if err := this.server.ListenAndServeTLS(certFile, keyFile); err != nil && errors.Is(err, http.ErrServerClosed) { - this.Errorf("listen err:%s", err) + this.options.Log.Errorln(err) } }() // err = http.ListenAndServeTLS(addr, certFile, keyFile, this.Handler()) @@ -84,10 +84,10 @@ func (this *Gin) RunTLS(listenPort int, certFile, keyFile string) (err error) { } func (this *Gin) RunListener(listener net.Listener) (err error) { - this.Debugf("Listening and serving HTTP on listener what's bind with address@%s", listener.Addr()) + this.options.Log.Debugf("Listening and serving HTTP on listener what's bind with address@%s", listener.Addr()) defer func() { if err != nil { - this.Errorf("Run err:%v", err) + this.options.Log.Errorln(err) } }() @@ -102,7 +102,7 @@ func (this *Gin) RunListener(listener net.Listener) (err error) { func (this *Gin) Close() (err error) { if err = this.server.Shutdown(context.Background()); err != nil { - this.Errorf("Close err:%v", err) + this.options.Log.Errorln(err) } this.server.Close() return @@ -154,39 +154,3 @@ func (this *Gin) Static(relativePath string, root string) engine.IRoutes { func (this *Gin) StaticFS(relativePath string, fs http.FileSystem) engine.IRoutes { return this.engine.StaticFS(relativePath, fs) } - -///日志*********************************************************************** -func (this *Gin) Debug() bool { - return this.options.Debug -} - -func (this *Gin) Debugf(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Debugf("[SYS Gin] "+format, a...) - } -} -func (this *Gin) Infof(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Infof("[SYS Gin] "+format, a...) - } -} -func (this *Gin) Warnf(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Warnf("[SYS Gin] "+format, a...) - } -} -func (this *Gin) Errorf(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Errorf("[SYS Gin] "+format, a...) - } -} -func (this *Gin) Panicf(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Panicf("[SYS Gin] "+format, a...) - } -} -func (this *Gin) Fatalf(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Fatalf("[SYS Gin] "+format, a...) - } -} diff --git a/lego/sys/gin/middleware/logger/logger.go b/lego/sys/gin/middleware/logger/logger.go index 71b293a51..5bf1f24cf 100644 --- a/lego/sys/gin/middleware/logger/logger.go +++ b/lego/sys/gin/middleware/logger/logger.go @@ -71,7 +71,7 @@ func Logger(SkipPaths []string) engine.HandlerFunc { path = path + "?" + raw } param.Path = path - c.Sys.Debugf(fmt.Sprintf("[FORMATTER TEST] %v | %3d | %13v | %15s | %-7s %s\n%s", + c.Log.Debugf(fmt.Sprintf("[FORMATTER TEST] %v | %3d | %13v | %15s | %-7s %s\n%s", param.TimeStamp.Format("2006/01/02 - 15:04:05"), param.StatusCode, param.Latency, diff --git a/lego/sys/gin/middleware/recovery/recovery.go b/lego/sys/gin/middleware/recovery/recovery.go index 9b2695a8e..deef67e6e 100644 --- a/lego/sys/gin/middleware/recovery/recovery.go +++ b/lego/sys/gin/middleware/recovery/recovery.go @@ -73,13 +73,10 @@ func CustomRecoveryWithWriter(handle RecoveryFunc) engine.HandlerFunc { } headersToStr := strings.Join(headers, "\r\n") if brokenPipe { - c.Sys.Errorf("%s\n%s%s", err, headersToStr, reset) - } else if c.Sys.Debug() { - c.Sys.Errorf("[Recovery] %s panic recovered:\n%s\n%s\n%s%s", - timeFormat(time.Now()), headersToStr, err, stack, reset) + c.Log.Errorf("%s\n%s%s", err, headersToStr, reset) } else { - c.Sys.Errorf("[Recovery] %s panic recovered:\n%s\n%s%s", - timeFormat(time.Now()), err, stack, reset) + c.Log.Errorf("[Recovery] %s panic recovered:\n%s\n%s\n%s%s", + timeFormat(time.Now()), headersToStr, err, stack, reset) } if brokenPipe { diff --git a/lego/sys/gin/options.go b/lego/sys/gin/options.go index 4111841ce..72073ac34 100644 --- a/lego/sys/gin/options.go +++ b/lego/sys/gin/options.go @@ -1,6 +1,8 @@ package gin import ( + "errors" + "go_dreamfactory/lego/sys/log" "go_dreamfactory/lego/utils/mapstructure" ) @@ -11,7 +13,7 @@ type Options struct { CertFile string //tls文件 KeyFile string //tls文件 Debug bool //日志是否开启 - Log log.ILog + Log log.ILogger } func SetListenPort(v int) Option { @@ -38,39 +40,47 @@ func SetDebug(v bool) Option { } } -func SetLog(v log.ILog) Option { +func SetLog(v log.ILogger) Option { return func(o *Options) { o.Log = v } } -func newOptions(config map[string]interface{}, opts ...Option) Options { - options := Options{ +func newOptions(config map[string]interface{}, opts ...Option) (options *Options, err error) { + options = &Options{ ListenPort: 8080, CertFile: "", KeyFile: "", Debug: true, - Log: log.Clone(log.SetLoglayer(2)), } if config != nil { mapstructure.Decode(config, &options) } for _, o := range opts { - o(&options) + o(options) } - return options + + if options.Log = log.NewTurnlog(options.Debug, log.Clone("sys.discovery", 2)); options.Log == nil { + err = errors.New("log is nil") + } + + return } -func newOptionsByOption(opts ...Option) Options { - options := Options{ +func newOptionsByOption(opts ...Option) (options *Options, err error) { + options = &Options{ ListenPort: 8080, CertFile: "", KeyFile: "", Debug: true, - Log: log.Clone(log.SetLoglayer(2)), } for _, o := range opts { - o(&options) + o(options) } - return options + + if options.Log = log.NewTurnlog(options.Debug, log.Clone("sys.discovery", 2)); options.Log == nil { + err = errors.New("log is nil") + } + + return } diff --git a/lego/sys/gin/sys_test.go b/lego/sys/gin/sys_test.go index c2a8299e3..b4e4723ef 100644 --- a/lego/sys/gin/sys_test.go +++ b/lego/sys/gin/sys_test.go @@ -14,7 +14,7 @@ import ( ) func Test_sys(t *testing.T) { - if err := log.OnInit(nil); err != nil { + if err := log.OnInit(nil, log.SetFileName("test"), log.SetReportCaller(true)); err != nil { fmt.Printf("log init err:%v", err) return } diff --git a/lego/sys/log/chown.go b/lego/sys/log/chown.go new file mode 100644 index 000000000..3cce41b1c --- /dev/null +++ b/lego/sys/log/chown.go @@ -0,0 +1,12 @@ +//go:build !linux +// +build !linux + +package log + +import ( + "os" +) + +func chown(_ string, _ os.FileInfo) error { + return nil +} diff --git a/lego/sys/log/chown_linux.go b/lego/sys/log/chown_linux.go new file mode 100644 index 000000000..071abedd3 --- /dev/null +++ b/lego/sys/log/chown_linux.go @@ -0,0 +1,19 @@ +package log + +import ( + "os" + "syscall" +) + +// osChown is a var so we can mock it out during tests. +var osChown = os.Chown + +func chown(name string, info os.FileInfo) error { + f, err := os.OpenFile(name, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, info.Mode()) + if err != nil { + return err + } + f.Close() + stat := info.Sys().(*syscall.Stat_t) + return osChown(name, int(stat.Uid), int(stat.Gid)) +} diff --git a/lego/sys/log/core.go b/lego/sys/log/core.go index a9024acfe..d3dc4f4ee 100644 --- a/lego/sys/log/core.go +++ b/lego/sys/log/core.go @@ -1,82 +1,138 @@ package log -import ( - "fmt" - "os" - "strings" - - "go_dreamfactory/lego/utils/flietools" -) +var AllLevels = []Loglevel{ + PanicLevel, + FatalLevel, + ErrorLevel, + WarnLevel, + InfoLevel, + DebugLevel, +} type ( - LogStrut interface { - ToString() (str string) - } Field struct { Key string Value interface{} } - Ilogf interface { - Debugf(format string, a ...interface{}) - Infof(format string, a ...interface{}) - Warnf(format string, a ...interface{}) - Errorf(format string, a ...interface{}) - Panicf(format string, a ...interface{}) - Fatalf(format string, a ...interface{}) + Fields []Field + Ilogf interface { + Debugf(format string, args ...interface{}) + Infof(format string, args ...interface{}) + Printf(format string, args ...interface{}) + Warnf(format string, args ...interface{}) + Errorf(format string, args ...interface{}) + Fatalf(format string, args ...interface{}) + Panicf(format string, args ...interface{}) + } + IlogIn interface { + Debugln(args ...interface{}) + Infoln(args ...interface{}) + Println(args ...interface{}) + Warnln(args ...interface{}) + Errorln(args ...interface{}) + Fatalln(args ...interface{}) + Panicln(args ...interface{}) } ILog interface { - Clone(option ...Option) ILog - Debug(msg string, fields ...Field) - Info(msg string, fields ...Field) - Warn(msg string, fields ...Field) - Error(msg string, fields ...Field) - Panic(msg string, fields ...Field) - Fatal(msg string, fields ...Field) + Debug(msg string, args ...Field) + Info(msg string, args ...Field) + Print(msg string, args ...Field) + Warn(msg string, args ...Field) + Error(msg string, args ...Field) + Fatal(msg string, args ...Field) + Panic(msg string, args ...Field) + } + ILogger interface { + SetName(name string) + Enabled(lvl Loglevel) bool Ilogf + IlogIn + ILog + } + ISys interface { + Clone(name string, skip int) ILogger + ILogger } ) var ( - defsys ILog + defsys ISys ) -func OnInit(config map[string]interface{}, option ...Option) (err error) { - defsys, err = newSys(newOptions(config, option...)) - return -} -func NewSys(option ...Option) (sys ILog, err error) { - sys, err = newSys(newOptionsByOption(option...)) +func OnInit(config map[string]interface{}, opt ...Option) (err error) { + var option *Options + if option, err = newOptions(config, opt...); err != nil { + return + } + defsys, err = newSys(option) return } -func Clone(option ...Option) ILog { - if defsys != nil { - return defsys.Clone(option...) +func NewSys(opt ...Option) (sys ISys, err error) { + var option *Options + if option, err = newOptionsByOption(opt...); err != nil { + return } - return nil + sys, err = newSys(option) + return } - -func Debug(msg string, fields ...Field) { defsys.Debug(msg, fields...) } -func Info(msg string, fields ...Field) { defsys.Info(msg, fields...) } -func Warn(msg string, fields ...Field) { defsys.Warn(msg, fields...) } -func Error(msg string, fields ...Field) { defsys.Error(msg, fields...) } -func Panic(msg string, fields ...Field) { defsys.Panic(msg, fields...) } -func Fatal(msg string, fields ...Field) { defsys.Fatal(msg, fields...) } -func Debugf(format string, a ...interface{}) { defsys.Debugf(format, a...) } -func Infof(format string, a ...interface{}) { defsys.Infof(format, a...) } -func Warnf(format string, a ...interface{}) { defsys.Warnf(format, a...) } -func Errorf(format string, a ...interface{}) { defsys.Errorf(format, a...) } -func Panicf(format string, a ...interface{}) { defsys.Panicf(format, a...) } -func Fatalf(format string, a ...interface{}) { defsys.Fatalf(format, a...) } - -//创建日志文件 -func createlogfile(logpath string) error { - logdir := string(logpath[0:strings.LastIndex(logpath, "/")]) - if !flietools.IsExist(logdir) { - err := os.MkdirAll(logdir, os.ModePerm) - if err != nil { - return fmt.Errorf("创建日志路径失败 1" + err.Error()) - } - } - return nil +func Clone(name string, skip int) ILogger { + return defsys.Clone(name, skip) +} +func Debug(msg string, args ...Field) { + defsys.Debug(msg, args...) +} +func Info(msg string, args ...Field) { + defsys.Info(msg, args...) +} +func Warn(msg string, args ...Field) { + defsys.Warn(msg, args...) +} +func Error(msg string, args ...Field) { + defsys.Error(msg, args...) +} +func Fatal(msg string, args ...Field) { + defsys.Fatal(msg, args...) +} +func Panic(msg string, args ...Field) { + defsys.Panic(msg, args...) +} +func Debugf(format string, args ...interface{}) { + defsys.Debugf(format, args...) +} +func Infof(format string, args ...interface{}) { + defsys.Infof(format, args...) +} +func Warnf(format string, args ...interface{}) { + defsys.Warnf(format, args...) +} +func Errorf(format string, args ...interface{}) { + defsys.Errorf(format, args...) +} +func Fatalf(format string, args ...interface{}) { + defsys.Fatalf(format, args...) +} +func Panicf(format string, args ...interface{}) { + defsys.Panicf(format, args...) +} +func Debugln(args ...interface{}) { + defsys.Debugln(args...) +} +func Infoln(args ...interface{}) { + defsys.Infoln(args...) +} +func Println(args ...interface{}) { + defsys.Println(args...) +} +func Warnln(args ...interface{}) { + defsys.Warnln(args...) +} +func Errorln(args ...interface{}) { + defsys.Errorln(args...) +} +func Fatalln(args ...interface{}) { + defsys.Fatalln(args...) +} +func Panicln(args ...interface{}) { + defsys.Panicln(args...) } diff --git a/lego/sys/log/entry.go b/lego/sys/log/entry.go new file mode 100644 index 000000000..ad98713b2 --- /dev/null +++ b/lego/sys/log/entry.go @@ -0,0 +1,116 @@ +package log + +import ( + "fmt" + "reflect" + "strings" + "sync" + "time" + + "go_dreamfactory/lego/utils/pools" +) + +var ( + _cePool = sync.Pool{New: func() interface{} { + // Pre-allocate some space for cores. + return &Entry{ + Data: make(Fields, 0, 6), + } + }} +) + +func getEntry() *Entry { + return _cePool.Get().(*Entry) +} +func putEntry(e *Entry) { + e.reset() + _cePool.Put(e) +} + +//日志堆栈信息 +type EntryCaller struct { + Defined bool + PC uintptr + File string + Line int + Function string + Stack string +} + +func (ec EntryCaller) String() string { + return ec.FullPath() +} +func (ec EntryCaller) FullPath() string { + if !ec.Defined { + return "undefined" + } + buf := pools.BufferPoolGet() + buf.AppendString(ec.File) + buf.AppendByte(':') + buf.AppendInt(int64(ec.Line)) + caller := buf.String() + buf.Free() + return caller +} +func (ec EntryCaller) TrimmedPath() string { + if !ec.Defined { + return "undefined" + } + idx := strings.LastIndexByte(ec.File, '/') + if idx == -1 { + return ec.FullPath() + } + idx = strings.LastIndexByte(ec.File[:idx], '/') + if idx == -1 { + return ec.FullPath() + } + buf := pools.BufferPoolGet() + buf.AppendString(ec.File[idx+1:]) + buf.AppendByte(':') + buf.AppendInt(int64(ec.Line)) + caller := buf.String() + buf.Free() + return caller +} + +type Entry struct { + Name string + Level Loglevel + Caller EntryCaller + Time time.Time + Message string + Data Fields + Err string +} + +func (entry *Entry) reset() { + entry.Message = "" + entry.Err = "" + entry.Data = entry.Data[:0] +} + +func (entry *Entry) WithFields(fields ...Field) { + if cap(entry.Data) < len(fields) { + entry.Data = make(Fields, 0, cap(entry.Data)+len(fields)) + } + fieldErr := entry.Err + for _, v := range fields { + isErrField := false + if t := reflect.TypeOf(v.Value); t != nil { + switch { + case t.Kind() == reflect.Func, t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Func: + isErrField = true + } + } + if isErrField { + tmp := fmt.Sprintf("can not add field %q", v.Key) + if fieldErr != "" { + fieldErr = entry.Err + ", " + tmp + } else { + fieldErr = tmp + } + } else { + entry.Data = append(entry.Data, v) + } + } +} diff --git a/lego/sys/log/flieout.go b/lego/sys/log/flieout.go new file mode 100644 index 000000000..9567e7145 --- /dev/null +++ b/lego/sys/log/flieout.go @@ -0,0 +1,391 @@ +package log + +import ( + "compress/gzip" + "errors" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "sort" + "strings" + "sync" + "time" +) + +const ( + backupTimeFormat = "2006-01-02T15-04-05.000" + compressSuffix = ".gz" + defaultMaxSize = 100 +) + +var ( + currentTime = time.Now + osStat = os.Stat + megabyte = 1024 * 1024 +) + +//日志文件输出 +type LogFileOut struct { + Filename string `json:"filename" yaml:"filename"` //日志文件名称 + MaxSize int `json:"maxsize" yaml:"maxsize"` //日志文件的大小 + CupTime time.Duration `json:"cuptime" yaml:"cuptime"` //日志切割间隔时间 + MaxAge int `json:"maxage" yaml:"maxage"` //日志的最大备份天数 + MaxBackups int `json:"maxbackups" yaml:"maxbackups"` //备份日志的最大数量 + LocalTime bool `json:"localtime" yaml:"localtime"` //是使用本地时间还是使用世界标准时间 + Compress bool `json:"compress" yaml:"compress"` //是否压缩备份日志 + size int64 + ctime time.Time + file *os.File + mu sync.Mutex + millCh chan bool + startMill sync.Once +} + +func (l *LogFileOut) filename() string { + if l.Filename != "" { + return l.Filename + } + name := filepath.Base(os.Args[0]) + "-lumberjack.log" + return filepath.Join(os.TempDir(), name) +} +func (l *LogFileOut) dir() string { + return filepath.Dir(l.filename()) +} + +func (l *LogFileOut) max() int64 { + if l.MaxSize == 0 { + return int64(defaultMaxSize * megabyte) + } + return int64(l.MaxSize) * int64(megabyte) +} +func (l *LogFileOut) Write(p []byte) (n int, err error) { + l.mu.Lock() + defer l.mu.Unlock() + writeLen := int64(len(p)) + if writeLen > l.max() { + return 0, fmt.Errorf( + "write length %d exceeds maximum file size %d", writeLen, l.max(), + ) + } + if l.file == nil { + if err = l.openExistingOrNew(len(p)); err != nil { + return 0, err + } + } + n, err = l.file.Write(p) + l.size += int64(n) + return n, err +} + +func (l *LogFileOut) openExistingOrNew(writeLen int) error { + l.mill() + + filename := l.filename() + info, err := osStat(filename) + if os.IsNotExist(err) { + return l.openNew() + } + if err != nil { + return fmt.Errorf("error getting log file info: %s", err) + } + + //校验是否需要切割日志 + if info.Size()+int64(writeLen) >= l.max() || time.Since(l.ctime) > l.CupTime { + return l.rotate() + } + + file, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY, 0644) + if err != nil { + // if we fail to open the old log file for some reason, just ignore + // it and open a new log file. + return l.openNew() + } + l.file = file + l.size = info.Size() + return nil +} + +//日志切割 +func (l *LogFileOut) rotate() error { + if err := l.close(); err != nil { + return err + } + if err := l.openNew(); err != nil { + return err + } + l.mill() + return nil +} + +func (l *LogFileOut) millRunOnce() error { + if l.MaxBackups == 0 && l.MaxAge == 0 && !l.Compress { + return nil + } + + files, err := l.oldLogFiles() + if err != nil { + return err + } + + var compress, remove []logInfo + + if l.MaxBackups > 0 && l.MaxBackups < len(files) { + preserved := make(map[string]bool) + var remaining []logInfo + for _, f := range files { + // Only count the uncompressed log file or the + // compressed log file, not both. + fn := f.Name() + if strings.HasSuffix(fn, compressSuffix) { + fn = fn[:len(fn)-len(compressSuffix)] + } + preserved[fn] = true + + if len(preserved) > l.MaxBackups { + remove = append(remove, f) + } else { + remaining = append(remaining, f) + } + } + files = remaining + } + if l.MaxAge > 0 { + diff := time.Duration(int64(24*time.Hour) * int64(l.MaxAge)) + cutoff := currentTime().Add(-1 * diff) + + var remaining []logInfo + for _, f := range files { + if f.timestamp.Before(cutoff) { + remove = append(remove, f) + } else { + remaining = append(remaining, f) + } + } + files = remaining + } + + if l.Compress { + for _, f := range files { + if !strings.HasSuffix(f.Name(), compressSuffix) { + compress = append(compress, f) + } + } + } + + for _, f := range remove { + errRemove := os.Remove(filepath.Join(l.dir(), f.Name())) + if err == nil && errRemove != nil { + err = errRemove + } + } + for _, f := range compress { + fn := filepath.Join(l.dir(), f.Name()) + errCompress := compressLogFile(fn, fn+compressSuffix) + if err == nil && errCompress != nil { + err = errCompress + } + } + + return err +} +func (l *LogFileOut) millRun() { + for range l.millCh { + // what am I going to do, log this? + _ = l.millRunOnce() + } +} + +//触发日志备份管理 +func (l *LogFileOut) mill() { + l.startMill.Do(func() { + l.millCh = make(chan bool, 1) + go l.millRun() + }) + select { + case l.millCh <- true: + default: + } +} + +//备份老的日志文件创建新的日志文件 +func (l *LogFileOut) openNew() error { + err := os.MkdirAll(l.dir(), 0755) + if err != nil { + return fmt.Errorf("can't make directories for new logfile: %s", err) + } + + name := l.filename() + mode := os.FileMode(0600) + info, err := osStat(name) + //备份老的日志文件 + if err == nil { + // Copy the mode off the old logfile. + mode = info.Mode() + // move the existing file + newname := backupName(name, l.LocalTime) + if err := os.Rename(name, newname); err != nil { + return fmt.Errorf("can't rename log file: %s", err) + } + + // this is a no-op anywhere but linux + if err := chown(name, info); err != nil { + return err + } + } + + //创建新的日志文件 + f, err := os.OpenFile(name, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, mode) + if err != nil { + return fmt.Errorf("can't open new logfile: %s", err) + } + l.file = f + l.size = 0 + l.ctime = currentTime() + return nil +} + +//关闭当前日志文件 +func (l *LogFileOut) close() error { + if l.file == nil { + return nil + } + err := l.file.Close() + l.file = nil + return err +} + +//获取备份的日子文件集合 +func (l *LogFileOut) oldLogFiles() ([]logInfo, error) { + files, err := ioutil.ReadDir(l.dir()) + if err != nil { + return nil, fmt.Errorf("can't read log file directory: %s", err) + } + logFiles := []logInfo{} + + prefix, ext := l.prefixAndExt() + + for _, f := range files { + if f.IsDir() { + continue + } + if t, err := l.timeFromName(f.Name(), prefix, ext); err == nil { + logFiles = append(logFiles, logInfo{t, f}) + continue + } + if t, err := l.timeFromName(f.Name(), prefix, ext+compressSuffix); err == nil { + logFiles = append(logFiles, logInfo{t, f}) + continue + } + // error parsing means that the suffix at the end was not generated + // by lumberjack, and therefore it's not a backup file. + } + + sort.Sort(byFormatTime(logFiles)) + + return logFiles, nil +} +func (l *LogFileOut) prefixAndExt() (prefix, ext string) { + filename := filepath.Base(l.filename()) + ext = filepath.Ext(filename) + prefix = filename[:len(filename)-len(ext)] + "-" + return prefix, ext +} +func (l *LogFileOut) timeFromName(filename, prefix, ext string) (time.Time, error) { + if !strings.HasPrefix(filename, prefix) { + return time.Time{}, errors.New("mismatched prefix") + } + if !strings.HasSuffix(filename, ext) { + return time.Time{}, errors.New("mismatched extension") + } + ts := filename[len(prefix) : len(filename)-len(ext)] + return time.Parse(backupTimeFormat, ts) +} + +//日志备份名 +func backupName(name string, local bool) string { + dir := filepath.Dir(name) + filename := filepath.Base(name) + ext := filepath.Ext(filename) + prefix := filename[:len(filename)-len(ext)] + t := currentTime() + if !local { + t = t.UTC() + } + + timestamp := t.Format(backupTimeFormat) + return filepath.Join(dir, fmt.Sprintf("%s-%s%s", prefix, timestamp, ext)) +} + +//压缩日志文件 +func compressLogFile(src, dst string) (err error) { + f, err := os.Open(src) + if err != nil { + return fmt.Errorf("failed to open log file: %v", err) + } + defer f.Close() + + fi, err := osStat(src) + if err != nil { + return fmt.Errorf("failed to stat log file: %v", err) + } + + if err := chown(dst, fi); err != nil { + return fmt.Errorf("failed to chown compressed log file: %v", err) + } + + // If this file already exists, we presume it was created by + // a previous attempt to compress the log file. + gzf, err := os.OpenFile(dst, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, fi.Mode()) + if err != nil { + return fmt.Errorf("failed to open compressed log file: %v", err) + } + defer gzf.Close() + + gz := gzip.NewWriter(gzf) + + defer func() { + if err != nil { + os.Remove(dst) + err = fmt.Errorf("failed to compress log file: %v", err) + } + }() + + if _, err := io.Copy(gz, f); err != nil { + return err + } + if err := gz.Close(); err != nil { + return err + } + if err := gzf.Close(); err != nil { + return err + } + + if err := f.Close(); err != nil { + return err + } + if err := os.Remove(src); err != nil { + return err + } + + return nil +} + +type logInfo struct { + timestamp time.Time + os.FileInfo +} +type byFormatTime []logInfo + +func (b byFormatTime) Less(i, j int) bool { + return b[i].timestamp.After(b[j].timestamp) +} + +func (b byFormatTime) Swap(i, j int) { + b[i], b[j] = b[j], b[i] +} + +func (b byFormatTime) Len() int { + return len(b) +} diff --git a/lego/sys/log/formatter.go b/lego/sys/log/formatter.go new file mode 100644 index 000000000..48a3cba52 --- /dev/null +++ b/lego/sys/log/formatter.go @@ -0,0 +1,70 @@ +package log + +import ( + "sync" + "time" + + "go_dreamfactory/lego/utils/pools" +) + +var _fieldsPool = sync.Pool{ + New: func() interface{} { + return make(Fields, 0, 6) + }, +} + +func getFields() Fields { + return _fieldsPool.Get().(Fields) +} + +func putFields(fields Fields) { + fields = fields[:0] + _fieldsPool.Put(fields) +} + +func NewDefEncoderConfig() *EncoderConfig { + return &EncoderConfig{ + TimeKey: "ts", + LevelKey: "level", + CallerKey: "caller", + MessageKey: "msg", + StacktraceKey: "stacktrace", + ConsoleSeparator: "\t", + EncodeTime: DefTimeEncoder, + EncodeLevel: LowercaseLevelEncoder, + EncodeCaller: ShortCallerEncoder, + } +} + +type TimeEncoder func(time.Time) string +type LevelEncoder func(Loglevel) string +type CallerEncoder func(EntryCaller) string + +func DefTimeEncoder(t time.Time) string { + return t.Format("2006/01/02 15:04:05.000") +} + +func LowercaseLevelEncoder(l Loglevel) string { + return l.CapitalString() +} + +func ShortCallerEncoder(caller EntryCaller) string { + return caller.TrimmedPath() +} + +type EncoderConfig struct { + MessageKey string `json:"messageKey" yaml:"messageKey"` + LevelKey string `json:"levelKey" yaml:"levelKey"` + TimeKey string `json:"timeKey" yaml:"timeKey"` + CallerKey string `json:"callerKey" yaml:"callerKey"` + FunctionKey string `json:"functionKey" yaml:"functionKey"` + StacktraceKey string `json:"stacktraceKey" yaml:"stacktraceKey"` + ConsoleSeparator string `json:"consoleSeparator" yaml:"consoleSeparator"` + EncodeTime TimeEncoder + EncodeLevel LevelEncoder + EncodeCaller CallerEncoder +} + +type Formatter interface { + Format(config *EncoderConfig, entry *Entry) (*pools.Buffer, error) +} diff --git a/lego/sys/log/formatter_console.go b/lego/sys/log/formatter_console.go new file mode 100644 index 000000000..56ff4180d --- /dev/null +++ b/lego/sys/log/formatter_console.go @@ -0,0 +1,144 @@ +package log + +import ( + "encoding/json" + "time" + + "go_dreamfactory/lego/utils/pools" +) + +func NewConsoleEncoder() Formatter { + return &ConsoleFormatter{} +} + +type ConsoleFormatter struct { + *EncoderConfig +} + +func (this *ConsoleFormatter) Format(config *EncoderConfig, entry *Entry) (*pools.Buffer, error) { + line := pools.BufferPoolGet() + isfirst := true + if config.TimeKey != "" && config.EncodeTime != nil { + line.AppendString(config.EncodeTime(entry.Time)) + isfirst = false + } + if config.LevelKey != "" && config.EncodeLevel != nil { + if !isfirst { + line.AppendString(config.ConsoleSeparator) + } + isfirst = false + line.AppendString(config.EncodeLevel(entry.Level)) + } + if entry.Caller.Defined { + if config.CallerKey != "" && config.EncodeCaller != nil { + if !isfirst { + line.AppendString(config.ConsoleSeparator) + } + isfirst = false + line.AppendString(config.EncodeCaller(entry.Caller)) + } + if config.FunctionKey != "" { + if !isfirst { + line.AppendString(config.ConsoleSeparator) + } + isfirst = false + line.AppendString(entry.Caller.Function) + } + } + if entry.Name != "" { + if !isfirst { + line.AppendString(config.ConsoleSeparator) + } + isfirst = false + line.AppendString("[") + line.AppendString(entry.Name) + line.AppendString("]") + } + + if config.MessageKey != "" { + if !isfirst { + line.AppendString(config.ConsoleSeparator) + } + isfirst = false + line.AppendString(entry.Message) + } + for _, v := range entry.Data { + if !isfirst { + line.AppendString(config.ConsoleSeparator) + } + isfirst = false + line.AppendString(v.Key) + line.AppendString(":") + writetoline(line, v.Value) + } + + if entry.Caller.Stack != "" && config.StacktraceKey != "" { + line.AppendString("\n") + line.AppendString(entry.Caller.Stack) + } + line.AppendString("\n") + return line, nil +} + +func writetoline(line *pools.Buffer, v interface{}) { + switch v := v.(type) { + case nil: + line.AppendString("nil") + break + case string: + line.AppendString(v) + break + case []byte: + line.AppendBytes(v) + break + case int: + line.AppendInt(int64(v)) + break + case int8: + line.AppendInt(int64(v)) + break + case int16: + line.AppendInt(int64(v)) + break + case int32: + line.AppendInt(int64(v)) + break + case int64: + line.AppendInt(int64(v)) + break + case uint: + line.AppendUint(uint64(v)) + break + case uint8: + line.AppendUint(uint64(v)) + break + case uint16: + line.AppendUint(uint64(v)) + break + case uint32: + line.AppendUint(uint64(v)) + break + case uint64: + line.AppendUint(uint64(v)) + break + case float32: + line.AppendFloat(float64(v), 64) + break + case float64: + line.AppendFloat(v, 64) + break + case bool: + line.AppendBool(v) + break + case time.Time: + line.AppendTime(v, time.RFC3339Nano) + break + case time.Duration: + line.AppendInt(v.Nanoseconds()) + break + default: + d, _ := json.Marshal(v) + line.AppendBytes(d) + break + } +} diff --git a/lego/sys/log/level.go b/lego/sys/log/level.go new file mode 100644 index 000000000..5a42c1964 --- /dev/null +++ b/lego/sys/log/level.go @@ -0,0 +1,59 @@ +package log + +import "fmt" + +type LevelEnabler interface { + Enabled(Loglevel) bool +} + +type Loglevel int8 + +const ( + PanicLevel Loglevel = iota + FatalLevel + ErrorLevel + WarnLevel + InfoLevel + DebugLevel +) + +func (l Loglevel) String() string { + switch l { + case DebugLevel: + return "debug" + case InfoLevel: + return "info" + case WarnLevel: + return "warn" + case ErrorLevel: + return "error" + case PanicLevel: + return "panic" + case FatalLevel: + return "fatal" + default: + return fmt.Sprintf("Level(%d)", l) + } +} +func (l Loglevel) CapitalString() string { + switch l { + case DebugLevel: + return "DEBUG" + case InfoLevel: + return "INFO" + case WarnLevel: + return "WARN" + case ErrorLevel: + return "ERROR" + case PanicLevel: + return "PANIC" + case FatalLevel: + return "FATAL" + default: + return fmt.Sprintf("LEVEL(%d)", l) + } +} + +func (l Loglevel) Enabled(lvl Loglevel) bool { + return lvl <= l +} diff --git a/lego/sys/log/logger.go b/lego/sys/log/logger.go new file mode 100644 index 000000000..50c527b92 --- /dev/null +++ b/lego/sys/log/logger.go @@ -0,0 +1,231 @@ +package log + +import ( + "fmt" + "os" + "time" + + "go_dreamfactory/lego/utils/pools" +) + +func newSys(options *Options) (sys *Logger, err error) { + hook := LogFileOut{ + Filename: options.FileName, //日志文件路径 + MaxAge: options.MaxAgeTime, //备份日志保存天数 + CupTime: time.Duration(options.CupTimeTime) * time.Hour, //日志切割间隔时间 + Compress: options.Compress, //是否压缩 disabled by default + MaxBackups: options.MaxBackups, //最大备份数 + LocalTime: true, //使用本地时间 + } + if err = hook.openNew(); err != nil { + return + } + out := make(writeTree, 0, 2) + out = append(out, AddSync(&hook)) + if options.IsDebug { + out = append(out, Lock(os.Stdout)) + } + sys = &Logger{ + config: NewDefEncoderConfig(), + formatter: NewConsoleEncoder(), + out: out, + level: options.Loglevel, + addCaller: options.ReportCaller, + callerSkip: options.CallerSkip, + addStack: FatalLevel, + } + return +} + +type Logger struct { + config *EncoderConfig //编码配置 + level LevelEnabler //日志输出级别 + formatter Formatter //日志格式化 + name string //日志标签 + out IWrite //日志输出 + addCaller bool //是否打印堆栈信息 + addStack LevelEnabler //堆栈信息输出级别 + callerSkip int //堆栈输出深度 +} + +func (this *Logger) Clone(name string, skip int) ILogger { + return &Logger{ + config: this.config, + formatter: this.formatter, + name: name, + out: this.out, + level: this.level, + addCaller: this.addCaller, + callerSkip: skip, + addStack: this.addStack, + } +} +func (this *Logger) SetName(name string) { + this.name = name +} +func (this *Logger) Enabled(lvl Loglevel) bool { + return this.level.Enabled(lvl) +} +func (this *Logger) Debug(msg string, args ...Field) { + this.Log(DebugLevel, msg, args...) +} +func (this *Logger) Info(msg string, args ...Field) { + this.Log(InfoLevel, msg, args...) +} +func (this *Logger) Print(msg string, args ...Field) { + this.Log(InfoLevel, msg, args...) +} +func (this *Logger) Warn(msg string, args ...Field) { + this.Log(WarnLevel, msg, args...) +} +func (this *Logger) Error(msg string, args ...Field) { + this.Log(ErrorLevel, msg, args...) +} +func (this *Logger) Panic(msg string, args ...Field) { + this.Log(PanicLevel, msg, args...) +} +func (this *Logger) Fatal(msg string, args ...Field) { + this.Log(FatalLevel, msg, args...) + os.Exit(1) +} +func (this *Logger) Log(level Loglevel, msg string, args ...Field) { + if this.level.Enabled(level) { + this.log(level, msg, args...) + } +} +func (this *Logger) Debugf(format string, args ...interface{}) { + this.Logf(DebugLevel, format, args...) +} +func (this *Logger) Infof(format string, args ...interface{}) { + this.Logf(InfoLevel, format, args...) +} +func (this *Logger) Printf(format string, args ...interface{}) { + this.Logf(InfoLevel, format, args...) +} +func (this *Logger) Warnf(format string, args ...interface{}) { + this.Logf(WarnLevel, format, args...) +} +func (this *Logger) Errorf(format string, args ...interface{}) { + this.Logf(ErrorLevel, format, args...) +} +func (this *Logger) Fatalf(format string, args ...interface{}) { + this.Logf(FatalLevel, format, args...) + os.Exit(1) +} +func (this *Logger) Panicf(format string, args ...interface{}) { + this.Logf(PanicLevel, format, args...) +} +func (this *Logger) Logf(level Loglevel, format string, args ...interface{}) { + if this.level.Enabled(level) { + this.log(level, fmt.Sprintf(format, args...)) + } +} +func (this *Logger) Debugln(args ...interface{}) { + this.Logln(DebugLevel, args...) +} +func (this *Logger) Infoln(args ...interface{}) { + this.Logln(InfoLevel, args...) +} +func (this *Logger) Println(args ...interface{}) { + this.Logln(InfoLevel, args...) +} +func (this *Logger) Warnln(args ...interface{}) { + this.Logln(WarnLevel, args...) +} +func (this *Logger) Errorln(args ...interface{}) { + this.Logln(ErrorLevel, args...) +} +func (this *Logger) Fatalln(args ...interface{}) { + this.Logln(FatalLevel, args...) + os.Exit(1) +} +func (this *Logger) Panicln(args ...interface{}) { + this.Logln(PanicLevel, args...) +} +func (this *Logger) Logln(level Loglevel, args ...interface{}) { + if this.level.Enabled(level) { + this.log(level, this.sprintlnn(args...)) + } +} + +func (this *Logger) log(level Loglevel, msg string, args ...Field) { + entry := this.check(level, msg, args...) + this.write(entry) + if level <= PanicLevel { + panic(entry) + } + putEntry(entry) +} + +func (this *Logger) check(level Loglevel, msg string, args ...Field) (entry *Entry) { + entry = getEntry() + entry.Name = this.name + entry.Time = time.Now() + entry.Level = level + entry.Message = msg + entry.WithFields(args...) + addStack := this.addStack.Enabled(level) + if !this.addCaller && !addStack { + return + } + stackDepth := stacktraceFirst + if addStack { + stackDepth = stacktraceFull + } + stack := captureStacktrace(this.callerSkip+callerSkipOffset, stackDepth) + defer stack.Free() + if stack.Count() == 0 { + if this.addCaller { + if entry.Err != "" { + entry.Err = entry.Err + ",error: failed to get caller" + } else { + entry.Err = "error:failed to get caller" + } + } + return + } + frame, more := stack.Next() + if this.addCaller { + entry.Caller.Defined = frame.PC != 0 + entry.Caller.PC = frame.PC + entry.Caller.File = frame.File + entry.Caller.Line = frame.Line + entry.Caller.Function = frame.Function + } + if addStack { + buffer := pools.BufferPoolGet() + defer buffer.Free() + + stackfmt := newStackFormatter(buffer) + + stackfmt.FormatFrame(frame) + if more { + stackfmt.FormatStack(stack) + } + entry.Caller.Stack = buffer.String() + } + return +} + +func (this *Logger) write(entry *Entry) { + buf, err := this.formatter.Format(this.config, entry) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err) + return + } + err = this.out.WriteTo(buf.Bytes()) + buf.Free() + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to obtain write, %v\n", err) + return + } + if entry.Level < ErrorLevel { + this.out.Sync() + } + return +} + +func (this *Logger) sprintlnn(args ...interface{}) string { + msg := fmt.Sprintln(args...) + return msg[:len(msg)-1] +} diff --git a/lego/sys/log/options.go b/lego/sys/log/options.go index a87adfbd1..1795cee19 100644 --- a/lego/sys/log/options.go +++ b/lego/sys/log/options.go @@ -1,114 +1,139 @@ package log import ( + "errors" + "go_dreamfactory/lego/utils/mapstructure" ) -type Loglevel int8 - -const ( - DebugLevel Loglevel = iota - InfoLevel - WarnLevel - ErrorLevel - PanicLevel - FatalLevel -) - type LogEncoder int8 const ( - Console LogEncoder = iota - JSON + TextEncoder LogEncoder = iota + JSONEncoder ) type Option func(*Options) type Options struct { - FileName string //日志文件名包含 - Loglevel Loglevel //日志输出级别 - Debugmode bool //是否debug模式 - Encoder LogEncoder //日志输出样式 - Loglayer int //日志堆栈信息打印层级 - LogMaxSize int //每个日志文件最大尺寸 单位 M 默认 1024M - LogMaxBackups int //最多保留备份个数 默认 10个 - LogMaxAge int //文件最多保存多少天 默认 7天 + FileName string //日志文件名包含 + Loglevel Loglevel //日志输出级别 + IsDebug bool //是否是开发模式 + ReportCaller bool //是否输出堆栈信息 + CallerSkip int //堆栈深度 + Encoder LogEncoder //日志输出样式 + CupTimeTime int //日志分割时间 单位 小时 + MaxAgeTime int //日志最大保存时间 单位天 + MaxBackups int //最大备份日志个数 + Compress bool //是否压缩备份日志 } +///日志文件名包含 func SetFileName(v string) Option { return func(o *Options) { o.FileName = v } } +//是否是开发模式 +func SetIsDebug(v bool) Option { + return func(o *Options) { + o.IsDebug = v + } +} + +///日志输出级别 debug info warning error fatal panic func SetLoglevel(v Loglevel) Option { return func(o *Options) { o.Loglevel = v } } -func SetDebugMode(v bool) Option { +func SetReportCaller(v bool) Option { return func(o *Options) { - o.Debugmode = v + o.ReportCaller = v } } +func SetCallerSkip(v int) Option { + return func(o *Options) { + o.CallerSkip = v + } +} + +///日志输出样式 func SetEncoder(v LogEncoder) Option { return func(o *Options) { o.Encoder = v } } -func SetLoglayer(v int) Option { + +///日志分割时间 单位 小时 +func SetRotationTime(v int) Option { return func(o *Options) { - o.Loglayer = v - } -} -func SetLogMaxSize(v int) Option { - return func(o *Options) { - o.LogMaxSize = v - } -} -func SetLogMaxBackups(v int) Option { - return func(o *Options) { - o.LogMaxBackups = v - } -} -func SetLogMaxAge(v int) Option { - return func(o *Options) { - o.LogMaxAge = v + o.CupTimeTime = v } } -func newOptions(config map[string]interface{}, opts ...Option) Options { - options := Options{ - FileName: "./lego.log", - Loglevel: WarnLevel, - Debugmode: false, - Encoder: Console, - Loglayer: 2, - LogMaxSize: 1024, - LogMaxBackups: 10, - LogMaxAge: 7, +///日志最大保存时间 单位天 +func SetMaxAgeTime(v int) Option { + return func(o *Options) { + o.MaxAgeTime = v + } +} + +///日志备份最大文件数 +func SetMaxBackups(v int) Option { + return func(o *Options) { + o.MaxBackups = v + } +} + +///是否压缩备份日志 +func SetCompress(v bool) Option { + return func(o *Options) { + o.Compress = v + } +} +func newOptions(config map[string]interface{}, opts ...Option) (options *Options, err error) { + options = &Options{ + FileName: "log", + Loglevel: DebugLevel, + CupTimeTime: 24, + MaxAgeTime: 7, + MaxBackups: 250, + Compress: false, + Encoder: TextEncoder, + CallerSkip: 0, + ReportCaller: false, + IsDebug: true, } if config != nil { - mapstructure.Decode(config, &options) + mapstructure.Decode(config, options) } for _, o := range opts { - o(&options) + o(options) } - return options + if options.CupTimeTime <= 0 || options.MaxAgeTime <= 0 { + err = errors.New("log options RotationTime or MaxAgeTime is zero!") + return + } + return } -func newOptionsByOption(opts ...Option) Options { - options := Options{ - FileName: "./lego.log", - Loglevel: WarnLevel, - Debugmode: false, - Loglayer: 2, - LogMaxSize: 1024, - LogMaxBackups: 10, - LogMaxAge: 7, +func newOptionsByOption(opts ...Option) (options *Options, err error) { + options = &Options{ + FileName: "log.log", + Loglevel: DebugLevel, + CupTimeTime: 24, + MaxAgeTime: 7, + MaxBackups: 250, + Compress: false, + Encoder: TextEncoder, + CallerSkip: 0, + ReportCaller: false, + IsDebug: true, } for _, o := range opts { - o(&options) + o(options) } - return options + return } diff --git a/lego/sys/log/stacktrace.go b/lego/sys/log/stacktrace.go new file mode 100644 index 000000000..8a2910c9d --- /dev/null +++ b/lego/sys/log/stacktrace.go @@ -0,0 +1,156 @@ +package log + +import ( + "runtime" + "sync" + + "go_dreamfactory/lego/utils/pools" +) + +var _stacktracePool = sync.Pool{ + New: func() interface{} { + return &stacktrace{ + storage: make([]uintptr, 64), + } + }, +} + +type stacktrace struct { + pcs []uintptr // program counters; always a subslice of storage + frames *runtime.Frames + + // The size of pcs varies depending on requirements: + // it will be one if the only the first frame was requested, + // and otherwise it will reflect the depth of the call stack. + // + // storage decouples the slice we need (pcs) from the slice we pool. + // We will always allocate a reasonably large storage, but we'll use + // only as much of it as we need. + storage []uintptr +} + +// stacktraceDepth specifies how deep of a stack trace should be captured. +type stacktraceDepth int + +const callerSkipOffset = 2 +const ( + // stacktraceFirst captures only the first frame. + stacktraceFirst stacktraceDepth = iota + + // stacktraceFull captures the entire call stack, allocating more + // storage for it if needed. + stacktraceFull +) + +// captureStacktrace captures a stack trace of the specified depth, skipping +// the provided number of frames. skip=0 identifies the caller of +// captureStacktrace. +// +// The caller must call Free on the returned stacktrace after using it. +func captureStacktrace(skip int, depth stacktraceDepth) *stacktrace { + stack := _stacktracePool.Get().(*stacktrace) + + switch depth { + case stacktraceFirst: + stack.pcs = stack.storage[:1] + case stacktraceFull: + stack.pcs = stack.storage + } + + // Unlike other "skip"-based APIs, skip=0 identifies runtime.Callers + // itself. +2 to skip captureStacktrace and runtime.Callers. + numFrames := runtime.Callers( + skip+2, + stack.pcs, + ) + + // runtime.Callers truncates the recorded stacktrace if there is no + // room in the provided slice. For the full stack trace, keep expanding + // storage until there are fewer frames than there is room. + if depth == stacktraceFull { + pcs := stack.pcs + for numFrames == len(pcs) { + pcs = make([]uintptr, len(pcs)*2) + numFrames = runtime.Callers(skip+2, pcs) + } + + // Discard old storage instead of returning it to the pool. + // This will adjust the pool size over time if stack traces are + // consistently very deep. + stack.storage = pcs + stack.pcs = pcs[:numFrames] + } else { + stack.pcs = stack.pcs[:numFrames] + } + + stack.frames = runtime.CallersFrames(stack.pcs) + return stack +} + +// Free releases resources associated with this stacktrace +// and returns it back to the pool. +func (st *stacktrace) Free() { + st.frames = nil + st.pcs = nil + _stacktracePool.Put(st) +} + +// Count reports the total number of frames in this stacktrace. +// Count DOES NOT change as Next is called. +func (st *stacktrace) Count() int { + return len(st.pcs) +} + +// Next returns the next frame in the stack trace, +// and a boolean indicating whether there are more after it. +func (st *stacktrace) Next() (_ runtime.Frame, more bool) { + return st.frames.Next() +} + +func takeStacktrace(skip int) string { + stack := captureStacktrace(skip+1, stacktraceFull) + defer stack.Free() + + buffer := pools.BufferPoolGet() + defer buffer.Free() + + stackfmt := newStackFormatter(buffer) + stackfmt.FormatStack(stack) + return buffer.String() +} + +// stackFormatter formats a stack trace into a readable string representation. +type stackFormatter struct { + b *pools.Buffer + nonEmpty bool // whehther we've written at least one frame already +} + +// newStackFormatter builds a new stackFormatter. +func newStackFormatter(b *pools.Buffer) stackFormatter { + return stackFormatter{b: b} +} + +// FormatStack formats all remaining frames in the provided stacktrace -- minus +// the final runtime.main/runtime.goexit frame. +func (sf *stackFormatter) FormatStack(stack *stacktrace) { + // Note: On the last iteration, frames.Next() returns false, with a valid + // frame, but we ignore this frame. The last frame is a a runtime frame which + // adds noise, since it's only either runtime.main or runtime.goexit. + for frame, more := stack.Next(); more; frame, more = stack.Next() { + sf.FormatFrame(frame) + } +} + +// FormatFrame formats the given frame. +func (sf *stackFormatter) FormatFrame(frame runtime.Frame) { + if sf.nonEmpty { + sf.b.AppendByte('\n') + } + sf.nonEmpty = true + sf.b.AppendString(frame.Function) + sf.b.AppendByte('\n') + sf.b.AppendByte('\t') + sf.b.AppendString(frame.File) + sf.b.AppendByte(':') + sf.b.AppendInt(int64(frame.Line)) +} diff --git a/lego/sys/log/sys_test.go b/lego/sys/log/sys_test.go index f91b2ae22..a97e73db4 100644 --- a/lego/sys/log/sys_test.go +++ b/lego/sys/log/sys_test.go @@ -13,14 +13,18 @@ type TestData struct { Age int32 } -var sys log.ILog +func (this *TestData) Log() { + sys.Error("妈妈咪呀!") +} + +var sys log.ISys func TestMain(m *testing.M) { var err error if sys, err = log.NewSys( - log.SetFileName("./log.log"), - log.SetDebugMode(false), - log.SetLoglayer(2), + log.SetFileName("log.log"), + log.SetIsDebug(false), + log.SetEncoder(log.TextEncoder), ); err != nil { fmt.Println(err) return @@ -28,10 +32,12 @@ func TestMain(m *testing.M) { defer os.Exit(m.Run()) } func Test_sys(t *testing.T) { - sys.Error("测试日志接口代码!") + data := &TestData{} + data.Log() } -func Benchmark_Ability_Zap(b *testing.B) { +//性能测试 +func Benchmark_Ability(b *testing.B) { for i := 0; i < b.N; i++ { //use b.N for looping sys.Error("妈妈咪呀!") } diff --git a/lego/sys/log/turnlog.go b/lego/sys/log/turnlog.go new file mode 100644 index 000000000..c402402a9 --- /dev/null +++ b/lego/sys/log/turnlog.go @@ -0,0 +1,132 @@ +package log + +func NewTurnlog(isturnon bool, log ILogger) ILogger { + return &Turnlog{ + isturnon: isturnon, + log: log, + } +} + +type Turnlog struct { + isturnon bool + log ILogger +} + +func (this *Turnlog) SetName(name string) { + if this.log != nil { + this.log.SetName(name) + } +} + +func (this *Turnlog) Enabled(lvl Loglevel) bool { + if this.isturnon && this.log != nil { + return this.log.Enabled(lvl) + } else { + return false + } +} +func (this *Turnlog) Debug(msg string, args ...Field) { + if this.isturnon && this.log != nil { + this.log.Debug(msg, args...) + } +} +func (this *Turnlog) Info(msg string, args ...Field) { + if this.isturnon && this.log != nil { + this.log.Info(msg, args...) + } +} +func (this *Turnlog) Print(msg string, args ...Field) { + if this.isturnon && this.log != nil { + this.log.Print(msg, args...) + } +} +func (this *Turnlog) Warn(msg string, args ...Field) { + if this.isturnon && this.log != nil { + this.log.Warn(msg, args...) + } +} +func (this *Turnlog) Error(msg string, args ...Field) { + if this.log != nil { + this.log.Error(msg, args...) + } +} +func (this *Turnlog) Panic(msg string, args ...Field) { + if this.log != nil { + this.log.Panic(msg, args...) + } +} +func (this *Turnlog) Fatal(msg string, args ...Field) { + if this.log != nil { + this.log.Fatal(msg, args...) + } +} +func (this *Turnlog) Debugf(format string, args ...interface{}) { + if this.isturnon && this.log != nil { + this.log.Debugf(format, args...) + } +} +func (this *Turnlog) Infof(format string, args ...interface{}) { + if this.isturnon && this.log != nil { + this.log.Infof(format, args...) + } +} +func (this *Turnlog) Printf(format string, args ...interface{}) { + if this.isturnon && this.log != nil { + this.log.Printf(format, args...) + } +} +func (this *Turnlog) Warnf(format string, args ...interface{}) { + if this.isturnon && this.log != nil { + this.log.Warnf(format, args...) + } +} +func (this *Turnlog) Errorf(format string, args ...interface{}) { + if this.log != nil { + this.log.Errorf(format, args...) + } +} +func (this *Turnlog) Fatalf(format string, args ...interface{}) { + if this.log != nil { + this.log.Fatalf(format, args...) + } +} +func (this *Turnlog) Panicf(format string, args ...interface{}) { + if this.log != nil { + this.log.Panicf(format, args...) + } +} +func (this *Turnlog) Debugln(args ...interface{}) { + if this.isturnon && this.log != nil { + this.log.Debugln(args...) + } +} +func (this *Turnlog) Infoln(args ...interface{}) { + if this.isturnon && this.log != nil { + this.log.Infoln(args...) + } +} +func (this *Turnlog) Println(args ...interface{}) { + if this.isturnon && this.log != nil { + this.log.Println(args...) + } +} +func (this *Turnlog) Warnln(args ...interface{}) { + if this.isturnon && this.log != nil { + this.log.Warnln(args...) + } +} +func (this *Turnlog) Errorln(args ...interface{}) { + if this.log != nil { + this.log.Errorln(args...) + } +} +func (this *Turnlog) Fatalln(args ...interface{}) { + if this.log != nil { + this.log.Fatalln(args...) + } +} +func (this *Turnlog) Panicln(args ...interface{}) { + if this.log != nil { + this.log.Panicln(args...) + } +} diff --git a/lego/sys/log/write_syncer.go b/lego/sys/log/write_syncer.go new file mode 100644 index 000000000..f4e7cfd15 --- /dev/null +++ b/lego/sys/log/write_syncer.go @@ -0,0 +1,87 @@ +package log + +import ( + "io" + "sync" + + "go.uber.org/multierr" +) + +func AddWrites(w ...IWrite) IWrite { + ws := make(writeTree, 0, len(w)) + for _, v := range w { + ws = append(ws, v) + } + return ws +} + +type writeTree []IWrite + +func (mc writeTree) WriteTo(bs []byte) error { + var err error + for i := range mc { + err = multierr.Append(err, mc[i].WriteTo(bs)) + } + return err +} + +func (mc writeTree) Sync() error { + var err error + for i := range mc { + err = multierr.Append(err, mc[i].Sync()) + } + return err +} + +type IWriteSyncer interface { + io.Writer + Sync() error +} +type IWrite interface { + WriteTo(bs []byte) error + Sync() error +} + +func AddSync(w io.Writer) IWrite { + switch w := w.(type) { + case IWrite: + return w + default: + return writerWrapper{w} + } +} + +type writerWrapper struct { + io.Writer +} + +func (w writerWrapper) WriteTo(bs []byte) error { + _, err := w.Write(bs) + return err +} +func (w writerWrapper) Sync() error { + return nil +} + +func Lock(w IWriteSyncer) IWrite { + return &lockedWriteSyncer{w: w} +} + +type lockedWriteSyncer struct { + sync.Mutex + w IWriteSyncer +} + +func (s *lockedWriteSyncer) WriteTo(bs []byte) error { + s.Lock() + _, err := s.w.Write(bs) + s.Unlock() + return err +} + +func (s *lockedWriteSyncer) Sync() error { + s.Lock() + err := s.w.Sync() + s.Unlock() + return err +} diff --git a/lego/sys/log/zaplog.go b/lego/sys/log/zaplog.go deleted file mode 100644 index c967002a6..000000000 --- a/lego/sys/log/zaplog.go +++ /dev/null @@ -1,190 +0,0 @@ -package log - -import ( - "os" - "time" - - "github.com/natefinch/lumberjack" - "go.uber.org/zap" - "go.uber.org/zap/zapcore" -) - -func newSys(options Options) (sys *Logger, err error) { - createlogfile(options.FileName) - var allCore []zapcore.Core - hook := lumberjack.Logger{ - Filename: options.FileName, //日志文件路径 - MaxSize: options.LogMaxSize, //每个日志文件保存的最大尺寸 单位:M - MaxBackups: options.LogMaxBackups, //最多保留备份个数 - MaxAge: options.LogMaxAge, //文件最多保存多少天 - Compress: false, //是否压缩 disabled by default - LocalTime: true, //使用本地时间 - } - var level zapcore.Level - switch options.Loglevel { - case DebugLevel: - level = zap.DebugLevel - case InfoLevel: - level = zap.InfoLevel - case WarnLevel: - level = zap.WarnLevel - case ErrorLevel: - level = zap.ErrorLevel - case PanicLevel: - level = zap.PanicLevel - case FatalLevel: - level = zap.FatalLevel - default: - level = zap.InfoLevel - } - fileWriter := zapcore.AddSync(&hook) - consoleDebugging := zapcore.Lock(os.Stdout) - var encoderConfig zapcore.EncoderConfig - timeFormat := func(t time.Time, enc zapcore.PrimitiveArrayEncoder) { - enc.AppendString(t.Format("2006/01/02 15:04:05.000")) - } - _, err = os.OpenFile(options.FileName, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666) - if err != nil { - return - } - if options.Debugmode { - //重新生成文件 - encoderConfig = zap.NewDevelopmentEncoderConfig() - encoderConfig.EncodeTime = timeFormat - allCore = append(allCore, zapcore.NewCore(zapcore.NewConsoleEncoder(encoderConfig), consoleDebugging, level)) - } else { - encoderConfig = zap.NewProductionEncoderConfig() - encoderConfig.EncodeTime = timeFormat - } - if options.Encoder == Console { - allCore = append(allCore, zapcore.NewCore(zapcore.NewConsoleEncoder(encoderConfig), fileWriter, level)) - } else { - allCore = append(allCore, zapcore.NewCore(zapcore.NewJSONEncoder(encoderConfig), fileWriter, level)) - } - core := zapcore.NewTee(allCore...) - tlog := zap.New(core).WithOptions(zap.AddCaller(), zap.AddCallerSkip(options.Loglayer)) - sys = &Logger{ - core: core, - tlog: tlog, - log: tlog.Sugar(), - } - return -} - -type Logger struct { - core zapcore.Core - tlog *zap.Logger - log *zap.SugaredLogger -} - -func FieldTozapField(fields ...Field) (fds []zap.Field) { - fds = make([]zap.Field, 0) - for _, v := range fields { - field := zap.Field{Key: v.Key} - - switch v.Value.(type) { - case []byte: - field.Type = zapcore.BinaryType - field.Interface = v.Value - case bool: - field.Type = zapcore.BoolType - if v.Value.(bool) { - field.Integer = 1 - } else { - field.Integer = 0 - } - case byte: - field.Type = zapcore.Uint8Type - field.Integer = int64(v.Value.(byte)) - case time.Duration: - field.Type = zapcore.DurationType - field.Integer = int64(v.Value.(time.Duration)) - case float64: - field.Type = zapcore.Float64Type - field.Integer = v.Value.(int64) - case float32: - field.Type = zapcore.Float32Type - field.Integer = v.Value.(int64) - case int64: - field.Type = zapcore.Int64Type - field.Integer = v.Value.(int64) - case uint64: - field.Type = zapcore.Uint64Type - field.Integer = int64(v.Value.(uint64)) - case int32: - field.Type = zapcore.Int32Type - field.Integer = int64(v.Value.(int32)) - case uint32: - field.Type = zapcore.Uint64Type - field.Integer = int64(v.Value.(uint32)) - case int16: - field.Type = zapcore.Int16Type - field.Integer = int64(v.Value.(int16)) - case uint16: - field.Type = zapcore.Uint64Type - field.Integer = int64(v.Value.(uint16)) - case int8: - field.Type = zapcore.Int8Type - field.Integer = int64(v.Value.(int8)) - case string: - field.Type = zapcore.StringType - field.String = v.Value.(string) - case LogStrut: - field.Type = zapcore.StringType - field.String = v.Value.(LogStrut).ToString() - default: - field.Type = zapcore.UnknownType - field.Interface = v.Value - } - fds = append(fds, field) - } - return -} - -func (this *Logger) Clone(option ...Option) (sys ILog) { - options := newOptionsByOption(option...) - tlog := zap.New(this.core).WithOptions(zap.AddCaller(), zap.AddCallerSkip(options.Loglayer)) - sys = &Logger{ - core: this.core, - tlog: tlog, - log: tlog.Sugar(), - } - return -} - -func (this *Logger) Debug(msg string, fields ...Field) { - this.tlog.Debug(msg, FieldTozapField(fields...)...) -} -func (this *Logger) Info(msg string, fields ...Field) { - this.tlog.Info(msg, FieldTozapField(fields...)...) -} -func (this *Logger) Warn(msg string, fields ...Field) { - this.tlog.Warn(msg, FieldTozapField(fields...)...) -} -func (this *Logger) Error(msg string, fields ...Field) { - this.tlog.Error(msg, FieldTozapField(fields...)...) -} -func (this *Logger) Panic(msg string, fields ...Field) { - this.tlog.Panic(msg, FieldTozapField(fields...)...) -} -func (this *Logger) Fatal(msg string, fields ...Field) { - this.tlog.Fatal(msg, FieldTozapField(fields...)...) -} -func (this *Logger) Debugf(format string, a ...interface{}) { - this.log.Debugf(format, a...) -} -func (this *Logger) Infof(format string, a ...interface{}) { - this.log.Infof(format, a...) -} -func (this *Logger) Warnf(format string, a ...interface{}) { - this.log.Warnf(format, a...) -} -func (this *Logger) Errorf(format string, a ...interface{}) { - this.log.Errorf(format, a...) -} -func (this *Logger) Panicf(format string, a ...interface{}) { - this.log.Panicf(format, a...) -} -func (this *Logger) Fatalf(format string, a ...interface{}) { - this.log.Fatalf(format, a...) -} diff --git a/lego/sys/nacos/core.go b/lego/sys/nacos/core.go deleted file mode 100644 index bb5879888..000000000 --- a/lego/sys/nacos/core.go +++ /dev/null @@ -1,98 +0,0 @@ -package nacos - -import ( - "github.com/nacos-group/nacos-sdk-go/model" - "github.com/nacos-group/nacos-sdk-go/vo" -) - -type ( - ISys interface { - Naming_RegisterInstance(service vo.RegisterInstanceParam) (success bool, err error) - Naming_DeregisterInstance(service vo.DeregisterInstanceParam) (success bool, err error) - Naming_GetService(param vo.GetServiceParam) (services model.Service, err error) - Naming_SelectAllInstances(param vo.SelectAllInstancesParam) (instances []model.Instance, err error) - Naming_SelectInstances(param vo.SelectInstancesParam) (instances []model.Instance, err error) - Naming_SelectOneHealthyInstance(param vo.SelectOneHealthInstanceParam) (instance *model.Instance, err error) - Naming_Subscribe(param *vo.SubscribeParam) (err error) - Naming_Unsubscribe(param *vo.SubscribeParam) (err error) - Naming_GetAllServicesInfo(param vo.GetAllServiceInfoParam) (serviceInfos model.ServiceList, err error) - Config_GetConfig(param vo.ConfigParam) (string, error) - Config_PublishConfig(param vo.ConfigParam) (bool, error) - Config_DeleteConfig(param vo.ConfigParam) (bool, error) - Config_ListenConfig(params vo.ConfigParam) (err error) - Config_CancelListenConfig(params vo.ConfigParam) (err error) - Config_SearchConfig(param vo.SearchConfigParam) (*model.ConfigPage, error) - Config_PublishAggr(param vo.ConfigParam) (published bool, err error) - } -) - -var ( - defsys ISys -) - -func OnInit(config map[string]interface{}, option ...Option) (err error) { - defsys, err = newSys(newOptions(config, option...)) - return -} - -func NewSys(option ...Option) (sys ISys, err error) { - sys, err = newSys(newOptionsByOption(option...)) - return -} - -///注册服务 -func Naming_RegisterInstance(service vo.RegisterInstanceParam) (success bool, err error) { - return defsys.Naming_RegisterInstance(service) -} - -///注销服务 -func Naming_DeregisterInstance(service vo.DeregisterInstanceParam) (success bool, err error) { - return defsys.Naming_DeregisterInstance(service) -} - -///获取服务 -func Naming_GetService(param vo.GetServiceParam) (services model.Service, err error) { - return defsys.Naming_GetService(param) -} - -///获取全部服务实例 -func Naming_SelectAllInstances(param vo.SelectAllInstancesParam) (instances []model.Instance, err error) { - return defsys.Naming_SelectAllInstances(param) -} -func Naming_SelectInstances(param vo.SelectInstancesParam) (instances []model.Instance, err error) { - return defsys.Naming_SelectInstances(param) -} -func Naming_SelectOneHealthyInstance(param vo.SelectOneHealthInstanceParam) (instance *model.Instance, err error) { - return defsys.Naming_SelectOneHealthyInstance(param) -} -func Naming_Subscribe(param *vo.SubscribeParam) (err error) { - return defsys.Naming_Subscribe(param) -} -func Naming_Unsubscribe(param *vo.SubscribeParam) (err error) { - return defsys.Naming_Unsubscribe(param) -} -func Naming_GetAllServicesInfo(param vo.GetAllServiceInfoParam) (serviceInfos model.ServiceList, err error) { - return defsys.Naming_GetAllServicesInfo(param) -} - -func Config_GetConfig(param vo.ConfigParam) (string, error) { - return defsys.Config_GetConfig(param) -} -func Config_PublishConfig(param vo.ConfigParam) (bool, error) { - return defsys.Config_PublishConfig(param) -} -func Config_DeleteConfig(param vo.ConfigParam) (bool, error) { - return defsys.Config_DeleteConfig(param) -} -func Config_ListenConfig(params vo.ConfigParam) (err error) { - return defsys.Config_ListenConfig(params) -} -func Config_CancelListenConfig(params vo.ConfigParam) (err error) { - return defsys.Config_ListenConfig(params) -} -func Config_SearchConfig(param vo.SearchConfigParam) (*model.ConfigPage, error) { - return defsys.Config_SearchConfig(param) -} -func Config_PublishAggr(param vo.ConfigParam) (published bool, err error) { - return defsys.Config_PublishAggr(param) -} diff --git a/lego/sys/nacos/nacos.go b/lego/sys/nacos/nacos.go deleted file mode 100644 index 5b4aba79b..000000000 --- a/lego/sys/nacos/nacos.go +++ /dev/null @@ -1,143 +0,0 @@ -package nacos - -import ( - "github.com/nacos-group/nacos-sdk-go/clients" - "github.com/nacos-group/nacos-sdk-go/clients/config_client" - "github.com/nacos-group/nacos-sdk-go/clients/naming_client" - "github.com/nacos-group/nacos-sdk-go/common/constant" - "github.com/nacos-group/nacos-sdk-go/model" - "github.com/nacos-group/nacos-sdk-go/vo" -) - -func newSys(options Options) (sys *Nacos, err error) { - sys = &Nacos{ - options: options, - } - // 创建clientConfig - clientConfig := constant.ClientConfig{ - NamespaceId: options.NamespaceId, - TimeoutMs: options.TimeoutMs, - NotLoadCacheAtStart: true, - Username: options.Username, - Password: options.Password, - LogDir: "./nacos/log", - CacheDir: "./nacos/cache", - RotateTime: "1h", - MaxAge: 3, - LogLevel: "debug", - } - // 至少一个ServerConfig - serverConfigs := []constant.ServerConfig{ - { - IpAddr: options.NacosAddr, - ContextPath: "/nacos", - Port: options.Port, - Scheme: "http", - }, - } - if sys.options.NacosClientType == NamingClient || sys.options.NacosClientType == All { - // 创建服务发现客户端的另一种方式 (推荐) - sys.namingClient, err = clients.NewNamingClient( - vo.NacosClientParam{ - ClientConfig: &clientConfig, - ServerConfigs: serverConfigs, - }, - ) - } - if sys.options.NacosClientType == ConfigClient || sys.options.NacosClientType == All { - // 创建服务发现客户端的另一种方式 (推荐) - sys.configClient, err = clients.NewConfigClient( - vo.NacosClientParam{ - ClientConfig: &clientConfig, - ServerConfigs: serverConfigs, - }, - ) - } - return -} - -type Nacos struct { - options Options - namingClient naming_client.INamingClient - configClient config_client.IConfigClient -} - -///注册服务 -func (this *Nacos) Naming_RegisterInstance(service vo.RegisterInstanceParam) (success bool, err error) { - success, err = this.namingClient.RegisterInstance(service) - return -} - -///注销服务 -func (this *Nacos) Naming_DeregisterInstance(service vo.DeregisterInstanceParam) (success bool, err error) { - success, err = this.namingClient.DeregisterInstance(service) - return -} - -///获取服务 -func (this *Nacos) Naming_GetService(param vo.GetServiceParam) (services model.Service, err error) { - services, err = this.namingClient.GetService(param) - return -} - -/// SelectAllInstance可以返回全部实例列表,包括healthy=false,enable=false,weight<=0 -func (this *Nacos) Naming_SelectAllInstances(param vo.SelectAllInstancesParam) (instances []model.Instance, err error) { - instances, err = this.namingClient.SelectAllInstances(param) - return -} - -///选中实例列表 -func (this *Nacos) Naming_SelectInstances(param vo.SelectInstancesParam) (instances []model.Instance, err error) { - instances, err = this.namingClient.SelectInstances(param) - return -} - -/// SelectOneHealthyInstance将会按加权随机轮询的负载均衡策略返回一个健康的实例 实例必须满足的条件:health=true,enable=true and weight>0 -func (this *Nacos) Naming_SelectOneHealthyInstance(param vo.SelectOneHealthInstanceParam) (instance *model.Instance, err error) { - instance, err = this.namingClient.SelectOneHealthyInstance(param) - return -} - -/// Subscribe key=serviceName+groupName+cluster 注意:我们可以在相同的key添加多个SubscribeCallback. -func (this *Nacos) Naming_Subscribe(param *vo.SubscribeParam) (err error) { - err = this.namingClient.Subscribe(param) - return -} - -func (this *Nacos) Naming_Unsubscribe(param *vo.SubscribeParam) (err error) { - err = this.namingClient.Unsubscribe(param) - return -} - -func (this *Nacos) Naming_GetAllServicesInfo(param vo.GetAllServiceInfoParam) (serviceInfos model.ServiceList, err error) { - serviceInfos, err = this.namingClient.GetAllServicesInfo(param) - return -} - -func (this *Nacos) Config_GetConfig(param vo.ConfigParam) (string, error) { - return this.configClient.GetConfig(param) -} - -func (this *Nacos) Config_PublishConfig(param vo.ConfigParam) (bool, error) { - return this.configClient.PublishConfig(param) -} - -func (this *Nacos) Config_DeleteConfig(param vo.ConfigParam) (bool, error) { - return this.configClient.PublishConfig(param) -} - -func (this *Nacos) Config_ListenConfig(params vo.ConfigParam) (err error) { - return this.configClient.ListenConfig(params) -} - -func (this *Nacos) Config_CancelListenConfig(params vo.ConfigParam) (err error) { - return this.configClient.CancelListenConfig(params) -} - -func (this *Nacos) Config_SearchConfig(param vo.SearchConfigParam) (*model.ConfigPage, error) { - return this.configClient.SearchConfig(param) -} - -func (this *Nacos) Config_PublishAggr(param vo.ConfigParam) (published bool, err error) { - return this.configClient.PublishAggr(param) -} diff --git a/lego/sys/nacos/options.go b/lego/sys/nacos/options.go deleted file mode 100644 index 54343cff9..000000000 --- a/lego/sys/nacos/options.go +++ /dev/null @@ -1,86 +0,0 @@ -package nacos - -import ( - "go_dreamfactory/lego/utils/mapstructure" -) - -type NacosClientType uint8 - -const ( - NamingClient NacosClientType = iota - ConfigClient - All -) - -type Option func(*Options) -type Options struct { - NacosClientType NacosClientType - NamespaceId string - NacosAddr string - Port uint64 - Username string - Password string - TimeoutMs uint64 -} - -func SetNacosClientType(v NacosClientType) Option { - return func(o *Options) { - o.NacosClientType = v - } -} -func SetNamespaceId(v string) Option { - return func(o *Options) { - o.NamespaceId = v - } -} -func SetNacosAddr(v string) Option { - return func(o *Options) { - o.NacosAddr = v - } -} - -func SetPort(v uint64) Option { - return func(o *Options) { - o.Port = v - } -} - -func SetUsername(v string) Option { - return func(o *Options) { - o.Username = v - } -} -func SetPassword(v string) Option { - return func(o *Options) { - o.Password = v - } -} - -func SetTimeoutMs(v uint64) Option { - return func(o *Options) { - o.TimeoutMs = v - } -} - -func newOptions(config map[string]interface{}, opts ...Option) Options { - options := Options{ - TimeoutMs: 5000, - } - if config != nil { - mapstructure.Decode(config, &options) - } - for _, o := range opts { - o(&options) - } - return options -} - -func newOptionsByOption(opts ...Option) Options { - options := Options{ - TimeoutMs: 5000, - } - for _, o := range opts { - o(&options) - } - return options -} diff --git a/lego/sys/nacos/sys_test.go b/lego/sys/nacos/sys_test.go deleted file mode 100644 index 2a9dcfebf..000000000 --- a/lego/sys/nacos/sys_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package nacos_test - -import ( - "fmt" - "testing" - - "go_dreamfactory/lego/sys/nacos" - - "github.com/nacos-group/nacos-sdk-go/vo" -) - -func Test_SysInit(t *testing.T) { - sys, err := nacos.NewSys( - nacos.SetNacosAddr("127.0.0.1"), - nacos.SetPort(8848), - nacos.SetNamespaceId("17d02ef9-afaa-4878-ad6c-9fd697f3b628"), - ) - if err != nil { - fmt.Printf("启动系统错误err:%v", err) - } - succ, err := sys.Naming_RegisterInstance(vo.RegisterInstanceParam{ - Ip: "127.0.0.1", - Port: 8848, - Weight: 0.69, - GroupName: "demo", - ClusterName: "demo", - ServiceName: "demo1", - Metadata: map[string]string{ - "tag": "demo", - }, - }) - fmt.Printf("sys RegisterInstance succ:%v err:%v", succ, err) - // time.Sleep(time.Second * 3) - serviceInfos, err := sys.Naming_GetAllServicesInfo(vo.GetAllServiceInfoParam{ - NameSpace: "17d02ef9-afaa-4878-ad6c-9fd697f3b628", - GroupName: "demo", - }) - - fmt.Printf("sys GetAllServicesInfo serviceInfos:%+v err:%v", serviceInfos, err) - - // succ, err = sys.DeregisterInstance() - // fmt.Printf("sys DeregisterInstance succ:%v err:%v", succ, err) -} diff --git a/lego/sys/redis/redis.go b/lego/sys/redis/redis.go index fab5d5f8c..261b66321 100644 --- a/lego/sys/redis/redis.go +++ b/lego/sys/redis/redis.go @@ -5,9 +5,9 @@ import ( "fmt" "time" - "go_dreamfactory/lego/sys/codec" "go_dreamfactory/lego/sys/redis/cluster" "go_dreamfactory/lego/sys/redis/single" + "go_dreamfactory/lego/utils/codec/json" "github.com/go-redis/redis/v8" ) @@ -378,41 +378,41 @@ func (this *Redis) Marshal(v interface{}) ([]byte, error) { if this.options.Codec != nil { return this.options.Codec.Marshal(v) } else { - return codec.MarshalJson(v) + return json.Marshal(v) } } func (this *Redis) Unmarshal(data []byte, v interface{}) error { if this.options.Codec != nil { return this.options.Codec.Unmarshal(data, v) } else { - return codec.UnmarshalJson(data, v) + return json.Unmarshal(data, v) } } func (this *Redis) MarshalMap(val interface{}) (ret map[string]string, err error) { if this.options.Codec != nil { return this.options.Codec.MarshalMap(val) } else { - return codec.MarshalMapJson(val) + return json.MarshalMap(val) } } func (this *Redis) UnmarshalMap(data map[string]string, val interface{}) (err error) { if this.options.Codec != nil { return this.options.Codec.UnmarshalMap(data, val) } else { - return codec.UnmarshalMapJson(data, val) + return json.UnmarshalMap(data, val) } } func (this *Redis) MarshalSlice(val interface{}) (ret []string, err error) { if this.options.Codec != nil { return this.options.Codec.MarshalSlice(val) } else { - return codec.MarshalSliceJson(val) + return json.MarshalSlice(val) } } func (this *Redis) UnmarshalSlice(data []string, val interface{}) (err error) { if this.options.Codec != nil { return this.options.Codec.UnmarshalSlice(data, val) } else { - return codec.UnmarshalSliceJson(data, val) + return json.UnmarshalSlice(data, val) } } diff --git a/lego/sys/registry/consul.go b/lego/sys/registry/consul.go deleted file mode 100644 index 9b0dca305..000000000 --- a/lego/sys/registry/consul.go +++ /dev/null @@ -1,391 +0,0 @@ -package registry - -import ( - "fmt" - "strconv" - "sync" - "time" - - hash "github.com/mitchellh/hashstructure" - - "go_dreamfactory/lego/core" - "go_dreamfactory/lego/sys/log" - - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/api/watch" -) - -func newConsul(options Options) (sys *Consul_Registry, err error) { - sys = &Consul_Registry{ - options: options, - } - config := api.DefaultConfig() - if len(options.Consul_Addr) > 0 { - config.Address = options.Consul_Addr - } - if sys.client, err = api.NewClient(config); err != nil { - return nil, err - } - if sys.snodeWP, err = watch.Parse(map[string]interface{}{"type": "services"}); err != nil { - return nil, err - } - sys.snodeWP.Handler = sys.shandler - sys.options.Consul_Addr = config.Address - sys.shash = make(map[string]uint64) - sys.services = make(map[string]*ServiceNode) - sys.rpcsubs = make(map[core.Rpc_Key][]*ServiceNode) - sys.watchers = make(map[string]*watch.Plan) - sys.closeSig = make(chan bool) - sys.isstart = false - return -} - -type Consul_Registry struct { - options Options - client *api.Client - snodeWP *watch.Plan - isstart bool - closeSig chan bool - shash map[string]uint64 - slock sync.RWMutex - services map[string]*ServiceNode - rlock sync.RWMutex - rpcsubs map[core.Rpc_Key][]*ServiceNode - watchers map[string]*watch.Plan -} - -func (this *Consul_Registry) Start() (err error) { - if err = this.getServices(); err != nil { - return - } - if err = this.registerSNode(&ServiceNode{ - Tag: this.options.Service.GetTag(), - Id: this.options.Service.GetId(), - IP: this.options.Service.GetIp(), - Port: this.options.Service.GetPort(), - Type: this.options.Service.GetType(), - Category: this.options.Service.GetCategory(), - Version: this.options.Service.GetVersion(), - RpcId: this.options.Service.GetRpcId(), - PreWeight: this.options.Service.GetPreWeight(), - }); err != nil { - return - } - go this.snodeWP.Run(this.options.Consul_Addr) - go this.run() - this.isstart = true - return -} - -func (this *Consul_Registry) Stop() (err error) { - this.closeSig <- true - this.isstart = false - this.snodeWP.Stop() - this.deregisterSNode() - return -} -func (this *Consul_Registry) PushServiceInfo() (err error) { - if this.isstart { - err = this.registerSNode(&ServiceNode{ - Tag: this.options.Service.GetTag(), - Id: this.options.Service.GetId(), - IP: this.options.Service.GetIp(), - Port: this.options.Service.GetPort(), - Type: this.options.Service.GetType(), - Category: this.options.Service.GetCategory(), - Version: this.options.Service.GetVersion(), - RpcId: this.options.Service.GetRpcId(), - PreWeight: this.options.Service.GetPreWeight(), - }) - } - return -} -func (this *Consul_Registry) GetServiceById(sId string) (n *ServiceNode, err error) { - this.slock.RLock() - n, ok := this.services[sId] - this.slock.RUnlock() - if !ok { - return nil, fmt.Errorf("No Found %s", sId) - } - return -} -func (this *Consul_Registry) GetServiceByType(sType string) (n []*ServiceNode) { - this.slock.RLock() - defer this.slock.RUnlock() - n = make([]*ServiceNode, 0) - for _, v := range this.services { - if v.Type == sType { - n = append(n, v) - } - } - return -} -func (this *Consul_Registry) GetAllServices() (n []*ServiceNode) { - this.slock.RLock() - defer this.slock.RUnlock() - n = make([]*ServiceNode, 0) - for _, v := range this.services { - n = append(n, v) - } - return -} -func (this *Consul_Registry) GetServiceByCategory(category core.S_Category) (n []*ServiceNode) { - this.slock.RLock() - defer this.slock.RUnlock() - n = make([]*ServiceNode, 0) - for _, v := range this.services { - if v.Category == category { - n = append(n, v) - } - } - return -} -func (this *Consul_Registry) GetRpcSubById(rId core.Rpc_Key) (n []*ServiceNode) { - n = make([]*ServiceNode, 0) - this.rlock.RLock() - d, ok := this.rpcsubs[rId] - this.rlock.RUnlock() - if ok { - n = d - } - return -} - -//内部函数------------------------------------------------------------------------------------------------------------------------- -func (this *Consul_Registry) run() { - t := time.NewTicker(time.Duration(this.options.Consul_RegisterInterval) * time.Second) -locp: - for { - select { - case <-t.C: - err := this.PushServiceInfo() - if err != nil { - log.Warnf("service run Server.Register error: ", err) - } - case <-this.closeSig: - break locp - } - } - log.Infof("Sys Registry is succ exit") -} - -func (this *Consul_Registry) getServices() (err error) { - services, err := this.client.Agent().Services() - if err == nil { - for _, v := range services { - if v.Tags[0] == this.options.Service.GetTag() { //自能读取相同标签的服务 - this.addandupdataServiceNode(v) - } - } - } - return err -} -func (this *Consul_Registry) registerSNode(snode *ServiceNode) (err error) { - h, err := hash.Hash(snode, nil) - if err != nil { - return err - } - - if v, ok := this.shash[snode.Id]; ok && v != 0 && v == h { - if err := this.client.Agent().PassTTL("service:"+snode.Id, ""); err == nil { - return nil - } - } - deregTTL := this.getDeregisterTTL(time.Second * time.Duration(this.options.Consul_RegisterTTL)) - check := &api.AgentServiceCheck{ - TTL: fmt.Sprintf("%v", time.Second*time.Duration(this.options.Consul_RegisterTTL)), - DeregisterCriticalServiceAfter: fmt.Sprintf("%v", deregTTL), - } - asr := &api.AgentServiceRegistration{ - ID: snode.Id, - Name: snode.Type, - Tags: []string{this.options.Service.GetTag()}, - Check: check, - Meta: map[string]string{ - "tag": snode.Tag, - "ip": snode.IP, - "port": fmt.Sprintf("%d", snode.Port), - "category": string(snode.Category), - "version": snode.Version, - "rpcid": snode.RpcId, - "preweight": fmt.Sprintf("%f", snode.PreWeight), - }, - } - if err := this.client.Agent().ServiceRegister(asr); err != nil { - return err - } - return this.client.Agent().PassTTL("service:"+snode.Id, "") -} -func (this *Consul_Registry) deregisterSNode() (err error) { - return this.client.Agent().ServiceDeregister(this.options.Service.GetId()) -} - -func (this *Consul_Registry) addandupdataServiceNode(as *api.AgentService) (sn *ServiceNode, err error) { - - tag := as.Meta["tag"] - ip := as.Meta["ip"] - port, err := strconv.ParseInt(as.Meta["port"], 10, 64) - if err != nil { - log.Errorf("port 读取服务节点异常:%s err:%v", as.Meta["port"], err) - return - } - category := as.Meta["category"] - version := as.Meta["version"] - rpcid := as.Meta["rpcid"] - preweight, err := strconv.ParseFloat(as.Meta["preweight"], 64) - if err != nil { - log.Errorf("registry 读取服务节点异常:%s err:%v", as.Meta["preweight"], err) - return - } - - snode := &ServiceNode{ - Tag: tag, - Type: as.Service, - Category: core.S_Category(category), - Id: as.ID, - IP: ip, - Port: int(port), - Version: version, - RpcId: rpcid, - PreWeight: preweight, - } - if h, err := hash.Hash(snode, nil); err == nil { - _, ok := this.services[snode.Id] - if !ok { - log.Infof("发现新的服务【%s:%s】", snode.Id, snode.Version) - this.rlock.Lock() - this.services[snode.Id] = snode - this.shash[snode.Id] = h - this.rlock.Unlock() - if this.options.Listener != nil { //异步通知 - go this.options.Listener.FindServiceHandlefunc(*snode) - } - } else { - this.rlock.RLock() - v, ok := this.shash[snode.Id] - this.rlock.RUnlock() - if !ok || v != h { //校验不一致 - // log.Debugf("更新服务【%s】", snode.Id) - this.rlock.Lock() - this.services[snode.Id] = snode - this.shash[snode.Id] = h - this.rlock.Unlock() - if this.options.Listener != nil { //异步通知 - go this.options.Listener.UpDataServiceHandlefunc(*snode) - } - } - } - } else { - log.Errorf("registry 校验服务 hash 值异常:%s", err.Error()) - } - return -} - -func (this *Consul_Registry) removeServiceNode(sId string) { - this.rlock.RLock() - _, ok := this.services[sId] - this.rlock.RUnlock() - if !ok { - return - } - log.Infof("丢失服务【%s】", sId) - this.rlock.Lock() - delete(this.shash, sId) - delete(this.services, sId) - this.rlock.Unlock() - if this.options.Listener != nil { //异步通知 - go this.options.Listener.LoseServiceHandlefunc(sId) - } -} - -func (this *Consul_Registry) shandler(idx uint64, data interface{}) { - services, ok := data.(map[string][]string) - if !ok { - return - } - for k, v := range services { - if len(v) > 0 { - if v[0] == this.options.Service.GetTag() { - _, ok := this.watchers[k] - if ok { - continue - } - wp, err := watch.Parse(map[string]interface{}{ - "type": "service", - "service": k, - }) - if err == nil { - wp.Handler = this.snodehandler - go wp.Run(this.options.Consul_Addr) - this.watchers[k] = wp - } - } - } - } - temp := make(map[string]*ServiceNode) - this.rlock.RLock() - for k, v := range this.services { - temp[k] = v - } - this.rlock.RUnlock() - for k, v := range this.watchers { - if _, ok := services[k]; !ok { //不存在了 - v.Stop() - delete(this.watchers, k) - for k1, v1 := range temp { - if v1.Type == k { - this.removeServiceNode(k1) - } - } - } - } -} - -func (this *Consul_Registry) snodehandler(idx uint64, data interface{}) { - entries, ok := data.([]*api.ServiceEntry) - if !ok { - return - } - stype := "" - serviceMap := map[string]struct{}{} - for _, v := range entries { - isdele := false - for _, check := range v.Checks { - if check.Status == "critical" { - this.removeServiceNode(v.Service.ID) - isdele = true - break - } - } - if !isdele { - this.addandupdataServiceNode(v.Service) - stype = v.Service.Service - serviceMap[v.Service.ID] = struct{}{} - } - } - - temp := make(map[string]*ServiceNode) - this.rlock.RLock() - for k, v := range this.services { - temp[k] = v - } - this.rlock.RUnlock() - for _, v := range temp { - if v.Type == stype { - if _, ok := serviceMap[v.Id]; !ok { - this.removeServiceNode(v.Id) - } - } - } -} - -func (this *Consul_Registry) getDeregisterTTL(t time.Duration) time.Duration { - // splay slightly for the watcher? - splay := time.Second * 5 - deregTTL := t + splay - // consul has a minimum timeout on deregistration of 1 minute. - if t < time.Minute { - deregTTL = time.Minute + splay - } - return deregTTL -} diff --git a/lego/sys/registry/core.go b/lego/sys/registry/core.go deleted file mode 100644 index d5b2915af..000000000 --- a/lego/sys/registry/core.go +++ /dev/null @@ -1,81 +0,0 @@ -package registry - -import "go_dreamfactory/lego/core" - -type ( - IListener interface { - FindServiceHandlefunc(snode ServiceNode) - UpDataServiceHandlefunc(snode ServiceNode) - LoseServiceHandlefunc(sId string) - } - ServiceNode struct { - Tag string `json:"Tag"` //服务集群标签 - Type string `json:"Type"` //服务类型 - Category core.S_Category `json:"Category"` //服务列别 - Id string `json:"Id"` //服务Id - Version string `json:"Version"` //服务版本 - IP string `json:"Ip"` //服务Ip - Port int `json:"Port"` //端口 - RpcId string `json:"RpcId"` //服务通信Id - PreWeight float64 `json:"PreWeight"` //服务负载权重 - } - - ISys interface { - Start() error - Stop() error - PushServiceInfo() (err error) - GetServiceById(sId string) (n *ServiceNode, err error) - GetServiceByType(sType string) (n []*ServiceNode) - GetAllServices() (n []*ServiceNode) - GetServiceByCategory(category core.S_Category) (n []*ServiceNode) - GetRpcSubById(rId core.Rpc_Key) (n []*ServiceNode) - } -) - -var ( - defsys ISys -) - -func OnInit(config map[string]interface{}, option ...Option) (err error) { - defsys, err = newSys(newOptions(config, option...)) - return -} - -func NewSys(option ...Option) (sys ISys, err error) { - sys, err = newSys(newOptionsByOption(option...)) - return -} - -func Start() error { - return defsys.Start() -} -func Stop() error { - return defsys.Stop() -} - -func PushServiceInfo() (err error) { - return defsys.PushServiceInfo() -} - -func GetServiceById(sId string) (n *ServiceNode, err error) { - return defsys.GetServiceById(sId) -} -func GetServiceByType(sType string) (n []*ServiceNode) { - return defsys.GetServiceByType(sType) -} - -func GetAllServices() (n []*ServiceNode) { - return defsys.GetAllServices() -} - -func GetServiceByCategory(category core.S_Category) (n []*ServiceNode) { - return defsys.GetServiceByCategory(category) -} - -func GetRpcSubById(rId core.Rpc_Key) (n []*ServiceNode) { - return defsys.GetRpcSubById(rId) -} - -func SubscribeRpc(rpc core.Rpc_Key) { - -} diff --git a/lego/sys/registry/nacos.go b/lego/sys/registry/nacos.go deleted file mode 100644 index b453737d5..000000000 --- a/lego/sys/registry/nacos.go +++ /dev/null @@ -1,413 +0,0 @@ -package registry - -import ( - "context" - "fmt" - "sync" - "time" - - "go_dreamfactory/lego/core" - "go_dreamfactory/lego/sys/log" - - hash "github.com/mitchellh/hashstructure" - "github.com/nacos-group/nacos-sdk-go/clients" - "github.com/nacos-group/nacos-sdk-go/clients/naming_client" - "github.com/nacos-group/nacos-sdk-go/common/constant" - "github.com/nacos-group/nacos-sdk-go/model" - "github.com/nacos-group/nacos-sdk-go/vo" -) - -func newNacos(options Options) (sys *Nacos_Registry, err error) { - ctx, cancel := context.WithCancel(context.TODO()) - sys = &Nacos_Registry{ - options: options, - ctx: ctx, - cancel: cancel, - shash: make(map[string]uint64), - services: make(map[string]*ServiceNode), - subscribe: make(map[string]*vo.SubscribeParam), - rpcsubs: make(map[core.Rpc_Key][]*ServiceNode), - } - // 创建clientConfig - clientConfig := constant.ClientConfig{ - NamespaceId: options.Nacos_NamespaceId, - TimeoutMs: options.Nacos_TimeoutMs, - BeatInterval: options.Nacos_BeatInterval, - Username: options.Nacos_UserName, - Password: options.Nacos_Password, - NotLoadCacheAtStart: true, - UpdateCacheWhenEmpty: true, - LogDir: "nacos/log", - CacheDir: "nacos/cache", - RotateTime: "1h", - MaxAge: 3, - LogLevel: "error", - } - // 至少一个ServerConfig - serverConfigs := []constant.ServerConfig{ - { - IpAddr: options.Nacos_NacosAddr, - ContextPath: "/nacos", - Port: options.Nacos_Port, - Scheme: "http", - }, - } - - // 创建服务发现客户端的另一种方式 (推荐) - sys.client, err = clients.NewNamingClient( - vo.NacosClientParam{ - ClientConfig: &clientConfig, - ServerConfigs: serverConfigs, - }, - ) - return -} - -type Nacos_Registry struct { - options Options - client naming_client.INamingClient - isstart bool - ctx context.Context - cancel context.CancelFunc - slock sync.RWMutex - shash map[string]uint64 - subscribe map[string]*vo.SubscribeParam - services map[string]*ServiceNode - rlock sync.RWMutex - rpcsubs map[core.Rpc_Key][]*ServiceNode -} - -func (this *Nacos_Registry) Start() (err error) { - if err = this.getServices(); err != nil && err.Error() != "instance list is empty!" { - return - } - if err = this.registerSNode(&ServiceNode{ - Tag: this.options.Service.GetTag(), - Id: this.options.Service.GetId(), - IP: this.options.Service.GetIp(), - Port: this.options.Service.GetPort(), - Type: this.options.Service.GetType(), - Category: this.options.Service.GetCategory(), - Version: this.options.Service.GetVersion(), - RpcId: this.options.Service.GetRpcId(), - PreWeight: this.options.Service.GetPreWeight(), - }); err != nil { - return - } - ctx1, _ := context.WithCancel(this.ctx) - go this.run(ctx1) - ctx2, _ := context.WithCancel(this.ctx) - go this.listener(ctx2) - this.isstart = true - return -} - -func (this *Nacos_Registry) Stop() (err error) { - this.cancel() - this.isstart = false - return -} - -func (this *Nacos_Registry) PushServiceInfo() (err error) { - if this.isstart { - err = this.registerSNode(&ServiceNode{ - Tag: this.options.Service.GetTag(), - Id: this.options.Service.GetId(), - IP: this.options.Service.GetIp(), - Port: this.options.Service.GetPort(), - Type: this.options.Service.GetType(), - Category: this.options.Service.GetCategory(), - Version: this.options.Service.GetVersion(), - RpcId: this.options.Service.GetRpcId(), - PreWeight: this.options.Service.GetPreWeight(), - }) - } - return -} -func (this *Nacos_Registry) GetServiceById(sId string) (n *ServiceNode, err error) { - this.slock.RLock() - n, ok := this.services[sId] - this.slock.RUnlock() - if !ok { - return nil, fmt.Errorf("No Found %s", sId) - } - return -} -func (this *Nacos_Registry) GetServiceByType(sType string) (n []*ServiceNode) { - this.slock.RLock() - defer this.slock.RUnlock() - n = make([]*ServiceNode, 0) - for _, v := range this.services { - if v.Type == sType { - n = append(n, v) - } - } - return -} -func (this *Nacos_Registry) GetAllServices() (n []*ServiceNode) { - this.slock.RLock() - defer this.slock.RUnlock() - n = make([]*ServiceNode, 0) - for _, v := range this.services { - n = append(n, v) - } - return -} -func (this *Nacos_Registry) GetServiceByCategory(category core.S_Category) (n []*ServiceNode) { - this.slock.RLock() - defer this.slock.RUnlock() - n = make([]*ServiceNode, 0) - for _, v := range this.services { - if v.Category == category { - n = append(n, v) - } - } - return -} -func (this *Nacos_Registry) GetRpcSubById(rId core.Rpc_Key) (n []*ServiceNode) { - n = make([]*ServiceNode, 0) - this.rlock.RLock() - d, ok := this.rpcsubs[rId] - this.rlock.RUnlock() - if ok { - n = d - } - return -} - -//内部函数------------------------------------------------------------------------------------------------------------------------- -func (this *Nacos_Registry) run(ctx context.Context) { - t := time.NewTicker(time.Duration(this.options.Consul_RegisterInterval) * time.Second) - defer t.Stop() -locp: - for { - select { - case <-t.C: - err := this.PushServiceInfo() - if err != nil { - log.Warnf("service run Server.Register error: %v", err) - } - case <-ctx.Done(): - break locp - } - } - log.Infof("Sys Registry is succ exit run") -} - -func (this *Nacos_Registry) listener(ctx context.Context) { - var ( - slist model.ServiceList - instances []model.Instance - err error - ) - t := time.NewTicker(time.Duration(this.options.Nacos_RegisterTTL) * time.Second) - defer t.Stop() -locp: - for { - select { - case <-t.C: - if slist, err = this.client.GetAllServicesInfo(vo.GetAllServiceInfoParam{ - NameSpace: this.options.Nacos_NamespaceId, - GroupName: this.options.Service.GetTag(), - PageNo: 1, - PageSize: 100, - }); err == nil { - var service = make(map[string]struct{}) - for _, v := range slist.Doms { - if instances, err = this.client.SelectInstances(vo.SelectInstancesParam{ - ServiceName: v, - GroupName: this.options.Service.GetTag(), - HealthyOnly: true, - }); err == nil { - for _, v1 := range instances { - if v1.Enable && v1.Healthy { - service[v] = struct{}{} - this.addandupdataServiceNode(v1) - } - } - } - } - temp := make(map[string]*ServiceNode) - this.rlock.RLock() - for k, v := range this.services { - temp[k] = v - } - this.rlock.RUnlock() - for k, v := range temp { - if _, ok := service[k]; !ok { //不存在了 移除 - this.removeServiceNode(v.Id) - } - } - } - case <-ctx.Done(): - break locp - } - } - log.Infof("Sys Registry is succ exit listener") -} - -func (this *Nacos_Registry) getServices() (err error) { - var ( - slist model.ServiceList - instances []model.Instance - ) - if slist, err = this.client.GetAllServicesInfo(vo.GetAllServiceInfoParam{ - NameSpace: this.options.Nacos_NamespaceId, - GroupName: this.options.Service.GetTag(), - PageNo: 1, - PageSize: 20, - }); err == nil { - for _, v := range slist.Doms { - this.rlock.RLock() - _, ok := this.services[v] - this.rlock.RUnlock() - if !ok { - if instances, err = this.client.SelectInstances(vo.SelectInstancesParam{ - ServiceName: v, - GroupName: this.options.Service.GetTag(), - HealthyOnly: true, - }); err == nil { - for _, v1 := range instances { - if v1.Enable && v1.Healthy { - this.addandupdataServiceNode(v1) - } - } - } - } - } - } - return err -} -func (this *Nacos_Registry) registerSNode(snode *ServiceNode) (err error) { - h, err := hash.Hash(snode, nil) - if err != nil { - return err - } - if v, ok := this.shash[snode.Id]; ok && v != 0 && v == h { //没变化不用注册 - return - } - var ( - // success bool - ) - this.deregisterSNode() - _, err = this.client.RegisterInstance(vo.RegisterInstanceParam{ - Ip: snode.IP, - Port: uint64(snode.Port), - Weight: snode.PreWeight, - GroupName: snode.Tag, - ServiceName: snode.Id, - Enable: true, - Healthy: true, - Ephemeral: true, - Metadata: map[string]string{ - "id": snode.Id, - "tag": snode.Tag, - "type": string(snode.Type), - "category": string(snode.Category), - "version": fmt.Sprintf("%v", snode.Version), - "rpcid": snode.RpcId, - }, - }) - return -} -func (this *Nacos_Registry) deregisterSNode() (err error) { - _, err = this.client.DeregisterInstance(vo.DeregisterInstanceParam{ - Ip: this.options.Service.GetIp(), - Port: 8848, - ServiceName: this.options.Service.GetId(), - GroupName: this.options.Service.GetTag(), - }) - return -} -func (this *Nacos_Registry) addandupdataServiceNode(as model.Instance) (sn *ServiceNode, err error) { - var ( - version string - rpcid string - snode *ServiceNode - h uint64 - ) - version = as.Metadata["version"] - rpcid = as.Metadata["rpcid"] - snode = &ServiceNode{ - Tag: as.Metadata["tag"], - Type: as.Metadata["type"], - Category: core.S_Category(as.Metadata["category"]), - Id: as.Metadata["id"], - IP: as.Ip, - Port: int(as.Port), - Version: version, - RpcId: rpcid, - PreWeight: as.Weight, - } - if h, err = hash.Hash(snode, nil); err == nil { - _, ok := this.services[snode.Id] - if !ok { - log.Infof("发现新的服务【%s:%s】", snode.Id, snode.Version) - sub := &vo.SubscribeParam{ - ServiceName: snode.Id, - GroupName: snode.Tag, - SubscribeCallback: this.subscribecallback, - } - this.rlock.Lock() - this.services[snode.Id] = snode - this.shash[snode.Id] = h - this.subscribe[snode.Id] = sub - this.rlock.Unlock() - if this.options.Listener != nil { //异步通知 - go this.options.Listener.FindServiceHandlefunc(*snode) - } - err = this.client.Subscribe(sub) - } else { - this.rlock.RLock() - v, ok := this.shash[snode.Id] - this.rlock.RUnlock() - if !ok || v != h { //校验不一致 - // log.Debugf("更新服务【%s】", snode.Id) - this.rlock.Lock() - this.services[snode.Id] = snode - this.shash[snode.Id] = h - this.rlock.Unlock() - if this.options.Listener != nil { //异步通知 - go this.options.Listener.UpDataServiceHandlefunc(*snode) - } - } - } - } else { - log.Errorf("registry 校验服务 hash 值异常:%s", err.Error()) - } - return -} -func (this *Nacos_Registry) removeServiceNode(sId string) { - this.rlock.RLock() - _, ok := this.services[sId] - sub, _ := this.subscribe[sId] - this.rlock.RUnlock() - if !ok { - return - } - log.Infof("丢失服务【%s】", sId) - this.rlock.Lock() - delete(this.services, sId) - delete(this.subscribe, sId) - delete(this.shash, sId) - this.rlock.Unlock() - this.client.Unsubscribe(sub) - if this.options.Listener != nil { //异步通知 - go this.options.Listener.LoseServiceHandlefunc(sId) - } -} - -func (this *Nacos_Registry) subscribecallback(services []model.SubscribeService, err error) { - for _, v := range services { - // log.Debugf("subscribecallback:%+v", v) - this.addandupdataServiceNode(model.Instance{ - Valid: v.Valid, - Enable: v.Enable, - ServiceName: v.ServiceName, - Ip: v.Ip, - Port: v.Port, - Metadata: v.Metadata, - Weight: v.Weight, - }) - } -} diff --git a/lego/sys/registry/options.go b/lego/sys/registry/options.go deleted file mode 100644 index 342b78caf..000000000 --- a/lego/sys/registry/options.go +++ /dev/null @@ -1,135 +0,0 @@ -package registry - -import ( - "go_dreamfactory/lego/base" - "go_dreamfactory/lego/utils/mapstructure" -) - -type RegistryType uint8 - -const ( - Registry_Consul RegistryType = iota - Registry_Nacos - Registry_Zookeeper -) - -type ( - Option func(*Options) - Options struct { - RegistryType RegistryType - Service base.IClusterServiceBase - Listener IListener - Consul_Addr string - Consul_RegisterInterval int //定期注册 - Consul_RegisterTTL int - Nacos_NamespaceId string - Nacos_NacosAddr string - Nacos_Port uint64 - Nacos_UserName string - Nacos_Password string - Nacos_TimeoutMs uint64 //连接超时 ms - Nacos_BeatInterval int64 //心跳间隔 ms - Nacos_RegisterTTL int - } -) - -func SetRegistryType(v RegistryType) Option { - return func(o *Options) { - o.RegistryType = v - } -} -func SetService(v base.IClusterServiceBase) Option { - return func(o *Options) { - o.Service = v - } -} -func SetListener(v IListener) Option { - return func(o *Options) { - o.Listener = v - } -} -func SetConsul_Addr(v string) Option { - return func(o *Options) { - o.Consul_Addr = v - } -} -func SetConsul_RegisterInterval(v int) Option { - return func(o *Options) { - o.Consul_RegisterInterval = v - } -} -func SetConsul_RegisterTTL(v int) Option { - return func(o *Options) { - o.Consul_RegisterTTL = v - } -} -func SetNacos_NamespaceId(v string) Option { - return func(o *Options) { - o.Nacos_NamespaceId = v - } -} -func SetNacos_NacosAddr(v string) Option { - return func(o *Options) { - o.Nacos_NacosAddr = v - } -} - -func SetNacos_Port(v uint64) Option { - return func(o *Options) { - o.Nacos_Port = v - } -} - -func SetNacos_UserName(v string) Option { - return func(o *Options) { - o.Nacos_UserName = v - } -} - -func SetNacos_Password(v string) Option { - return func(o *Options) { - o.Nacos_Password = v - } -} - -func SetNacos_TimeoutMs(v uint64) Option { - return func(o *Options) { - o.Nacos_TimeoutMs = v - } -} -func SetNacos_BeatInterval(v int64) Option { - return func(o *Options) { - o.Nacos_BeatInterval = v - } -} - -func newOptions(config map[string]interface{}, opts ...Option) Options { - options := Options{ - Consul_RegisterInterval: 10, - Consul_RegisterTTL: 15, - Nacos_TimeoutMs: 10000, - Nacos_BeatInterval: 5000, - Nacos_RegisterTTL: 8, - } - if config != nil { - mapstructure.Decode(config, &options) - } - for _, o := range opts { - o(&options) - } - return options -} - -func newOptionsByOption(opts ...Option) Options { - options := Options{ - Consul_RegisterInterval: 10, - Consul_RegisterTTL: 30, - Nacos_TimeoutMs: 10000, - Nacos_BeatInterval: 5000, - Nacos_RegisterTTL: 8, - } - for _, o := range opts { - o(&options) - } - return options -} diff --git a/lego/sys/registry/registry.go b/lego/sys/registry/registry.go deleted file mode 100644 index 4fa7070d5..000000000 --- a/lego/sys/registry/registry.go +++ /dev/null @@ -1,10 +0,0 @@ -package registry - -func newSys(options Options) (sys ISys, err error) { - if options.RegistryType == Registry_Consul { - sys, err = newConsul(options) - } else if options.RegistryType == Registry_Nacos { - sys, err = newNacos(options) - } - return -} diff --git a/lego/sys/registry/sys_test.go b/lego/sys/registry/sys_test.go deleted file mode 100644 index c8c6897d0..000000000 --- a/lego/sys/registry/sys_test.go +++ /dev/null @@ -1,117 +0,0 @@ -package registry_test - -import ( - "fmt" - "testing" - - "github.com/hashicorp/consul/api" - "github.com/nacos-group/nacos-sdk-go/clients" - "github.com/nacos-group/nacos-sdk-go/common/constant" - "github.com/nacos-group/nacos-sdk-go/vo" -) - -func Test_Sys_Nacose(t *testing.T) { - // 创建clientConfig - clientConfig := constant.ClientConfig{ - NamespaceId: "ac1b23d5-1c14-4485-9e08-f3cde8c83163", - } - // 至少一个ServerConfig - serverConfigs := []constant.ServerConfig{ - { - IpAddr: "172.20.27.126", - ContextPath: "/nacos", - Port: 8888, - Scheme: "http", - }, - } - - // 创建服务发现客户端的另一种方式 (推荐) - client, err := clients.NewNamingClient( - vo.NacosClientParam{ - ClientConfig: &clientConfig, - ServerConfigs: serverConfigs, - }, - ) - if err != nil { - fmt.Printf("初始化系统失败\n") - } - - // if succ, err := client.RegisterInstance(vo.RegisterInstanceParam{ - // Ip: "127.0.0.2", - // Port: 8848, - // Weight: 1, - // ServiceName: "test_1", - // Enable: true, - // Healthy: true, - // Ephemeral: true, - // Metadata: map[string]string{ - // "type": "test", - // "category": "test", - // "version": fmt.Sprintf("%e", 1.0), - // "rpcid": "rwercsfsdwer", - // "rpcsubscribe": "{}", - // }, - // }); err != nil { - // fmt.Printf("RegisterInstance err:%v\n", err) - // } else { - // fmt.Printf("RegisterInstance succ:%v\n", succ) - // } - - if slist, err := client.GetAllServicesInfo(vo.GetAllServiceInfoParam{ - NameSpace: "ac1b23d5-1c14-4485-9e08-f3cde8c83163", - GroupName: "datacollector", - PageNo: 1, - PageSize: 20, - }); err != nil { - fmt.Printf("GetAllServicesInfo err:%v\n", err) - } else { - fmt.Printf("GetAllServicesInfo :%+v\n", slist) - for _, v := range slist.Doms { - if instances, err := client.SelectInstances(vo.SelectInstancesParam{ - ServiceName: v, - GroupName: "datacollector", - HealthyOnly: true, - }); err == nil { - fmt.Printf("instances :%+v\n", instances) - } else { - fmt.Printf("instances err:%v\n", err) - } - // if services, err := client.SelectInstances(vo.SelectInstancesParam{ - // ServiceName: v, - // HealthyOnly: true, - // }); err != nil { - // fmt.Printf("SelectInstances err:%v\n", err) - // } else { - // fmt.Printf("SelectInstances :%+v\n", services) - // } - // if services, err := client.SelectAllInstances(vo.SelectAllInstancesParam{ - // ServiceName: v, - // }); err != nil { - // fmt.Printf("SelectAllInstances err:%v\n", err) - // } else { - // fmt.Printf("SelectAllInstances :%+v\n", services) - // } - } - } -} - -func Test_Sys_Consul(t *testing.T) { - config := api.DefaultConfig() - config.Address = "172.20.27.145:10003" - if client, err := api.NewClient(config); err != nil { - fmt.Printf("NewClient Err:%v\n", err) - return - } else { - if err := client.Agent().ServiceRegister(&api.AgentServiceRegistration{ - ID: "test", - Name: "test", - Tags: []string{"test"}, - Meta: map[string]string{}, - }); err != nil { - fmt.Printf("ServiceRegister Err:%v\n", err) - return - } else { - fmt.Printf("ServiceRegister Succ\n") - } - } -} diff --git a/lego/sys/registry/zookeeper.go b/lego/sys/registry/zookeeper.go deleted file mode 100644 index c04b90f74..000000000 --- a/lego/sys/registry/zookeeper.go +++ /dev/null @@ -1,10 +0,0 @@ -package registry - -func newZookeeper(options Options) (sys *Zookeeper_Registry, err error) { - - return -} - -type Zookeeper_Registry struct { - options Options -} diff --git a/lego/sys/rpcx/client.go b/lego/sys/rpcx/client.go index eed13bf6c..a01793bf4 100644 --- a/lego/sys/rpcx/client.go +++ b/lego/sys/rpcx/client.go @@ -36,6 +36,7 @@ type Client struct { metadata string writeTimeout time.Duration AsyncWrite bool + clusterMu sync.RWMutex clusterClients map[string]map[string]client.XClient //其他集群客户端 connsMapMu sync.RWMutex conns map[string]net.Conn @@ -51,15 +52,15 @@ func (this *Client) DoMessage() { for msg := range this.msgChan { go func(req *protocol.Message) { if req.ServicePath != "" && req.ServiceMethod != "" { - this.Debugf("DoMessage :%v", req) + this.options.Log.Debugf("DoMessage :%v", req) addr, ok := req.Metadata[ServiceAddrKey] if !ok { - this.Errorf("Metadata no found ServiceAddrKey!") + this.options.Log.Errorf("Metadata no found ServiceAddrKey!") return } conn, ok := this.conns[addr] if !ok { - this.Errorf("no found conn addr:%s", addr) + this.options.Log.Errorf("no found conn addr:%s", addr) return } res, _ := this.handleRequest(context.Background(), req) @@ -86,6 +87,19 @@ func (this *Client) Stop() (err error) { return } +//获取服务集群列表 +func (this *Client) GetServiceTags() []string { + this.clusterMu.RLock() + tags := make([]string, len(this.clusterClients)) + n := 0 + for k, _ := range this.clusterClients { + tags[n] = k + n++ + } + this.clusterMu.RUnlock() + return tags +} + //注册Rpc 服务 func (this *Client) RegisterFunction(fn interface{}) (err error) { _, err = this.registerFunction(this.options.ServiceType, fn, "", false) @@ -247,12 +261,12 @@ func (this *Client) UpdateServer(servers map[string]*ServiceNode) { ServiceType: this.options.ServiceType, ServiceAddr: this.options.ServiceAddr}, &ServiceNode{}); err != nil { - this.Errorf("ShakeHands new node addr:%s err:%v", v.ServiceAddr, err) + this.options.Log.Errorf("ShakeHands new node addr:%s err:%v", v.ServiceAddr, err) this.connectMapMu.Lock() delete(this.connecting, v.ServiceAddr) this.connectMapMu.Unlock() } else { - this.Debugf("UpdateServer addr:%s ", v.ServiceAddr) + this.options.Log.Debugf("UpdateServer addr:%s ", v.ServiceAddr) } } } @@ -265,7 +279,7 @@ func (this *Client) ClientConnected(conn net.Conn) (net.Conn, error) { this.connsMapMu.Lock() this.conns[addr] = conn this.connsMapMu.Unlock() - this.Debugf("ClientConnected addr:%v", addr) + this.options.Log.Debugf("ClientConnected addr:%v", addr) return conn, nil } @@ -275,51 +289,10 @@ func (this *Client) ClientConnectionClose(conn net.Conn) error { this.connsMapMu.Lock() delete(this.conns, addr) this.connsMapMu.Unlock() - this.Debugf("ClientConnectionClose addr:%v", addr) + this.options.Log.Debugf("ClientConnectionClose addr:%v", addr) return nil } -///日志*********************************************************************** -func (this *Client) Debug() bool { - return this.options.Debug -} - -func (this *Client) Debugf(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Debugf("[SYS RPCX] "+format, a...) - } -} - -func (this *Client) Infof(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Infof("[SYS RPCX] "+format, a...) - } -} - -func (this *Client) Warnf(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Warnf("[SYS RPCX] "+format, a...) - } -} - -func (this *Client) Errorf(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Errorf("[SYS RPCX] "+format, a...) - } -} - -func (this *Client) Panicf(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Panicf("[SYS RPCX] "+format, a...) - } -} - -func (this *Client) Fatalf(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Fatalf("[SYS RPCX] "+format, a...) - } -} - //获取目标客户端 func (this *Client) getclient(ctx *context.Context, clusterTag string, servicePath string) (c client.XClient, err error) { if servicePath == "" { @@ -392,7 +365,7 @@ func (this *Client) registerFunction(servicePath string, fn interface{}, name st } if fname == "" { errorStr := "rpcx.registerFunction: no func name for type " + f.Type().String() - this.Errorf(errorStr) + this.options.Log.Errorf(errorStr) return fname, errors.New(errorStr) } @@ -505,7 +478,7 @@ func (this *Client) handleRequest(ctx context.Context, req *protocol.Message) (r } else if replyv != nil { reflectTypePools.Put(mtype.ReplyType, replyv) } - this.Debugf("server called service %+v for an request %+v", service, req) + this.options.Log.Debugf("server called service %+v for an request %+v", service, req) return res, nil } diff --git a/lego/sys/rpcx/core.go b/lego/sys/rpcx/core.go index e5a9160a3..6fad3f0c7 100644 --- a/lego/sys/rpcx/core.go +++ b/lego/sys/rpcx/core.go @@ -22,6 +22,7 @@ type ( ISys interface { Start() (err error) Stop() (err error) + GetServiceTags() []string RegisterFunction(fn interface{}) (err error) RegisterFunctionName(name string, fn interface{}) (err error) UnregisterAll() (err error) diff --git a/lego/sys/rpcx/options.go b/lego/sys/rpcx/options.go index 486a730c8..679f1892a 100644 --- a/lego/sys/rpcx/options.go +++ b/lego/sys/rpcx/options.go @@ -28,7 +28,7 @@ type Options struct { AutoConnect bool //自动连接 客户端启动模式下 主动连接发现的节点服务器 SerializeType protocol.SerializeType Debug bool //日志是否开启 - Log log.ILog + Log log.ILogger } func SetServiceTag(v string) Option { @@ -79,7 +79,7 @@ func SetDebug(v bool) Option { o.Debug = v } } -func SetLog(v log.ILog) Option { +func SetLog(v log.ILogger) Option { return func(o *Options) { o.Log = v } @@ -100,7 +100,7 @@ func newOptions(config map[string]interface{}, opts ...Option) (options *Options return options, errors.New("[Sys.RPCX] newOptions err: 启动参数异常") } if options.Debug && options.Log == nil { - if options.Log = log.Clone(log.SetLoglayer(2)); options.Log == nil { + if options.Log = log.NewTurnlog(options.Debug, log.Clone("sys.rpc", 2)); options.Log == nil { err = errors.New("log is nil") } } @@ -111,8 +111,6 @@ func newOptionsByOption(opts ...Option) (options *Options, err error) { options = &Options{ AutoConnect: true, SerializeType: protocol.MsgPack, - Debug: true, - Log: log.Clone(log.SetLoglayer(2)), } for _, o := range opts { o(options) @@ -121,7 +119,7 @@ func newOptionsByOption(opts ...Option) (options *Options, err error) { return options, errors.New("[Sys.RPCX] newOptions err: 启动参数异常") } if options.Debug && options.Log == nil { - if options.Log = log.Clone(log.SetLoglayer(2)); options.Log == nil { + if options.Log = log.NewTurnlog(options.Debug, log.Clone("sys.rpc", 2)); options.Log == nil { err = errors.New("log is nil") } } diff --git a/lego/sys/rpcx/rpcx.go b/lego/sys/rpcx/rpcx.go index edd14091b..5f8d27e2e 100644 --- a/lego/sys/rpcx/rpcx.go +++ b/lego/sys/rpcx/rpcx.go @@ -46,6 +46,10 @@ func (this *RPCX) Stop() (err error) { return } +//获取服务集群列表 +func (this *RPCX) GetServiceTags() []string { + return this.GetServiceTags() +} func (this *RPCX) RegisterFunction(fn interface{}) (err error) { this.service.RegisterFunction(fn) return diff --git a/lego/sys/rpcx/service.go b/lego/sys/rpcx/service.go index 408e958e5..67fc6cedc 100644 --- a/lego/sys/rpcx/service.go +++ b/lego/sys/rpcx/service.go @@ -63,7 +63,7 @@ type Service struct { func (this *Service) Start() (err error) { go func() { if err = this.server.Serve("tcp", this.options.ServiceAddr); err != nil { - this.Warnf("rpcx server exit:%v", err) + this.options.Log.Warnf("rpcx server exit:%v", err) } }() return @@ -75,6 +75,19 @@ func (this *Service) Stop() (err error) { return } +//获取服务集群列表 +func (this *Service) GetServiceTags() []string { + this.selectormutex.RLock() + tags := make([]string, len(this.selectors)) + n := 0 + for k, _ := range this.selectors { + tags[n] = k + n++ + } + this.selectormutex.RUnlock() + return tags +} + //注册RPC 服务 func (this *Service) RegisterFunction(fn interface{}) (err error) { err = this.server.RegisterFunction(this.options.ServiceType, fn, this.metadata) @@ -204,7 +217,7 @@ func (this *Service) PostReadRequest(ctx context.Context, r *protocol.Message, e ok bool ) req_metadata := r.Metadata - this.Debugf("PreReadRequest ServicePath:%s ServicePath:%s Metadata:%v ", r.ServicePath, r.ServiceMethod, r.Metadata) + this.options.Log.Debugf("PreReadRequest ServicePath:%s ServicePath:%s Metadata:%v ", r.ServicePath, r.ServiceMethod, r.Metadata) if stag, ok = req_metadata[ServiceClusterTag]; ok { this.selectormutex.RLock() selector, ok = this.selectors[stag] @@ -228,7 +241,7 @@ func (this *Service) PostReadRequest(ctx context.Context, r *protocol.Message, e } this.clientmutex.Unlock() selector.UpdateServer(servers) - this.Debugf("fond new node addr:%s smeta:%s \n", addr, smeta) + this.options.Log.Debugf("fond new node addr:%s smeta:%s \n", addr, smeta) } } } @@ -243,7 +256,7 @@ func (this *Service) PostReadRequest(ctx context.Context, r *protocol.Message, e this.mutex.Unlock() switch { case call == nil: - this.Errorf("callmessage no found call:%d", seq) + this.options.Log.Errorf("callmessage no found call:%d", seq) case r.MessageStatusType() == protocol.Error: if len(r.Metadata) > 0 { call.ResMetadata = r.Metadata @@ -284,42 +297,6 @@ func (this *Service) RpcxShakeHands(ctx context.Context, args *ServiceNode, repl return nil } -///日志*********************************************************************** -func (this *Service) Debug() bool { - return this.options.Debug -} - -func (this *Service) Debugf(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Debugf("[SYS RPCX] "+format, a...) - } -} -func (this *Service) Infof(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Infof("[SYS RPCX] "+format, a...) - } -} -func (this *Service) Warnf(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Warnf("[SYS RPCX] "+format, a...) - } -} -func (this *Service) Errorf(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Errorf("[SYS RPCX] "+format, a...) - } -} -func (this *Service) Panicf(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Panicf("[SYS RPCX] "+format, a...) - } -} -func (this *Service) Fatalf(format string, a ...interface{}) { - if this.options.Debug { - this.options.Log.Fatalf("[SYS RPCX] "+format, a...) - } -} - //执行远程调用 func (this *Service) call(ctx context.Context, clusterTag string, servicePath string, serviceMethod string, args interface{}, reply interface{}, done chan *client.Call) (conn net.Conn, _call *client.Call, err error) { var ( diff --git a/lego/utils/codec/core.go b/lego/utils/codec/bytes.go similarity index 69% rename from lego/utils/codec/core.go rename to lego/utils/codec/bytes.go index 649be552b..67f8d3aed 100644 --- a/lego/utils/codec/core.go +++ b/lego/utils/codec/bytes.go @@ -3,29 +3,11 @@ package codec import ( "encoding/binary" "math" - "strconv" "unsafe" ) const host32bit = ^uint(0)>>32 == 0 -type ( - IDecoder interface { - Decoder(buf []byte, v interface{}) error - DecoderMap(data map[string][]byte, v interface{}) error - DecoderString(buf string, v interface{}) error - DecoderMapString(data map[string]string, v interface{}) error - DecoderSliceString(data []string, v interface{}) error - } - IEncoder interface { - Encoder(v interface{}) (data []byte, err error) - EncoderToMap(v interface{}) (data map[string][]byte, err error) - EncoderString(v interface{}) (data string, err error) - EncoderToMapString(v interface{}) (data map[string]string, err error) - EncoderToSliceString(v interface{}) (data []string, err error) - } -) - // string func BytesToString(b []byte) string { return *(*string)(unsafe.Pointer(&b)) @@ -186,31 +168,3 @@ func BytesToBool(buf []byte) bool { var data bool = buf[0] != 0 return data } - -func Atoi(b []byte) (int, error) { - return strconv.Atoi(BytesToString(b)) -} - -func ParseInt(b []byte, base int, bitSize int) (int64, error) { - return strconv.ParseInt(BytesToString(b), base, bitSize) -} - -func ParseUint(b []byte, base int, bitSize int) (uint64, error) { - return strconv.ParseUint(BytesToString(b), base, bitSize) -} - -func ParseFloat(b []byte, bitSize int) (float64, error) { - return strconv.ParseFloat(BytesToString(b), bitSize) -} - -func UintToString(n uint64) string { - return BytesToString(strconv.AppendUint([]byte{}, n, 10)) -} - -func IntToString(n int64) string { - return BytesToString(strconv.AppendInt([]byte{}, n, 10)) -} - -func FloatToString(f float64) string { - return BytesToString(strconv.AppendFloat([]byte{}, f, 'f', -1, 64)) -} diff --git a/lego/utils/codec/codec.go b/lego/utils/codec/codec.go new file mode 100644 index 000000000..eebc0753e --- /dev/null +++ b/lego/utils/codec/codec.go @@ -0,0 +1,70 @@ +package codec + +import ( + "sync" + + "go_dreamfactory/lego/utils/codec/codecore" + "go_dreamfactory/lego/utils/codec/factory" + + "github.com/modern-go/reflect2" +) + +var decoderCache = new(sync.Map) +var encoderCache = new(sync.Map) + +func AddDecoder(cacheKey uintptr, decoder codecore.IDecoder) { + decoderCache.Store(cacheKey, decoder) +} +func AddEncoder(cacheKey uintptr, encoder codecore.IEncoder) { + encoderCache.Store(cacheKey, encoder) +} +func GetEncoder(cacheKey uintptr) codecore.IEncoder { + encoder, found := encoderCache.Load(cacheKey) + if found { + return encoder.(codecore.IEncoder) + } + return nil +} +func GetDecoder(cacheKey uintptr) codecore.IDecoder { + decoder, found := decoderCache.Load(cacheKey) + if found { + return decoder.(codecore.IDecoder) + } + return nil +} +func EncoderOf(typ reflect2.Type, config *codecore.Config) codecore.IEncoder { + cacheKey := typ.RType() + encoder := GetEncoder(cacheKey) + if encoder != nil { + return encoder + } + ctx := &codecore.Ctx{ + Config: config, + Prefix: "", + Decoders: map[reflect2.Type]codecore.IDecoder{}, + Encoders: map[reflect2.Type]codecore.IEncoder{}, + } + encoder = factory.EncoderOfType(ctx, typ) + if typ.LikePtr() { + encoder = factory.NewonePtrEncoder(encoder) + } + AddEncoder(cacheKey, encoder) + return encoder +} +func DecoderOf(typ reflect2.Type, config *codecore.Config) codecore.IDecoder { + cacheKey := typ.RType() + decoder := GetDecoder(cacheKey) + if decoder != nil { + return decoder + } + ctx := &codecore.Ctx{ + Config: config, + Prefix: "", + Decoders: map[reflect2.Type]codecore.IDecoder{}, + Encoders: map[reflect2.Type]codecore.IEncoder{}, + } + ptrType := typ.(*reflect2.UnsafePtrType) + decoder = factory.DecoderOfType(ctx, ptrType.Elem()) + AddDecoder(cacheKey, decoder) + return decoder +} diff --git a/lego/utils/codec/codec_test.go b/lego/utils/codec/codec_test.go index c04930b97..dc4ee05a4 100644 --- a/lego/utils/codec/codec_test.go +++ b/lego/utils/codec/codec_test.go @@ -1,65 +1,43 @@ -package codec +package codec_test import ( - "encoding/json" "fmt" + "go_dreamfactory/lego/utils/codec/json" "testing" ) type TestData struct { - Fild_1 string - Fild_3 int - Fild_4 float32 + Name string + Value int + Array []interface{} + Data map[string]interface{} +} +type Test1Data struct { + Name string + Value int } -func Test_Encoder(t *testing.T) { - encoder := &Encoder{} - // data, err := encoder.EncoderToMap(map[string]interface{}{"liwei": 106, "sasd": "2564"}) - // fmt.Printf("EncoderToMap data1:%v err:%v", data, err) - data, err := encoder.EncoderToMap([]interface{}{"liwei", 106, "sasd", "2564"}) - fmt.Printf("EncoderToMap data1:%v err:%v", data, err) - // data, err := encoder.EncoderToMap(&TestData{Fild_1: "liwei1dao", Fild_3: 25, Fild_4: 3.54}) - // fmt.Printf("EncoderToMap data2:%v err:%v", data, err) +func Test_sys_slice(t *testing.T) { + data := []*Test1Data{{"liwe", 1}, {"liwe2", 2}} + d, err := json.Marshal(data) + fmt.Printf("codec Marshal d:%s err:%v", d, err) + data = []*Test1Data{} + err = json.Unmarshal(d, &data) + fmt.Printf("codec UnmarshalJson data:%v err:%v", data, err) } - -func Test_Decoder(t *testing.T) { - decoder := &Decoder{} +func Test_sys_json(t *testing.T) { + d, err := json.Marshal(&TestData{Name: "http://liwei1dao.com?asd=1&dd=1", Value: 10, Array: []interface{}{1, "dajiahao", &Test1Data{Name: "liwe1dao", Value: 123}}, Data: map[string]interface{}{"hah": 1, "asd": 999}}) + fmt.Printf("codec Marshal d:%s err:%v", d, err) data := &TestData{} - err := decoder.DecoderMapString(map[string]string{"Fild_1": "liwei1dao"}, data) - fmt.Printf("DecoderMap data1:%v err:%v", data, err) + err = json.Unmarshal(d, data) + fmt.Printf("codec UnmarshalJson data:%v err:%v", data, err) } -func Test_Slice_Decoder(t *testing.T) { - decoder := &Decoder{DefDecoder: json.Unmarshal} - encoder := &Encoder{DefEncoder: json.Marshal} - data := []*TestData{{Fild_1: "1dao", Fild_3: 10, Fild_4: 3.5}, {Fild_1: "2dao", Fild_3: 20, Fild_4: 6.5}} - datastr, err := encoder.EncoderToSliceString(data) - fmt.Printf("EncoderToSliceString datastr:%v err:%v", datastr, err) - if err != nil { - return - } - data1 := make([]*TestData, 0) - err = decoder.DecoderSliceString(datastr, data1) - fmt.Printf("DecoderMap data1:%v err:%v", data1, err) -} +func Test_sys_mapjson(t *testing.T) { + d, err := json.MarshalMap(&TestData{Name: "http://liwei1dao.com?asd=1&dd=1", Value: 10, Array: []interface{}{1, "dajiahao", &Test1Data{Name: "liwe1dao", Value: 123}}, Data: map[string]interface{}{"hah": 1, "asd": 999}}) + fmt.Printf("codec Marshal d:%s err:%v", d, err) + data := &TestData{} + err = json.UnmarshalMap(d, data) + fmt.Printf("codec UnmarshalJson data:%v err:%v", data, err) -func Test_Slice_Type(t *testing.T) { - decoder := &Decoder{DefDecoder: json.Unmarshal} - encoder := &Encoder{DefEncoder: json.Marshal} - data := []*TestData{{Fild_1: "1dao", Fild_3: 10, Fild_4: 3.5}, {Fild_1: "2dao", Fild_3: 20, Fild_4: 6.5}} - datastr, err := encoder.EncoderToSliceString(data) - fmt.Printf("EncoderToSliceString datastr:%v err:%v", datastr, err) - if err != nil { - return - } - data1 := make([]*TestData, 0) - err = decoder.DecoderSliceString(datastr, &data1) - fmt.Printf("DecoderMap data1:%v err:%v", data1, err) -} - -func Test_EncoderToMapString(t *testing.T) { - encoder := &Encoder{DefEncoder: json.Marshal} - data := &TestData{Fild_1: "1dao", Fild_3: 10, Fild_4: 3.5} - _map, err := encoder.EncoderToMapString(data) - fmt.Printf("DecoderMap map:%v err:%v", _map, err) } diff --git a/lego/sys/codec/core/core.go b/lego/utils/codec/codecore/core.go similarity index 74% rename from lego/sys/codec/core/core.go rename to lego/utils/codec/codecore/core.go index 191765a3a..3fd429a55 100644 --- a/lego/sys/codec/core/core.go +++ b/lego/utils/codec/codecore/core.go @@ -1,4 +1,4 @@ -package core +package codecore import ( "reflect" @@ -7,15 +7,6 @@ import ( "github.com/modern-go/reflect2" ) -//数据类型 -type CodecType int8 - -const ( - Json CodecType = iota //json 格式数据 - Bytes //byte 字节流数据 - Proto //proto google protobuff 数据 -) - //结构值类型 type ValueType int @@ -37,18 +28,14 @@ const ( ) type ( - ICodec interface { - Options() *Options - GetEncoderFromCache(cacheKey uintptr) IEncoder - GetDecoderFromCache(cacheKey uintptr) IDecoder - EncoderOf(typ reflect2.Type) IEncoder - DecoderOf(typ reflect2.Type) IDecoder - BorrowExtractor(buf []byte) IExtractor //借 提取器 - ReturnExtractor(extra IExtractor) //还 提取器 - BorrowStream() IStream //借 输出对象 - ReturnStream(stream IStream) //换 输出对象 + IPools interface { + GetReader(buf []byte) IReader + PutReader(w IReader) + GetWriter() IWriter + PutWriter(w IWriter) } - IExtractor interface { + IReader interface { + IPools ReadVal(obj interface{}) //读取指定类型对象 WhatIsNext() ValueType Read() interface{} @@ -80,7 +67,8 @@ type ( Error() error SetErr(err error) } - IStream interface { + IWriter interface { + IPools WriteVal(val interface{}) //写入一个对象 WriteNil() //写空 null WriteEmptyArray() //写空数组 [] @@ -107,42 +95,36 @@ type ( WriteFloat64(val float64) WriteString(val string) WriteBytes(val []byte) - Reset(bufSize int) + Reset() Buffer() []byte //返回缓存区数据 + Buffered() int Error() error SetErr(err error) } - //Json 编码器 - IEncoder interface { - GetType() reflect.Kind - IsEmpty(ptr unsafe.Pointer) bool - Encode(ptr unsafe.Pointer, stream IStream) - } - //MapJson 编码器 - IEncoderMapJson interface { - EncodeToMapJson(ptr unsafe.Pointer) (ret map[string]string, err error) - } - //SliceJson 编码器 - IEncoderSliceJson interface { - EncodeToSliceJson(ptr unsafe.Pointer) (ret []string, err error) - } - - //Json 解码器 IDecoder interface { GetType() reflect.Kind - Decode(ptr unsafe.Pointer, extra IExtractor) + Decode(ptr unsafe.Pointer, r IReader) } //MapJson 解码器 IDecoderMapJson interface { - DecodeForMapJson(ptr unsafe.Pointer, extra map[string]string) (err error) + DecodeForMapJson(ptr unsafe.Pointer, r IReader, extra map[string]string) (err error) } //MapJson 解码器 IDecoderSliceJson interface { - DecodeForSliceJson(ptr unsafe.Pointer, extra []string) (err error) + DecodeForSliceJson(ptr unsafe.Pointer, r IReader, extra []string) (err error) } - //空校验 - CheckIsEmpty interface { + IEncoder interface { + GetType() reflect.Kind IsEmpty(ptr unsafe.Pointer) bool + Encode(ptr unsafe.Pointer, w IWriter) + } + //MapJson 编码器 + IEncoderMapJson interface { + EncodeToMapJson(ptr unsafe.Pointer, w IWriter) (ret map[string]string, err error) + } + //SliceJson 编码器 + IEncoderSliceJson interface { + EncodeToSliceJson(ptr unsafe.Pointer, w IWriter) (ret []string, err error) } //内嵌指针是否是空 IsEmbeddedPtrNil interface { @@ -150,8 +132,17 @@ type ( } ) +//序列化配置 +type Config struct { + SortMapKeys bool //排序mapkey + IndentionStep int //缩进步骤 + OnlyTaggedField bool //仅仅处理标签字段 + DisallowUnknownFields bool //禁止未知字段 + CaseSensitive bool //是否区分大小写 + TagKey string //标签 +} type Ctx struct { - ICodec + Config *Config Prefix string Encoders map[reflect2.Type]IEncoder Decoders map[reflect2.Type]IDecoder @@ -159,7 +150,7 @@ type Ctx struct { func (this *Ctx) Append(prefix string) *Ctx { return &Ctx{ - ICodec: this.ICodec, + Config: this.Config, Prefix: this.Prefix + " " + prefix, Encoders: this.Encoders, Decoders: this.Decoders, diff --git a/lego/utils/codec/compress.go b/lego/utils/codec/compress.go new file mode 100644 index 000000000..db5392b16 --- /dev/null +++ b/lego/utils/codec/compress.go @@ -0,0 +1,75 @@ +package codec + +import ( + "bytes" + "compress/gzip" + "io/ioutil" + "sync" +) + +var ( + spWriter sync.Pool + spReader sync.Pool + spBuffer sync.Pool +) + +func init() { + spWriter = sync.Pool{New: func() interface{} { + return gzip.NewWriter(nil) + }} + spReader = sync.Pool{New: func() interface{} { + return new(gzip.Reader) + }} + spBuffer = sync.Pool{New: func() interface{} { + return bytes.NewBuffer(nil) + }} +} + +// Unzip unzips data. +func Unzip(data []byte) ([]byte, error) { + buf := bytes.NewBuffer(data) + + gr := spReader.Get().(*gzip.Reader) + defer func() { + spReader.Put(gr) + }() + err := gr.Reset(buf) + if err != nil { + return nil, err + } + defer gr.Close() + + data, err = ioutil.ReadAll(gr) + if err != nil { + return nil, err + } + return data, err +} + +// Zip zips data. +func Zip(data []byte) ([]byte, error) { + buf := spBuffer.Get().(*bytes.Buffer) + w := spWriter.Get().(*gzip.Writer) + w.Reset(buf) + + defer func() { + buf.Reset() + spBuffer.Put(buf) + w.Close() + spWriter.Put(w) + }() + _, err := w.Write(data) + if err != nil { + return nil, err + } + err = w.Flush() + if err != nil { + return nil, err + } + err = w.Close() + if err != nil { + return nil, err + } + dec := buf.Bytes() + return dec, nil +} diff --git a/lego/utils/codec/decoder.go b/lego/utils/codec/decoder.go deleted file mode 100644 index 6d34bb75a..000000000 --- a/lego/utils/codec/decoder.go +++ /dev/null @@ -1,362 +0,0 @@ -package codec - -import ( - "fmt" - "reflect" - "strconv" - "time" -) - -//解码器 -type Decoder struct { - DefDecoder func(buf []byte, v interface{}) error //默认编码 扩展自定义编码方式 -} - -func (this *Decoder) Decoder(buf []byte, v interface{}) error { - switch v := v.(type) { - case nil: - return fmt.Errorf("decoder: Decoder(nil)") - case *string: - *v = BytesToString(buf) - return nil - case *[]byte: - *v = buf - return nil - case *int: - *v = BytesToInt(buf) - return nil - case *int8: - *v = BytesToInt8(buf) - return nil - case *int16: - *v = BytesToInt16(buf) - return nil - case *int32: - *v = BytesToInt32(buf) - return nil - case *int64: - *v = BytesToInt64(buf) - return nil - case *uint: - *v = BytesToUInt(buf) - return nil - case *uint8: - *v = BytesToUInt8(buf) - return nil - case *uint16: - *v = BytesToUInt16(buf) - return nil - case *uint32: - *v = BytesToUInt32(buf) - return nil - case *uint64: - *v = BytesToUInt64(buf) - return nil - case *float32: - *v = BytesToFloat32(buf) - return nil - case *float64: - *v = BytesToFloat64(buf) - return nil - case *bool: - *v = BytesToBool(buf) - return nil - case *time.Time: - var err error - *v, err = time.Parse(time.RFC3339Nano, BytesToString(buf)) - return err - case *time.Duration: - *v = time.Duration(BytesToInt64(buf)) - return nil - default: - if this.DefDecoder != nil { - return this.DefDecoder(buf, v) - } else { - return fmt.Errorf( - "decoder: can't marshal %T (implement decoder.DefDecoder)", v) - } - } -} - -func (this *Decoder) DecoderMap(data map[string][]byte, v interface{}) error { - vof := reflect.ValueOf(v) - if !vof.IsValid() { - return fmt.Errorf("Decoder: DecoderMap(nil)") - } - if vof.Kind() != reflect.Ptr && vof.Kind() != reflect.Map && vof.Kind() != reflect.Slice { - return fmt.Errorf("Decoder: DecoderMap(non-pointer %T)", v) - } - if vof.Kind() == reflect.Map { - kt, vt := vof.Type().Key(), vof.Type().Elem() - for k, v := range data { - key := reflect.New(kt).Elem() - if key.Kind() != reflect.Ptr { - if err := this.Decoder(StringToBytes(k), key.Addr().Interface()); err != nil { - return fmt.Errorf("Decoder: Decoder(non-pointer %T) err:%v", key, err) - } - } else { - if err := this.Decoder(StringToBytes(k), key.Addr()); err != nil { - return fmt.Errorf("Decoder: Decoder(non-pointer %T) err:%v", key, err) - } - } - value := reflect.New(vt).Elem() - if value.Kind() != reflect.Ptr { - if err := this.Decoder(v, value.Addr().Interface()); err != nil { - return fmt.Errorf("Decoder: Decoder(non-pointer %T) err:%v", value, err) - } - } else { - value.Interface() - if err := this.Decoder(v, value.Addr().Interface()); err != nil { - return fmt.Errorf("Decoder: Decoder(non-pointer %T) err:%v", value, err) - } - } - vof.SetMapIndex(key, value) - } - } else if vof.Kind() == reflect.Ptr { - elem := vof.Elem() - relType := elem.Type() - for i := 0; i < relType.NumField(); i++ { - fieldInfo := relType.Field(i) - tag := fieldInfo.Tag - name := tag.Get("json") - if len(name) == 0 { - name = fieldInfo.Name - } - if value, ok := data[name]; ok { - v := reflect.New(fieldInfo.Type).Elem() - if fieldInfo.Type.Kind() != reflect.Ptr { - if err := this.Decoder(value, v.Addr().Interface()); err != nil { - return fmt.Errorf("Decoder: Decoder(non-pointer %T) err:%v", value, err) - } - elem.FieldByName(fieldInfo.Name).Set(v) - } else { - if err := this.Decoder(value, v); err != nil { - return fmt.Errorf("Decoder: Decoder(non-pointer %T) err:%v", value, err) - } - elem.FieldByName(fieldInfo.Name).Set(v) - } - } - } - } - return nil -} - -//redis 存储解析 针对 string 转换 -func (this *Decoder) DecoderString(buf string, v interface{}) (err error) { - switch v := v.(type) { - case nil: - return fmt.Errorf("decoder: Decoder(nil)") - case *string: - *v = buf - return nil - case *[]byte: - *v = StringToBytes(buf) - return nil - case *int: - *v, err = Atoi(StringToBytes(buf)) - return - case *int8: - var n int64 - n, err = ParseInt(StringToBytes(buf), 10, 8) - if err != nil { - return err - } - *v = int8(n) - return - case *int16: - var n int64 - n, err = ParseInt(StringToBytes(buf), 10, 16) - if err != nil { - return err - } - *v = int16(n) - return - case *int32: - var n int64 - n, err = ParseInt(StringToBytes(buf), 10, 32) - if err != nil { - return err - } - *v = int32(n) - return - case *int64: - var n int64 - n, err = ParseInt(StringToBytes(buf), 10, 64) - if err != nil { - return err - } - *v = n - return - case *uint: - var n uint64 - n, err = ParseUint(StringToBytes(buf), 10, 64) - if err != nil { - return err - } - *v = uint(n) - return - case *uint8: - var n uint64 - n, err = ParseUint(StringToBytes(buf), 10, 8) - if err != nil { - return err - } - *v = uint8(n) - return - case *uint16: - var n uint64 - n, err = ParseUint(StringToBytes(buf), 10, 16) - if err != nil { - return err - } - *v = uint16(n) - return - case *uint32: - var n uint64 - n, err = ParseUint(StringToBytes(buf), 10, 32) - if err != nil { - return err - } - *v = uint32(n) - return - case *uint64: - var n uint64 - n, err = ParseUint(StringToBytes(buf), 10, 64) - if err != nil { - return err - } - *v = n - return - case *float32: - var f float64 - f, err = strconv.ParseFloat(buf, 32) - *v = float32(f) - return - case *float64: - *v, err = strconv.ParseFloat(buf, 64) - return - case *bool: - *v, err = strconv.ParseBool(buf) - return - case *time.Time: - var err error - *v, err = time.Parse(time.RFC3339Nano, buf) - return err - case *time.Duration: - var n int64 - n, err = ParseInt(StringToBytes(buf), 10, 64) - if err != nil { - return err - } - *v = time.Duration(n) - return - default: - if this.DefDecoder != nil { - return this.DefDecoder(StringToBytes(buf), v) - } else { - return fmt.Errorf( - "decoder: can't marshal %T (implement decoder.DefDecoder)", v) - } - } -} - -//redis 存储解析 针对 string 转换 -func (this *Decoder) DecoderMapString(data map[string]string, v interface{}) error { - vof := reflect.ValueOf(v) - if !vof.IsValid() { - return fmt.Errorf("Decoder: DecoderMap(nil)") - } - if vof.Kind() != reflect.Ptr && vof.Kind() != reflect.Map && vof.Kind() != reflect.Slice { - return fmt.Errorf("Decoder: DecoderMap(non-pointer %T)", v) - } - if vof.Kind() == reflect.Map { - kt, vt := vof.Type().Key(), vof.Type().Elem() - for k, v := range data { - key := reflect.New(kt).Elem() - if key.Kind() != reflect.Ptr { - if err := this.DecoderString(k, key.Addr().Interface()); err != nil { - return fmt.Errorf("Decoder: Decoder(non-pointer %T) err:%v", key, err) - } - } else { - if err := this.DecoderString(k, key.Addr()); err != nil { - return fmt.Errorf("Decoder: Decoder(non-pointer %T) err:%v", key, err) - } - } - value := reflect.New(vt).Elem() - if value.Kind() != reflect.Ptr { - if err := this.DecoderString(v, value.Addr().Interface()); err != nil { - return fmt.Errorf("Decoder: Decoder(non-pointer %T) err:%v", value, err) - } - } else { - value.Interface() - if err := this.DecoderString(v, value.Addr().Interface()); err != nil { - return fmt.Errorf("Decoder: Decoder(non-pointer %T) err:%v", value, err) - } - } - vof.SetMapIndex(key, value) - } - } else if vof.Kind() == reflect.Ptr { - elem := vof.Elem() - relType := elem.Type() - for i := 0; i < relType.NumField(); i++ { - fieldInfo := relType.Field(i) - tag := fieldInfo.Tag - name := tag.Get("json") - if len(name) == 0 { - name = fieldInfo.Name - } - if value, ok := data[name]; ok { - v := reflect.New(fieldInfo.Type).Elem() - if err := this.DecoderString(value, v.Addr().Interface()); err != nil { - return fmt.Errorf("Decoder: Decoder(non-pointer %T) err:%v", value, err) - } - elem.FieldByName(fieldInfo.Name).Set(v) - } - } - } - return nil -} - -//redis 存储解析 针对 string 转换 -func (this *Decoder) DecoderSliceString(data []string, v interface{}) error { - t := reflect.TypeOf(v) - if t.Kind() == reflect.Ptr { - t = t.Elem() - } - - if t.Kind() == reflect.Slice { - t = t.Elem() - } else { - panic("Input param is not a slice") - } - - sl := reflect.ValueOf(v) - - if t.Kind() == reflect.Ptr { - sl = sl.Elem() - } - - st := sl.Type() - fmt.Printf("Slice Type %s:\n", st) - - sliceType := st.Elem() - if sliceType.Kind() == reflect.Ptr { - sliceType = sliceType.Elem() - } - fmt.Printf("Slice Elem Type %v:\n", sliceType) - for _, buf := range data { - if sl.Len() < sl.Cap() { - sl.Set(sl.Slice(0, sl.Len()+1)) - elem := sl.Index(sl.Len() - 1) - if elem.IsNil() { - elem.Set(reflect.New(sliceType)) - } - this.DecoderString(buf, elem.Elem().Addr().Interface()) - continue - } - elem := reflect.New(sliceType) - sl.Set(reflect.Append(sl, elem)) - this.DecoderString(buf, elem.Elem().Addr().Interface()) - } - return nil -} diff --git a/lego/utils/codec/encoder.go b/lego/utils/codec/encoder.go deleted file mode 100644 index 14cbab1ea..000000000 --- a/lego/utils/codec/encoder.go +++ /dev/null @@ -1,260 +0,0 @@ -package codec - -import ( - "fmt" - "reflect" - "time" -) - -//编码器 -type Encoder struct { - DefEncoder func(v interface{}) (data []byte, err error) //默认编码 扩展自定义编码方式 -} - -func (this *Encoder) Encoder(v interface{}) (data []byte, err error) { - switch v := v.(type) { - case nil: - return StringToBytes(""), nil - case string: - return StringToBytes(v), nil - case []byte: - return v, nil - case int: - return IntToBytes(v), nil - case int8: - return Int8ToBytes(v), nil - case int16: - return Int16ToBytes(v), nil - case int32: - return Int32ToBytes(v), nil - case int64: - return Int64ToBytes(v), nil - case uint: - return UIntToBytes(v), nil - case uint8: - return UInt8ToBytes(v), nil - case uint16: - return UInt16ToBytes(v), nil - case uint32: - return UInt32ToBytes(v), nil - case uint64: - return UInt64ToBytes(v), nil - case float32: - return Float32ToBytes(v), nil - case float64: - return Float64ToBytes(v), nil - case bool: - return BoolToBytes(v), nil - case time.Time: - return v.AppendFormat([]byte{}, time.RFC3339Nano), nil - case time.Duration: - return Int64ToBytes(v.Nanoseconds()), nil - default: - if this.DefEncoder != nil { - return this.DefEncoder(v) - } else { - return nil, fmt.Errorf( - "encoder: can't marshal %T (implement encoder.DefEncoder)", v) - } - } -} - -func (this *Encoder) EncoderToMap(v interface{}) (data map[string][]byte, err error) { - vof := reflect.ValueOf(v) - if !vof.IsValid() { - return nil, fmt.Errorf("Encoder: EncoderToMap(nil)") - } - if vof.Kind() != reflect.Ptr && vof.Kind() != reflect.Map && vof.Kind() != reflect.Slice { - return nil, fmt.Errorf("Encoder: EncoderToMap(non-pointer %T)", v) - } - // vof = vof.Elem() - data = make(map[string][]byte) - if vof.Kind() == reflect.Map { - keys := vof.MapKeys() - for _, k := range keys { - value := vof.MapIndex(k) - var keydata []byte - var valuedata []byte - if keydata, err = this.Encoder(k.Interface()); err != nil { - return nil, fmt.Errorf("Encoder: EncoderToMap(invalid type %T) err:%v", value.Interface(), err) - } - if valuedata, err = this.Encoder(value.Interface()); err != nil { - return nil, fmt.Errorf("Encoder: EncoderToMap(invalid type %T) err:%v", value.Interface(), err) - } - data[BytesToString(keydata)] = valuedata - } - return - } else if vof.Kind() == reflect.Slice { - for i := 0; i < vof.Len(); i++ { - value := vof.Index(i).Interface() - var valuedata []byte - if valuedata, err = this.Encoder(value); err != nil { - return nil, fmt.Errorf("Encoder: EncoderToMap(invalid type %T) err:%v", value, err) - } - data[BytesToString(IntToBytes(i))] = valuedata - } - return - } else if vof.Kind() == reflect.Ptr { - elem := vof.Elem() - relType := elem.Type() - for i := 0; i < relType.NumField(); i++ { - fieldInfo := relType.Field(i) - tag := fieldInfo.Tag - name := tag.Get("json") - if len(name) == 0 { - name = fieldInfo.Name - } - field := elem.Field(i).Interface() - var valuedata []byte - if valuedata, err = this.Encoder(field); err != nil { - return nil, fmt.Errorf("Encoder: EncoderToMap(invalid type %T) err:%v", field, err) - } - data[name] = valuedata - } - return - } else { - return nil, fmt.Errorf("Encoder: EncoderToMap(invalid type %T)", v) - } -} - -//redis 存储编码 针对 string 转换 -func (this *Encoder) EncoderString(v interface{}) (data string, err error) { - switch v := v.(type) { - case nil: - return "", nil - case string: - return v, nil - case []byte: - return BytesToString(v), nil - case int: - return IntToString(int64(v)), nil - case int8: - return IntToString(int64(v)), nil - case int16: - return IntToString(int64(v)), nil - case int32: - return IntToString(int64(v)), nil - case int64: - return IntToString(int64(v)), nil - case uint: - return UintToString(uint64(v)), nil - case uint8: - return UintToString(uint64(v)), nil - case uint16: - return UintToString(uint64(v)), nil - case uint32: - return UintToString(uint64(v)), nil - case uint64: - return UintToString(uint64(v)), nil - case float32: - return UintToString(uint64(v)), nil - case float64: - return UintToString(uint64(v)), nil - case bool: - if v { - return IntToString(1), nil - } - return IntToString(0), nil - case time.Time: - return BytesToString(v.AppendFormat([]byte{}, time.RFC3339Nano)), nil - case time.Duration: - return IntToString(v.Nanoseconds()), nil - default: - if this.DefEncoder != nil { - var b []byte - b, err = this.DefEncoder(v) - if err != nil { - return "", err - } - return BytesToString(b), nil - } else { - return "", fmt.Errorf( - "encoder: can't marshal %T (implement encoder.DefEncoder)", v) - } - } -} - -//redis 存储编码 针对 string 转换 -func (this *Encoder) EncoderToMapString(v interface{}) (data map[string]string, err error) { - vof := reflect.ValueOf(v) - if !vof.IsValid() { - return nil, fmt.Errorf("Encoder: EncoderToMap(nil)") - } - if vof.Kind() != reflect.Ptr && vof.Kind() != reflect.Map && vof.Kind() != reflect.Slice { - return nil, fmt.Errorf("Encoder: EncoderToMap(non-pointer %T)", v) - } - // vof = vof.Elem() - data = make(map[string]string) - if vof.Kind() == reflect.Map { - keys := vof.MapKeys() - for _, k := range keys { - value := vof.MapIndex(k) - var keydata string - var valuedata string - if keydata, err = this.EncoderString(k.Interface()); err != nil { - return nil, fmt.Errorf("Encoder: EncoderToMap(invalid type %T) err:%v", value.Interface(), err) - } - if valuedata, err = this.EncoderString(value.Interface()); err != nil { - return nil, fmt.Errorf("Encoder: EncoderToMap(invalid type %T) err:%v", value.Interface(), err) - } - data[keydata] = valuedata - } - return - } else if vof.Kind() == reflect.Slice { - for i := 0; i < vof.Len(); i++ { - value := vof.Index(i).Interface() - var valuedata string - if valuedata, err = this.EncoderString(value); err != nil { - return nil, fmt.Errorf("Encoder: EncoderToMap(invalid type %T) err:%v", value, err) - } - data[IntToString(int64(i))] = valuedata - } - return - } else if vof.Kind() == reflect.Ptr { - elem := vof.Elem() - relType := elem.Type() - for i := 0; i < relType.NumField(); i++ { - fieldInfo := relType.Field(i) - tag := fieldInfo.Tag - name := tag.Get("json") - if len(name) == 0 { - continue - } - field := elem.Field(i).Interface() - var valuedata string - if valuedata, err = this.EncoderString(field); err != nil { - return nil, fmt.Errorf("Encoder: EncoderToMap(invalid type %T) err:%v", field, err) - } - data[name] = valuedata - } - return - } else { - return nil, fmt.Errorf("Encoder: EncoderToMap(invalid type %T)", v) - } -} - -//redis 存储编码 针对 string 转换 -func (this *Encoder) EncoderToSliceString(v interface{}) (data []string, err error) { - vof := reflect.ValueOf(v) - if !vof.IsValid() { - return nil, fmt.Errorf("Encoder: EncoderToSliceString(nil)") - } - if vof.Kind() != reflect.Ptr && vof.Kind() != reflect.Map && vof.Kind() != reflect.Slice { - return nil, fmt.Errorf("Encoder: EncoderToSliceString(non-pointer %T)", v) - } - // vof = vof.Elem() - if vof.Kind() == reflect.Slice { - data = make([]string, vof.Len()) - for i := 0; i < vof.Len(); i++ { - value := vof.Index(i).Interface() - var valuedata string - if valuedata, err = this.EncoderString(value); err != nil { - return nil, fmt.Errorf("Encoder: EncoderToSliceString(invalid type %T) err:%v", value, err) - } - data[i] = valuedata - } - return - } else { - return nil, fmt.Errorf("Encoder: EncoderToSliceString(invalid type %T)", v) - } -} diff --git a/lego/sys/codec/factory/factory.go b/lego/utils/codec/factory/factory.go similarity index 77% rename from lego/sys/codec/factory/factory.go rename to lego/utils/codec/factory/factory.go index ca6cf2039..0e8f0cb44 100644 --- a/lego/sys/codec/factory/factory.go +++ b/lego/utils/codec/factory/factory.go @@ -5,7 +5,7 @@ import ( "reflect" "unsafe" - "go_dreamfactory/lego/sys/codec/core" + "go_dreamfactory/lego/utils/codec/codecore" "github.com/modern-go/reflect2" ) @@ -35,7 +35,7 @@ func (this sortableBindings) Swap(i, j int) { } //---------------------------------------------------------------------------------------------------------------------------------------------------------------- -func EncoderOfType(ctx *core.Ctx, typ reflect2.Type) core.IEncoder { +func EncoderOfType(ctx *codecore.Ctx, typ reflect2.Type) codecore.IEncoder { encoder := ctx.Encoders[typ] if encoder != nil { return encoder @@ -47,8 +47,8 @@ func EncoderOfType(ctx *core.Ctx, typ reflect2.Type) core.IEncoder { return encoder } -func _createEncoderOfType(ctx *core.Ctx, typ reflect2.Type) core.IEncoder { - var encoder core.IEncoder +func _createEncoderOfType(ctx *codecore.Ctx, typ reflect2.Type) codecore.IEncoder { + var encoder codecore.IEncoder encoder = createEncoderOfNative(ctx, typ) if encoder != nil { return encoder @@ -72,7 +72,7 @@ func _createEncoderOfType(ctx *core.Ctx, typ reflect2.Type) core.IEncoder { } } -func DecoderOfType(ctx *core.Ctx, typ reflect2.Type) core.IDecoder { +func DecoderOfType(ctx *codecore.Ctx, typ reflect2.Type) codecore.IDecoder { decoder := ctx.Decoders[typ] if decoder != nil { return decoder @@ -84,8 +84,8 @@ func DecoderOfType(ctx *core.Ctx, typ reflect2.Type) core.IDecoder { return decoder } -func _createDecoderOfType(ctx *core.Ctx, typ reflect2.Type) core.IDecoder { - var decoder core.IDecoder +func _createDecoderOfType(ctx *codecore.Ctx, typ reflect2.Type) codecore.IDecoder { + var decoder codecore.IDecoder decoder = createDecoderOfNative(ctx, typ) if decoder != nil { @@ -129,25 +129,25 @@ func StringToBytes(s string) []byte { //根节点 ------------------------------------------------------------------- type rootDecoder struct { - decoder core.IDecoder + decoder codecore.IDecoder } func (this *rootDecoder) GetType() reflect.Kind { return reflect.Ptr } -func (this *rootDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) { - this.decoder.Decode(ptr, extra) +func (this *rootDecoder) Decode(ptr unsafe.Pointer, r codecore.IReader) { + this.decoder.Decode(ptr, r) } type rootEncoder struct { - encoder core.IEncoder + encoder codecore.IEncoder } func (this *rootEncoder) GetType() reflect.Kind { return reflect.Ptr } -func (this *rootEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) { - this.encoder.Encode(ptr, stream) +func (this *rootEncoder) Encode(ptr unsafe.Pointer, w codecore.IWriter) { + this.encoder.Encode(ptr, w) } func (this *rootEncoder) IsEmpty(ptr unsafe.Pointer) bool { @@ -155,12 +155,12 @@ func (this *rootEncoder) IsEmpty(ptr unsafe.Pointer) bool { } //onePtrEncoder--------------------------------------------------------------- -func NewonePtrEncoder(encoder core.IEncoder) core.IEncoder { +func NewonePtrEncoder(encoder codecore.IEncoder) codecore.IEncoder { return &onePtrEncoder{encoder} } type onePtrEncoder struct { - encoder core.IEncoder + encoder codecore.IEncoder } func (this *onePtrEncoder) GetType() reflect.Kind { @@ -171,16 +171,16 @@ func (this *onePtrEncoder) IsEmpty(ptr unsafe.Pointer) bool { return this.encoder.IsEmpty(unsafe.Pointer(&ptr)) } -func (this *onePtrEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) { +func (this *onePtrEncoder) Encode(ptr unsafe.Pointer, stream codecore.IWriter) { this.encoder.Encode(unsafe.Pointer(&ptr), stream) } -func (this *onePtrEncoder) EncodeToMapJson(ptr unsafe.Pointer) (ret map[string]string, err error) { - if encoderMapJson, ok := this.encoder.(core.IEncoderMapJson); !ok { +func (this *onePtrEncoder) EncodeToMapJson(ptr unsafe.Pointer, w codecore.IWriter) (ret map[string]string, err error) { + if encoderMapJson, ok := this.encoder.(codecore.IEncoderMapJson); !ok { err = fmt.Errorf("encoder %T not support EncodeToMapJson", this.encoder) return } else { - return encoderMapJson.EncodeToMapJson(unsafe.Pointer(&ptr)) + return encoderMapJson.EncodeToMapJson(unsafe.Pointer(&ptr), w) } } @@ -192,7 +192,7 @@ type lazyErrorDecoder struct { func (this *lazyErrorDecoder) GetType() reflect.Kind { return reflect.Ptr } -func (this *lazyErrorDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) { +func (this *lazyErrorDecoder) Decode(ptr unsafe.Pointer, extra codecore.IReader) { if extra.Error() == nil { extra.SetErr(this.err) } @@ -206,7 +206,7 @@ func (this *lazyErrorEncoder) GetType() reflect.Kind { return reflect.Ptr } -func (this *lazyErrorEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) { +func (this *lazyErrorEncoder) Encode(ptr unsafe.Pointer, stream codecore.IWriter) { if ptr == nil { stream.WriteNil() } else if stream.Error() == nil { diff --git a/lego/sys/codec/factory/factory_array.go b/lego/utils/codec/factory/factory_array.go similarity index 70% rename from lego/sys/codec/factory/factory_array.go rename to lego/utils/codec/factory/factory_array.go index 7f50618ec..19eaf8396 100644 --- a/lego/sys/codec/factory/factory_array.go +++ b/lego/utils/codec/factory/factory_array.go @@ -7,37 +7,36 @@ import ( "reflect" "unsafe" - "go_dreamfactory/lego/sys/codec/core" + "go_dreamfactory/lego/utils/codec/codecore" "github.com/modern-go/reflect2" ) -func decoderOfArray(ctx *core.Ctx, typ reflect2.Type) core.IDecoder { +func decoderOfArray(ctx *codecore.Ctx, typ reflect2.Type) codecore.IDecoder { arrayType := typ.(*reflect2.UnsafeArrayType) decoder := DecoderOfType(ctx.Append("[arrayElem]"), arrayType.Elem()) - return &arrayDecoder{ctx.ICodec, arrayType, decoder} + return &arrayDecoder{arrayType, decoder} } -func encoderOfArray(ctx *core.Ctx, typ reflect2.Type) core.IEncoder { +func encoderOfArray(ctx *codecore.Ctx, typ reflect2.Type) codecore.IEncoder { arrayType := typ.(*reflect2.UnsafeArrayType) if arrayType.Len() == 0 { return &emptyArrayEncoder{} } encoder := EncoderOfType(ctx.Append("[arrayElem]"), arrayType.Elem()) - return &arrayEncoder{ctx.ICodec, arrayType, encoder} + return &arrayEncoder{arrayType, encoder} } //array------------------------------------------------------------------------------------------------------------------------------- type arrayEncoder struct { - codec core.ICodec arrayType *reflect2.UnsafeArrayType - elemEncoder core.IEncoder + elemEncoder codecore.IEncoder } func (codec *arrayEncoder) GetType() reflect.Kind { return reflect.Array } -func (this *arrayEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) { +func (this *arrayEncoder) Encode(ptr unsafe.Pointer, stream codecore.IWriter) { stream.WriteArrayStart() elemPtr := unsafe.Pointer(ptr) this.elemEncoder.Encode(elemPtr, stream) @@ -57,32 +56,30 @@ func (this *arrayEncoder) IsEmpty(ptr unsafe.Pointer) bool { } //编码对象到json数组 -func (this *arrayEncoder) EncodeToSliceJson(ptr unsafe.Pointer) (ret []string, err error) { +func (this *arrayEncoder) EncodeToSliceJson(ptr unsafe.Pointer, w codecore.IWriter) (ret []string, err error) { ret = make([]string, this.arrayType.Len()) - stream := this.codec.BorrowStream() for i := 1; i < this.arrayType.Len(); i++ { elemPtr := this.arrayType.UnsafeGetIndex(ptr, i) - this.elemEncoder.Encode(elemPtr, stream) - if stream.Error() != nil && stream.Error() != io.EOF { - err = stream.Error() + this.elemEncoder.Encode(elemPtr, w) + if w.Error() != nil && w.Error() != io.EOF { + err = w.Error() return } - ret[i] = BytesToString(stream.Buffer()) - stream.Reset(512) + ret[i] = BytesToString(w.Buffer()) + w.Reset() } return } type arrayDecoder struct { - codec core.ICodec arrayType *reflect2.UnsafeArrayType - elemDecoder core.IDecoder + elemDecoder codecore.IDecoder } func (codec *arrayDecoder) GetType() reflect.Kind { return reflect.Array } -func (this *arrayDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) { +func (this *arrayDecoder) Decode(ptr unsafe.Pointer, extra codecore.IReader) { arrayType := this.arrayType if extra.ReadNil() { return @@ -110,20 +107,19 @@ func (this *arrayDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) { } } -func (this *arrayDecoder) DecodeForSliceJson(ptr unsafe.Pointer, data []string) (err error) { +func (this *arrayDecoder) DecodeForSliceJson(ptr unsafe.Pointer, r codecore.IReader, data []string) (err error) { arrayType := this.arrayType if data == nil { err = errors.New("extra is nil") return } - extra := this.codec.BorrowExtractor([]byte{}) arrayType.UnsafeGetIndex(ptr, len(data)) for i, v := range data { elemPtr := arrayType.UnsafeGetIndex(ptr, i) - extra.ResetBytes(StringToBytes(v)) - this.elemDecoder.Decode(elemPtr, extra) - if extra.Error() != nil && extra.Error() != io.EOF { - err = extra.Error() + r.ResetBytes(StringToBytes(v)) + this.elemDecoder.Decode(elemPtr, r) + if r.Error() != nil && r.Error() != io.EOF { + err = r.Error() return } } @@ -136,7 +132,7 @@ func (this *emptyArrayEncoder) GetType() reflect.Kind { return reflect.Array } -func (this *emptyArrayEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) { +func (this *emptyArrayEncoder) Encode(ptr unsafe.Pointer, stream codecore.IWriter) { stream.WriteEmptyArray() } diff --git a/lego/sys/codec/factory/factory_interface.go b/lego/utils/codec/factory/factory_interface.go similarity index 91% rename from lego/sys/codec/factory/factory_interface.go rename to lego/utils/codec/factory/factory_interface.go index d9e446285..167100d36 100644 --- a/lego/sys/codec/factory/factory_interface.go +++ b/lego/utils/codec/factory/factory_interface.go @@ -5,7 +5,7 @@ import ( "reflect" "unsafe" - "go_dreamfactory/lego/sys/codec/core" + "go_dreamfactory/lego/utils/codec/codecore" "github.com/modern-go/reflect2" ) @@ -17,7 +17,7 @@ type dynamicEncoder struct { func (codec *dynamicEncoder) GetType() reflect.Kind { return reflect.Interface } -func (encoder *dynamicEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) { +func (encoder *dynamicEncoder) Encode(ptr unsafe.Pointer, stream codecore.IWriter) { obj := encoder.valType.UnsafeIndirect(ptr) stream.WriteVal(obj) } @@ -32,7 +32,7 @@ type efaceDecoder struct { func (codec *efaceDecoder) GetType() reflect.Kind { return reflect.Interface } -func (decoder *efaceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) { +func (decoder *efaceDecoder) Decode(ptr unsafe.Pointer, extra codecore.IReader) { pObj := (*interface{})(ptr) obj := *pObj if obj == nil { @@ -46,7 +46,7 @@ func (decoder *efaceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) { } ptrType := typ.(*reflect2.UnsafePtrType) ptrElemType := ptrType.Elem() - if extra.WhatIsNext() == core.NilValue { + if extra.WhatIsNext() == codecore.NilValue { if ptrElemType.Kind() != reflect.Ptr { extra.ReadNil() *pObj = nil @@ -69,7 +69,7 @@ type ifaceDecoder struct { func (codec *ifaceDecoder) GetType() reflect.Kind { return reflect.Interface } -func (decoder *ifaceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) { +func (decoder *ifaceDecoder) Decode(ptr unsafe.Pointer, extra codecore.IReader) { if extra.ReadNil() { decoder.valType.UnsafeSet(ptr, decoder.valType.UnsafeNew()) return diff --git a/lego/sys/codec/factory/factory_map.go b/lego/utils/codec/factory/factory_map.go similarity index 66% rename from lego/sys/codec/factory/factory_map.go rename to lego/utils/codec/factory/factory_map.go index 017249cb0..fe70437bb 100644 --- a/lego/sys/codec/factory/factory_map.go +++ b/lego/utils/codec/factory/factory_map.go @@ -4,19 +4,19 @@ import ( "fmt" "io" "reflect" + "sort" "unsafe" - "go_dreamfactory/lego/sys/codec/core" + "go_dreamfactory/lego/utils/codec/codecore" "github.com/modern-go/reflect2" ) -func decoderOfMap(ctx *core.Ctx, typ reflect2.Type) core.IDecoder { +func decoderOfMap(ctx *codecore.Ctx, typ reflect2.Type) codecore.IDecoder { mapType := typ.(*reflect2.UnsafeMapType) keyDecoder := decoderOfMapKey(ctx.Append("[mapKey]"), mapType.Key()) elemDecoder := DecoderOfType(ctx.Append("[mapElem]"), mapType.Elem()) return &mapDecoder{ - codec: ctx.ICodec, mapType: mapType, keyType: mapType.Key(), elemType: mapType.Elem(), @@ -25,17 +25,23 @@ func decoderOfMap(ctx *core.Ctx, typ reflect2.Type) core.IDecoder { } } -func encoderOfMap(ctx *core.Ctx, typ reflect2.Type) core.IEncoder { +func encoderOfMap(ctx *codecore.Ctx, typ reflect2.Type) codecore.IEncoder { mapType := typ.(*reflect2.UnsafeMapType) + if ctx.Config.SortMapKeys { + return &sortKeysMapEncoder{ + mapType: mapType, + keyEncoder: encoderOfMapKey(ctx.Append("[mapKey]"), mapType.Key()), + elemEncoder: EncoderOfType(ctx.Append("[mapElem]"), mapType.Elem()), + } + } return &mapEncoder{ - codec: ctx.ICodec, mapType: mapType, keyEncoder: encoderOfMapKey(ctx.Append("[mapKey]"), mapType.Key()), elemEncoder: EncoderOfType(ctx.Append("[mapElem]"), mapType.Elem()), } } -func decoderOfMapKey(ctx *core.Ctx, typ reflect2.Type) core.IDecoder { +func decoderOfMapKey(ctx *codecore.Ctx, typ reflect2.Type) codecore.IDecoder { switch typ.Kind() { case reflect.String: return DecoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String)) @@ -54,7 +60,7 @@ func decoderOfMapKey(ctx *core.Ctx, typ reflect2.Type) core.IDecoder { } } -func encoderOfMapKey(ctx *core.Ctx, typ reflect2.Type) core.IEncoder { +func encoderOfMapKey(ctx *codecore.Ctx, typ reflect2.Type) codecore.IEncoder { switch typ.Kind() { case reflect.String: return EncoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String)) @@ -77,17 +83,72 @@ func encoderOfMapKey(ctx *core.Ctx, typ reflect2.Type) core.IEncoder { } //Map-------------------------------------------------------------------------------------------------------------------------------------- -type mapEncoder struct { - codec core.ICodec +type sortKeysMapEncoder struct { mapType *reflect2.UnsafeMapType - keyEncoder core.IEncoder - elemEncoder core.IEncoder + keyEncoder codecore.IEncoder + elemEncoder codecore.IEncoder +} + +func (this *sortKeysMapEncoder) GetType() reflect.Kind { + return reflect.Map +} +func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, w codecore.IWriter) { + if *(*unsafe.Pointer)(ptr) == nil { + w.WriteNil() + return + } + w.WriteObjectStart() + mapIter := encoder.mapType.UnsafeIterate(ptr) + subStream := w.GetWriter() + subIter := w.GetReader(nil) + keyValues := encodedKeyValues{} + for mapIter.HasNext() { + key, elem := mapIter.UnsafeNext() + subStreamIndex := subStream.Buffered() + encoder.keyEncoder.Encode(key, subStream) + if subStream.Error() != nil && subStream.Error() != io.EOF && w.Error() == nil { + w.SetErr(subStream.Error()) + } + encodedKey := subStream.Buffer()[subStreamIndex:] + subIter.ResetBytes(encodedKey) + decodedKey := subIter.ReadString() + subStream.WriteKVSplit() + encoder.elemEncoder.Encode(elem, subStream) + keyValues = append(keyValues, encodedKV{ + key: decodedKey, + keyValue: subStream.Buffer()[subStreamIndex:], + }) + } + sort.Sort(keyValues) + for i, keyValue := range keyValues { + if i != 0 { + w.WriteMemberSplit() + } + w.WriteBytes(keyValue.keyValue) + } + if subStream.Error() != nil && w.Error() == nil { + w.SetErr(subStream.Error()) + } + w.WriteObjectEnd() + w.PutWriter(subStream) + w.PutReader(subIter) +} + +func (encoder *sortKeysMapEncoder) IsEmpty(ptr unsafe.Pointer) bool { + iter := encoder.mapType.UnsafeIterate(ptr) + return !iter.HasNext() +} + +type mapEncoder struct { + mapType *reflect2.UnsafeMapType + keyEncoder codecore.IEncoder + elemEncoder codecore.IEncoder } func (this *mapEncoder) GetType() reflect.Kind { return reflect.Map } -func (this *mapEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) { +func (this *mapEncoder) Encode(ptr unsafe.Pointer, stream codecore.IWriter) { if *(*unsafe.Pointer)(ptr) == nil { stream.WriteNil() return @@ -106,14 +167,17 @@ func (this *mapEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) { stream.WriteObjectEnd() } -func (this *mapEncoder) EncodeToMapJson(ptr unsafe.Pointer) (ret map[string]string, err error) { +func (this *mapEncoder) EncodeToMapJson(ptr unsafe.Pointer, w codecore.IWriter) (ret map[string]string, err error) { ret = make(map[string]string) var ( k, v string ) - - keystream := this.codec.BorrowStream() - elemstream := this.codec.BorrowStream() + keystream := w.GetWriter() + elemstream := w.GetWriter() + defer func() { + w.PutWriter(keystream) + w.PutWriter(elemstream) + }() iter := this.mapType.UnsafeIterate(ptr) for i := 0; iter.HasNext(); i++ { key, elem := iter.UnsafeNext() @@ -138,8 +202,8 @@ func (this *mapEncoder) EncodeToMapJson(ptr unsafe.Pointer) (ret map[string]stri v = *((*string)(elem)) } ret[k] = v - keystream.Reset(512) - elemstream.Reset(512) + keystream.Reset() + elemstream.Reset() } return } @@ -150,18 +214,17 @@ func (this *mapEncoder) IsEmpty(ptr unsafe.Pointer) bool { } type mapDecoder struct { - codec core.ICodec mapType *reflect2.UnsafeMapType keyType reflect2.Type elemType reflect2.Type - keyDecoder core.IDecoder - elemDecoder core.IDecoder + keyDecoder codecore.IDecoder + elemDecoder codecore.IDecoder } func (codec *mapDecoder) GetType() reflect.Kind { return reflect.Map } -func (this *mapDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) { +func (this *mapDecoder) Decode(ptr unsafe.Pointer, extra codecore.IReader) { mapType := this.mapType if extra.ReadNil() { *(*unsafe.Pointer)(ptr) = nil @@ -200,9 +263,13 @@ func (this *mapDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) { } //解码对象从MapJson 中 -func (this *mapDecoder) DecodeForMapJson(ptr unsafe.Pointer, extra map[string]string) (err error) { - keyext := this.codec.BorrowExtractor([]byte{}) - elemext := this.codec.BorrowExtractor([]byte{}) +func (this *mapDecoder) DecodeForMapJson(ptr unsafe.Pointer, r codecore.IReader, extra map[string]string) (err error) { + keyext := r.GetReader([]byte{}) + elemext := r.GetReader([]byte{}) + defer func() { + r.PutReader(keyext) + r.PutReader(keyext) + }() for k, v := range extra { key := this.keyType.UnsafeNew() if this.keyDecoder.GetType() != reflect.String { @@ -233,13 +300,13 @@ func (this *mapDecoder) DecodeForMapJson(ptr unsafe.Pointer, extra map[string]st //NumericMap------------------------------------------------------------------------------------------------------------------------------- type numericMapKeyDecoder struct { - decoder core.IDecoder + decoder codecore.IDecoder } func (this *numericMapKeyDecoder) GetType() reflect.Kind { return this.decoder.GetType() } -func (this *numericMapKeyDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) { +func (this *numericMapKeyDecoder) Decode(ptr unsafe.Pointer, extra codecore.IReader) { if !extra.ReadKeyStart() { return } @@ -250,13 +317,13 @@ func (this *numericMapKeyDecoder) Decode(ptr unsafe.Pointer, extra core.IExtract } type numericMapKeyEncoder struct { - encoder core.IEncoder + encoder codecore.IEncoder } func (this *numericMapKeyEncoder) GetType() reflect.Kind { return this.encoder.GetType() } -func (this *numericMapKeyEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) { +func (this *numericMapKeyEncoder) Encode(ptr unsafe.Pointer, stream codecore.IWriter) { stream.WriteKeyStart() this.encoder.Encode(ptr, stream) stream.WriteKeyEnd() @@ -268,7 +335,7 @@ func (encoder *numericMapKeyEncoder) IsEmpty(ptr unsafe.Pointer) bool { //------------------------------------------------------------------------------------------------------------------ type dynamicMapKeyEncoder struct { - ctx *core.Ctx + ctx *codecore.Ctx valType reflect2.Type } @@ -276,7 +343,7 @@ func (this *dynamicMapKeyEncoder) GetType() reflect.Kind { return reflect.Interface } -func (this *dynamicMapKeyEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) { +func (this *dynamicMapKeyEncoder) Encode(ptr unsafe.Pointer, stream codecore.IWriter) { obj := this.valType.UnsafeIndirect(ptr) encoderOfMapKey(this.ctx, reflect2.TypeOf(obj)).Encode(reflect2.PtrOf(obj), stream) } @@ -285,3 +352,14 @@ func (this *dynamicMapKeyEncoder) IsEmpty(ptr unsafe.Pointer) bool { obj := this.valType.UnsafeIndirect(ptr) return encoderOfMapKey(this.ctx, reflect2.TypeOf(obj)).IsEmpty(reflect2.PtrOf(obj)) } + +type encodedKeyValues []encodedKV + +type encodedKV struct { + key string + keyValue []byte +} + +func (sv encodedKeyValues) Len() int { return len(sv) } +func (sv encodedKeyValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] } +func (sv encodedKeyValues) Less(i, j int) bool { return sv[i].key < sv[j].key } diff --git a/lego/sys/codec/factory/factory_native.go b/lego/utils/codec/factory/factory_native.go similarity index 80% rename from lego/sys/codec/factory/factory_native.go rename to lego/utils/codec/factory/factory_native.go index c8cfdb0f1..6ca78b45b 100644 --- a/lego/sys/codec/factory/factory_native.go +++ b/lego/utils/codec/factory/factory_native.go @@ -5,14 +5,14 @@ import ( "strconv" "unsafe" - "go_dreamfactory/lego/sys/codec/core" + "go_dreamfactory/lego/utils/codec/codecore" "github.com/modern-go/reflect2" ) const ptrSize = 32 << uintptr(^uintptr(0)>>63) //计算int的大小 是32 还是64 -func createDecoderOfNative(ctx *core.Ctx, typ reflect2.Type) core.IDecoder { +func createDecoderOfNative(ctx *codecore.Ctx, typ reflect2.Type) codecore.IDecoder { typeName := typ.String() switch typ.Kind() { case reflect.String: @@ -103,7 +103,7 @@ func createDecoderOfNative(ctx *core.Ctx, typ reflect2.Type) core.IDecoder { return nil } -func createEncoderOfNative(ctx *core.Ctx, typ reflect2.Type) core.IEncoder { +func createEncoderOfNative(ctx *codecore.Ctx, typ reflect2.Type) codecore.IEncoder { typeName := typ.String() kind := typ.Kind() switch kind { @@ -201,11 +201,11 @@ type stringCodec struct { func (codec *stringCodec) GetType() reflect.Kind { return reflect.String } -func (codec *stringCodec) Decode(ptr unsafe.Pointer, extra core.IExtractor) { +func (codec *stringCodec) Decode(ptr unsafe.Pointer, extra codecore.IReader) { *((*string)(ptr)) = extra.ReadString() } -func (codec *stringCodec) Encode(ptr unsafe.Pointer, stream core.IStream) { +func (codec *stringCodec) Encode(ptr unsafe.Pointer, stream codecore.IWriter) { str := *((*string)(ptr)) stream.WriteString(str) } @@ -221,13 +221,13 @@ func (codec *int8Codec) GetType() reflect.Kind { return reflect.Int8 } -func (codec *int8Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) { +func (codec *int8Codec) Decode(ptr unsafe.Pointer, extra codecore.IReader) { if !extra.ReadNil() { *((*int8)(ptr)) = extra.ReadInt8() } } -func (codec *int8Codec) Encode(ptr unsafe.Pointer, stream core.IStream) { +func (codec *int8Codec) Encode(ptr unsafe.Pointer, stream codecore.IWriter) { stream.WriteInt8(*((*int8)(ptr))) } @@ -241,13 +241,13 @@ type int16Codec struct { func (codec *int16Codec) GetType() reflect.Kind { return reflect.Int16 } -func (codec *int16Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) { +func (codec *int16Codec) Decode(ptr unsafe.Pointer, extra codecore.IReader) { if !extra.ReadNil() { *((*int16)(ptr)) = extra.ReadInt16() } } -func (codec *int16Codec) Encode(ptr unsafe.Pointer, stream core.IStream) { +func (codec *int16Codec) Encode(ptr unsafe.Pointer, stream codecore.IWriter) { stream.WriteInt16(*((*int16)(ptr))) } @@ -261,13 +261,13 @@ type int32Codec struct { func (codec *int32Codec) GetType() reflect.Kind { return reflect.Int32 } -func (codec *int32Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) { +func (codec *int32Codec) Decode(ptr unsafe.Pointer, extra codecore.IReader) { if !extra.ReadNil() { *((*int32)(ptr)) = extra.ReadInt32() } } -func (codec *int32Codec) Encode(ptr unsafe.Pointer, stream core.IStream) { +func (codec *int32Codec) Encode(ptr unsafe.Pointer, stream codecore.IWriter) { stream.WriteInt32(*((*int32)(ptr))) } func (codec *int32Codec) IsEmpty(ptr unsafe.Pointer) bool { @@ -280,13 +280,13 @@ type int64Codec struct { func (codec *int64Codec) GetType() reflect.Kind { return reflect.Int64 } -func (codec *int64Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) { +func (codec *int64Codec) Decode(ptr unsafe.Pointer, extra codecore.IReader) { if !extra.ReadNil() { *((*int64)(ptr)) = extra.ReadInt64() } } -func (codec *int64Codec) Encode(ptr unsafe.Pointer, stream core.IStream) { +func (codec *int64Codec) Encode(ptr unsafe.Pointer, stream codecore.IWriter) { stream.WriteInt64(*((*int64)(ptr))) } @@ -300,13 +300,13 @@ type uint8Codec struct { func (codec *uint8Codec) GetType() reflect.Kind { return reflect.Uint8 } -func (codec *uint8Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) { +func (codec *uint8Codec) Decode(ptr unsafe.Pointer, extra codecore.IReader) { if !extra.ReadNil() { *((*uint8)(ptr)) = extra.ReadUint8() } } -func (codec *uint8Codec) Encode(ptr unsafe.Pointer, stream core.IStream) { +func (codec *uint8Codec) Encode(ptr unsafe.Pointer, stream codecore.IWriter) { stream.WriteUint8(*((*uint8)(ptr))) } @@ -320,13 +320,13 @@ type uint16Codec struct { func (codec *uint16Codec) GetType() reflect.Kind { return reflect.Uint16 } -func (codec *uint16Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) { +func (codec *uint16Codec) Decode(ptr unsafe.Pointer, extra codecore.IReader) { if !extra.ReadNil() { *((*uint16)(ptr)) = extra.ReadUint16() } } -func (codec *uint16Codec) Encode(ptr unsafe.Pointer, stream core.IStream) { +func (codec *uint16Codec) Encode(ptr unsafe.Pointer, stream codecore.IWriter) { stream.WriteUint16(*((*uint16)(ptr))) } @@ -340,13 +340,13 @@ type uint32Codec struct { func (codec *uint32Codec) GetType() reflect.Kind { return reflect.Uint32 } -func (codec *uint32Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) { +func (codec *uint32Codec) Decode(ptr unsafe.Pointer, extra codecore.IReader) { if !extra.ReadNil() { *((*uint32)(ptr)) = extra.ReadUint32() } } -func (codec *uint32Codec) Encode(ptr unsafe.Pointer, stream core.IStream) { +func (codec *uint32Codec) Encode(ptr unsafe.Pointer, stream codecore.IWriter) { stream.WriteUint32(*((*uint32)(ptr))) } func (codec *uint32Codec) IsEmpty(ptr unsafe.Pointer) bool { @@ -359,13 +359,13 @@ type uint64Codec struct { func (codec *uint64Codec) GetType() reflect.Kind { return reflect.Uint64 } -func (codec *uint64Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) { +func (codec *uint64Codec) Decode(ptr unsafe.Pointer, extra codecore.IReader) { if !extra.ReadNil() { *((*uint64)(ptr)) = extra.ReadUint64() } } -func (codec *uint64Codec) Encode(ptr unsafe.Pointer, stream core.IStream) { +func (codec *uint64Codec) Encode(ptr unsafe.Pointer, stream codecore.IWriter) { stream.WriteUint64(*((*uint64)(ptr))) } @@ -379,13 +379,13 @@ type float32Codec struct { func (codec *float32Codec) GetType() reflect.Kind { return reflect.Float32 } -func (codec *float32Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) { +func (codec *float32Codec) Decode(ptr unsafe.Pointer, extra codecore.IReader) { if !extra.ReadNil() { *((*float32)(ptr)) = extra.ReadFloat32() } } -func (codec *float32Codec) Encode(ptr unsafe.Pointer, stream core.IStream) { +func (codec *float32Codec) Encode(ptr unsafe.Pointer, stream codecore.IWriter) { stream.WriteFloat32(*((*float32)(ptr))) } @@ -399,13 +399,13 @@ type float64Codec struct { func (codec *float64Codec) GetType() reflect.Kind { return reflect.Float64 } -func (codec *float64Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) { +func (codec *float64Codec) Decode(ptr unsafe.Pointer, extra codecore.IReader) { if !extra.ReadNil() { *((*float64)(ptr)) = extra.ReadFloat64() } } -func (codec *float64Codec) Encode(ptr unsafe.Pointer, stream core.IStream) { +func (codec *float64Codec) Encode(ptr unsafe.Pointer, stream codecore.IWriter) { stream.WriteFloat64(*((*float64)(ptr))) } @@ -419,13 +419,13 @@ type boolCodec struct { func (codec *boolCodec) GetType() reflect.Kind { return reflect.Bool } -func (codec *boolCodec) Decode(ptr unsafe.Pointer, extra core.IExtractor) { +func (codec *boolCodec) Decode(ptr unsafe.Pointer, extra codecore.IReader) { if !extra.ReadNil() { *((*bool)(ptr)) = extra.ReadBool() } } -func (codec *boolCodec) Encode(ptr unsafe.Pointer, stream core.IStream) { +func (codec *boolCodec) Encode(ptr unsafe.Pointer, stream codecore.IWriter) { stream.WriteBool(*((*bool)(ptr))) } diff --git a/lego/sys/codec/factory/factory_optional.go b/lego/utils/codec/factory/factory_optional.go similarity index 79% rename from lego/sys/codec/factory/factory_optional.go rename to lego/utils/codec/factory/factory_optional.go index 558f7d500..c0f75fb02 100644 --- a/lego/sys/codec/factory/factory_optional.go +++ b/lego/utils/codec/factory/factory_optional.go @@ -5,19 +5,19 @@ import ( "reflect" "unsafe" - "go_dreamfactory/lego/sys/codec/core" + "go_dreamfactory/lego/utils/codec/codecore" "github.com/modern-go/reflect2" ) -func decoderOfOptional(ctx *core.Ctx, typ reflect2.Type) core.IDecoder { +func decoderOfOptional(ctx *codecore.Ctx, typ reflect2.Type) codecore.IDecoder { ptrType := typ.(*reflect2.UnsafePtrType) elemType := ptrType.Elem() decoder := DecoderOfType(ctx, elemType) return &OptionalDecoder{elemType, decoder} } -func encoderOfOptional(ctx *core.Ctx, typ reflect2.Type) core.IEncoder { +func encoderOfOptional(ctx *codecore.Ctx, typ reflect2.Type) codecore.IEncoder { ptrType := typ.(*reflect2.UnsafePtrType) elemType := ptrType.Elem() elemEncoder := EncoderOfType(ctx, elemType) @@ -28,13 +28,13 @@ func encoderOfOptional(ctx *core.Ctx, typ reflect2.Type) core.IEncoder { //Optional-------------------------------------------------------------------------------------------------------------------- type OptionalDecoder struct { ValueType reflect2.Type - ValueDecoder core.IDecoder + ValueDecoder codecore.IDecoder } func (this *OptionalDecoder) GetType() reflect.Kind { return this.ValueDecoder.GetType() } -func (this *OptionalDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) { +func (this *OptionalDecoder) Decode(ptr unsafe.Pointer, extra codecore.IReader) { if extra.ReadNil() { *((*unsafe.Pointer)(ptr)) = nil } else { @@ -48,23 +48,23 @@ func (this *OptionalDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) { } } -func (this *OptionalDecoder) DecodeForMapJson(ptr unsafe.Pointer, extra map[string]string) (err error) { - if decoderMapJson, ok := this.ValueDecoder.(core.IDecoderMapJson); !ok { +func (this *OptionalDecoder) DecodeForMapJson(ptr unsafe.Pointer, r codecore.IReader, extra map[string]string) (err error) { + if decoderMapJson, ok := this.ValueDecoder.(codecore.IDecoderMapJson); !ok { err = fmt.Errorf("encoder %T not support EncodeToMapJson", this.ValueDecoder) return } else { - return decoderMapJson.DecodeForMapJson(ptr, extra) + return decoderMapJson.DecodeForMapJson(ptr, r, extra) } } type OptionalEncoder struct { - ValueEncoder core.IEncoder + ValueEncoder codecore.IEncoder } func (this *OptionalEncoder) GetType() reflect.Kind { return this.ValueEncoder.GetType() } -func (this *OptionalEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) { +func (this *OptionalEncoder) Encode(ptr unsafe.Pointer, stream codecore.IWriter) { if *((*unsafe.Pointer)(ptr)) == nil { stream.WriteNil() } else { @@ -76,8 +76,8 @@ func (this *OptionalEncoder) IsEmpty(ptr unsafe.Pointer) bool { return *((*unsafe.Pointer)(ptr)) == nil } -func (this *OptionalEncoder) EncodeToMapJson(ptr unsafe.Pointer) (ret map[string]string, err error) { - if encoderMapJson, ok := this.ValueEncoder.(core.IEncoderMapJson); !ok { +func (this *OptionalEncoder) EncodeToMapJson(ptr unsafe.Pointer, w codecore.IWriter) (ret map[string]string, err error) { + if encoderMapJson, ok := this.ValueEncoder.(codecore.IEncoderMapJson); !ok { err = fmt.Errorf("encoder %T not support EncodeToMapJson", this.ValueEncoder) return } else { @@ -85,17 +85,17 @@ func (this *OptionalEncoder) EncodeToMapJson(ptr unsafe.Pointer) (ret map[string err = fmt.Errorf("encoder ptr is nil") return } else { - return encoderMapJson.EncodeToMapJson(*((*unsafe.Pointer)(ptr))) + return encoderMapJson.EncodeToMapJson(*((*unsafe.Pointer)(ptr)), w) } } } //reference-------------------------------------------------------------------------------------------------------------------- type referenceEncoder struct { - encoder core.IEncoder + encoder codecore.IEncoder } -func (this *referenceEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) { +func (this *referenceEncoder) Encode(ptr unsafe.Pointer, stream codecore.IWriter) { this.encoder.Encode(unsafe.Pointer(&ptr), stream) } @@ -104,23 +104,23 @@ func (this *referenceEncoder) IsEmpty(ptr unsafe.Pointer) bool { } type referenceDecoder struct { - decoder core.IDecoder + decoder codecore.IDecoder } -func (this *referenceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) { +func (this *referenceDecoder) Decode(ptr unsafe.Pointer, extra codecore.IReader) { this.decoder.Decode(unsafe.Pointer(&ptr), extra) } //dereference-------------------------------------------------------------------------------------------------------------------- type dereferenceDecoder struct { valueType reflect2.Type - valueDecoder core.IDecoder + valueDecoder codecore.IDecoder } func (this *dereferenceDecoder) GetType() reflect.Kind { return this.valueDecoder.GetType() } -func (this *dereferenceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) { +func (this *dereferenceDecoder) Decode(ptr unsafe.Pointer, extra codecore.IReader) { if *((*unsafe.Pointer)(ptr)) == nil { newPtr := this.valueType.UnsafeNew() this.valueDecoder.Decode(newPtr, extra) @@ -131,13 +131,13 @@ func (this *dereferenceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor } type dereferenceEncoder struct { - ValueEncoder core.IEncoder + ValueEncoder codecore.IEncoder } func (this *dereferenceEncoder) GetType() reflect.Kind { return this.ValueEncoder.GetType() } -func (this *dereferenceEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) { +func (this *dereferenceEncoder) Encode(ptr unsafe.Pointer, stream codecore.IWriter) { if *((*unsafe.Pointer)(ptr)) == nil { stream.WriteNil() } else { @@ -158,7 +158,7 @@ func (this *dereferenceEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool { if deReferenced == nil { return true } - isEmbeddedPtrNil, converted := this.ValueEncoder.(core.IsEmbeddedPtrNil) + isEmbeddedPtrNil, converted := this.ValueEncoder.(codecore.IsEmbeddedPtrNil) if !converted { return false } diff --git a/lego/sys/codec/factory/factory_slice.go b/lego/utils/codec/factory/factory_slice.go similarity index 71% rename from lego/sys/codec/factory/factory_slice.go rename to lego/utils/codec/factory/factory_slice.go index 291c59e78..c093efdcd 100644 --- a/lego/sys/codec/factory/factory_slice.go +++ b/lego/utils/codec/factory/factory_slice.go @@ -7,32 +7,31 @@ import ( "reflect" "unsafe" - "go_dreamfactory/lego/sys/codec/core" + "go_dreamfactory/lego/utils/codec/codecore" "github.com/modern-go/reflect2" ) -func decoderOfSlice(ctx *core.Ctx, typ reflect2.Type) core.IDecoder { +func decoderOfSlice(ctx *codecore.Ctx, typ reflect2.Type) codecore.IDecoder { sliceType := typ.(*reflect2.UnsafeSliceType) decoder := DecoderOfType(ctx.Append("[sliceElem]"), sliceType.Elem()) - return &sliceDecoder{ctx.ICodec, sliceType, decoder} + return &sliceDecoder{sliceType, decoder} } -func encoderOfSlice(ctx *core.Ctx, typ reflect2.Type) core.IEncoder { +func encoderOfSlice(ctx *codecore.Ctx, typ reflect2.Type) codecore.IEncoder { sliceType := typ.(*reflect2.UnsafeSliceType) encoder := EncoderOfType(ctx.Append("[sliceElem]"), sliceType.Elem()) - return &sliceEncoder{ctx.ICodec, sliceType, encoder} + return &sliceEncoder{sliceType, encoder} } type sliceEncoder struct { - codec core.ICodec sliceType *reflect2.UnsafeSliceType - elemEncoder core.IEncoder + elemEncoder codecore.IEncoder } func (codec *sliceEncoder) GetType() reflect.Kind { return reflect.Slice } -func (this *sliceEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) { +func (this *sliceEncoder) Encode(ptr unsafe.Pointer, stream codecore.IWriter) { if this.sliceType.UnsafeIsNil(ptr) { stream.WriteNil() return @@ -60,7 +59,7 @@ func (this *sliceEncoder) IsEmpty(ptr unsafe.Pointer) bool { } //编码对象到json数组 -func (this *sliceEncoder) EncodeToSliceJson(ptr unsafe.Pointer) (ret []string, err error) { +func (this *sliceEncoder) EncodeToSliceJson(ptr unsafe.Pointer, w codecore.IWriter) (ret []string, err error) { if this.sliceType.UnsafeIsNil(ptr) { err = errors.New("val is nil") return @@ -70,30 +69,28 @@ func (this *sliceEncoder) EncodeToSliceJson(ptr unsafe.Pointer) (ret []string, e if length == 0 { return } - stream := this.codec.BorrowStream() for i := 1; i < length; i++ { elemPtr := this.sliceType.UnsafeGetIndex(ptr, i) - this.elemEncoder.Encode(elemPtr, stream) - if stream.Error() != nil && stream.Error() != io.EOF { - err = stream.Error() + this.elemEncoder.Encode(elemPtr, w) + if w.Error() != nil && w.Error() != io.EOF { + err = w.Error() return } - ret[i] = BytesToString(stream.Buffer()) - stream.Reset(512) + ret[i] = BytesToString(w.Buffer()) + w.Reset() } return } type sliceDecoder struct { - codec core.ICodec sliceType *reflect2.UnsafeSliceType - elemDecoder core.IDecoder + elemDecoder codecore.IDecoder } func (codec *sliceDecoder) GetType() reflect.Kind { return reflect.Slice } -func (this *sliceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) { +func (this *sliceDecoder) Decode(ptr unsafe.Pointer, extra codecore.IReader) { sliceType := this.sliceType if extra.ReadNil() { sliceType.UnsafeSetNil(ptr) @@ -125,20 +122,19 @@ func (this *sliceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) { } } -func (this *sliceDecoder) DecodeForSliceJson(ptr unsafe.Pointer, data []string) (err error) { +func (this *sliceDecoder) DecodeForSliceJson(ptr unsafe.Pointer, r codecore.IReader, data []string) (err error) { sliceType := this.sliceType if data == nil { err = errors.New("extra is nil") return } - extra := this.codec.BorrowExtractor([]byte{}) sliceType.UnsafeGrow(ptr, len(data)) for i, v := range data { elemPtr := sliceType.UnsafeGetIndex(ptr, i) - extra.ResetBytes(StringToBytes(v)) - this.elemDecoder.Decode(elemPtr, extra) - if extra.Error() != nil && extra.Error() != io.EOF { - err = extra.Error() + r.ResetBytes(StringToBytes(v)) + this.elemDecoder.Decode(elemPtr, r) + if r.Error() != nil && r.Error() != io.EOF { + err = r.Error() return } } diff --git a/lego/sys/codec/factory/factory_struct.go b/lego/utils/codec/factory/factory_struct.go similarity index 69% rename from lego/sys/codec/factory/factory_struct.go rename to lego/utils/codec/factory/factory_struct.go index a07ae27ce..e2999283d 100644 --- a/lego/sys/codec/factory/factory_struct.go +++ b/lego/utils/codec/factory/factory_struct.go @@ -10,7 +10,7 @@ import ( "unicode" "unsafe" - "go_dreamfactory/lego/sys/codec/core" + "go_dreamfactory/lego/utils/codec/codecore" "github.com/modern-go/reflect2" ) @@ -25,11 +25,11 @@ type Binding struct { Field reflect2.StructField FromNames []string ToNames []string - Encoder core.IEncoder - Decoder core.IDecoder + Encoder codecore.IEncoder + Decoder codecore.IDecoder } -func encoderOfStruct(ctx *core.Ctx, typ reflect2.Type) core.IEncoder { +func encoderOfStruct(ctx *codecore.Ctx, typ reflect2.Type) codecore.IEncoder { type bindingTo struct { binding *Binding toName string @@ -47,7 +47,7 @@ func encoderOfStruct(ctx *core.Ctx, typ reflect2.Type) core.IEncoder { if old.toName != toName { continue } - old.ignored, new.ignored = resolveConflictBinding(ctx.Options(), old.binding, new.binding) + old.ignored, new.ignored = resolveConflictBinding(ctx.Config, old.binding, new.binding) } orderedBindings = append(orderedBindings, new) } @@ -64,10 +64,10 @@ func encoderOfStruct(ctx *core.Ctx, typ reflect2.Type) core.IEncoder { }) } } - return &structEncoder{ctx.ICodec, typ, finalOrderedFields} + return &structEncoder{typ, finalOrderedFields} } -func decoderOfStruct(ctx *core.Ctx, typ reflect2.Type) core.IDecoder { +func decoderOfStruct(ctx *codecore.Ctx, typ reflect2.Type) codecore.IDecoder { bindings := map[string]*Binding{} structDescriptor := describeStruct(ctx, typ) for _, binding := range structDescriptor.Fields { @@ -77,7 +77,7 @@ func decoderOfStruct(ctx *core.Ctx, typ reflect2.Type) core.IDecoder { bindings[fromName] = binding continue } - ignoreOld, ignoreNew := resolveConflictBinding(ctx.Options(), old, binding) + ignoreOld, ignoreNew := resolveConflictBinding(ctx.Config, old, binding) if ignoreOld { delete(bindings, fromName) } @@ -91,25 +91,25 @@ func decoderOfStruct(ctx *core.Ctx, typ reflect2.Type) core.IDecoder { fields[k] = binding.Decoder.(*structFieldDecoder) } - if !ctx.Options().CaseSensitive { + if !ctx.Config.CaseSensitive { for k, binding := range bindings { if _, found := fields[strings.ToLower(k)]; !found { fields[strings.ToLower(k)] = binding.Decoder.(*structFieldDecoder) } } } - return createStructDecoder(ctx.ICodec, typ, fields) + return &structDecoder{ctx.Config, typ, fields} } //结构第编辑码构建 -func describeStruct(ctx *core.Ctx, typ reflect2.Type) *StructDescriptor { +func describeStruct(ctx *codecore.Ctx, typ reflect2.Type) *StructDescriptor { structType := typ.(*reflect2.UnsafeStructType) embeddedBindings := []*Binding{} bindings := []*Binding{} for i := 0; i < structType.NumField(); i++ { field := structType.Field(i) - tag, hastag := field.Tag().Lookup(ctx.Options().TagKey) - if ctx.Options().OnlyTaggedField && !hastag && !field.Anonymous() { + tag, hastag := field.Tag().Lookup(ctx.Config.TagKey) + if ctx.Config.OnlyTaggedField && !hastag && !field.Anonymous() { continue } if tag == "-" || field.Name() == "_" { @@ -160,22 +160,22 @@ func describeStruct(ctx *core.Ctx, typ reflect2.Type) *StructDescriptor { return createStructDescriptor(ctx, typ, bindings, embeddedBindings) } -func createStructDescriptor(ctx *core.Ctx, typ reflect2.Type, bindings []*Binding, embeddedBindings []*Binding) *StructDescriptor { +func createStructDescriptor(ctx *codecore.Ctx, typ reflect2.Type, bindings []*Binding, embeddedBindings []*Binding) *StructDescriptor { structDescriptor := &StructDescriptor{ Type: typ, Fields: bindings, } - processTags(structDescriptor, ctx.ICodec) + processTags(structDescriptor, ctx.Config) allBindings := sortableBindings(append(embeddedBindings, structDescriptor.Fields...)) sort.Sort(allBindings) structDescriptor.Fields = allBindings return structDescriptor } -func processTags(structDescriptor *StructDescriptor, codec core.ICodec) { +func processTags(structDescriptor *StructDescriptor, config *codecore.Config) { for _, binding := range structDescriptor.Fields { shouldOmitEmpty := false - tagParts := strings.Split(binding.Field.Tag().Get(codec.Options().TagKey), ",") + tagParts := strings.Split(binding.Field.Tag().Get(config.TagKey), ",") for _, tagPart := range tagParts[1:] { if tagPart == "omitempty" { shouldOmitEmpty = true @@ -206,17 +206,9 @@ func calcFieldNames(originalFieldName string, tagProvidedFieldName string, whole return fieldNames } -func createStructDecoder(codec core.ICodec, typ reflect2.Type, fields map[string]*structFieldDecoder) core.IDecoder { - if codec.Options().DisallowUnknownFields { - return &structDecoder{typ: typ, fields: fields, disallowUnknownFields: true} - } else { - return &structDecoder{codec, typ, fields, false} - } -} - -func resolveConflictBinding(opt *core.Options, old, new *Binding) (ignoreOld, ignoreNew bool) { - newTagged := new.Field.Tag().Get(opt.TagKey) != "" - oldTagged := old.Field.Tag().Get(opt.TagKey) != "" +func resolveConflictBinding(config *codecore.Config, old, new *Binding) (ignoreOld, ignoreNew bool) { + newTagged := new.Field.Tag().Get(config.TagKey) != "" + oldTagged := old.Field.Tag().Get(config.TagKey) != "" if newTagged { if oldTagged { if len(old.levels) > len(new.levels) { @@ -245,7 +237,6 @@ func resolveConflictBinding(opt *core.Options, old, new *Binding) (ignoreOld, ig //结构对象 编解码----------------------------------------------------------------------------------------------------------------------- type structEncoder struct { - codec core.ICodec typ reflect2.Type fields []structFieldTo } @@ -253,7 +244,7 @@ type structEncoder struct { func (codec *structEncoder) GetType() reflect.Kind { return reflect.Struct } -func (this *structEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) { +func (this *structEncoder) Encode(ptr unsafe.Pointer, stream codecore.IWriter) { stream.WriteObjectStart() isNotFirst := false for _, field := range this.fields { @@ -276,9 +267,8 @@ func (this *structEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) { } } -func (this *structEncoder) EncodeToMapJson(ptr unsafe.Pointer) (ret map[string]string, err error) { +func (this *structEncoder) EncodeToMapJson(ptr unsafe.Pointer, w codecore.IWriter) (ret map[string]string, err error) { ret = make(map[string]string) - stream := this.codec.BorrowStream() for _, field := range this.fields { if field.encoder.omitempty && field.encoder.IsEmpty(ptr) { continue @@ -286,13 +276,13 @@ func (this *structEncoder) EncodeToMapJson(ptr unsafe.Pointer) (ret map[string]s if field.encoder.IsEmbeddedPtrNil(ptr) { continue } - stream.Reset(512) - field.encoder.Encode(ptr, stream) - if stream.Error() != nil && stream.Error() != io.EOF { - err = stream.Error() + w.Reset() + field.encoder.Encode(ptr, w) + if w.Error() != nil && w.Error() != io.EOF { + err = w.Error() return } - ret[field.toName] = BytesToString(stream.Buffer()) + ret[field.toName] = BytesToString(w.Buffer()) } return } @@ -302,68 +292,67 @@ func (this *structEncoder) IsEmpty(ptr unsafe.Pointer) bool { } type structDecoder struct { - codec core.ICodec - typ reflect2.Type - fields map[string]*structFieldDecoder - disallowUnknownFields bool + config *codecore.Config + typ reflect2.Type + fields map[string]*structFieldDecoder } func (codec *structDecoder) GetType() reflect.Kind { return reflect.Struct } -func (this *structDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) { - if !extra.ReadObjectStart() { +func (this *structDecoder) Decode(ptr unsafe.Pointer, r codecore.IReader) { + if !r.ReadObjectStart() { return } - this.decodeField(ptr, extra) - for extra.ReadMemberSplit() { - this.decodeField(ptr, extra) + this.decodeField(ptr, r) + for r.ReadMemberSplit() { + this.decodeField(ptr, r) } - if extra.Error() != nil && extra.Error() != io.EOF && len(this.typ.Type1().Name()) != 0 { - extra.SetErr(fmt.Errorf("%v.%s", this.typ, extra.Error().Error())) + if r.Error() != nil && r.Error() != io.EOF && len(this.typ.Type1().Name()) != 0 { + r.SetErr(fmt.Errorf("%v.%s", this.typ, r.Error().Error())) } - extra.ReadObjectEnd() + r.ReadObjectEnd() } -func (this *structDecoder) decodeField(ptr unsafe.Pointer, extra core.IExtractor) { +func (this *structDecoder) decodeField(ptr unsafe.Pointer, r codecore.IReader) { var field string var fieldDecoder *structFieldDecoder - field = extra.ReadString() + field = r.ReadString() fieldDecoder = this.fields[field] - if fieldDecoder == nil && !this.codec.Options().CaseSensitive { + if fieldDecoder == nil && !this.config.CaseSensitive { fieldDecoder = this.fields[strings.ToLower(field)] } if fieldDecoder == nil { - if this.disallowUnknownFields { + if this.config.DisallowUnknownFields { msg := "found unknown field: " + field - extra.SetErr(fmt.Errorf("decodeField %s", msg)) + r.SetErr(fmt.Errorf("decodeField %s", msg)) return } - if !extra.ReadKVSplit() { + if !r.ReadKVSplit() { return } - extra.Skip() //跳过一个数据单元 + r.Skip() //跳过一个数据单元 return } - if !extra.ReadKVSplit() { + if !r.ReadKVSplit() { return } - fieldDecoder.Decode(ptr, extra) + fieldDecoder.Decode(ptr, r) } //解码对象从MapJson 中 -func (this *structDecoder) DecodeForMapJson(ptr unsafe.Pointer, extra map[string]string) (err error) { +func (this *structDecoder) DecodeForMapJson(ptr unsafe.Pointer, r codecore.IReader, extra map[string]string) (err error) { var fieldDecoder *structFieldDecoder - ext := this.codec.BorrowExtractor([]byte{}) + ext := r.GetReader([]byte{}) for k, v := range extra { fieldDecoder = this.fields[k] - if fieldDecoder == nil && !this.codec.Options().CaseSensitive { + if fieldDecoder == nil && !this.config.CaseSensitive { fieldDecoder = this.fields[strings.ToLower(k)] } if fieldDecoder == nil { - if this.disallowUnknownFields { + if this.config.DisallowUnknownFields { err = errors.New("found unknown field: " + k) return } @@ -386,18 +375,18 @@ type structFieldTo struct { } type structFieldEncoder struct { field reflect2.StructField - fieldEncoder core.IEncoder + fieldEncoder codecore.IEncoder omitempty bool } func (this *structFieldEncoder) GetType() reflect.Kind { return this.fieldEncoder.GetType() } -func (encoder *structFieldEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) { +func (encoder *structFieldEncoder) Encode(ptr unsafe.Pointer, w codecore.IWriter) { fieldPtr := encoder.field.UnsafeGet(ptr) - encoder.fieldEncoder.Encode(fieldPtr, stream) - if stream.Error() != nil && stream.Error() != io.EOF { - stream.SetErr(fmt.Errorf("%s: %s", encoder.field.Name(), stream.Error().Error())) + encoder.fieldEncoder.Encode(fieldPtr, w) + if w.Error() != nil && w.Error() != io.EOF { + w.SetErr(fmt.Errorf("%s: %s", encoder.field.Name(), w.Error().Error())) } } @@ -407,7 +396,7 @@ func (encoder *structFieldEncoder) IsEmpty(ptr unsafe.Pointer) bool { } func (encoder *structFieldEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool { - isEmbeddedPtrNil, converted := encoder.fieldEncoder.(core.IsEmbeddedPtrNil) + isEmbeddedPtrNil, converted := encoder.fieldEncoder.(codecore.IsEmbeddedPtrNil) if !converted { return false } @@ -417,17 +406,17 @@ func (encoder *structFieldEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool { type structFieldDecoder struct { field reflect2.StructField - fieldDecoder core.IDecoder + fieldDecoder codecore.IDecoder } func (this *structFieldDecoder) GetType() reflect.Kind { return this.fieldDecoder.GetType() } -func (decoder *structFieldDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) { +func (decoder *structFieldDecoder) Decode(ptr unsafe.Pointer, r codecore.IReader) { fieldPtr := decoder.field.UnsafeGet(ptr) - decoder.fieldDecoder.Decode(fieldPtr, extra) - if extra.Error() != nil && extra.Error() != io.EOF { - extra.SetErr(fmt.Errorf("%s: %s", decoder.field.Name(), extra.Error().Error())) + decoder.fieldDecoder.Decode(fieldPtr, r) + if r.Error() != nil && r.Error() != io.EOF { + r.SetErr(fmt.Errorf("%s: %s", decoder.field.Name(), r.Error().Error())) } } @@ -438,8 +427,8 @@ type emptyStructEncoder struct { func (codec *emptyStructEncoder) GetType() reflect.Kind { return reflect.Struct } -func (encoder *emptyStructEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) { - stream.WriteEmptyObject() +func (encoder *emptyStructEncoder) Encode(ptr unsafe.Pointer, w codecore.IWriter) { + w.WriteEmptyObject() } func (encoder *emptyStructEncoder) IsEmpty(ptr unsafe.Pointer) bool { diff --git a/lego/utils/codec/json/core.go b/lego/utils/codec/json/core.go new file mode 100644 index 000000000..464216883 --- /dev/null +++ b/lego/utils/codec/json/core.go @@ -0,0 +1,221 @@ +package json + +import ( + "errors" + "fmt" + "reflect" + "sync" + + "go_dreamfactory/lego/utils/codec" + "go_dreamfactory/lego/utils/codec/codecore" + + "github.com/modern-go/reflect2" +) + +const defsize = 512 + +var writerPool = &sync.Pool{ + New: func() interface{} { + return &JsonWriter{ + buf: make([]byte, 0, defsize), + err: nil, + indention: 0, + } + }, +} + +func GetReader(buf []byte) codecore.IReader { + reader := readerPool.Get().(codecore.IReader) + reader.ResetBytes(buf) + return reader +} + +func PutReader(r codecore.IReader) { + readerPool.Put(r) +} + +var readerPool = &sync.Pool{ + New: func() interface{} { + return &JsonReader{ + buf: nil, + head: 0, + tail: 0, + depth: 0, + err: nil, + } + }, +} + +func GetWriter() codecore.IWriter { + writer := writerPool.Get().(codecore.IWriter) + return writer +} + +func PutWriter(w codecore.IWriter) { + writerPool.Put(w) +} + +const maxDepth = 10000 + +var hexDigits []byte +var valueTypes []codecore.ValueType + +func init() { + hexDigits = make([]byte, 256) + for i := 0; i < len(hexDigits); i++ { + hexDigits[i] = 255 + } + for i := '0'; i <= '9'; i++ { + hexDigits[i] = byte(i - '0') + } + for i := 'a'; i <= 'f'; i++ { + hexDigits[i] = byte((i - 'a') + 10) + } + for i := 'A'; i <= 'F'; i++ { + hexDigits[i] = byte((i - 'A') + 10) + } + valueTypes = make([]codecore.ValueType, 256) + for i := 0; i < len(valueTypes); i++ { + valueTypes[i] = codecore.InvalidValue + } + valueTypes['"'] = codecore.StringValue + valueTypes['-'] = codecore.NumberValue + valueTypes['0'] = codecore.NumberValue + valueTypes['1'] = codecore.NumberValue + valueTypes['2'] = codecore.NumberValue + valueTypes['3'] = codecore.NumberValue + valueTypes['4'] = codecore.NumberValue + valueTypes['5'] = codecore.NumberValue + valueTypes['6'] = codecore.NumberValue + valueTypes['7'] = codecore.NumberValue + valueTypes['8'] = codecore.NumberValue + valueTypes['9'] = codecore.NumberValue + valueTypes['t'] = codecore.BoolValue + valueTypes['f'] = codecore.BoolValue + valueTypes['n'] = codecore.NilValue + valueTypes['['] = codecore.ArrayValue + valueTypes['{'] = codecore.ObjectValue +} + +var defconf = &codecore.Config{ + SortMapKeys: true, + IndentionStep: 1, + OnlyTaggedField: false, + DisallowUnknownFields: false, + CaseSensitive: false, + TagKey: "json", +} + +func Marshal(val interface{}) (buf []byte, err error) { + writer := GetWriter() + defer PutWriter(writer) + writer.WriteVal(val) + if writer.Error() != nil { + return nil, writer.Error() + } + result := writer.Buffer() + copied := make([]byte, len(result)) + copy(copied, result) + return copied, nil +} + +func Unmarshal(data []byte, v interface{}) error { + extra := GetReader(data) + defer PutReader(extra) + extra.ReadVal(v) + return extra.Error() +} + +func MarshalMap(val interface{}) (ret map[string]string, err error) { + if nil == val { + err = errors.New("val is null") + return + } + cacheKey := reflect2.RTypeOf(val) + encoder := codec.GetEncoder(cacheKey) + if encoder == nil { + typ := reflect2.TypeOf(val) + encoder = codec.EncoderOf(typ, defconf) + } + if encoderMapJson, ok := encoder.(codecore.IEncoderMapJson); !ok { + err = fmt.Errorf("val type:%T not support MarshalMapJson", val) + } else { + w := GetWriter() + ret, err = encoderMapJson.EncodeToMapJson(reflect2.PtrOf(val), w) + PutWriter(w) + } + return +} + +func UnmarshalMap(data map[string]string, val interface{}) (err error) { + cacheKey := reflect2.RTypeOf(val) + decoder := codec.GetDecoder(cacheKey) + if decoder == nil { + typ := reflect2.TypeOf(val) + if typ == nil || typ.Kind() != reflect.Ptr { + err = errors.New("can only unmarshal into pointer") + return + } + decoder = codec.DecoderOf(typ, defconf) + } + ptr := reflect2.PtrOf(val) + if ptr == nil { + err = errors.New("can not read into nil pointer") + return + } + if decoderMapJson, ok := decoder.(codecore.IDecoderMapJson); !ok { + err = fmt.Errorf("val type:%T not support MarshalMapJson", val) + } else { + r := GetReader([]byte{}) + err = decoderMapJson.DecodeForMapJson(ptr, r, data) + PutReader(r) + } + return +} + +func MarshalSlice(val interface{}) (ret []string, err error) { + if nil == val { + err = errors.New("val is null") + return + } + cacheKey := reflect2.RTypeOf(val) + encoder := codec.GetEncoder(cacheKey) + if encoder == nil { + typ := reflect2.TypeOf(val) + encoder = codec.EncoderOf(typ, defconf) + } + if encoderMapJson, ok := encoder.(codecore.IEncoderSliceJson); !ok { + err = fmt.Errorf("val type:%T not support MarshalMapJson", val) + } else { + w := GetWriter() + ret, err = encoderMapJson.EncodeToSliceJson(reflect2.PtrOf(val), w) + w.PutWriter(w) + } + return +} + +func UnmarshalSlice(data []string, val interface{}) (err error) { + cacheKey := reflect2.RTypeOf(val) + decoder := codec.GetDecoder(cacheKey) + if decoder == nil { + typ := reflect2.TypeOf(val) + if typ == nil || typ.Kind() != reflect.Ptr { + err = errors.New("can only unmarshal into pointer") + return + } + decoder = codec.DecoderOf(typ, defconf) + } + ptr := reflect2.PtrOf(val) + if ptr == nil { + err = errors.New("can not read into nil pointer") + return + } + if decoderMapJson, ok := decoder.(codecore.IDecoderSliceJson); !ok { + err = fmt.Errorf("val type:%T not support UnmarshalSliceJson", val) + } else { + r := GetReader([]byte{}) + err = decoderMapJson.DecodeForSliceJson(ptr, r, data) + PutReader(r) + } + return +} diff --git a/lego/sys/codec/render/json_extractor.go b/lego/utils/codec/json/reader.go similarity index 80% rename from lego/sys/codec/render/json_extractor.go rename to lego/utils/codec/json/reader.go index f12bc59a2..d6388e2d8 100644 --- a/lego/sys/codec/render/json_extractor.go +++ b/lego/utils/codec/json/reader.go @@ -1,30 +1,21 @@ -package render +package json import ( "fmt" - "go_dreamfactory/lego/sys/codec/core" - "go_dreamfactory/lego/sys/codec/utils" + "io" "math/big" "reflect" "unicode/utf16" + "go_dreamfactory/lego/utils/codec" + "go_dreamfactory/lego/utils/codec/codecore" + "go_dreamfactory/lego/utils/codec/utils" + "github.com/modern-go/reflect2" ) -func NewExtractor(codec core.ICodec) *JsonExtractor { - return &JsonExtractor{ - codec: codec, - buf: nil, - head: 0, - tail: 0, - depth: 0, - err: nil, - } -} - -type JsonExtractor struct { - codec core.ICodec +type JsonReader struct { buf []byte head int tail int @@ -32,17 +23,29 @@ type JsonExtractor struct { err error } -func (this *JsonExtractor) ReadVal(obj interface{}) { +func (this *JsonReader) GetReader(buf []byte) codecore.IReader { + return GetReader(buf) +} +func (this *JsonReader) PutReader(r codecore.IReader) { + PutReader(r) +} +func (this *JsonReader) GetWriter() codecore.IWriter { + return GetWriter() +} +func (this *JsonReader) PutWriter(w codecore.IWriter) { + PutWriter(w) +} +func (this *JsonReader) ReadVal(obj interface{}) { depth := this.depth cacheKey := reflect2.RTypeOf(obj) - decoder := this.codec.GetDecoderFromCache(cacheKey) + decoder := codec.GetDecoder(cacheKey) if decoder == nil { typ := reflect2.TypeOf(obj) if typ == nil || typ.Kind() != reflect.Ptr { this.reportError("ReadVal", "can only unmarshal into pointer") return } - decoder = this.codec.DecoderOf(typ) + decoder = codec.DecoderOf(typ, defconf) } ptr := reflect2.PtrOf(obj) if ptr == nil { @@ -55,35 +58,35 @@ func (this *JsonExtractor) ReadVal(obj interface{}) { return } } -func (this *JsonExtractor) WhatIsNext() core.ValueType { +func (this *JsonReader) WhatIsNext() codecore.ValueType { valueType := valueTypes[this.nextToken()] this.unreadByte() return valueType } -func (this *JsonExtractor) Read() interface{} { +func (this *JsonReader) Read() interface{} { valueType := this.WhatIsNext() switch valueType { - case core.StringValue: + case codecore.StringValue: return this.ReadString() - case core.NumberValue: + case codecore.NumberValue: return this.ReadFloat64() - case core.NilValue: + case codecore.NilValue: this.skipFourBytes('n', 'u', 'l', 'l') return nil - case core.BoolValue: + case codecore.BoolValue: return this.ReadBool() - case core.ArrayValue: + case codecore.ArrayValue: arr := []interface{}{} - this.ReadArrayCB(func(extra core.IExtractor) bool { + this.ReadArrayCB(func(extra codecore.IReader) bool { var elem interface{} extra.ReadVal(&elem) arr = append(arr, elem) return true }) return arr - case core.ObjectValue: + case codecore.ObjectValue: obj := map[string]interface{}{} - this.ReadMapCB(func(extra core.IExtractor, field string) bool { + this.ReadMapCB(func(extra codecore.IReader, field string) bool { var elem interface{} this.ReadVal(&elem) obj[field] = elem @@ -95,7 +98,7 @@ func (this *JsonExtractor) Read() interface{} { return nil } } -func (this *JsonExtractor) ReadNil() (ret bool) { +func (this *JsonReader) ReadNil() (ret bool) { c := this.nextToken() if c == 'n' { this.skipThreeBytes('u', 'l', 'l') // null @@ -104,7 +107,7 @@ func (this *JsonExtractor) ReadNil() (ret bool) { this.unreadByte() return false } -func (this *JsonExtractor) ReadArrayStart() (ret bool) { +func (this *JsonReader) ReadArrayStart() (ret bool) { c := this.nextToken() if c == '[' { return true @@ -112,7 +115,7 @@ func (this *JsonExtractor) ReadArrayStart() (ret bool) { this.reportError("ReadArrayStart", `expect [ but found `+string([]byte{c})) return } -func (this *JsonExtractor) CheckNextIsArrayEnd() (ret bool) { +func (this *JsonReader) CheckNextIsArrayEnd() (ret bool) { c := this.nextToken() this.unreadByte() if c == ']' { @@ -120,7 +123,7 @@ func (this *JsonExtractor) CheckNextIsArrayEnd() (ret bool) { } return } -func (this *JsonExtractor) ReadArrayEnd() (ret bool) { +func (this *JsonReader) ReadArrayEnd() (ret bool) { c := this.nextToken() if c == ']' { return true @@ -128,7 +131,7 @@ func (this *JsonExtractor) ReadArrayEnd() (ret bool) { this.reportError("ReadArrayEnd", `expect ] but found `+string([]byte{c})) return } -func (this *JsonExtractor) ReadObjectStart() (ret bool) { +func (this *JsonReader) ReadObjectStart() (ret bool) { c := this.nextToken() if c == '{' { return this.incrementDepth() @@ -136,7 +139,7 @@ func (this *JsonExtractor) ReadObjectStart() (ret bool) { this.reportError("ReadObjectStart", `expect { but found `+string([]byte{c})) return } -func (this *JsonExtractor) CheckNextIsObjectEnd() (ret bool) { +func (this *JsonReader) CheckNextIsObjectEnd() (ret bool) { c := this.nextToken() this.unreadByte() if c == '}' { @@ -144,7 +147,7 @@ func (this *JsonExtractor) CheckNextIsObjectEnd() (ret bool) { } return } -func (this *JsonExtractor) ReadObjectEnd() (ret bool) { +func (this *JsonReader) ReadObjectEnd() (ret bool) { c := this.nextToken() if c == '}' { return this.decrementDepth() @@ -152,7 +155,7 @@ func (this *JsonExtractor) ReadObjectEnd() (ret bool) { this.reportError("ReadObjectEnd", `expect } but found `+string([]byte{c})) return } -func (this *JsonExtractor) ReadMemberSplit() (ret bool) { +func (this *JsonReader) ReadMemberSplit() (ret bool) { c := this.nextToken() if c == ',' { return true @@ -160,7 +163,7 @@ func (this *JsonExtractor) ReadMemberSplit() (ret bool) { this.unreadByte() return } -func (this *JsonExtractor) ReadKVSplit() (ret bool) { +func (this *JsonReader) ReadKVSplit() (ret bool) { c := this.nextToken() if c == ':' { return true @@ -168,7 +171,7 @@ func (this *JsonExtractor) ReadKVSplit() (ret bool) { this.reportError("ReadKVSplit", `expect : but found `+string([]byte{c})) return } -func (this *JsonExtractor) ReadKeyStart() (ret bool) { +func (this *JsonReader) ReadKeyStart() (ret bool) { c := this.nextToken() if c == '"' { return true @@ -176,7 +179,7 @@ func (this *JsonExtractor) ReadKeyStart() (ret bool) { this.reportError("ReadKeyStart", `expect " but found `+string([]byte{c})) return } -func (this *JsonExtractor) ReadKeyEnd() (ret bool) { +func (this *JsonReader) ReadKeyEnd() (ret bool) { c := this.nextToken() if c == '"' { return true @@ -184,7 +187,7 @@ func (this *JsonExtractor) ReadKeyEnd() (ret bool) { this.reportError("ReadKeyEnd", `expect " but found `+string([]byte{c})) return } -func (this *JsonExtractor) Skip() { +func (this *JsonReader) Skip() { c := this.nextToken() switch c { case '"': @@ -209,7 +212,7 @@ func (this *JsonExtractor) Skip() { return } } -func (this *JsonExtractor) ReadBool() (ret bool) { +func (this *JsonReader) ReadBool() (ret bool) { c := this.nextToken() if c == 't' { this.skipThreeBytes('r', 'u', 'e') @@ -222,7 +225,7 @@ func (this *JsonExtractor) ReadBool() (ret bool) { this.reportError("ReadBool", "expect t or f, but found "+string([]byte{c})) return } -func (this *JsonExtractor) ReadInt8() (ret int8) { +func (this *JsonReader) ReadInt8() (ret int8) { var ( n int err error @@ -234,7 +237,7 @@ func (this *JsonExtractor) ReadInt8() (ret int8) { this.head += n return } -func (this *JsonExtractor) ReadInt16() (ret int16) { +func (this *JsonReader) ReadInt16() (ret int16) { var ( n int err error @@ -246,7 +249,7 @@ func (this *JsonExtractor) ReadInt16() (ret int16) { this.head += n return } -func (this *JsonExtractor) ReadInt32() (ret int32) { +func (this *JsonReader) ReadInt32() (ret int32) { var ( n int err error @@ -258,7 +261,7 @@ func (this *JsonExtractor) ReadInt32() (ret int32) { this.head += n return } -func (this *JsonExtractor) ReadInt64() (ret int64) { +func (this *JsonReader) ReadInt64() (ret int64) { var ( n int err error @@ -270,7 +273,7 @@ func (this *JsonExtractor) ReadInt64() (ret int64) { this.head += n return } -func (this *JsonExtractor) ReadUint8() (ret uint8) { +func (this *JsonReader) ReadUint8() (ret uint8) { var ( n int err error @@ -282,7 +285,7 @@ func (this *JsonExtractor) ReadUint8() (ret uint8) { this.head += n return } -func (this *JsonExtractor) ReadUint16() (ret uint16) { +func (this *JsonReader) ReadUint16() (ret uint16) { var ( n int err error @@ -294,7 +297,7 @@ func (this *JsonExtractor) ReadUint16() (ret uint16) { this.head += n return } -func (this *JsonExtractor) ReadUint32() (ret uint32) { +func (this *JsonReader) ReadUint32() (ret uint32) { var ( n int err error @@ -306,7 +309,7 @@ func (this *JsonExtractor) ReadUint32() (ret uint32) { this.head += n return } -func (this *JsonExtractor) ReadUint64() (ret uint64) { +func (this *JsonReader) ReadUint64() (ret uint64) { var ( n int err error @@ -318,7 +321,7 @@ func (this *JsonExtractor) ReadUint64() (ret uint64) { this.head += n return } -func (this *JsonExtractor) ReadFloat32() (ret float32) { +func (this *JsonReader) ReadFloat32() (ret float32) { var ( n int err error @@ -330,7 +333,7 @@ func (this *JsonExtractor) ReadFloat32() (ret float32) { this.head += n return } -func (this *JsonExtractor) ReadFloat64() (ret float64) { +func (this *JsonReader) ReadFloat64() (ret float64) { var ( n int err error @@ -342,7 +345,7 @@ func (this *JsonExtractor) ReadFloat64() (ret float64) { this.head += n return } -func (this *JsonExtractor) ReadString() (ret string) { +func (this *JsonReader) ReadString() (ret string) { c := this.nextToken() if c == '"' { for i := this.head; i < this.tail; i++ { @@ -367,20 +370,20 @@ func (this *JsonExtractor) ReadString() (ret string) { this.reportError("ReadString", `expects " or n, but found `+string([]byte{c})) return } -func (this *JsonExtractor) ResetBytes(d []byte) { +func (this *JsonReader) ResetBytes(d []byte) { this.buf = d this.head = 0 this.tail = len(d) } -func (this *JsonExtractor) Error() error { +func (this *JsonReader) Error() error { return this.err } -func (this *JsonExtractor) SetErr(err error) { +func (this *JsonReader) SetErr(err error) { this.err = err } //----------------------------------------------------------------------------------------------------------------------------------- -func (this *JsonExtractor) readByte() (ret byte) { +func (this *JsonReader) readByte() (ret byte) { if this.head == this.tail { return 0 } @@ -388,7 +391,7 @@ func (this *JsonExtractor) readByte() (ret byte) { this.head++ return ret } -func (this *JsonExtractor) readStringSlowPath() (ret string) { +func (this *JsonReader) readStringSlowPath() (ret string) { var str []byte var c byte for this.err == nil { @@ -406,7 +409,7 @@ func (this *JsonExtractor) readStringSlowPath() (ret string) { this.reportError("readStringSlowPath", "unexpected end of input") return } -func (this *JsonExtractor) readEscapedChar(c byte, str []byte) []byte { +func (this *JsonReader) readEscapedChar(c byte, str []byte) []byte { switch c { case 'u': r := this.readU4() @@ -465,7 +468,7 @@ func (this *JsonExtractor) readEscapedChar(c byte, str []byte) []byte { } return str } -func (this *JsonExtractor) readU4() (ret rune) { +func (this *JsonReader) readU4() (ret rune) { for i := 0; i < 4; i++ { c := this.readByte() if this.err != nil { @@ -484,7 +487,7 @@ func (this *JsonExtractor) readU4() (ret rune) { } return ret } -func (this *JsonExtractor) nextToken() byte { +func (this *JsonReader) nextToken() byte { for i := this.head; i < this.tail; i++ { c := this.buf[i] switch c { @@ -496,14 +499,14 @@ func (this *JsonExtractor) nextToken() byte { } return 0 } -func (this *JsonExtractor) unreadByte() { +func (this *JsonReader) unreadByte() { if this.err != nil { return } this.head-- return } -func (this *JsonExtractor) skipNumber() { +func (this *JsonReader) skipNumber() { if !this.trySkipNumber() { this.unreadByte() if this.err != nil && this.err != io.EOF { @@ -516,7 +519,7 @@ func (this *JsonExtractor) skipNumber() { } } } -func (this *JsonExtractor) ReadBigFloat() (ret *big.Float) { +func (this *JsonReader) ReadBigFloat() (ret *big.Float) { var ( n int err error @@ -528,7 +531,7 @@ func (this *JsonExtractor) ReadBigFloat() (ret *big.Float) { this.head += n return } -func (iter *JsonExtractor) trySkipNumber() bool { +func (iter *JsonReader) trySkipNumber() bool { dotFound := false for i := iter.head; i < iter.tail; i++ { c := iter.buf[i] @@ -564,13 +567,13 @@ func (iter *JsonExtractor) trySkipNumber() bool { } return false } -func (this *JsonExtractor) skipString() { +func (this *JsonReader) skipString() { if !this.trySkipString() { this.unreadByte() this.ReadString() } } -func (this *JsonExtractor) trySkipString() bool { +func (this *JsonReader) trySkipString() bool { for i := this.head; i < this.tail; i++ { c := this.buf[i] if c == '"' { @@ -586,21 +589,21 @@ func (this *JsonExtractor) trySkipString() bool { } return false } -func (this *JsonExtractor) skipObject() { +func (this *JsonReader) skipObject() { this.unreadByte() - this.ReadObjectCB(func(extra core.IExtractor, field string) bool { + this.ReadObjectCB(func(extra codecore.IReader, field string) bool { extra.Skip() return true }) } -func (this *JsonExtractor) skipArray() { +func (this *JsonReader) skipArray() { this.unreadByte() - this.ReadArrayCB(func(extra core.IExtractor) bool { + this.ReadArrayCB(func(extra codecore.IReader) bool { extra.Skip() return true }) } -func (this *JsonExtractor) skipThreeBytes(b1, b2, b3 byte) { +func (this *JsonReader) skipThreeBytes(b1, b2, b3 byte) { if this.readByte() != b1 { this.reportError("skipThreeBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3}))) return @@ -614,7 +617,7 @@ func (this *JsonExtractor) skipThreeBytes(b1, b2, b3 byte) { return } } -func (this *JsonExtractor) skipFourBytes(b1, b2, b3, b4 byte) { +func (this *JsonReader) skipFourBytes(b1, b2, b3, b4 byte) { if this.readByte() != b1 { this.reportError("skipFourBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3, b4}))) return @@ -632,7 +635,7 @@ func (this *JsonExtractor) skipFourBytes(b1, b2, b3, b4 byte) { return } } -func (this *JsonExtractor) reportError(operation string, msg string) { +func (this *JsonReader) reportError(operation string, msg string) { if this.err != nil { if this.err != io.EOF { return @@ -659,7 +662,7 @@ func (this *JsonExtractor) reportError(operation string, msg string) { this.err = fmt.Errorf("%s: %s, error found in #%v byte of ...|%s|..., bigger context ...|%s|...", operation, msg, this.head-peekStart, parsing, context) } -func (this *JsonExtractor) incrementDepth() (success bool) { +func (this *JsonReader) incrementDepth() (success bool) { this.depth++ if this.depth <= maxDepth { return true @@ -667,7 +670,7 @@ func (this *JsonExtractor) incrementDepth() (success bool) { this.reportError("incrementDepth", "exceeded max depth") return false } -func (this *JsonExtractor) decrementDepth() (success bool) { +func (this *JsonReader) decrementDepth() (success bool) { this.depth-- if this.depth >= 0 { return true @@ -675,7 +678,7 @@ func (this *JsonExtractor) decrementDepth() (success bool) { this.reportError("decrementDepth", "unexpected negative nesting") return false } -func (iter *JsonExtractor) ReadObjectCB(callback func(core.IExtractor, string) bool) bool { +func (iter *JsonReader) ReadObjectCB(callback func(codecore.IReader, string) bool) bool { c := iter.nextToken() var field string if c == '{' { @@ -729,7 +732,7 @@ func (iter *JsonExtractor) ReadObjectCB(callback func(core.IExtractor, string) b return false } -func (iter *JsonExtractor) ReadMapCB(callback func(core.IExtractor, string) bool) bool { +func (iter *JsonReader) ReadMapCB(callback func(codecore.IReader, string) bool) bool { c := iter.nextToken() if c == '{' { if !iter.incrementDepth() { @@ -784,7 +787,7 @@ func (iter *JsonExtractor) ReadMapCB(callback func(core.IExtractor, string) bool return false } -func (iter *JsonExtractor) ReadArrayCB(callback func(core.IExtractor) bool) (ret bool) { +func (iter *JsonReader) ReadArrayCB(callback func(codecore.IReader) bool) (ret bool) { c := iter.nextToken() if c == '[' { if !iter.incrementDepth() { diff --git a/lego/utils/codec/json/writer.go b/lego/utils/codec/json/writer.go new file mode 100644 index 000000000..3b083dfc1 --- /dev/null +++ b/lego/utils/codec/json/writer.go @@ -0,0 +1,216 @@ +package json + +import ( + "go_dreamfactory/lego/utils/codec" + "go_dreamfactory/lego/utils/codec/codecore" + "go_dreamfactory/lego/utils/codec/utils" + + "github.com/modern-go/reflect2" +) + +const indentionStep = 1 + +type JsonWriter struct { + err error + buf []byte + indention int +} + +func (this *JsonWriter) GetReader(buf []byte) codecore.IReader { + return GetReader(buf) +} +func (this *JsonWriter) PutReader(r codecore.IReader) { + PutReader(r) +} +func (this *JsonWriter) GetWriter() codecore.IWriter { + return GetWriter() +} +func (this *JsonWriter) PutWriter(w codecore.IWriter) { + PutWriter(w) +} + +//写入对象 +func (this *JsonWriter) WriteVal(val interface{}) { + if nil == val { + this.WriteNil() + return + } + cacheKey := reflect2.RTypeOf(val) + encoder := codec.GetEncoder(cacheKey) + if encoder == nil { + typ := reflect2.TypeOf(val) + encoder = codec.EncoderOf(typ, defconf) + } + encoder.Encode(reflect2.PtrOf(val), this) +} + +func (this *JsonWriter) WriteNil() { + this.writeFourBytes('n', 'u', 'l', 'l') +} +func (this *JsonWriter) WriteEmptyArray() { + this.writeTwoBytes('[', ']') +} +func (this *JsonWriter) WriteArrayStart() { + this.indention += indentionStep + this.writeByte('[') + this.writeIndention(0) +} +func (this *JsonWriter) WriteArrayEnd() { + this.writeIndention(indentionStep) + this.indention -= indentionStep + this.writeByte(']') +} +func (this *JsonWriter) WriteEmptyObject() { + this.writeTwoBytes('{', '}') +} +func (this *JsonWriter) WriteObjectStart() { + this.indention += indentionStep + this.writeByte('{') + this.writeIndention(0) +} +func (this *JsonWriter) WriteObjectEnd() { + this.writeIndention(indentionStep) + this.indention -= indentionStep + this.writeByte('}') +} +func (this *JsonWriter) WriteMemberSplit() { + this.writeByte(',') + this.writeIndention(0) +} +func (this *JsonWriter) WriteKVSplit() { + this.writeByte(':') +} +func (this *JsonWriter) WriteKeyStart() { + this.writeByte('"') +} +func (this *JsonWriter) WriteKeyEnd() { + this.writeByte('"') +} +func (this *JsonWriter) WriteObjectFieldName(val string) { + this.WriteString(val) + if this.indention > 0 { + this.writeTwoBytes(':', ' ') + } else { + this.writeByte(':') + } +} +func (this *JsonWriter) WriteBool(val bool) { + if val { + this.writeTrue() + } else { + this.writeFalse() + } +} +func (this *JsonWriter) WriteInt8(val int8) { + utils.WriteInt8ToString(&this.buf, val) +} +func (this *JsonWriter) WriteInt16(val int16) { + utils.WriteInt16ToString(&this.buf, val) +} +func (this *JsonWriter) WriteInt32(val int32) { + utils.WriteInt32ToString(&this.buf, val) +} +func (this *JsonWriter) WriteInt64(val int64) { + utils.WriteInt64ToString(&this.buf, val) +} +func (this *JsonWriter) WriteUint8(val uint8) { + utils.WriteUint8ToString(&this.buf, val) +} +func (this *JsonWriter) WriteUint16(val uint16) { + utils.WriteUint16ToString(&this.buf, val) +} +func (this *JsonWriter) WriteUint32(val uint32) { + utils.WriteUint32ToString(&this.buf, val) +} +func (this *JsonWriter) WriteUint64(val uint64) { + utils.WriteUint64ToString(&this.buf, val) +} +func (this *JsonWriter) WriteFloat32(val float32) { + utils.WriteFloat32ToString(&this.buf, val) +} +func (this *JsonWriter) WriteFloat64(val float64) { + utils.WriteFloat64ToString(&this.buf, val) +} +func (this *JsonWriter) WriteString(val string) { + valLen := len(val) + this.buf = append(this.buf, '"') + i := 0 + for ; i < valLen; i++ { + c := val[i] + if c > 31 && c != '"' && c != '\\' { + this.buf = append(this.buf, c) + } else { + break + } + } + if i == valLen { + this.buf = append(this.buf, '"') + return + } + utils.WriteStringSlowPath(&this.buf, i, val, valLen) +} +func (this *JsonWriter) WriteBytes(val []byte) { + this.buf = append(this.buf, val...) +} +func (this *JsonWriter) Reset() { + this.buf = this.buf[:0] + this.err = nil + this.indention = 0 + return +} +func (this *JsonWriter) Buffer() []byte { + return this.buf +} +func (this *JsonWriter) Buffered() int { + return len(this.buf) +} + +func (this *JsonWriter) Error() error { + return this.err +} +func (this *JsonWriter) SetErr(err error) { + this.err = err +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +// WriteTrue write true to stream +func (stream *JsonWriter) writeTrue() { + stream.writeFourBytes('t', 'r', 'u', 'e') +} + +// WriteFalse write false to stream +func (stream *JsonWriter) writeFalse() { + stream.writeFiveBytes('f', 'a', 'l', 's', 'e') +} + +func (this *JsonWriter) writeByte(c byte) { + this.buf = append(this.buf, c) +} + +func (this *JsonWriter) writeTwoBytes(c1 byte, c2 byte) { + this.buf = append(this.buf, c1, c2) +} + +func (this *JsonWriter) writeThreeBytes(c1 byte, c2 byte, c3 byte) { + this.buf = append(this.buf, c1, c2, c3) +} + +func (this *JsonWriter) writeFourBytes(c1 byte, c2 byte, c3 byte, c4 byte) { + this.buf = append(this.buf, c1, c2, c3, c4) +} + +func (this *JsonWriter) writeFiveBytes(c1 byte, c2 byte, c3 byte, c4 byte, c5 byte) { + this.buf = append(this.buf, c1, c2, c3, c4, c5) +} + +func (stream *JsonWriter) writeIndention(delta int) { + if stream.indention == 0 { + return + } + stream.writeByte('\n') + toWrite := stream.indention - delta + for i := 0; i < toWrite; i++ { + stream.buf = append(stream.buf, ' ') + } +} diff --git a/lego/utils/codec/string.go b/lego/utils/codec/string.go new file mode 100644 index 000000000..64d93aefb --- /dev/null +++ b/lego/utils/codec/string.go @@ -0,0 +1,31 @@ +package codec + +import "strconv" + +func Atoi(b []byte) (int, error) { + return strconv.Atoi(BytesToString(b)) +} + +func ParseInt(b []byte, base int, bitSize int) (int64, error) { + return strconv.ParseInt(BytesToString(b), base, bitSize) +} + +func ParseUint(b []byte, base int, bitSize int) (uint64, error) { + return strconv.ParseUint(BytesToString(b), base, bitSize) +} + +func ParseFloat(b []byte, bitSize int) (float64, error) { + return strconv.ParseFloat(BytesToString(b), bitSize) +} + +func UintToString(n uint64) string { + return BytesToString(strconv.AppendUint([]byte{}, n, 10)) +} + +func IntToString(n int64) string { + return BytesToString(strconv.AppendInt([]byte{}, n, 10)) +} + +func FloatToString(f float64) string { + return BytesToString(strconv.AppendFloat([]byte{}, f, 'f', -1, 64)) +} diff --git a/lego/sys/codec/utils/float.go b/lego/utils/codec/utils/float.go similarity index 100% rename from lego/sys/codec/utils/float.go rename to lego/utils/codec/utils/float.go diff --git a/lego/sys/codec/utils/int.go b/lego/utils/codec/utils/int.go similarity index 100% rename from lego/sys/codec/utils/int.go rename to lego/utils/codec/utils/int.go diff --git a/lego/sys/codec/utils/string.go b/lego/utils/codec/utils/string.go similarity index 100% rename from lego/sys/codec/utils/string.go rename to lego/utils/codec/utils/string.go diff --git a/lego/utils/pools/bufferpool.go b/lego/utils/pools/bufferpool.go new file mode 100644 index 000000000..c7adac989 --- /dev/null +++ b/lego/utils/pools/bufferpool.go @@ -0,0 +1,136 @@ +package pools + +import ( + "io" + "strconv" + "sync" + "time" +) + +/* + bytes buffer 缓存池 +*/ + +const _size = 1024 + +var bufferPool = &BufferPool{p: &sync.Pool{ + New: func() interface{} { + return &Buffer{bs: make([]byte, 0, _size)} + }, +}} + +func BufferPoolGet() *Buffer { + return bufferPool.get() +} +func BufferPoolPut(buf *Buffer) { + bufferPool.put(buf) +} + +type BufferPool struct { + p *sync.Pool +} + +func (p BufferPool) get() *Buffer { + buf := p.p.Get().(*Buffer) + buf.reset() + buf.pool = p + return buf +} + +func (p BufferPool) put(buf *Buffer) { + p.p.Put(buf) +} + +type Buffer struct { + bs []byte + pool BufferPool +} + +func (b *Buffer) reset() { + b.bs = b.bs[:0] +} +func (b *Buffer) Len() int { + return len(b.bs) +} +func (b *Buffer) Cap() int { + return cap(b.bs) +} +func (b *Buffer) Bytes() []byte { + return b.bs +} +func (b *Buffer) String() string { + return string(b.bs) +} +func (b *Buffer) ReadFrom(r io.Reader) (int64, error) { + p := b.bs + nStart := int64(len(p)) + nMax := int64(cap(p)) + n := nStart + if nMax == 0 { + nMax = 64 + p = make([]byte, nMax) + } else { + p = p[:nMax] + } + for { + if n == nMax { + nMax *= 2 + bNew := make([]byte, nMax) + copy(bNew, p) + p = bNew + } + nn, err := r.Read(p[n:]) + n += int64(nn) + if err != nil { + b.bs = p[:n] + n -= nStart + if err == io.EOF { + return n, nil + } + return n, err + } + } +} +func (b *Buffer) AppendByte(v byte) { + b.bs = append(b.bs, v) +} +func (b *Buffer) AppendInt(i int64) { + b.bs = strconv.AppendInt(b.bs, i, 10) +} +func (b *Buffer) AppendUint(i uint64) { + b.bs = strconv.AppendUint(b.bs, i, 10) +} +func (b *Buffer) AppendFloat(f float64, bitSize int) { + b.bs = strconv.AppendFloat(b.bs, f, 'f', -1, bitSize) +} +func (b *Buffer) AppendBool(v bool) { + b.bs = strconv.AppendBool(b.bs, v) +} +func (b *Buffer) AppendTime(t time.Time, layout string) { + b.bs = t.AppendFormat(b.bs, layout) +} +func (b *Buffer) AppendString(s string) { + b.bs = append(b.bs, s...) +} +func (b *Buffer) AppendBytes(s []byte) { + b.bs = append(b.bs, s...) +} +func (b *Buffer) Write(p []byte) (int, error) { + b.bs = append(b.bs, p...) + return len(p), nil +} +func (b *Buffer) WriteString(s string) (int, error) { + b.AppendString(s) + return len(s), nil +} +func (b *Buffer) WriteByte(v byte) error { + b.AppendByte(v) + return nil +} +func (b *Buffer) WriteTo(w io.Writer) (int64, error) { + n, err := w.Write(b.bs) + return int64(n), err +} +func (b *Buffer) Free() { + b.pool.put(b) +} diff --git a/modules/chat/modelChat.go b/modules/chat/modelChat.go index 1f04e44c4..67b3fef80 100644 --- a/modules/chat/modelChat.go +++ b/modules/chat/modelChat.go @@ -5,8 +5,8 @@ import ( "fmt" "go_dreamfactory/comm" "go_dreamfactory/lego/core" - "go_dreamfactory/lego/sys/codec" "go_dreamfactory/lego/sys/redis" + "go_dreamfactory/lego/utils/codec/json" "go_dreamfactory/modules" "go_dreamfactory/pb" @@ -101,7 +101,7 @@ func (this *modelChatComp) GetChatQueue(channel pb.ChatChannel, union, group, ar result = make([]*pb.DBChat, len(cdata)) for i, v := range cdata { chat := &pb.DBChat{} - if err = codec.UnmarshalMapJson(v, chat); err != nil { + if err = json.UnmarshalMap(v, chat); err != nil { return } result[i] = chat @@ -256,7 +256,7 @@ func (this *modelChatComp) addChatMsg(key string, count int32, msgs ...*pb.DBCha vs = make([]map[string]string, len(msgs)) values = make([]interface{}, len(msgs)) for i, v := range msgs { - if tempdata, err = codec.MarshalMapJson(v); err != nil { + if tempdata, err = json.MarshalMap(v); err != nil { this.module.Errorf("err:%v", err) return } diff --git a/modules/comp_model.go b/modules/comp_model.go index 2b02e7ff7..d3edcbe23 100644 --- a/modules/comp_model.go +++ b/modules/comp_model.go @@ -6,11 +6,12 @@ import ( "go_dreamfactory/comm" "go_dreamfactory/lego/core" "go_dreamfactory/lego/core/cbase" - "go_dreamfactory/lego/sys/codec" - ccore "go_dreamfactory/lego/sys/codec/core" "go_dreamfactory/lego/sys/log" "go_dreamfactory/lego/sys/mgo" "go_dreamfactory/lego/sys/redis" + "go_dreamfactory/lego/utils/codec" + "go_dreamfactory/lego/utils/codec/codecore" + "go_dreamfactory/lego/utils/codec/json" "go_dreamfactory/sys/cache" "go_dreamfactory/sys/db" "reflect" @@ -22,6 +23,15 @@ import ( "go.mongodb.org/mongo-driver/mongo" ) +var defconf = &codecore.Config{ + SortMapKeys: true, + IndentionStep: 1, + OnlyTaggedField: false, + DisallowUnknownFields: false, + CaseSensitive: false, + TagKey: "json", +} + //Redis 自定义脚本 批量读取列表数据 var LuaScriptgetList = ` local key = tostring(KEYS[1]) @@ -374,8 +384,8 @@ func (this *MCompModel) GetList(uid string, data interface{}) (err error) { sType reflect2.Type sliceType *reflect2.UnsafeSliceType sliceelemType reflect2.Type - decoder ccore.IDecoderMapJson - encoder ccore.IEncoderMapJson + decoder codecore.IDecoderMapJson + encoder codecore.IEncoderMapJson dptr unsafe.Pointer elemPtr unsafe.Pointer n int @@ -405,7 +415,7 @@ func (this *MCompModel) GetList(uid string, data interface{}) (err error) { err = fmt.Errorf("MCompModel: GetList(sliceelemType non-pointer %T)", data) return } - if decoder, ok = codec.DecoderOf(sliceelemType).(ccore.IDecoderMapJson); !ok { + if decoder, ok = codec.DecoderOf(sliceelemType, defconf).(codecore.IDecoderMapJson); !ok { err = fmt.Errorf("MCompModel: GetList(data not support MarshalMapJson %T)", data) return } @@ -416,13 +426,13 @@ func (this *MCompModel) GetList(uid string, data interface{}) (err error) { elemPtr = sliceType.UnsafeGetIndex(dptr, n) if *((*unsafe.Pointer)(elemPtr)) == nil { newPtr := sliceelemType.UnsafeNew() - if err = decoder.DecodeForMapJson(newPtr, v); err != nil { + if err = decoder.DecodeForMapJson(newPtr, json.GetReader([]byte{}), v); err != nil { log.Errorf("err:%v", err) return } *((*unsafe.Pointer)(elemPtr)) = newPtr } else { - decoder.DecodeForMapJson(*((*unsafe.Pointer)(elemPtr)), v) + decoder.DecodeForMapJson(*((*unsafe.Pointer)(elemPtr)), json.GetReader([]byte{}), v) } n++ } @@ -432,7 +442,7 @@ func (this *MCompModel) GetList(uid string, data interface{}) (err error) { if c, err = this.DB.Find(core.SqlTable(this.TableName), bson.M{"uid": uid}); err != nil { return err } else { - if encoder, ok = codec.EncoderOf(sliceelemType).(ccore.IEncoderMapJson); !ok { + if encoder, ok = codec.EncoderOf(sliceelemType, defconf).(codecore.IEncoderMapJson); !ok { err = fmt.Errorf("MCompModel: GetList(data not support UnMarshalMapJson %T)", data) return } @@ -450,7 +460,7 @@ func (this *MCompModel) GetList(uid string, data interface{}) (err error) { if err = c.Decode(elem); err != nil { return } - if tempdata, err = encoder.EncodeToMapJson(*((*unsafe.Pointer)(elemPtr))); err != nil { + if tempdata, err = encoder.EncodeToMapJson(*((*unsafe.Pointer)(elemPtr)), json.GetWriter()); err != nil { return } key := this.ukeylist(uid, _id) @@ -668,33 +678,6 @@ func (this *MCompModel) logOpt(uid string, data interface{}, attrs ...*cache.Ope return nil } -//获取用户通过扩展表 -// func (this *MCompModel) GetUserRecord(uid string) (result *pb.DBUserRecord, err error) { -// result = &pb.DBUserRecord{} -// key := fmt.Sprintf("userrecord:%s{userrecord}", uid) -// if err = this.Redis.HGetAll(key, result); err != nil && err != redis.RedisNil { -// return -// } -// if err == redis.RedisNil { -// if err = this.DB.FindOne(core.SqlTable("userrecord"), bson.M{"uid": uid}).Decode(result); err != nil { -// return -// } -// err = this.Redis.HMSet(key, result) -// } -// return -// } - -// //修改用户扩展数据 -// func (this *MCompModel) ChangeUserRecord(uid string, value map[string]interface{}) (err error) { -// value["mtime"] = time.Now().Unix() // 更新时间 -// key := fmt.Sprintf("userrecord:%s{userrecord}", uid) -// if err = this.Redis.HMSet(key, value); err != nil && err != redis.RedisNil { -// return -// } -// err = this.UpdateModelLogs("userrecord", uid, bson.M{"uid": uid}, value) -// return -// } - // 删除玩家缓存信息 func (this *MCompModel) CleanUserRecord(uid string) (err error) { err = this.Redis.Delete(this.ukey(uid)) diff --git a/modules/gateway/module.go b/modules/gateway/module.go index 634689e6c..8011b8430 100644 --- a/modules/gateway/module.go +++ b/modules/gateway/module.go @@ -1,7 +1,6 @@ package gateway import ( - "fmt" "go_dreamfactory/comm" "go_dreamfactory/lego/base" @@ -103,33 +102,69 @@ func (this *Gateway) GetMsgDistribute(mtype, stype string) (rule string, ok bool } //日志 -func (this *Gateway) Debugf(format string, a ...interface{}) { - if this.options.GetDebug() { - this.options.GetLog().Debugf(fmt.Sprintf("[Module:%s] ", this.GetType())+format, a...) - } +//日志接口 +func (this *Gateway) Debug(msg string, args ...log.Field) { + this.options.GetLog().Debug(msg, args...) } -func (this *Gateway) Infof(format string, a ...interface{}) { - if this.options.GetDebug() { - this.options.GetLog().Infof(fmt.Sprintf("[Module:%s] ", this.GetType())+format, a...) - } +func (this *Gateway) Info(msg string, args ...log.Field) { + this.options.GetLog().Info(msg, args...) } -func (this *Gateway) Warnf(format string, a ...interface{}) { - if this.options.Debug { - this.options.GetLog().Warnf(fmt.Sprintf("[Module:%s] ", this.GetType())+format, a...) - } +func (this *Gateway) Print(msg string, args ...log.Field) { + this.options.GetLog().Print(msg, args...) } -func (this *Gateway) Errorf(format string, a ...interface{}) { - if this.options.GetLog() != nil { - this.options.GetLog().Errorf(fmt.Sprintf("[Module:%s] ", this.GetType())+format, a...) - } +func (this *Gateway) Warn(msg string, args ...log.Field) { + this.options.GetLog().Warn(msg, args...) } -func (this *Gateway) Panicf(format string, a ...interface{}) { - if this.options.GetLog() != nil { - this.options.GetLog().Panicf(fmt.Sprintf("[Module:%s] ", this.GetType())+format, a...) - } +func (this *Gateway) Error(msg string, args ...log.Field) { + this.options.GetLog().Error(msg, args...) } -func (this *Gateway) Fatalf(format string, a ...interface{}) { - if this.options.GetLog() != nil { - this.options.GetLog().Fatalf(fmt.Sprintf("[Module:%s] ", this.GetType())+format, a...) - } +func (this *Gateway) Panic(msg string, args ...log.Field) { + this.options.GetLog().Panic(msg, args...) +} +func (this *Gateway) Fatal(msg string, args ...log.Field) { + this.options.GetLog().Fatal(msg, args...) +} + +func (this *Gateway) Debugf(format string, args ...interface{}) { + this.options.GetLog().Debugf(format, args...) +} +func (this *Gateway) Infof(format string, args ...interface{}) { + this.options.GetLog().Infof(format, args...) +} +func (this *Gateway) Printf(format string, args ...interface{}) { + this.options.GetLog().Printf(format, args...) +} +func (this *Gateway) Warnf(format string, args ...interface{}) { + this.options.GetLog().Warnf(format, args...) +} +func (this *Gateway) Errorf(format string, args ...interface{}) { + this.options.GetLog().Errorf(format, args...) +} +func (this *Gateway) Fatalf(format string, args ...interface{}) { + this.options.GetLog().Fatalf(format, args...) +} +func (this *Gateway) Panicf(format string, args ...interface{}) { + this.options.GetLog().Panicf(format, args...) +} + +func (this *Gateway) Debugln(args ...interface{}) { + this.options.GetLog().Debugln(args...) +} +func (this *Gateway) Infoln(args ...interface{}) { + this.options.GetLog().Infoln(args...) +} +func (this *Gateway) Println(args ...interface{}) { + this.options.GetLog().Println(args...) +} +func (this *Gateway) Warnln(args ...interface{}) { + this.options.GetLog().Warnln(args...) +} +func (this *Gateway) Errorln(args ...interface{}) { + this.options.GetLog().Errorln(args...) +} +func (this *Gateway) Fatalln(args ...interface{}) { + this.options.GetLog().Fatalln(args...) +} +func (this *Gateway) Panicln(args ...interface{}) { + this.options.GetLog().Panicln(args...) } diff --git a/modules/modulebase.go b/modules/modulebase.go index 5df5317c7..992ec4b3a 100644 --- a/modules/modulebase.go +++ b/modules/modulebase.go @@ -43,6 +43,7 @@ func (this *ModuleBase) Init(service core.IService, module core.IModule, options this.service = service.(base.IRPCXService) this.module = module this.options = options.(IOptions) + this.options.GetLog().SetName("module." + string(module.GetType())) return } @@ -289,33 +290,68 @@ func (this *ModuleBase) DispenseRes(session comm.IUserSession, res []*cfg.Game_a } //日志接口 -func (this *ModuleBase) Debugf(format string, a ...interface{}) { - if this.options.GetDebug() { - this.options.GetLog().Debugf(fmt.Sprintf("[Module:%s] ", this.module.GetType())+format, a...) - } +func (this *ModuleBase) Debug(msg string, args ...log.Field) { + this.options.GetLog().Debug(msg, args...) } -func (this *ModuleBase) Infof(format string, a ...interface{}) { - if this.options.GetDebug() { - this.options.GetLog().Infof(fmt.Sprintf("[Module:%s] ", this.module.GetType())+format, a...) - } +func (this *ModuleBase) Info(msg string, args ...log.Field) { + this.options.GetLog().Info(msg, args...) } -func (this *ModuleBase) Warnf(format string, a ...interface{}) { - if this.options.GetDebug() { - this.options.GetLog().Warnf(fmt.Sprintf("[Module:%s] ", this.module.GetType())+format, a...) - } +func (this *ModuleBase) Print(msg string, args ...log.Field) { + this.options.GetLog().Print(msg, args...) } -func (this *ModuleBase) Errorf(format string, a ...interface{}) { - if this.options.GetLog() != nil { - this.options.GetLog().Errorf(fmt.Sprintf("[Module:%s] ", this.module.GetType())+format, a...) - } +func (this *ModuleBase) Warn(msg string, args ...log.Field) { + this.options.GetLog().Warn(msg, args...) } -func (this *ModuleBase) Panicf(format string, a ...interface{}) { - if this.options.GetLog() != nil { - this.options.GetLog().Panicf(fmt.Sprintf("[Module:%s] ", this.module.GetType())+format, a...) - } +func (this *ModuleBase) Error(msg string, args ...log.Field) { + this.options.GetLog().Error(msg, args...) } -func (this *ModuleBase) Fatalf(format string, a ...interface{}) { - if this.options.GetLog() != nil { - this.options.GetLog().Fatalf(fmt.Sprintf("[Module:%s] ", this.module.GetType())+format, a...) - } +func (this *ModuleBase) Panic(msg string, args ...log.Field) { + this.options.GetLog().Panic(msg, args...) +} +func (this *ModuleBase) Fatal(msg string, args ...log.Field) { + this.options.GetLog().Fatal(msg, args...) +} + +func (this *ModuleBase) Debugf(format string, args ...interface{}) { + this.options.GetLog().Debugf(format, args...) +} +func (this *ModuleBase) Infof(format string, args ...interface{}) { + this.options.GetLog().Infof(format, args...) +} +func (this *ModuleBase) Printf(format string, args ...interface{}) { + this.options.GetLog().Printf(format, args...) +} +func (this *ModuleBase) Warnf(format string, args ...interface{}) { + this.options.GetLog().Warnf(format, args...) +} +func (this *ModuleBase) Errorf(format string, args ...interface{}) { + this.options.GetLog().Errorf(format, args...) +} +func (this *ModuleBase) Fatalf(format string, args ...interface{}) { + this.options.GetLog().Fatalf(format, args...) +} +func (this *ModuleBase) Panicf(format string, args ...interface{}) { + this.options.GetLog().Panicf(format, args...) +} + +func (this *ModuleBase) Debugln(args ...interface{}) { + this.options.GetLog().Debugln(args...) +} +func (this *ModuleBase) Infoln(args ...interface{}) { + this.options.GetLog().Infoln(args...) +} +func (this *ModuleBase) Println(args ...interface{}) { + this.options.GetLog().Println(args...) +} +func (this *ModuleBase) Warnln(args ...interface{}) { + this.options.GetLog().Warnln(args...) +} +func (this *ModuleBase) Errorln(args ...interface{}) { + this.options.GetLog().Errorln(args...) +} +func (this *ModuleBase) Fatalln(args ...interface{}) { + this.options.GetLog().Fatalln(args...) +} +func (this *ModuleBase) Panicln(args ...interface{}) { + this.options.GetLog().Panicln(args...) } diff --git a/modules/options.go b/modules/options.go index 1b76f5d24..c2479d720 100644 --- a/modules/options.go +++ b/modules/options.go @@ -1,7 +1,7 @@ package modules import ( - "fmt" + "errors" "go_dreamfactory/lego/core" "go_dreamfactory/lego/sys/log" "go_dreamfactory/lego/utils/mapstructure" @@ -12,11 +12,11 @@ type ( IOptions interface { core.IModuleOptions GetDebug() bool - GetLog() log.ILog + GetLog() log.ILogger } Options struct { Debug bool //日志是否开启 - Log log.ILog + Log log.ILogger } ) @@ -24,7 +24,7 @@ func (this *Options) GetDebug() bool { return this.Debug } -func (this *Options) GetLog() log.ILog { +func (this *Options) GetLog() log.ILogger { return this.Log } @@ -32,12 +32,9 @@ func (this *Options) LoadConfig(settings map[string]interface{}) (err error) { if settings != nil { err = mapstructure.Decode(settings, this) } - if this.Debug && this.Log == nil { - this.Log = log.Clone() - if this.Log == nil { - err = fmt.Errorf("Log is nil") - return - } + + if this.Log = log.NewTurnlog(this.Debug, log.Clone("", 2)); this.Log == nil { + err = errors.New("log is nil") } return } diff --git a/services/comp_gateroute.go b/services/comp_gateroute.go index 013741c34..4163ee59c 100644 --- a/services/comp_gateroute.go +++ b/services/comp_gateroute.go @@ -153,11 +153,25 @@ func (this *SCompGateRoute) ReceiveMsg(ctx context.Context, args *pb.AgentMessag data, _ := anypb.New(errdata.(proto.Message)) reply.ErrorData = data } - log.Errorf("[Handle Api] t:%v m:%s req:%v reply:%v", time.Since(stime), method, msg, reply) + // log.Errorf("[Handle Api] t:%v m:%s req:%v reply:%v", time.Since(stime), method, msg, reply) + log.Error("[Handle Api]", + log.Field{Key: "t", Value: time.Since(stime)}, + log.Field{Key: "m", Value: method}, + log.Field{Key: "uid", Value: args.UserId}, + log.Field{Key: "req", Value: msg}, + log.Field{Key: "reply", Value: reply}, + ) } else { reply.Reply = session.Polls() if this.options.Debug { - log.Debugf("[Handle Api] t:%v m:%s uid:%s req:%v reply:%v", time.Since(stime), method, args.UserId, msg, reply) + // log.Debugf("[Handle Api] t:%v m:%s uid:%s req:%v reply:%v", time.Since(stime), method, args.UserId, msg, reply) + log.Debug("[Handle Api]", + log.Field{Key: "t", Value: time.Since(stime)}, + log.Field{Key: "m", Value: method}, + log.Field{Key: "uid", Value: args.UserId}, + log.Field{Key: "req", Value: msg}, + log.Field{Key: "reply", Value: reply}, + ) } } } else { //未找到消息处理函数 diff --git a/services/service_test.go b/services/service_test.go new file mode 100644 index 000000000..7f904b4ad --- /dev/null +++ b/services/service_test.go @@ -0,0 +1,37 @@ +package services_test + +import ( + "fmt" + "go_dreamfactory/lego/sys/log" + "os" + "testing" +) + +type TestData struct { + Name string + Age int32 +} + +func (this *TestData) Log() { + sys.Error("妈妈咪呀!") +} + +var sys log.ISys + +func TestMain(m *testing.M) { + var err error + if sys, err = log.NewSys( + log.SetFileName("log.log"), + log.SetIsDebug(false), + log.SetEncoder(log.TextEncoder), + ); err != nil { + fmt.Println(err) + return + } + defer os.Exit(m.Run()) +} +func Test_sys(t *testing.T) { + data := &TestData{} + data.Log() + +}