From b701ea28e81a735a51b05b5eacda86f639e9a83a Mon Sep 17 00:00:00 2001 From: Drew Short Date: Fri, 22 Aug 2014 23:48:39 -0500 Subject: [PATCH] Fix for the concurrent engine. Made the concurrent engine the default again. Updated the license Added a script to clean the logs in the base directory. Updated the .gitignore to ignore configuration files in the base directory needed for individual runs from within intellij. Improved the handling around cached images, falling back on restoring the data from the database when the ehcache fails. --- .gitignore | 6 +++++- LICENSE | 2 +- cleanLogs.sh | 6 ++++++ .../imagetools/engine/ConcurrentEngine.scala | 21 ++++++++++++++++--- .../sothr/imagetools/image/ImageService.scala | 6 +++--- .../ui/controller/AppController.scala | 4 ++-- 6 files changed, 35 insertions(+), 10 deletions(-) create mode 100755 cleanLogs.sh diff --git a/.gitignore b/.gitignore index 17c51c8..d857016 100644 --- a/.gitignore +++ b/.gitignore @@ -37,4 +37,8 @@ version.info *.versionsBackup #Cache directory -.cache/ \ No newline at end of file +.cache/ + +#Root Config Files +/user.conf +/logback.xml diff --git a/LICENSE b/LICENSE index c969132..0dcd862 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2013 Drew Short +Copyright (c) 2014 Drew Short Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/cleanLogs.sh b/cleanLogs.sh new file mode 100755 index 0000000..354870c --- /dev/null +++ b/cleanLogs.sh @@ -0,0 +1,6 @@ +rm ImageTools.debug +rm ImageTools.debug.* +rm ImageTools.info +rm ImageTools.info.* +rm ImageTools.err +rm ImageTools.err.* diff --git a/src/main/scala/com/sothr/imagetools/engine/ConcurrentEngine.scala b/src/main/scala/com/sothr/imagetools/engine/ConcurrentEngine.scala index ea08b21..35f9322 100644 --- a/src/main/scala/com/sothr/imagetools/engine/ConcurrentEngine.scala +++ b/src/main/scala/com/sothr/imagetools/engine/ConcurrentEngine.scala @@ -31,6 +31,8 @@ class ConcurrentEngine extends Engine with grizzled.slf4j.Logging { debug(s"Looking for images in directory: $directoryPath") val imageFiles = getAllImageFiles(directoryPath, recursive, recursiveDepth) val images:mutable.MutableList[Image] = new mutable.MutableList[Image]() + // make sure the engine is listening + engineProcessingController ! EngineStart for (file <- imageFiles) { engineProcessingController ! EngineProcessFile(file) } @@ -61,6 +63,8 @@ class ConcurrentEngine extends Engine with grizzled.slf4j.Logging { debug(s"Looking for similar images in directory: $directoryPath") val images = getImagesForDirectory(directoryPath, recursive, recursiveDepth) info(s"Searching ${images.length} images for similarities") + // make sure the engine is listening + engineSimilarityController ! EngineStart for (rootImage <- images) { debug(s"Looking for images similar to: ${rootImage.imagePath}") engineSimilarityController ! EngineCompareImages(rootImage, images) @@ -113,6 +117,7 @@ class ConcurrentEngine extends Engine with grizzled.slf4j.Logging { // external cases // case class SetNewListener(listenerType: ActorRef) +case object EngineStart // processing files into images case class EngineProcessFile(file:File) @@ -133,8 +138,8 @@ class ConcurrentEngineProcessingController extends Actor with ActorLogging { if (processors > max) threads = max else if (processors > 1) threads = processors - 1 else threads = 1 threads } - val router = context.actorOf(Props[ConcurrentEngineProcessingActor].withRouter(SmallestMailboxRouter(nrOfInstances = numOfRouters))) - + var router = context.actorOf(Props[ConcurrentEngineProcessingActor].withRouter(SmallestMailboxRouter(nrOfInstances = numOfRouters))) + var images:mutable.MutableList[Image] = new mutable.MutableList[Image]() var toProcess = 0 var processed = 0 @@ -159,6 +164,7 @@ class ConcurrentEngineProcessingController extends Actor with ActorLogging { case command:SetNewListener => setListener(command.listenerType) case command:EngineProcessFile => processFile(command) case command:EngineFileProcessed => fileProcessed(command) + case EngineStart => startEngine() case EngineNoMoreFiles => requestWrapup() case EngineActorProcessingFinished => actorProcessingFinished() case EngineIsProcessingFinished => checkIfProcessingIsFinished() @@ -170,7 +176,11 @@ class ConcurrentEngineProcessingController extends Actor with ActorLogging { super.postStop() this.listener ! PoisonPill } - + + def startEngine() = { + router ! Broadcast(EngineActorReactivate) + } + def processFile(command:EngineProcessFile) = { log.debug(s"Started evaluating ${command.file.getAbsolutePath}") toProcess += 1 @@ -302,6 +312,7 @@ class ConcurrentEngineSimilarityController extends Actor with ActorLogging { case command:SetNewListener => setListener(command.listenerType) case command:EngineCompareImages => findSimilarities(command) case command:EngineCompareImagesComplete => similarityProcessed(command) + case EngineStart => startEngine() case EngineNoMoreComparisons => requestWrapup() case EngineActorCompareImagesFinished => actorProcessingFinished() case EngineIsSimilarityFinished => checkIfProcessingIsFinished() @@ -314,6 +325,10 @@ class ConcurrentEngineSimilarityController extends Actor with ActorLogging { this.listener ! PoisonPill } + def startEngine() = { + router ! Broadcast(EngineActorReactivate) + } + def findSimilarities(command:EngineCompareImages) = { log.debug(s"Finding similarities between {} and {} images", command.image1.imagePath, command.images.length) toProcess += 1 diff --git a/src/main/scala/com/sothr/imagetools/image/ImageService.scala b/src/main/scala/com/sothr/imagetools/image/ImageService.scala index 9d85bdf..8ad7b9d 100644 --- a/src/main/scala/com/sothr/imagetools/image/ImageService.scala +++ b/src/main/scala/com/sothr/imagetools/image/ImageService.scala @@ -23,11 +23,11 @@ object ImageService extends Logging { //get from memory cache if possible try { if (imageCache.isKeyInCache(file.getAbsolutePath)) { - found = true image = imageCache.get(file.getAbsolutePath).getObjectValue.asInstanceOf[Image] + found = true } } catch { - case npe:NullPointerException => error(s"Error grabbing \'${file.getAbsolutePath}\' from cache", npe) + case npe:NullPointerException => debug(s"\'${file.getAbsolutePath}\' was supposed to be in the cache, but was not") } //get from datastore if possible if (!found) { @@ -35,7 +35,7 @@ object ImageService extends Logging { val tempImage = imageDAO.find(file.getAbsolutePath) if (tempImage != null) image = tempImage } catch { - case ex:Exception => error(s"Error looking up \'${file.getAbsolutePath}\' from database", ex) + case ex:Exception => error(s"Error looking up \'${file.getAbsolutePath}\' was supposed to be in the database, but was not", ex) } } image diff --git a/src/main/scala/com/sothr/imagetools/ui/controller/AppController.scala b/src/main/scala/com/sothr/imagetools/ui/controller/AppController.scala index a089248..48a1723 100644 --- a/src/main/scala/com/sothr/imagetools/ui/controller/AppController.scala +++ b/src/main/scala/com/sothr/imagetools/ui/controller/AppController.scala @@ -10,7 +10,7 @@ import javafx.scene.web.WebView import javafx.scene.{Group, Node, Scene} import javafx.stage.{DirectoryChooser, Stage, StageStyle} -import com.sothr.imagetools.engine.{Engine, SequentialEngine} +import com.sothr.imagetools.engine.{ConcurrentEngine, Engine} import com.sothr.imagetools.ui.component.ImageTileFactory import com.sothr.imagetools.util.{PropertiesService, ResourceLoader} import grizzled.slf4j.Logging @@ -33,7 +33,7 @@ class AppController extends Logging { @FXML var selectedDirectoryLabel: javafx.scene.control.Label = null // Engine - val engine:Engine = new SequentialEngine() + val engine:Engine = new ConcurrentEngine() // Current State var currentDirectory:String = "."