Update Copyright header point to COPYING file
[cascardo/ipsilon.git] / ipsilon / util / sessions.py
1 # Copyright (C) 2014 Ipsilon project Contributors, for license see COPYING
2
3 import base64
4 from cherrypy.lib.sessions import Session
5 from ipsilon.util.data import SqlStore, SqlQuery
6 import threading
7 try:
8     import cPickle as pickle
9 except ImportError:
10     import pickle
11
12
13 SESSION_COLUMNS = ['id', 'data', 'expiration_time']
14
15
16 class SqlSession(Session):
17
18     dburi = None
19     _db = None
20     _proto = 2
21     locks = {}
22
23     @classmethod
24     def setup(cls, **kwargs):
25         """Initialization from cherrypy"""
26
27         for k, v in kwargs.items():
28             if k == 'storage_dburi':
29                 cls.dburi = v
30
31         cls._db = SqlStore(cls.dburi)
32
33     def _exists(self):
34         q = SqlQuery(self._db, 'sessions', SESSION_COLUMNS)
35         result = q.select({'id': self.id})
36         return True if result.fetchone() else False
37
38     def _load(self):
39         q = SqlQuery(self._db, 'sessions', SESSION_COLUMNS)
40         result = q.select({'id': self.id})
41         r = result.fetchone()
42         if r:
43             data = str(base64.b64decode(r[1]))
44             return pickle.loads(data)
45
46     def _save(self, expiration_time):
47         q = None
48         try:
49             q = SqlQuery(self._db, 'sessions', SESSION_COLUMNS, trans=True)
50             q.delete({'id': self.id})
51             data = pickle.dumps((self._data, expiration_time), self._proto)
52             q.insert((self.id, base64.b64encode(data), expiration_time))
53             q.commit()
54         except Exception:  # pylint: disable=broad-except
55             if q:
56                 q.rollback()
57             raise
58
59     def _delete(self):
60         q = SqlQuery(self._db, 'sessions', SESSION_COLUMNS)
61         q.delete({'id': self.id})
62
63     # copy what RamSession does for now
64     def acquire_lock(self):
65         """Acquire an exclusive lock on the currently-loaded session data."""
66         self.locked = True
67         self.locks.setdefault(self.id, threading.RLock()).acquire()
68
69     def release_lock(self):
70         """Release the lock on the currently-loaded session data."""
71         self.locks[self.id].release()
72         self.locked = False