...

Source file src/github.com/golang/groupcache/sinks.go

Documentation: github.com/golang/groupcache

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

View as plain text