|
# -*- coding: utf-8 -*-
import errno
import glob
import os
import re
import sqlite3
import stat
import time
from functools import wraps
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from tornado.log import app_log as logger
from tornado.options import define, options
from tornado.web import Application, RequestHandler, StaticFileHandler
define('host', default='127.0.0.1', help='run on the given host', type=str)
define('port', default=8001, help='run on the given port', type=int)
options.parse_command_line()
ROOT_PATH = '/home/work/minipai2'
# Create Table SQL
CREATE_TABLE_STMT = """
CREATE TABLE IF NOT EXISTS photoinfo (
id integer primary key,
lensman varchar(20),
session varchar(20),
photo_id varchar(13),
photo_name varchar(255),
thumb_path varchar(255),
origin_path varchar(255)
);"""
# Create Index SQL
CREATE_INDEX1 = 'CREATE INDEX IF NOT EXISTS idx_lensman ON photoinfo (lensman);'
CREATE_INDEX2 = 'CREATE INDEX IF NOT EXISTS idx_session ON photoinfo (session);'
# Insert Record SQL
INSERT_RECORD_STMT = 'INSERT INTO photoinfo VALUES (NULL, ?, ?, ?, ?, ?, ?);'
# Delete Record SQL
DELETE_RECORD_STMT = 'DELETE FROM photoinfo WHERE lensman = ? and session = ? and name = ?;'
# Query Max(photo_id) SQL
SELECT_MAX_PHOTO_ID_STMT = 'SELECT MAX(photo_id) FROM photoinfo WHERE lensman = ? and session = ?;'
# Query Origin Path SQL
SELECT_ORIGIN_PATH_STMT = 'SELECT origin_path FROM photoinfo WHERE lensman = ? and photo_id = ?;'
conn = sqlite3.connect('minipai2.db')
cur = conn.cursor()
# Synchronous Off
# cur.execute('PRAGMA synchronous = OFF')
# Execute SQL
cur.execute(CREATE_TABLE_STMT)
cur.execute(CREATE_INDEX1)
cur.execute(CREATE_INDEX2)
conn.commit()
# Logging Some Vars
def logit(self, content, key='content'):
uri = self.request.uri if hasattr(self, 'request') else self
logger.info('uri=%s&%s=%s', uri, key, content)
# Logging Request Arguments
def log_request_arguments(func):
@wraps(func)
def returned_wrapper(self, *args, **kwargs):
logit(self, self.request.arguments, key='arguments')
return func(self, *args, **kwargs)
return returned_wrapper
# FILE OPERATE
def silent_makdirs(path):
try:
os.makedirs(path)
except OSError as e:
if e.errno != errno.EEXIST:
raise
def silent_remove(path):
try:
os.remove(path)
except OSError as e:
if e.errno != errno.ENOENT:
raise
def get_session_root(lensman, session):
return '{}/{}'.format(ROOT_PATH, session)
def get_session_dir(lensman, session):
session_root = get_session_root(lensman, session)
return '{}/{}'.format(session_root, 'origin'), '{}/{}'.format(session_root, 'thumbnail')
def create_session_dir(lensman, session):
for path in get_session_dir(lensman, session):
if os.path.exists(path):
return False
silent_makdirs(path)
return True
def get_last_timestamp(lensman, session):
cur.execute(SELECT_MAX_PHOTO_ID_STMT, (lensman, session))
result = cur.fetchall()
return int(result[0][0] or 0)
def insert_session_file(files_):
start_at = time.time()
cur.executemany(INSERT_RECORD_STMT, files_)
conn.commit()
end_at = time.time()
logit('/fetch_thumbnail', start_at, key='start_at')
logit('/fetch_thumbnail', end_at, key='end_at')
logit('/fetch_thumbnail', end_at - start_at, key='delta_time')
def delete_session_file(lensman, session, name):
cur.execute(DELETE_RECORD_STMT, (lensman, session, name))
conn.commit()
def get_file_info(file_):
photo_name = file_.split('/')[-1]
photo_id = photo_name.split('.')[0]
thumb_path = file_.replace('{}/'.format(ROOT_PATH), '')
origin_path = thumb_path.replace('thumbnail', 'origin')
return photo_id, photo_name, thumb_path, origin_path
def is_file_valid(file_):
if file_.endswith('.tmp'): # Whether 'xxx.tmp' or not
return False
if not re.match(r'.*\/\d+\.\w+', file_): # Whether 'xxx/digit.xxx' or not
return False
if not os.stat(file_).st_size: # Whether `file size zero` or not
return False
return True
def get_glob_files(lensman, session):
_, thumb = get_session_dir(lensman, session)
return glob.iglob('{}/*'.format(thumb))
def get_all_files(lensman, session):
# Glob Files
files = get_glob_files(lensman, session)
# Init Vars
files_ = []
# Foreach Glob Files
for file_ in files:
logit('/session_end', file_, key='globfile')
if is_file_valid(file_):
photo_id, photo_name, thumb_path, origin_path = get_file_info(file_)
# Insert When Photo_id Large Than Maxt
files_.append((lensman, session, photo_id, photo_name, thumb_path, origin_path))
# If Having Files To Insert Into SQLite
if files_:
insert_session_file(files_)
return files_
def get_new_files(lensman, session, maxid):
# Glob Files
files = get_glob_files(lensman, session)
# Init Vars
files_ = []
# Foreach Glob Files
for file_ in files:
logit('/fetch_thumbnail', file_, key='globfile')
if is_file_valid(file_):
photo_id, photo_name, thumb_path, _ = get_file_info(file_)
# Return When Photo_id Large Than Maxid
# Solve APP Doesn't Get Photo When Timeout
if int(photo_id) > maxid:
files_.append({
'id': photo_id,
'name': photo_name,
'path': thumb_path,
})
return files_
def get_origin_path_from_id(lensman, session, id_):
cur.execute(SELECT_ORIGIN_PATH_STMT, (lensman, id_))
result = cur.fetchall()
if not result:
return ''
origin_path = result[0][0]
if not os.path.isfile('{}/{}'.format(ROOT_PATH, origin_path)):
return ''
return origin_path
class HelloHandler(RequestHandler):
def get(self):
self.write('Hello Tornado')
class SessionStartHandler(RequestHandler):
@log_request_arguments
def post(self):
lensman = self.get_argument('lensman', '')
session = self.get_argument('session', '')
# Create Session Dir
created = create_session_dir(lensman, session)
# Change Mode to 0777
os.chmod(get_session_root(lensman, session), 0777)
self.write({
'status': 200,
'data': {
'created': created,
}
})
class SessionEndHandler(RequestHandler):
@log_request_arguments
def post(self):
lensman = self.get_argument('lensman', '')
session = self.get_argument('session', '')
# Session Root
session_root = get_session_root(lensman, session)
# Whether Mode Has Changed
if stat.S_IMODE(os.stat(session_root).st_mode) != 0700:
# Insert Files Into SQLite
get_all_files(lensman, session)
# Change Mode to 0700
os.chmod(session_root, 0700)
self.write({
'status': 200,
})
class FetchThumbnailHandler(RequestHandler):
@log_request_arguments
def post(self):
lensman = self.get_argument('lensman', '')
session = self.get_argument('session', '')
maxid = int(self.get_argument('maxid', 0))
# New Files
files = get_new_files(lensman, session, maxid)
# logit(self, maxt, key='maxt')
logit(self, files, key='files')
self.write({
'status': 200,
'data': {
'files': files,
}
})
class FetchOriginHandler(RequestHandler):
@log_request_arguments
def post(self):
lensman = self.get_argument('lensman', '')
session = self.get_argument('session', '')
id_ = self.get_argument('id', '')
path = get_origin_path_from_id(lensman, session, id_)
self.write({
'status': 200,
'data': {
'path': path,
}
})
class DeletePhotoHandler(RequestHandler):
@log_request_arguments
def post(self):
lensman = self.get_argument('lensman', '')
session = self.get_argument('session', '')
id_ = self.get_argument('id', '')
name = self.get_argument('name', '')
path = self.get_argument('path', '')
# Delete Record from Sqlite3
delete_session_file(lensman, session, id_)
# Delete Photo from Disk
origin, thumb = get_session_dir(lensman, session)
# Delete Thumbnail
silent_remove('{}/{}'.format(thumb, name))
# Delete Origin
silent_remove('{}/{}'.format(origin, name))
self.write({
'status': 200,
})
class BoxInfoHandler(RequestHandler):
def post(self):
self.write({
'status': 200,
'data': {
'no.': 'paiai000001',
'status': {
'code': '200',
'msg': u'正常',
}
}
})
handlers = [
(r'/', HelloHandler),
(r'/session_start', SessionStartHandler),
(r'/session_end', SessionEndHandler),
(r'/fetch_thumbnail', FetchThumbnailHandler),
(r'/fetch_origin', FetchOriginHandler),
(r'/delete_photo', DeletePhotoHandler),
(r'/box_info', BoxInfoHandler),
(r'/static/(.*)', StaticFileHandler, {'path': ROOT_PATH}),
]
def main():
app = Application(handlers=handlers, default_host=options.host)
server = HTTPServer(app)
server.listen(options.port)
IOLoop.current().start()
if __name__ == '__main__':
main()
|