sinks.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /*
  2. Copyright 2012 Google Inc.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package groupcache
  14. import (
  15. "errors"
  16. "github.com/golang/protobuf/proto"
  17. )
  18. // A Sink receives data from a Get call.
  19. //
  20. // Implementation of Getter must call exactly one of the Set methods
  21. // on success.
  22. type Sink interface {
  23. // SetString sets the value to s.
  24. SetString(s string) error
  25. // SetBytes sets the value to the contents of v.
  26. // The caller retains ownership of v.
  27. SetBytes(v []byte) error
  28. // SetProto sets the value to the encoded version of m.
  29. // The caller retains ownership of m.
  30. SetProto(m proto.Message) error
  31. // view returns a frozen view of the bytes for caching.
  32. view() (ByteView, error)
  33. }
  34. func cloneBytes(b []byte) []byte {
  35. c := make([]byte, len(b))
  36. copy(c, b)
  37. return c
  38. }
  39. func setSinkView(s Sink, v ByteView) error {
  40. // A viewSetter is a Sink that can also receive its value from
  41. // a ByteView. This is a fast path to minimize copies when the
  42. // item was already cached locally in memory (where it's
  43. // cached as a ByteView)
  44. type viewSetter interface {
  45. setView(v ByteView) error
  46. }
  47. if vs, ok := s.(viewSetter); ok {
  48. return vs.setView(v)
  49. }
  50. if v.b != nil {
  51. return s.SetBytes(v.b)
  52. }
  53. return s.SetString(v.s)
  54. }
  55. // StringSink returns a Sink that populates the provided string pointer.
  56. func StringSink(sp *string) Sink {
  57. return &stringSink{sp: sp}
  58. }
  59. type stringSink struct {
  60. sp *string
  61. v ByteView
  62. // TODO(bradfitz): track whether any Sets were called.
  63. }
  64. func (s *stringSink) view() (ByteView, error) {
  65. // TODO(bradfitz): return an error if no Set was called
  66. return s.v, nil
  67. }
  68. func (s *stringSink) SetString(v string) error {
  69. s.v.b = nil
  70. s.v.s = v
  71. *s.sp = v
  72. return nil
  73. }
  74. func (s *stringSink) SetBytes(v []byte) error {
  75. return s.SetString(string(v))
  76. }
  77. func (s *stringSink) SetProto(m proto.Message) error {
  78. b, err := proto.Marshal(m)
  79. if err != nil {
  80. return err
  81. }
  82. s.v.b = b
  83. *s.sp = string(b)
  84. return nil
  85. }
  86. // ByteViewSink returns a Sink that populates a ByteView.
  87. func ByteViewSink(dst *ByteView) Sink {
  88. if dst == nil {
  89. panic("nil dst")
  90. }
  91. return &byteViewSink{dst: dst}
  92. }
  93. type byteViewSink struct {
  94. dst *ByteView
  95. // if this code ever ends up tracking that at least one set*
  96. // method was called, don't make it an error to call set
  97. // methods multiple times. Lorry's payload.go does that, and
  98. // it makes sense. The comment at the top of this file about
  99. // "exactly one of the Set methods" is overly strict. We
  100. // really care about at least once (in a handler), but if
  101. // multiple handlers fail (or multiple functions in a program
  102. // using a Sink), it's okay to re-use the same one.
  103. }
  104. func (s *byteViewSink) setView(v ByteView) error {
  105. *s.dst = v
  106. return nil
  107. }
  108. func (s *byteViewSink) view() (ByteView, error) {
  109. return *s.dst, nil
  110. }
  111. func (s *byteViewSink) SetProto(m proto.Message) error {
  112. b, err := proto.Marshal(m)
  113. if err != nil {
  114. return err
  115. }
  116. *s.dst = ByteView{b: b}
  117. return nil
  118. }
  119. func (s *byteViewSink) SetBytes(b []byte) error {
  120. *s.dst = ByteView{b: cloneBytes(b)}
  121. return nil
  122. }
  123. func (s *byteViewSink) SetString(v string) error {
  124. *s.dst = ByteView{s: v}
  125. return nil
  126. }
  127. // ProtoSink returns a sink that unmarshals binary proto values into m.
  128. func ProtoSink(m proto.Message) Sink {
  129. return &protoSink{
  130. dst: m,
  131. }
  132. }
  133. type protoSink struct {
  134. dst proto.Message // authorative value
  135. typ string
  136. v ByteView // encoded
  137. }
  138. func (s *protoSink) view() (ByteView, error) {
  139. return s.v, nil
  140. }
  141. func (s *protoSink) SetBytes(b []byte) error {
  142. err := proto.Unmarshal(b, s.dst)
  143. if err != nil {
  144. return err
  145. }
  146. s.v.b = cloneBytes(b)
  147. s.v.s = ""
  148. return nil
  149. }
  150. func (s *protoSink) SetString(v string) error {
  151. b := []byte(v)
  152. err := proto.Unmarshal(b, s.dst)
  153. if err != nil {
  154. return err
  155. }
  156. s.v.b = b
  157. s.v.s = ""
  158. return nil
  159. }
  160. func (s *protoSink) SetProto(m proto.Message) error {
  161. b, err := proto.Marshal(m)
  162. if err != nil {
  163. return err
  164. }
  165. // TODO(bradfitz): optimize for same-task case more and write
  166. // right through? would need to document ownership rules at
  167. // the same time. but then we could just assign *dst = *m
  168. // here. This works for now:
  169. err = proto.Unmarshal(b, s.dst)
  170. if err != nil {
  171. return err
  172. }
  173. s.v.b = b
  174. s.v.s = ""
  175. return nil
  176. }
  177. // AllocatingByteSliceSink returns a Sink that allocates
  178. // a byte slice to hold the received value and assigns
  179. // it to *dst. The memory is not retained by groupcache.
  180. func AllocatingByteSliceSink(dst *[]byte) Sink {
  181. return &allocBytesSink{dst: dst}
  182. }
  183. type allocBytesSink struct {
  184. dst *[]byte
  185. v ByteView
  186. }
  187. func (s *allocBytesSink) view() (ByteView, error) {
  188. return s.v, nil
  189. }
  190. func (s *allocBytesSink) setView(v ByteView) error {
  191. if v.b != nil {
  192. *s.dst = cloneBytes(v.b)
  193. } else {
  194. *s.dst = []byte(v.s)
  195. }
  196. s.v = v
  197. return nil
  198. }
  199. func (s *allocBytesSink) SetProto(m proto.Message) error {
  200. b, err := proto.Marshal(m)
  201. if err != nil {
  202. return err
  203. }
  204. return s.setBytesOwned(b)
  205. }
  206. func (s *allocBytesSink) SetBytes(b []byte) error {
  207. return s.setBytesOwned(cloneBytes(b))
  208. }
  209. func (s *allocBytesSink) setBytesOwned(b []byte) error {
  210. if s.dst == nil {
  211. return errors.New("nil AllocatingByteSliceSink *[]byte dst")
  212. }
  213. *s.dst = cloneBytes(b) // another copy, protecting the read-only s.v.b view
  214. s.v.b = b
  215. s.v.s = ""
  216. return nil
  217. }
  218. func (s *allocBytesSink) SetString(v string) error {
  219. if s.dst == nil {
  220. return errors.New("nil AllocatingByteSliceSink *[]byte dst")
  221. }
  222. *s.dst = []byte(v)
  223. s.v.b = nil
  224. s.v.s = v
  225. return nil
  226. }
  227. // TruncatingByteSliceSink returns a Sink that writes up to len(*dst)
  228. // bytes to *dst. If more bytes are available, they're silently
  229. // truncated. If fewer bytes are available than len(*dst), *dst
  230. // is shrunk to fit the number of bytes available.
  231. func TruncatingByteSliceSink(dst *[]byte) Sink {
  232. return &truncBytesSink{dst: dst}
  233. }
  234. type truncBytesSink struct {
  235. dst *[]byte
  236. v ByteView
  237. }
  238. func (s *truncBytesSink) view() (ByteView, error) {
  239. return s.v, nil
  240. }
  241. func (s *truncBytesSink) SetProto(m proto.Message) error {
  242. b, err := proto.Marshal(m)
  243. if err != nil {
  244. return err
  245. }
  246. return s.setBytesOwned(b)
  247. }
  248. func (s *truncBytesSink) SetBytes(b []byte) error {
  249. return s.setBytesOwned(cloneBytes(b))
  250. }
  251. func (s *truncBytesSink) setBytesOwned(b []byte) error {
  252. if s.dst == nil {
  253. return errors.New("nil TruncatingByteSliceSink *[]byte dst")
  254. }
  255. n := copy(*s.dst, b)
  256. if n < len(*s.dst) {
  257. *s.dst = (*s.dst)[:n]
  258. }
  259. s.v.b = b
  260. s.v.s = ""
  261. return nil
  262. }
  263. func (s *truncBytesSink) SetString(v string) error {
  264. if s.dst == nil {
  265. return errors.New("nil TruncatingByteSliceSink *[]byte dst")
  266. }
  267. n := copy(*s.dst, v)
  268. if n < len(*s.dst) {
  269. *s.dst = (*s.dst)[:n]
  270. }
  271. s.v.b = nil
  272. s.v.s = v
  273. return nil
  274. }