Beispiel #1
0
  /**
   * Add the provided record at the end of this log.
   *
   * <p>The record must have a key strictly higher than the key of the last record added. If it is
   * not the case, the record is not appended and the method returns immediately.
   *
   * <p>In order to ensure that record is written out of buffers and persisted to file system, it is
   * necessary to explicitely call the {@code syncToFileSystem()} method.
   *
   * @param record The record to add.
   * @throws ChangelogException If an error occurs while adding the record to the log.
   */
  public void append(final Record<K, V> record) throws ChangelogException {
    // If this exclusive lock happens to be a bottleneck :
    // 1. use a shared lock for appending the record first
    // 2. switch to an exclusive lock only if rotation is needed
    // See http://sources.forgerock.org/cru/CR-3548#c27521 for full detail
    exclusiveLock.lock();
    try {
      if (isClosed) {
        return;
      }
      if (recordIsBreakingKeyOrdering(record)) {
        logger.info(
            LocalizableMessage.raw(
                "Rejecting append to log '%s' for record: [%s], last key appended: [%s]",
                logPath.getPath(), record, lastAppendedKey != null ? lastAppendedKey : "null"));
        return;
      }
      LogFile<K, V> headLogFile = getHeadLogFile();
      if (mustRotate(headLogFile)) {
        logger.trace(
            INFO_CHANGELOG_LOG_FILE_ROTATION.get(logPath.getPath(), headLogFile.getSizeInBytes()));

        rotateHeadLogFile();
        headLogFile = getHeadLogFile();
      }
      headLogFile.append(record);
      lastAppendedKey = record.getKey();
    } finally {
      exclusiveLock.unlock();
    }
  }
Beispiel #2
0
 private boolean mustRotate(LogFile<K, V> headLogFile) {
   if (lastAppendedKey == null) {
     // never rotate an empty file
     return false;
   }
   if (headLogFile.getSizeInBytes() > sizeLimitPerLogFileInBytes) {
     // rotate because file size exceeded threshold
     logger.trace(
         "Rotate log %s due to size: %s", logPath.getPath(), headLogFile.getSizeInBytes());
     return true;
   }
   if (rotationIntervalInMillis > 0) {
     // rotate if time limit is reached
     final long timeElapsed = timeService.since(lastRotationTime);
     boolean shouldRotate = timeElapsed > rotationIntervalInMillis;
     if (shouldRotate) {
       logger.trace(
           "Rotate log %s due to time: time elapsed %s, rotation interval: %s",
           logPath.getPath(), timeElapsed, rotationIntervalInMillis);
     }
     return shouldRotate;
   }
   return false;
 }