from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy import Column, String, create_engine, Integer, Text
import time
import os
import base64
import hashlib
import hmac
import json
from globalstring import cookie_name
import tornado
from time import sleep
from utils.logger import WebLog, AlarmPostersql
_Session = sessionmaker()
_Base = declarative_base()json
def init(timeout = 900, isEcho=False):
engine = create_engine('sqlite:///:memory:', echo=isEcho)
_Session.configure(bind=engine)
_Base.metadata.create_all(engine)
UserSession.set_timeout(timeout)cookie
class _UserSessionData(_Base):
__tablename__ = 'sessiondata'
sid = Column(String(64), primary_key = True, unique = True)
createtime = Column(Integer, default = 0)
lasttime = Column(Integer, default = 0)
expiretime= Column(Integer, index=True, default = 0)
content = Column(Text, default = '')session
class UserSession(object):
_timeout = 0
@classmethod
def set_timeout(cls, timeout):
cls._timeout = timeout
def __init__(self, requesthandler):
self._requesthandler = requesthandler
self._dbdata = None
self._dbsession = _Session()
self._delete = False
self._isNew = False;dom
def _gen_sid(self):
h = hmac.new(str(time.time()), os.urandom(128), hashlib.sha256)
return base64.b64encode(h.digest())
def prepare(self):
#if it is run already, run
if self._dbdata:
return
sid = self._requesthandler.get_cookie(cookie_name.sessionId)
if sid :
self._dbdata = self._dbsession.query(_UserSessionData).filter(_UserSessionData.sid == sid).one_or_none()tornado
try:
if self._dbdata is not None:
self._data = json.loads(self._dbdata.content)
return
else:
sid = None
except:
sid = None
sid = self._gen_sid()
self._dbdata = _UserSessionData(sid=sid)
self._data = dict()
self._sync()
self._dbsession.add(self._dbdata)
self._isNew = True
@property
def isNew(self):
return self._isNew
def _sync(self):
n = int(time.time())
if not self._dbdata.createtime:
self._dbdata.createtime = n
self._dbdata.lasttime = n
self._dbdata.expiretime = (n + self._timeout + 9)//10 * 10
self._dbdata.content = json.dumps(self._data)
def clear(self):
self.prepare()
self._delete = True
#sync the session with the db data, or else we can NOT delete the record via that way
self._dbsession.commit()
self._dbsession.delete(self._dbdata)
self._dbsession.commit()
self._data.clear()
self._requesthandler.clear_cookie(cookie_name.sessionId)
def finish(self):
if not self._dbdata:
self._requesthandler.log.debug('do othing')
return
if self._delete:
return
try:
if not self._delete:
self._sync()
self._dbsession.commit()
self._requesthandler.set_cookie(cookie_name.sessionId, self.sid)
self._requesthandler.log.debug('write sid %s', self.sid)
except Exception as e:
print e
self._dbsession.rollback()
finally:
self._dbsession.close()
@property
def data(self):
self.prepare()
return self._data
@property
def sid(self):
self.prepare()
return self._dbdata.sid
@property
def createtime(self):
self.prepare()
return self._dbdata.createtime
@property
def expiretime(self):
self.prepare()
return self._dbdata.expiretimeoop
@property
def lasttime(self):
self.prepare()
return self._dbdata.lasttime
_log = WebLog()
class UserSessionManager(object):
@staticmethod
def clear_expire_data():
s = _Session()
n = int(time.time())//10 * 10
try:
_log.debug('clear_expire_data is running')
s.query(_UserSessionData).filter(_UserSessionData.expiretime == n).delete()
s.commit()
except Exception as e:
_log.error('clear_expire_data exception:' +e.msg)
finally:
s.close()
del spost
@staticmethod
def clear_expire_data_strick():
s = _Session()
n = int(time.time())
try:
_log.info('clear_expire_data_strick is running')
AlarmPoster.post('clear expire session strickly')
s.query(_UserSessionData).filter(_UserSessionData.expiretime < n).delete()
s.commit()
except Exception as e:
_log.info('clear_expire_data_strick exception:' +e.msg)
finally:
s.close()
del s
@classmethod
def install(cls):
m = UserSessionManager()
_log.info('install')
cls.normal = tornado.ioloop.PeriodicCallback(m.clear_expire_data, 5 * 1000)
cls.normal.start()
c = time.localtime(tornado.ioloop.IOLoop.instance().time())
#after x hours, it is 3:00~4:00
x = 24 + 3 - c.tm_hour
x = x if x < 24 else x - 24
def cycle():
m.clear_expire_data_strick()
_log.info('install strick clear')
cls.strick = tornado.ioloop.PeriodicCallback(m.clear_expire_data, 24 * 3600 * 1000)
cls.strick.start()
if x > 0:
cls.delay = tornado.ioloop.IOLoop.instance().call_later(x * 3600, cycle)
else:
cycle()
@classmethod
def uninstall(cls):
_log.info('uninstall')
if hasattr(cls, 'normal'):
cls.normal.stop()
if hasattr(cls, 'delay'):
tornado.ioloop.IOLoop.instance().remove_timeout(cls.delay)
if hasattr(cls, 'strick'):
cls.strick.stop()
.net