summaryrefslogtreecommitdiffstats
path: root/module/database/FileDatabase.py
diff options
context:
space:
mode:
Diffstat (limited to 'module/database/FileDatabase.py')
-rw-r--r--module/database/FileDatabase.py224
1 files changed, 77 insertions, 147 deletions
diff --git a/module/database/FileDatabase.py b/module/database/FileDatabase.py
index 357cd766d..eb76f468b 100644
--- a/module/database/FileDatabase.py
+++ b/module/database/FileDatabase.py
@@ -22,10 +22,9 @@ from threading import RLock
from time import time
from module.utils import formatSize, lock
-from module.PullEvents import InsertEvent, ReloadAllEvent, RemoveEvent, UpdateEvent
from module.PyPackage import PyPackage
from module.PyFile import PyFile
-from module.database import style, DatabaseBackend
+from module.database import DatabaseBackend, queue, async, inner
try:
from pysqlite2 import dbapi2 as sqlite3
@@ -40,11 +39,12 @@ class FileHandler:
def __init__(self, core):
"""Constructor"""
self.core = core
+ self.evm = core.eventManager
# translations
self.statusMsg = [_("finished"), _("offline"), _("online"), _("queued"), _("skipped"), _("waiting"), _("temp. offline"), _("starting"), _("failed"), _("aborted"), _("decrypting"), _("custom"), _("downloading"), _("processing"), _("unknown")]
- self.cache = {} #holds instances for files
+ self.cache = {} # holds instances for files
self.packageCache = {} # same for packages
#@TODO: purge the cache
@@ -54,14 +54,12 @@ class FileHandler:
#self.lock._Verbose__verbose = True
self.filecount = -1 # if an invalid value is set get current value from db
- self.queuecount = -1 #number of package to be loaded
- self.unchanged = False #determines if any changes was made since last call
+ self.queuecount = -1 # number of package to be loaded
self.db = self.core.db
def change(func):
def new(*args):
- args[0].unchanged = False
args[0].filecount = -1
args[0].queuecount = -1
args[0].jobCache = {}
@@ -118,31 +116,23 @@ class FileHandler:
@lock
@change
- def addLinks(self, urls, package):
- """adds links"""
-
- self.core.hookManager.dispatchEvent("linksAdded", urls, package)
-
- data = self.core.pluginManager.parseUrls(urls)
-
+ def addLinks(self, data, package):
+ """Add links, data = (plugin, url) tuple. Internal method you should use API."""
self.db.addLinks(data, package)
- self.core.threadManager.createInfoThread(data, package)
+ self.evm.dispatchEvent("packageUpdated", package)
- #@TODO change from reloadAll event to package update event
- self.core.pullManager.addEvent(ReloadAllEvent("collector"))
- #----------------------------------------------------------------------
@lock
@change
- def addPackage(self, name, folder, queue=0):
+ def addPackage(self, name, folder, queue=0, password=""):
"""adds a package, default to link collector"""
- lastID = self.db.addPackage(name, folder, queue)
- p = self.db.getPackage(lastID)
- e = InsertEvent("pack", lastID, p.order, "collector" if not queue else "queue")
- self.core.pullManager.addEvent(e)
- return lastID
+ pid = self.db.addPackage(name, folder, queue, password)
+ p = self.db.getPackage(pid)
+
+ self.evm.dispatchEvent("packageInserted", pid, p.queue, p.order)
+ return pid
+
- #----------------------------------------------------------------------
@lock
@change
def deletePackage(self, id):
@@ -156,7 +146,6 @@ class FileHandler:
oldorder = p.order
queue = p.queue
- e = RemoveEvent("pack", id, "collector" if not p.queue else "queue")
pyfiles = self.cache.values()
@@ -166,8 +155,7 @@ class FileHandler:
pyfile.release()
self.db.deletePackage(p)
- self.core.pullManager.addEvent(e)
- self.core.hookManager.dispatchEvent("packageDeleted", id)
+ self.evm.dispatchEvent("packageDeleted", id)
if id in self.packageCache:
del self.packageCache[id]
@@ -178,7 +166,7 @@ class FileHandler:
pack.order -= 1
pack.notifyChange()
- #----------------------------------------------------------------------
+
@lock
@change
def deleteLink(self, id):
@@ -189,8 +177,6 @@ class FileHandler:
return None
pid = f.packageid
- e = RemoveEvent("file", id, "collector" if not f.package().queue else "queue")
-
oldorder = f.order
if id in self.core.threadManager.processingIds():
@@ -201,11 +187,10 @@ class FileHandler:
self.db.deleteLink(f)
- self.core.pullManager.addEvent(e)
+ self.evm.dispatchEvent("linkDeleted", id, pid)
p = self.getPackage(pid)
- if not len(p.getChildren()):
- p.delete()
+ p.deleteIfEmpty()
pyfiles = self.cache.values()
for pyfile in pyfiles:
@@ -213,35 +198,26 @@ class FileHandler:
pyfile.order -= 1
pyfile.notifyChange()
- #----------------------------------------------------------------------
def releaseLink(self, id):
"""removes pyfile from cache"""
if id in self.cache:
del self.cache[id]
- #----------------------------------------------------------------------
def releasePackage(self, id):
"""removes package from cache"""
if id in self.packageCache:
del self.packageCache[id]
- #----------------------------------------------------------------------
def updateLink(self, pyfile):
"""updates link"""
self.db.updateLink(pyfile)
+ self.evm.dispatchEvent("linkUpdated", pyfile.id, pyfile.packageid)
- e = UpdateEvent("file", pyfile.id, "collector" if not pyfile.package().queue else "queue")
- self.core.pullManager.addEvent(e)
-
- #----------------------------------------------------------------------
def updatePackage(self, pypack):
"""updates a package"""
self.db.updatePackage(pypack)
+ self.evm.dispatchEvent("packageUpdated", pypack.id)
- e = UpdateEvent("pack", pypack.id, "collector" if not pypack.queue else "queue")
- self.core.pullManager.addEvent(e)
-
- #----------------------------------------------------------------------
def getPackage(self, id):
"""return package instance"""
@@ -250,7 +226,6 @@ class FileHandler:
else:
return self.db.getPackage(id)
- #----------------------------------------------------------------------
def getPackageData(self, id):
"""returns dict with package information"""
pack = self.getPackage(id)
@@ -274,7 +249,7 @@ class FileHandler:
return pack
- #----------------------------------------------------------------------
+
def getFileData(self, id):
"""returns dict with file information"""
if id in self.cache:
@@ -282,7 +257,7 @@ class FileHandler:
return self.db.getLinkData(id)
- #----------------------------------------------------------------------
+
def getFile(self, id):
"""returns pyfile instance"""
if id in self.cache:
@@ -290,7 +265,7 @@ class FileHandler:
else:
return self.db.getFile(id)
- #----------------------------------------------------------------------
+
@lock
def getJob(self, occ):
"""get suitable job"""
@@ -334,21 +309,6 @@ class FileHandler:
#pyfile = self.getFile(self.jobCache[occ].pop())
return pyfile
- @lock
- def getDecryptJob(self):
- """return job for decrypting"""
- if "decrypt" in self.jobCache:
- return None
-
- plugins = self.core.pluginManager.crypterPlugins.keys() + self.core.pluginManager.containerPlugins.keys()
- plugins = str(tuple(plugins))
-
- jobs = self.db.getPluginJob(plugins)
- if jobs:
- return self.getFile(jobs[0])
- else:
- self.jobCache["decrypt"] = "empty"
- return None
def getFileCount(self):
"""returns number of files"""
@@ -405,8 +365,7 @@ class FileHandler:
if id in self.packageCache:
self.packageCache[id].setFinished = False
- e = UpdateEvent("pack", id, "collector" if not self.getPackage(id).queue else "queue")
- self.core.pullManager.addEvent(e)
+ self.evm.dispatchEvent("packageUpdated", id)
@lock
@change
@@ -420,9 +379,8 @@ class FileHandler:
self.db.restartFile(id)
+ self.evm.dispatchEvent("linkUpdated", id)
- e = UpdateEvent("file", id, "collector" if not self.getFile(id).package().queue else "queue")
- self.core.pullManager.addEvent(e)
@lock
@change
@@ -431,17 +389,10 @@ class FileHandler:
p = self.db.getPackage(id)
oldorder = p.order
+ p.queue = queue
- e = RemoveEvent("pack", id, "collector" if not p.queue else "queue")
- self.core.pullManager.addEvent(e)
-
self.db.clearPackageOrder(p)
-
- p = self.db.getPackage(id)
-
- p.queue = queue
self.db.updatePackage(p)
-
self.db.reorderPackage(p, -1, True)
packs = self.packageCache.values()
@@ -452,37 +403,34 @@ class FileHandler:
self.db.commit()
self.releasePackage(id)
- p = self.getPackage(id)
-
- e = InsertEvent("pack", id, p.order, "collector" if not p.queue else "queue")
- self.core.pullManager.addEvent(e)
+
+ self.evm.dispatchEvent("packageDeleted", id)
+ self.evm.dispatchEvent("packageInserted", id, p.queue, p.order)
@lock
@change
def reorderPackage(self, id, position):
p = self.getPackage(id)
- e = RemoveEvent("pack", id, "collector" if not p.queue else "queue")
- self.core.pullManager.addEvent(e)
self.db.reorderPackage(p, position)
packs = self.packageCache.values()
for pack in packs:
if pack.queue != p.queue or pack.order < 0 or pack == p: continue
if p.order > position:
- if pack.order >= position and pack.order < p.order:
+ if position <= pack.order < p.order:
pack.order += 1
pack.notifyChange()
elif p.order < position:
- if pack.order <= position and pack.order > p.order:
+ if position >= pack.order > p.order:
pack.order -= 1
pack.notifyChange()
p.order = position
self.db.commit()
- e = InsertEvent("pack", id, position, "collector" if not p.queue else "queue")
- self.core.pullManager.addEvent(e)
+ self.evm.dispatchEvent("packageDeleted", id)
+ self.evm.dispatchEvent("packageInserted", id, p.queue, p.order)
@lock
@change
@@ -490,20 +438,17 @@ class FileHandler:
f = self.getFileData(id)
f = f[id]
- e = RemoveEvent("file", id, "collector" if not self.getPackage(f["package"]).queue else "queue")
- self.core.pullManager.addEvent(e)
-
self.db.reorderLink(f, position)
pyfiles = self.cache.values()
for pyfile in pyfiles:
if pyfile.packageid != f["package"] or pyfile.order < 0: continue
if f["order"] > position:
- if pyfile.order >= position and pyfile.order < f["order"]:
+ if position <= pyfile.order < f["order"]:
pyfile.order += 1
pyfile.notifyChange()
elif f["order"] < position:
- if pyfile.order <= position and pyfile.order > f["order"]:
+ if position >= pyfile.order > f["order"]:
pyfile.order -= 1
pyfile.notifyChange()
@@ -512,15 +457,14 @@ class FileHandler:
self.db.commit()
- e = InsertEvent("file", id, position, "collector" if not self.getPackage(f["package"]).queue else "queue")
- self.core.pullManager.addEvent(e)
+ self.evm.dispatchEvent("packageUpdated", f["package"])
+
@change
def updateFileInfo(self, data, pid):
""" updates file info (name, size, status, url)"""
ids = self.db.updateLinkInfo(data)
- e = UpdateEvent("pack", pid, "collector" if not self.getPackage(pid).queue else "queue")
- self.core.pullManager.addEvent(e)
+ self.evm.dispatchEvent("packageUpdated", pid)
def checkPackageFinished(self, pyfile):
""" checks if package is finished and calls hookmanager """
@@ -574,25 +518,25 @@ class FileHandler:
self.db.restartFailed()
class FileMethods():
- @style.queue
+ @queue
def filecount(self, queue):
"""returns number of files in queue"""
self.c.execute("SELECT COUNT(*) FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE p.queue=?", (queue, ))
return self.c.fetchone()[0]
- @style.queue
+ @queue
def queuecount(self, queue):
""" number of files in queue not finished yet"""
self.c.execute("SELECT COUNT(*) FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE p.queue=? AND l.status NOT IN (0,4)", (queue, ))
return self.c.fetchone()[0]
- @style.queue
+ @queue
def processcount(self, queue, fid):
""" number of files which have to be proccessed """
self.c.execute("SELECT COUNT(*) FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE p.queue=? AND l.status IN (2,3,5,7,12) AND l.id != ?", (queue, str(fid)))
return self.c.fetchone()[0]
- @style.inner
+ @inner
def _nextPackageOrder(self, queue=0):
self.c.execute('SELECT MAX(packageorder) FROM packages WHERE queue=?', (queue,))
max = self.c.fetchone()[0]
@@ -601,7 +545,7 @@ class FileMethods():
else:
return 0
- @style.inner
+ @inner
def _nextFileOrder(self, package):
self.c.execute('SELECT MAX(linkorder) FROM links WHERE package=?', (package,))
max = self.c.fetchone()[0]
@@ -610,13 +554,13 @@ class FileMethods():
else:
return 0
- @style.queue
+ @queue
def addLink(self, url, name, plugin, package):
order = self._nextFileOrder(package)
self.c.execute('INSERT INTO links(url, name, plugin, package, linkorder) VALUES(?,?,?,?,?)', (url, name, plugin, package, order))
return self.c.lastrowid
- @style.queue
+ @queue
def addLinks(self, links, package):
""" links is a list of tupels (url,plugin)"""
order = self._nextFileOrder(package)
@@ -624,27 +568,27 @@ class FileMethods():
links = [(x[0], x[0], x[1], package, o) for x, o in zip(links, orders)]
self.c.executemany('INSERT INTO links(url, name, plugin, package, linkorder) VALUES(?,?,?,?,?)', links)
- @style.queue
- def addPackage(self, name, folder, queue):
+ @queue
+ def addPackage(self, name, folder, queue, password):
order = self._nextPackageOrder(queue)
- self.c.execute('INSERT INTO packages(name, folder, queue, packageorder) VALUES(?,?,?,?)', (name, folder, queue, order))
+ self.c.execute('INSERT INTO packages(name, folder, queue, packageorder, password) VALUES(?,?,?,?,?)', (name, folder, queue, order, password))
return self.c.lastrowid
- @style.queue
+ @queue
def deletePackage(self, p):
self.c.execute('DELETE FROM links WHERE package=?', (str(p.id),))
self.c.execute('DELETE FROM packages WHERE id=?', (str(p.id),))
self.c.execute('UPDATE packages SET packageorder=packageorder-1 WHERE packageorder > ? AND queue=?', (p.order, p.queue))
- @style.queue
+ @queue
def deleteLink(self, f):
self.c.execute('DELETE FROM links WHERE id=?', (str(f.id),))
self.c.execute('UPDATE links SET linkorder=linkorder-1 WHERE linkorder > ? AND package=?', (f.order, str(f.packageid)))
- @style.queue
+ @queue
def getAllLinks(self, q):
"""return information about all links in queue q
@@ -677,7 +621,7 @@ class FileMethods():
return data
- @style.queue
+ @queue
def getAllPackages(self, q):
"""return information about packages in queue q
(only useful in get all data)
@@ -692,7 +636,7 @@ class FileMethods():
}
"""
self.c.execute('SELECT p.id, p.name, p.folder, p.site, p.password, p.queue, p.packageorder, s.sizetotal, s.sizedone, s.linksdone, s.linkstotal \
- FROM packages p JOIN pstats s ON p.id = s.id \
+ FROM packages p LEFT OUTER JOIN pstats s ON p.id = s.id \
WHERE p.queue=? ORDER BY p.packageorder', str(q))
data = {}
@@ -705,16 +649,16 @@ class FileMethods():
'password': r[4],
'queue': r[5],
'order': r[6],
- 'sizetotal': int(r[7]),
- 'sizedone': r[8] if r[8] else 0, #these can be None
+ 'sizetotal': int(r[7]) if r[7] else 0,
+ 'sizedone': int(r[8]) if r[8] else 0, #these can be None
'linksdone': r[9] if r[9] else 0,
- 'linkstotal': r[10],
+ 'linkstotal': r[10] if r[10] else 0,
'links': {}
}
return data
- @style.queue
+ @queue
def getLinkData(self, id):
"""get link information as dict"""
self.c.execute('SELECT id,url,name,size,status,error,plugin,package,linkorder FROM links WHERE id=?', (str(id), ))
@@ -738,7 +682,7 @@ class FileMethods():
return data
- @style.queue
+ @queue
def getPackageData(self, id):
"""get data about links for a package"""
self.c.execute('SELECT id,url,name,size,status,error,plugin,package,linkorder FROM links WHERE package=? ORDER BY linkorder', (str(id), ))
@@ -762,15 +706,15 @@ class FileMethods():
return data
- @style.async
+ @async
def updateLink(self, f):
self.c.execute('UPDATE links SET url=?,name=?,size=?,status=?,error=?,package=? WHERE id=?', (f.url, f.name, f.size, f.status, f.error, str(f.packageid), str(f.id)))
- @style.queue
+ @queue
def updatePackage(self, p):
self.c.execute('UPDATE packages SET name=?,folder=?,site=?,password=?,queue=? WHERE id=?', (p.name, p.folder, p.site, p.password, p.queue, str(p.id)))
- @style.queue
+ @queue
def updateLinkInfo(self, data):
""" data is list of tupels (name, size, status, url) """
self.c.executemany('UPDATE links SET name=?, size=?, status=? WHERE url=? AND status IN (1,2,3,14)', data)
@@ -780,7 +724,7 @@ class FileMethods():
ids.append(int(r[0]))
return ids
- @style.queue
+ @queue
def reorderPackage(self, p, position, noMove=False):
if position == -1:
position = self._nextPackageOrder(p.queue)
@@ -792,7 +736,7 @@ class FileMethods():
self.c.execute('UPDATE packages SET packageorder=? WHERE id=?', (position, str(p.id)))
- @style.queue
+ @queue
def reorderLink(self, f, position):
""" reorder link with f as dict for pyfile """
if f["order"] > position:
@@ -803,20 +747,20 @@ class FileMethods():
self.c.execute('UPDATE links SET linkorder=? WHERE id=?', (position, f["id"]))
- @style.queue
+ @queue
def clearPackageOrder(self, p):
self.c.execute('UPDATE packages SET packageorder=? WHERE id=?', (-1, str(p.id)))
self.c.execute('UPDATE packages SET packageorder=packageorder-1 WHERE packageorder > ? AND queue=? AND id != ?', (p.order, p.queue, str(p.id)))
- @style.async
+ @async
def restartFile(self, id):
self.c.execute('UPDATE links SET status=3,error="" WHERE id=?', (str(id),))
- @style.async
+ @async
def restartPackage(self, id):
self.c.execute('UPDATE links SET status=3 WHERE package=?', (str(id),))
- @style.queue
+ @queue
def getPackage(self, id):
"""return package instance from id"""
self.c.execute("SELECT name,folder,site,password,queue,packageorder FROM packages WHERE id=?", (str(id), ))
@@ -824,8 +768,8 @@ class FileMethods():
if not r: return None
return PyPackage(self.manager, id, * r)
- #----------------------------------------------------------------------
- @style.queue
+
+ @queue
def getFile(self, id):
"""return link instance from id"""
self.c.execute("SELECT url, name, size, status, error, plugin, package, linkorder FROM links WHERE id=?", (str(id), ))
@@ -834,58 +778,44 @@ class FileMethods():
return PyFile(self.manager, id, * r)
- @style.queue
+ @queue
def getJob(self, occ):
"""return pyfile ids, which are suitable for download and dont use a occupied plugin"""
-
- #@TODO improve this hardcoded method
- pre = "('DLC', 'LinkList', 'SerienjunkiesOrg', 'CCF', 'RSDF')" #plugins which are processed in collector
-
cmd = "("
for i, item in enumerate(occ):
if i: cmd += ", "
cmd += "'%s'" % item
-
- cmd += ")"
-
- cmd = "SELECT l.id FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE ((p.queue=1 AND l.plugin NOT IN %s) OR l.plugin IN %s) AND l.status IN (2,3,14) ORDER BY p.packageorder ASC, l.linkorder ASC LIMIT 5" % (cmd, pre)
-
- self.c.execute(cmd) # very bad!
- return [x[0] for x in self.c]
-
- @style.queue
- def getPluginJob(self, plugins):
- """returns pyfile ids with suited plugins"""
- cmd = "SELECT l.id FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE l.plugin IN %s AND l.status IN (2,3,14) ORDER BY p.packageorder ASC, l.linkorder ASC LIMIT 5" % plugins
+ cmd += ")"
+ cmd = "SELECT l.id FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE p.queue=1 AND l.plugin NOT IN %s AND l.status IN (2,3,14) ORDER BY p.packageorder ASC, l.linkorder ASC LIMIT 5" % cmd
self.c.execute(cmd) # very bad!
return [x[0] for x in self.c]
- @style.queue
+ @queue
def getUnfinished(self, pid):
"""return list of max length 3 ids with pyfiles in package not finished or processed"""
self.c.execute("SELECT id FROM links WHERE package=? AND status NOT IN (0, 4, 13) LIMIT 3", (str(pid),))
return [r[0] for r in self.c]
- @style.queue
+ @queue
def deleteFinished(self):
self.c.execute("DELETE FROM links WHERE status IN (0,4)")
self.c.execute("DELETE FROM packages WHERE NOT EXISTS(SELECT 1 FROM links WHERE packages.id=links.package)")
- @style.queue
+ @queue
def restartFailed(self):
self.c.execute("UPDATE links SET status=3,error='' WHERE status IN (8, 9)")
- @style.queue
+ @queue
def findDuplicates(self, id, folder, filename):
""" checks if filename exists with different id and same package """
self.c.execute("SELECT l.plugin FROM links as l INNER JOIN packages as p ON l.package=p.id AND p.folder=? WHERE l.id!=? AND l.status=0 AND l.name=?", (folder, id, filename))
return self.c.fetchone()
- @style.queue
+ @queue
def purgeLinks(self):
self.c.execute("DELETE FROM links;")
self.c.execute("DELETE FROM packages;")