zkstore

package
v0.0.0-...-3b86d9c Latest Latest
Warning

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

Go to latest
Published: Feb 5, 2019 License: Apache-2.0 Imports: 12 Imported by: 0

README

zstorage

A ZK-based object storage library

Overview

This library facilitates the storage of data in Zookeeper.

At a high level, the Store supports the following API:

Put(item Item) (Ident, error)
Get(ident Ident) (item Item, err error)
List(category string) (locations []Location, err error)
Variants(location Location) (variants []string, err error)
Delete(ident Ident) error
Close() error

Nomenclature

An Item fully represents an item in the datastore. Clients will provide an Item when Putting data and will receive an Item when Getting data.

An Item is fully identified by a composed Ident. The Ident points to a Location and also an optional Variant and an optional Version.

Variants

An item may have any number of variants. Note that this is different from the Version which is described below. If a client Puts an item with a variant, it will live as a child of the current node for that item.

Additionally, when deleting an item, the user may specify a variant. If no variant is specified when deleting an item, that item and all of its variant will be deleted.

Paths

Here is an example of how a typical path might look like in the system:

/[basePath]/[category]/buckets/[bucket]/[name]/[variant]

The basePath can be configured on the Store, and will be prepended to any znode path that is generated for an operation.

The category, name, and variant parts are set on the item's Ident property.

The bucket is generated by the Store using a configurable hashing function. It is derived by hashing the item name. The number of buckets to which a name might possibly hash can be configured when constructing the store.

Optimistic Locking

Part of an item's Ident is a Version field called Version.

When performing a Get, the Store will set the Version on the returned Item. This allows the client to specify that version when performing a subsequent mutating operation.

If this is set on an item's Ident property when performing a mutating operation, it will ensure that the item that is updated is specifically that version when setting it. If another client happened to set the item before the first client was able to do so, the library will return the ErrVersionConflict error. At this point, the client may choose to do another read and try again.

If the Item.Ident.Version is set to NoPriorVersion when passing an Item to Put() it is assumed that this Put() must create the item and it will return ErrVersionConflict if the node already exists. If no Version is specified, Put will create the node if it doesn't already exist or ignore and overwrite the existing Item with the new one if it does.

Documentation

Index

Constants

View Source
const (
	// ErrIllegalOption is returned when a StoreOpt configuration is set w/ an illegal value.
	ErrIllegalOption = internalError("illegal option configuration")

	// ErrVersionConflict is returned when a specified ZKVersion is rejected by
	// ZK when performing a mutating operation on a znode.  Clients that receive
	// this can retry by re-reading the Item and then trying again.
	ErrVersionConflict = internalError("zk version conflict")

	// ErrNotFound is returned when an attempting to read a znode that does not exist.
	ErrNotFound = internalError("znode not found")
)
View Source
const (
	// DefaultNumHashBuckets is the number of buckets that will be used to
	// spread out items living within a category by placing children of the
	// category into numerically named buckets.  Clients may choose to override
	// this by specifying OptNumHashBuckets when building the Store.
	DefaultNumHashBuckets = 256

	// DefaultBucketsZnodeName is the default name of parent znode that will
	// store the buckets for a particular category.  This is necessary to
	// allow categories like "foo" and "foo/bar", since we enforce that
	// category names cannot end in this name.  Clients may choose to override
	// this default by specifying OptBucketsZnodeName when building the
	// Store.
	DefaultBucketsZnodeName = "buckets"
)
View Source
const MaxDataSize = 1024 * 1024

MaxDataSize represents the size of the largest data blob that a caller can store.

View Source
const NoPriorVersion = -1

NoPriorVersion tells Put that we're expecting to create a new znode for a particular item, not to update an existing item. If znode already exists, then ErrVersionConflict may be returned.

Variables

View Source
var DefaultHashProviderFunc = HashProvider(md5.New)

DefaultHashProviderFunc is the default provider of hash functions unless overriden with OptHashProviderFunc when building the Store.

View Source
var (
	// DefaultZKACL is the default ACL set that will be used when creating
	// nodes in ZK unless overridden with OptACL when building the Store.
	DefaultZKACL = zk.WorldACL(zk.PermAll)
)

Functions

func LocationsByName

func LocationsByName(locations []Location) (interface{}, func(_, _ int) bool)

LocationsByName returns a sort function helper that may be passed to sort.Slice in order to sort a slice of Location structs.

func ValidateCategory

func ValidateCategory(name string) error

ValidateCategory checks that a category is required, and can look like a path or not.

func ValidateNamed

func ValidateNamed(name string, required bool) error

ValidateNamed validates items that have a "name". Like an actual Name or perhaps a Version. Since some names can be blank, we use the 'required' parameter to signify whether or not a name can be blank, and then after that we check against the regexp.

Types

type ConnectionOpts

type ConnectionOpts struct {
	// ConnectTimeout is the timeout to make the initial connection to ZK.
	ConnectTimeout time.Duration

	// InitialSessionTimeout is how long to wait for a valid session to
	// be established once the connection happens.
	InitialSessionTimeout time.Duration

	// Auth represents authentication details. If left alone, no auth will
	// be performed
	Auth struct {
		Schema string
		Secret []byte
	}
}

ConnectionOpts are used when creating a new Zk connection

type Connector

type Connector interface {
	// Connect returns a ZK connection
	Connect() (*zk.Conn, error)

	// Close should ensure the ZK connection is closed.
	Close() error
}

Connector specifies a way to connect to ZK

func ExistingConnection

func ExistingConnection(conn *zk.Conn) Connector

ExistingConnection returns an existing connection.

The existing connection should have already established a session before calling this method

func NewConnection

func NewConnection(addrs []string, opts ConnectionOpts) Connector

NewConnection returns a Connector that creates a new ZK connection

type HashProviderFunc

type HashProviderFunc func(string) (uint64, error)

HashProviderFunc is a factory for hashers.

func HashProvider

func HashProvider(f func() hash.Hash) HashProviderFunc

HashProvider adapts a golang stdlib hasher into a hash provider func for use by this package.

type IStore

type IStore interface {
	Put(item Item) (Ident, error)
	Get(ident Ident) (item Item, err error)
	List(category string) (locations []Location, err error)
	Variants(location Location) (variants []string, err error)
	Delete(ident Ident) error
	Close() error
}

IStore is the interface to which Store confirms. Documentation for these methods lives on the concrete Store type, as the NewStore method returns a concrete type, not this interface. Clients may choose to use the IStore interface if they wish.

type Ident

type Ident struct {
	// Location points to where an item lives in the store.
	Location

	// Variant, if specified, specifies a named version of the data.
	Variant string

	// Version specifies the ZK version of the data.  This will be
	// used to prevent accidental overwrites.  If Version is nil,
	// then the version will not be considered for operations.
	Version Version
}

Ident specifies the location of a stored item

func (Ident) String

func (i Ident) String() string

func (Ident) Validate

func (i Ident) Validate() error

Validate performs validation on the Ident

type Item

type Item struct {
	// Ident identifies an Item in the ZK backend.
	Ident

	// Data represents the bytes to be stored within the znode.
	Data []byte
}

Item represents the data of a particular item in the store

func (Item) String

func (i Item) String() string

func (Item) Validate

func (i Item) Validate() error

Validate performs validation on the Item

type Location

type Location struct {
	// Category is a base path for a particular category of data. For example,
	// this might be something like "widgets" or "widgets/2017" etc. This
	// field is required.
	Category string

	// Name is the name of the stored data. This field is required.
	Name string
}

Location points to a particular item in the store

func (Location) String

func (l Location) String() string

func (Location) Validate

func (l Location) Validate() error

Validate performs validation on the Location

type Store

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

Store exposes an API for performing CRUD operations against a backing ZK cluster.

func NewStore

func NewStore(connector Connector, opts ...StoreOpt) (*Store, error)

NewStore creates a new Store that is ready for use.

func (*Store) Close

func (s *Store) Close() error

Close shuts down the Store

func (*Store) Delete

func (s *Store) Delete(ident Ident) (err error)

Delete deletes the identified item. An error is NOT returned in the case where the item does not already exist in the store.

func (*Store) Get

func (s *Store) Get(ident Ident) (item Item, err error)

Get fetches the data for a particuar item. If a particluar version is desired, it must be set on the ident. Returns ErrNotFound if no such item exists.

func (*Store) List

func (s *Store) List(category string) (locations []Location, err error)

List lists all of the known, latest version Locations that exist under the specified category. Returns ErrNotFound if the category cannot be found within the store.

func (*Store) Put

func (s *Store) Put(item Item) (Ident, error)

Put stores the specified item. If successful, an Ident will be returned that reflects the updated metadata for that item (specifically, the Version)

If a client attempts to set an Item with a Variant, and the current item (with no Variant) does not exist yet, the current item will be created as well, with the same data as the specified Item.

Returns ErrVersionConflict if there is a Version mismatch between the item given and the version of the data currently stored. This check is not performed if there is no Version set for the given item.

func (*Store) Variants

func (s *Store) Variants(location Location) (variants []string, err error)

Variants fetches all of the variants for a particular item. Returns ErrNotFound if no item exists at the given location.

type StoreOpt

type StoreOpt func(store *Store) error

StoreOpt allows a Store to be configured. Returns ErrIllegalOption if the option configuration cannot be applied to the store.

func OptACL

func OptACL(acl []zk.ACL) StoreOpt

OptACL configures the store to use a particular ACL when creating nodes. A nil or empty ACL list does not alter the store configuration.

func OptBasePath

func OptBasePath(basePath string) StoreOpt

OptBasePath specifies a root path that will be prepended to all paths written to or read from. An empty path will not change the store configuration. The specified path must begin with "/" and be 'clean' (see path.Clean) otherwise ErrIllegalOption is returned.

func OptBucketsZnodeName

func OptBucketsZnodeName(name string) StoreOpt

OptBucketsZnodeName allows the client to configure the znode name that will contain the numerically-named bucket nodes. Returns ErrIllegalOption when the specifeid znode name is invalid.

func OptHashProviderFunc

func OptHashProviderFunc(hashProviderFunc HashProviderFunc) StoreOpt

OptHashProviderFunc allows the client to configure which hasher to use to map item names to buckets. A nil hash func does not alter the store configuration.

func OptNumHashBuckets

func OptNumHashBuckets(numBuckets int) StoreOpt

OptNumHashBuckets specifies the number of hash buckets that will be created under a store path for each content type when data is being written or read.

If this value is changed after data is written, previously written data may not be able to be found later. If the bucket count is zero then the store configuration is not altered. If the bucket count is negative then ErrIllegalOption is returned.

func (StoreOpt) Apply

func (f StoreOpt) Apply(store *Store) error

Apply is a convenience method that handles nil StoreOpt funcs w/ aplomb: it is perfectly legal to invoke StoreOpt(nil).Apply(someStore).

type Version

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

Version represents an optional ZK version number.

func NewVersion

func NewVersion(v int32) Version

NewVersion returns a ZK version w/ the given value. Future calls to Version will return true.

func (*Version) Clear

func (v *Version) Clear()

Clear erases the real ZK version number. Future calls to Version will return false.

func (Version) Value

func (v Version) Value() (int32, bool)

Value returns true with a real ZK version number, false when there is no value.

Jump to

Keyboard shortcuts

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