Source code for alex.components.hub.calldb

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# pylint: disable-msg=E1101

import fcntl
import time
import cPickle as pickle

#FIXME: It should use sqlalchemy instead of the pickles.

[docs]class CallDB(object): """Implements logging of all interesting call stats. It can be used for customization of the SDS, e.g. for novice or expert users. """ def __init__(self, cfg, file_name, period = 24*60*60): self.cfg = cfg self.db_fname = file_name self.period = period
[docs] def read_database(self): db = dict() try: self.f = open(self.db_fname, 'r+') fcntl.lockf(self.f, fcntl.LOCK_EX) db = pickle.load(self.f) except (IOError, EOFError): pass try: fcntl.lockf(self.f, fcntl.LOCK_UN) self.f.close() except AttributeError: pass if 'calls_from_start_end_length' not in db: db['calls_from_start_end_length'] = dict() return db
[docs] def open_database(self): db = dict() try: self.f = open(self.db_fname, 'r+') fcntl.lockf(self.f, fcntl.LOCK_EX) db = pickle.load(self.f) except (IOError, AttributeError): # the DB file does not exist self.f = open(self.db_fname, 'w+') fcntl.lockf(self.f, fcntl.LOCK_EX) if 'calls_from_start_end_length' not in db: db['calls_from_start_end_length'] = dict() return db
[docs] def close_database(self, db): try: self.f.seek(0) self.f.truncate(0) pickle.dump(db, self.f) fcntl.lockf(self.f, fcntl.LOCK_UN) self.f.close() except AttributeError: pass
[docs] def release_database(self): try: fcntl.lockf(self.f, fcntl.LOCK_UN) self.f.close() except AttributeError: pass
[docs] def log(self): db = self.read_database() for remote_uri in db['calls_from_start_end_length']: num_all_calls, total_time, last_period_num_calls, last_period_total_time, last_period_num_short_calls = self.get_uri_stats(remote_uri) m = [] m.append('') m.append('=' * 120) m.append('Remote SIP URI: %s' % remote_uri) m.append('-' * 120) m.append('Total calls: %d' % num_all_calls) m.append('Total time (min): %0.1f' % (total_time/60.0, )) m.append('Last period short calls: %d' % last_period_num_short_calls) m.append('Last period total calls: %d' % last_period_num_calls) m.append('Last period total time (min): %0.1f' % (last_period_total_time/60.0, )) m.append('-' * 120) m.append('-' * 120) m.append('') self.cfg['Logging']['system_logger'].info('\n'.join(m))
[docs] def log_uri(self, remote_uri): db = self.read_database() num_all_calls, total_time, last_period_num_calls, last_period_total_time, last_period_num_short_calls = self.get_uri_stats(remote_uri) m = [] m.append('') m.append('=' * 120) m.append('Remote SIP URI: %s' % remote_uri) m.append('-' * 120) m.append('Total calls: %d' % num_all_calls) m.append('Total time (min): %0.1f' % (total_time/60.0, )) m.append('Last period short calls: %d' % last_period_num_short_calls) m.append('Last period total calls: %d' % last_period_num_calls) m.append('Last period total time (min): %0.1f' % (last_period_total_time/60.0, )) m.append('-' * 120) m.append('-' * 120) m.append('') return '\n'.join(m)
[docs] def get_uri_stats(self, remote_uri): db = self.read_database() num_all_calls = 0 total_time = 0 last_period_num_calls = 0 last_period_total_time = 0 last_period_num_short_calls = 0 try: for s, e, l in db['calls_from_start_end_length'][remote_uri]: if l > 0: num_all_calls += 1 total_time += l # do counts for last period hours if s > time.time() - self.period: last_period_num_calls += 1 last_period_total_time += l if l > 0 and l < self.cfg['VoipHub']['short_calls_time_duration']: last_period_num_short_calls += 1 except: pass return num_all_calls, total_time, last_period_num_calls, last_period_total_time, last_period_num_short_calls
[docs] def track_confirmed_call(self, remote_uri): db = self.open_database() try: db['calls_from_start_end_length'][remote_uri].append([time.time(), 0, 0]) except: db['calls_from_start_end_length'][remote_uri] = [[time.time(), 0, 0], ] self.close_database(db)
[docs] def track_disconnected_call(self, remote_uri): db = self.open_database() try: s, e, l = db['calls_from_start_end_length'][remote_uri][-1] if e == 0 and l == 0: # there is a record about last confirmed but not disconnected call db['calls_from_start_end_length'][remote_uri][-1] = [s, time.time(), time.time() - s] except KeyError: # disconnecting call which was not confirmed for URI calling for the first time pass self.close_database(db)