Search in sources :

Example 6 with MustBeLocked

use of com.helger.commons.annotation.MustBeLocked in project ph-commons by phax.

the class AbstractWALDAO method modifyWriteData.

/**
 * Modify the created document by e.g. adding some comment or digital
 * signature or whatsoever.
 *
 * @param aDoc
 *        The created non-<code>null</code> document.
 */
@OverrideOnDemand
@MustBeLocked(ELockType.WRITE)
protected void modifyWriteData(@Nonnull final IMicroDocument aDoc) {
    final IMicroComment aComment = new MicroComment("This file was generated automatically - do NOT modify!\n" + "Written at " + PDTToString.getAsString(ZonedDateTime.now(Clock.systemUTC()), Locale.US));
    final IMicroElement eRoot = aDoc.getDocumentElement();
    // Add a small comment
    if (eRoot != null)
        aDoc.insertBefore(aComment, eRoot);
    else
        aDoc.appendChild(aComment);
}
Also used : IMicroComment(com.helger.xml.microdom.IMicroComment) MicroComment(com.helger.xml.microdom.MicroComment) IMicroElement(com.helger.xml.microdom.IMicroElement) IMicroComment(com.helger.xml.microdom.IMicroComment) MustBeLocked(com.helger.commons.annotation.MustBeLocked) OverrideOnDemand(com.helger.commons.annotation.OverrideOnDemand)

Example 7 with MustBeLocked

use of com.helger.commons.annotation.MustBeLocked in project ph-commons by phax.

the class AbstractWALDAO method _writeToFile.

/**
 * The main method for writing the new data to a file. This method may only be
 * called within a write lock!
 *
 * @return {@link ESuccess} and never <code>null</code>.
 */
@Nonnull
@SuppressFBWarnings("RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE")
@MustBeLocked(ELockType.WRITE)
private ESuccess _writeToFile() {
    // Build the filename to write to
    final String sFilename = m_aFilenameProvider.get();
    if (sFilename == null) {
        // We're not operating on a file! Required for testing
        if (!isSilentMode())
            if (LOGGER.isInfoEnabled())
                LOGGER.info("The DAO of class " + getClass().getName() + " cannot write to a file");
        return ESuccess.FAILURE;
    }
    // Check for a filename change before writing
    if (!sFilename.equals(m_sPreviousFilename)) {
        onFilenameChange(m_sPreviousFilename, sFilename);
        m_sPreviousFilename = sFilename;
    }
    if (!isSilentMode())
        if (LOGGER.isInfoEnabled())
            LOGGER.info("Trying to write WAL DAO file '" + sFilename + "'");
    File aFileNew = null;
    IMicroDocument aDoc = null;
    final String sFilenameNew = _getFilenameNew(sFilename);
    final String sFilenamePrev = _getFilenamePrev(sFilename);
    try {
        // Get the file handle
        aFileNew = getSafeFile(sFilenameNew, EMode.WRITE);
        m_aStatsCounterWriteTotal.increment();
        final StopWatch aSW = StopWatch.createdStarted();
        // Create XML document to write
        aDoc = createWriteData();
        if (aDoc == null)
            throw new DAOException("Failed to create data to write to file");
        // Generic modification
        modifyWriteData(aDoc);
        // Get the output stream
        final OutputStream aOS = FileHelper.getOutputStream(aFileNew);
        if (aOS == null) {
            // Logger warning already emitted
            throw new DAOException("Failed to open output stream for '" + aFileNew.getAbsolutePath() + "'");
        }
        // Write to file (closes the OS)
        final IXMLWriterSettings aXWS = getXMLWriterSettings();
        if (MicroWriter.writeToStream(aDoc, aOS, aXWS).isFailure())
            throw new DAOException("Failed to write DAO XML data to file");
        // Rename existing file to old
        FileIOError aIOError;
        boolean bRenamedToPrev = false;
        if (m_aIO.existsFile(sFilename)) {
            aIOError = m_aIO.renameFile(sFilename, sFilenamePrev);
            bRenamedToPrev = true;
        } else
            aIOError = new FileIOError(EFileIOOperation.RENAME_FILE, EFileIOErrorCode.NO_ERROR);
        if (aIOError.isSuccess()) {
            // Rename new file to final
            aIOError = m_aIO.renameFile(sFilenameNew, sFilename);
            if (aIOError.isSuccess()) {
                // Finally delete old file
                aIOError = m_aIO.deleteFileIfExisting(sFilenamePrev);
            } else {
                // -> Revert original rename to stay as consistent as possible
                if (bRenamedToPrev)
                    m_aIO.renameFile(sFilenamePrev, sFilename);
            }
        }
        if (aIOError.isFailure())
            throw new IllegalStateException("Error on rename(existing-old)/rename(new-existing)/delete(old): " + aIOError);
        // Update stats etc.
        m_aStatsCounterWriteTimer.addTime(aSW.stopAndGetMillis());
        m_aStatsCounterWriteSuccess.increment();
        m_nWriteCount++;
        m_aLastWriteDT = PDTFactory.getCurrentLocalDateTime();
        return ESuccess.SUCCESS;
    } catch (final DAOException | RuntimeException ex) {
        final String sErrorFilename = aFileNew != null ? aFileNew.getAbsolutePath() : sFilename;
        if (LOGGER.isErrorEnabled())
            LOGGER.error("The DAO of class " + getClass().getName() + " failed to write the DAO data to '" + sErrorFilename + "'", ex);
        triggerExceptionHandlersWrite(ex, sErrorFilename, aDoc);
        m_aStatsCounterWriteExceptions.increment();
        return ESuccess.FAILURE;
    }
}
Also used : DAOException(com.helger.dao.DAOException) IXMLWriterSettings(com.helger.xml.serialize.write.IXMLWriterSettings) FileIOError(com.helger.commons.io.file.FileIOError) DataOutputStream(java.io.DataOutputStream) OutputStream(java.io.OutputStream) PDTToString(com.helger.commons.datetime.PDTToString) IMicroDocument(com.helger.xml.microdom.IMicroDocument) File(java.io.File) StopWatch(com.helger.commons.timing.StopWatch) MustBeLocked(com.helger.commons.annotation.MustBeLocked) Nonnull(javax.annotation.Nonnull) SuppressFBWarnings(edu.umd.cs.findbugs.annotations.SuppressFBWarnings)

Example 8 with MustBeLocked

use of com.helger.commons.annotation.MustBeLocked in project ph-commons by phax.

the class AbstractWALDAO method _writeWALFile.

@Nonnull
@MustBeLocked(ELockType.WRITE)
private ESuccess _writeWALFile(@Nonnull @Nonempty final List<DATATYPE> aModifiedElements, @Nonnull final EDAOActionType eActionType, @Nonnull @Nonempty final String sWALFilename) {
    final FileSystemResource aWALRes = m_aIO.getResource(sWALFilename);
    try (final DataOutputStream aDOS = new DataOutputStream(aWALRes.getOutputStream(EAppend.APPEND))) {
        // Write action type ID
        StreamHelper.writeSafeUTF(aDOS, eActionType.getID());
        // Write number of elements
        aDOS.writeInt(aModifiedElements.size());
        // Write all data elements as XML Strings :)
        for (final DATATYPE aModifiedElement : aModifiedElements) {
            final String sElement = convertNativeToWALString(aModifiedElement);
            StreamHelper.writeSafeUTF(aDOS, sElement);
        }
        return ESuccess.SUCCESS;
    } catch (final Exception ex) {
        if (LOGGER.isErrorEnabled())
            LOGGER.error("Error writing WAL file " + aWALRes, ex);
        triggerExceptionHandlersWrite(ex, sWALFilename, (IMicroDocument) null);
    }
    return ESuccess.FAILURE;
}
Also used : DataOutputStream(java.io.DataOutputStream) FileSystemResource(com.helger.commons.io.resource.FileSystemResource) PDTToString(com.helger.commons.datetime.PDTToString) IMicroDocument(com.helger.xml.microdom.IMicroDocument) EOFException(java.io.EOFException) DAOException(com.helger.dao.DAOException) IOException(java.io.IOException) MustBeLocked(com.helger.commons.annotation.MustBeLocked) Nonnull(javax.annotation.Nonnull)

Example 9 with MustBeLocked

use of com.helger.commons.annotation.MustBeLocked in project ph-commons by phax.

the class AbstractWALDAO method markAsChanged.

@MustBeLocked(ELockType.WRITE)
protected final void markAsChanged(@Nonnull final List<DATATYPE> aModifiedElements, @Nonnull final EDAOActionType eActionType) {
    ValueEnforcer.notNull(aModifiedElements, "ModifiedElements");
    ValueEnforcer.notNull(eActionType, "ActionType");
    // Just remember that something changed
    internalSetPendingChanges(true);
    if (internalIsAutoSaveEnabled()) {
        // Auto save
        // Write a WAL file
        final String sWALFilename = _getWALFilename();
        // Note: writing a WAL makes no sense, if the waiting time is zero
        if (m_bCanWriteWAL && m_aWaitingTime.compareTo(Duration.ZERO) > 0 && sWALFilename != null && _writeWALFile(aModifiedElements, eActionType, sWALFilename).isSuccess()) {
            // Remember change for later writing
            // Note: pass the WAL filename in case the filename changes over time!
            m_aWALListener.registerForLaterWriting(this, sWALFilename, m_aWaitingTime);
        } else {
            // write directly
            _writeToFileAndResetPendingChanges("markAsChanged(" + eActionType.getID() + ")");
        }
    }
}
Also used : PDTToString(com.helger.commons.datetime.PDTToString) MustBeLocked(com.helger.commons.annotation.MustBeLocked)

Example 10 with MustBeLocked

use of com.helger.commons.annotation.MustBeLocked in project ph-commons by phax.

the class FileIntIDFactory method readAndUpdateIDCounter.

/*
   * Note: this method must only be called from within a locked section!
   */
@Override
@MustBeLocked(ELockType.WRITE)
protected final int readAndUpdateIDCounter(@Nonnegative final int nReserveCount) {
    // Read the old content
    final String sContent = SimpleFileIO.getFileAsString(m_aFile, CHARSET_TO_USE);
    final int nRead = sContent != null ? StringParser.parseInt(sContent.trim(), 0) : 0;
    // Write the new content to the new file
    // This will fail, if the disk is full
    SimpleFileIO.writeFile(m_aNewFile, Integer.toString(nRead + nReserveCount), CHARSET_TO_USE);
    FileIOError aIOError;
    boolean bRenamedToPrev = false;
    if (m_aFile.exists()) {
        // Rename the existing file to the prev file
        aIOError = FileOperationManager.INSTANCE.renameFile(m_aFile, m_aPrevFile);
        bRenamedToPrev = true;
    } else
        aIOError = new FileIOError(EFileIOOperation.RENAME_FILE, EFileIOErrorCode.NO_ERROR);
    if (aIOError.isSuccess()) {
        // Rename the new file to the destination file
        aIOError = FileOperationManager.INSTANCE.renameFile(m_aNewFile, m_aFile);
        if (aIOError.isSuccess()) {
            // Finally delete the prev file (may not be existing for fresh
            // instances)
            aIOError = FileOperationManager.INSTANCE.deleteFileIfExisting(m_aPrevFile);
        } else {
            // -> Revert original rename to stay as consistent as possible
            if (bRenamedToPrev)
                FileOperationManager.INSTANCE.renameFile(m_aPrevFile, m_aFile);
        }
    }
    if (aIOError.isFailure())
        throw new IllegalStateException("Error on rename(existing-old)/rename(new-existing)/delete(old): " + aIOError);
    return nRead;
}
Also used : FileIOError(com.helger.commons.io.file.FileIOError) MustBeLocked(com.helger.commons.annotation.MustBeLocked)

Aggregations

MustBeLocked (com.helger.commons.annotation.MustBeLocked)10 PDTToString (com.helger.commons.datetime.PDTToString)5 IMicroDocument (com.helger.xml.microdom.IMicroDocument)5 DAOException (com.helger.dao.DAOException)4 Nonnull (javax.annotation.Nonnull)4 StopWatch (com.helger.commons.timing.StopWatch)3 IMicroElement (com.helger.xml.microdom.IMicroElement)3 File (java.io.File)3 OverrideOnDemand (com.helger.commons.annotation.OverrideOnDemand)2 FileIOError (com.helger.commons.io.file.FileIOError)2 IMicroComment (com.helger.xml.microdom.IMicroComment)2 MicroComment (com.helger.xml.microdom.MicroComment)2 IXMLWriterSettings (com.helger.xml.serialize.write.IXMLWriterSettings)2 SuppressFBWarnings (edu.umd.cs.findbugs.annotations.SuppressFBWarnings)2 DataOutputStream (java.io.DataOutputStream)2 OutputStream (java.io.OutputStream)2 EUnicodeBOM (com.helger.commons.charset.EUnicodeBOM)1 CommonsArrayList (com.helger.commons.collection.impl.CommonsArrayList)1 FileSystemResource (com.helger.commons.io.resource.FileSystemResource)1 ESuccess (com.helger.commons.state.ESuccess)1