Index: trunk/WikiWord/WikiWordBuilder/src/main/java/de/brightbyte/wikiword/builder/ImportApp.java |
— | — | @@ -7,6 +7,7 @@ |
8 | 8 | |
9 | 9 | import de.brightbyte.application.Agenda; |
10 | 10 | import de.brightbyte.application.Agenda.Monitor; |
| 11 | +import de.brightbyte.db.DatabaseTask; |
11 | 12 | import de.brightbyte.io.Prompt; |
12 | 13 | import de.brightbyte.util.PersistenceException; |
13 | 14 | import de.brightbyte.wikiword.StoreBackedApp; |
— | — | @@ -14,6 +15,7 @@ |
15 | 16 | import de.brightbyte.wikiword.store.WikiWordStore; |
16 | 17 | import de.brightbyte.wikiword.store.WikiWordStoreFactory; |
17 | 18 | import de.brightbyte.wikiword.store.builder.DatabaseConceptStoreBuilders; |
| 19 | +import de.brightbyte.wikiword.store.builder.DatabaseWikiWordStoreBuilder; |
18 | 20 | import de.brightbyte.wikiword.store.builder.WikiWordConceptStoreBuilder; |
19 | 21 | import de.brightbyte.wikiword.store.builder.WikiWordStoreBuilder; |
20 | 22 | |
— | — | @@ -36,7 +38,7 @@ |
37 | 39 | protected Operation operation = null; |
38 | 40 | private Monitor agendaMonitor; |
39 | 41 | protected String[] baseTasks = new String[] {}; |
40 | | - protected InputFileHelper inputHelper; |
| 42 | + protected InputFileHelper inputHelper; |
41 | 43 | |
42 | 44 | public ImportApp(String agendaTask, boolean allowGlobal, boolean allowLocal) { //TODO: agenda-params! |
43 | 45 | super(allowGlobal, allowLocal); |
— | — | @@ -268,6 +270,10 @@ |
269 | 271 | protected void createStores(WikiWordStoreFactory<? extends S> factory) throws IOException, PersistenceException { |
270 | 272 | super.createStores(factory); |
271 | 273 | |
| 274 | + if (conceptStore instanceof DatabaseWikiWordStoreBuilder) { |
| 275 | + ((DatabaseWikiWordStoreBuilder)conceptStore).setBackgroundErrorHandler(new FatalBackgroundErrorHandler<Runnable, Throwable, Error>()); |
| 276 | + } |
| 277 | + |
272 | 278 | boolean noimport = args.isSet("noimport"); |
273 | 279 | |
274 | 280 | if (!noimport && useAgenda) { |
Index: trunk/WikiWord/WikiWordBuilder/src/main/java/de/brightbyte/wikiword/builder/ConceptImporter.java |
— | — | @@ -21,6 +21,7 @@ |
22 | 22 | import de.brightbyte.wikiword.model.LocalConceptReference; |
23 | 23 | import de.brightbyte.wikiword.processor.ImportProgressTracker; |
24 | 24 | import de.brightbyte.wikiword.schema.AliasScope; |
| 25 | +import de.brightbyte.wikiword.schema.ConceptStoreSchemas; |
25 | 26 | import de.brightbyte.wikiword.store.builder.IncrementalStoreBuilder; |
26 | 27 | import de.brightbyte.wikiword.store.builder.LocalConceptStoreBuilder; |
27 | 28 | import de.brightbyte.wikiword.store.builder.PropertyStoreBuilder; |
Index: trunk/WikiWord/WikiWordBuilder/src/main/java/de/brightbyte/wikiword/builder/ImportDump.java |
— | — | @@ -17,7 +17,7 @@ |
18 | 18 | super(agendaTask, false, true); |
19 | 19 | } |
20 | 20 | |
21 | | - private URL dumpFile; |
| 21 | + protected URL dumpFile; |
22 | 22 | |
23 | 23 | @Override |
24 | 24 | protected boolean applyArguments() { |
— | — | @@ -107,7 +107,7 @@ |
108 | 108 | |
109 | 109 | ///////////////////////// main import run //////////////////////////////////// |
110 | 110 | if (agenda.beginTask("ImportDump.run", "analysis")) { |
111 | | - DataSourceDriver driver = new XmlDumpDriver(getDumpFileURL(), inputHelper, getLogOutput(), tweaks); |
| 111 | + DataSourceDriver driver = new XmlDumpDriver(getDumpFileURL(), inputHelper, getLogOutput(), new FatalBackgroundErrorHandler<XmlDumpDriver, Throwable, RuntimeException>(), tweaks); |
112 | 112 | |
113 | 113 | importer.reset(); |
114 | 114 | importer.prepare(); |
Index: trunk/WikiWord/WikiWordBuilder/src/main/java/de/brightbyte/wikiword/extract/ExtractFromDump.java |
— | — | @@ -6,7 +6,6 @@ |
7 | 7 | |
8 | 8 | import de.brightbyte.util.PersistenceException; |
9 | 9 | import de.brightbyte.wikiword.analyzer.WikiTextAnalyzer; |
10 | | -import de.brightbyte.wikiword.builder.InputFileHelper; |
11 | 10 | import de.brightbyte.wikiword.output.DataOutput; |
12 | 11 | import de.brightbyte.wikiword.processor.DataSourceDriver; |
13 | 12 | import de.brightbyte.wikiword.processor.WikiWordPageProcessor; |
— | — | @@ -61,7 +60,7 @@ |
62 | 61 | processor.setLogOutput(getLogOutput()); |
63 | 62 | processor.configure(args); |
64 | 63 | |
65 | | - DataSourceDriver driver = new XmlDumpDriver(dumpFile, inputHelper, getLogOutput(), tweaks); |
| 64 | + DataSourceDriver driver = new XmlDumpDriver(dumpFile, inputHelper, getLogOutput(), new FatalBackgroundErrorHandler<XmlDumpDriver, Throwable, RuntimeException>(), tweaks); |
66 | 65 | |
67 | 66 | processor.reset(); |
68 | 67 | processor.prepare(); |
Index: trunk/WikiWord/WikiWordBuilder/src/main/java/de/brightbyte/wikiword/store/builder/DatabaseLocalConceptStoreBuilder.java |
— | — | @@ -1342,12 +1342,14 @@ |
1343 | 1343 | @Override |
1344 | 1344 | protected DatabaseConceptInfoStoreBuilder<LocalConcept> newConceptInfoStoreBuilder() throws SQLException { |
1345 | 1345 | ConceptInfoStoreSchema schema = new ConceptInfoStoreSchema(getDatasetIdentifier(), getDatabaseAccess().getConnection(), true, tweaks, false, true); |
| 1346 | + schema.setBackgroundErrorHandler(database.getBackgroundErrorHandler()); |
1346 | 1347 | return new DatabaseLocalConceptInfoStoreBuilder(schema, tweaks, getAgenda()); |
1347 | 1348 | } |
1348 | 1349 | |
1349 | 1350 | @Override |
1350 | 1351 | protected DatabaseStatisticsStoreBuilder newStatisticsStoreBuilder() throws SQLException { |
1351 | 1352 | StatisticsStoreSchema schema = new LocalStatisticsStoreSchema(getDatasetIdentifier(), getDatabaseAccess().getConnection(), tweaks, false); |
| 1353 | + schema.setBackgroundErrorHandler(database.getBackgroundErrorHandler()); |
1352 | 1354 | return new DatabaseLocalStatisticsStoreBuilder(schema, tweaks, getAgenda()); |
1353 | 1355 | } |
1354 | 1356 | |
Index: trunk/WikiWord/WikiWordBuilder/src/main/java/de/brightbyte/wikiword/store/builder/WikiWordStoreBuilder.java |
— | — | @@ -12,7 +12,6 @@ |
13 | 13 | public abstract void prepareImport() throws PersistenceException; |
14 | 14 | public void finalizeImport() throws PersistenceException; |
15 | 15 | |
16 | | - |
17 | 16 | public abstract void close(boolean flush) throws PersistenceException; |
18 | 17 | |
19 | 18 | public abstract void open() throws PersistenceException; |
Index: trunk/WikiWord/WikiWordBuilder/src/main/java/de/brightbyte/wikiword/store/builder/DatabaseTextStoreBuilder.java |
— | — | @@ -40,14 +40,14 @@ |
41 | 41 | } |
42 | 42 | |
43 | 43 | public DatabaseTextStoreBuilder(DatabaseLocalConceptStoreBuilder conceptStore, TweakSet tweaks) throws SQLException, PersistenceException { |
44 | | - this(new LocalConceptStoreSchema(conceptStore.getCorpus(), |
45 | | - conceptStore.getDatabaseAccess().getConnection(), |
46 | | - tweaks, true), |
| 44 | + this((LocalConceptStoreSchema)conceptStore.getDatabaseAccess(), |
47 | 45 | new TextStoreSchema(conceptStore.getCorpus(), |
48 | 46 | conceptStore.getDatabaseAccess().getConnection(), |
49 | 47 | tweaks, true), |
50 | 48 | tweaks, |
51 | 49 | conceptStore.getAgenda()); |
| 50 | + |
| 51 | + database.setBackgroundErrorHandler(conceptStore.getDatabaseAccess().getBackgroundErrorHandler()); |
52 | 52 | } |
53 | 53 | |
54 | 54 | protected DatabaseTextStoreBuilder(LocalConceptStoreSchema conceptStoreSchema, TextStoreSchema database, TweakSet tweaks, Agenda agenda) throws SQLException, PersistenceException { |
Index: trunk/WikiWord/WikiWordBuilder/src/main/java/de/brightbyte/wikiword/store/builder/DatabasePropertyStoreBuilder.java |
— | — | @@ -36,15 +36,15 @@ |
37 | 37 | } |
38 | 38 | |
39 | 39 | public DatabasePropertyStoreBuilder(DatabaseLocalConceptStoreBuilder conceptStore, TweakSet tweaks) throws SQLException, PersistenceException { |
40 | | - this(new LocalConceptStoreSchema(conceptStore.getCorpus(), |
41 | | - conceptStore.getDatabaseAccess().getConnection(), |
42 | | - tweaks, true), |
| 40 | + this((LocalConceptStoreSchema)conceptStore.getDatabaseAccess(), |
43 | 41 | new PropertyStoreSchema(conceptStore.getCorpus(), |
44 | 42 | conceptStore.getDatabaseAccess().getConnection(), |
45 | 43 | tweaks, true), |
46 | 44 | conceptStore.idManager, |
47 | 45 | tweaks, |
48 | 46 | conceptStore.getAgenda()); |
| 47 | + |
| 48 | + database.setBackgroundErrorHandler(conceptStore.getDatabaseAccess().getBackgroundErrorHandler()); |
49 | 49 | } |
50 | 50 | |
51 | 51 | protected DatabasePropertyStoreBuilder(LocalConceptStoreSchema conceptStoreSchema, PropertyStoreSchema database, PersistentIdManager idManager, TweakSet tweaks, Agenda agenda) throws SQLException, PersistenceException { |
Index: trunk/WikiWord/WikiWordBuilder/src/main/java/de/brightbyte/wikiword/store/builder/DatabaseWikiWordStoreBuilder.java |
— | — | @@ -19,6 +19,7 @@ |
20 | 20 | import de.brightbyte.db.ReferenceField; |
21 | 21 | import de.brightbyte.db.RelationTable; |
22 | 22 | import de.brightbyte.db.StatementBasedInserter; |
| 23 | +import de.brightbyte.util.ErrorHandler; |
23 | 24 | import de.brightbyte.util.PersistenceException; |
24 | 25 | import de.brightbyte.util.StringUtils; |
25 | 26 | import de.brightbyte.wikiword.TweakSet; |
— | — | @@ -64,6 +65,14 @@ |
65 | 66 | warningInserter.disableAutomaticField(); |
66 | 67 | } |
67 | 68 | |
| 69 | + public void setBackgroundErrorHandler(ErrorHandler<Runnable, Throwable, Error> handler) { |
| 70 | + database.setBackgroundErrorHandler(handler); |
| 71 | + } |
| 72 | + |
| 73 | + public ErrorHandler<Runnable, Throwable, Error> getBackgroundErrorHandler() { |
| 74 | + return database.getBackgroundErrorHandler(); |
| 75 | + } |
| 76 | + |
68 | 77 | protected Inserter configureTable(String name, int bufferLength, int bufferWidth) throws SQLException { |
69 | 78 | DatabaseTable t = database.getTable(name); |
70 | 79 | return configureTable(t, bufferLength, bufferWidth); |
Index: trunk/WikiWord/WikiWordBuilder/src/main/java/de/brightbyte/wikiword/processor/XmlDumpDriver.java |
— | — | @@ -17,6 +17,7 @@ |
18 | 18 | |
19 | 19 | import de.brightbyte.io.LeveledOutput; |
20 | 20 | import de.brightbyte.job.BlockingJobQueue; |
| 21 | +import de.brightbyte.util.ErrorHandler; |
21 | 22 | import de.brightbyte.util.PersistenceException; |
22 | 23 | import de.brightbyte.wikiword.Namespace; |
23 | 24 | import de.brightbyte.wikiword.NamespaceSet; |
— | — | @@ -33,6 +34,7 @@ |
34 | 35 | protected InputStream in; |
35 | 36 | protected TweakSet tweaks; |
36 | 37 | protected LeveledOutput log; |
| 38 | + protected ErrorHandler<XmlDumpDriver, Throwable, RuntimeException> errorHandler; |
37 | 39 | |
38 | 40 | protected class Sink implements DumpWriter { |
39 | 41 | |
— | — | @@ -145,9 +147,8 @@ |
146 | 148 | try { |
147 | 149 | importPage(p, r); |
148 | 150 | } catch (Throwable e) { |
149 | | - log.error("exception while processing page `"+p.Title.toString()+"` (id="+p.Id+", rev="+r.Id+", date="+r.Timestamp.getTime()+")", e); |
150 | | - error = e; |
151 | 151 | executor.shutdownNow(); |
| 152 | + handleImportError("exception while processing page `"+p.Title.toString()+"` (id="+p.Id+", rev="+r.Id+", date="+r.Timestamp.getTime()+")", e); |
152 | 153 | |
153 | 154 | if (e instanceof Error) throw (Error)e; |
154 | 155 | } |
— | — | @@ -197,24 +198,29 @@ |
198 | 199 | importer.handlePage(page.Id, page.Title.Namespace, page.Title.Text, revision.Text, revision.Timestamp.getTime()); |
199 | 200 | } |
200 | 201 | |
| 202 | + protected void handleImportError(String message, Throwable e) { |
| 203 | + error = e; |
| 204 | + if (errorHandler!=null) errorHandler.handleError(XmlDumpDriver.this, message, e); |
| 205 | + else log.error(message, e); |
| 206 | + } |
201 | 207 | } |
202 | 208 | |
203 | | - public XmlDumpDriver(URL dump, InputFileHelper inputHelper, LeveledOutput log, TweakSet tweaks) { |
| 209 | + public XmlDumpDriver(URL dump, InputFileHelper inputHelper, LeveledOutput log, ErrorHandler<XmlDumpDriver, Throwable, RuntimeException> errorHandler, TweakSet tweaks) { |
204 | 210 | if (dump==null) throw new NullPointerException(); |
205 | 211 | this.dump= dump; |
206 | | - init(inputHelper, log, tweaks); |
| 212 | + init(inputHelper, log, errorHandler, tweaks); |
207 | 213 | } |
208 | 214 | |
209 | | - public XmlDumpDriver(InputStream in, LeveledOutput log, TweakSet tweaks) { |
| 215 | + public XmlDumpDriver(InputStream in, LeveledOutput log, ErrorHandler<XmlDumpDriver, Throwable, RuntimeException> errorHandler, TweakSet tweaks) { |
210 | 216 | if (in==null) throw new NullPointerException(); |
211 | 217 | this.in= in; |
212 | | - init(null, log, tweaks); |
| 218 | + init(null, log, errorHandler, tweaks); |
213 | 219 | } |
214 | 220 | |
215 | 221 | private int importQueueCapacity = 0; |
216 | 222 | private InputFileHelper inputHelper; |
217 | 223 | |
218 | | - private void init(InputFileHelper inputHelper, LeveledOutput log, TweakSet tweaks) { |
| 224 | + private void init(InputFileHelper inputHelper, LeveledOutput log, ErrorHandler<XmlDumpDriver, Throwable, RuntimeException> errorHandler, TweakSet tweaks) { |
219 | 225 | if (log==null) throw new NullPointerException(); |
220 | 226 | if (tweaks==null) throw new NullPointerException(); |
221 | 227 | if (inputHelper==null && in==null) throw new NullPointerException(); |
— | — | @@ -222,6 +228,7 @@ |
223 | 229 | this.tweaks = tweaks; |
224 | 230 | this.log = log; |
225 | 231 | this.inputHelper = inputHelper; |
| 232 | + this.errorHandler = errorHandler; |
226 | 233 | |
227 | 234 | importQueueCapacity = tweaks.getTweak("dumpdriver.pageImportQueue", 8); |
228 | 235 | } |
— | — | @@ -243,4 +250,5 @@ |
244 | 251 | sink.close(); //NOTE: make sure the executor queue is terminated |
245 | 252 | } |
246 | 253 | } |
| 254 | + |
247 | 255 | } |
Index: trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/CliApp.java |
— | — | @@ -16,6 +16,7 @@ |
17 | 17 | import de.brightbyte.io.LeveledOutput; |
18 | 18 | import de.brightbyte.io.LogOutput; |
19 | 19 | import de.brightbyte.io.Output; |
| 20 | +import de.brightbyte.util.ErrorHandler; |
20 | 21 | import de.brightbyte.util.PersistenceException; |
21 | 22 | import de.brightbyte.util.SystemUtils; |
22 | 23 | import de.brightbyte.wikiword.rdf.WikiWordIdentifiers; |
— | — | @@ -25,6 +26,20 @@ |
26 | 27 | */ |
27 | 28 | public abstract class CliApp { |
28 | 29 | |
| 30 | + public class FatalBackgroundErrorHandler<T, X extends Throwable, Y extends Throwable> implements |
| 31 | + ErrorHandler<T, X, Y> { |
| 32 | + |
| 33 | + public void handleError(T context, String message, X error) throws Y { |
| 34 | + String m = message; |
| 35 | + if (context!=null) m = m + " ("+context+")"; |
| 36 | + |
| 37 | + out.error(m, error); |
| 38 | + |
| 39 | + terminate(); |
| 40 | + } |
| 41 | + |
| 42 | + } |
| 43 | + |
29 | 44 | public static final String VERSION_INFO = "WikiWord by Daniel Kinzler, brightbyte.de, 2007-2009"; |
30 | 45 | public static final String LICENSE_INFO = "Originally created at the University of Leipzig,\n\tdevelopment supported by Wikimedia Deutschland.\n\tFree Software, GNU LGPL. See COPYING for details."; |
31 | 46 | |
— | — | @@ -415,4 +430,8 @@ |
416 | 431 | return exitCode; |
417 | 432 | } |
418 | 433 | |
| 434 | + protected void terminate() { |
| 435 | + info("exiting application"); |
| 436 | + exit(55); |
| 437 | + } |
419 | 438 | } |
Index: trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/StoreBackedApp.java |
— | — | @@ -185,4 +185,31 @@ |
186 | 186 | } |
187 | 187 | } |
188 | 188 | |
| 189 | + protected void terminate() { |
| 190 | + info("terminating application"); |
| 191 | + |
| 192 | + //XXX: note: flushing first would be nice, but |
| 193 | + // can deadlock, especially when called from a worker of the database's background flush queue! |
| 194 | + // would need to detect that. |
| 195 | + /* |
| 196 | + try { |
| 197 | + closeStores(true); |
| 198 | + } catch (Exception ex) { |
| 199 | + error("failed to flush stores", ex); |
| 200 | + try { |
| 201 | + closeStores(false); |
| 202 | + } catch (Exception exx) { |
| 203 | + error("failed to close stores", exx); |
| 204 | + } |
| 205 | + } */ |
| 206 | + |
| 207 | + try { |
| 208 | + closeStores(false); |
| 209 | + } catch (Exception exx) { |
| 210 | + error("failed to close stores", exx); |
| 211 | + } |
| 212 | + |
| 213 | + super.terminate(); |
| 214 | + } |
| 215 | + |
189 | 216 | } |