blob: c36c9aa628b73d29508fc5d3958a58fd2ac80650 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ignite.internal.processors.cache.persistence;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.EnumSet;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteLogger;
import org.apache.ignite.internal.pagemem.wal.record.DataEntry;
import org.apache.ignite.internal.pagemem.wal.record.DataRecord;
import org.apache.ignite.internal.pagemem.wal.record.TxRecord;
import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.jetbrains.annotations.Nullable;
import static java.nio.file.StandardOpenOption.CREATE;
import static java.nio.file.StandardOpenOption.READ;
import static java.nio.file.StandardOpenOption.WRITE;
/**
*
*/
public class RecoveryDebug implements AutoCloseable {
/** */
private static final DateTimeFormatter DATE_FORMATTER =
DateTimeFormatter.ofPattern("dd-MM-yyyy-HH-mm-ss-SSS").withZone(ZoneId.of("UTC"));
/** */
@Nullable private final IgniteLogger log;
/** */
@Nullable private FileChannel fc;
/**
* @param constId Consistent ID.
*/
public RecoveryDebug(Object constId, long time) {
this(constId, time, null);
}
/**
* @param constId Consistent ID.
* @param log Logger.
*/
public RecoveryDebug(Object constId, long time, @Nullable IgniteLogger log) {
this.log = log;
try {
String workDir = U.defaultWorkDirectory();
File tmpDir = new File(workDir, "tmp");
if (!tmpDir.exists())
if (!tmpDir.mkdir())
return;
File f = new File(tmpDir, "recovery-" +
DATE_FORMATTER.format(Instant.ofEpochMilli(time)) + "-" + constId + ".log");
f.createNewFile();
fc = FileChannel.open(Paths.get(f.getPath()), EnumSet.of(CREATE, READ, WRITE));
}
catch (IgniteCheckedException | IOException e) {
U.error(log, "Fail create recovery debug file.", e);
fc = null;
}
}
/**
* @param rec TX record to append.
* @return {@code this} for convenience.
*/
public RecoveryDebug append(TxRecord rec) {
GridCacheVersion txVer = rec.nearXidVersion();
return fc == null ? this : appendFile(
"Tx record " + rec.state() + " " + rec.nearXidVersion() + " timestamp " + rec.timestamp()
);
}
/**
* @param rec Data record to append.
* @param unwrapKeyValue unwrap key and value flag.
* @return {@code this} for convenience.
*/
public RecoveryDebug append(DataRecord rec, boolean unwrapKeyValue) {
if (fc == null)
return this;
append("Data record\n");
for (DataEntry dataEntry : rec.writeEntries())
append("\t" + dataEntry.op() + " " + dataEntry.nearXidVersion() +
(unwrapKeyValue ? " " + dataEntry.key() + " " + dataEntry.value() : "") + "\n"
);
return this;
}
/**
* @param st Statement to append.
* @return {@code this} for convenience.
*/
public RecoveryDebug append(Object st) {
return fc == null ? this : appendFile(st);
}
/**
* @param st Statement to append.
* @return {@code this} for convenience.
*/
private RecoveryDebug appendFile(Object st) {
try {
fc.write(ByteBuffer.wrap(st.toString().getBytes()));
}
catch (IOException e) {
U.error(null, "Fail write to recovery dump file.", e);
}
return this;
}
/**
* Closes this debug insrance.
*/
@Override public void close() {
if (fc != null) {
try {
fc.force(true);
fc.close();
}
catch (IOException e) {
U.error(null, "Fail close recovery dump file.", e);
}
}
}
}