@Override
  public void run() {
    List<Transaction> records = new ArrayList<Transaction>();
    if (archivingEnabled == false) {
      log.info("Archiving has not been enabled");
      return;
    }
    while (isExit() == false) {
      records.clear();
      buffer.drainTo(records);
      PrintWriter wf = null;
      try {
        FileWriter ff = new FileWriter(filename, true);
        wf = new PrintWriter(ff);
      } catch (FileNotFoundException e) {
        log.error("Should not have happened for [" + filename + "]");
        continue;
      } catch (IOException e) {
        log.error("Cannot write to [" + filename + "]");
        setExit(true);
        continue;
      }

      TransactionLogRecord tlr = new TransactionLogRecord();
      for (Transaction t : records) {
        log.debug("Logging " + t);
        if (t instanceof ExitTransaction) {
          setExit(true);
          continue;
        }
        if (t.getDirection().equals(DirectionType.NONE)) {
          log.error("Transaction [" + t + "] is empty");
          continue;
        }
        wf.print(tlr.toString(t));
      }
      wf.close();
    }
    log.info("Archiving is ending");
  }
Example #2
0
  /**
   * 写入事务日志
   *
   * @param tlog
   * @return
   * @throws BKException
   * @throws InterruptedException
   */
  public SyncCounter writeLog(TransactionLogRecord tlog) throws InterruptedException {
    int recordSize = tlog.calculateTotalRecordSize();
    long futureFilePosition = handle.getLength() + recordSize;
    if (futureFilePosition >= conf.getBtmConf().getMaxLogSizeInMb() * 1024 * 1024) {
      if (log.isDebugEnabled())
        log.debug(
            "log file is full (size would be: "
                + futureFilePosition
                + ", max allowed: "
                + conf.getBtmConf().getMaxLogSizeInMb()
                + "Mbs");
      return null;
    }

    ByteBuffer buf = ByteBuffer.allocate(recordSize);
    buf.putInt(tlog.getStatus());
    buf.putInt(tlog.getRecordLength());
    buf.putInt(tlog.getHeaderLength());
    buf.putLong(tlog.getTime());
    buf.putInt(tlog.getSequenceNumber());
    buf.putInt(tlog.getCrc32());
    buf.put((byte) tlog.getGtrid().getArray().length);
    buf.put(tlog.getGtrid().getArray());
    Set<String> uniqueNames = tlog.getUniqueNames();
    buf.putInt(uniqueNames.size());
    for (String uniqueName : uniqueNames) {
      buf.putShort((short) uniqueName.length());
      buf.put(uniqueName.getBytes());
    }
    buf.putInt(tlog.getEndRecord());

    byte[] data = buf.array();
    SyncCounter counter = new SyncCounter();
    counter.inc();
    handle.asyncAddEntry(data, new SyncAddCallback(), counter);
    lastCounter.set(counter);
    return counter;
  }
  /**
   * Fetch the next TransactionLogRecord from log.
   *
   * @param skipCrcCheck if set to false, the method will thow an InvalidChecksumException if the
   *     CRC on disk does not match the recalculated one. Otherwise, the CRC is not recalculated nor
   *     checked agains the stored one.
   * @return the TransactionLogRecord or null if the end of the log file has been reached
   * @throws IOException if an I/O error occurs.
   */
  public TransactionLogRecord readLog(boolean skipCrcCheck) throws IOException {
    if (currentPosition >= endPosition) {
      if (log.isDebugEnabled())
        log.debug("end of transaction log file reached at " + currentPosition);
      return null;
    }

    final int status = page.getInt();
    // currentPosition += 4;
    final int recordLength = page.getInt();
    // currentPosition += 4;
    currentPosition += 8;

    if (page.position() + recordLength + 8 > page.limit()) {
      page.compact();
      fileChannel.read(page);
      page.rewind();
    }

    final int endOfRecordPosition = page.position() + recordLength;
    if (currentPosition + recordLength > endPosition) {
      page.position(page.position() + recordLength);
      currentPosition += recordLength;
      throw new CorruptedTransactionLogException(
          "corrupted log found at position "
              + currentPosition
              + " (record terminator outside of file bounds: "
              + currentPosition
              + recordLength
              + " of "
              + endPosition
              + ", recordLength: "
              + recordLength
              + ")");
    }

    final int headerLength = page.getInt();
    // currentPosition += 4;
    final long time = page.getLong();
    // currentPosition += 8;
    final int sequenceNumber = page.getInt();
    // currentPosition += 4;
    final int crc32 = page.getInt();
    // currentPosition += 4;
    final byte gtridSize = page.get();
    // currentPosition += 1;
    currentPosition += 21;

    // check for log terminator
    page.mark();
    page.position(endOfRecordPosition - 4);
    int endCode = page.getInt();
    page.reset();
    if (endCode != TransactionLogAppender.END_RECORD)
      throw new CorruptedTransactionLogException(
          "corrupted log found at position " + currentPosition + " (no record terminator found)");

    // check that GTRID is not too long
    if (4 + 8 + 4 + 4 + 1 + gtridSize > recordLength) {
      page.position(endOfRecordPosition);
      throw new CorruptedTransactionLogException(
          "corrupted log found at position " + currentPosition + " (GTRID size too long)");
    }

    final byte[] gtridArray = new byte[gtridSize];
    page.get(gtridArray);
    currentPosition += gtridSize;
    Uid gtrid = new Uid(gtridArray);
    final int uniqueNamesCount = page.getInt();
    currentPosition += 4;
    Set<String> uniqueNames = new HashSet<String>();
    int currentReadCount = 4 + 8 + 4 + 4 + 1 + gtridSize + 4;

    for (int i = 0; i < uniqueNamesCount; i++) {
      int length = page.getShort();
      currentPosition += 2;

      // check that names aren't too long
      currentReadCount += 2 + length;
      if (currentReadCount > recordLength) {
        page.position(endOfRecordPosition);
        throw new CorruptedTransactionLogException(
            "corrupted log found at position "
                + currentPosition
                + " (unique names too long, "
                + (i + 1)
                + " out of "
                + uniqueNamesCount
                + ", length: "
                + length
                + ", currentReadCount: "
                + currentReadCount
                + ", recordLength: "
                + recordLength
                + ")");
      }

      byte[] nameBytes = new byte[length];
      page.get(nameBytes);
      currentPosition += length;
      uniqueNames.add(new String(nameBytes, "US-ASCII"));
    }
    final int cEndRecord = page.getInt();
    currentPosition += 4;

    TransactionLogRecord tlog =
        new TransactionLogRecord(
            status,
            recordLength,
            headerLength,
            time,
            sequenceNumber,
            crc32,
            gtrid,
            uniqueNames,
            cEndRecord);

    // check that CRC is okay
    if (!skipCrcCheck && !tlog.isCrc32Correct()) {
      page.position(endOfRecordPosition);
      throw new CorruptedTransactionLogException(
          "corrupted log found at position "
              + currentPosition
              + "(invalid CRC, recorded: "
              + tlog.getCrc32()
              + ", calculated: "
              + tlog.calculateCrc32()
              + ")");
    }

    return tlog;
  }