Commit 37943a26 authored by Julien Muchembled's avatar Julien Muchembled

Remove type specifier on config.value column

For the registry at least, we'll want to store integers
without having to convert to/from strings.

To upgrade 'registry.db':
- dump it to a file
- fix create table statements
- load it

Nodes will restart with an empty cache.
parent 648e6774
import logging, sqlite3, socket, subprocess, time import logging, os, sqlite3, socket, subprocess, time
from re6st.registry import RegistryClient from re6st.registry import RegistryClient
from . import utils
class PeerDB(object): class PeerDB(object):
...@@ -11,20 +12,16 @@ class PeerDB(object): ...@@ -11,20 +12,16 @@ class PeerDB(object):
self._registry = RegistryClient(registry, cert) self._registry = RegistryClient(registry, cert)
logging.info('Initialize cache ...') logging.info('Initialize cache ...')
self._db = sqlite3.connect(db_path, isolation_level=None) try:
self._db.text_factory = str self._db = self._open(db_path)
except sqlite3.OperationalError:
logging.exception("Start with empty cache")
os.rename(db_path, db_path + '.bak')
self._db = self._open(db_path)
q = self._db.execute q = self._db.execute
q("PRAGMA synchronous = OFF")
q("PRAGMA journal_mode = MEMORY")
q("""CREATE TABLE IF NOT EXISTS peer (
prefix TEXT PRIMARY KEY,
address TEXT NOT NULL)""")
q("""CREATE TABLE IF NOT EXISTS config (
name text primary key,
value text)""")
q('ATTACH DATABASE ":memory:" AS volatile') q('ATTACH DATABASE ":memory:" AS volatile')
q("""CREATE TABLE volatile.stat ( q("""CREATE TABLE volatile.stat (
peer TEXT PRIMARY KEY, peer TEXT PRIMARY KEY NOT NULL,
try INTEGER NOT NULL DEFAULT 0)""") try INTEGER NOT NULL DEFAULT 0)""")
q("CREATE INDEX volatile.stat_try ON stat(try)") q("CREATE INDEX volatile.stat_try ON stat(try)")
q("INSERT INTO volatile.stat (peer) SELECT prefix FROM peer") q("INSERT INTO volatile.stat (peer) SELECT prefix FROM peer")
...@@ -49,6 +46,19 @@ class PeerDB(object): ...@@ -49,6 +46,19 @@ class PeerDB(object):
logging.info("Cache initialized. Prefix of registry node is %s/%u", logging.info("Cache initialized. Prefix of registry node is %s/%u",
int(a, 2), len(a)) int(a, 2), len(a))
def _open(self, path):
db = sqlite3.connect(path, isolation_level=None)
db.text_factory = str
db.execute("PRAGMA synchronous = OFF")
db.execute("PRAGMA journal_mode = MEMORY")
utils.sqliteCreateTable(db, "peer",
"prefix TEXT PRIMARY KEY NOT NULL",
"address TEXT NOT NULL")
utils.sqliteCreateTable(db, "config",
"name TEXT PRIMARY KEY NOT NULL",
"value")
return db
def log(self): def log(self):
if logging.getLogger().isEnabledFor(5): if logging.getLogger().isEnabledFor(5):
logging.trace("Cache:") logging.trace("Cache:")
......
...@@ -55,28 +55,19 @@ class RegistryServer(object): ...@@ -55,28 +55,19 @@ class RegistryServer(object):
utils.makedirs(os.path.dirname(self.config.db)) utils.makedirs(os.path.dirname(self.config.db))
self.db = sqlite3.connect(self.config.db, isolation_level=None, self.db = sqlite3.connect(self.config.db, isolation_level=None,
check_same_thread=False) check_same_thread=False)
self.db.execute("""CREATE TABLE IF NOT EXISTS config ( utils.sqliteCreateTable(self.db, "config",
name text primary key, "name TEXT PRIMARY KEY NOT NULL",
value text)""") "value")
try: self.prefix = self.getConfig("prefix", None)
(self.prefix,), = self.db.execute( utils.sqliteCreateTable(self.db, "token",
"SELECT value FROM config WHERE name='prefix'") "token TEXT PRIMARY KEY NOT NULL",
except ValueError: "email TEXT NOT NULL",
self.prefix = None "prefix_len INTEGER NOT NULL",
self.db.execute("""CREATE TABLE IF NOT EXISTS token ( "date INTEGER NOT NULL")
token text primary key not null, if utils.sqliteCreateTable(self.db, "cert",
email text not null, "prefix TEXT PRIMARY KEY NOT NULL",
prefix_len integer not null, "email TEXT",
date integer not null)""") "cert TEXT"):
try:
self.db.execute("""CREATE TABLE cert (
prefix text primary key not null,
email text,
cert text)""")
except sqlite3.OperationalError, e:
if e.args[0] != 'table cert already exists':
raise RuntimeError
else:
self.db.execute("INSERT INTO cert VALUES ('',null,null)") self.db.execute("INSERT INTO cert VALUES ('',null,null)")
self.cert = x509.Cert(self.config.ca, self.config.key) self.cert = x509.Cert(self.config.ca, self.config.key)
...@@ -92,6 +83,15 @@ class RegistryServer(object): ...@@ -92,6 +83,15 @@ class RegistryServer(object):
self.onTimeout() self.onTimeout()
def getConfig(self, name, *default):
r, = next(self.db.execute(
"SELECT value FROM config WHERE name=?", (name,)), default)
return r
def setConfig(self, *name_value):
self.db.execute("INSERT OR REPLACE INTO config VALUES (?, ?)",
name_value)
def sendto(self, prefix, code): def sendto(self, prefix, code):
self.sock.sendto("%s\0%c" % (prefix, code), ('::1', tunnel.PORT)) self.sock.sendto("%s\0%c" % (prefix, code), ('::1', tunnel.PORT))
...@@ -302,8 +302,7 @@ class RegistryServer(object): ...@@ -302,8 +302,7 @@ class RegistryServer(object):
(email, prefix)) (email, prefix))
if self.prefix is None: if self.prefix is None:
self.prefix = prefix self.prefix = prefix
self.db.execute( self.setConfig('prefix', prefix)
"INSERT INTO config VALUES ('prefix',?)", (prefix,))
return self.createCertificate(prefix, req.get_subject(), return self.createCertificate(prefix, req.get_subject(),
req.get_pubkey()) req.get_pubkey())
......
import argparse, errno, hashlib, logging, os, select as _select, shlex, signal import argparse, errno, hashlib, logging, os, select as _select
import socket, struct, subprocess, sys, textwrap, threading, time, traceback import shlex, signal, socket, sqlite3, struct, subprocess
import sys, textwrap, threading, time, traceback
HMAC_LEN = len(hashlib.sha1('').digest()) HMAC_LEN = len(hashlib.sha1('').digest())
...@@ -236,3 +237,15 @@ def newHmacSecret(): ...@@ -236,3 +237,15 @@ def newHmacSecret():
assert len(pack(0,0,0)) == HMAC_LEN assert len(pack(0,0,0)) == HMAC_LEN
return lambda x=None: pack(g(64) if x is None else x, g(64), g(32)) return lambda x=None: pack(g(64) if x is None else x, g(64), g(32))
newHmacSecret = newHmacSecret() newHmacSecret = newHmacSecret()
def sqliteCreateTable(db, name, *columns):
sql = "CREATE TABLE %s (%s)" % (name, ','.join('\n ' + x for x in columns))
for x, in db.execute(
"SELECT sql FROM sqlite_master WHERE type='table' and name=?""",
(name,)):
if x == sql:
return
raise sqlite3.OperationalError(
"table %r already exists with unexpected schema" % name)
db.execute(sql)
return True
#!/usr/bin/python #!/usr/bin/python
import atexit, errno, logging, os, signal, socket import atexit, errno, logging, os, signal, socket
import sqlite3, subprocess, sys, time, threading import subprocess, sys, time, threading
from collections import deque from collections import deque
from re6st import ctl, db, plib, tunnel, utils, version, x509 from re6st import ctl, db, plib, tunnel, utils, version, x509
from re6st.utils import exit, ReexecException from re6st.utils import exit, ReexecException
...@@ -393,9 +393,6 @@ def main(): ...@@ -393,9 +393,6 @@ def main():
except: except:
pass pass
exit.release() exit.release()
except sqlite3.Error:
logging.exception("Restarting with empty cache")
os.rename(db_path, db_path + '.bak')
except ReexecException, e: except ReexecException, e:
logging.info(e) logging.info(e)
except Exception: except Exception:
......
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 to comment