github.com/felipejfc/helm@v2.1.2+incompatible/pkg/storage/driver/memory.go (about)

     1  /*
     2  Copyright 2016 The Kubernetes Authors All rights reserved.
     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 driver
    18  
    19  import (
    20  	"bytes"
    21  	"fmt"
    22  	"io"
    23  	"strconv"
    24  	"strings"
    25  	"sync"
    26  
    27  	rspb "k8s.io/helm/pkg/proto/hapi/release"
    28  )
    29  
    30  var _ Driver = (*Memory)(nil)
    31  
    32  // MemoryDriverName is the string name of this driver.
    33  const MemoryDriverName = "Memory"
    34  
    35  // Memory is the in-memory storage driver implementation.
    36  type Memory struct {
    37  	sync.RWMutex
    38  	cache map[string]records
    39  }
    40  
    41  // NewMemory initializes a new memory driver.
    42  func NewMemory() *Memory {
    43  	return &Memory{cache: map[string]records{}}
    44  }
    45  
    46  // Name returns the name of the driver.
    47  func (mem *Memory) Name() string {
    48  	return MemoryDriverName
    49  }
    50  
    51  // Get returns the release named by key or returns ErrReleaseNotFound.
    52  func (mem *Memory) Get(key string) (*rspb.Release, error) {
    53  	defer unlock(mem.rlock())
    54  
    55  	switch elems := strings.Split(key, ".v"); len(elems) {
    56  	case 2:
    57  		name, ver := elems[0], elems[1]
    58  		if _, err := strconv.Atoi(ver); err != nil {
    59  			return nil, ErrInvalidKey
    60  		}
    61  		if recs, ok := mem.cache[name]; ok {
    62  			if r := recs.Get(key); r != nil {
    63  				return r.rls, nil
    64  			}
    65  		}
    66  		return nil, ErrReleaseNotFound
    67  	default:
    68  		return nil, ErrInvalidKey
    69  	}
    70  }
    71  
    72  // List returns the list of all releases such that filter(release) == true
    73  func (mem *Memory) List(filter func(*rspb.Release) bool) ([]*rspb.Release, error) {
    74  	defer unlock(mem.rlock())
    75  
    76  	var ls []*rspb.Release
    77  	for _, recs := range mem.cache {
    78  		recs.Iter(func(_ int, rec *record) bool {
    79  			if filter(rec.rls) {
    80  				ls = append(ls, rec.rls)
    81  			}
    82  			return true
    83  		})
    84  	}
    85  	return ls, nil
    86  }
    87  
    88  // Query returns the set of releases that match the provided set of labels
    89  func (mem *Memory) Query(keyvals map[string]string) ([]*rspb.Release, error) {
    90  	defer unlock(mem.rlock())
    91  
    92  	var lbs labels
    93  
    94  	lbs.init()
    95  	lbs.fromMap(keyvals)
    96  
    97  	var ls []*rspb.Release
    98  	for _, recs := range mem.cache {
    99  		recs.Iter(func(_ int, rec *record) bool {
   100  			if rec.lbs.match(lbs) {
   101  				ls = append(ls, rec.rls)
   102  			}
   103  			return true
   104  		})
   105  	}
   106  	return ls, nil
   107  }
   108  
   109  // Create creates a new release or returns ErrReleaseExists.
   110  func (mem *Memory) Create(key string, rls *rspb.Release) error {
   111  	defer unlock(mem.wlock())
   112  
   113  	if recs, ok := mem.cache[rls.Name]; ok {
   114  		if err := recs.Add(newRecord(key, rls)); err != nil {
   115  			return err
   116  		}
   117  		mem.cache[rls.Name] = recs
   118  		return nil
   119  	}
   120  	mem.cache[rls.Name] = records{newRecord(key, rls)}
   121  	return nil
   122  }
   123  
   124  // Update updates a release or returns ErrReleaseNotFound.
   125  func (mem *Memory) Update(key string, rls *rspb.Release) error {
   126  	defer unlock(mem.wlock())
   127  
   128  	if rs, ok := mem.cache[rls.Name]; ok && rs.Exists(key) {
   129  		rs.Replace(key, newRecord(key, rls))
   130  		return nil
   131  	}
   132  	return ErrReleaseNotFound
   133  }
   134  
   135  // Delete deletes a release or returns ErrReleaseNotFound.
   136  func (mem *Memory) Delete(key string) (*rspb.Release, error) {
   137  	defer unlock(mem.wlock())
   138  
   139  	switch elems := strings.Split(key, ".v"); len(elems) {
   140  	case 2:
   141  		name, ver := elems[0], elems[1]
   142  		if _, err := strconv.Atoi(ver); err != nil {
   143  			return nil, ErrInvalidKey
   144  		}
   145  		if recs, ok := mem.cache[name]; ok {
   146  			if r := recs.Remove(key); r != nil {
   147  				return r.rls, nil
   148  			}
   149  		}
   150  		return nil, ErrReleaseNotFound
   151  	default:
   152  		return nil, ErrInvalidKey
   153  	}
   154  }
   155  
   156  func (mem *Memory) dump(w io.Writer) error {
   157  	var b bytes.Buffer
   158  
   159  	fmt.Fprintln(&b, "memory:")
   160  	for key, recs := range mem.cache {
   161  		fmt.Fprintf(&b, "\t# %q\n", key)
   162  
   163  		recs.Iter(func(index int, r *record) bool {
   164  			fmt.Fprintf(&b, "\t\t- [%d] v%d (status = %s)\n",
   165  				index,
   166  				r.rls.Version,
   167  				r.rls.Info.Status.Code,
   168  			)
   169  
   170  			return true
   171  		})
   172  	}
   173  
   174  	_, err := w.Write(b.Bytes())
   175  	return err
   176  }
   177  
   178  // wlock locks mem for writing
   179  func (mem *Memory) wlock() func() {
   180  	mem.Lock()
   181  	return func() { mem.Unlock() }
   182  }
   183  
   184  // rlock locks mem for reading
   185  func (mem *Memory) rlock() func() {
   186  	mem.RLock()
   187  	return func() { mem.RUnlock() }
   188  }
   189  
   190  // unlock calls fn which reverses a mem.rlock or mem.wlock. e.g:
   191  // ```defer unlock(mem.rlock())```, locks mem for reading at the
   192  // call point of defer and unlocks upon exiting the block.
   193  func unlock(fn func()) { fn() }