Tweak the pool sizes and allow for longer time to load things. This improves reliabi...
[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                                 return t;
58                         }
59
60                 });
61
62                 workGenerator = new Thread( new WorkGenerator(),"PresetGeneratorThread");
63         }
64
65         public void load() {
66                 startTime = System.currentTimeMillis();
67                 workGenerator.start();
68         }
69
70         public void await() throws InterruptedException {
71                 latch.await();
72                 loaderPool.shutdown();
73                 loaderPool.awaitTermination(90, TimeUnit.SECONDS);
74                 writerPool.shutdown();
75                 writerPool.awaitTermination(90, TimeUnit.SECONDS);
76                 iterator.close();
77                 long end = System.currentTimeMillis();
78                 log.debug("Time to load presets: " + (end-startTime) + "ms " + presetCount + " loaded from " + fileCount + " files");
79         }
80
81
82         private class WorkGenerator implements Runnable {
83                 @Override
84                 public void run() {
85                         // Start loading
86                         log.info("Loading component presets from " + SYSTEM_PRESET_DIR);
87
88                         iterator = DirectoryIterator.findDirectory(SYSTEM_PRESET_DIR,
89                                         new SimpleFileFilter("", false, "orc"));
90
91                         if (iterator == null) {
92                                 throw new IllegalStateException("Component preset directory " + SYSTEM_PRESET_DIR +
93                                                 " not found, distribution built wrong");
94                         }
95
96                         while( iterator.hasNext() ) {
97                                 Pair<String,InputStream> f = iterator.next();
98                                 FileLoader loader = new FileLoader( f.getV(), f.getU() );
99                                 loaderPool.execute(loader);
100                                 fileCount ++;
101                         }
102
103                         latch.countDown();
104                 }
105         }
106
107         private class FileLoader implements Runnable {
108                 private final InputStream is;
109                 private final String fileName;
110
111                 public FileLoader(InputStream is, String fileName) {
112                         super();
113                         this.is = is;
114                         this.fileName = fileName;
115                 }
116
117                 @Override
118                 public void run() {
119                         OpenRocketComponentLoader loader = new OpenRocketComponentLoader();
120                         Collection<ComponentPreset> presets = loader.load(is, fileName);
121                         PresetWriter writer = new PresetWriter(presets);
122                         writerPool.execute(writer);
123                 }               
124         }
125
126         private class PresetWriter implements Runnable {
127                 private final Collection<ComponentPreset> presets;
128
129                 public PresetWriter(Collection<ComponentPreset> presets) {
130                         super();
131                         this.presets = presets;
132                 }
133
134                 @Override
135                 public void run() {
136                         presetCount += presets.size();
137                         componentPresetDao.addAll(presets);
138                 }
139
140         }
141 }