Ask java to use min priority on the loader threads.
[debian/openrocket] / core / src / net / sf / openrocket / startup / ConcurrentComponentPresetDatabaseLoader.java
1 package net.sf.openrocket.startup;
2
3 import java.io.InputStream;
4 import java.util.Collection;
5 import java.util.concurrent.CountDownLatch;
6 import java.util.concurrent.ExecutorService;
7 import java.util.concurrent.Executors;
8 import java.util.concurrent.ThreadFactory;
9 import java.util.concurrent.TimeUnit;
10
11 import net.sf.openrocket.database.ComponentPresetDatabase;
12 import net.sf.openrocket.file.iterator.DirectoryIterator;
13 import net.sf.openrocket.file.iterator.FileIterator;
14 import net.sf.openrocket.gui.util.SimpleFileFilter;
15 import net.sf.openrocket.logging.LogHelper;
16 import net.sf.openrocket.preset.ComponentPreset;
17 import net.sf.openrocket.preset.xml.OpenRocketComponentLoader;
18 import net.sf.openrocket.util.Pair;
19
20 public class ConcurrentComponentPresetDatabaseLoader {
21
22         private static final LogHelper log = Application.getLogger();
23         private static final String SYSTEM_PRESET_DIR = "datafiles/presets";
24
25         private final CountDownLatch latch = new CountDownLatch(1);
26
27         private final ComponentPresetDatabase componentPresetDao;
28
29         private final ExecutorService writerPool;
30
31         private final ExecutorService loaderPool;
32
33         private final Thread workGenerator;
34
35         private FileIterator iterator;
36
37         private long startTime;
38         private long fileCount = 0;
39         private long presetCount = 0;
40
41         ConcurrentComponentPresetDatabaseLoader( ComponentPresetDatabase componentPresetDao ) {
42                 this.componentPresetDao = componentPresetDao;
43
44                 writerPool = Executors.newSingleThreadExecutor(new ThreadFactory() {
45                         @Override
46                         public Thread newThread(Runnable r) {
47                                 Thread t = new Thread(r,"PresetWriterThread");
48                                 return t;
49                         }
50                 });
51
52                 loaderPool = Executors.newFixedThreadPool(3, new ThreadFactory() {
53                         int threadCount = 0;
54                         @Override
55                         public Thread newThread(Runnable r) {
56                                 Thread t = new Thread(r,"PresetLoaderPool-" + threadCount++);
57                                 t.setPriority(Thread.MIN_PRIORITY);
58                                 return t;
59                         }
60
61                 });
62
63                 workGenerator = new Thread( new WorkGenerator(),"PresetGeneratorThread");
64         }
65
66         public void load() {
67                 startTime = System.currentTimeMillis();
68                 workGenerator.start();
69         }
70
71         public void await() throws InterruptedException {
72                 latch.await();
73                 loaderPool.shutdown();
74                 loaderPool.awaitTermination(90, TimeUnit.SECONDS);
75                 writerPool.shutdown();
76                 writerPool.awaitTermination(90, TimeUnit.SECONDS);
77                 if ( iterator != null ) {
78                         iterator.close();
79                 }
80                 long end = System.currentTimeMillis();
81                 log.debug("Time to load presets: " + (end-startTime) + "ms " + presetCount + " loaded from " + fileCount + " files");
82         }
83
84
85         private class WorkGenerator implements Runnable {
86                 @Override
87                 public void run() {
88                         // Start loading
89                         log.info("Loading component presets from " + SYSTEM_PRESET_DIR);
90
91                         iterator = DirectoryIterator.findDirectory(SYSTEM_PRESET_DIR,
92                                         new SimpleFileFilter("", false, "orc"));
93
94                         if (iterator != null) {
95                                 while( iterator.hasNext() ) {
96                                         Pair<String,InputStream> f = iterator.next();
97                                         FileLoader loader = new FileLoader( f.getV(), f.getU() );
98                                         loaderPool.execute(loader);
99                                         fileCount ++;
100                                 }
101                         }
102                         latch.countDown();
103                 }
104         }
105
106         private class FileLoader implements Runnable {
107                 private final InputStream is;
108                 private final String fileName;
109
110                 public FileLoader(InputStream is, String fileName) {
111                         super();
112                         this.is = is;
113                         this.fileName = fileName;
114                 }
115
116                 @Override
117                 public void run() {
118                         OpenRocketComponentLoader loader = new OpenRocketComponentLoader();
119                         Collection<ComponentPreset> presets = loader.load(is, fileName);
120                         PresetWriter writer = new PresetWriter(presets);
121                         writerPool.execute(writer);
122                 }               
123         }
124
125         private class PresetWriter implements Runnable {
126                 private final Collection<ComponentPreset> presets;
127
128                 public PresetWriter(Collection<ComponentPreset> presets) {
129                         super();
130                         this.presets = presets;
131                 }
132
133                 @Override
134                 public void run() {
135                         presetCount += presets.size();
136                         componentPresetDao.addAll(presets);
137                 }
138
139         }
140 }