2 Storage class for P2P logging information.
4 2011, Razvan Deaconescu, razvan.deaconescu@cs.pub.ro
14 # Logging code heavily inspired by Logging HOWTO documentation:
15 # http://docs.python.org/dev/howto/logging.html#configuring-logging
18 # Create logger; default logging level is DEBUG.
19 logger = logging.getLogger(__name__)
20 logger.setLevel(logging.DEBUG)
22 # Create console handler and set level to ERROR.
23 ch = logging.StreamHandler()
24 ch.setLevel(logging.DEBUG)
27 formatter = logging.Formatter('%(filename)s:%(lineno)s - %(levelname)s: %(message)s')
29 # Add formatter to console handler.
30 ch.setFormatter(formatter)
32 # Add console handler to logger.
37 'CHOKE': {'id': 1, 'parameters': None},
38 'UNCHOKE': {'id': 2, 'parameters': None},
39 'INTERESTED': {'id': 3, 'parameters': None},
40 'NOT_INTERESTED': {'id': 4, 'parameters': None},
41 'HAVE': {'id': 5, 'parameters': None},
42 'BITFIELD': {'id': 6, 'parameters': None},
43 'REQUEST': {'id': 7, 'parameters': None},
44 'PIECE': {'id': 8, 'parameters': None},
45 'CANCEL': {'id': 9, 'parameters': None},
46 'DHT_PORT': {'id': 10, 'parameters': None}
49 bittorrent_clients = {
53 'url': 'http://www.tribler.org/trac',
55 'streaming_support': True,
62 'url': 'https://trac.p2p-next.org/',
64 'streaming_support': True,
68 'libtorrent-rasterbar': {
71 'url': 'http://www.rasterbar.com/products/libtorrent/',
73 'streaming_support': True,
80 'url': 'http://www.vuze.com/',
82 'streaming_support': True,
89 'url': 'http://www.transmissionbt.com/',
91 'streaming_support': False,
98 'url': 'http://aria2.sourceforge.net/',
100 'streaming_support': False,
106 'language': 'Python',
107 'url': 'http://www.bittorrent.com/',
109 'streaming_support': False,
115 transfer_directions = {
121 """ Class mimics a C structure. """
122 def __init__(self, torrent_filename=None, data_size=None,
124 self.torrent_filename = torrent_filename
125 self.data_size = data_size
126 self.description = description
128 class ClientSession(object):
129 """ Class mimics a C structure. """
130 def __init__(self, swarm_id=None, btclient=None, system_os=None,
131 system_os_version=None, system_ram=None, system_cpu=None,
132 public_ip=None, public_port=None, ds_limit=None, us_limit=None,
133 start_time=None, dht_enabled=None, pxe_enabled=None,
134 streaming_enabled=None, features=None, description=None):
135 self.swarm_id = swarm_id
136 self.btclient = btclient
137 self.system_os = system_os
138 self.system_os_version = system_os_version
139 self.system_ram = system_ram
140 self.system_cpu = system_cpu
141 self.public_ip = public_ip
142 self.public_port = public_port
143 self.ds_limit = ds_limit
144 self.us_limit = us_limit
145 self.start_time = start_time
146 self.dht_enabled = dht_enabled
147 self.pxe_enabled = pxe_enabled
148 self.streaming_enabled = streaming_enabled
149 self.features = features
150 self.description = description
152 class PeerStatusMessage(object):
153 """ Class mimics a C structure. """
154 def __init__(self, swarm_id=None, client_session_id=None, date=None,
155 time=None, peer_ip=None, peer_port=None, download_speed=None,
157 self.swarm_id = swarm_id
158 self.client_session_id = client_session_id
161 self.peer_ip = peer_ip
162 self.peer_port = peer_port
163 self.download_speed = download_speed
164 self.upload_speed = upload_speed
166 class StatusMessage(object):
167 """ Class mimics a C structure. """
168 def __init__(self, swarm_id=None, client_session_id=None, date=None,
169 time=None, num_peers=None, num_dht_peers=None,
170 download_speed=None, upload_speed=None, download_size=None,
171 upload_size=None, eta=None):
172 self.swarm_id = swarm_id
173 self.client_session_id = client_session_id
176 self.num_peers = num_peers
177 self.num_dht_peers = num_dht_peers
178 self.download_speed = download_speed
179 self.upload_speed = upload_speed
180 self.download_size = download_size
181 self.upload_size = upload_size
184 class VerboseMessage(object):
185 """ Class mimics a C structure. """
186 def __init__(self, swarm_id=None, client_session_id=None, date=None,
187 time=None, transfer_direction=None, peer_ip=None, peer_port=None,
188 message_type=None, index=None, begin=None, length=None,
190 self.swarm_id = swarm_id
191 self.client_session_id = client_session_id
194 self.transfer_direction = transfer_direction
195 self.peer_ip = peer_ip
196 self.peer_port = peer_port
197 self.message_type = message_type
201 self.listen_port = listen_port
203 class SwarmDataAccess(object):
207 def add_swarm(self, swarm):
210 def remove_swarm(self):
216 def update_swarm(self):
219 def add_client_session(self, session):
222 def remove_client_session(self):
225 def get_client_session(self):
228 def update_client_session(self):
231 def add_peer_status_message(self, msg):
234 def remove_peer_status_message(self):
237 def get_peer_status_message(self):
240 def update_peer_status_message(self):
243 def add_status_message(self, msg):
246 def remove_status_message(self):
249 def get_status_message(self):
252 def update_status_message(self):
255 def add_verbose_message(self, msg):
258 def remove_verbose_message(self):
261 def get_verbose_message(self):
264 def update_verbose_message(self):
267 class FileAccess(SwarmDataAccess):
268 def __init__(self, path):
269 self.base_path = path
271 def find_last_numeric_subfolder(path):
273 Find last numeric folder in base_path folder.
274 The last numeric folder is the last swarm_id.
277 pattern = re.compile("[0-9]+")
279 # Browse entries in base_path folder.
280 listing = os.listdir(path)
281 for entry in listing:
282 # If directory name is a number (id) add it to the list.
283 if os.path.isdir(os.path.join(path, entry)):
284 if pattern.match(entry):
285 dir_list.append(int(entry))
291 return dir_list[len(dir_list)-1]
293 class TreeTextFileAccess(FileAccess):
294 def __init__(self, path):
295 super(TreeTextFileAccess, self).__init__(path)
297 def add_swarm(self, swarm):
299 Create a subfolder with an unique id. Add 1 to the last numeric
300 subfolder id. In case none exists, use 1 as id.
302 id = find_last_numeric_subfolder(self.base_path)
308 swarm_path = os.path.join(self.base_path, str(id))
311 swarm_config = os.path.join(swarm_path, "swarm.conf")
312 f = open(swarm_config, 'w')
314 torrent_filename = %s
317 """ %(id, swarm.torrent_filename, swarm.data_size, swarm.description))
320 def add_client_session(self, session):
322 Create session subfolder in swarm subfolder and add config file.
323 TODO: Throw exception in case swarm subfolder doesn't exist.
325 swarm_path = os.path.join(self.base_path, str(session.swarm_id))
327 # Search first available folder in swarm_path.
328 id = find_last_numeric_subfolder(swarm_path)
334 # Create session subfolder.
335 session_path = os.path.join(swarm_path, str(id))
336 os.mkdir(session_path)
338 # Create and populate configuration file.
339 session_config = os.path.join(session_path, "client_session.conf")
340 f = open(session_config, 'w')
345 system_os_version = %s
355 streaming_enabled = %s
358 """ %(id, session.swarm_id, session.btclient, session.system_os,
359 session.system_os_version, session.system_ram, session.system_cpu,
360 session.public_ip, session.public_port, session.ds_limit,
361 session.us_limit, session.start_time, session.dht_enabled,
362 session.pxe_enabled, session.streaming_enabled,
363 session.features, session.description))
366 def add_peer_status_message(self, msg):
367 # TODO: id is number of lines in file.
368 swarm_path = os.path.join(self.base_path, str(msg.swarm_id))
369 session_path = os.path.join(swarm_path, str(msg.client_session_id))
370 message_file = os.path.join(session_path, "peer_status.txt")
372 f = open(message_file, 'w')
375 client_session_id = %s
382 """ %(1, msg.swarm_id, msg.client_session_id, msg.date, msg.time,
383 msg.peer_ip, msg.peer_port, msg.download_speed, msg.upload_speed))
386 def add_status_message(self, msg):
387 # TODO: id is number of lines in file.
388 swarm_path = os.path.join(self.base_path, str(msg.swarm_id))
389 session_path = os.path.join(swarm_path, str(msg.client_session_id))
390 message_file = os.path.join(session_path, "status.txt")
392 f = open(message_file, 'w')
395 client_session_id = %s
405 """ %(1, msg.swarm_id, msg.client_session_id, msg.date, msg.time,
406 msg.num_peers, msg.num_dht_peers, msg.download_speed,
407 msg.upload_speed, msg.download_size, msg.upload_size, msg.eta))
410 def add_verbose_message(self, msg):
411 # TODO: id is number of lines in file.
412 swarm_path = os.path.join(self.base_path, str(msg.swarm_id))
413 session_path = os.path.join(swarm_path, str(msg.client_session_id))
414 message_file = os.path.join(session_path, "verbose.txt")
416 f = open(message_file, 'w')
419 client_session_id = %s
422 transfer_direction = %s
430 """ %(1, msg.swarm_id, msg.client_session_id, msg.date, msg.time,
431 msg.transfer_direction, msg.peer_ip, msg.peer_port,
432 msg.message_type, msg.index, msg.begin, msg.length,
436 class DatabaseAccess(SwarmDataAccess):
440 def connect(self, database):
441 self.database = database
445 def disconnect(self):
449 class SQLiteDatabaseAccess(DatabaseAccess):
453 def connect(self, database):
454 self.database = database
455 self.conn = sqlite3.connect(self.database)
456 self.cursor = self.conn.cursor()
458 def add_swarm(self, swarm):
461 def add_client_session(self, session):
464 def add_peer_status_message(self, msg):
467 def add_status_message(self, msg):
470 def add_verbose_message(self, msg):
473 class MySQLDatabaseAccess(DatabaseAccess):
477 def connect(self, database):
480 def add_swarm(self, swarm):
483 def add_client_session(self, session):
486 def add_peer_status_message(self, msg):
489 def add_status_message(self, msg):
492 def add_verbose_message(self, msg):