Browse Source

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.
master
Drew Short 10 years ago
parent
commit
b701ea28e8
  1. 6
      .gitignore
  2. 2
      LICENSE
  3. 6
      cleanLogs.sh
  4. 21
      src/main/scala/com/sothr/imagetools/engine/ConcurrentEngine.scala
  5. 6
      src/main/scala/com/sothr/imagetools/image/ImageService.scala
  6. 4
      src/main/scala/com/sothr/imagetools/ui/controller/AppController.scala

6
.gitignore

@ -37,4 +37,8 @@ version.info
*.versionsBackup
#Cache directory
.cache/
.cache/
#Root Config Files
/user.conf
/logback.xml

2
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

6
cleanLogs.sh

@ -0,0 +1,6 @@
rm ImageTools.debug
rm ImageTools.debug.*
rm ImageTools.info
rm ImageTools.info.*
rm ImageTools.err
rm ImageTools.err.*

21
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

6
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

4
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 = "."

Loading…
Cancel
Save