added graph folder
[p2prfd.git] / observer.py
blobaa081995c473d695b28fc2e4d78c7a92ac2db7cf
1 import cgi
2 import hashlib
3 import http_helper
4 import httplib
5 import random
6 import socket
7 import sys
8 import threading
9 import urllib
10 import urlparse
12 import twisted.internet.reactor
13 import twisted.web.resource
14 import twisted.web.server
16 import entangled_network
18 class ObserverResource(twisted.web.resource.Resource):
19 isLeaf = True
20 trees = {}
21 last_name = 0
22 names = {}
23 publish_time = {}
24 delay_count = 0
25 average_delay = 0
26 graph_counter = 0
27 def __init__(self):
28 self.delay_log_file = open('delays.log', 'w')
29 def produce_graph(self, rss):
30 f = open('graph/graph%03d.dot' % self.graph_counter, 'w')
31 f.write(self.tree_pic_dot(self.trees[rss]))
32 f.close()
33 self.graph_counter += 1
34 def node_pic(self, node, tree):
35 if node:
36 name = self.names[node]
37 retu = name
38 left_node = None
39 right_node = None
40 if node in tree['child_left']: left_node = tree['child_left'][node]
41 if node in tree['child_right']: right_node = tree['child_right'][node]
42 left_pic = self.node_pic(left_node, tree)
43 right_pic = self.node_pic(right_node, tree)
44 lefts = left_pic.split('\n')
45 retu += '-' + lefts[0] + '\n'
46 for line in lefts[1:]:
47 retu += ' |' + line + '\n'
48 pass
49 rights = right_pic.split('\n')
50 retu += ' -' + rights[0] + '\n'
51 for line in rights[1:]:
52 retu += ' ' + line + '\n'
53 pass
54 return retu
55 else:
56 return '00'
57 pass
58 def node_dot(self, node, tree):
59 retu = ''
60 if node in tree['child_left'] and tree['child_left'][node]:
61 left_node = tree['child_left'][node]
62 retu += self.names[node] + ' -> ' + self.names[left_node] + ';\n'
63 retu += self.node_dot(left_node, tree)
64 if node in tree['child_right'] and tree['child_right'][node]:
65 right_node = tree['child_right'][node]
66 retu += self.names[node] + ' -> ' + self.names[right_node] + ';\n'
67 retu += self.node_dot(right_node, tree)
68 return retu
69 def tree_pic_dot(self, tree):
70 root = tree['root']
71 retu = 'digraph p2prfd {\n'
72 retu += self.names[root] + ';\n'
73 retu += self.node_dot(root, tree)
74 retu += '}\n'
75 return retu
76 pass
77 def tree_pic(self, tree):
78 root = tree['root']
79 return self.node_pic(root, tree)
80 pass
81 def add_name(self, node):
82 if node and not (node in self.names):
83 self.last_name += 1
84 self.names[node] = '%02d' % self.last_name
85 pass
86 def render_GET(self, request):
87 queries = request.args
88 request.responseHeaders.setRawHeaders('content-type', ['text/plain'])
89 print 'queries = %s' % repr(queries)
90 action = None
91 if 'action' in queries: action = queries['action'][0]
92 if action == 'new_root':
93 feed_url = queries['rss'][0]
94 root = eval(queries['root'][0])
95 self.add_name(root)
96 if feed_url in self.trees:
97 pass
98 else:
99 self.trees[feed_url] = {'root': None, 'child_left': {}, 'child_right': {}}
100 self.trees[feed_url]['root'] = root
101 self.produce_graph(feed_url)
102 pass
103 elif action == 'adopt_child':
104 parent = eval(queries['parent'][0]);
105 child = eval(queries['child'][0]);
106 feed_url = queries['rss'][0]
107 loc = queries['loc'][0]
108 self.add_name(parent)
109 self.add_name(child)
110 if loc == 'left':
111 self.trees[feed_url]['child_left'][parent] = child
112 pass
113 elif loc == 'right':
114 self.trees[feed_url]['child_right'][parent] = child
115 pass
116 self.produce_graph(feed_url)
117 pass
118 elif action == 'update_received':
119 print 'publish_id =', queries['publish_id'][0]
120 print 'timestamp =', queries['timestamp'][0]
121 publish_id = queries['publish_id'][0]
122 timestamp = queries['timestamp'][0]
123 if publish_id not in self.publish_time:
124 self.publish_time[publish_id] = float(timestamp)
125 else:
126 update_delay = float(timestamp) - self.publish_time[publish_id]
127 self.average_delay = (self.average_delay*self.delay_count + update_delay) / (self.delay_count+1)
128 self.delay_count = self.delay_count+1
129 print 'update_delay = %.2f' % update_delay
130 print 'average_delay = %.5f' % self.average_delay
131 level = int(queries['level'][0])
132 node = eval(queries['node'][0])
133 name = self.names[node]
134 self.delay_log_file.write('update delay = %.2f (node %s, level %d)\n' % (update_delay, name, level))
135 self.delay_log_file.write('average delay = %.5f\n' % self.average_delay)
136 pass
137 else:
138 rss = None
139 if 'rss' in queries: rss = queries['rss'][0]
140 if rss:
141 if rss in self.trees:
142 if 'type' in queries:
143 return self.tree_pic_dot(self.trees[rss])
144 else:
145 return self.tree_pic(self.trees[rss])
146 else: return 'tree for %s not found' % rss
147 pass
148 result = {}
149 return repr(result)
150 pass
151 rsrc = ObserverResource()
152 site = twisted.web.server.Site(rsrc)
153 twisted.internet.reactor.listenTCP(9501, site)
154 twisted.internet.reactor.run()