文档章节

基于 tornado框架 , 利用sqlite 的 内存数据库实现 session

Franca
 Franca
发布于 2016/12/12 21:44
字数 557
阅读 134
收藏 0
点赞 0
评论 1

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, AlarmPoster

_Session = sessionmaker()
_Base = declarative_base()

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)


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 = '')


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;

    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()

            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.expiretime

    @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 s

  
    @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()  
        
        
 

© 著作权归作者所有

共有 人打赏支持
Franca
粉丝 0
博文 1
码字总数 557
作品 0
南京
加载中

评论(1)

红薯
红薯
应该来点文字说明
【防衰老教程】-windows环境下安装SQLite

什么是 SQLite? SQLite是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。它是一个零配置的数据库,这意味着与其他数据库一样,您不需要在系统中配置。...

Weijue ⋅ 05/09 ⋅ 0

YYCache 源码剖析:一览亮点

写在前面 YYCache 作为当下 iOS 圈最流行的缓存框架,有着优越的性能和绝佳的设计。笔者花了些时间对其“解剖”了一番,发现了很多有意思的东西,所以写下本文分享一下。 考虑到篇幅,笔者对...

indulge_in ⋅ 06/10 ⋅ 0

python中的SQLite数据库

python中的SQLite数据库 Python SQLITE数据库是一款非常小巧的嵌入式开源数据库软件,也就是说没有独立的维护进程,所有的维护都来自于程序本身。它使用一个文件存储整个数据库,操作十分方便...

幸运券发放 ⋅ 05/03 ⋅ 0

安卓应用安全指南 4.5.3 使用 SQLite 高级话题

安卓应用安全指南 4.5.3 使用 SQLite 高级话题 原书:Android Application Secure Design/Secure Coding Guidebook 译者:飞龙 协议:CC BY-NC-SA 4.0 4.5.3.1 在 SQL 语句的断言中使用通配符...

apachecn_飞龙 ⋅ 03/22 ⋅ 0

【Kotlin For Android】(三): Anko 库

一、简介 Github地址 是一个使 Android应用程序 开发更快,更容易的库。它使你的代码变得简洁易读,并让您忘记 的粗糙边缘。 Anko 由几部分组成: :一个轻量级的库,里面充满了,对话框,日...

Agnes2017 ⋅ 04/27 ⋅ 0

C语言实现的CGI,完成了留言板功能

地址:https://github.com/zhouweiit/cgi 基于ngnix+spawn_cgi+fastcgi作为服务器,使用C语言编写的cgi,实现了简单的留言板功能; 项目结构简介: 1.conf主要包含了nginx与fastcig的配置 2....

zhouweiit_ ⋅ 05/09 ⋅ 0

写一个“特殊”的查询构造器 - (一、程序结构,基础封装)

程序的结构 本篇开始,正式进入编码实践中。首先,简单的规划下程序的结构。 如上一篇所说的,我们需要一个基类 PDODriver 用来封装 PDO 的一些公用的方法,Mysql 等每个数据库都新建一个类 ...

MrQ被抢注了 ⋅ 05/11 ⋅ 0

Node.js 的 SQLite 教程

在本教程中,我将演示如何结合sqlite3 Node.js驱动程序在Node.js环境中使用SQLite。 对于那些不熟悉SQLite的人来说,它是一个简单的单文件关系数据库,在智能设备,嵌入式系统甚至小型Web应用...

oschina ⋅ 05/31 ⋅ 0

Android_6.数据存储3_SQLite存储之创建数据库

本文是以Android Studio为开发工具,<> 为学习指导书籍的学习记录 6.4 SQLite数据 SQLite用于存储大量复杂的关系型数据,是内置在Android系统的一种轻量级的关系型数据库,它有速度快,占用资...

橄榄工作室 ⋅ 05/26 ⋅ 0

D 语言的 ORM 框架 - Entity

Entity 是 D 语言(dlang)数据库操作 ORM 框架,设计参照 javax JPA 实现,具有很好的扩展性和规范性,数据库驱动依赖 Huntlabs 开发的 database for dlang 。 特性: 实现了完整的 Criteria...

冰力 ⋅ 05/14 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

uWSGI + Django @ Ubuntu

创建 Django App Project 创建后, 可以看到路径下有一个wsgi.py的问题 uWSGI运行 直接命令行运行 利用如下命令, 可直接访问 uwsgi --http :8080 --wsgi-file dj/wsgi.py 配置文件 & 运行 [u...

袁祾 ⋅ 30分钟前 ⋅ 0

JVM堆的理解

在JVM中,我们经常提到的就是堆了,堆确实很重要,其实,除了堆之外,还有几个重要的模块,看下图: 大 多数情况下,我们并不需要关心JVM的底层,但是如果了解它的话,对于我们系统调优是非常...

不羁之后 ⋅ 昨天 ⋅ 0

推荐:并发情况下:Java HashMap 形成死循环的原因

在淘宝内网里看到同事发了贴说了一个CPU被100%的线上故障,并且这个事发生了很多次,原因是在Java语言在并发情况下使用HashMap造成Race Condition,从而导致死循环。这个事情我4、5年前也经历...

码代码的小司机 ⋅ 昨天 ⋅ 1

聊聊spring cloud gateway的RetryGatewayFilter

序 本文主要研究一下spring cloud gateway的RetryGatewayFilter GatewayAutoConfiguration spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/config/G......

go4it ⋅ 昨天 ⋅ 0

创建新用户和授予MySQL中的权限教程

导读 MySQL是一个开源数据库管理软件,可帮助用户存储,组织和以后检索数据。 它有多种选项来授予特定用户在表和数据库中的细微的权限 - 本教程将简要介绍一些选项。 如何创建新用户 在MySQL...

问题终结者 ⋅ 昨天 ⋅ 0

android -------- 颜色的半透明效果配置

最近有朋友问我 Android 背景颜色的半透明效果配置,我网上看资料,总结了一下, 开发中也是常常遇到的,所以来写篇博客 常用的颜色值格式有: RGB ARGB RRGGBB AARRGGBB 这4种 透明度 透明度...

切切歆语 ⋅ 昨天 ⋅ 0

CentOS开机启动subversion

建立自启动脚本: vim /etc/init.d/subversion 输入如下内容: #!/bin/bash## subversion startup script for the server## chkconfig: 2345 90 10# description: start the subve......

随风而飘 ⋅ 昨天 ⋅ 0

版本控制工具

CSV , SVN , GIT ,VSS

颖伙虫 ⋅ 昨天 ⋅ 0

【2018.06.19学习笔记】【linux高级知识 13.1-13.3】

13.1 设置更改root密码 13.2 连接mysql 13.3 mysql常用命令

lgsxp ⋅ 昨天 ⋅ 0

LVM

LVM: 硬盘划分分区成物理卷->物理卷组成卷组->卷组划分逻辑分区。 1.磁盘分区: fdisk /dev/sdb 划分几个主分区 输入t更改每个分区类型为8e(LVM) 使用partprobe生成分区的文件:如/dev/sd...

ZHENG-JY ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部