Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
lancet
/
kvcache
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
4a2f5db4
authored
Sep 09, 2019
by
lancet
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
heavy refactoring of vault, still WIP
parent
c68ad926
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
104 additions
and
36 deletions
+104
-36
main.go
+1
-2
vault/control.go
+14
-32
vault/data.go
+3
-1
vault/public.go
+43
-0
vault/store.go
+43
-1
No files found.
main.go
View file @
4a2f5db4
...
...
@@ -97,8 +97,7 @@ func main() {
flag
.
Parse
()
listenStr
:=
fmt
.
Sprintf
(
"%s:%d"
,
*
hostF
,
*
portF
)
router
:=
new
(
web
.
Svc
)
storage
:=
new
(
vault
.
Store
)
storage
.
Init
(
*
ttlF
)
storage
:=
vault
.
Store
{
30
}
routing
:=
[]
web
.
Route
{
{
URL
:
"/storage/{id}"
,
Methods
:
[]
string
{
"GET"
},
Handler
:
router
.
GetValue
},
{
URL
:
"/storage/{id}/{value}"
,
Methods
:
[]
string
{
"PUT"
,
"POST"
},
Handler
:
router
.
SetValue
},
...
...
vault/control.go
View file @
4a2f5db4
package
vault
import
(
"errors"
"time"
)
// Init - инициализация хранилища
func
(
store
*
Store
)
Init
(
ttl
uint64
)
error
{
if
store
.
ttl
!=
0
{
return
errors
.
New
(
"Already up"
)
}
if
ttl
<
1
{
return
errors
.
New
(
"Wrong TTL"
)
}
store
.
ttl
=
ttl
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
}
// cleaner - уничтожаем устаревшие ключи
func
(
store
*
Store
)
cleaner
()
{
reply
:=
make
(
chan
Message
)
for
{
msg
:=
Message
{
Action
:
"POP"
,
Reply
:
reply
}
store
.
E
xchange
<-
msg
store
.
e
xchange
<-
msg
got
:=
<-
reply
if
got
.
Error
==
true
{
time
.
Sleep
(
1
*
time
.
Second
)
...
...
@@ -50,14 +24,22 @@ func (store *Store) control() {
select
{
case
<-
tick
:
store
.
addNode
(
""
,
""
,
false
)
case
request
:=
<-
store
.
Exchange
:
reply
:=
Message
{}
switch
request
.
Action
{
case
"POP"
:
// внутренний метод, часть механизма устаревания. Недоступен клиентам.
for
{
err
:=
store
.
popNode
()
if
err
!=
nil
{
reply
.
Error
=
true
break
}
}
case
request
:=
<-
store
.
exchange
:
reply
:=
Message
{}
switch
request
.
Action
{
/*
case "POP": // внутренний метод, часть механизма устаревания. Недоступен клиентам.
err := store.popNode()
if err != nil {
reply.Error = true
}
*/
case
"SET"
:
err
:=
store
.
setNode
(
request
.
Key
,
request
.
Value
)
reply
.
Key
=
request
.
Key
...
...
vault/data.go
View file @
4a2f5db4
...
...
@@ -21,7 +21,9 @@ type node struct {
// Store - корневая структура для хранения данных
type
Store
struct
{
Exchange
chan
Message
// Небуферизованный канал для синхронизации доступа
TTL
uint64
// Публично доступный TTL для инициализации
isInit
bool
// Признак выполненной инициализации
exchange
chan
Message
// Небуферизованный канал для синхронизации доступа
ttl
uint64
// Время жизни узла, сек
head
*
node
// Голова, выходит первым
tail
*
node
// Добавлен последним
...
...
vault/public.go
0 → 100644
View file @
4a2f5db4
/* Методы, доступные внешним сущностям. */
package
vault
import
(
"errors"
)
// GetValue - получить значение ключа из хранилища
func
(
store
*
Store
)
GetValue
(
key
string
)
(
string
,
error
)
{
reply
:=
make
(
chan
Message
)
msg
:=
Message
{
Action
:
"GET"
,
Reply
:
reply
,
Key
:
key
}
store
.
exchange
<-
msg
resp
:=
<-
reply
if
resp
.
Error
!=
true
{
return
resp
.
Value
,
nil
}
return
""
,
errors
.
New
(
"No such key"
)
}
// SetValue - установить/обновить значение ключа
func
(
store
*
Store
)
SetValue
(
key
,
value
string
)
error
{
reply
:=
make
(
chan
Message
)
msg
:=
Message
{
Action
:
"SET"
,
Reply
:
reply
,
Key
:
key
,
Value
:
value
}
store
.
exchange
<-
msg
resp
:=
<-
reply
if
resp
.
Error
!=
true
{
return
nil
}
return
errors
.
New
(
"Cannot set value"
)
}
// DelValue - удалить ключ из хранилища
func
(
store
*
Store
)
DelValue
(
key
string
)
error
{
reply
:=
make
(
chan
Message
)
msg
:=
Message
{
Action
:
"DEL"
,
Reply
:
reply
,
Key
:
key
}
store
.
exchange
<-
msg
resp
:=
<-
reply
if
resp
.
Error
!=
true
{
return
nil
}
return
errors
.
New
(
"There was no such key"
)
}
vault/store.go
View file @
4a2f5db4
...
...
@@ -4,8 +4,37 @@ import (
"errors"
)
// init - инициализация хранилища с заданным TTL
func
(
store
*
Store
)
init
()
{
if
store
.
isInit
==
true
{
return
}
if
store
.
TTL
<
1
{
store
.
TTL
=
30
}
store
.
ttl
=
store
.
TTL
store
.
exchange
=
make
(
chan
Message
)
store
.
flat
=
make
(
map
[
string
]
*
node
)
// Создаём достаточное количество узлов-филлеров, чтобы механизм
// устаревания не начал уничтожать записи преждевременно.
var
i
uint64
for
i
=
0
;
i
<
store
.
ttl
;
i
++
{
store
.
addNode
(
""
,
""
,
false
)
}
go
store
.
control
()
// запускаем управление хранилищем
//go store.cleaner() // запускаем устаревание записей
store
.
isInit
=
true
}
// addNode - добавляем новый узел в хвост очереди.
func
(
store
*
Store
)
addNode
(
key
,
value
string
,
kind
bool
)
{
func
(
store
*
Store
)
addNode
(
key
,
value
string
,
kind
bool
)
error
{
if
store
.
isInit
==
false
{
store
.
init
()
}
var
prev
*
node
if
store
.
tail
!=
nil
{
prev
=
store
.
tail
...
...
@@ -20,12 +49,16 @@ func (store *Store) addNode(key, value string, kind bool) {
if
kind
==
true
{
store
.
flat
[
key
]
=
store
.
tail
}
return
nil
}
// setNode - собираемся добавить новый узел.
// Если ключа ещё нет - просто добавляем в хвост.
// Если ключ есть - переносим в хвост.
func
(
store
*
Store
)
setNode
(
key
,
value
string
)
error
{
if
store
.
isInit
==
false
{
store
.
init
()
}
if
_
,
ok
:=
store
.
flat
[
key
];
ok
==
false
{
store
.
addNode
(
key
,
value
,
true
)
return
nil
...
...
@@ -39,6 +72,9 @@ func (store *Store) setNode(key, value string) error {
// Если Kind == 0 - то возвращаем ошибку.
// При ошибке устаревание приостанавливается на секунду.
func
(
store
*
Store
)
popNode
()
error
{
if
store
.
isInit
==
false
{
store
.
init
()
}
var
err
error
if
store
.
head
==
nil
{
return
errors
.
New
(
"No nodes"
)
...
...
@@ -58,6 +94,9 @@ func (store *Store) popNode() error {
// getNode - получить значение ключа, или ошибку, если такого нет.
func
(
store
*
Store
)
getNode
(
key
string
)
(
string
,
error
)
{
if
store
.
isInit
==
false
{
store
.
init
()
}
if
v
,
ok
:=
store
.
flat
[
key
];
ok
!=
false
{
return
v
.
Value
,
nil
}
...
...
@@ -67,6 +106,9 @@ func (store *Store) getNode(key string) (string, error) {
// delNode - удалить узел с указанным ключом.
// Если такого ключа не было - вернуть ошибку.
func
(
store
*
Store
)
delNode
(
key
string
)
error
{
if
store
.
isInit
==
false
{
store
.
init
()
}
if
_
,
ok
:=
store
.
flat
[
key
];
ok
==
false
{
return
errors
.
New
(
"No such key"
)
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment