Documentation
¶
Overview ¶
Package keystore содержит реализацию простого хранилища данных по ключу (key-value store).
Все данные хранятся в одном файле и не используют отдельного индекса. При первом открытии хранилища происходит построение индекса с содержимым файла и проверка целостности хранилища. Эта операция может занимать некоторое время при открытии действительно больших файлов, поэтому данная библиотека расчитана в первую очередь на небольшие хранилища.
По умолчанию все записи в хранилище заканчиваются вызовом метода os.File.Sync, что позволяет быть до некоторой степени уверенными, что данные при сбое не потеряются. Но, к сожалению, это одновременно сильно замедляет любую операцию записи. Если вы хотите самостоятельно управлять операциями сброса кешей файловой системы, то можно вызвать метод db.SetSync(false) и затем вызывать метод db.Sync вручную из кода.
При удалении или перезаписи значений, свободные участки помечаются специальным образом и в дальнейшем используются повторно, когда в них может уместиться новая запись. Таким образом файл не очень сильно разрастается при большом количестве удалений/вставок новый записей, при условии, что новые значения не превышают по объему удаленные.
При работе с хранилищем поддерживаются групповые операции: db.Gets, db.Puts, db.Deletes. Так же добавлены методы для работы с данными в формате JSON и автоматического преобразования объектов в/из него.
Работа с ключами хранилища и выборки данных поддерживается единственным методом db.Keys, который позволяет достаточно гибко выбирать только те ключи, которые соответствуют заданным критериям. Список ключей всегда возвращается в упорядоченном виде и может быть использован в дальнейшем для выполнения групповых операций.
То, что ключи представлены в виде string не ограничивает вас в использовании бинарных данных. Например, ключ может быть и вида "\x00\x00\x00\xc7". Так что это говорит только о том, что ключ не может динамически изменять свое значение.
Для облегчения работы с данной библиотекой все методы хранилища продублированы в виде глобальных функций, где первым параметром указывается имя файла с хранилищем. Открытые таким образом хранилища кешируются в глобальном списке и могут быть закрыты все сразу вызовом CloseAll.
Example ¶
package main import ( "encoding/json" "log" "os" "time" "github.com/mdigger/keystore" ) func main() { // автоматически закрыть по окончании все открытые хранилища defer keystore.CloseAll() var dbname = "db/test.db" // имя файла с хранилищем данных // сохраняем данные в хранилище в формате JSON // если такого файла с хранилищем не существует, то он будет создан // автоматически err := keystore.PutsJSON(dbname, map[string]interface{}{ "t1": "text message", "t2": 24, "t3": time.Date(1971, time.December, 24, 23, 0, 0, 0, time.UTC), "t4": &struct { Text string `json:"text"` }{ Text: "test", }, }) if err != nil { log.Fatal("PutsJSON error:", err) } // выбираем все ключи, сохраненные в хранилище, которые начинаются на `t` keys, err := keystore.Keys(dbname, "t", "", 0, 0, true) if err != nil { log.Fatal("Keys error:", err) } // получаем список значений из выборки по ключам result, err := keystore.GetsJSON(dbname, keys...) if err != nil { log.Fatal("GetsJSON error:", err) } // выводим выбранные значения в консоль в виде JSON enc := json.NewEncoder(os.Stdout) enc.SetIndent("", " ") err = enc.Encode(result) if err != nil { log.Fatal("JSON encode error:", err) } }
Output: [ "text message", 24, "1971-12-24T23:00:00Z", { "text": "test" } ]
Index ¶
- Variables
- func Bytes(v interface{}) ([]byte, error)
- func Close(filename string) error
- func CloseAll()
- func Count(filename string) (uint32, error)
- func Delete(filename, key string) error
- func Deletes(filename string, keys ...string) error
- func Get(filename, key string) ([]byte, error)
- func GetJSON(filename, key string, v interface{}) error
- func Gets(filename string, keys ...string) (result [][]byte, err error)
- func GetsJSON(filename string, keys ...string) (result []json.RawMessage, err error)
- func Has(filename, key string) (bool, error)
- func Keys(filename, prefix, last string, offset, limit uint32, asc bool) ([]string, error)
- func NextSequence(filename string) (uint64, error)
- func OpenAll(filenames ...string) error
- func Put(filename, key string, value interface{}) error
- func PutJSON(filename, key string, value interface{}) error
- func Puts(filename string, values map[string]interface{}) error
- func PutsJSON(filename string, values map[string]interface{}) error
- func Remove(filename string) error
- type DB
- func (db *DB) Close() error
- func (db *DB) Count() uint32
- func (db *DB) Delete(key string) error
- func (db *DB) Deletes(keys ...string) error
- func (db *DB) Get(key string) ([]byte, error)
- func (db *DB) GetJSON(key string, v interface{}) error
- func (db *DB) Gets(keys ...string) (result [][]byte, err error)
- func (db *DB) GetsJSON(keys ...string) (result []json.RawMessage, err error)
- func (db *DB) Has(key string) bool
- func (db *DB) Keys(prefix, last string, offset, limit uint32, asc bool) []string
- func (db *DB) NextSequence() (uint64, error)
- func (db *DB) Path() string
- func (db *DB) Put(key string, value []byte) error
- func (db *DB) PutJSON(key string, value interface{}) error
- func (db *DB) Puts(values map[string][]byte) error
- func (db *DB) PutsJSON(values map[string]interface{}) error
- func (db *DB) SetSync(sync bool)
- func (db *DB) String() string
- func (db *DB) Sync() error
- type Timestamp
- type UID
- func (uid UID) Byte() []byte
- func (uid UID) Counter() uint16
- func (uid UID) MarshalBinary() ([]byte, error)
- func (uid UID) MarshalText() (text []byte, err error)
- func (uid UID) String() string
- func (uid UID) Time() time.Time
- func (uid *UID) UnmarshalBinary(data []byte) error
- func (uid *UID) UnmarshalText(data []byte) error
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrNotFound = errors.New("key not found")
ErrNotFound возвращается, если данные с таким ключом в хранилище не найдены.
Если вы не хотите отдельно обрабатывать эту ошибку, то можно установить ее значение в nil. Так же иногда бывает удобно переопределить эту ошибку на какую-то другую, более полезную в приложении. Например, для веб-сервера можно переопределить ее в rest.ErrNotFound и тогда не потребуется отдельной проверки на то, что значения с таким ключем нет в хранилище.
Functions ¶
func Bytes ¶
Bytes преобразует данные в бинарный формат с помощью binary.BigEndian. Отдельная обработка добавлена для string, []byte, json.RawMessage, byte и всех остальных, кто поддерживает encoding.BinaryMarshaler, encoding.TextMarshaler, json.Marshaler или fmt.Stringer. Возвращает ошибку, если преобразование не получилось.
func Close ¶
Close закрывает хранилище с указанным именем. Не возвращает ошибку, если хранилище не было открыто.
func CloseAll ¶
func CloseAll()
CloseAll закрывает все открытые хранилища. Ошибка закрытия хранилищ не обрабатывается.
func Deletes ¶
Deletes удаляет список ключей из хранилища. В отличие от метода Delete, позволяет удалить более одного ключа сразу и не возвращает ошибку при отсуствии ключа в хранилище.
func Get ¶
Get возвращает данные, сохраненные с указанным ключом. Если данных с таким ключем в хранилище нет, то возвращается ошибка ErrNotFound.
func GetJSON ¶
GetJSON преобразует значение из хранилища в объект. Значение в хранилище должно быть представлено в формате JSON, иначе вернется ошибка.
func Gets ¶
Gets возвращает список значений, соответствующих списку ключей. Игнорирует ошибки с ненайденными ключами: в этом случае в качестве значения для данного ключа будет возвращен nil.
func GetsJSON ¶
func GetsJSON(filename string, keys ...string) (result []json.RawMessage, err error)
GetsJSON возвращает массив значений для указанных ключей в формате json.RawMessage. Возвращает ошибку, если данные не соответствуют формату JSON. Для ненайденных ключей возвращается значение nil.
func Keys ¶
Keys возвращает список ключей, подходящих под запрос.
Подробную информацию по параметрам смотри в описании метода db.Keys.
func NextSequence ¶
NextSequence возвращает значение счетчика, которое увеличивается при каждом обращении к данной функции хранилища.
func OpenAll ¶
OpenAll открывает сразу несколько хранилищ с указанными именами файлов. Позволяет провести инициализацию всех используемых хранилищ приложения в одном месте и убедиться, что они существуют или будут созданы.
func Put ¶
Put сохраняет данные в хранилище с указанным ключом. Если данные с таким ключом уже были сохранены в хранилище, то они удаляются и перезаписываются на новые. Значение автоматически преобразуется в формат []byte, используя функцию Bytes.
func PutJSON ¶
PutJSON сохраняет данные в хранилище с указанным ключом в формате JSON. Возвращает ошибку, если не удалось преобразовать объект в формат JSON.
func Puts ¶
Puts позволяет записать сразу несколько значений в хранилище. Для передачи списка данных используется словарь с именем ключа и связанным с ним значением. Для приведения значений к формату []byte используется функция Bytes.
Types ¶
type DB ¶
type DB struct {
// contains filtered or unexported fields
}
DB описывает файловое хранилище данных, где значения задаются и выбираются с помощью ключа (key-value store).
func Open ¶
Open возвращает открытую базу с хранилищем в указанном файле. Если база уже была открыта, то повторного открытия не происходит, а возвращается ссылка на ранее открытую.
При первом открытии файла происходит построение индекса ключей и проверка целостности данных, в процессе чего файл читается от начала и до конца. При очень больших файлах данных это может занимать некоторое время, поэтому не рекомендуется использовать эту библиотеку для хранения большого количества данных.
По умолчанию хранилище открывается в синхронном режиме: т.е. любая запись в хранилище приводит к принудительному сбросу данных в файл, что сильно замедляет работу. Если вы хотите самостоятельно управлять процессом сброса кеша или довериться операционной системе, то используйте вызов метода db.SetSync(false).
func (*DB) Close ¶
Close закрывает хранилище. Если специально не задано не выполнять синхронизацию, то при этом происходит принудительный сброс кешей в файл. Повторное выполнение уже закрытого хранилища не приводит к ошибке.
func (*DB) Delete ¶
Delete удаляет ключ из хранилища. Если значения с таким ключом в хранилище нет, то возвращается ошибка ErrNotFound.
func (*DB) Deletes ¶
Deletes удаляет список ключей из хранилища. В отличие от метода Delete, не возвращает ошибку об отсуствии ключа в хранилище.
func (*DB) Get ¶
Get возвращает данные, сохраненные с указанным ключом. Если данные с таким ключем в хранилище не сохранены, то возвращается ошибка ErrNotFound и nil в качестве значения. Для пустого значения (nil) всегда возвращается пуcтой массив байт ([]byte{}).
func (*DB) GetJSON ¶
GetJSON преобразует значение из хранилища обратно в объект. Возвращает ошибку, если данные с таким ключем не сохранены или формат сохраненных данных не соответствует формату JSON.
func (*DB) Gets ¶
Gets возвращает список значений, соответствующих списку ключей. Игнорирует ошибки с ненайденными ключами: в этом случае в качестве значения для такого ключа будет возвращено nil.
func (*DB) GetsJSON ¶
func (db *DB) GetsJSON(keys ...string) (result []json.RawMessage, err error)
GetsJSON возвращает массив значений для указанных ключей в формате json.RawMessage. Возвращает ошибку, если сохраненные данные не соответствуют формату JSON. Для тех ключей, для которых не задано значение, возвращается nil.
Данную функцию удобно использовать для отдачи результатов выборки в ответ на HTTP-запрос.
func (*DB) Keys ¶
Keys возвращает список ключей, подходящих под запрос.
Для выборки по ключам используется их отсортированный список. Сортировка осуществляется, в первую очередь, по длине ключа, а только потом по алфавиту. Т.е. более короткие ключи имеют больший приоритет. Порядок сортировки задается параметром asc: при значении false сортировка меняется на обратную. Следует обратить на это особое внимание, т.к. данная опция сильно влияет на то, как будет интерпретироваться параметр last.
Если указан prefix, то будут выбраны только те ключи, которые начинаются с этого префикса.
last позволяет выбрать только те ключи, которые идут за или перед индексом (в зависимости от asc) с этим значением (не включая сам элемент last). Ключ со значением last не обязательно должен присутствовать в хранилище: в этом случае просто отбрасывается все до того места, где бы он мог быть в отсортированном списке.
offset задает сдвиг относительно начала списка, а limit - ограничивает количество ключей в выборке.
Example ¶
package main import ( "fmt" "log" "github.com/mdigger/keystore" ) func main() { // открываем хранилище db, err := keystore.Open("db/test_keys.db") if err != nil { log.Fatal(err) } defer db.Close() // закрываем по окончании // заносим тестовые данные err = db.PutsJSON(map[string]interface{}{ "test1": 1, "test2": 2, "test3": 3, "test4": 4, "test5": 5, "aaaa6": 6, }) if err != nil { log.Fatal(err) } // выбираем все ключи, которые начинаются на `test` keys := db.Keys("test", "", 0, 0, true) fmt.Printf("1: %q\n", keys) // выбираем все ключи, которые начинаются на `test`, но после ключа `test2` keys = db.Keys("test", "test2", 0, 0, true) fmt.Printf("2: %q\n", keys) // сортируем вывод в обратном порядке keys = db.Keys("", "", 0, 0, false) fmt.Printf("3: %q\n", keys) // выбираем не более двух ключей keys = db.Keys("test", "test2", 0, 2, true) fmt.Printf("4: %q\n", keys) // не используем префикс ключа, а выбираем по всем keys = db.Keys("", "test3", 0, 0, false) fmt.Printf("5: %q\n", keys) }
Output: 1: ["test1" "test2" "test3" "test4" "test5"] 2: ["test3" "test4" "test5"] 3: ["test5" "test4" "test3" "test2" "test1" "aaaa6"] 4: ["test3" "test4"] 5: ["test2" "test1" "aaaa6"]
func (*DB) NextSequence ¶
NextSequence возвращает значение счетчика, которое увеличивается при каждом обращении к данной функции. Обычно используется для задания гарантированного уникального идентификатора записи хранилища, т.к. последнее использованное значение сохраняется в хранилище.
func (*DB) Put ¶
Put сохраняет данные в хранилище с указанным ключом. Если данные с таким ключом уже были ранее сохранены в хранилище, то они перезаписываются.
func (*DB) PutJSON ¶
PutJSON сохраняет данные в хранилище с указанным ключом в формате JSON. Возвращает ошибку, если не удалось преобразовать объект в формат JSON.
func (*DB) Puts ¶
Puts позволяет записать сразу несколько значений в хранилище. Данные передаются в виде связанного списка: ключ - значение. Т.к. ключем в map не может выступать изменяемый массив байт, то значение ключа задается в виде строки.
func (*DB) PutsJSON ¶
PutsJSON сохраняет в хранилище объекты в формате JSON. Возвращает ошибку, если не удалось преобразовать объект в формат JSON. При этом те значения, которые на момент ошибки уже были сохранены в хранилище, остаются.
func (*DB) SetSync ¶
SetSync устанавливает значение флага автоматического сброса кеша после каждой записи.
type Timestamp ¶
Timestamp подменяет представление времени в формате JSON в виде числа.
func (Timestamp) MarshalJSON ¶
MarshalJSON представляет время в формате JSON в виде числа.
func (*Timestamp) UnmarshalJSON ¶
UnmarshalJSON десериализует представление времени из формата JSON.
type UID ¶
type UID uint64
UID представляет из себя уникальный идентификатор, основанный на временной метке и внутреннем счетчике. Его удобно использовать в качестве глобального уникального идентификатора сразу для нескольких хранилищ, так как его значения действительно будут уникальными и монотонно возрастающими, что позволяет использовать сортировку ключей в запросах. В качестве точки отсчета используется дата 2006-01-02T15:04:05Z07:00.
func DateUID ¶
DateUID возвращает уже не совсем уникальный идентификатор для указанных даты и времени, но без учета счетчика. Может использоваться для выборки ключей до или после указанной даты.
Даты до 2006-01-02T15:04:05Z07:00 считаются невалидными и используются как нулевые значения, чтобы не нарушать порядок сортировки.
func NewUID ¶
func NewUID() UID
NewUID возвращает уникальный идентификатор, основанный на времени и внутреннем счетчике. Шесть байт отведено под текущее время, и два байта - под счетчик.
func ParseUID ¶
ParseUID разбирает уникальный идентификатор из строки. В случае ошибки разбора будет возвращен 0.
func (UID) MarshalBinary ¶
MarshalBinary возвращает бинарное представление уникального идентификатора.
func (UID) MarshalText ¶
MarshalText обеспечивает представление уникального идентификатора в виде текста.
func (*UID) UnmarshalBinary ¶
UnmarshalBinary восстанавливает уникальный идентификатор из его бинарного представления.
func (*UID) UnmarshalText ¶
UnmarshalText восстанавливает значение уникального идентификатора из текстового представления.