github.com/m3db/m3@v1.5.0/src/x/ident/identifier_pool.go (about)

     1  // Copyright (c) 2016 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package ident
    22  
    23  import (
    24  	"github.com/m3db/m3/src/x/checked"
    25  	"github.com/m3db/m3/src/x/context"
    26  	"github.com/m3db/m3/src/x/pool"
    27  )
    28  
    29  const (
    30  	defaultCapacityOptions    = 16
    31  	defaultMaxCapacityOptions = 32
    32  )
    33  
    34  // PoolOptions is a set of pooling options.
    35  type PoolOptions struct {
    36  	IDPoolOptions           pool.ObjectPoolOptions
    37  	TagsPoolOptions         pool.ObjectPoolOptions
    38  	TagsCapacity            int
    39  	TagsMaxCapacity         int
    40  	TagsIteratorPoolOptions pool.ObjectPoolOptions
    41  }
    42  
    43  func (o PoolOptions) defaultsIfNotSet() PoolOptions {
    44  	if o.IDPoolOptions == nil {
    45  		o.IDPoolOptions = pool.NewObjectPoolOptions()
    46  	}
    47  	if o.TagsPoolOptions == nil {
    48  		o.TagsPoolOptions = pool.NewObjectPoolOptions()
    49  	}
    50  	if o.TagsCapacity == 0 {
    51  		o.TagsCapacity = defaultCapacityOptions
    52  	}
    53  	if o.TagsMaxCapacity == 0 {
    54  		o.TagsMaxCapacity = defaultMaxCapacityOptions
    55  	}
    56  	if o.TagsIteratorPoolOptions == nil {
    57  		o.TagsIteratorPoolOptions = pool.NewObjectPoolOptions()
    58  	}
    59  	return o
    60  }
    61  
    62  // NewPool constructs a new simple Pool.
    63  func NewPool(
    64  	bytesPool pool.CheckedBytesPool,
    65  	opts PoolOptions,
    66  ) Pool {
    67  	opts = opts.defaultsIfNotSet()
    68  
    69  	p := &simplePool{
    70  		bytesPool: bytesPool,
    71  		pool:      pool.NewObjectPool(opts.IDPoolOptions),
    72  		tagArrayPool: newTagArrayPool(tagArrayPoolOpts{
    73  			Options:     opts.TagsPoolOptions,
    74  			Capacity:    opts.TagsCapacity,
    75  			MaxCapacity: opts.TagsMaxCapacity,
    76  		}),
    77  		itersPool: pool.NewObjectPool(opts.TagsIteratorPoolOptions),
    78  	}
    79  	p.pool.Init(func() interface{} {
    80  		return &id{pool: p}
    81  	})
    82  	p.tagArrayPool.Init()
    83  	p.itersPool.Init(func() interface{} {
    84  		return newTagSliceIter(Tags{}, nil, p)
    85  	})
    86  
    87  	return p
    88  }
    89  
    90  type simplePool struct {
    91  	bytesPool    pool.CheckedBytesPool
    92  	pool         pool.ObjectPool
    93  	tagArrayPool tagArrayPool
    94  	itersPool    pool.ObjectPool
    95  }
    96  
    97  func (p *simplePool) GetBinaryID(ctx context.Context, v checked.Bytes) ID {
    98  	id := p.BinaryID(v)
    99  	ctx.RegisterFinalizer(id)
   100  	return id
   101  }
   102  
   103  func (p *simplePool) BinaryID(v checked.Bytes) ID {
   104  	id := p.pool.Get().(*id)
   105  	v.IncRef()
   106  	id.pool, id.data = p, v
   107  	return id
   108  }
   109  
   110  func (p *simplePool) GetBinaryTag(
   111  	ctx context.Context,
   112  	name checked.Bytes,
   113  	value checked.Bytes,
   114  ) Tag {
   115  	return Tag{
   116  		Name:  TagName(p.GetBinaryID(ctx, name)),
   117  		Value: TagValue(p.GetBinaryID(ctx, value)),
   118  	}
   119  }
   120  
   121  func (p *simplePool) BinaryTag(
   122  	name checked.Bytes,
   123  	value checked.Bytes,
   124  ) Tag {
   125  	return Tag{
   126  		Name:  TagName(p.BinaryID(name)),
   127  		Value: TagValue(p.BinaryID(value)),
   128  	}
   129  }
   130  
   131  func (p *simplePool) GetStringID(ctx context.Context, v string) ID {
   132  	id := p.StringID(v)
   133  	ctx.RegisterFinalizer(id)
   134  	return id
   135  }
   136  
   137  func (p *simplePool) StringID(v string) ID {
   138  	data := p.bytesPool.Get(len(v))
   139  	data.IncRef()
   140  	data.AppendAll([]byte(v))
   141  	data.DecRef()
   142  
   143  	return p.BinaryID(data)
   144  }
   145  
   146  func (p *simplePool) GetTagsIterator(c context.Context) TagsIterator {
   147  	iter := p.itersPool.Get().(*tagSliceIter)
   148  	c.RegisterCloser(iter)
   149  	return iter
   150  }
   151  
   152  func (p *simplePool) TagsIterator() TagsIterator {
   153  	return p.itersPool.Get().(*tagSliceIter)
   154  }
   155  
   156  func (p *simplePool) Tags() Tags {
   157  	return Tags{
   158  		values: p.tagArrayPool.Get(),
   159  		pool:   p,
   160  	}
   161  }
   162  
   163  func (p *simplePool) Put(v ID) {
   164  	p.pool.Put(v)
   165  }
   166  
   167  func (p *simplePool) PutTag(t Tag) {
   168  	p.Put(t.Name)
   169  	p.Put(t.Value)
   170  }
   171  
   172  func (p *simplePool) PutTags(t Tags) {
   173  	p.tagArrayPool.Put(t.values)
   174  }
   175  
   176  func (p *simplePool) PutTagsIterator(iter TagsIterator) {
   177  	iter.Reset(Tags{})
   178  	p.itersPool.Put(iter)
   179  }
   180  
   181  func (p *simplePool) GetStringTag(ctx context.Context, name string, value string) Tag {
   182  	return Tag{
   183  		Name:  TagName(p.GetStringID(ctx, name)),
   184  		Value: TagValue(p.GetStringID(ctx, value)),
   185  	}
   186  }
   187  
   188  func (p *simplePool) StringTag(name string, value string) Tag {
   189  	return Tag{
   190  		Name:  TagName(p.StringID(name)),
   191  		Value: TagValue(p.StringID(value)),
   192  	}
   193  }
   194  
   195  func (p *simplePool) Clone(existing ID) ID {
   196  	var (
   197  		id      = p.pool.Get().(*id)
   198  		data    = existing.Bytes()
   199  		newData = p.bytesPool.Get(len(data))
   200  	)
   201  
   202  	newData.IncRef()
   203  	newData.AppendAll(data)
   204  
   205  	id.pool, id.data = p, newData
   206  
   207  	return id
   208  }
   209  
   210  func (p *simplePool) CloneTag(t Tag) Tag {
   211  	return Tag{
   212  		Name:  p.Clone(t.Name),
   213  		Value: p.Clone(t.Value),
   214  	}
   215  }
   216  
   217  func (p *simplePool) CloneTags(t Tags) Tags {
   218  	tags := p.tagArrayPool.Get()[:0]
   219  	for _, tag := range t.Values() {
   220  		tags = append(tags, p.CloneTag(tag))
   221  	}
   222  	return Tags{
   223  		values: tags,
   224  		pool:   p,
   225  	}
   226  }