def add_local(self, database, target, subtree): database = truepath(database) target = hashdb_sql.normalize(truepath(target)) if target not in ['//' or '\\\\'] else None if target in ['/', '//']: target = None subtree = hashdb_sql.normalize(truepath(subtree)) if subtree not in ['//' or '\\\\'] else None if subtree in ['/', '//']: subtree = None data = self.get_local_by_path(database) if data == None: data = HashDatabase2.AttachLocal('localdb%02d' % len(self.locals), database, {}) self._locals.append(data) self._subtrees_add(data.grafts.setdefault(target, set()), subtree)
def add_remote(self, database, subtree): database = truepath(database) subtree = hashdb_sql.normalize(truepath(subtree)) if subtree not in ['//' or '\\\\'] else None if subtree == '/': subtree = None data = self.get_remote_by_path(database) if data == None: data = HashDatabase2.AttachRemote('remotedb%02d' % len(self._remotes), database, set()) self._subtrees_add(data.subtress, subtree)
def path_select_duplicates(self, path, hash, size): path = hashdb_sql.normalize(path) for select, paramaters in self.build_selects( sources=[None, self.locals, self.remotes], columns=HashDatabase2.RowDetailed._fields, filters=[ 'hash = :hash', 'size = :size', 'path <> :path', ] ): paramaters['path'] = path paramaters['size'] = size paramaters['hash'] = hash log.debug('-- select') log.debug(select) log.debug('-- paramaters') log.debug(paramaters) for row in self.connection.execute(select, paramaters): yield HashDatabase2.RowDetailed(**row)
def path_hash(self, path, stat): '''Returns: hash of the file specified by @path if available, else None If hash is available and marking is True, marks the path. Seeks hash information from all local databases (but not remote ones) ''' path = hashdb_sql.normalize(path) # check primary table row = self.connection.execute('SELECT mark, hash, time, size FROM hashtab WHERE path=?', (path,)).fetchone() if row: # database is already up to date? if row['mark'] == self.mark: return row['hash'] # database contains a match, but it isn't yet tagged if (row['time'] == stat.st_mtime) and (row['size'] == stat.st_size): if self.marking: self.connection.execute('UPDATE hashtab SET mark=? WHERE (path=?) AND (time=?) AND (size=?)', (self.mark, path, stat.st_mtime, stat.st_size)) return row['hash'] # check attached local databases for local in self.locals: for select, paramaters in self.build_selects_local(local, ['hash'], ["%(path)s = :target_path", "%(time)s = :target_time", "%(size)s = :target_size"]): paramaters['target_path'] = path paramaters['target_time'] = stat.st_mtime paramaters['target_size'] = stat.st_size #log.debug(select) #log.debug(paramaters) row = self.connection.execute(select, paramaters).fetchone() if row: self.path_setstat(path, stat, row['hash']) return row['hash'] # nothing found return None
def path_select_subtrees(self, targets=['//'], filters=[], paramaters={}, depth=True): alltargets = {} for target in targets: target_tables, target_path = self.target_split(target) target_path = hashdb_sql.normalize(target_path) for target_type, target_index, target_table in target_tables: alltargets.setdefault((target_type, target_index, target_table), []).append(target_path) dborder = list(alltargets.keys()) dborder.sort(key=lambda x: x[2]) allselects = [] allparamaters = paramaters.copy() for table_index, target in enumerate(order): target_type, target_index, target_table = target target_paths = alltargets[target] aliases = { 'table': target_table } if target_type == 'prime': aliases['mark'] = "mark" aliases['root'] = "'<prime>'" aliases['full'] = "'<prime>:' || path" aliases['user'] = "******" elif target_type == 'local': aliases['mark'] = "0" aliases['root'] = "'<local>'" aliases['full'] = "'<local>:' || path" aliases['user'] = "******" elif target_type == 'remote': allparamaters['_dbalias%02d' % target_index] = self.remote_fnalias(target_index) aliases['mark'] = "0" aliases['root'] = ":_dbalias%02d || ':' || path" % target_index aliases['full'] = ":_dbalias%02d || ':' || path" % target_index aliases['user'] = "******" % target_index select = """ SELECT path, time, size, hash, %(mark)s AS mark, %(root)s AS root, %(full)s AS full, %(user)s AS user FROM %(table)s WHERE """ % aliases pathfilters = [] if ('//' not in target_paths) and ('/' not in target_paths): for i, target_path in enumerate(target_paths): name = '_target%02d_%02d' % (table_index, i) allparamaters[name] = target_path pathfilters.append("(path = :%(name)s)" % name) pathfilters.append("(substr(path, 1, length(:%(name)s) + 1) = path || '/')") select += ' AND '.join( ['1'] ['(' + ' OR '.join(pathfilters) + ')'] +\ ['(' + f + ')' for f in filters] ) allselects.append(select) select = ' UNION '.join(allselects) + ' ORDER BY ' + ('mark DESC, full' if depth else 'mark DESC, path_count(path), path') for row in self.connection.execute(select, allparamaters): yield self.RowDetailed(**row)
def path_get_prime(self, path): path = hashdb_sql.normalize(path) row = self.connection.execute('SELECT * FROM hashtab WHERE path=?', (path,)).fetchone() if row: return HashDatabase2.RowBasic(**row) return None
def path_setdirect(self, path, time, size, hash): '''inserts/updates @path in the database''' path = hashdb_sql.normalize(path) return self.connection.execute('INSERT OR REPLACE INTO hashtab (path, time, size, hash, mark) VALUES (?,?,?,?,?)', (path, time, size, hash, self.mark)).rowcount