def accept(self, parent_id, name, stat_info, arc_flag, fullPath = None): # print fullPath, name fileInfo = FileInfo(name = name, fromStat = stat_info) if type(parent_id) == type(()): oldParentId = parent_id[1] else: oldParentId = parent_id match = self.fileApi.findByParentIdAndName(self.disk_id, oldParentId, name) if len(match) > 0: fi = FileInfo(fromDb = match[0]) cmpr = fileInfo.compare(fi) if not (cmpr & FileInfo.MATCH_TYPE): print "Type changed!" # If file type was changed, that's horrible self.newFiles.append((parent_id, name, stat_info, arc_flag, fullPath)) self.i += 1 return (int(self.i), -1) if cmpr == FileInfo.MATCH_ALL: # print match, " - perfect match" pass else: if self.debugLevel & DbUpdateDumper.DEBUG_STAGE_1: print "!", `fileInfo`, `fi`, " - match:", cmpr sql = "UPDATE directory SET size=%d, mdate='%s' WHERE id=%d" % (fileInfo.size, fileInfo.mtime, match[0]['id']) if self.debugLevel & DbUpdateDumper.DEBUG_SQL: print sql self.c.execute(sql) self.i += 1 del self.idMap[match[0][0]] return (int(self.i), match[0][0]) else: if self.debugLevel & DbUpdateDumper.DEBUG_STAGE_1: print "+", `fileInfo` self.newFiles.append((parent_id, name, stat_info, arc_flag, fullPath)) self.i += 1 return (int(self.i), -1)
def finish(self): print print "Stage 2: Results of volume/DB scan" for f in self.newFiles: if self.debugLevel & DbUpdateDumper.DEBUG_STAGE_2: print "+", self.getInVoumePath(f[4]) missingDirs = [] for f in self.idMap.values(): if self.debugLevel & DbUpdateDumper.DEBUG_STAGE_2: print "-", self.resolverApi.getFilePath(f["id"]) recs = self.filenameMap.get(f['name'], []) recs.append(f) self.filenameMap[f['name']] = recs recs = self.sizeMap.get(f['size'], []) recs.append(f) self.sizeMap[f['size']] = recs if f['is_dir']: missingDirs.append(f) if self.debugLevel & DbUpdateDumper.DEBUG_STAGE_2: print "New files:", self.newFiles print "Missing by id:", self.idMap print "Missing by name:", self.filenameMap print "Missing by size:", self.sizeMap print "Missing directories:", missingDirs self.deletions = [] self.additions = [] self.updates = [] print print "Stage 3: Matching files" for f in self.newFiles: if self.debugLevel & DbUpdateDumper.DEBUG_STAGE_3: print "Processing new:", f newFile = FileInfo(name = f[1], fromStat = f[2]) # match for new file is found (i.e. the file was updated) matchFound = False if self.filenameMap.has_key(newFile.name): completeMatches = [] for match in self.filenameMap[newFile.name]: cmpr = newFile.compare(FileInfo(fromDb = match)) if self.debugLevel & DbUpdateDumper.DEBUG_STAGE_3: print hex(cmpr), ":", match assert cmpr & FileInfo.MATCH_TYPE, "Changing type is not supported" if cmpr == FileInfo.MATCH_ALL: completeMatches.append(match) elif cmpr & FileInfo.MATCH_SIZE == 0: pass # if sizes don't match, it's not match at all else: assert False, "This match type is not supported: %d" % cmpr assert len(completeMatches) <= 1, "More than one complete match" if len(completeMatches) == 1: self.reparent(f[4], newFile, completeMatches[0]) self.unsetByDbRec(completeMatches[0]) matchFound = True else: assert False, "Non-complete match(es) not yet supported" if not matchFound and not newFile.isDir and self.sizeMap.has_key(newFile.size): if self.debugLevel & DbUpdateDumper.DEBUG_STAGE_3: print "Matches by size: ", self.sizeMap[newFile.size] perfectMatches = [] imperfectMatches = [] for match in self.sizeMap[newFile.size]: cmpr = newFile.compare(FileInfo(fromDb = match)) if self.debugLevel & DbUpdateDumper.DEBUG_STAGE_3: print "match", hex(cmpr), ":", match if cmpr & (FileInfo.MATCH_TYPE|FileInfo.MATCH_SIZE|FileInfo.MATCH_MTIME): perfectMatches.append((cmpr, match)) elif cmpr & (FileInfo.MATCH_TYPE|FileInfo.MATCH_SIZE): imperfectMatches.append((cmpr, match)) else: assert False if self.debugLevel & DbUpdateDumper.DEBUG_STAGE_3: print "Perfect matches:", perfectMatches print "Imperfect matches:", imperfectMatches if len(perfectMatches) == 0 and len(imperfectMatches) == 0: pass # no match at all if len(perfectMatches) == 1 and len(imperfectMatches) == 0: match = perfectMatches[0][1] self.reparent(f[4], newFile, match) self.unsetByDbRec(match) matchFound = True if self.debugLevel & DbUpdateDumper.DEBUG_STAGE_3: print "Missing by id:", self.idMap print "Missing by name:", self.filenameMap print "Missing by size:", self.sizeMap print "Missing directories:", missingDirs else: assert False, "More than one match not supported" if not matchFound: self.insertNew(f[4], newFile) # idMap now has unclaimed files - this means, delete them fileIds = map(lambda f: f["id"], self.idMap.values()) categoryApi = objects.Category.Category(self.connection) assert not categoryApi.isCategoriesAssignedToFiles(fileIds), "Files to delete have categories assigned" for f in self.idMap.values(): self.deleteOld(f) print print "Stage 4: Final changes" for r in self.updates: print "! %s -> %s" % (r[0], r[1]) for r in self.deletions: print "- %s" % (r) for r in self.additions: print "+ %s" % (r) # self.connection.rollback() DbDumper.finish(self)