Implement a multithreaded pipeline to load the component preset files. This greatly...
authorkruland2607 <kruland2607@180e2498-e6e9-4542-8430-84ac67f01cd8>
Wed, 9 May 2012 02:01:57 +0000 (02:01 +0000)
committerkruland2607 <kruland2607@180e2498-e6e9-4542-8430-84ac67f01cd8>
Wed, 9 May 2012 02:01:57 +0000 (02:01 +0000)
git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@657 180e2498-e6e9-4542-8430-84ac67f01cd8

core/src/net/sf/openrocket/database/ComponentPresetDatabase.java
core/src/net/sf/openrocket/startup/ConcurrentComponentPresetDatabaseLoader.java [new file with mode: 0644]
core/src/net/sf/openrocket/startup/Startup2.java

index 6fc187e76e106e9a48067087a78ef44fd1594d6d..0fd0d419e8d9adf620eef5c5eb501abcb227aad4 100644 (file)
@@ -1,6 +1,5 @@
 package net.sf.openrocket.database;
 
-import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.util.ArrayList;
@@ -23,11 +22,10 @@ public class ComponentPresetDatabase extends Database<ComponentPreset> implement
 
        private static final LogHelper log = Application.getLogger();
 
-       private static class ComponentPresetLoader implements Loader<ComponentPreset> {
+       public static class ComponentPresetLoader implements Loader<ComponentPreset> {
 
                @Override
-               public Collection<ComponentPreset> load(InputStream stream,
-                               String filename) throws IOException {
+               public Collection<ComponentPreset> load(InputStream stream,     String filename) {
 
                        log.debug("Loading presets from file " + filename);
 
@@ -41,7 +39,7 @@ public class ComponentPresetDatabase extends Database<ComponentPreset> implement
                                                preset.setFavorite(true);
                                        }
                                }                               
-
+                               log.debug("ComponentPreset file " + filename + " contained " + presets.size() + " presets");
                                return presets;
                        } catch (JAXBException e) {
                                throw new BugException("Unable to parser file: "+ filename, e);
diff --git a/core/src/net/sf/openrocket/startup/ConcurrentComponentPresetDatabaseLoader.java b/core/src/net/sf/openrocket/startup/ConcurrentComponentPresetDatabaseLoader.java
new file mode 100644 (file)
index 0000000..a97d688
--- /dev/null
@@ -0,0 +1,140 @@
+package net.sf.openrocket.startup;
+
+import java.io.InputStream;
+import java.util.Collection;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+
+import net.sf.openrocket.database.ComponentPresetDatabase;
+import net.sf.openrocket.file.iterator.DirectoryIterator;
+import net.sf.openrocket.file.iterator.FileIterator;
+import net.sf.openrocket.gui.util.SimpleFileFilter;
+import net.sf.openrocket.logging.LogHelper;
+import net.sf.openrocket.preset.ComponentPreset;
+import net.sf.openrocket.util.Pair;
+
+public class ConcurrentComponentPresetDatabaseLoader {
+
+       private static final LogHelper log = Application.getLogger();
+       private static final String SYSTEM_PRESET_DIR = "datafiles/presets";
+
+       private final CountDownLatch latch = new CountDownLatch(1);
+
+       private final ComponentPresetDatabase componentPresetDao;
+
+       private final ExecutorService writerPool;
+
+       private final ExecutorService loaderPool;
+
+       private final Thread workGenerator;
+
+       private FileIterator iterator;
+
+       private long startTime;
+       private long fileCount = 0;
+       private long presetCount = 0;
+
+       ConcurrentComponentPresetDatabaseLoader( ComponentPresetDatabase componentPresetDao ) {
+               this.componentPresetDao = componentPresetDao;
+
+               writerPool = Executors.newSingleThreadExecutor(new ThreadFactory() {
+                       @Override
+                       public Thread newThread(Runnable r) {
+                               Thread t = new Thread(r,"PresetWriterThread");
+                               return t;
+                       }
+               });
+
+               loaderPool = Executors.newFixedThreadPool(15, new ThreadFactory() {
+                       int threadCount = 0;
+                       @Override
+                       public Thread newThread(Runnable r) {
+                               Thread t = new Thread(r,"PresetLoaderPool-" + threadCount++);
+                               return t;
+                       }
+
+               });
+
+               workGenerator = new Thread( new WorkGenerator(),"PresetGeneratorThread");
+       }
+
+       public void load() {
+               startTime = System.currentTimeMillis();
+               workGenerator.start();
+       }
+
+       public void await() throws InterruptedException {
+               latch.await();
+               loaderPool.shutdown();
+               loaderPool.awaitTermination(10, TimeUnit.SECONDS);
+               writerPool.shutdown();
+               writerPool.awaitTermination(10, TimeUnit.SECONDS);
+               iterator.close();
+               long end = System.currentTimeMillis();
+               log.debug("Time to load presets: " + (end-startTime) + "ms " + presetCount + " loaded from " + fileCount + " files");
+       }
+
+
+       private class WorkGenerator implements Runnable {
+               @Override
+               public void run() {
+                       // Start loading
+                       log.info("Loading component presets from " + SYSTEM_PRESET_DIR);
+
+                       iterator = DirectoryIterator.findDirectory(SYSTEM_PRESET_DIR,
+                                       new SimpleFileFilter("", false, "orc"));
+
+                       if (iterator == null) {
+                               throw new IllegalStateException("Component preset directory " + SYSTEM_PRESET_DIR +
+                                               " not found, distribution built wrong");
+                       }
+
+                       while( iterator.hasNext() ) {
+                               Pair<String,InputStream> f = iterator.next();
+                               FileLoader loader = new FileLoader( f.getV(), f.getU() );
+                               loaderPool.execute(loader);
+                               fileCount ++;
+                       }
+
+                       latch.countDown();
+               }
+       }
+
+       private class FileLoader implements Runnable {
+               private final InputStream is;
+               private final String fileName;
+
+               public FileLoader(InputStream is, String fileName) {
+                       super();
+                       this.is = is;
+                       this.fileName = fileName;
+               }
+
+               @Override
+               public void run() {
+                       ComponentPresetDatabase.ComponentPresetLoader loader = new ComponentPresetDatabase.ComponentPresetLoader();
+                       Collection<ComponentPreset> presets = loader.load(is, fileName);
+                       PresetWriter writer = new PresetWriter(presets);
+                       writerPool.execute(writer);
+               }               
+       }
+
+       private class PresetWriter implements Runnable {
+               private final Collection<ComponentPreset> presets;
+
+               public PresetWriter(Collection<ComponentPreset> presets) {
+                       super();
+                       this.presets = presets;
+               }
+
+               @Override
+               public void run() {
+                       presetCount += presets.size();
+                       componentPresetDao.addAll(presets);
+               }
+
+       }
+}
index d7206f306e64eba656caa6d8a4e2113c652b739f..b2e13195e49ca97c153567b9195a96dea3210d1e 100644 (file)
@@ -4,13 +4,6 @@ import java.awt.GraphicsEnvironment;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.io.File;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.atomic.AtomicInteger;
 
 import javax.swing.SwingUtilities;
 import javax.swing.Timer;
@@ -20,21 +13,13 @@ import net.sf.openrocket.communication.UpdateInfo;
 import net.sf.openrocket.communication.UpdateInfoRetriever;
 import net.sf.openrocket.database.ComponentPresetDatabase;
 import net.sf.openrocket.database.Databases;
-import net.sf.openrocket.database.ThrustCurveMotorSet;
-import net.sf.openrocket.database.ThrustCurveMotorSetDatabase;
-import net.sf.openrocket.file.iterator.DirectoryIterator;
-import net.sf.openrocket.file.iterator.FileIterator;
-import net.sf.openrocket.file.motor.MotorLoaderHelper;
 import net.sf.openrocket.gui.dialogs.UpdateInfoDialog;
 import net.sf.openrocket.gui.main.BasicFrame;
 import net.sf.openrocket.gui.main.Splash;
 import net.sf.openrocket.gui.main.SwingExceptionHandler;
 import net.sf.openrocket.gui.util.GUIUtil;
-import net.sf.openrocket.gui.util.SimpleFileFilter;
 import net.sf.openrocket.gui.util.SwingPreferences;
 import net.sf.openrocket.logging.LogHelper;
-import net.sf.openrocket.motor.Motor;
-import net.sf.openrocket.motor.ThrustCurveMotor;
 import net.sf.openrocket.util.BuildProperties;
 
 /**
@@ -91,22 +76,10 @@ public class Startup2 {
                log.info("Initializing the splash screen");
                Splash.init();
                
-               // Latch which counts the number of background loading processes we need to complete.
-               CountDownLatch loading = new CountDownLatch(1);
-               ExecutorService exec = Executors.newFixedThreadPool(1, new ThreadFactory() {
-
-                       @Override
-                       public Thread newThread(Runnable r) {
-                               Thread t = new Thread(r);
-                               t.setPriority(Thread.MIN_PRIORITY);
-                               return t;
-                       }
-                       
-               });
-
                // Must be done after localization is initialized
                ComponentPresetDatabase componentPresetDao = new ComponentPresetDatabase();
-               exec.submit( new ComponentPresetLoader( loading, componentPresetDao));
+               ConcurrentComponentPresetDatabaseLoader presetLoader = new ConcurrentComponentPresetDatabaseLoader( componentPresetDao );
+               presetLoader.load();
                
                Application.setComponentPresetDao( componentPresetDao );
                
@@ -147,7 +120,7 @@ public class Startup2 {
                Databases.fakeMethod();
                
                try {
-                       loading.await();
+                       presetLoader.await();
                } catch ( InterruptedException iex) {
                        
                }
@@ -226,28 +199,6 @@ public class Startup2 {
                timer.start();
        }
        
-       private static class ComponentPresetLoader implements Callable {
-
-               CountDownLatch latch;
-               ComponentPresetDatabase componentPresetDao;
-               
-               private ComponentPresetLoader( CountDownLatch latch, ComponentPresetDatabase componentPresetDao ) {
-                       this.componentPresetDao = componentPresetDao;
-                       this.latch = latch;
-               }
-               
-               @Override
-               public Object call() throws Exception {
-                       long start = System.currentTimeMillis();
-                       componentPresetDao.load("datafiles/presets", "(?i).*orc");
-                       latch.countDown();
-                       long end = System.currentTimeMillis();
-                       log.debug("Time to load presets: " + (end-start) + "ms");
-                       return null;
-               }
-
-       }
-       
        /**
         * Handles arguments passed from the command line.  This may be used either
         * when starting the first instance of OpenRocket or later when OpenRocket is