class Reduce(QObject): def __init__(self,reduce='../../bin/redcsl'): traceLogger.debug("######### reduce is %s", reduce) super(Reduce,self).__init__() self.__process = procNew(sys.path[0] + "/" + reduce) self.__processId = self.__process['processId'] self.__process = self.__process['handle'] self.__mutex = QMutex() def __del__(self): traceLogger.warning("about to delete Reduce process - this is good!") procDelete(self.__process) def compute(self,c): self.__mutex.lock() l = c.split('\n') for sc in l: a = self.__compute(sc) self.__mutex.unlock() return a def __compute(self,c): a = ansNew(self.__process,c) ansDelete(a['handle']) return a['data'] def signal(self,c): signalLogger.debug("c=%s" % c) os.system('/bin/kill -' + c + ' ' + str(self.__processId))
class WorkThread(QThread): def __init__(self, runnable): super(WorkThread, self).__init__() self.runnable = runnable self.stopped = False self.mutex = QMutex() def run(self, *args, **kwargs): self.runnable() self.stop() self.finished.connect(self.deleteLater) def stop(self): try: self.mutex.lock() self.stopped = False finally: self.mutex.unlock() def isStopped(self): try: self.mutex.lock() return self.stopped finally: self.mutex.unlock()
class SyncThread(QThread): """Sync notes with evernote thread""" force_sync_signal = Signal() sync_state_changed = Signal(int) def __init__(self, app, *args, **kwargs): QThread.__init__(self, *args, **kwargs) self.app = app self.status = STATUS_NONE self.last_sync = datetime.now() self.timer = QTimer() self.timer.timeout.connect(self.sync) self.update_timer() self.wait_condition = QWaitCondition() self.mutex = QMutex() def update_timer(self): self.timer.stop() delay = int(self.app.settings.value('sync_delay') or 0) or DEFAULT_SYNC_DELAY if delay != SYNC_MANUAL: self.timer.start(delay) def run(self): self.session = get_db_session() self.sq = self.session.query self.auth_token = get_auth_token() self.note_store = get_note_store(self.auth_token) self.perform() while True: self.mutex.lock() self.wait_condition.wait(self.mutex) self.perform() self.mutex.unlock() def force_sync(self): self.timer.stop() self.sync() self.update_timer() @Slot() def sync(self): self.wait_condition.wakeAll() def perform(self): """Perform all sync""" self.status = STATUS_SYNC self.last_sync = datetime.now() self.sync_state_changed.emit(SYNC_STATE_START) try: self.local_changes() self.remote_changes() except Exception, e: # maybe log this self.session.rollback() finally:
class Buffer(QObject): """ Class buffers annotation objects to cache from database for given frame or frame interval. :param video: reference to video object :type video: tovian.models.entity.Video :param parent: parent widget :type parent: PySide.QtCore.QObject """ checkBufferState = Signal() buffering = Signal() buffered = Signal() initialized = Signal() MAX_MEMORY_USAGE = 52428800 # 50MB def __init__(self, video, user_id, parent=None): super(Buffer, self).__init__(parent) self.mutex = QMutex() self.video = video self.last_frame_accessed = (0, 0) self.displayed_frames_range = 1 # must be odd self.video_frame_count = self.video.frame_count self.video_frame_fps = self.video.fps self.user_id = user_id self.cache = {} self.cached_min_frame = 0 self.cached_max_frame = 0 self.cached_time = 10 # seconds self.cached_time_border = 0.25 # 25 percent from cached interval, where it starts to buffer new objects self.checkBufferState.connect(self.__checkBuffer) def initBuffer(self): """ Called just first time after initializing buffed and moving to separated thread. """ new_start = 0 new_stop = int(self.cached_time * self.video_frame_fps) new_stop = new_stop if new_stop < self.video_frame_count else self.video_frame_count logger.debug("Filling buffer on interval [%s, %s]", new_start, new_stop) self.__bufferObjects(new_start, new_stop) self.initialized.emit() def setDisplayedFrameRange(self, length): """ Sets how long frame interval is displayed (non-vis annotations). i.e. 11 meas [currentframe-5, currentframe+5] :param length: range length :type length: int """ logger.debug("Setting new displayed range value %s", length) self.mutex.lock() self.displayed_frames_range = length self.mutex.unlock() def getObjectsInFrame(self, frame): """ Returns list of annotation objects for given frame. When accessing to cache, cached is locked for other access. :type frame: int :rtype: tuple of (tovian.models.entity.AnnotationObject, int, int) :raise AttributeError: if given frame number is out of range [0, video.frame_count] """ logger.debug("Called get an_object from buffer for frame: %s", frame) if frame < 0 or frame > self.video_frame_count: raise AttributeError("Given frame number %s is out of range [0, %s]" % (frame, self.video_frame_count)) # --- locked ---- self.mutex.lock() try: objects = self.cache[frame] except KeyError: logger.error("Buffer objects could not be found for frame: %s", frame) models.repository.logs.insert('gui.exception.get_obj_from_buffer_error', "Buffer objects could not be found for frame: %s" % frame, annotator_id=self.user_id) objects = self.video.annotation_objects_in_frame(frame) else: objects = objects.values() finally: self.last_frame_accessed = (frame, frame) self.mutex.unlock() # don't forget to release lock # --------------- self.checkBufferState.emit() return tuple(objects) def getObjectsInFrameInterval(self, frame_from, frame_to): """ Returns list of annotation objects for given frame interval. :type frame_from: int :type frame_to: int :rtype: tuple of (tovian.models.entity.AnnotationObject, int, int) :raise AttributeError: if given frame number interval is not in range [0, video.frame_count] or is invalid """ logger.debug("Called get an_object from buffer for frame interval [%s, %s]", frame_from, frame_to) if frame_from > frame_to: raise AttributeError("frame_from '%s' is greater than frame_to '%s'" % (frame_from, frame_to)) if frame_from < 0 or frame_to < 0 or frame_to > self.video_frame_count or frame_from > self.video_frame_count: raise AttributeError("Given frame interval [%s, %s] is out of range [0, %s]" % (frame_from, frame_to, self.video_frame_count)) if frame_from == frame_to: objects = self.getObjectsInFrame(frame_from) return objects objects = [] self.mutex.lock() try: for frame in range(frame_from, frame_to + 1): try: data = self.cache[frame] except KeyError: logger.error("Buffer objects could not be found for frame: %s", frame) models.repository.logs.insert('gui.exception.get_obj_from_buffer_error', "Buffer objects could not be found for frame: %s" % frame, annotator_id=self.user_id) data = self.video.annotation_objects_in_frame(frame) else: data = data.values() objects.extend(data) # converts iterator to values finally: self.last_frame_accessed = (frame_from, frame_from) self.mutex.unlock() self.checkBufferState.emit() return tuple(set(objects)) def resetBuffer(self, frame, clear_all=False, clear_object=None): """ Reset buffer - loads new objects depending on given frame number (i.e. when seeking to new frame). Method requests lock when clearing cache! :param frame: target frame :type frame: int :param clear_all: manually clears buffer :type clear_all: bool :param clear_object: object that has to be refreshed in buffer (object_id, old_start_frame, old_end_frame) :raise ValueError: if given frame number is out of range [0, video.frame_count] | when new min and max cached frame are equaled or invalid """ #logger.debug("Locking thread") #self.mutex.lock() #self.last_frame_accessed = (min_frame_interval, max_frame_interval) #self.mutex.unlock() #logger.debug("Thread unlocked") if frame < 0 or frame > self.video_frame_count: raise ValueError("Given frame number %s is out of range [0, %s]" % (frame, self.video_frame_count)) if not clear_all and not clear_object: # if new frame has been already cached if frame in self.cache: min_frame = frame - ((self.displayed_frames_range - 1) / 2.0) max_frame = frame + ((self.displayed_frames_range - 1) / 2.0) min_frame = 0 if min_frame < 0 else min_frame max_frame = self.video_frame_count if max_frame > self.video_frame_count else max_frame # if new frame display frame range is also cached if self.cached_min_frame <= min_frame and self.cached_max_frame >= max_frame: logger.debug("New frame and displayed frame interval is cached and no need to reset") return else: logger.debug("Target frame is cached, but displayed frame range isn't.") else: logger.debug("Target frame is not cached.") # calculate new start_frame and stop_frame new_start_frame = frame - int((self.cached_time / 2.0) * self.video_frame_fps) new_stop_frame = frame + int((self.cached_time / 2.0) * self.video_frame_fps) new_start_frame = 0 if new_start_frame < 0 else new_start_frame new_stop_frame = self.video_frame_count if new_stop_frame > self.video_frame_count else new_stop_frame if new_stop_frame == new_start_frame or new_stop_frame < new_start_frame: logger.error("New start_frame '%s' and stop_frame '%s' are equal or invalid.", new_start_frame, new_stop_frame) raise ValueError("New start_frame '%s' and stop_frame '%s' are equal or invalid." % (new_start_frame, new_stop_frame)) if clear_object: object_id, old_start, old_end = clear_object logger.debug("Deleting old object data from cache") self.mutex.lock() for i in range(old_start, old_end + 1): cache_data = self.cache[i] del cache_data[object_id] self.mutex.unlock() logger.debug("Thread unlocked") ## TODO DELETE !!!!!!!!!!!!!!!!!!!!!!!! FOR DEBUGGING PURPOSES #for key, value in self.cache.iteritems(): # if object_id in value: # print key, value # raise Exception() logger.debug("Clearing object id '%s' from buffer and resetting for new frame: %s", object_id, frame) self.__bufferObjectByID(frame, object_id) else: logger.debug("Resetting and clearing whole buffer for new frame: %s", frame) self.mutex.lock() self.cache = {} self.mutex.unlock() self.__bufferObjects(new_start_frame, new_stop_frame) # manually invoked buffering def __bufferObjects(self, frame_from, frame_to): """ Called to buffer new objects from database for given frame interval. Method requests lock when writing to cache! :type frame_from: int :type frame_to: int :raise ValueError: When frame_from or frame_to has invalid value (out of range, etc.) """ logger.debug("Tries buffer new frame interval [%s, %s]...", frame_from, frame_to) if frame_from > frame_to or frame_from < 0 or frame_to > self.video_frame_count: raise ValueError("Invalid frame_from '%s' and frame_to values '%s'", frame_from, frame_to) self.mutex.lock() try: objectsTuples = self.video.annotation_objects_in_frame_intervals([(frame_from, frame_to)]) except Exception: # TODO display error to user logger.exception("Error when buffering new objects from database on interval [%s, %s]", frame_from, frame_to) models.repository.logs.insert('gui.exception.buffering_new_obj_error', "Error when buffering new objects from database on interval [%s, %s]" % (frame_from, frame_to), annotator_id=self.user_id) self.mutex.unlock() # don't forget to release lock return cleared = not self.cache self.buffering.emit() #logger.debug("Locking thread -> adding new data to cache") #self.mutex.lock() # request lock try: for frame in range(frame_from, frame_to + 1): try: frame_dict = self.cache[frame] except KeyError: self.cache[frame] = {} frame_dict = self.cache[frame] # add record to cache for objectTuple in objectsTuples: an_object, start_frame, end_frame = objectTuple if start_frame <= frame <= end_frame: frame_dict[an_object.id] = objectTuple # if cache has been cleared when method called, set min and max pointers as usually if cleared: self.cached_max_frame = frame_to self.cached_min_frame = frame_from # if don't, cache has been extended, so moves pointer a bit else: if frame_from < self.cached_min_frame: self.cached_min_frame = frame_from if frame_to > self.cached_max_frame: self.cached_max_frame = frame_to finally: self.mutex.unlock() # don't forget to release lock self.buffered.emit() logger.debug("Buffered new time interval [%s, %s]", frame_from, frame_to) def __bufferObjectByID(self, target_frame, object_id): """ Buffer new object by given ID from database on given frame :type target_frame: int :type object_id: int :raise ValueError: When frame is out of range """ logger.debug("Trying to buffer new object id '%s' on frame '%s'", object_id, target_frame) if target_frame < 0 or target_frame > self.video_frame_count: raise ValueError("Given frame number is out of video frame count range") try: objectTuples = self.video.annotation_objects_in_frame_intervals([(target_frame, target_frame)], [object_id, ]) except Exception: # TODO display error to user logger.exception("Error when buffering new object id '%s' from database on on frame '%s'", object_id, target_frame) models.repository.logs.insert('gui.exception.buffering_new_obj_error', "Error when buffering new object id '%s' from database on on frame '%s'" % (object_id, target_frame), annotator_id=self.user_id) return if not objectTuples: logger.warning("No object id '%s' for frame '%s' in database!") return elif len(objectTuples) > 1: logger.warning("Returned more than one object by id from database!") self.buffering.emit() logger.debug("Locking thread -> adding to cache new data") self.mutex.lock() try: an_object, start_frame, end_frame = objectTuples[0] for frame in range(start_frame, end_frame + 1): try: frame_dict = self.cache[frame] except KeyError: self.cache[frame] = {} frame_dict = self.cache[frame] frame_dict[an_object.id] = objectTuples[0] finally: self.mutex.unlock() logger.debug("Thread unlocked") self.buffered.emit() logger.debug("Buffered new by id '%s' on frame '%s'", object_id, target_frame) @Slot() def __checkBuffer(self): """ Method called when some data in cache has been accessed to check, if needs to be loaded new objects from database. """ memory_usage = sys.getsizeof(self.cache) if memory_usage > self.MAX_MEMORY_USAGE: logger.warning("Reached maximum allowed memory usage '%s' bytes -> resetting buffer", self.MAX_MEMORY_USAGE) lower_accessed_frame, higher_accessed_frame = self.last_frame_accessed if lower_accessed_frame == higher_accessed_frame: frame = higher_accessed_frame else: frame = ((higher_accessed_frame - lower_accessed_frame) / 2) + lower_accessed_frame self.resetBuffer(frame, clear_all=True) return cached_min_border = self.cached_min_frame - self.last_frame_accessed[0] cached_max_border = self.cached_max_frame - self.last_frame_accessed[1] allowed_border = self.cached_time_border * self.cached_time * self.video_frame_fps # ---- # If the last_accessed_frame pointer is between borders (typically between 25% and 75% cache), do nothing. # else cache new interval and merge cached data # i.e. cache status = |bottom|--------------0current0--|top| => max border passed, cache new objects => # => new status = |bottom|--------------0current0--(-----------------------------)|top| # ---- # bottom border if cached_min_border > -allowed_border: new_stop = self.cached_min_frame - 1 new_start = new_stop - int(self.cached_time * self.video_frame_fps) new_start = 0 if new_start < 0 else new_start new_start = self.video_frame_count if new_start > self.video_frame_count else new_start new_stop = 0 if new_stop < 0 else new_stop new_stop = self.video_frame_count if new_stop > self.video_frame_count else new_stop if new_start != new_stop: logger.debug("Check buffer - buffer needs to load new objects, direction down") self.__bufferObjects(new_start, new_stop) # upper border elif cached_max_border < allowed_border: new_start = self.cached_max_frame + 1 new_stop = new_start + int(self.cached_time * self.video_frame_fps) new_start = 0 if new_start < 0 else new_start new_start = self.video_frame_count if new_start > self.video_frame_count else new_start new_stop = 0 if new_stop < 0 else new_stop new_stop = self.video_frame_count if new_stop > self.video_frame_count else new_stop if new_start != new_stop: logger.debug("Check buffer - buffer needs to load new objects, direction up") self.__bufferObjects(new_start, new_stop) else: logger.debug("Check buffer - status OK") @staticmethod def bufferFinished(): """ Called when buffer thread is finished (closed). """ logger.debug("Buffer thread closed.") @staticmethod def bufferTerminated(): """ Called when buffer thread is terminated (forced to close). """ logger.warning("Buffer thread terminated!")
class SyncThread(QThread): """Sync notes with evernote thread""" force_sync_signal = Signal() sync_state_changed = Signal(int) data_changed = Signal() def __init__(self, app, *args, **kwargs): QThread.__init__(self, *args, **kwargs) self.app = app self.status = STATUS_NONE self.last_sync = datetime.now() self.update_count = 0 self.timer = QTimer() self.timer.timeout.connect(self.sync) self.update_timer() self.wait_condition = QWaitCondition() self.mutex = QMutex() def update_timer(self): self.timer.stop() delay = int(self.app.settings.value('sync_delay') or 0) or DEFAULT_SYNC_DELAY if delay != SYNC_MANUAL: self.timer.start(delay) def run(self): self.init_db() self.init_network() while True: self.mutex.lock() self.wait_condition.wait(self.mutex) self.perform() self.mutex.unlock() time.sleep(1) # prevent cpu eating def init_db(self): self.session = get_db_session() self.sq = self.session.query def init_network(self): while True: try: self.auth_token = get_auth_token() self.note_store = get_note_store(self.auth_token) break except socket.error: time.sleep(30) def force_sync(self): self.timer.stop() self.sync() self.update_timer() @Slot() def sync(self): self.wait_condition.wakeAll() def perform(self): """Perform all sync""" self.status = STATUS_SYNC self.last_sync = datetime.now() self.sync_state_changed.emit(SYNC_STATE_START) if self._need_to_update(): self.need_to_update = True self.all_notes = list(self._iter_all_notes()) try: if self.need_to_update: self.remote_changes() self.local_changes() except Exception, e: # maybe log this self.session.rollback() self.init_db() self.app.log(e) finally:
class manager(QObject): _scanParams = [] _scanRunning = 0 # _storageEnabled = 0 #_folderStorage = None #_fileStorage = None #_storagePath = None _resultsToPrint = [] def __init__(self, theMainWindow, parent=None): global abnormalTermination global scanPath global homeDir global scanReportPath global scanReportFolder global infectionsList global infectedFiles super(manager, self).__init__(parent) # Opening Configuration File if config.debug: self.confileName = os.getcwd() + "/conf/config.ini" else: self.confileName = os.path.expanduser("~") + "/.avgui/config.ini" #self.confileName = os.path.expanduser("~") + "/.avgui/config.ini" self.configparser = SafeConfigParser() self.configparser.read(self.confileName) self.mutexPrint = QMutex() self._theMainWindow = theMainWindow self.setupConnections(self._theMainWindow) self.theTimer = QTimer() abnormalTermination = 0 self.scanReportStorageEnabled = 0 scanReportPath = None scanReportFolder = None scanPath = None homeDir = expanduser("~") def displayAVGinfo(self): self._theMainWindow.theavgavInfo.show() def displayAVGuiinfo(self): self._theMainWindow.theavguiInfo .show() def setupConnections(self, theMainWindow): # Main Window self._theMainWindow.btnHistory.clicked.connect(self.emitHistory) self._theMainWindow.btnScan.clicked.connect(self.emitScan) self._theMainWindow.btnUpdate.clicked.connect(self.emitUpdate) self._theMainWindow.sigMainSent.connect(self.handleMainWindowEmits) self._theMainWindow.btnStatus.clicked.connect(self.showStatus) self._theMainWindow.comLangsel.currentIndexChanged.connect(self.setLanguage) self._theMainWindow.action_AVG.triggered.connect(self.displayAVGinfo) self._theMainWindow.action_AVGui.triggered.connect(self.displayAVGuiinfo) # Scan Dialog self._theMainWindow.theScan.btnSelectF.clicked.connect(self.selectWhatToScan) self._theMainWindow.theScan.btnBeginScan.clicked.connect(self.beginScan) self._theMainWindow.theScan.btnScanSettings.clicked.connect(self.setScanSettings) self._theMainWindow.theScan.sigCleanScanDialog.connect(self.cleanUpScanSettings) # Scan Select Dialog # self._theMainWindow.theScan.theSelect.sigSelectType.connect(self.handleSelectScanTypeEmits) self._theMainWindow.theScan.theSelect.radioFile.clicked.connect(self.emitFileSelected) self._theMainWindow.theScan.theSelect.radioFolder.clicked.connect(self.emitFolderSelected) # Scan Settings Dialog self._theMainWindow.theScan.theScanSettings.btnOK.clicked.connect(self.getScanSettings) self._theMainWindow.theScan.theScanSettings.chkbFileStore.stateChanged.connect(self.enableStorage) self._theMainWindow.theScan.theScanSettings.btnSelectFolder.clicked.connect(self.selectScanReportFolder) # Scan Progress Dialog self._theMainWindow.theScan.theScanProgress.btnExitScan.clicked.connect(self.terminateScan) self._theMainWindow.theScan.theScanProgress.sigCloseEvent.connect(self.terminateScan) # Scan History Dialog self._theMainWindow.theHistory.btnExecute.clicked.connect(self.execSearch) self._theMainWindow.theHistory.btnHistoryDB.clicked.connect(self.retrieveDBHistory) self._theMainWindow.theHistory.theResults.btnExtractTxt.clicked.connect(self.extractToText) self._theMainWindow.theHistory.theResults.sigCloseEvent.connect(self.clearResults) # Update Dialog self._theMainWindow.theUpdate.btnUpdateCheck.clicked.connect(self.checkUpdates) self._theMainWindow.theUpdate.btnUpdate.clicked.connect(self.performUpdate) self._theMainWindow.theUpdate.btnUpdateSet.clicked.connect(self.setUpdateSettings) self._theMainWindow.theUpdate.theUpdateSettings.btnOK.clicked.connect(self.setUpdateSettings) self._theMainWindow.theUpdate.theUpdateSettings.btnCancel.clicked.connect(self.setUpdateSettings) def emitScan(self): self._theMainWindow.sigMainSent.emit("SCAN") def emitHistory(self): self._theMainWindow.sigMainSent.emit("HISTORY") def emitUpdate(self): self._theMainWindow.sigMainSent.emit("UPDATE") def handleMainWindowEmits(self, param): #print(param) if param == "SCAN": self._theMainWindow.theScan.clear() self._theMainWindow.theScan.theSelect.clear() self._theMainWindow.theScan.show() elif param == "UPDATE": self._theMainWindow.theUpdate.show() elif param == "HISTORY": self._theMainWindow.theHistory.show() # populating combo boxes availMal = utilities.populateMalware() modelMalware = utilities.malwareModel(availMal) self._theMainWindow.theHistory.comMalware.setModel(modelMalware) availDBs = utilities.populateVirusDBs() modelDBs = utilities.virusDBModel(availDBs) #populating date fields self.curDateList = date.today().isoformat().split('-') self.curQDate = QDate(int(self.curDateList[0]), int(self.curDateList[1]), int(self.curDateList[2])) self._theMainWindow.theHistory.comStartDate.setDate(self.curQDate ) self._theMainWindow.theHistory.comEndDate.setDate(self.curQDate ) self._theMainWindow.theHistory.comDatabase.setModel(modelDBs) else: QMessageBox.critical(None, langmodule.attention, langmodule.applicationError, QMessageBox.Ok | QMessageBox.Default, QMessageBox.NoButton) def selectWhatToScan(self): self._theMainWindow.theScan.theSelect.clear() self._theMainWindow.theScan.theSelect.show() def emitFileSelected(self): global scanPath options = QFileDialog.DontResolveSymlinks scanPath = QFileDialog.getOpenFileName(self._theMainWindow.theScan.theSelect, langmodule.chooseFileToScan, '/home', 'All files (*.*)', "", options)[0] print("scan path is: " + scanPath) if scanPath == "": scanPath=None return else: self._theMainWindow.theScan.infoLabel.setText(langmodule.scanFileTitle) self._theMainWindow.theScan.fileToScanLabel.setText(str(scanPath)) self._theMainWindow.theScan.theSelect.close() def emitFolderSelected(self): global scanPath options = QFileDialog.DontResolveSymlinks | QFileDialog.ShowDirsOnly scanPath = QFileDialog.getExistingDirectory(self._theMainWindow.theScan.theSelect, langmodule.chooseFolderToScan, '/home', options) print("scan path is: " + scanPath) if scanPath == "": scanPath=None return else: self._theMainWindow.theScan.infoLabel.setText(langmodule.scanFolderTitle) self._theMainWindow.theScan.fileToScanLabel.setText(str(scanPath)) self._theMainWindow.theScan.theSelect.close() ############################################ Setting Language ############################################################# def setLanguage(self): oldLang = self.configparser.get('Language', 'lang') print("oldLang: " + oldLang) newLang = self._theMainWindow.comLangsel.currentText() self.configparser.set('Language', 'lang', newLang) print("newLang: " + newLang) if oldLang != newLang: QMessageBox.information(None, langmodule.attention, langmodule.needRestartTitle, QMessageBox.Ok | QMessageBox.Default, QMessageBox.NoButton) self.configparser.set('Language', 'lang', newLang) with open(self.confileName, 'r+') as confile: self.configparser.write(confile) ################################### Methods related to setting the Scan Settings ########################################## def setScanSettings(self): self._theMainWindow.theScan.theScanSettings.show() def getScanSettings(self): global scanParameters global scanReportFolder global scanReportFile global scanReportPath #global scanReportStorageEnabled closeWidget = True #print("Setting up scan settings...") scanParams = [] # scan for specific file extensions if self._theMainWindow.theScan.theScanSettings.chkbIfType.isChecked(): #print("Getting file extension") filesToScan = self._theMainWindow.theScan.theScanSettings.textIfType.toPlainText() print("files to scan BEFORE: " + str(filesToScan)) if (utilities.checkIsExtension(filesToScan)): scanParams.append("--ext") scanParams.append(filesToScan) #print("files to scan AFTER: " + str(filesToScan)) #print("Just after setting file extensions: " + str(scanParams)) fileStorageOK = self.validateFileStorage() if (self.scanReportStorageEnabled == 1) & (fileStorageOK): scanParams.append("--report") scanParams.append(scanReportPath) #print(scanParams) if self._theMainWindow.theScan.theScanSettings.chkbBackUpFiles.isChecked(): scanParams.append("--vv-backup") if self._theMainWindow.theScan.theScanSettings.chkbArchive.isChecked(): scanParams.append("--arc") if self._theMainWindow.theScan.theScanSettings.chkbBootSec.isChecked(): scanParams.append("--boot-sector") if self._theMainWindow.theScan.theScanSettings.chkbCookies.isChecked(): scanParams.append("--coo") if self._theMainWindow.theScan.theScanSettings.chkbMultimedia.isChecked(): scanParams.append("--media") # check which radio button is set # and create parameter if self._theMainWindow.theScan.theScanSettings.radioDelete.isChecked(): scanParams.append("--delete") elif self._theMainWindow.theScan.theScanSettings.radioHeal.isChecked(): scanParams.append("--heal") elif self._theMainWindow.theScan.theScanSettings.radioVault.isChecked(): scanParams.append("--vv-move") #print("Inside function the scanParams are: " + str(scanParams)) scanParameters = scanParams #print("Just set manager._scanParams: " + str(manager._scanParams)) #scanParameters = scanParams print("Just set scanParameters: " + str(scanParameters)) #print("Clicked OK_1: " + "self.validateFileStorage: " + str(self.validateFileStorage()) + " scanReportStorageEnabled: " + str(self.scanReportStorageEnabled) ) if self.scanReportStorageEnabled == 1: print("Level 1") if fileStorageOK: print("Level 2") self._theMainWindow.theScan.theScanSettings.close() print("just closed") elif self.scanReportStorageEnabled == 0: self._theMainWindow.theScan.theScanSettings.close() #print("Clicked OK_2: " + "self.validateFileStorage: " + str(self.validateFileStorage()) + " scanReportStorageEnabled: " + str(self.scanReportStorageEnabled) ) #self._theMainWindow.theScan.theScanSettings.close() def selectScanReportFolder(self): global scanReportFolder #global scanReportStorageEnabled result = False #if self._theMainWindow.theScan.theScanSettings.chkbFileStore.isChecked(): if self.scanReportStorageEnabled == 1: reportDir = "" while not result: self._theMainWindow.theScan.theScanSettings.theStoreFileDialog.ShowDirsOnly self._theMainWindow.theScan.theSelect.selectDialog.setFileMode(QFileDialog.Directory) reportDir = self._theMainWindow.theScan.theSelect.selectDialog.getExistingDirectory() if reportDir == "": return result = utilities.checkFolderPermissions(reportDir) if not result: QMessageBox.information(None, langmodule.attention, langmodule.noAccessRights, QMessageBox.Ok | QMessageBox.Default, QMessageBox.NoButton) else: scanReportFolder = reportDir self._theMainWindow.theScan.theScanSettings.btnSelectFolder.setText(scanReportFolder) def validateFileStorage(self): global scanReportFolder global scanReportPath storagePathOK = True if (self._theMainWindow.theScan.theScanSettings.textStoreFile.toPlainText() == "") & (self.scanReportStorageEnabled == 1): print("here...") QMessageBox.information(None, langmodule.attention, langmodule.noFileNameProvided, QMessageBox.Ok | QMessageBox.Default, QMessageBox.NoButton) storagePathOK = False elif (self._theMainWindow.theScan.theScanSettings.textStoreFile.toPlainText() != "") & (self.scanReportStorageEnabled == 1): print("scanReportFolder is: " + str(scanReportFolder)) scanReportFile = self._theMainWindow.theScan.theScanSettings.textStoreFile.toPlainText() if scanReportFolder != None: scanReportPath = scanReportFolder + "/" + scanReportFile else: scanReportPath = scanReportFile storagePathOK = True return storagePathOK #print("scanReportPath is: " + str(scanReportPath)) return storagePathOK def enableStorage(self): #global scanReportStorageEnabled if self.scanReportStorageEnabled == 0: self._theMainWindow.theScan.theScanSettings.btnSelectFolder.setEnabled(True) self._theMainWindow.theScan.theScanSettings.textStoreFile.setEnabled(True) #print("setting to 1") #print("sender: " + str(self.sender().objectName())) self.scanReportStorageEnabled = 1 else: self._theMainWindow.theScan.theScanSettings.btnSelectFolder.setDisabled(True) self._theMainWindow.theScan.theScanSettings.textStoreFile.setDisabled(True) #print("Setting to 0") #print("sender: " + str(self.sender().objectName())) self.scanReportStorageEnabled = 0 ################################################################################ ############################### DB Updates History ############################# ################################################################################ def retrieveDBHistory(self): self.thedbHistoryWorker = utilities.dbHistoryWorker() #self.thedbHistoryWorker.finished.connect(self.showdbHistoryResults) self.thedbHistoryWorker.sigHistoryRetrieved.connect(self.showdbHistoryResults) self.thedbHistoryWorker.start() def showdbHistoryResults(self, theResults): if theResults: print("theResults = " + str(theResults)) modelHisDBRes = utilities.dbHistoryTableModel(theResults) self._theMainWindow.theHistory.theHistdbResults.tblViewHistoryDB.setModel(modelHisDBRes) self._theMainWindow.theHistory.theHistdbResults.tblViewHistoryDB.resizeColumnsToContents() self._theMainWindow.theHistory.theHistdbResults.show() self.thedbHistoryWorker.exit() else: QMessageBox.information(None, langmodule.noResults, langmodule.noUpdatesYes, QMessageBox.Ok | QMessageBox.Default, QMessageBox.NoButton) ################################################################################ ################################### SCAN ####################################### ################################################################################ def beginScan(self): global infectionsList global infectedFiles global infectionsList self._theMainWindow.theScan.theScanProgress.theShowScanResults.tableWidget.clear() self.isCleanScan = False global scanPath global abnormalTermination global scanParameters self.getScanSettings() infectedFiles = [] infectionsList = [] abnormalTermination = 0 self._theMainWindow.theScan.theScanProgress.btnExitScan.setText(langmodule.terminateScan) #print("Scan path is: " + str(scanPath)) if scanPath == None: QMessageBox.information(None, langmodule.attention, langmodule.noFilesChosen, QMessageBox.Ok | QMessageBox.Default, QMessageBox.NoButton) return -1 # preparing to start scan in a new thread self.theScanWorker = utilities.scanWorker(scanPath, scanParameters) #self.theScanWorker.finished.connect(self.onScanFinish) self.theScanWorker.sigWriteScan.connect(self.printToWidget) self.theScanWorker.sigScanTerminated.connect(self.onScanFinish) self._theMainWindow.theScan.theScanProgress.textScanProg.clear() self._theMainWindow.theScan.theScanProgress.show() self.theScanWorker.start() #preparing to store scan event in a new thread self.theSQLITEWorker = utilities.sqliteWorker() self.theSQLITEWorker.finished.connect(self.onSQLiteFinish) def onSQLiteFinish(self): pass #print("Data Insertion Completed!!!!") def printToWidget(self, linetoappend): self.mutexPrint.lock() global infectionsList global infectedFiles lineList = (linetoappend.split()) if ("Trojan" in lineList): position = lineList.index('Trojan') infectedFiles.append(lineList[position - 1]) infectionsList.append(lineList[position +2]) if ("Virus" in lineList): if ("identified" in lineList): position = lineList.index('Virus') infectedFiles.append(lineList[position - 1]) infectionsList.append(lineList[position +2]) if ("Could" in lineList): position = lineList.index('Could') infectedFiles.append(lineList[position - 1]) infectionsList.append(lineList[position +3]) print("Infected Files: " + str(infectedFiles)) print("List of Infections: " + str(infectionsList)) for i,j in langmodule.translationDict.items(): linetoappend = linetoappend.replace(i,j) # curDateTime = datetime.now().isoformat(' ')[:19] self._theMainWindow.theScan.theScanProgress.textScanProg.appendPlainText(linetoappend) self.mutexPrint.unlock() def terminateScan(self): global infectionsList infectionsList = [] if not self.isCleanScan: global abnormalTermination print("Entering terminateScan from signalManager") if hasattr(self, 'theScanWorker'): if (self.theScanWorker.getScanState() == QProcess.ProcessState.Running) | (self.theScanWorker.getScanState() == QProcess.ProcessState.Starting): print("Seems it was running, calling killScan method") self.theScanWorker.killScan() self.isCleanScan = True self._theMainWindow.theScan.theScanProgress.hide() manager._scanParams = [] def onScanFinish(self, normalTermination): global infectionsList self.theScanWorker.sigWriteScan.disconnect() # infectionsList = [] print("Entering onScanFinish, from signalManager, normalTermination = " + str(normalTermination)) if hasattr(self, 'theScanWorker'): self.theScanWorker.exit() while not self.theScanWorker.wait(): print("Waiting for scan worker to finish") self._theMainWindow.theScan.theScanProgress.btnExitScan.setText(langmodule.btnExitUpdateProgTitle) if hasattr(self, 'theScanWorker'): del self.theScanWorker print("The Scan Worker is being Deleted") else: print("The Scan Worker Was Already Deleted") try: lockerFinish = QMutexLocker(mutexTermination) if normalTermination=="True": if infectionsList: header1 = QTableWidgetItem("Threats") header2 = QTableWidgetItem(("Files")) self._theMainWindow.theScan.theScanProgress.theShowScanResults.tableWidget.setColumnCount(2) self._theMainWindow.theScan.theScanProgress.theShowScanResults.tableWidget.setRowCount(len(infectionsList)) self._theMainWindow.theScan.theScanProgress.theShowScanResults.tableWidget.setHorizontalHeaderItem(0, header1) self._theMainWindow.theScan.theScanProgress.theShowScanResults.tableWidget.setHorizontalHeaderItem(1, header2) self._theMainWindow.theScan.theScanProgress.theShowScanResults.tableWidget.horizontalHeader().setStretchLastSection(True) for i in range(1, len(infectionsList) + 1): newItem0 = QTableWidgetItem(infectionsList[i-1]) newItem1 = QTableWidgetItem(infectedFiles[i-1]) print("line " + str(i) + ": " + newItem0.text()) print("line " + str(i) + ": " + newItem1.text()) self._theMainWindow.theScan.theScanProgress.theShowScanResults.tableWidget.setItem(i-1, 0, newItem0) self._theMainWindow.theScan.theScanProgress.theShowScanResults.tableWidget.setItem(i-1, 1, newItem1) self._theMainWindow.theScan.theScanProgress.theShowScanResults.tableWidget.resizeColumnsToContents() self._theMainWindow.theScan.theScanProgress.theShowScanResults.show() self.theSQLITEWorker.start() except Exception as errmut2: print(str(errmut2)) exit(-1) gc.collect() def cleanUpScanSettings(self): global scanPath print("Running cleanup") scanPath = None manager._scanParams = [] ######################################################## END OF SCAN ############################################### def execSearch(self): flag = 0 if (self._theMainWindow.theHistory.comStartDate.date() > self._theMainWindow.theHistory.comEndDate.date()): QMessageBox.information(None, langmodule.wrongDates1, langmodule.wrongDates2, QMessageBox.Ok | QMessageBox.Default, QMessageBox.NoButton) return dateFrom = self._theMainWindow.theHistory.comStartDate.date().toString('yyyy-MM-dd') dateTo = self._theMainWindow.theHistory.comEndDate.date().toString('yyyy-MM-dd') #dateFrom = self._theMainWindow.theHistory.comStartDate.date().toString('yyyy-MM-dd') + ' 23:59:59' #dateTo = self._theMainWindow.theHistory.comEndDate.date().toString('yyyy-MM-dd') + ' 23:59:59' if dateFrom == dateTo: dateFrom = dateFrom + ' 00:00:00' dateTo = dateTo + ' 23:59:59' malware = self._theMainWindow.theHistory.comMalware.currentText() virusDB = self._theMainWindow.theHistory.comDatabase.currentText() results = utilities.scanSearchQuery(dateFrom, dateTo, malware, virusDB) if not results: QMessageBox.information(None, langmodule.noResults, langmodule.noResultsCriteria, QMessageBox.Ok | QMessageBox.Default, QMessageBox.NoButton) else: if (malware == '') & (virusDB == ''): flag = 0 elif (malware =='') & (virusDB != ''): flag = 1 elif (malware != '') & (virusDB == ''): flag = 2 else: flag = 3 nestedResults = [] for item in results: tempList = [] for i in item: tempList.append(str(i)) nestedResults.append(tempList) manager._resultsToPrint = nestedResults modelResults = utilities.scanResultsTableModel(nestedResults, flag) # print("Nested Results: " + str(nestedResults)) self._theMainWindow.theHistory.theResults.tblVscanResults.setModel(modelResults) #self._theMainWindow.theHistory.theResults.tblVscanResults.resizeColumnsToContents() if flag == 0: for i in range(3): self._theMainWindow.theHistory.theResults.tblVscanResults.setColumnWidth(i, 300) if flag == 2: self._theMainWindow.theHistory.theResults.tblVscanResults.setColumnWidth(0, 170) self._theMainWindow.theHistory.theResults.tblVscanResults.setColumnWidth(1, 180) self._theMainWindow.theHistory.theResults.tblVscanResults.setColumnWidth(2, 200) if flag == 3: self._theMainWindow.theHistory.theResults.tblVscanResults.setColumnWidth(0, 150) self._theMainWindow.theHistory.theResults.tblVscanResults.setColumnWidth(1, 170) self._theMainWindow.theHistory.theResults.tblVscanResults.setColumnWidth(2, 190) self._theMainWindow.theHistory.theResults.tblVscanResults.setColumnWidth(3, 170) #print("flag = " + str(flag)) #qsize = QSize(2000, 2000) #self._theMainWindow.theHistory.theResults.tblVscanResults.resize(qsize) self._theMainWindow.theHistory.theResults.show() def extractToText(self): try: now = datetime.now().isoformat().split('T') filename='scanLog_' + now[0][0:10] + '_' + now[1][0:8] + '.txt' flags = QFileDialog.DontResolveSymlinks | QFileDialog.ShowDirsOnly folder = QFileDialog.getExistingDirectory(self._theMainWindow.theHistory.theResults, langmodule.chooseFolderToStoreText, homeDir, flags) print(filename) print(manager._resultsToPrint) path = folder + '/' + filename with open(path, 'w') as file: file.write(langmodule.userTitle + '\t\t\t' + langmodule.noOfResultsTitle + '\t\t' + langmodule.scanDateTimeTitle + '\n') # linux specific newline - not portable! file.write("----------------------------------------------------------------------------------" + '\n') # linux specific newline - not portable! for inlist in manager._resultsToPrint: file.write(inlist[0] + '\t\t\t') file.write(inlist[1] + '\t\t\t\t\t') file.write(inlist[2] + '\n') # linux specific newline - not portable! file.close() except IOError as error: print(str(error)[0:13]) if "Permission denied" in str(error): QMessageBox.critical(None, langmodule.attention, langmodule.noAccessRightsInFolder, QMessageBox.Ok | QMessageBox.Default, QMessageBox.NoButton) except Exception: QMessageBox.critical(None, langmodule.attention, langmodule.errorStoringFile, QMessageBox.Ok | QMessageBox.Default, QMessageBox.NoButton) def clearResults(self): manager._resultsToPrint = [] #print("Test") ################################################## UPDATES ########################################################### ################################################## Check Updates ##################################################### def checkUpdates(self): self.abnormalTermination = False self.isCleanCheck = False self._theMainWindow.theUpdate.theCheckPanel.txtCheck.clear() self._theMainWindow.theUpdate.theCountDown.countDownLCD.display(30) self.theChecker = utilities.chkUpdateWorker() self.theChecker.sigFailed.connect(self.handleCheckTermination) self.theChecker.sigCheckFinished.connect(self.handleCheckTermination) self.theChecker.started.connect(self.beginDaemonChecker) self._theMainWindow.theUpdate.theCountDown.sigCloseEvent.connect(self.closeCounterWidget) self.theDaemonChecker = utilities.checkDaemonD() self.theDaemonChecker.sigDstarted.connect(self.startTimer) self._theMainWindow.theUpdate.theCountDown.show() self.theChecker.start() while not self.theChecker.isRunning(): print("Waiting for checker to start") def beginDaemonChecker(self): #print("beginning daemon checker") self.theDaemonChecker.start() while not self.theDaemonChecker.isRunning(): print("Waiting for daemon checker to start") def startTimer(self, result): try: self.theTimer.timeout.disconnect() except Exception as err: print("Error disconnecting timeout signal from timer") if result == 1: # process failed to start QMessageBox.critical(None, langmodule.attention, langmodule.restartUpdate, QMessageBox.Ok | QMessageBox.Default, QMessageBox.NoButton) self._theMainWindow.theUpdate.theCountDown.close() if result == 2: self._theMainWindow.theUpdate.theCountDown.close() return # user cancelled the operation else: # normal process initiation #print("starting timer...") self.theTimer.timeout.connect(self.decrementLCD) self.theTimer.start(1000) def decrementLCD(self): currentValue = self._theMainWindow.theUpdate.theCountDown.countDownLCD.intValue() #print("decrementing: current value is: " + str(currentValue)) self._theMainWindow.theUpdate.theCountDown.countDownLCD.display(currentValue - 1) def closeCounterWidget(self): if not self.isCleanCheck: print("In Close Counter Widget") if hasattr(self, 'theChecker'): print("it has!") self.theChecker.cleanUp() self.isCleanCheck = True else: pass def handleCheckTermination(self, abnormalTermination, theOutput): self.abnormalTermination = abnormalTermination if self._theMainWindow.theUpdate.theCountDown.isVisible(): print("was visible") self._theMainWindow.theUpdate.theCountDown.close() print("inside with abnormalTermination: " + str(self.abnormalTermination)) self.theTimer.stop() if hasattr(self, 'theChecker'): if self.theChecker.isRunning(): self.theChecker.exit() if hasattr(self, 'theDaemonChecker'): if self.theDaemonChecker.isRunning(): self.theDaemonChecker.exit() while not self.theDaemonChecker.wait(): print("Waiting for daemon checker to exit") if hasattr(self, 'theDaemonChecker'): del self.theDaemonChecker if hasattr(self, 'theChecker'): #self.theChecker.exit() print("Trying to delete the checker") del self.theChecker gc.collect() #if hasattr(self, 'theChecker'): # print("Failed to delete the checker") #self._theMainWindow.theUpdate.theCountDown.close() if not self.abnormalTermination: self._theMainWindow.theUpdate.theCheckPanel.txtCheck.appendPlainText(theOutput) self._theMainWindow.theUpdate.theCheckPanel.show() gc.collect() ############################################### Run Update ####################################################### def performUpdate(self): self.isClean = False self._theMainWindow.theUpdate.theUpdateProgress.sigCloseEvent.connect(self.closeUpdateProgress) self.theUpdater = utilities.updateWorker() self.theUpdater.sigWriteUpdate.connect(self.printToUpdateWidget) self.theUpdater.sigUpdateTerminated.connect(self.onUpdateFinish) self.theUpdater.started.connect(self.startChecker) self.theUpdateChecker = utilities.checkDaemonD() self.theUpdateChecker.sigDstarted.connect(self.showProgress) self.theUpdater.start() def closeUpdateProgress(self): print("is clean: " + str(self.isClean)) if self.isClean: pass else: if hasattr(self, "theUpdater"): self.theUpdater.cleanUp() self.isClean = True def startChecker(self): self.theUpdateChecker.start() while not self.theUpdateChecker.isRunning(): print("Waiting for checker to start") def showProgress(self, result): print("result is: " + str(result)) self._theMainWindow.theUpdate.theUpdateProgress.textUpdateProg.clear() if result == 0: self._theMainWindow.theUpdate.theUpdateProgress.show() self._theMainWindow.theUpdate.theUpdateProgress.btnExit.setEnabled(False) else: pass def printToUpdateWidget(self, theInput): self._theMainWindow.theUpdate.theUpdateProgress.textUpdateProg.appendPlainText(theInput) def onUpdateFinish(self, exitCode): print("EXIT CODE IS: " + str(exitCode)) if exitCode == 1: # process did not start QMessageBox.critical(None, langmodule.attention, langmodule.restartUpdate, QMessageBox.Ok | QMessageBox.Default, QMessageBox.NoButton) if hasattr(self, 'theUpdateChecker'): self.theUpdateChecker.exit() if hasattr(self, 'theUpdater'): self.theUpdater.exit() elif exitCode == 0 | exitCode == 255: # nornal process termination # print(str(self.theUpdater.isRunning())) # signals need to be disconnected in both cases self.theUpdater.started.disconnect() self.theUpdater.sigUpdateTerminated.disconnect() self.theUpdater.sigWriteUpdate.disconnect() self.theUpdateChecker.sigDstarted.disconnect() if exitCode == 0: self._theMainWindow.theUpdate.theUpdateProgress.btnExit.setEnabled(True) if exitCode == 299: # abnormalTermination if self._theMainWindow.theUpdate.theUpdateProgress.isVisible(): self._theMainWindow.theUpdate.theUpdateProgress.hide ### cleanup code, always runs ### if hasattr(self, 'theUpdateChecker'): print("here 1") self.theUpdateChecker.exit() while self.theUpdateChecker.isRunning(): print("here 2") self.theUpdateChecker.exit() QApplication.processEvents() if hasattr(self, 'theUpdateChecker'): del self.theUpdateChecker if hasattr(self, 'theUpdater'): while self.theUpdater.isRunning(): print("now waiting updater...") self.theUpdater.exit() QApplication.processEvents() if hasattr(self, 'theUpdater'): print("trying to delete the updater") del self.theUpdater #if self._theMainWindow.theUpdate.theUpdateProgress.isVisible(): #print("set it") gc.collect() ###################################################### Update Settings ############################################## #@QtCore.Slot() def setUpdateSettings(self): self._theMainWindow.theUpdate.theUpdateSettings.cmbBoxProxyMode.currentIndexChanged.connect(self.updateProxyModeSettings) self._theMainWindow.theUpdate.theUpdateSettings.chkUseLogin.stateChanged.connect(self.updateProxyModeSettings) self._theMainWindow.theUpdate.theUpdateSettings.cmbBoxProxyAuthType.currentIndexChanged.connect(self.updateProxyModeSettings) if self.sender().objectName() == "btnUpdateSet": self.getSettings() print("getting settings") if self._theMainWindow.theUpdate.theUpdateSettings.cmbBoxProxyMode.currentIndex() == 0: self._theMainWindow.theUpdate.theUpdateSettings.leditProxyName.setEnabled(False) self._theMainWindow.theUpdate.theUpdateSettings.leditProxyPort.setEnabled(False) if (self._theMainWindow.theUpdate.theUpdateSettings.chkUseLogin.isEnabled()): self._theMainWindow.theUpdate.theUpdateSettings.chkUseLogin.setEnabled(False) self._theMainWindow.theUpdate.theUpdateSettings.cmbBoxProxyAuthType.setEnabled(False) self._theMainWindow.theUpdate.theUpdateSettings.leditProxyUsername.setEnabled(False) self._theMainWindow.theUpdate.theUpdateSettings.leditProxyPass.setEnabled(False) self._theMainWindow.theUpdate.theUpdateSettings.show() elif self.sender().objectName() == "btnOK": try: print("test") self.setSettings() self._theMainWindow.theUpdate.theUpdateSettings.close() except Exception as err: raise err elif self.sender().objectName() == "btnCancel": self._theMainWindow.theUpdate.theUpdateSettings.close() def updateProxyModeSettings(self): if (str(self.sender().objectName())) == "cmbBoxProxyMode": print("sender was cmbBoxProxyMode") if self._theMainWindow.theUpdate.theUpdateSettings.cmbBoxProxyMode.currentIndex() == 0: self._theMainWindow.theUpdate.theUpdateSettings.leditProxyName.setEnabled(False) self._theMainWindow.theUpdate.theUpdateSettings.leditProxyPort.setEnabled(False) if (self._theMainWindow.theUpdate.theUpdateSettings.chkUseLogin.isEnabled()): self._theMainWindow.theUpdate.theUpdateSettings.chkUseLogin.setEnabled(False) self._theMainWindow.theUpdate.theUpdateSettings.cmbBoxProxyAuthType.setEnabled(False) self._theMainWindow.theUpdate.theUpdateSettings.leditProxyUsername.setEnabled(False) self._theMainWindow.theUpdate.theUpdateSettings.leditProxyPass.setEnabled(False) else: self._theMainWindow.theUpdate.theUpdateSettings.leditProxyName.setEnabled(True) self._theMainWindow.theUpdate.theUpdateSettings.leditProxyPort.setEnabled(True) self._theMainWindow.theUpdate.theUpdateSettings.chkUseLogin.setEnabled(True) if self._theMainWindow.theUpdate.theUpdateSettings.chkUseLogin.isChecked(): self._theMainWindow.theUpdate.theUpdateSettings.cmbBoxProxyAuthType.setEnabled(True) self._theMainWindow.theUpdate.theUpdateSettings.leditProxyUsername.setEnabled(True) self._theMainWindow.theUpdate.theUpdateSettings.leditProxyPass.setEnabled(True) elif (str(self.sender().objectName())) == "chkUseLogin": if self._theMainWindow.theUpdate.theUpdateSettings.chkUseLogin.isChecked(): self._theMainWindow.theUpdate.theUpdateSettings.cmbBoxProxyAuthType.setEnabled(True) self._theMainWindow.theUpdate.theUpdateSettings.leditProxyUsername.setEnabled(True) self._theMainWindow.theUpdate.theUpdateSettings.leditProxyPass.setEnabled(True) else: self._theMainWindow.theUpdate.theUpdateSettings.cmbBoxProxyAuthType.setEnabled(False) self._theMainWindow.theUpdate.theUpdateSettings.leditProxyUsername.setEnabled(False) self._theMainWindow.theUpdate.theUpdateSettings.leditProxyPass.setEnabled(False) def showStatus(self): # !!!! NOT PORTABLE !!!! # statusList = subprocess.check_output(["avgctl", "--stat-all"]).decode("utf").split('\n') avgVersion = statusList[5].split()[-1] self._theMainWindow.theCurrentStatus.lblAVGtitle.setStyleSheet("QLabel { font-weight : bold; }"); self._theMainWindow.theCurrentStatus.lblAVGvalue.setText(avgVersion) if ("-" not in statusList[8]): # checking if at least one update has taken place lastUpdate = statusList[8].split()[4] + "/" + statusList[8].split()[5] + "/" + statusList[8].split()[6] + ", " + statusList[8].split()[7] self._theMainWindow.theCurrentStatus.lblLastUpdateTitle.setStyleSheet("QLabel { font-weight : bold; }"); self._theMainWindow.theCurrentStatus.lblLastUpdateValue.setText(lastUpdate) licence = statusList[11].split()[-1] licenceNo = statusList[12].split()[-1] self._theMainWindow.theCurrentStatus.lblLicenceTitle.setStyleSheet("QLabel { font-weight : bold; }"); self._theMainWindow.theCurrentStatus.lblLicenceValue.setText(licence + " / " + licenceNo) aviVersion = statusList[45].split()[-1] self._theMainWindow.theCurrentStatus.lblDatabaseTitle.setStyleSheet("QLabel { font-weight : bold; }"); self._theMainWindow.theCurrentStatus.lblDatabaseValue.setText(aviVersion) aviDate = statusList[46].split()[6] + "/" + statusList[46].split()[7] + "/" + statusList[46].split()[8] + ", " + statusList[46].split()[9] self._theMainWindow.theCurrentStatus.lblDBDateTitle.setStyleSheet("QLabel { font-weight : bold; }"); self._theMainWindow.theCurrentStatus.lblDBDateValue.setText(aviDate) oadStatus1 = statusList[21].split('\t')[2] self._theMainWindow.theCurrentStatus.lblOADTitle.setStyleSheet("QLabel { font-weight : bold; }"); if oadStatus1 == "running": self._theMainWindow.theCurrentStatus.lblOADValue.setStyleSheet("QLabel { color : green; }"); oadStatus = langmodule.genericON # perhaps add background color else: self._theMainWindow.theCurrentStatus.lblOADValue.setStyleSheet("QLabel { color : red; }"); oadStatus = langmodule.genericOFF self._theMainWindow.theCurrentStatus.lblOADValue.setText(oadStatus) schedStatus1 = statusList[22].split('\t')[2] self._theMainWindow.theCurrentStatus.lblSchedTitle.setStyleSheet("QLabel { font-weight : bold; }"); if schedStatus1 == "running": self._theMainWindow.theCurrentStatus.lblSchedValue.setStyleSheet("QLabel { color : green; }"); schedStatus = langmodule.genericON # perhaps add background color else: self._theMainWindow.theCurrentStatus.lblSchedValue.setStyleSheet("QLabel { color : red; }"); schedStatus = langmodule.genericOFF self._theMainWindow.theCurrentStatus.lblSchedValue.setText(schedStatus) if ("-" not in statusList[29]): # checking if at least one virus update has taken place lastVirUpdate = statusList[29].split()[3] + "/" + statusList[29].split()[4] + "/" + statusList[29].split()[5] + ", " + statusList[29].split()[6] self._theMainWindow.theCurrentStatus.lblNextVUpdateTitle.setStyleSheet("QLabel { font-weight : bold; }"); self._theMainWindow.theCurrentStatus.lblNextVUpdateValue.setText(lastVirUpdate) else: self._theMainWindow.theCurrentStatus.lblNextVUpdateValue.setText(" ") if ("-" not in statusList[30]): # checking if at least one program update has taken place lastProgUpdate = statusList[30].split()[3] + "/" + statusList[30].split()[4] + "/" + statusList[30].split()[5] + ", " + statusList[30].split()[6] self._theMainWindow.theCurrentStatus.lblNextPUpdateTitle.setStyleSheet("QLabel { font-weight : bold; }"); self._theMainWindow.theCurrentStatus.lblNextPUpdateValue.setText(lastProgUpdate) else: self._theMainWindow.theCurrentStatus.lblNextPUpdateTitle.setStyleSheet("QLabel { font-weight : bold; }"); self._theMainWindow.theCurrentStatus.lblNextPUpdateValue.setText(" ") self._theMainWindow.theCurrentStatus.show() def getSettings(self): # Automatic Program Update self.autoProgUpdateOut = subprocess.check_output(["avgcfgctl", "UpdateProgram.sched.Task.Disabled"]) self.tmp_autoProgUpdate = self.autoProgUpdateOut.decode("utf").rstrip().split("=",1)[-1].capitalize() if self.tmp_autoProgUpdate == "False": self.autoProgUpdate = True else: self.autoProgUpdate = False self._theMainWindow.theUpdate.theUpdateSettings.chkAutoUpdateProg.setChecked(self.autoProgUpdate) # Automatic Virus Database Update self.autoVirUpdateOut = subprocess.check_output(["avgcfgctl", "UpdateVir.sched.Task.Disabled"]) self.tmp_autoVirUpdate = self.autoVirUpdateOut.decode("utf").rstrip().split("=",1)[-1].capitalize() if self.tmp_autoVirUpdate == "False": self.autoVirUpdate = True else: self.autoVirUpdate = False self._theMainWindow.theUpdate.theUpdateSettings.chkAutoUpdateVir.setChecked(self.autoVirUpdate) # Minimum Speed self.minSpeedOut = subprocess.check_output(["avgcfgctl", "Default.update.Inet.disconnect_speed_limit"]) self.minSpeed = int(str(self.minSpeedOut.decode("utf")).split("=",1)[-1]) self._theMainWindow.theUpdate.theUpdateSettings.leditMinSpeed.setText(str(self.minSpeed)) # Maximum Time self.maxTimeOut = subprocess.check_output(["avgcfgctl", "Default.update.Inet.disconnect_time_limit"]) self.maxTime = int(str(self.maxTimeOut.decode("utf")).split("=",1)[-1]) self._theMainWindow.theUpdate.theUpdateSettings.leditMaxTime.setText(str(self.maxTime)) # Proxy Name self.proxyNameOut = subprocess.check_output(["avgcfgctl", "Default.update.Options.Proxy.Server"]) self.proxyName = str(self.proxyNameOut.decode("utf")).split("=",1)[-1] self._theMainWindow.theUpdate.theUpdateSettings.leditProxyName.setText(str(self.proxyName)) # Proxy Username self.proxyUsernameOut = subprocess.check_output(["avgcfgctl", "Default.update.Options.Proxy.Login"]) self.proxyUsername = str(self.proxyUsernameOut.decode("utf")).split("=",1)[-1] self._theMainWindow.theUpdate.theUpdateSettings.leditProxyUsername.setText(str(self.proxyUsername)) # Proxy Password self.proxyPassOut = subprocess.check_output(["avgcfgctl", "Default.update.Options.Proxy.Password"]) self.proxyPass = str(self.proxyPassOut.decode("utf")).split("=",1)[-1] self._theMainWindow.theUpdate.theUpdateSettings.leditProxyPass.setText(str(self.proxyPass)) # Proxy Port self.proxyPortOut = subprocess.check_output(["avgcfgctl", "Default.update.Options.Proxy.Port"]) self.proxyPort = int(str(self.proxyPortOut.decode("utf")).split("=",1)[-1]) self._theMainWindow.theUpdate.theUpdateSettings.leditProxyPort.setText(str(self.proxyPort)) # Proxy Set up self.proxyModeOut = subprocess.check_output(["avgcfgctl", "Default.update.Options.Proxy.Mode"]) self.proxyMode = int(str(self.proxyModeOut.decode("utf")).split("=",1)[-1]) self._theMainWindow.theUpdate.theUpdateSettings.cmbBoxProxyMode.setCurrentIndex(self.proxyMode) # Proxy Auth Type self.proxyAuthTypeOut = subprocess.check_output(["avgcfgctl", "Default.update.Options.Proxy.AuthenticationType"]) self.proxyAuthType = int(str(self.proxyModeOut.decode("utf")).split("=",1)[-1]) self._theMainWindow.theUpdate.theUpdateSettings.cmbBoxProxyAuthType.setCurrentIndex(self.proxyAuthType) # Proxy Log In Required self.proxyLoginRequiredOut = subprocess.check_output(["avgcfgctl", "Default.update.Options.Proxy.UseLogin"]) self.tmp_proxyLoginRequired = self.proxyLoginRequiredOut.decode("utf").rstrip().split("=",1)[-1].capitalize() if self.tmp_proxyLoginRequired == 'False': self.proxyLoginRequired = False else: self.proxyLoginRequired = True self._theMainWindow.theUpdate.theUpdateSettings.chkUseLogin.setChecked(self.proxyLoginRequired) def setSettings(self): self.command = "" # Automatic Program Update self.newAutoProgUpdate = self._theMainWindow.theUpdate.theUpdateSettings.chkAutoUpdateProg.isChecked() if (self.newAutoProgUpdate != self.autoProgUpdate): self.command = self.command + " UpdateProgram.sched.Task.Disabled=" + str(not self.newAutoProgUpdate) # Automatic Virus Database Update self.newAutoVirUpdate = self._theMainWindow.theUpdate.theUpdateSettings.chkAutoUpdateVir.isChecked() if (self.newAutoVirUpdate != self.autoVirUpdate): self.command = self.command + " UpdateVir.sched.Task.Disabled=" + str(not self.newAutoVirUpdate) # Minimum Speed self.newMinSpeed = int(self._theMainWindow.theUpdate.theUpdateSettings.leditMinSpeed.text()) if (self.newMinSpeed != self.minSpeed): self.command = self.command + "Default.update.Inet.disconnect_speed_limit=" + str(self.newMinSpeed) # Maximum Time self.newMaxTime = int(self._theMainWindow.theUpdate.theUpdateSettings.leditMaxTime.text()) if (self.newMaxTime != self.maxTime): self.command = self.command + " Default.update.Inet.disconnect_time_limit=" + str(self.newMaxTime) # Proxy Name self.newProxyName = self._theMainWindow.theUpdate.theUpdateSettings.leditProxyName.text() if (self.newProxyName != self.proxyName): self.command = self.command + " Default.update.Options.Proxy.Server="+self.newProxyName.replace(" ", "") # Proxy Username self.newProxyUsername = self._theMainWindow.theUpdate.theUpdateSettings.leditProxyUsername.text() if (self.newProxyUsername != self.proxyUsername): self.command = self.command + " Default.update.Options.Proxy.Login="******" Default.update.Options.Proxy.Password="******" Default.update.Options.Proxy.Port=" + str(self.newProxyPort) # Proxy Set up self.newProxyMode = int(self._theMainWindow.theUpdate.theUpdateSettings.cmbBoxProxyMode.currentIndex()) if (self.newProxyMode != self.proxyMode): self.command = self.command + " Default.update.Options.Proxy.Mode=" + str(self.newProxyMode) # Proxy Auth Type self.newProxyAuthType = int(self._theMainWindow.theUpdate.theUpdateSettings.cmbBoxProxyAuthType.currentIndex()) if (self.newProxyAuthType != self.proxyAuthType): self.command = self.command + " Default.update.Options.Proxy.AuthenticationType=" + str(self.newProxyAuthType) # Proxy Log in Required self.newProxyLoginRequired = self._theMainWindow.theUpdate.theUpdateSettings.chkUseLogin.isChecked() print(self.newProxyLoginRequired) print(self.proxyLoginRequired) if (self.newProxyLoginRequired != self.proxyLoginRequired): self.command = self.command + " Default.update.Options.Proxy.UseLogin="******"command is: " + self.command) self.command = " ".join(self.command.split()) print("new command is: " + self.command) if self.command != "": try: subprocess.call(["gksu", "avgcfgctl -w " + self.command]) except Exception as err: print("Error setting new update settings") raise err
class SyncThread(QThread, SyncAgent): """Sync notes with evernote thread""" force_sync_signal = Signal() sync_state_changed = Signal(int) data_changed = Signal() def __init__(self, *args, **kwargs): QThread.__init__(self, *args, **kwargs) self.app = AppClass.instance() self.status = STATUS_NONE self.last_sync = datetime.now() self.update_count = 0 self.timer = QTimer() self.timer.timeout.connect(self.sync) self.update_timer() self.wait_condition = QWaitCondition() self.mutex = QMutex() def update_timer(self): self.timer.stop() delay = int(self.app.settings.value('sync_delay') or 0) or DEFAULT_SYNC_DELAY if delay != SYNC_MANUAL: self.timer.start(delay) def run(self): self.init_db() self.init_network() while True: self.mutex.lock() self.wait_condition.wait(self.mutex) self.perform() self.mutex.unlock() time.sleep(1) # prevent cpu eating def init_db(self): self.session = get_db_session() self.sq = self.session.query def init_network(self): while True: try: self.auth_token = get_auth_token() self.note_store = get_note_store(self.auth_token) break except socket.error: time.sleep(30) def force_sync(self): self.timer.stop() self.sync() self.update_timer() @Slot() def sync(self): self.wait_condition.wakeAll() def perform(self): """Perform all sync""" self.status = STATUS_SYNC self.last_sync = datetime.now() self.sync_state_changed.emit(SYNC_STATE_START) if self._need_to_update(): self.need_to_update = True self.all_notes = list(self._iter_all_notes()) try: if self.need_to_update: self.remote_changes() self.local_changes() self.sharing_changes() except Exception, e: # maybe log this self.session.rollback() self.init_db() self.app.log(e) finally:
class PusThread(QThread): """ This class overrides a QThread object to be able to define custom safe threads with custom signals. This class is used to be able to make a simulation of a connection with the robot where the packets arrives with an interval between them without blocking the rest of the functionality of the application. The simulation is done by reading the packets from a json file. """ def __init__(self, controller, model): """ This is the constructor of the class :param file: The json file where the packets are defined :param model: The model of the application """ QThread.__init__(self) self.model = model self.controller = controller self.add_table_signal = AddTableSignal() self.add_table_signal.signal.connect(self.model.add) self.filter_table_signal = AddTableSignal() self.filter_table_signal.signal.connect( self.controller.open_filter_callback) self.json_file = None self.timer = QTimer(self) self.timer.timeout.connect(self.update_packets) self.json_file_loaded = QWaitCondition() self.mutex = QMutex() def run(self): """ This method runs the thread reading from the json defined and making an sleep of T seconds between packet and packet according to the interval defined in the json file. """ self.timer.start(1000) while True: self.mutex.lock() self.json_file_loaded.wait(self.mutex) file = self.json_file self.mutex.unlock() pt = PacketTranslator() mt = MakoTranslate() if file is not None: with open(file) as jfile: jsondata = mt.replace(jfile.read()) activities = json.loads(jsondata)[TestTags.ACTIVITIES_TAG] for activity in activities: interval = activity[TestTags.INTERVAL_TAG] self.sleep(interval) if TestTags.PACKET_TAG in activity: packet = pt.json2packet( activity[TestTags.PACKET_TAG]) pb.pus_notify_sendPacket(packet) self.add_table_signal.throw(packet) elif TestTags.ACTIONS_TAG in activity: if activity[TestTags. ACTIONS_TAG] == TestTags.SAVEDB_TAG: file = activity[TestTags.PARAMS_TAG] d = Database(file) d.create_dump_table() packages = [ tuple(e[1:-1]) for e in self.model.table ] d.insert_db( "INSERT INTO packages VALUES(?,?,?,?,?,?,?,?,?,?)", packages) elif activity[ TestTags. ACTIONS_TAG] == TestTags.SETFILTER_TAG: filter_ = FilterModel() type_ = activity[TestTags.PARAMS_TAG]["type"] svc = activity[TestTags.PARAMS_TAG]["svc"] msg = activity[TestTags.PARAMS_TAG]["msg"] filter_.set_filter_options(type_, svc, msg) filter_index = self.model.set_filter( filter_.get_filter_options()) self.filter_table_signal.throw(filter_index) self.mutex.lock() self.json_file = None self.mutex.unlock() def update_packets(self): for _ in range(10): packet = pb.pusPacket_t() if pb.pusError_t.PUS_NO_ERROR == pb.pus_notify_readTm( packet): # Comprobar si null self.add_table_signal.throw(packet) def load_test(self, json_file): self.mutex.lock() self.json_file = json_file if json_file is not None: self.json_file_loaded.wakeAll() self.mutex.unlock()
class Buffer(QObject): """ Class buffers annotation objects to cache from database for given frame or frame interval. :param video: reference to video object :type video: tovian.models.entity.Video :param parent: parent widget :type parent: PySide.QtCore.QObject """ checkBufferState = Signal() buffering = Signal() buffered = Signal() initialized = Signal() MAX_MEMORY_USAGE = 52428800 # 50MB def __init__(self, video, user_id, parent=None): super(Buffer, self).__init__(parent) self.mutex = QMutex() self.video = video self.last_frame_accessed = (0, 0) self.displayed_frames_range = 1 # must be odd self.video_frame_count = self.video.frame_count self.video_frame_fps = self.video.fps self.user_id = user_id self.cache = {} self.cached_min_frame = 0 self.cached_max_frame = 0 self.cached_time = 10 # seconds self.cached_time_border = 0.25 # 25 percent from cached interval, where it starts to buffer new objects self.checkBufferState.connect(self.__checkBuffer) def initBuffer(self): """ Called just first time after initializing buffed and moving to separated thread. """ new_start = 0 new_stop = int(self.cached_time * self.video_frame_fps) new_stop = new_stop if new_stop < self.video_frame_count else self.video_frame_count logger.debug("Filling buffer on interval [%s, %s]", new_start, new_stop) self.__bufferObjects(new_start, new_stop) self.initialized.emit() def setDisplayedFrameRange(self, length): """ Sets how long frame interval is displayed (non-vis annotations). i.e. 11 meas [currentframe-5, currentframe+5] :param length: range length :type length: int """ logger.debug("Setting new displayed range value %s", length) self.mutex.lock() self.displayed_frames_range = length self.mutex.unlock() def getObjectsInFrame(self, frame): """ Returns list of annotation objects for given frame. When accessing to cache, cached is locked for other access. :type frame: int :rtype: tuple of (tovian.models.entity.AnnotationObject, int, int) :raise AttributeError: if given frame number is out of range [0, video.frame_count] """ logger.debug("Called get an_object from buffer for frame: %s", frame) if frame < 0 or frame > self.video_frame_count: raise AttributeError( "Given frame number %s is out of range [0, %s]" % (frame, self.video_frame_count)) # --- locked ---- self.mutex.lock() try: objects = self.cache[frame] except KeyError: logger.error("Buffer objects could not be found for frame: %s", frame) models.repository.logs.insert( 'gui.exception.get_obj_from_buffer_error', "Buffer objects could not be found for frame: %s" % frame, annotator_id=self.user_id) objects = self.video.annotation_objects_in_frame(frame) else: objects = objects.values() finally: self.last_frame_accessed = (frame, frame) self.mutex.unlock() # don't forget to release lock # --------------- self.checkBufferState.emit() return tuple(objects) def getObjectsInFrameInterval(self, frame_from, frame_to): """ Returns list of annotation objects for given frame interval. :type frame_from: int :type frame_to: int :rtype: tuple of (tovian.models.entity.AnnotationObject, int, int) :raise AttributeError: if given frame number interval is not in range [0, video.frame_count] or is invalid """ logger.debug( "Called get an_object from buffer for frame interval [%s, %s]", frame_from, frame_to) if frame_from > frame_to: raise AttributeError( "frame_from '%s' is greater than frame_to '%s'" % (frame_from, frame_to)) if frame_from < 0 or frame_to < 0 or frame_to > self.video_frame_count or frame_from > self.video_frame_count: raise AttributeError( "Given frame interval [%s, %s] is out of range [0, %s]" % (frame_from, frame_to, self.video_frame_count)) if frame_from == frame_to: objects = self.getObjectsInFrame(frame_from) return objects objects = [] self.mutex.lock() try: for frame in range(frame_from, frame_to + 1): try: data = self.cache[frame] except KeyError: logger.error( "Buffer objects could not be found for frame: %s", frame) models.repository.logs.insert( 'gui.exception.get_obj_from_buffer_error', "Buffer objects could not be found for frame: %s" % frame, annotator_id=self.user_id) data = self.video.annotation_objects_in_frame(frame) else: data = data.values() objects.extend(data) # converts iterator to values finally: self.last_frame_accessed = (frame_from, frame_from) self.mutex.unlock() self.checkBufferState.emit() return tuple(set(objects)) def resetBuffer(self, frame, clear_all=False, clear_object=None): """ Reset buffer - loads new objects depending on given frame number (i.e. when seeking to new frame). Method requests lock when clearing cache! :param frame: target frame :type frame: int :param clear_all: manually clears buffer :type clear_all: bool :param clear_object: object that has to be refreshed in buffer (object_id, old_start_frame, old_end_frame) :raise ValueError: if given frame number is out of range [0, video.frame_count] | when new min and max cached frame are equaled or invalid """ #logger.debug("Locking thread") #self.mutex.lock() #self.last_frame_accessed = (min_frame_interval, max_frame_interval) #self.mutex.unlock() #logger.debug("Thread unlocked") if frame < 0 or frame > self.video_frame_count: raise ValueError("Given frame number %s is out of range [0, %s]" % (frame, self.video_frame_count)) if not clear_all and not clear_object: # if new frame has been already cached if frame in self.cache: min_frame = frame - ((self.displayed_frames_range - 1) / 2.0) max_frame = frame + ((self.displayed_frames_range - 1) / 2.0) min_frame = 0 if min_frame < 0 else min_frame max_frame = self.video_frame_count if max_frame > self.video_frame_count else max_frame # if new frame display frame range is also cached if self.cached_min_frame <= min_frame and self.cached_max_frame >= max_frame: logger.debug( "New frame and displayed frame interval is cached and no need to reset" ) return else: logger.debug( "Target frame is cached, but displayed frame range isn't." ) else: logger.debug("Target frame is not cached.") # calculate new start_frame and stop_frame new_start_frame = frame - int( (self.cached_time / 2.0) * self.video_frame_fps) new_stop_frame = frame + int( (self.cached_time / 2.0) * self.video_frame_fps) new_start_frame = 0 if new_start_frame < 0 else new_start_frame new_stop_frame = self.video_frame_count if new_stop_frame > self.video_frame_count else new_stop_frame if new_stop_frame == new_start_frame or new_stop_frame < new_start_frame: logger.error( "New start_frame '%s' and stop_frame '%s' are equal or invalid.", new_start_frame, new_stop_frame) raise ValueError( "New start_frame '%s' and stop_frame '%s' are equal or invalid." % (new_start_frame, new_stop_frame)) if clear_object: object_id, old_start, old_end = clear_object logger.debug("Deleting old object data from cache") self.mutex.lock() for i in range(old_start, old_end + 1): cache_data = self.cache[i] del cache_data[object_id] self.mutex.unlock() logger.debug("Thread unlocked") ## TODO DELETE !!!!!!!!!!!!!!!!!!!!!!!! FOR DEBUGGING PURPOSES #for key, value in self.cache.iteritems(): # if object_id in value: # print key, value # raise Exception() logger.debug( "Clearing object id '%s' from buffer and resetting for new frame: %s", object_id, frame) self.__bufferObjectByID(frame, object_id) else: logger.debug( "Resetting and clearing whole buffer for new frame: %s", frame) self.mutex.lock() self.cache = {} self.mutex.unlock() self.__bufferObjects(new_start_frame, new_stop_frame) # manually invoked buffering def __bufferObjects(self, frame_from, frame_to): """ Called to buffer new objects from database for given frame interval. Method requests lock when writing to cache! :type frame_from: int :type frame_to: int :raise ValueError: When frame_from or frame_to has invalid value (out of range, etc.) """ logger.debug("Tries buffer new frame interval [%s, %s]...", frame_from, frame_to) if frame_from > frame_to or frame_from < 0 or frame_to > self.video_frame_count: raise ValueError( "Invalid frame_from '%s' and frame_to values '%s'", frame_from, frame_to) self.mutex.lock() try: objectsTuples = self.video.annotation_objects_in_frame_intervals([ (frame_from, frame_to) ]) except Exception: # TODO display error to user logger.exception( "Error when buffering new objects from database on interval [%s, %s]", frame_from, frame_to) models.repository.logs.insert( 'gui.exception.buffering_new_obj_error', "Error when buffering new objects from database on interval [%s, %s]" % (frame_from, frame_to), annotator_id=self.user_id) self.mutex.unlock() # don't forget to release lock return cleared = not self.cache self.buffering.emit() #logger.debug("Locking thread -> adding new data to cache") #self.mutex.lock() # request lock try: for frame in range(frame_from, frame_to + 1): try: frame_dict = self.cache[frame] except KeyError: self.cache[frame] = {} frame_dict = self.cache[frame] # add record to cache for objectTuple in objectsTuples: an_object, start_frame, end_frame = objectTuple if start_frame <= frame <= end_frame: frame_dict[an_object.id] = objectTuple # if cache has been cleared when method called, set min and max pointers as usually if cleared: self.cached_max_frame = frame_to self.cached_min_frame = frame_from # if don't, cache has been extended, so moves pointer a bit else: if frame_from < self.cached_min_frame: self.cached_min_frame = frame_from if frame_to > self.cached_max_frame: self.cached_max_frame = frame_to finally: self.mutex.unlock() # don't forget to release lock self.buffered.emit() logger.debug("Buffered new time interval [%s, %s]", frame_from, frame_to) def __bufferObjectByID(self, target_frame, object_id): """ Buffer new object by given ID from database on given frame :type target_frame: int :type object_id: int :raise ValueError: When frame is out of range """ logger.debug("Trying to buffer new object id '%s' on frame '%s'", object_id, target_frame) if target_frame < 0 or target_frame > self.video_frame_count: raise ValueError( "Given frame number is out of video frame count range") try: objectTuples = self.video.annotation_objects_in_frame_intervals( [(target_frame, target_frame)], [ object_id, ]) except Exception: # TODO display error to user logger.exception( "Error when buffering new object id '%s' from database on on frame '%s'", object_id, target_frame) models.repository.logs.insert( 'gui.exception.buffering_new_obj_error', "Error when buffering new object id '%s' from database on on frame '%s'" % (object_id, target_frame), annotator_id=self.user_id) return if not objectTuples: logger.warning("No object id '%s' for frame '%s' in database!") return elif len(objectTuples) > 1: logger.warning( "Returned more than one object by id from database!") self.buffering.emit() logger.debug("Locking thread -> adding to cache new data") self.mutex.lock() try: an_object, start_frame, end_frame = objectTuples[0] for frame in range(start_frame, end_frame + 1): try: frame_dict = self.cache[frame] except KeyError: self.cache[frame] = {} frame_dict = self.cache[frame] frame_dict[an_object.id] = objectTuples[0] finally: self.mutex.unlock() logger.debug("Thread unlocked") self.buffered.emit() logger.debug("Buffered new by id '%s' on frame '%s'", object_id, target_frame) @Slot() def __checkBuffer(self): """ Method called when some data in cache has been accessed to check, if needs to be loaded new objects from database. """ memory_usage = sys.getsizeof(self.cache) if memory_usage > self.MAX_MEMORY_USAGE: logger.warning( "Reached maximum allowed memory usage '%s' bytes -> resetting buffer", self.MAX_MEMORY_USAGE) lower_accessed_frame, higher_accessed_frame = self.last_frame_accessed if lower_accessed_frame == higher_accessed_frame: frame = higher_accessed_frame else: frame = ((higher_accessed_frame - lower_accessed_frame) / 2) + lower_accessed_frame self.resetBuffer(frame, clear_all=True) return cached_min_border = self.cached_min_frame - self.last_frame_accessed[0] cached_max_border = self.cached_max_frame - self.last_frame_accessed[1] allowed_border = self.cached_time_border * self.cached_time * self.video_frame_fps # ---- # If the last_accessed_frame pointer is between borders (typically between 25% and 75% cache), do nothing. # else cache new interval and merge cached data # i.e. cache status = |bottom|--------------0current0--|top| => max border passed, cache new objects => # => new status = |bottom|--------------0current0--(-----------------------------)|top| # ---- # bottom border if cached_min_border > -allowed_border: new_stop = self.cached_min_frame - 1 new_start = new_stop - int(self.cached_time * self.video_frame_fps) new_start = 0 if new_start < 0 else new_start new_start = self.video_frame_count if new_start > self.video_frame_count else new_start new_stop = 0 if new_stop < 0 else new_stop new_stop = self.video_frame_count if new_stop > self.video_frame_count else new_stop if new_start != new_stop: logger.debug( "Check buffer - buffer needs to load new objects, direction down" ) self.__bufferObjects(new_start, new_stop) # upper border elif cached_max_border < allowed_border: new_start = self.cached_max_frame + 1 new_stop = new_start + int(self.cached_time * self.video_frame_fps) new_start = 0 if new_start < 0 else new_start new_start = self.video_frame_count if new_start > self.video_frame_count else new_start new_stop = 0 if new_stop < 0 else new_stop new_stop = self.video_frame_count if new_stop > self.video_frame_count else new_stop if new_start != new_stop: logger.debug( "Check buffer - buffer needs to load new objects, direction up" ) self.__bufferObjects(new_start, new_stop) else: logger.debug("Check buffer - status OK") @staticmethod def bufferFinished(): """ Called when buffer thread is finished (closed). """ logger.debug("Buffer thread closed.") @staticmethod def bufferTerminated(): """ Called when buffer thread is terminated (forced to close). """ logger.warning("Buffer thread terminated!")
class AsyncResolver(QThread): object_resolved = QtCore.Signal('object_resolved(QVariant)') def __init__(self): super(AsyncResolver, self).__init__() self._task_queue = [] self._mutex = QMutex() self._semaphore = QSemaphore() self.working = False def synchronized(f): def wrap(self, *args, **kwargs): self._mutex.lock() try: return f(self, *args, **kwargs) finally: self._mutex.unlock() return wrap def add_task(self, dn): self._task_queue.append(dn) #print self._semaphore.available() self._semaphore.release() #print 'before release' @synchronized def _append_task(self, task): self._task_queue.append(task) @synchronized def _pop_task(self, task): return self._task_queue.pop() def consume_task(self): #print self._semaphore.available() self._semaphore.acquire() #print 'after acq' obj = self._task_queue.pop() return obj def stop_work(self): self.working = False if self._task_queue: self._append_task(None) self._semaphore.release() @synchronized def _do_task(self, task): return task() def run(self): self.working = True while self.working: task = self.consume_task() if task: try: obj = self._do_task(task) except UcsmError: pass else: self.emit(SIGNAL('object_resolved(QVariant)'), obj) else: break