1 # Written by Boxun Zhang
2 # see LICENSE.txt for license information
7 from traceback import print_exc
9 from BaseLib.__init__ import LIBRARYNAME
10 from BaseLib.Core.CacheDB.sqlitecachedb import *
11 from BaseLib.Core.CacheDB.SqliteCacheDBHandler import BasicDBHandler
12 from BaseLib.Core.simpledefs import *
14 CREATE_SEEDINGSTATS_SQL_FILE = None
15 CREATE_SEEDINGSTATS_SQL_FILE_POSTFIX = os.path.join(LIBRARYNAME, 'Core', 'Statistics', 'tribler_seedingstats_sdb.sql')
16 DB_FILE_NAME = 'tribler_seedingstats.sdb'
17 DB_DIR_NAME = 'sqlite' # db file path = DB_DIR_NAME/DB_FILE_NAME
18 CURRENT_DB_VERSION = 1
19 DEFAULT_BUSY_TIMEOUT = 10000
20 MAX_SQL_BATCHED_TO_TRANSACTION = 1000 # don't change it unless carefully tested. A transaction with 1000 batched updates took 1.5 seconds
21 SHOW_ALL_EXECUTE = False
27 def init_seeding_stats(config, db_exception_handler = None):
28 """ create SeedingStats database """
29 global CREATE_SEEDINGSTATS_SQL_FILE
30 config_dir = config['state_dir']
31 install_dir = config['install_dir']
32 CREATE_SEEDINGSTATS_SQL_FILE = os.path.join(install_dir,CREATE_SEEDINGSTATS_SQL_FILE_POSTFIX)
33 sqlitedb = SQLiteSeedingStatsCacheDB.getInstance(db_exception_handler)
34 sqlite_db_path = os.path.join(config_dir, DB_DIR_NAME, DB_FILE_NAME)
35 sqlitedb.initDB(sqlite_db_path, CREATE_SEEDINGSTATS_SQL_FILE) # the first place to create db in Tribler
38 class SQLiteSeedingStatsCacheDB(SQLiteCacheDBBase):
39 __single = None # used for multithreaded singletons pattern
40 lock = threading.RLock()
43 def getInstance(cls, *args, **kw):
44 # Singleton pattern with double-checking to ensure that it can only create one object
45 if cls.__single is None:
48 if cls.__single is None:
49 cls.__single = cls(*args, **kw)
54 def __init__(self, *args, **kw):
55 # always use getInstance() to create this object
56 if self.__single != None:
57 raise RuntimeError, "SQLiteSeedingStatsCacheDB is singleton"
59 SQLiteCacheDBBase.__init__(self, *args, **kw)
62 class SeedingStatsDBHandler(BasicDBHandler):
64 __single = None # used for multithreaded singletons pattern
65 lock = threading.Lock()
67 def getInstance(*args, **kw):
68 # Singleton pattern with double-checking
69 if SeedingStatsDBHandler.__single is None:
70 SeedingStatsDBHandler.lock.acquire()
72 if SeedingStatsDBHandler.__single is None:
73 SeedingStatsDBHandler(*args, **kw)
75 SeedingStatsDBHandler.lock.release()
76 return SeedingStatsDBHandler.__single
78 getInstance = staticmethod(getInstance)
81 if SeedingStatsDBHandler.__single is not None:
82 raise RuntimeError, "SeedingStatDBHandler is singleton"
83 SeedingStatsDBHandler.__single = self
84 db = SQLiteSeedingStatsCacheDB.getInstance()
85 BasicDBHandler.__init__(self, db, 'SeedingStats')
87 def updateSeedingStats(self, permID, reputation, dslist, interval):
88 permID = bin2str(permID)
93 if item.get_status() == DLSTATUS_SEEDING:
97 for i in range(0, len(seedings)):
100 infohash = bin2str(ds.get_download().get_def().get_infohash())
102 stats = ds.stats['stats']
105 if i == len(seedings)-1:
108 res = self.existedInfoHash(infohash)
111 # res is list of ONE tuple
112 #self.updateSeedingStat(infohash, reputation, res[0][0], interval, commit)
114 # NAT/Firewall & Seeding Behavior
115 # Store upload amount instead peer reputation
116 self.updateSeedingStat(infohash, ul, res[0][0], interval, commit)
119 #self.insertSeedingStat(infohash, permID, reputation, interval, commit)
121 # NAT/Firewall & Seeding Behavior
122 # Store upload amount instead peer reputation
123 self.insertSeedingStat(infohash, permID, ul, interval, commit)
126 def existedInfoHash(self, infohash):
128 sql = "SELECT seeding_time FROM SeedingStats WHERE info_hash='%s' and crawled=0"%infohash
131 cursor = self._db.execute_read(sql)
140 # something wrong, throw an exception?
145 def updateSeedingStat(self, infohash, reputation, seedingtime, interval, commit):
147 sql_update = "UPDATE SeedingStats SET seeding_time=%s, reputation=%s WHERE info_hash='%s' AND crawled=0"%(seedingtime + interval, reputation, infohash)
148 self._db.execute_write(sql_update, None, commit)
152 def insertSeedingStat(self, infohash, permID, reputation, interval, commit):
154 sql_insert = "INSERT INTO SeedingStats VALUES(%s, '%s', '%s', %s, %s, %s)"%(time(), permID, infohash, interval, reputation, 0)
155 self._db.execute_write(sql_insert, None, commit)
160 class SeedingStatsSettingsDBHandler(BasicDBHandler):
162 __single = None # used for multithreaded singletons pattern
163 lock = threading.Lock()
165 def getInstance(*args, **kw):
166 # Singleton pattern with double-checking
167 if SeedingStatsSettingsDBHandler.__single is None:
168 SeedingStatsSettingsDBHandler.lock.acquire()
170 if SeedingStatsSettingsDBHandler.__single is None:
171 SeedingStatsSettingsDBHandler(*args, **kw)
173 SeedingStatsSettingsDBHandler.lock.release()
174 return SeedingStatsSettingsDBHandler.__single
176 getInstance = staticmethod(getInstance)
179 if SeedingStatsSettingsDBHandler.__single is not None:
180 raise RuntimeError, "SeedingStatDBHandler is singleton"
181 SeedingStatsSettingsDBHandler.__single = self
182 db = SQLiteSeedingStatsCacheDB.getInstance()
183 BasicDBHandler.__init__(self, db, 'CrawlingSettings')
185 def loadCrawlingSettings(self):
187 sql_query = "SELECT * FROM SeedingStatsSettings"
188 cursor = self._db.execute_read(sql_query)
197 def updateCrawlingSettings(self, args):
199 sql_update = "UPDATE SeedingStatsSettings SET crawling_interval=%s, crawling_enabled=%s WHERE version=1"%(args[0], args[1])
200 cursor = self._db.execute_write(sql_update)