Commit 0060028b by lancet

some text and cleanups

parent a4de484c
......@@ -35,6 +35,48 @@ package main
curl -X DELETE http://localhost:8881/storage/mykey
удалит ключ "mykey" и вернёт код 200 с текстом "OK", либо вернёт код 400
с текстом "FAILURE", если такого ключа в хранилище нет.
Механика хранилища.
Хранилище организовано в виде связанного списка, работающего в качестве очереди.
Для ускорения выборки существует ассоциативный массив (map), со ссылками по
ключам на узлы данных с соответсвующими значениями (оверхед, но выигрыш в
скорости тем больше, чем больше записей в хранилище).
Узлы бывают двух типов: узел данных и "филлер".
Механизм устаревания последовательно извлекает узлы из головы очереди.
Если извлечён узел данных - то он отбрасывается в связи с устареванием.
Если извлечён "филлер", то механизм устаревания "засыпает" на секунду.
Каждую секунду в хвост очереди автоматически добавляется новый филлер.
При создании новой записи создаётся узел данных и добавляется в хвост очереди.
При обновлении существующей записи, её узел данных уничтожается и
создаётся заново в хвосте очереди (эффективней было бы просто править
ссылки, но это усложняет и запутывает код, при том, что не требуется в
данной задаче).
Таким образом, из хранилища каждую секунду удаляются записи, устаревшие на
данный момент.
Для синхронизации доступа использованы небуферизованные каналы, поэтому с
собственно хранилищем в каждый момент времени работает не более одной
процедуры, все операции с данными строго последовательные, конкурентный
доступ исключён.
Есть интересная потенциальная проблема, связанная с тем, что добавление
"филлеров" и их потребление механизмом устаревания могут происходить с
разной скоростью, что приведёт либо к постепенному неконтролируемому
нарастанию числа "филлеров", либо наоборот, к их исчерпанию и
преждевременному устареванию узлов данных.
Эта потенциальная проблема решается дополнительным механизмом контроля,
который я не стал включать в данную реализацию, поскольку указанная
проблема может возникнуть только через достаточно большое время,
заведомо превосходящее время демонстрации данного приложения.
*/
import (
......
......@@ -18,10 +18,13 @@ func (store *Store) Init(ttl uint64) error {
store.Exchange = make(chan Message)
store.flat = make(map[string]*node)
// Создаём достаточное количество узлов-филлеров, чтобы механизм
// устаревания не начал уничтожать записи преждевременно.
var i uint64
for i = 0; i < ttl; i++ {
store.addNode("", "", false)
}
go store.control() // запускаем управление хранилищем
go store.cleaner() // запускаем устаревание записей
return nil
......@@ -35,7 +38,6 @@ func (store *Store) cleaner() {
store.Exchange <- msg
got := <-reply
if got.Error == true {
//fmt.Print("Cleaner sleeps.\n")
time.Sleep(1 * time.Second)
}
}
......@@ -47,10 +49,8 @@ func (store *Store) control() {
for {
select {
case <-tick:
//fmt.Print("Got time tick\n")
store.addNode("", "", false)
case request := <-store.Exchange:
//fmt.Print("Got request: ", request.Action, "\n")
reply := Message{}
switch request.Action {
case "POP": // внутренний метод, часть механизма устаревания. Недоступен клиентам.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment