openmedialibrary/oml/update.py

98 lines
3.0 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from __future__ import division
#https://github.com/hiroakis/tornado-websocket-example/blob/master/app.py
#http://stackoverflow.com/questions/5892895/tornado-websocket-question
#possibly get https://github.com/methane/wsaccel
#possibly run the full django app throw tornado instead of gunicorn
#https://github.com/bdarnell/django-tornado-demo/blob/master/testsite/tornado_main.py
#http://stackoverflow.com/questions/7190431/tornado-with-django
#http://www.tornadoweb.org/en/stable/wsgi.html
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from tornado.web import Application
from tornado.websocket import WebSocketHandler
from Queue import Queue
import urllib2
import os
from contextlib import closing
import json
from threading import Thread
class Background:
def __init__(self, handler):
self.handler = handler
self.q = Queue()
def worker(self):
while True:
message = self.q.get()
action, data = json.loads(message)
if action == 'get':
if 'url' in data and data['url'].startswith('http'):
self.download(data['url'], '/tmp/test.data')
elif action == 'update':
self.post({'error': 'not implemented'})
else:
self.post({'error': 'unknown action'})
self.q.task_done()
def join(self):
self.q.join()
def put(self, data):
self.q.put(data)
def post(self, data):
if not isinstance(data, basestring):
data = json.dumps(data)
main.add_callback(lambda: self.handler.write_message(data))
def download(self, url, filename):
dirname = os.path.dirname(filename)
if dirname and not os.path.exists(dirname):
os.makedirs(dirname)
with open(filename, 'w') as f:
with closing(urllib2.urlopen(url)) as u:
size = int(u.headers.get('content-length', 0))
done = 0
chunk_size = max(min(1024*1024, int(size/100)), 4096)
print 'chunksize', chunk_size
for data in iter(lambda: u.read(chunk_size), ''):
f.write(data)
done += len(data)
if size:
percent = done/size
self.post({'url': url, 'size': size, 'done': done, 'percent': percent})
class Handler(WebSocketHandler):
def open(self):
print "New connection opened."
self.background = Background(self)
self.t = Thread(target=self.background.worker)
self.t.daemon = True
self.t.start()
#websocket calls
def on_message(self, message):
self.background.put(message)
def on_close(self):
print "Connection closed."
self.background.join()
print "Server started."
HTTPServer(Application([("/", Handler)])).listen(28161)
main = IOLoop.instance()
main.start()