Index: foo/server.py |
diff --git a/foo/server.py b/foo/server.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..1fcfc1dc0c973e576ca52eea20f82f2a65fe8534 |
--- /dev/null |
+++ b/foo/server.py |
@@ -0,0 +1,187 @@ |
+import argparse |
+import collections |
+import cherrypy |
+import json |
+import os |
+import time |
+ |
+genDelta = [ |
+ 0, |
+ 10, |
+ 100, |
+ 1000, |
+] |
+ |
+genCount = 4 |
+maxGenLength = 5 |
+ |
+def cleanGeneration(gen, delta): |
+ for i in range(len(gen) - 1): |
+ if gen[i + 1]['time'] - gen[i]['time'] < delta: |
+ e = gen.pop(i + 1) |
+ os.remove(e['path']) |
+ return None |
+ return gen.pop(0) |
+ |
+ |
+def cleanUpArchives(archives): |
+ for i, gen in enumerate(archives): |
+ if len(gen) > maxGenLength: |
+ e = cleanGeneration(gen, genDelta[i]) |
+ if e: |
+ if i + 1 < len(archives): |
+ archives[i + 1].append(e) |
+ |
+def printArchives(archives): |
+ print '******' |
+ for i in archives: |
+ for e in i: |
+ print e['time'] |
+ print ' -- ' |
+ |
+archiveIdx = 0 |
+def saveData(service): |
+ global archiveIdx |
+ archives = service.getArchives() |
+ lastGeneration = archives[0] |
+ lastSavedUpdate = -1 |
+ if len(lastGeneration) > 0: |
+ lastSavedUpdate = lastGeneration[-1]['lastId'] |
+ lastUpdate = service.getLastUpdateId() |
+ hasChanges = lastSavedUpdate < lastUpdate |
+ |
+ if not hasChanges: |
+ return |
+ |
+ timeFormat = '%Y-%m-%e-%H:%M:%S' |
+ currentTime = time.time() |
+ path = os.path.join(service.getArchivePath(), 'archive-%s.json' % time.strftime(timeFormat)) |
+ with open(path, 'w') as outfile: |
+ json.dump(service.getData(), outfile) |
+ lastGeneration.append({ |
+ 'lastId': lastUpdate, |
+ 'path': path, |
+ 'time': archiveIdx, |
+ 'realtime': currentTime, |
+ }) |
+ archiveIdx += 1 |
+ |
+ cleanUpArchives(service.getArchives()) |
+ |
+class Service(object): |
+ exposed = True |
+ |
+ def __init__(self, data_dir): |
+ self.data = None |
+ self.updates = collections.deque(maxlen=500) |
+ self.nextUpdateId = 0 |
+ self.idxMap = None |
+ self.archive_path = os.path.join(data_dir, 'archive') |
+ if not os.path.exists(self.archive_path): |
+ os.makedirs(self.archive_path) |
+ with open(os.path.join(data_dir, 'index')) as inf: |
+ self.data = json.load(inf) |
+ self.initIdxMap() |
+ |
+ self.archives = [] |
+ for i in range(genCount): |
+ self.archives.append([]) |
+ |
+ self.saver = cherrypy.process.plugins.BackgroundTask(2.0 * 60, saveData, [self]) |
+ self.saver.start() |
+ |
+ def initIdxMap(self): |
+ self.idxMap = dict() |
+ for i, entry in enumerate(self.data): |
+ self.idxMap[entry['url']] = i |
+ |
+ def getArchivePath(self): |
+ return self.archive_path |
+ |
+ def getArchives(self): |
+ return self.archives |
+ |
+ def getData(self): |
+ return self.data |
+ |
+ def getDataResponse(self): |
+ return { |
+ 'data': self.data, |
+ 'nextId': self.nextUpdateId, |
+ } |
+ |
+ def appendUpdate(self, entry, idx): |
+ self.updates.append({'index': idx, 'id': self.nextUpdateId, 'entry': entry}) |
+ self.nextUpdateId += 1 |
+ |
+ def update(self, entry): |
+ key = entry['url'] |
+ idx = self.idxMap[key] |
+ self.data[idx] = entry |
+ self.appendUpdate(entry, idx) |
+ return 'sdf' |
+ |
+ @cherrypy.expose |
+ def getupdates(self, nextId): |
+ data = None |
+ updates = None |
+ nextId = int(nextId) |
+ newNextId = nextId |
+ |
+ if len(self.updates) > 0: |
+ lastId = self.updates[-1]['id'] |
+ firstId = self.updates[0]['id'] |
+ if firstId > nextId: |
+ data = self.data |
+ elif lastId >= nextId: |
+ updates = list(self.updates)[nextId - firstId:] |
+ newNextId = lastId + 1 |
+ return json.dumps({'response': { |
+ 'data': data, |
+ 'updates': updates, |
+ 'nextId': newNextId, |
+ }}) |
+ |
+ |
+ @cherrypy.expose |
+ def message(self): |
+ cl = cherrypy.request.headers['Content-Length'] |
+ rawbody = cherrypy.request.body.read(int(cl)) |
+ request = json.loads(rawbody) |
+ action = request['action'] |
+ response = None |
+ if action == 'getData': |
+ response = self.getDataResponse() |
+ if action == 'update': |
+ response = self.update(request['data']) |
+ return json.dumps({'response': response}) |
+ |
+ def getLastUpdateId(self): |
+ return self.nextUpdateId - 1 |
+ |
+ |
+ |
+if __name__ == '__main__': |
+ parser = argparse.ArgumentParser() |
+ parser.add_argument('--data-dir') |
+ options = parser.parse_args() |
+ service = Service(options.data_dir) |
+ conf = { |
+ 'global': { |
+ 'server.socket_host': '0.0.0.0', |
+ 'server.socket_port': 8081, |
+ }, |
+ '/': { |
+ 'tools.response_headers.on': True, |
+ 'tools.response_headers.headers': [('Content-Type', 'text/plain')], |
+ }, |
+ '/foo': { |
+ 'tools.staticdir.on': True, |
+ 'tools.staticdir.dir': '/usr/local/google/code/dom_distiller/foo', |
+ }, |
+ '/images': { |
+ 'tools.staticdir.on': True, |
+ 'tools.staticdir.dir': os.path.join(os.getcwd(), options.data_dir), |
+ } |
+ } |
+ cherrypy.quickstart(service, '/', conf) |