~berthold-daum/zora/trunk

« back to all changes in this revision

Viewing changes to com.bdaum.zoom.db/src/com/bdaum/zoom/db/internal/DbManager.java

  • Committer: bdaum
  • Date: 2015-12-26 10:21:51 UTC
  • Revision ID: berthold.daum@bdaum.de-20151226102151-44f1j5113167thb9
VersionĀ 2.4.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
267
267
 
268
268
        private Set<String> previousLocationKeys = new HashSet<String>();
269
269
 
 
270
        private boolean emergency;
 
271
 
270
272
        /**
271
273
         * Constructor
272
274
         *
601
603
        }
602
604
 
603
605
        private void fatalError(String msg) {
604
 
                factory.getErrorHandler().fatalError(Messages.DbManager_Catalog_error,
605
 
                                msg, this);
 
606
                if (!emergency)
 
607
                        factory.getErrorHandler().fatalError(
 
608
                                        Messages.DbManager_Catalog_error, msg, this);
606
609
        }
607
610
 
608
611
        public ObjectContainer getDatabase() {
634
637
         * @see com.bdaum.zoom.core.IDbManager#obtainMeta()
635
638
         */
636
639
        private Meta obtainMeta() {
637
 
                List<MetaImpl> resultSet = obtainObjects(MetaImpl.class);
638
 
                if (resultSet.isEmpty())
639
 
                        return null;
640
 
                MetaImpl metaImpl = resultSet.get(0);
641
 
                if (metaImpl.getPlatform() == null)
642
 
                        metaImpl.setPlatform(Platform.getOS());
643
 
                return metaImpl;
 
640
                Iterator<MetaImpl> it = obtainObjects(MetaImpl.class).iterator();
 
641
                if (it.hasNext()) {
 
642
                        MetaImpl metaImpl = it.next();
 
643
                        if (metaImpl.getPlatform() == null)
 
644
                                metaImpl.setPlatform(Platform.getOS());
 
645
                        return metaImpl;
 
646
                }
 
647
                return null;
644
648
        }
645
649
 
646
650
        protected Meta createMeta() {
681
685
                                Query query = db.query();
682
686
                                query.constrain(clazz);
683
687
                                query.descend(Constants.OID).constrain(id);
684
 
                                ObjectSet<T> set = query.execute();
 
688
                                Iterator<T> iterator = query.<T> execute().iterator();
685
689
                                dbErrorCounter = 0;
686
 
                                return (set.isEmpty()) ? null : set.get(0);
 
690
                                return iterator.hasNext() ? iterator.next() : null;
687
691
                        } catch (DatabaseClosedException e) {
688
692
                                break;
689
693
                        } catch (IllegalStateException e) {
1238
1242
 
1239
1243
        public void reconnectToDb(RuntimeException e) {
1240
1244
                // Reset lucene
1241
 
                if (++dbErrorCounter > 100)
 
1245
                if (++dbErrorCounter > 100 || emergency)
1242
1246
                        throw e;
1243
1247
                removeLuceneWriteLock();
1244
1248
                while (!file.exists())
1356
1360
        }
1357
1361
 
1358
1362
        private void reconnectTrashcanToDb(RuntimeException e) {
1359
 
                if (++dbErrorCounter > 100)
 
1363
                if (++dbErrorCounter > 100 || emergency)
1360
1364
                        throw e;
1361
1365
                String trashcanName = getTrashcanName();
1362
1366
                File f = new File(trashcanName);
1434
1438
                                        // ignore
1435
1439
                                }
1436
1440
                        }
 
1441
                else if (mode == CatalogListener.EMERGENCY)
 
1442
                        emergency = true;
1437
1443
                previousDay = -1L;
1438
1444
                previousTimeline = Meta_type.timeline_no;
1439
1445
                previousLocationKeys.clear();
1440
1446
                lastFolderUris.clear();
 
1447
 
1441
1448
                if (db != null) {
1442
 
                        try {
1443
 
                                if (meta != null) {
1444
 
                                        meta.setLastSessionEnd(new Date());
1445
 
                                        storeAndCommit(meta);
 
1449
                        if (!emergency) // db4o has its own shutdown hook
 
1450
                                try {
 
1451
                                        db.close();
 
1452
                                } catch (Db4oIOException e) {
 
1453
                                        // ignore
 
1454
                                } catch (IllegalStateException e) {
 
1455
                                        // ignore
1446
1456
                                }
1447
 
                                db.close();
1448
 
                        } catch (Db4oIOException e) {
1449
 
                                // ignore
1450
 
                        } catch (IllegalStateException e) {
1451
 
                                // ignore
1452
 
                        }
1453
1457
                        db = null;
1454
1458
                        meta = null;
1455
1459
                        dirtyCollections.clear();
1457
1461
                }
1458
1462
                for (Object listener : factory.getListeners())
1459
1463
                        try {
1460
 
                                ((IDbListener) listener).databaseClosed(this);
 
1464
                                ((IDbListener) listener).databaseClosed(this, mode);
1461
1465
                        } catch (Exception e) {
1462
1466
                                // ignore
1463
1467
                        }
1580
1584
                SmartCollectionImpl coll1 = obtainById(SmartCollectionImpl.class, key);
1581
1585
                if (coll1 == null) {
1582
1586
                        coll1 = new SmartCollectionImpl(name, true, false, false, false,
1583
 
                                        null, 0, null, 0, null);
 
1587
                                        null, 0, null, 0, null, null);
1584
1588
                        coll1.setStringId(key);
1585
1589
                        Criterion crit = new CriterionImpl(fieldname, null, fieldvalue,
1586
1590
                                        rel, false);
1649
1653
                SmartCollectionImpl newcoll = new SmartCollectionImpl(
1650
1654
                                cumulate ? Messages.DbManager_recent_bg_imports
1651
1655
                                                : Messages.DbManager_last_import, true, false, false,
1652
 
                                false, description, 0, null, 0, null);
 
1656
                                false, description, 0, null, 0, null, null);
1653
1657
                newcoll.setStringId(Constants.LAST_IMPORT_ID);
1654
1658
                Criterion criterion = new CriterionImpl(QueryField.IMPORTDATE.getKey(),
1655
1659
                                null, "", //$NON-NLS-1$
1841
1845
                SmartCollectionImpl coll = obtainById(SmartCollectionImpl.class, id);
1842
1846
                if (coll == null) {
1843
1847
                        coll = new SmartCollectionImpl(name, true, false, false, false,
1844
 
                                        null, 0, null, 0, null);
 
1848
                                        null, 0, null, 0, null, null);
1845
1849
                        coll.setStringId(id);
1846
1850
                        Criterion exifCrit = new CriterionImpl(
1847
1851
                                        QueryField.IPTC_DATECREATED.getKey(), null, new Range(
2023
2027
                SmartCollectionImpl coll = obtainById(SmartCollectionImpl.class, id);
2024
2028
                if (coll == null) {
2025
2029
                        coll = new SmartCollectionImpl(name, true, false, false, false,
2026
 
                                        null, 0, null, 0, null);
 
2030
                                        null, 0, null, 0, null, null);
2027
2031
                        coll.setStringId(id);
2028
2032
                        for (Criterion criterion : criteria)
2029
2033
                                coll.addCriterion(criterion);
2057
2061
                // MessageDialog.openInformation(null, "", systemInfo.freespaceSize()
2058
2062
                // + ", " + systemInfo.totalSize() + "; "
2059
2063
                // + systemInfo.freespaceEntryCount());
2060
 
                try {
2061
 
                        if (force || needsDefragmentation()) {
2062
 
                                Meta meta1 = getMeta(false);
2063
 
                                boolean hasBackups = meta1 == null
2064
 
                                                || meta1.getBackupLocation() != null
2065
 
                                                && meta1.getBackupLocation().length() > 0;
2066
 
                                if (force
2067
 
                                                || hasBackups
2068
 
                                                || factory
2069
 
                                                                .getErrorHandler()
2070
 
                                                                .question(
2071
 
                                                                                Messages.DbManager_Catalog_maintenance,
2072
 
                                                                                Messages.DbManager_The_cat_seems_to_be_fragmented,
2073
 
                                                                                this)) {
2074
 
                                        final String backupPath = fileName + ".defrag"; //$NON-NLS-1$
2075
 
                                        ProgressMonitorDialog dialog = new ProgressMonitorDialog(
2076
 
                                                        null);
2077
 
                                        try {
2078
 
                                                dialog.run(true, false, new IRunnableWithProgress() {
2079
 
 
2080
 
                                                        public void run(IProgressMonitor monitor)
2081
 
                                                                        throws InvocationTargetException,
2082
 
                                                                        InterruptedException {
2083
 
                                                                try {
2084
 
                                                                        monitor.beginTask(NLS.bind(
2085
 
                                                                                        Messages.DbManager_Defragmenting_,
2086
 
                                                                                        fileName), IProgressMonitor.UNKNOWN);
2087
 
                                                                        if (!force) {
2088
 
                                                                                monitor.subTask(Messages.DbManager_backing_up_cat);
2089
 
                                                                                performBackup(0L, -1L, true);
2090
 
                                                                        }
2091
 
                                                                        db.close();
2092
 
                                                                        db = null;
2093
 
                                                                        monitor.subTask(Messages.DbManager_defragmenting_cat);
2094
 
 
2095
 
                                                                        DefragmentConfig config = new DefragmentConfig(
2096
 
                                                                                        fileName, backupPath);
2097
 
                                                                        config.objectCommitFrequency(1000);
2098
 
                                                                        config.forceBackupDelete(true);
2099
 
                                                                        boolean fileNeedsUpgrade = config
2100
 
                                                                                        .fileNeedsUpgrade();
2101
 
                                                                        EmbeddedConfiguration ef = createDatabaseConfiguration(
2102
 
                                                                                        fileNeedsUpgrade, fileName);
2103
 
                                                                        config.db4oConfig(ef);
2104
 
                                                                        try {
2105
 
                                                                                Defragment.defrag(config);
2106
 
                                                                        } catch (Exception e) {
2107
 
                                                                                File target = new File(fileName);
2108
 
                                                                                target.delete();
2109
 
                                                                                new File(backupPath).renameTo(target);
2110
 
                                                                                throw new InvocationTargetException(e);
2111
 
                                                                        }
2112
 
                                                                        if (fileNeedsUpgrade) {
2113
 
                                                                                monitor.subTask(Messages.DbManager_updating_database_version);
2114
 
                                                                                db = Db4oEmbedded
2115
 
                                                                                                .openFile(ef, fileName);
2116
 
                                                                                db.close();
2117
 
                                                                                db = null;
2118
 
                                                                                DbActivator
2119
 
                                                                                                .getDefault()
2120
 
                                                                                                .logInfo(
 
2064
                if (!emergency)
 
2065
                        try {
 
2066
                                if (force || needsDefragmentation()) {
 
2067
                                        Meta meta1 = getMeta(false);
 
2068
                                        boolean hasBackups = meta1 == null
 
2069
                                                        || meta1.getBackupLocation() != null
 
2070
                                                        && meta1.getBackupLocation().length() > 0;
 
2071
                                        if (force
 
2072
                                                        || hasBackups
 
2073
                                                        || factory
 
2074
                                                                        .getErrorHandler()
 
2075
                                                                        .question(
 
2076
                                                                                        Messages.DbManager_Catalog_maintenance,
 
2077
                                                                                        Messages.DbManager_The_cat_seems_to_be_fragmented,
 
2078
                                                                                        this)) {
 
2079
                                                final String backupPath = fileName + ".defrag"; //$NON-NLS-1$
 
2080
                                                ProgressMonitorDialog dialog = new ProgressMonitorDialog(
 
2081
                                                                null);
 
2082
                                                try {
 
2083
                                                        dialog.run(true, false,
 
2084
                                                                        new IRunnableWithProgress() {
 
2085
 
 
2086
                                                                                public void run(IProgressMonitor monitor)
 
2087
                                                                                                throws InvocationTargetException,
 
2088
                                                                                                InterruptedException {
 
2089
                                                                                        try {
 
2090
                                                                                                monitor.beginTask(
2121
2091
                                                                                                                NLS.bind(
2122
 
                                                                                                                                Messages.DbManager_database_converted_to_version_n,
2123
 
                                                                                                                                Db4o.version()));
2124
 
                                                                        }
2125
 
                                                                } finally {
2126
 
                                                                        if (db == null)
2127
 
                                                                                db = createDatabase(fileName);
2128
 
                                                                }
 
2092
                                                                                                                                Messages.DbManager_Defragmenting_,
 
2093
                                                                                                                                fileName),
 
2094
                                                                                                                IProgressMonitor.UNKNOWN);
 
2095
                                                                                                if (!force) {
 
2096
                                                                                                        monitor.subTask(Messages.DbManager_backing_up_cat);
 
2097
                                                                                                        performBackup(0L, -1L, true);
 
2098
                                                                                                }
 
2099
                                                                                                db.close();
 
2100
                                                                                                db = null;
 
2101
                                                                                                monitor.subTask(Messages.DbManager_defragmenting_cat);
 
2102
 
 
2103
                                                                                                DefragmentConfig config = new DefragmentConfig(
 
2104
                                                                                                                fileName, backupPath);
 
2105
                                                                                                config.objectCommitFrequency(1000);
 
2106
                                                                                                config.forceBackupDelete(true);
 
2107
                                                                                                boolean fileNeedsUpgrade = config
 
2108
                                                                                                                .fileNeedsUpgrade();
 
2109
                                                                                                EmbeddedConfiguration ef = createDatabaseConfiguration(
 
2110
                                                                                                                fileNeedsUpgrade,
 
2111
                                                                                                                fileName);
 
2112
                                                                                                config.db4oConfig(ef);
 
2113
                                                                                                try {
 
2114
                                                                                                        Defragment.defrag(config);
 
2115
                                                                                                } catch (Exception e) {
 
2116
                                                                                                        File target = new File(
 
2117
                                                                                                                        fileName);
 
2118
                                                                                                        target.delete();
 
2119
                                                                                                        new File(backupPath)
 
2120
                                                                                                                        .renameTo(target);
 
2121
                                                                                                        throw new InvocationTargetException(
 
2122
                                                                                                                        e);
 
2123
                                                                                                }
 
2124
                                                                                                if (fileNeedsUpgrade) {
 
2125
                                                                                                        monitor.subTask(Messages.DbManager_updating_database_version);
 
2126
                                                                                                        db = Db4oEmbedded.openFile(
 
2127
                                                                                                                        ef, fileName);
 
2128
                                                                                                        db.close();
 
2129
                                                                                                        db = null;
 
2130
                                                                                                        DbActivator
 
2131
                                                                                                                        .getDefault()
 
2132
                                                                                                                        .logInfo(
 
2133
                                                                                                                                        NLS.bind(
 
2134
                                                                                                                                                        Messages.DbManager_database_converted_to_version_n,
 
2135
                                                                                                                                                        Db4o.version()));
 
2136
                                                                                                }
 
2137
                                                                                        } finally {
 
2138
                                                                                                if (db == null)
 
2139
                                                                                                        db = createDatabase(fileName);
 
2140
                                                                                        }
 
2141
                                                                                }
 
2142
                                                                        });
 
2143
                                                } catch (InvocationTargetException e1) {
 
2144
                                                        factory.getErrorHandler().showError(
 
2145
                                                                        Messages.DbManager_Defrag_error,
 
2146
                                                                        NLS.bind(Messages.DbManager_Defrag_failed,
 
2147
                                                                                        e1.getCause()), this);
 
2148
                                                } catch (InterruptedException e1) {
 
2149
                                                        // should never happen
 
2150
                                                } finally {
 
2151
                                                        File backup = new File(backupPath);
 
2152
                                                        if (!file.exists()) {
 
2153
                                                                if (backup.exists())
 
2154
                                                                        backup.renameTo(file);
 
2155
                                                                DbActivator
 
2156
                                                                                .getDefault()
 
2157
                                                                                .logError(
 
2158
                                                                                                Messages.DbManager_defragmentation_failed,
 
2159
                                                                                                null);
 
2160
                                                        } else {
 
2161
                                                                backup.delete();
 
2162
                                                                DbActivator
 
2163
                                                                                .getDefault()
 
2164
                                                                                .logInfo(
 
2165
                                                                                                Messages.DbManager_defragmentation_successfiul);
2129
2166
                                                        }
2130
 
                                                });
2131
 
                                        } catch (InvocationTargetException e1) {
2132
 
                                                factory.getErrorHandler().showError(
2133
 
                                                                Messages.DbManager_Defrag_error,
2134
 
                                                                NLS.bind(Messages.DbManager_Defrag_failed,
2135
 
                                                                                e1.getCause()), this);
2136
 
                                        } catch (InterruptedException e1) {
2137
 
                                                // should never happen
2138
 
                                        } finally {
2139
 
                                                File backup = new File(backupPath);
2140
 
                                                if (!file.exists()) {
2141
 
                                                        if (backup.exists())
2142
 
                                                                backup.renameTo(file);
2143
 
                                                        DbActivator.getDefault().logError(
2144
 
                                                                        Messages.DbManager_defragmentation_failed,
2145
 
                                                                        null);
2146
 
                                                } else {
2147
 
                                                        backup.delete();
2148
 
                                                        DbActivator
2149
 
                                                                        .getDefault()
2150
 
                                                                        .logInfo(
2151
 
                                                                                        Messages.DbManager_defragmentation_successfiul);
2152
2167
                                                }
2153
2168
                                        }
2154
2169
                                }
 
2170
                        } catch (Throwable e) {
 
2171
                                DbActivator.getDefault().logError(
 
2172
                                                Messages.DbManager_error_checking_sanity, e);
2155
2173
                        }
2156
 
                } catch (Throwable e) {
2157
 
                        DbActivator.getDefault().logError(
2158
 
                                        Messages.DbManager_error_checking_sanity, e);
2159
 
                }
2160
2174
        }
2161
2175
 
2162
2176
        public boolean needsDefragmentation() {
2202
2216
         */
2203
2217
 
2204
2218
        public void markSystemCollectionsForPurge(Asset asset) {
2205
 
                if (beginSafeTransactionWithReport()) {
 
2219
                getMeta(true);
 
2220
                boolean cleaned = meta.getCleaned();
 
2221
                if (!cleaned || beginSafeTransactionWithReport()) {
2206
2222
                        try {
2207
2223
                                boolean notEmpty = hasDirtyCollection();
2208
2224
                                boolean added = false;
2262
2278
                                if (importDate != null)
2263
2279
                                        added |= addDirtyCollection(IMPORTKEY
2264
2280
                                                        + Constants.DFIMPORT.format(importDate));
2265
 
                                if (added && !notEmpty) {
2266
 
                                        Meta meta1 = getMeta(true);
2267
 
                                        meta1.setCleaned(false);
2268
 
                                        storeAndCommit(meta1);
 
2281
                                if (added && !notEmpty && cleaned) {
 
2282
                                        meta.setCleaned(false);
 
2283
                                        storeAndCommit(meta);
2269
2284
                                }
2270
2285
                        } catch (Exception e) {
2271
2286
                                rollback();
2272
2287
                                DbActivator.getDefault().logError(
2273
2288
                                                Messages.DbManager_internal_error_cleaning, e);
2274
2289
                        } finally {
2275
 
                                endSafeTransaction();
 
2290
                                if (cleaned)
 
2291
                                        endSafeTransaction();
2276
2292
                        }
2277
2293
                }
2278
2294
        }
2297
2313
        public boolean pruneSystemCollection(final SmartCollectionImpl sm) {
2298
2314
                if (readOnly)
2299
2315
                        return false;
2300
 
                if (sm.getCriterion() != null
2301
 
                                && !sm.getCriterion().isEmpty()
 
2316
                if (sm.getCriterion() != null && !sm.getCriterion().isEmpty()
2302
2317
                                && sm.getCriterion().get(0) != null
2303
 
                                && !createCollectionProcessor(sm, null, null).select(false)
2304
 
                                                .isEmpty())
 
2318
                                && !createCollectionProcessor(sm, null, null).isEmpty())
2305
2319
                        return false;
2306
2320
                if (beginSafeTransactionWithReport()) {
2307
2321
                        try {
2334
2348
 
2335
2349
        public void pruneEmptySystemCollections(IProgressMonitor monitor) {
2336
2350
                synchronized (dirtyCollections) {
 
2351
                        // long time = System.currentTimeMillis();
2337
2352
                        if (!readOnly && hasDirtyCollection()) {
2338
2353
                                Group importGroup = getImportGroup();
2339
2354
                                List<Group> subgroups = importGroup.getSubgroup();
2345
2360
                                int maxImports = factory.getMaxImports() - 1;
2346
2361
                                int work = dirtyCollections.size() + 1 + imports;
2347
2362
                                monitor.beginTask(Messages.DbManager_pruning_empty, work);
2348
 
                                List<String> sorted = new LinkedList<String>(dirtyCollections);
 
2363
                                LinkedList<String> sorted = new LinkedList<String>(
 
2364
                                                dirtyCollections);
2349
2365
                                Collections.sort(sorted, new Comparator<String>() {
2350
2366
                                        public int compare(String o1, String o2) {
2351
2367
                                                return (o1.length() == o2.length() ? 0
2355
2371
                                monitor.worked(1);
2356
2372
                                if (db != null) {
2357
2373
                                        while (!sorted.isEmpty()) {
2358
 
                                                String[] todo = sorted
2359
 
                                                                .toArray(new String[sorted.size()]);
2360
 
                                                for (String id : todo) {
2361
 
                                                        if (id.startsWith(IDbManager.IMPORTKEY)) {
2362
 
                                                                sorted.remove(id);
 
2374
                                                String id = sorted.poll();
 
2375
                                                monitor.worked(1);
 
2376
                                                if (id.startsWith(IDbManager.IMPORTKEY))
 
2377
                                                        continue;
 
2378
                                                SmartCollectionImpl sm = obtainById(
 
2379
                                                                SmartCollectionImpl.class, id);
 
2380
                                                if (sm == null || pruneSystemCollection(sm))
 
2381
                                                        continue;
 
2382
                                                Iterator<String> it = sorted.iterator();
 
2383
                                                while (it.hasNext()) {
 
2384
                                                        String next = it.next();
 
2385
                                                        if (id.startsWith(next)) {
 
2386
                                                                it.remove();
2363
2387
                                                                monitor.worked(1);
2364
 
                                                                continue;
2365
2388
                                                        }
2366
 
                                                        SmartCollectionImpl sm = obtainById(
2367
 
                                                                        SmartCollectionImpl.class, id);
2368
 
                                                        if (sm != null) {
2369
 
                                                                if (pruneSystemCollection(sm)) {
2370
 
                                                                        sorted.remove(id);
2371
 
                                                                        monitor.worked(1);
2372
 
                                                                } else {
2373
 
                                                                        Iterator<String> it = sorted.iterator();
2374
 
                                                                        while (it.hasNext()) {
2375
 
                                                                                String cand = it.next();
2376
 
                                                                                if (id.startsWith(cand)) {
2377
 
                                                                                        it.remove();
2378
 
                                                                                        monitor.worked(1);
2379
 
                                                                                } else
2380
 
                                                                                        break;
2381
 
                                                                        }
2382
 
                                                                        break;
2383
 
                                                                }
2384
 
                                                        } else if (sorted.remove(id))
2385
 
                                                                monitor.worked(1);
2386
2389
                                                }
2387
2390
                                        }
2388
2391
                                        importIds.remove(Constants.LAST_IMPORT_ID);
2392
2395
                                                SmartCollectionImpl sm = obtainById(
2393
2396
                                                                SmartCollectionImpl.class, id);
2394
2397
                                                if (sm != null && sm.getSubSelection().isEmpty()) {
2395
 
                                                        if (i < maxImports && !Utilities.isEmpty(this, sm)) {
 
2398
                                                        if (i < maxImports
 
2399
                                                                        && !Utilities.isImportEmpty(this, sm)) {
2396
2400
                                                                monitor.worked(1);
2397
2401
                                                                i++;
2398
2402
                                                                continue;
2435
2439
                                }
2436
2440
                                monitor.done();
2437
2441
                        }
 
2442
                        // System.out.println(System.currentTimeMillis() - time);
2438
2443
                }
2439
2444
        }
2440
2445
 
2746
2751
        }
2747
2752
 
2748
2753
        private void connectionLostWarning() {
2749
 
                factory.getErrorHandler().connectionLostWarning(
2750
 
                                Messages.DbManager_lost_connection,
2751
 
                                Messages.DbManager_operation_was_aborted, this);
 
2754
                if (!emergency)
 
2755
                        factory.getErrorHandler().connectionLostWarning(
 
2756
                                        Messages.DbManager_lost_connection,
 
2757
                                        Messages.DbManager_operation_was_aborted, this);
2752
2758
        }
2753
2759
 
2754
2760
        public void backup(String filename) {