honu

package module
v0.0.0-...-3bfbf6a Latest Latest
Warning

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

Go to latest
Published: Mar 16, 2018 License: MIT Imports: 21 Imported by: 0

README

Honu

Throughput testing for a simple, volatile, in-memory key/value store.

Modes

Currently Honu can implement different modes of operation for a variety of experimental circumstances. The current dimensions are as follows:

Consistency

  • linearizable: the entire store is locked on writes and read-locked on reads
  • sequential: only the object for the specified keys is locked on accesses

Replication

  • standalone: no replication, the server exists in isolation
  • anti-entropy: full replication of objects using bilateral anti-entropy

Getting Started

First, fetch the code and install it:

$ go get github.com/bbengfort/honu/...

You should now have honu on your $PATH:

$ honu --help
Servers

You can run a server as follows:

$ honu serve

Which by default will run on :3264, you can specify a different address with the -a, --addr flag or the $HONU_SERVER_ADDR environment variable.

The default consistency mode for a server is linearizable, this means that the entire store is read locked to Get a value and write locked to Put a value. All versions have a single monotonically increasing version number and accesses between objects are totally ordered.

NOTE: linearizable here is only with respect to the local replica. Forks can still occur if concurrent accesses happen before replication.

In order to switch to sequential mode (each object is accessed independently with respect to key), specify the -r, --relax or set the $HONU_SEQUENTIAL_CONSISTENCY environment variable to true.

Clients and Throughput

Clients can be run as follows:

$ honu put -k foo -v bar
$ honu get -k foo

By default, the client will connect to a local server or the one specified by the $HONU_SERVER_ADDR; to specify a different address to connect to, use the -a, --addr flag.

The throughput experiment can be run for a specified duration as follows:

$ honu run -d 30s -k foo

This will test how many writes to the server can occur within 30 seconds.

Version History

The server can be quit using CTRL+C, it will perform any clean up required and shutdown. If you would like to dump a version log from the server on shutdown, run the server with the -o, --objects option:

$ honu server --objects path/to/version.log

This will write out the view of the replica; that is the version history that the replica has seen to a JSON file locally. Note that the version history is the chain or tree of versions that have been applied to objects, not the actual values!

Replication

For replication, servers need to know their peers. This can be specified with a comma delimited list using the -p, --peers flag, or using the $HONU_PEERS environment variable. Replication is the default mode, but will not occur if there are no peers (e.g. an empty string) or if the -s, --standalone flag is set (alternatively the $HONU_STANDALONE_MODE environment variable is set to true).

Replication is currently implemented by bilateral anti-entropy. Specify the anti-entropy delay with the -d, --delay flag or the $HONU_ANTI_ENTROPY_DELAY environment variable. This value must be a parseable duration, the default is 1s.

Configuration

You can create a .env file in the local directory that you're running honu from (or export environment variables) with the following configuration:

# Replica Configuration
HONU_PROCESS_ID=1
HONU_SERVER_ADDR=:3264
HONU_PEERS=""
HONU_STANDALONE_MODE=false
HONU_ANTI_ENTROPY_DELAY=1s
HONU_BANDIT_STRATEGY=uniform
HONU_SEQUENTIAL_CONSISTENCY=false
HONU_RANDOM_SEED=42

# Client and Experiment Configuration
HONU_LOCAL_KEY=foo
HONU_RUN_DURATION=30s
HONU_RUN_DISABLED=false

Hopefully this will help run experiments without typing in tons of arguments at the command line.

Experiments and Results

For more, see experiments and fixtures, which contains detailed listings of the various results and methods that employ Honu.

To run the anti-entropy reinforcement learning experiments:

$ cd fixtures/aerl

This directory contains the fabfile.py that runs the various ssh commands against the UMD replica servers. Install fabric with pip:

$ pip2 install fabric

Write go code to change the behavior of the system, then push it to Github. To update the code on the servers:

$ fab update

Make sure you're in the same working directory as the fabfile.py. To clean up previous results:

$ fab cleanup

And finally, to run clients with the specified configuration:

$ fab bench

Note that the configuration is found in config.json that declares the setup for each of the hosts.

Documentation

Index

Constants

View Source
const (
	Trace uint8 = iota
	Debug
	Info
	Caution
	Status
	Warn
	Silent
)

Levels for implementing the debug and trace message functionality.

View Source
const CautionThreshold = 80

CautionThreshold for issuing caution logs after accumulating cautions.

View Source
const DefaultAddr = ":3264"

DefaultAddr that the honu server listens on.

View Source
const PackageVersion = "0.11c"

PackageVersion of the current Honu implementation

View Source
const VisibilityBufferSize = 10000

VisibilityBufferSize describes the maximum number of async visiblity log statements before the caller will have to block.

Variables

View Source
var NullVersion = Version{0, 0}

NullVersion is the zero value version that does not exist.

Functions

func LogLevel

func LogLevel() string

LogLevel returns a string representation of the current level

func SetLogLevel

func SetLogLevel(level uint8)

SetLogLevel modifies the log level for messages at runtime. Ensures that the highest level that can be set is the trace level.

Types

type AnnealingEpsilonGreedy

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

AnnealingEpsilonGreedy implements a reinforcement learning strategy such that value of epsilon starts small then grows increasingly bigger, leading to an exploring learning strategy at start and prefering exploitation as more selections are made.

func (*AnnealingEpsilonGreedy) Counts

func (b *AnnealingEpsilonGreedy) Counts() []uint64

Counts returns the frequency each arm was selected

func (*AnnealingEpsilonGreedy) Epsilon

func (b *AnnealingEpsilonGreedy) Epsilon() float64

Epsilon is computed by the current number of trials such that the more trials have occured, the smaller epsilon is (on a log scale).

func (*AnnealingEpsilonGreedy) Init

func (b *AnnealingEpsilonGreedy) Init(nArms int)

Init the bandit with nArms number of possible choices, which are referred to by index in both the Counts and Values arrays.

func (*AnnealingEpsilonGreedy) Select

func (b *AnnealingEpsilonGreedy) Select() int

Select the arm with the maximizing value with probability epsilon, otherwise uniform random selection of all arms with probability 1-epsilon.

func (*AnnealingEpsilonGreedy) Serialize

func (b *AnnealingEpsilonGreedy) Serialize() interface{}

Serialize the bandit strategy to dump to JSON.

func (*AnnealingEpsilonGreedy) Update

func (b *AnnealingEpsilonGreedy) Update(arm int, reward float64)

Update the selected arm with the reward so that the strategy can learn the maximizing value (conditioned by the frequency of selection).

func (*AnnealingEpsilonGreedy) Values

func (b *AnnealingEpsilonGreedy) Values() []float64

Values returns the reward distribution of each arm

type BanditHistory

type BanditHistory struct {
	Arms    []int     `json:"arms"`    // selected arms per iteration
	Rewards []float64 `json:"rewards"` // reward values per iteration
}

BanditHistory tracks the selected arms and their rewards over time.

func NewBanditHistory

func NewBanditHistory() *BanditHistory

NewBanditHistory creates and returns a bandit history struct.

func (*BanditHistory) Update

func (h *BanditHistory) Update(arm int, reward float64)

Update the history

type BanditStrategy

type BanditStrategy interface {
	Init(nArms int)                 // Initialize the bandit with n choices
	Select() int                    // Selects an arm and returns the index of the choice
	Update(arm int, reward float64) // Update the given arm with a reward
	Counts() []uint64               // The frequency of each arm being selected
	Values() []float64              // The reward distributions for each arm
	Serialize() interface{}         // Return a JSON representation of the strategy
}

BanditStrategy specifies the methods required by an algorithm to compute multi-armed bandit probabilities for reinforcement learning. The basic mechanism allows you to initialize a strategy with n arms (or n choices). The Select() method will return a selected index based on the internal strategy, and the Update() method allows external callers to update the reward function for the selected arm.

type Benchmark

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

Benchmark runs clients sending continuous accesses to the remote server.

func NewBenchmark

func NewBenchmark(workers int, prefix string, visibility bool, extra map[string]interface{}) (*Benchmark, error)

NewBenchmark creates the data structure and clients.

func (*Benchmark) Results

func (b *Benchmark) Results(path string) error

Results writes the results to disk.

func (*Benchmark) Run

func (b *Benchmark) Run(addr, outpath string, duration, delay, rate time.Duration) error

Run the benchmark with the specified duration

func (*Benchmark) String

func (b *Benchmark) String() string

String returns the metrics results

type Client

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

Client wraps information about throughput to the storage server, each client works with a single key and maintains information about the version of each key as it generates work.

func (*Client) Access

func (c *Client) Access(done chan<- bool, echan chan<- error, rate time.Duration)

Access sends a put request, measuring latency.

func (*Client) Close

func (c *Client) Close() error

Close the connection to the server

func (*Client) Connect

func (c *Client) Connect(addr string) error

Connect creates the connection and rpc client to the server

func (*Client) Get

func (c *Client) Get(key string) ([]byte, string, error)

Get composes a Get Request and returns the value and version.

func (*Client) IsConnected

func (c *Client) IsConnected() bool

IsConnected verifies if the client is connected

func (*Client) Put

func (c *Client) Put(key string, value []byte, trackVisibility bool) (string, error)

Put composes a Put request and returns the version created.

func (*Client) Run

func (c *Client) Run(addr string, duration, rate time.Duration) error

Run a continuous access client for the specified duration.

type Entry

type Entry struct {
	sync.RWMutex
	Key             *string  // The associated key with the entry
	Version         *Version // The conflict-free version of the entry
	Parent          *Version // The version of the parent the entry was derived from
	Value           []byte   // The data value of the entry
	TrackVisibility bool     // Whether or not this entry is being tracked
	Current         uint64   // The current version scalar
}

Entry is a thin wrapper around values in the key/value store. It tracks meta data and is lockable for different types of consistency requirements.

type EpsilonGreedy

type EpsilonGreedy struct {
	Epsilon float64 // Probability of selecting maximizing value
	// contains filtered or unexported fields
}

EpsilonGreedy implements a reinforcement learning strategy such that the maximizing value is selected with probability epsilon and a uniform random selection is made with probability 1-epsilon.

func (*EpsilonGreedy) Counts

func (b *EpsilonGreedy) Counts() []uint64

Counts returns the frequency each arm was selected

func (*EpsilonGreedy) Init

func (b *EpsilonGreedy) Init(nArms int)

Init the bandit with nArms number of possible choices, which are referred to by index in both the Counts and Values arrays.

func (*EpsilonGreedy) Select

func (b *EpsilonGreedy) Select() int

Select the arm with the maximizing value with probability epsilon, otherwise uniform random selection of all arms with probability 1-epsilon.

func (*EpsilonGreedy) Serialize

func (b *EpsilonGreedy) Serialize() interface{}

Serialize the bandit strategy to dump to JSON.

func (*EpsilonGreedy) Update

func (b *EpsilonGreedy) Update(arm int, reward float64)

Update the selected arm with the reward so that the strategy can learn the maximizing value (conditioned by the frequency of selection).

func (*EpsilonGreedy) Values

func (b *EpsilonGreedy) Values() []float64

Values returns the reward distribution of each arm

type History

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

History keeps track of the version linkage (but does not store values) in order to evaluate the consistency of one model or another. It stores all versions in a single array, serializing appends via a channel that allows multiple go routines to stream version information to the history.

func (*History) Append

func (h *History) Append(key *string, parent, version *Version)

Append an entry to the version history.

func (*History) Init

func (h *History) Init()

Init the history with a buffered channel and dynamic array.

func (*History) Run

func (h *History) Run()

Run the history to continually pull entries off the queue, create version tree nodes and add them to the ordered version history.

type LinearizableStore

type LinearizableStore struct {
	sync.RWMutex
	// contains filtered or unexported fields
}

LinearizableStore implements a versioned, in-memory key-value store that keeps a single montonically increasing counter across all objects such that a single ordering for all writes (and associated reads) exists. All accesses are guarded by read and write locks to ensure linearizable consistency and version parents are the last written object no matter the key to create a cross-object version history.

func (*LinearizableStore) Get

func (s *LinearizableStore) Get(key string) (value []byte, version string, err error)

Get the most recently seen value and version pair for a specific key. Returns a not found error if the key has not been written to the namespace.

This operation wraps the entire store in a read lock, meaning that other values can be read but no values can be written on Get.

func (*LinearizableStore) GetEntry

func (s *LinearizableStore) GetEntry(key string) *Entry

GetEntry returns the entire entry from the namespace without a lock. Returns nil if the given key is not in the store.

func (*LinearizableStore) Init

func (s *LinearizableStore) Init(pid uint64)

Init the store creating the internal data structures.

func (*LinearizableStore) Length

func (s *LinearizableStore) Length() int

Length returns the number of items in the Store, namely the number of keys in the namespace. This does not reflect the number of versions.

func (*LinearizableStore) Put

func (s *LinearizableStore) Put(key string, value []byte, trackVisibility bool) (string, error)

Put a value into the namespace, incrementing the version across all objects. This operation creates an entry whose parent is the last written version of any object. Put also stores all versions and associated entries, maintaining a complete version history.

This operation locks the entire store, waiting for all read locks to be released and not allowing any other read or write locks until complete.

func (*LinearizableStore) PutEntry

func (s *LinearizableStore) PutEntry(key string, entry *Entry) bool

PutEntry without modifying version information. Returns true if the entry is modified or not -- will only put an entry that has a greater version than the current entry.

This method is also responsible for updating the lamport clock.

func (*LinearizableStore) Snapshot

func (s *LinearizableStore) Snapshot(path string) error

Snapshot the current version history to disk, writing the version data to the specified path. Returns any I/O errors if snapshotting is unsuccessful.

func (*LinearizableStore) Update

func (s *LinearizableStore) Update(key string, version *Version)

Update the current version counter with the global value.

func (*LinearizableStore) View

func (s *LinearizableStore) View() map[string]Version

View returns the current version for every key in the namespace.

type Locker

type Locker interface {
	sync.Locker
	RLock()
	RUnlock()
}

Locker is an interface for defining the sync.RWMutex methods including Lock and Unlock for write protection from sync.Locker and RLock and RUnlock for read protection.

type NopLogger

type NopLogger struct {
	*log.Logger
}

NopLogger is a noop logger for passing to grpclog to minimize spew.

func (*NopLogger) Fatal

func (l *NopLogger) Fatal(args ...interface{})

Fatal is a noop

func (*NopLogger) Fatalf

func (l *NopLogger) Fatalf(format string, args ...interface{})

Fatalf is a noop

func (*NopLogger) Fatalln

func (l *NopLogger) Fatalln(args ...interface{})

Fatalln is a noop

func (*NopLogger) Print

func (l *NopLogger) Print(args ...interface{})

Print is a noop

func (*NopLogger) Printf

func (l *NopLogger) Printf(format string, args ...interface{})

Printf is a noop

func (*NopLogger) Println

func (l *NopLogger) Println(v ...interface{})

Println is a noop

type NullWriter

type NullWriter int

NullWriter implements the io.Write interface but doesn't do anything.

func (NullWriter) Write

func (NullWriter) Write([]byte) (int, error)

Write implements the io.Write interface but is a noop.

type SequentialStore

type SequentialStore struct {
	sync.RWMutex
	// contains filtered or unexported fields
}

SequentialStore implements a key/value store where each key is versioned independently of all other keys. The Store is only locked when a new key is added, but readers and writers take locks on individual keys afterward. A sequential store therefore allows multi-thread access to different objects simultaneously.

The version history for objects in a sequential store is therefore relative to the object itself. Parent versions of entries are simply the previous entry in the store. Each object has its own independent scalar component.

func (*SequentialStore) Get

func (s *SequentialStore) Get(key string) (value []byte, version string, err error)

Get the most recently seen value and version pair for a specific key. Returns a not found error if the key has not been written to the namespace.

This operation only locks the store with a read-lock on fetch but also adds a read-lock to the entry so that it cannot be modified in flight.

func (*SequentialStore) GetEntry

func (s *SequentialStore) GetEntry(key string) *Entry

GetEntry returns the entire entry from the namespace without a lock. Returns nil if the given key is not in the store.

func (*SequentialStore) Init

func (s *SequentialStore) Init(pid uint64)

Init the store creating the internal data structures.

func (*SequentialStore) Length

func (s *SequentialStore) Length() int

Length returns the number of items in the Store, namely the number of keys in the namespace. This does not reflect the number of versions.

func (*SequentialStore) Put

func (s *SequentialStore) Put(key string, value []byte, trackVisibility bool) (string, error)

Put a value into the namespace and increment the version. Returns the version for the given key and any error that might occur.

func (*SequentialStore) PutEntry

func (s *SequentialStore) PutEntry(key string, entry *Entry) bool

PutEntry without modifying version information. Returns true if the entry is modified or not -- will only put an entry that has a greater version than the current entry.

This method is also responsible for updating the lamport clock.

func (*SequentialStore) Snapshot

func (s *SequentialStore) Snapshot(path string) error

Snapshot the current version history to disk, writing the version data to the specified path. Returns any I/O errors if snapshotting is unsuccessful.

func (*SequentialStore) Update

func (s *SequentialStore) Update(key string, version *Version)

Update the current version counter with the global value.

func (*SequentialStore) View

func (s *SequentialStore) View() map[string]Version

View returns the current version for every key in the namespace.

type Server

type Server struct {
	sync.Mutex
	// contains filtered or unexported fields
}

Server responds to Get and Put requests, modifying an in-memory store in a thread-safe fashion (because the store is surrounded by locks).

func NewServer

func NewServer(pid uint64, sequential bool) *Server

NewServer creates and initializes a server.

func (*Server) AntiEntropy

func (s *Server) AntiEntropy()

AntiEntropy performs a pairwise, bilateral syncrhonization with a random remote peer, first sending our version vector, then sending any required versions to the remote host.

NOTE: the view specified is the view at the start of anti-entropy.

func (*Server) GetValue

func (s *Server) GetValue(ctx context.Context, in *pb.GetRequest) (*pb.GetReply, error)

GetValue implements the RPC for a get request from a client.

func (*Server) Measure

func (s *Server) Measure(stats, history string)

Measure the Honu server activity on shutdown. Pass in the paths to write stats and history to on shutdown. If empty strings, they will be ignored.

func (*Server) Metrics

func (s *Server) Metrics(path string) error

Metrics writes server-side statistics as a JSON line to the specified path on disk. This function also logs the overall metrics (usually on shutdown) so if the path is an empty string, the metrics can be reported to the log without being saved to disk.

func (*Server) Pull

func (s *Server) Pull(ctx context.Context, in *pb.PullRequest) (*pb.PullReply, error)

Pull handles incoming push requests, comparing the object version with the current view of the server and returning a push reply with entries that are later than the remote and a pull request where the remote's versions are later. This method operates by read locking the entire store.

func (*Server) Push

func (s *Server) Push(ctx context.Context, in *pb.PushRequest) (*pb.PushReply, error)

Push handles incoming push requests, accepting any entries in the request that are later than the current view. It returns success if any synchronization occurs, otherwise false for a late push.

func (*Server) PutValue

func (s *Server) PutValue(ctx context.Context, in *pb.PutRequest) (*pb.PutReply, error)

PutValue implements the RPC for a put request from a client.

func (*Server) Replicate

func (s *Server) Replicate(peers []string, delay time.Duration, strategy string, epsilon float64) error

Replicate the Honu server using anti-entropy.

func (*Server) Run

func (s *Server) Run(addr string) error

Run the Honu server.

func (*Server) Shutdown

func (s *Server) Shutdown() error

Shutdown the Huno server, printing metrics.

func (*Server) Uptime

func (s *Server) Uptime(d time.Duration)

Uptime sets a fixed amount of time to keep the server up for, shutting it down when the duration has passed and exiting gracefully.

func (*Server) Visibility

func (s *Server) Visibility(path string) (err error)

Visibility opens the visibility logger at the specified path.

type Store

type Store interface {
	Locker
	Init(pid uint64)                                                                // Initialize the store
	Get(key string) (value []byte, version string, err error)                       // Get a value and version for a given key
	GetEntry(key string) *Entry                                                     // Get the entire entry without a lock
	Put(key string, value []byte, trackVisibility bool) (version string, err error) // Put a value for a given key and get associated version
	PutEntry(key string, entry *Entry) (modified bool)                              // Put the entry without modifying the version
	View() map[string]Version                                                       // Returns a map containing the latest version of all keys
	Update(key string, version *Version)                                            // Update the version scalar from a remote source
	Snapshot(path string) error                                                     // Write a snapshot of the version history to disk
	Length() int                                                                    // Returns the number of items in the store (number of keys)

}

Store is an interface for multiple in-memory storage types under the hood.

func NewStore

func NewStore(pid uint64, sequential bool) Store

NewStore creates and initializes a key value store

type SyncStats

type SyncStats struct {
	Syncs       uint64 // Total number of anti-entropy sessions between peers
	Pulls       uint64 // Number of successful pull exchanges between peers
	Pushes      uint64 // Number of successful push exchanges between peers
	Misses      uint64 // Number of unsuccessful exchanges between peers
	Versions    uint64 // The total number of object versions exchanged
	PullLatency *stats.Benchmark
	PushLatency *stats.Benchmark
	// contains filtered or unexported fields
}

SyncStats represents per-peer pairwise metrics of synchronization.

func (*SyncStats) Init

func (s *SyncStats) Init()

Init the Syncstats to ensure it's ready for updating.

func (*SyncStats) Serialize

func (s *SyncStats) Serialize() map[string]interface{}

Serialize the SyncStats to write to disk

func (*SyncStats) Update

func (s *SyncStats) Update(latency time.Duration, method string) error

Update the latency of the given type

type Syncs

type Syncs map[string]*SyncStats

Syncs is a map of peer hostnames to their synchronization statistics.

func (Syncs) Serialize

func (s Syncs) Serialize() map[string]interface{}

Serialize the syncs to save to JSON format.

type Uniform

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

Uniform selects all values with an equal likelihood on every selection. While it tracks the frequency of selection and the reward costs, this information does not affect the way it selects values.

func (*Uniform) Counts

func (b *Uniform) Counts() []uint64

Counts returns the frequency each arm was selected

func (*Uniform) Init

func (b *Uniform) Init(nArms int)

Init the bandit with nArms number of possible choices, which are referred to by index in both the Counts and Values arrays.

func (*Uniform) Select

func (b *Uniform) Select() int

Select the arm with equal probability for each choice.

func (*Uniform) Serialize

func (b *Uniform) Serialize() interface{}

Serialize the bandit strategy to dump to JSON.

func (*Uniform) Update

func (b *Uniform) Update(arm int, reward float64)

Update the selected arm with the reward so that the strategy can learn the maximizing value (conditioned by the frequency of selection).

func (*Uniform) Values

func (b *Uniform) Values() []float64

Values returns the reward distribution of each arm

type Version

type Version struct {
	Scalar uint64 // monotonically increasing scalar version number (starts at one)
	PID    uint64 // process identifier for tie-breaks (should not be zero)
}

Version implements conflict-free or concurrent versioning for objects.

func ParseVersion

func ParseVersion(s string) (Version, error)

ParseVersion converts a version string into a version object.

func (Version) Equals

func (v Version) Equals(o *Version) bool

Equals compares two *Versions to determine if they're identical.

func (Version) Greater

func (v Version) Greater(o *Version) bool

Greater returns true if the local version is later than the other version.

func (Version) GreaterEqual

func (v Version) GreaterEqual(o *Version) bool

GreaterEqual returns true if the local version is greater than or equal to the other version.

func (Version) IsZero

func (v Version) IsZero() bool

IsZero determines if a version is null

func (Version) Lesser

func (v Version) Lesser(o *Version) bool

Lesser returns true if the local version is earlier than the other version.

func (Version) LesserEqual

func (v Version) LesserEqual(o *Version) bool

LesserEqual returns true if the local version is less than or equal to the other version.

func (Version) String

func (v Version) String() string

String returns a parsable representation of the version number.

type VersionFactory

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

VersionFactory tracks version information and returns new versions on a per-key basis. Implements Lamport scalar versioning. Note that the factory is not thread-safe and should be used in a thread-safe object.

func (*VersionFactory) Next

func (f *VersionFactory) Next(key string) *Version

Next creates and returns the next version for the given key.

func (*VersionFactory) Update

func (f *VersionFactory) Update(key string, vers *Version)

Update the latest version with the version for the given key.

type VersionNode

type VersionNode struct {
	Key     *string
	Parent  *Version
	Version *Version
}

VersionNode is similar to an Entry, but omits the value, allowing for a compact version chain that can be stored in memory, written to disk and otherwise evaluated as needed.

type VisibilityLogger

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

VisibilityLogger records the time a write becomes visible on the local replica, storing the information on disk. It uses an asynchronous writer so it doesn't block other store operations.

func NewVisibilityLogger

func NewVisibilityLogger(path string) (*VisibilityLogger, error)

NewVisibilityLogger creates a logger for write visibility at the path.

func (*VisibilityLogger) Close

func (l *VisibilityLogger) Close() error

Close the logger and wait until it's done writing all buffered messages.

func (*VisibilityLogger) Error

func (l *VisibilityLogger) Error() error

Error returns any issues the visibility logger had

func (*VisibilityLogger) Log

func (l *VisibilityLogger) Log(key, version string)

Log a Put to the key/value store

Directories

Path Synopsis
cmd
honu command
Package rpc is a generated protocol buffer package.
Package rpc is a generated protocol buffer package.

Jump to

Keyboard shortcuts

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