private static void setCurrentVersion() { myRecords.putInt(HEADER_VERSION_OFFSET, VERSION); myRecords.putLong(HEADER_TIMESTAMP_OFFSET, System.currentTimeMillis()); myAttributes.setVersion(VERSION); myContents.setVersion(VERSION); myRecords.putInt(HEADER_CONNECTION_STATUS_OFFSET, SAFELY_CLOSED_MAGIC); }
private static void markClean() { if (myDirty) { myDirty = false; myRecords.putInt( HEADER_CONNECTION_STATUS_OFFSET, myCorrupted ? CORRUPTED_MAGIC : SAFELY_CLOSED_MAGIC); } }
private static void closeFiles() throws IOException { if (myFlushingFuture != null) { myFlushingFuture.cancel(false); myFlushingFuture = null; } if (myNames != null) { myNames.close(); myNames = null; } if (myAttributes != null) { Disposer.dispose(myAttributes); myAttributes = null; } if (myContents != null) { Disposer.dispose(myContents); myContents = null; } if (myRecords != null) { markClean(); myRecords.close(); myRecords = null; } ourInitialized = false; }
private static int getVersion() { final int recordsVersion = myRecords.getInt(HEADER_VERSION_OFFSET); if (myAttributes.getVersion() != recordsVersion || myContents.getVersion() != recordsVersion) return -1; return recordsVersion; }
public static boolean isDirty() { return myDirty || myNames.isDirty() || myAttributes.isDirty() || myContents.isDirty() || myRecords.isDirty(); }
public static void force() { try { w.lock(); if (myRecords != null) { markClean(); } if (myNames != null) { myNames.force(); myAttributes.force(); myContents.force(); myRecords.force(); } } finally { w.unlock(); } }
public static void flushSome() { if (!isDirty() || HeavyProcessLatch.INSTANCE.isRunning()) return; try { w.lock(); if (myFlushingFuture == null) { return; // avoid NPE when close has already taken place } myNames.force(); final boolean attribsFlushed = myAttributes.flushSome(); final boolean contentsFlushed = myContents.flushSome(); if (attribsFlushed && contentsFlushed) { markClean(); myRecords.force(); } } finally { w.unlock(); } }
public static void cleanRecord(final int id) { myRecords.put(id * RECORD_SIZE, ZEROES, 0, RECORD_SIZE); }
public static long getTimestamp() { return myRecords.getLong(HEADER_TIMESTAMP_OFFSET); }
private static void markDirty() { if (!myDirty) { myDirty = true; myRecords.putInt(HEADER_CONNECTION_STATUS_OFFSET, CONNECTED_MAGIC); } }
private static void init() { final File basePath = basePath(); basePath.mkdirs(); final File namesFile = new File(basePath, "names.dat"); final File attributesFile = new File(basePath, "attrib.dat"); final File contentsFile = new File(basePath, "content.dat"); final File recordsFile = new File(basePath, "records.dat"); if (!namesFile.exists()) { invalidateIndex(); } try { if (getCorruptionMarkerFile().exists()) { invalidateIndex(); throw new IOException("Corruption marker file found"); } PagedFileStorage.StorageLockContext storageLockContext = new PagedFileStorage.StorageLock(false).myDefaultStorageLockContext; myNames = new PersistentStringEnumerator(namesFile, storageLockContext); myAttributes = new Storage(attributesFile.getCanonicalPath(), REASONABLY_SMALL); myContents = new RefCountingStorage( contentsFile.getCanonicalPath(), CapacityAllocationPolicy .FIVE_PERCENT_FOR_GROWTH); // sources usually zipped with 4x ratio boolean aligned = PagedFileStorage.BUFFER_SIZE % RECORD_SIZE == 0; assert aligned; // for performance myRecords = new ResizeableMappedFile( recordsFile, 20 * 1024, storageLockContext, PagedFileStorage.BUFFER_SIZE, aligned); if (myRecords.length() == 0) { cleanRecord(0); // Clean header cleanRecord(1); // Create root record setCurrentVersion(); } if (getVersion() != VERSION) { throw new IOException("FS repository version mismatch"); } if (myRecords.getInt(HEADER_CONNECTION_STATUS_OFFSET) != SAFELY_CLOSED_MAGIC) { throw new IOException("FS repository wasn't safely shut down"); } markDirty(); scanFreeRecords(); } catch (Exception e) { // IOException, IllegalArgumentException LOG.info( "Filesystem storage is corrupted or does not exist. [Re]Building. Reason: " + e.getMessage()); try { closeFiles(); boolean deleted = FileUtil.delete(getCorruptionMarkerFile()); deleted &= deleteWithSubordinates(namesFile); deleted &= AbstractStorage.deleteFiles(attributesFile.getCanonicalPath()); deleted &= AbstractStorage.deleteFiles(contentsFile.getCanonicalPath()); deleted &= deleteWithSubordinates(recordsFile); if (!deleted) { throw new IOException("Cannot delete filesystem storage files"); } } catch (final IOException e1) { final Runnable warnAndShutdown = new Runnable() { @Override public void run() { if (ApplicationManager.getApplication().isUnitTestMode()) { //noinspection CallToPrintStackTrace e1.printStackTrace(); } else { final String message = "Files in " + basePath.getPath() + " are locked.\n" + ApplicationNamesInfo.getInstance().getProductName() + " will not be able to start up."; if (!ApplicationManager.getApplication().isHeadlessEnvironment()) { JOptionPane.showMessageDialog( JOptionPane.getRootFrame(), message, "Fatal Error", JOptionPane.ERROR_MESSAGE); } else { //noinspection UseOfSystemOutOrSystemErr System.err.println(message); } } Runtime.getRuntime().halt(1); } }; if (EventQueue.isDispatchThread()) { warnAndShutdown.run(); } else { //noinspection SSBasedInspection SwingUtilities.invokeLater(warnAndShutdown); } throw new RuntimeException("Can't rebuild filesystem storage ", e1); } init(); } }