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 # TODO: Add timezone.
131 def __init__(self, swarm_id=None, btclient=None, system_os=None,
132 system_os_version=None, system_ram=None, system_cpu=None,
133 public_ip=None, public_port=None, ds_limit=None, us_limit=None,
134 start_time=None, dht_enabled=None, pxe_enabled=None,
135 streaming_enabled=None, features=None, description=None):
136 self.swarm_id = swarm_id
137 self.btclient = btclient
138 self.system_os = system_os
139 self.system_os_version = system_os_version
140 self.system_ram = system_ram
141 self.system_cpu = system_cpu
142 self.public_ip = public_ip
143 self.public_port = public_port
144 self.ds_limit = ds_limit
145 self.us_limit = us_limit
146 self.start_time = start_time
147 self.dht_enabled = dht_enabled
148 self.pxe_enabled = pxe_enabled
149 self.streaming_enabled = streaming_enabled
150 self.features = features
151 self.description = description
153 class PeerStatusMessage(object):
154 """ Class mimics a C structure. """
155 def __init__(self, swarm_id=None, client_session_id=None, timestamp=None,
156 peer_ip=None, peer_port=None, download_speed=None,
158 self.swarm_id = swarm_id
159 self.client_session_id = client_session_id
160 self.timestamp = timestamp
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, timestamp=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
174 self.timestamp = timestamp
175 self.num_peers = num_peers
176 self.num_dht_peers = num_dht_peers
177 self.download_speed = download_speed
178 self.upload_speed = upload_speed
179 self.download_size = download_size
180 self.upload_size = upload_size
183 class VerboseMessage(object):
184 """ Class mimics a C structure. """
185 def __init__(self, swarm_id=None, client_session_id=None, timestamp=None,
186 transfer_direction=None, peer_ip=None, peer_port=None,
187 message_type=None, index=None, begin=None, length=None,
189 self.swarm_id = swarm_id
190 self.client_session_id = client_session_id
191 self.timestamp = timestamp
192 self.transfer_direction = transfer_direction
193 self.peer_ip = peer_ip
194 self.peer_port = peer_port
195 self.message_type = message_type
199 self.listen_port = listen_port
201 class SwarmDataAccess(object):
205 def add_swarm(self, swarm):
208 def remove_swarm(self):
214 def update_swarm(self):
217 def add_client_session(self, session):
220 def remove_client_session(self):
223 def get_client_session(self):
226 def update_client_session(self):
229 def add_peer_status_message(self, msg):
232 def remove_peer_status_message(self):
235 def get_peer_status_message(self):
238 def update_peer_status_message(self):
241 def add_status_message(self, msg):
244 def remove_status_message(self):
247 def get_status_message(self):
250 def update_status_message(self):
253 def add_verbose_message(self, msg):
256 def remove_verbose_message(self):
259 def get_verbose_message(self):
262 def update_verbose_message(self):
265 class FileAccess(SwarmDataAccess):
266 def __init__(self, path):
267 self.base_path = path
269 def find_last_numeric_subfolder(path):
271 Find last numeric folder in base_path folder.
272 The last numeric folder is the last swarm_id.
275 pattern = re.compile("[0-9]+")
277 # Browse entries in base_path folder.
278 listing = os.listdir(path)
279 for entry in listing:
280 # If directory name is a number (id) add it to the list.
281 if os.path.isdir(os.path.join(path, entry)):
282 if pattern.match(entry):
283 dir_list.append(int(entry))
289 return dir_list[len(dir_list)-1]
291 class TreeTextFileAccess(FileAccess):
292 def __init__(self, path):
293 super(TreeTextFileAccess, self).__init__(path)
295 def add_swarm(self, swarm):
297 Create a subfolder with an unique id. Add 1 to the last numeric
298 subfolder id. In case none exists, use 1 as id.
300 id = find_last_numeric_subfolder(self.base_path)
306 swarm_path = os.path.join(self.base_path, str(id))
309 swarm_config = os.path.join(swarm_path, "swarm.conf")
310 f = open(swarm_config, 'w')
312 torrent_filename = %s
315 """ %(id, swarm.torrent_filename, swarm.data_size, swarm.description))
318 def add_client_session(self, session):
320 Create session subfolder in swarm subfolder and add config file.
321 TODO: Throw exception in case swarm subfolder doesn't exist.
323 swarm_path = os.path.join(self.base_path, str(session.swarm_id))
325 # Search first available folder in swarm_path.
326 id = find_last_numeric_subfolder(swarm_path)
332 # Create session subfolder.
333 session_path = os.path.join(swarm_path, str(id))
334 os.mkdir(session_path)
336 # Create and populate configuration file.
337 session_config = os.path.join(session_path, "client_session.conf")
338 f = open(session_config, 'w')
343 system_os_version = %s
353 streaming_enabled = %s
356 """ %(id, session.swarm_id, session.btclient, session.system_os,
357 session.system_os_version, session.system_ram, session.system_cpu,
358 session.public_ip, session.public_port, session.ds_limit,
359 session.us_limit, session.start_time, session.dht_enabled,
360 session.pxe_enabled, session.streaming_enabled,
361 session.features, session.description))
364 def add_peer_status_message(self, msg):
365 # TODO: id is number of lines in file.
366 swarm_path = os.path.join(self.base_path, str(msg.swarm_id))
367 session_path = os.path.join(swarm_path, str(msg.client_session_id))
368 message_file = os.path.join(session_path, "peer_status.txt")
370 f = open(message_file, 'a')
371 f.write("""%s,%s,%s,%s,%s,%s,%s,%s\n"""
372 %(1, msg.swarm_id, msg.client_session_id, msg.timestamp,
373 msg.peer_ip, msg.peer_port, msg.download_speed,
377 def add_status_message(self, msg):
378 # TODO: id is number of lines in file.
379 swarm_path = os.path.join(self.base_path, str(msg.swarm_id))
380 session_path = os.path.join(swarm_path, str(msg.client_session_id))
381 message_file = os.path.join(session_path, "status.txt")
383 f = open(message_file, 'a')
384 f.write("""%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n"""
385 %(1, msg.swarm_id, msg.client_session_id, msg.timestamp,
386 msg.num_peers, msg.num_dht_peers, msg.download_speed,
387 msg.upload_speed, msg.download_size, msg.upload_size,
391 def add_verbose_message(self, msg):
392 # TODO: id is number of lines in file.
393 swarm_path = os.path.join(self.base_path, str(msg.swarm_id))
394 session_path = os.path.join(swarm_path, str(msg.client_session_id))
395 message_file = os.path.join(session_path, "verbose.txt")
397 f = open(message_file, 'a')
398 f.write("""%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n"""
399 %(1, msg.swarm_id, msg.client_session_id, msg.timestamp,
400 msg.transfer_direction, msg.peer_ip, msg.peer_port,
401 msg.message_type, msg.index, msg.begin, msg.length,
405 class DatabaseAccess(SwarmDataAccess):
406 def __init__(self, database):
407 self.database = database
413 def disconnect(self):
417 class SQLiteDatabaseAccess(DatabaseAccess):
418 def __init___(self, database):
419 super(SQLiteDatabaseAccess, self).__init__(database)
422 self.conn = sqlite3.connect(self.database)
423 self.cursor = self.conn.cursor()
425 def add_swarm(self, swarm):
428 def add_client_session(self, session):
431 def add_peer_status_message(self, msg):
434 def add_status_message(self, msg):
437 def add_verbose_message(self, msg):
440 class MySQLDatabaseAccess(DatabaseAccess):
441 def __init___(self, database):
442 super(SQLiteDatabaseAccess, self).__init__(database)
447 def add_swarm(self, swarm):
450 def add_client_session(self, session):
453 def add_peer_status_message(self, msg):
456 def add_status_message(self, msg):
459 def add_verbose_message(self, msg):