containerd/vendor/github.com/nats-io/nats-streaming-server/stores/store.go

262 lines
8.1 KiB
Go

// Copyright 2016 Apcera Inc. All rights reserved.
package stores
import (
"errors"
"time"
"github.com/nats-io/gnatsd/server"
"github.com/nats-io/go-nats-streaming/pb"
"github.com/nats-io/nats-streaming-server/spb"
)
const (
// TypeMemory is the store type name for memory based stores
TypeMemory = "MEMORY"
// TypeFile is the store type name for file based stores
TypeFile = "FILE"
)
const (
// AllChannels allows to get state for all channels.
AllChannels = "*"
)
// Errors.
var (
ErrTooManyChannels = errors.New("too many channels")
ErrTooManySubs = errors.New("too many subscriptions per channel")
)
// Noticef logs a notice statement
func Noticef(format string, v ...interface{}) {
server.Noticef(format, v...)
}
// StoreLimits define limits for a store.
type StoreLimits struct {
// How many channels are allowed.
MaxChannels int
// Global limits. Any 0 value means that the limit is ignored (unlimited).
ChannelLimits
// Per-channel limits. If a limit for a channel in this map is 0,
// the corresponding global limit (specified above) is used.
PerChannel map[string]*ChannelLimits
}
// ChannelLimits defines limits for a given channel
type ChannelLimits struct {
// Limits for message stores
MsgStoreLimits
// Limits for subscriptions stores
SubStoreLimits
}
// MsgStoreLimits defines limits for a MsgStore.
// For global limits, a value of 0 means "unlimited".
// For per-channel limits, it means that the corresponding global
// limit is used.
type MsgStoreLimits struct {
// How many messages are allowed.
MaxMsgs int
// How many bytes are allowed.
MaxBytes int64
// How long messages are kept in the log (unit is seconds)
MaxAge time.Duration
}
// SubStoreLimits defines limits for a SubStore
type SubStoreLimits struct {
// How many subscriptions are allowed.
MaxSubscriptions int
}
// DefaultStoreLimits are the limits that a Store must
// use when none are specified to the Store constructor.
// Store limits can be changed with the Store.SetLimits() method.
var DefaultStoreLimits = StoreLimits{
100,
ChannelLimits{
MsgStoreLimits{
MaxMsgs: 1000000,
MaxBytes: 1000000 * 1024,
},
SubStoreLimits{
MaxSubscriptions: 1000,
},
},
nil,
}
// RecoveredState allows the server to reconstruct its state after a restart.
type RecoveredState struct {
Info *spb.ServerInfo
Clients []*Client
Subs RecoveredSubscriptions
}
// Client represents a client with ID, Heartbeat Inbox and user data sets
// when adding it to the store.
type Client struct {
spb.ClientInfo
UserData interface{}
}
// RecoveredSubscriptions is a map of recovered subscriptions, keyed by channel name.
type RecoveredSubscriptions map[string][]*RecoveredSubState
// PendingAcks is a set of message sequences waiting to be acknowledged.
type PendingAcks map[uint64]struct{}
// RecoveredSubState represents a recovered Subscription with a map
// of pending messages.
type RecoveredSubState struct {
Sub *spb.SubState
Pending PendingAcks
}
// ChannelStore contains a reference to both Subscription and Message stores.
type ChannelStore struct {
// UserData is set when the channel is created.
UserData interface{}
// Subs is the Subscriptions Store.
Subs SubStore
// Msgs is the Messages Store.
Msgs MsgStore
}
// Store is the storage interface for NATS Streaming servers.
//
// If an implementation has a Store constructor with StoreLimits, it should be
// noted that the limits don't apply to any state being recovered, for Store
// implementations supporting recovery.
//
type Store interface {
// Init can be used to initialize the store with server's information.
Init(info *spb.ServerInfo) error
// Name returns the name type of this store (e.g: MEMORY, FILESTORE, etc...).
Name() string
// SetLimits sets limits for this store. The action is not expected
// to be retroactive.
// The store implementation should make a deep copy as to not change
// the content of the structure passed by the caller.
// This call may return an error due to limits validation errors.
SetLimits(limits *StoreLimits) error
// CreateChannel creates a ChannelStore for the given channel, and returns
// `true` to indicate that the channel is new, false if it already exists.
// Limits defined for this channel in StoreLimits.PeChannel map, if present,
// will apply. Otherwise, the global limits in StoreLimits will apply.
CreateChannel(channel string, userData interface{}) (*ChannelStore, bool, error)
// LookupChannel returns a ChannelStore for the given channel, nil if channel
// does not exist.
LookupChannel(channel string) *ChannelStore
// HasChannel returns true if this store has any channel.
HasChannel() bool
// MsgsState returns message store statistics for a given channel, or all
// if 'channel' is AllChannels.
MsgsState(channel string) (numMessages int, byteSize uint64, err error)
// AddClient stores information about the client identified by `clientID`.
// If a Client is already registered, this call returns the currently
// registered Client object, and the boolean set to false to indicate
// that the client is not new.
AddClient(clientID, hbInbox string, userData interface{}) (*Client, bool, error)
// GetClient returns the stored Client, or nil if it does not exist.
GetClient(clientID string) *Client
// GetClients returns a map of all stored Client objects, keyed by client IDs.
// The returned map is a copy of the state maintained by the store so that
// it is safe for the caller to walk through the map while clients may be
// added/deleted from the store.
GetClients() map[string]*Client
// GetClientsCount returns the number of registered clients.
GetClientsCount() int
// DeleteClient removes the client identified by `clientID` from the store
// and returns it to the caller.
DeleteClient(clientID string) *Client
// Close closes all stores.
Close() error
}
// SubStore is the interface for storage of Subscriptions on a given channel.
//
// Implementations of this interface should not attempt to validate that
// a subscription is valid (that is, has not been deleted) when processing
// updates.
type SubStore interface {
// CreateSub records a new subscription represented by SubState. On success,
// it records the subscription's ID in SubState.ID. This ID is to be used
// by the other SubStore methods.
CreateSub(*spb.SubState) error
// UpdateSub updates a given subscription represented by SubState.
UpdateSub(*spb.SubState) error
// DeleteSub invalidates the subscription 'subid'.
DeleteSub(subid uint64)
// AddSeqPending adds the given message 'seqno' to the subscription 'subid'.
AddSeqPending(subid, seqno uint64) error
// AckSeqPending records that the given message 'seqno' has been acknowledged
// by the subscription 'subid'.
AckSeqPending(subid, seqno uint64) error
// Flush is for stores that may buffer operations and need them to be persisted.
Flush() error
// Close closes the subscriptions store.
Close() error
}
// MsgStore is the interface for storage of Messages on a given channel.
type MsgStore interface {
// State returns some statistics related to this store.
State() (numMessages int, byteSize uint64, err error)
// Store stores a message and returns the message sequence.
Store(data []byte) (uint64, error)
// Lookup returns the stored message with given sequence number.
Lookup(seq uint64) *pb.MsgProto
// FirstSequence returns sequence for first message stored, 0 if no
// message is stored.
FirstSequence() uint64
// LastSequence returns sequence for last message stored, 0 if no
// message is stored.
LastSequence() uint64
// FirstAndLastSequence returns sequences for the first and last messages stored,
// 0 if no message is stored.
FirstAndLastSequence() (uint64, uint64)
// GetSequenceFromTimestamp returns the sequence of the first message whose
// timestamp is greater or equal to given timestamp.
GetSequenceFromTimestamp(timestamp int64) uint64
// FirstMsg returns the first message stored.
FirstMsg() *pb.MsgProto
// LastMsg returns the last message stored.
LastMsg() *pb.MsgProto
// Flush is for stores that may buffer operations and need them to be persisted.
Flush() error
// Close closes the store.
Close() error
}