hmetcd

package module
v1.10.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 10, 2021 License: MIT Imports: 11 Imported by: 1

README

This Go package wraps the ETCD Client V3 Go package.  

The reason for the wrapper is to reduce code bloat and repetition.  Common
K/V functions are made available and the Client V3 details hidden.

Functions available via this packages interface:

 o Open()           # Open a connection to ETCD
 o Close()          # Close a connection to ETCD
 o DistLock()       # Acquire distributed lock
 o DistTimedLock()  # Acquire lock but time out if already held
 o DistUnlock()     # Release dist'd lock
 o Store()          # Store a value for a key
 o Get()            # Get the value of a key
 o Delete()         # Delete a K/V
 o Transaction()    # Atomic if/then/else
 o TAS()            # Atomic test-and-set operation
 o Watch()          # Blocking watch for a key's value change or deletion
 o WatchWithCB()    # Watch for key val change/deletion in the background,
                    # call a callback function when change happens.
 o WatchCBCancel()  # Cancel a callback function watcher

IMPLEMENTATIONS:

There are 2 implementations to this interface:

 o Actual ETCD
 o Memory-backed

The actual ETCD interface will be used in production.   The memory-backed
interface can be used until the ETCD kubernetes pods are deployed and 
available.  It is also handy for local testing.


ETCD CLIENT V3 PACKAGE

Note that this is not necessary as it is part of our build tree.  It is noted
here for future reference.

To install the ETCD V3 client:

 o Make a directory and go to it.

 o GOPATH=`pwd` go get -v go.etcd.io/etcd/clientv3

 o cd go.etcd.io

 o mkdir ~/xxx/hms-services/go/src/vendor/go.etcd.io

 o cp -r * ~/xxx/hms-services/go/src/vendor/go.etcd.io

NOTE: this can't go under vendor/github.com because the code inside
go.etcd.io imports packages without the 'github.com' prefix.  Due to the
way GOPATH works this flat-out won't work.

One way to get it to work and be underneath github.com is to make a symlink
in the vendor directory to go.etcd.io, but it's not clear that can be 
checked into GIT.

GO DOCS

There is a rudimentary doc.go file that can be used by 'godoc' to generate
the documentation for this package.  To generate a static HTML file:

  cd go/src/hss/hmetcd
  GOPATH=`pwd`/../../.. godoc -html . > hmetcd.html

Documentation

Overview

This package contains GO interfaces for ETCD, based on the "clientV3" Go package.

Package hmetcd provides an interface to ETCD along with an alternate implementation using memory/map storage.

Index

Constants

View Source
const (
	KVC_KEYCHANGE_INVAL  = 0
	KVC_KEYCHANGE_PUT    = 1
	KVC_KEYCHANGE_DELETE = 2
)
View Source
const (
	DIST_LOCK_KEY = "hbtd_dist_lock"
)

Variables

This section is empty.

Functions

This section is empty.

Types

type KvcLockResult

type KvcLockResult int
const (
	KVC_LOCK_RSLT_INVALID KvcLockResult = 0
	KVC_LOCK_SET_FAIL     KvcLockResult = 1
	KVC_LOCK_OCCUPIED     KvcLockResult = 2
	KVC_LOCK_GRANTED      KvcLockResult = 3
	KVC_LOCK_RELEASE_FAIL KvcLockResult = 4
	KVC_LOCK_RELEASED     KvcLockResult = 5
)

type Kvi

type Kvi interface {
	DistLock() error
	DistTimedLock(tosec int) error
	DistUnlock() error
	Store(key string, value string) error
	TempKey(key string) error
	Get(key string) (string, bool, error)
	GetRange(keystart string, keyend string) ([]Kvi_KV, error)
	Delete(key string) error
	Transaction(key, op, value, thenkey, thenval, elsekey, elseval string) (bool, error)
	TAS(key string, testval string, setval string) (bool, error)
	Watch(key string) (string, int)
	WatchWithCB(key string, op int, cb WatchCBFunc, userdata interface{}) (WatchCBHandle, error)
	WatchCBCancel(cbh WatchCBHandle)
	Close() error
}

func Open

func Open(endpoint string, options string) (Kvi, error)

Opens an ETCD/MEM interface.

endpoint(in): ETCD endpoint URL, e.g. "http://10.2.3.4:2379" MEM endpoint URL, e.g. "mem:"

options(in): Array of option strings. Ignored for now. Someday there may be RBAC stuff, etc. in the options.

Return: ETCD or MEM data descriptor; nil on success, error string on error

type Kvi_KV

type Kvi_KV struct {
	Key   string
	Value string
}

type Kvs_etcd

type Kvs_etcd struct {
	// contains filtered or unexported fields
}

func (*Kvs_etcd) Close

func (kvs *Kvs_etcd) Close() error

(ETCD) Close an ETCD connection.

Args: None

Return: nil (reserved for future expansion)

func (*Kvs_etcd) Delete

func (kvs *Kvs_etcd) Delete(key string) error

(ETCD) Delete a key. Note that deleting a non-existent key is not an error.

key(in): Key to delete.

Return: nil on success, error string on error.

func (*Kvs_etcd) DistLock

func (kvs *Kvs_etcd) DistLock() error

(ETCD) Acquire a distributed lock. This is an atomic operation. The lock lives within ETCD and can be used by any number of other applications.

NOTE: if this lock is used multiple times within an application, it will just appear to acquire the lock multiple times. This is not the lock to use within an application; use plain mutexes instead. This lock is specifically designed to only work ACROSS applications, even multiple copies of the same application.

Args: None

Return: nil on success, error string on error.

func (*Kvs_etcd) DistTimedLock

func (kvs *Kvs_etcd) DistTimedLock(tosec int) error

(ETCD) Acquire a distributed lock, but time out if it remains held by some other actor. This can effectively be used as a "TryLock" by using a short timeout.

NOTE: if this lock is used multiple times within an application, it will just appear to acquire the lock multiple times. This is not the lock to use within an application; use plain mutexes instead. This lock is specifically designed to only work across applications, even multiple copies of the same application.

tosec(in): Number of seconds to wait for lock.

Return: nil on success, error string on error (including timeout).

func (*Kvs_etcd) DistUnlock

func (kvs *Kvs_etcd) DistUnlock() error

(ETCD) Unlock a distributed lock.

NOTE: if this lock is unlocked multiple times within an application, it will just appear to work. This is not the lock to use within an application; use plain mutexes instead. This lock is specifically designed to only work across applications, even multiple copies of the same application.

Args: None

Return: nil on success, error string on error.

func (*Kvs_etcd) Get

func (kvs *Kvs_etcd) Get(key string) (string, bool, error)

(ETCD) Get the value of a key. There are several possible return scenarios:

o There is an error fetching the key.  This will result in an empty key,
  non-nil error string and the key-exists indicator set to false.
o The key exists but has an empty-string value.  The return values will
  be an empty string, key-exists flag set to true, and a nil error.
o The key exists and has a non-empty value.  The return value will be
  the key's value, key-exissts flag set to true, and a nil error.

key(in): Key to get the value of.

Return: see above

func (*Kvs_etcd) GetRange

func (kvs *Kvs_etcd) GetRange(keystart string, keyend string) ([]Kvi_KV, error)

(ETCD) Get a range of keys. All keys returned will be lexicographically constrained by 'keystart' and 'keyend'. Note that ETCD doesn't have a way to just grab an arbitrary list of keys -- they must be a "range" where (returned_keys >= keystart) && (returned_keys <= keyend))

NOTE!!! The returned list of keys is NOT SORTED. This is to save time when callers don't care.

Also note: if there are no matches, an empty set is returned; this is not an error.

keystart(in): Key range start.

keyend(in): Key range end.

Return: Unsorted array of key/value structs on success; nil on success, error string on error

func (*Kvs_etcd) Store

func (kvs *Kvs_etcd) Store(key string, val string) error

(ETCD) Store a value of a key. If the key does not exist it is created.

key(in): Key to create or update.

val(in): Value to assign to they key.

Return: nil on success, else error string.

func (*Kvs_etcd) TAS

func (kvs *Kvs_etcd) TAS(key string, testval string, setval string) (bool, error)

(ETCD) Do an atomic Test-And-Set operation:

key(in): Key to test.

testval(in): Test value.

setval(in): Value to set if key value == test value.

Return: true if the set happened, else false; nil, unless an error occurred.

func (*Kvs_etcd) TempKey

func (kvs *Kvs_etcd) TempKey(key string) error

Create a temporary key. It will exist only for the life of the application. Once the app dies or aborts unexpectedly, the lease will expire and ETCD will delete the key. This is useful for horizontally scaled applications so that any given copy can know how many copies are running, as one example. When the key is created, some arbitrary token value is placed in the key (not specifyable by the caller).

key(in): Temporary key to create. Return: nil on success, error string on error.

func (*Kvs_etcd) Transaction

func (kvs *Kvs_etcd) Transaction(key, op, value, thenkey, thenval, elsekey, elseval string) (bool, error)

(ETCD) Perform a Transaction (atomic if... then... else...). Does the following case sensitive check:

if (value_of_key op value) then key.val = thenval else key.val = elseval

key(in): Key to check, drives the transaction.

op(in): Operator in "if" portion -- supports =, !=, <, and >.

value(in): Value to check against key's value in "if" portion.

thenkey(in): Key to change if "if" evaluates to TRUE.

thenval(in): Value to assign to key if "if" evaluates to TRUE.

elsekey(in): Key to change if "if" evaluates to FALSE.

elseval(in): Value to assign to key if "if" evaluates to FALSE.

Return: true if the 'if' portion succeeded, else 'false'; nil on success, error string if transaction fails to execute. if err != nil then no transaction took place

func (*Kvs_etcd) Watch

func (kvs *Kvs_etcd) Watch(key string) (string, int)

(ETCD) Watch a key and block until it either changes value, gets created, or gets deleted.

key(in): Key to watch.

Return: New key value if the value changed; Operation, either KVC_KEYCHANGE_PUT or KVC_KEYCHANGE_DELETE

func (*Kvs_etcd) WatchCBCancel

func (kvs *Kvs_etcd) WatchCBCancel(cbh WatchCBHandle)

(ETCD) Cancel a K/V watch-with-callback.

cbh(in): Watch handle from WatchWithCB().

Return: None.

func (*Kvs_etcd) WatchWithCB

func (kvs *Kvs_etcd) WatchWithCB(key string, op int, cb WatchCBFunc, userdata interface{}) (WatchCBHandle, error)

(ETCD) Set up a watcher goroutine for a key and call a callback function when there is a change. The callback func will get called when a key's value either changes or when the key is deleted.

Cancelation:

The watcher will run until the one of the following takes place:

o The key watched key is deleted,
o The callback function returns 'false'
o The watcher is manually cancelled by calling WatchCBCancel().

key(in): Key to watch.

op(in): Key change operation to watch for: KVC_KEYCHANGE_PUT, KVC_KEYCHANGE_DELETE

cb(in): Function to call when specified key changes as specified by 'op'.

userdata(in): Arbitrary data to pass to callback func.

Return: Handle (used for cancellation); nil on success, error string on error.

type Kvs_mem

type Kvs_mem struct {
	// contains filtered or unexported fields
}

func (*Kvs_mem) Close

func (kvs *Kvs_mem) Close() error

(MEM) Close an MEM connection. Note that we don't delete the underlying storage! This will more closely mimic the ETCD backing which remains after a close.

Args: None

Return: nil (reserved for future expansion)

func (*Kvs_mem) Delete

func (kvs *Kvs_mem) Delete(key string) error

(MEM) Delete a key. Note that deleting a non-existent key is not an error.

key(in): Key to delete.

Return: nil on success, error string on error.

func (*Kvs_mem) DistLock

func (kvs *Kvs_mem) DistLock() error

(MEM) Acquire a lock. Note that without ETCD backing, this won't work. That is OK because it makes no sense to use a memory-backed implementation in a horizontally scaled application! So, do nothing.

Args: None

Return: nil on success, error string on error.

func (*Kvs_mem) DistTimedLock

func (kvs *Kvs_mem) DistTimedLock(tosec int) error

(MEM) Acquire a distributed lock, but time out eventually. NOTE: THIS DOES NOT WORK -- mem: based instances can't do dist'd locks and are assumed to be single instance implementations. So, do nothing.

tosec(in): Number of seconds to wait for lock. (IGNORED)

Return: nil

func (*Kvs_mem) DistUnlock

func (kvs *Kvs_mem) DistUnlock() error

(MEM) Unlock a distributed lock. Since mem: based instances can't do dist'd locks, we do nothing.

Args: None

Return: nil on success, error string on error.

func (*Kvs_mem) Get

func (kvs *Kvs_mem) Get(key string) (string, bool, error)

(MEM) Get the value of a key. There are several possible return scenarios:

o There is an error fetching the key.  This will result in an empty key,
  non-nil error string and the key-exists indicator set to false.
o The key exists but has an empty-string value.  The return values will
  be an empty string, key-exists flag set to true, and a nil error.
o The key exists and has a non-empty value.  The return value will be
  the key's value, key-exissts flag set to true, and a nil error.

key(in): Key to get the value of.

Return: see above

func (*Kvs_mem) GetRange

func (kvs *Kvs_mem) GetRange(keystart string, keyend string) ([]Kvi_KV, error)

(MEM) Get a range of keys. All keys returned will be lexicographically constrained by 'keystart' and 'keyend'. Note that ETCD doesn't have a way to just grab an arbitrary list of keys -- they must be a "range" where (returned_keys >= keystart) && (returned_keys <= keyend))

NOTE!!! The returned list of keys is NOT SORTED. This is to save time when callers don't care.

Also note: if there are no matches, an empty set is returned; this is not an error.

keystart(in): Key range start.

keyend(in): Key range end.

Return: Unsorted array of key/value structs on success; nil on success, error string on error

func (*Kvs_mem) Store

func (kvs *Kvs_mem) Store(key string, val string) error

(MEM) Store a value of a key. If the key does not exist it is created.

key(in): Key to create or update.

val(in): Value to assign to they key.

Return: nil on success, else error string.

func (*Kvs_mem) TAS

func (kvs *Kvs_mem) TAS(key string, testval string, setval string) (bool, error)

(MEM) Do an atomic Test-And-Set operation:

key(in): Key to test.

testval(in): Test value.

setval(in): Value to set if key value == test value.

Return: true if the set happened, else false; nil, unless an error occurred.

func (*Kvs_mem) TempKey

func (kvs *Kvs_mem) TempKey(key string) error

Create a temporary key. Note that this does NOT mimic the ETCD implementation!! It will create the key, but it is up to the application developer to fake out the behavior of temp keys created by other instances.

key(in): Temporary key to create. Return: nil on success, error string on error.

func (*Kvs_mem) Transaction

func (kvs *Kvs_mem) Transaction(key, op, value, thenkey, thenval, elsekey, elseval string) (bool, error)

(MEM) Perform a Transaction (atomic if... then... else...). Does the following case sensitive check:

if (value_of_key op value) then key.val = thenval else key.val = elseval

key(in): Key to check, drives the transaction.

op(in): Operator in "if" portion -- supports =, !=, <, and >.

value(in): Value to check against key's value in "if" portion.

thenkey(in): Key to change if "if" evaluates to TRUE.

thenval(in): Value to assign to key if "if" evaluates to TRUE.

elsekey(in): Key to change if "if" evaluates to FALSE.

elseval(in): Value to assign to key if "if" evaluates to FALSE.

Return: true if the 'if' portion succeeded, else 'false'; nil on success, error string if transaction fails to execute. if err != nil then no transaction took place

func (*Kvs_mem) Watch

func (kvs *Kvs_mem) Watch(key string) (string, int)

(MEM) Watch a key and block until it either changes value, gets created, or gets deleted.

key(in): Key to watch.

Return: New key value if the value changed; Operation, either KVC_KEYCHANGE_PUT or KVC_KEYCHANGE_DELETE

func (*Kvs_mem) WatchCBCancel

func (kvs *Kvs_mem) WatchCBCancel(cbh WatchCBHandle)

(MEM) Cancel a K/V watch-with-callback.

cbh(in): Watch handle from WatchWithCB().

Return: None.

func (*Kvs_mem) WatchWithCB

func (kvs *Kvs_mem) WatchWithCB(key string, op int, cb WatchCBFunc, userdata interface{}) (WatchCBHandle, error)

(MEM) Set up a watcher goroutine for a key and call a callback function when there is a change. The callback func will get called when a key's value either changes or when the key is deleted.

Cancelation:

The watcher will run until the one of the following takes place:

o The key watched key is deleted,
o The callback function returns 'false'
o The watcher is manually cancelled by calling WatchCBCancel().

key(in): Key to watch.

op(in): Key change operation to watch for: KVC_KEYCHANGE_PUT,KVC_KEYCHANGE_DELETE

cb(in): Function to call when specified key changes as specified by 'op'.

userdata(in): Arbitrary data to pass to callback function.

Return: Handle (used for cancellation); nil on success, error string on error.

type WatchCBFunc

type WatchCBFunc func(key string, val string, op int, userdata interface{}) bool

type WatchCBHandle

type WatchCBHandle struct {
	// contains filtered or unexported fields
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL