diff options
Diffstat (limited to 'src/gnunet/util/key_value_store.go')
-rw-r--r-- | src/gnunet/util/key_value_store.go | 188 |
1 files changed, 0 insertions, 188 deletions
diff --git a/src/gnunet/util/key_value_store.go b/src/gnunet/util/key_value_store.go deleted file mode 100644 index 0658218..0000000 --- a/src/gnunet/util/key_value_store.go +++ /dev/null | |||
@@ -1,188 +0,0 @@ | |||
1 | // This file is part of gnunet-go, a GNUnet-implementation in Golang. | ||
2 | // Copyright (C) 2019, 2020 Bernd Fix >Y< | ||
3 | // | ||
4 | // gnunet-go is free software: you can redistribute it and/or modify it | ||
5 | // under the terms of the GNU Affero General Public License as published | ||
6 | // by the Free Software Foundation, either version 3 of the License, | ||
7 | // or (at your option) any later version. | ||
8 | // | ||
9 | // gnunet-go is distributed in the hope that it will be useful, but | ||
10 | // WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | // Affero General Public License for more details. | ||
13 | // | ||
14 | // You should have received a copy of the GNU Affero General Public License | ||
15 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | // | ||
17 | // SPDX-License-Identifier: AGPL3.0-or-later | ||
18 | |||
19 | package util | ||
20 | |||
21 | import ( | ||
22 | "context" | ||
23 | "database/sql" | ||
24 | "fmt" | ||
25 | "strconv" | ||
26 | "strings" | ||
27 | |||
28 | redis "github.com/go-redis/redis/v8" | ||
29 | ) | ||
30 | |||
31 | // Error messages related to the key/value-store implementations | ||
32 | var ( | ||
33 | ErrKVSInvalidSpec = fmt.Errorf("Invalid KVStore specification") | ||
34 | ErrKVSNotAvailable = fmt.Errorf("KVStore not available") | ||
35 | ) | ||
36 | |||
37 | // KeyValueStore interface for implementations that store and retrieve | ||
38 | // key/value pairs. Keys and values are strings. | ||
39 | type KeyValueStore interface { | ||
40 | Put(key string, value string) error // put a key/value pair into store | ||
41 | Get(key string) (string, error) // retrieve a value for a key from store | ||
42 | List() ([]string, error) // get all keys from the store | ||
43 | } | ||
44 | |||
45 | // OpenKVStore opens a key/value store for further put/get operations. | ||
46 | // The 'spec' option specifies the arguments required to connect to a specific | ||
47 | // persistence mechanism. The arguments in the 'spec' string are separated by | ||
48 | // the '+' character. | ||
49 | // The first argument specifies the type of key/value store to be used; the | ||
50 | // meaning and format of the following arguments depend on this type. | ||
51 | // | ||
52 | // Key/Value Store types defined: | ||
53 | // * 'redis': Use a Redis server for persistance; the specification is | ||
54 | // "redis+addr+[passwd]+db". 'db' must be an integer value. | ||
55 | // * 'mysql': MySQL-compatible database (see 'database.go' for details) | ||
56 | // * 'sqlite3': SQLite3-compatible database (see 'database.go' for details) | ||
57 | func OpenKVStore(spec string) (KeyValueStore, error) { | ||
58 | // check specification string | ||
59 | specs := strings.Split(spec, "+") | ||
60 | if len(specs) < 2 { | ||
61 | return nil, ErrKVSInvalidSpec | ||
62 | } | ||
63 | switch specs[0] { | ||
64 | case "redis": | ||
65 | //-------------------------------------------------------------- | ||
66 | // NoSQL-based persistance | ||
67 | //-------------------------------------------------------------- | ||
68 | if len(specs) < 4 { | ||
69 | return nil, ErrKVSInvalidSpec | ||
70 | } | ||
71 | db, err := strconv.Atoi(specs[3]) | ||
72 | if err != nil { | ||
73 | return nil, ErrKVSInvalidSpec | ||
74 | } | ||
75 | kvs := new(KvsRedis) | ||
76 | kvs.db = db | ||
77 | kvs.client = redis.NewClient(&redis.Options{ | ||
78 | Addr: specs[1], | ||
79 | Password: specs[2], | ||
80 | DB: db, | ||
81 | }) | ||
82 | if kvs.client == nil { | ||
83 | err = ErrKVSNotAvailable | ||
84 | } | ||
85 | return kvs, err | ||
86 | |||
87 | case "sqlite3", "mysql": | ||
88 | //-------------------------------------------------------------- | ||
89 | // SQL-based persistance | ||
90 | //-------------------------------------------------------------- | ||
91 | kvs := new(KvsSQL) | ||
92 | var err error | ||
93 | |||
94 | // connect to SQL database | ||
95 | kvs.db, err = ConnectSQLDatabase(spec) | ||
96 | if err != nil { | ||
97 | return nil, err | ||
98 | } | ||
99 | // get number of key/value pairs (as a check for existing table) | ||
100 | row := kvs.db.QueryRow("select count(*) from store") | ||
101 | var num int | ||
102 | if row.Scan(&num) != nil { | ||
103 | return nil, ErrKVSNotAvailable | ||
104 | } | ||
105 | return kvs, nil | ||
106 | } | ||
107 | return nil, ErrKVSInvalidSpec | ||
108 | } | ||
109 | |||
110 | //====================================================================== | ||
111 | // NoSQL-based key-value-stores | ||
112 | //====================================================================== | ||
113 | |||
114 | // KvsRedis represents a redis-based key/value store | ||
115 | type KvsRedis struct { | ||
116 | client *redis.Client // client connection | ||
117 | db int // index to database | ||
118 | } | ||
119 | |||
120 | // Put a key/value pair into the store | ||
121 | func (kvs *KvsRedis) Put(key string, value string) error { | ||
122 | return kvs.client.Set(context.TODO(), key, value, 0).Err() | ||
123 | } | ||
124 | |||
125 | // Get a value for a given key from store | ||
126 | func (kvs *KvsRedis) Get(key string) (value string, err error) { | ||
127 | return kvs.client.Get(context.TODO(), key).Result() | ||
128 | } | ||
129 | |||
130 | // List all keys in store | ||
131 | func (kvs *KvsRedis) List() (keys []string, err error) { | ||
132 | var ( | ||
133 | crs uint64 | ||
134 | segm []string | ||
135 | ctx = context.TODO() | ||
136 | ) | ||
137 | for { | ||
138 | segm, crs, err = kvs.client.Scan(ctx, crs, "*", 10).Result() | ||
139 | if err != nil { | ||
140 | return nil, err | ||
141 | } | ||
142 | if crs == 0 { | ||
143 | break | ||
144 | } | ||
145 | keys = append(keys, segm...) | ||
146 | } | ||
147 | return | ||
148 | } | ||
149 | |||
150 | //====================================================================== | ||
151 | // SQL-based key-value-store | ||
152 | //====================================================================== | ||
153 | |||
154 | // KvsSQL represents a SQL-based key/value store | ||
155 | type KvsSQL struct { | ||
156 | db *sql.DB | ||
157 | } | ||
158 | |||
159 | // Put a key/value pair into the store | ||
160 | func (kvs *KvsSQL) Put(key string, value string) error { | ||
161 | _, err := kvs.db.Exec("insert into store(key,value) values(?,?)", key, value) | ||
162 | return err | ||
163 | } | ||
164 | |||
165 | // Get a value for a given key from store | ||
166 | func (kvs *KvsSQL) Get(key string) (value string, err error) { | ||
167 | row := kvs.db.QueryRow("select value from store where key=?", key) | ||
168 | err = row.Scan(&value) | ||
169 | return | ||
170 | } | ||
171 | |||
172 | // List all keys in store | ||
173 | func (kvs *KvsSQL) List() (keys []string, err error) { | ||
174 | var ( | ||
175 | rows *sql.Rows | ||
176 | key string | ||
177 | ) | ||
178 | rows, err = kvs.db.Query("select key from store") | ||
179 | if err == nil { | ||
180 | for rows.Next() { | ||
181 | if err = rows.Scan(&key); err != nil { | ||
182 | break | ||
183 | } | ||
184 | keys = append(keys, key) | ||
185 | } | ||
186 | } | ||
187 | return | ||
188 | } | ||