use of com.zimbra.cs.redolog.logger.FileHeader in project zm-mailbox by Zimbra.
the class RedoLogVerify method scanLog.
public boolean scanLog(File logfile) throws IOException {
boolean good = false;
FileLogReader logReader = new FileLogReader(logfile, false);
logReader.open();
if (!mParams.quiet) {
FileHeader header = logReader.getHeader();
mOut.println("HEADER");
mOut.println("------");
mOut.print(header);
mOut.println("------");
}
boolean hasMailboxIdsFilter = !mParams.mboxIds.isEmpty();
RedoableOp op = null;
long lastPosition = 0;
long lastOpStartOffset = 0;
try {
while ((op = logReader.getNextOp()) != null) {
lastOpStartOffset = logReader.getLastOpStartOffset();
lastPosition = logReader.position();
if (hasMailboxIdsFilter) {
int mboxId = op.getMailboxId();
if (op instanceof StoreIncomingBlob) {
List<Integer> list = ((StoreIncomingBlob) op).getMailboxIdList();
if (list != null) {
boolean match = false;
for (Integer mid : list) {
if (mParams.mboxIds.contains(mid)) {
match = true;
break;
}
}
if (!match)
continue;
}
// If list==null, it's a store incoming blob op targeted at unknown set of mailboxes.
// It applies to our filtered mailboxes.
} else if (!mParams.mboxIds.contains(mboxId)) {
continue;
}
}
if (!mParams.quiet) {
printOp(mOut, op, mParams.hideOffset, lastOpStartOffset, lastPosition - lastOpStartOffset);
if (mParams.showBlob) {
InputStream dataStream = op.getAdditionalDataStream();
if (dataStream != null) {
mOut.println("<START OF BLOB>");
ByteUtil.copy(dataStream, true, mOut, false);
mOut.println();
mOut.println("<END OF BLOB>");
}
}
}
}
good = true;
} catch (IOException e) {
// The IOException could be a real I/O problem or it could mean
// there was a server crash previously and there were half-written
// log entries.
mOut.println();
mOut.printf("Error while parsing data starting at offset 0x%08x", lastPosition);
mOut.println();
long size = logReader.getSize();
long diff = size - lastPosition;
mOut.printf("%d bytes remaining in the file", diff);
mOut.println();
mOut.println();
if (op != null) {
mOut.println("Last suceessfully parsed redo op:");
printOp(mOut, op, false, lastOpStartOffset, lastPosition - lastOpStartOffset);
mOut.println();
}
// hexdump data around the bad bytes
int bytesPerLine = 16;
int linesBefore = 10;
int linesAfter = 10;
long startPos = Math.max(lastPosition - (lastPosition % bytesPerLine) - linesBefore * bytesPerLine, 0);
int count = (int) Math.min((linesBefore + linesAfter + 1) * bytesPerLine, lastPosition - startPos + diff);
RandomAccessFile raf = null;
try {
raf = new RandomAccessFile(logfile, "r");
raf.seek(startPos);
byte[] buf = new byte[count];
raf.read(buf, 0, count);
mOut.printf("Data near error offset %08x:", lastPosition);
mOut.println();
hexdump(mOut, buf, 0, count, startPos, lastPosition);
mOut.println();
} catch (IOException eh) {
mOut.println("Error opening log file " + logfile.getAbsolutePath() + " for hexdump");
eh.printStackTrace(mOut);
} finally {
if (raf != null)
raf.close();
}
throw e;
} finally {
logReader.close();
}
return good;
}
use of com.zimbra.cs.redolog.logger.FileHeader in project zm-mailbox by Zimbra.
the class PlaybackUtil method initParams.
private static Params initParams(CommandLine cl) throws ServiceException, IOException {
Params params = new Params();
params.help = cl.hasOption(OPT_HELP);
if (params.help)
return params;
params.stopOnError = cl.hasOption(OPT_STOP_ON_ERROR);
if (cl.hasOption(OPT_FROM_TIME)) {
String timeStr = cl.getOptionValue(OPT_FROM_TIME);
Date time = SoapCLI.parseDatetime(timeStr);
if (time != null) {
params.fromTime = time.getTime();
SimpleDateFormat f = new SimpleDateFormat(SoapCLI.CANONICAL_DATETIME_FORMAT);
String tstamp = f.format(time);
System.out.printf("Using from-time of %s\n", tstamp);
} else {
System.err.printf("Invalid timestamp \"%s\" specified for --%s option\n", timeStr, OPT_FROM_TIME);
System.err.println();
System.err.print(SoapCLI.getAllowedDatetimeFormatsHelp());
System.exit(1);
}
}
if (cl.hasOption(OPT_FROM_SEQ)) {
params.fromSeq = Long.parseLong(cl.getOptionValue(OPT_FROM_SEQ));
System.out.printf("Using from-sequence of %d\n", params.fromSeq);
}
if (cl.hasOption(OPT_TO_TIME)) {
String timeStr = cl.getOptionValue(OPT_TO_TIME);
Date time = SoapCLI.parseDatetime(timeStr);
if (time != null) {
params.toTime = time.getTime();
SimpleDateFormat f = new SimpleDateFormat(SoapCLI.CANONICAL_DATETIME_FORMAT);
String tstamp = f.format(time);
System.out.printf("Using to-time of %s\n", tstamp);
} else {
System.err.printf("Invalid timestamp \"%s\" specified for --%s option\n", timeStr, OPT_TO_TIME);
System.err.println();
System.err.print(SoapCLI.getAllowedDatetimeFormatsHelp());
System.exit(1);
}
}
if (cl.hasOption(OPT_TO_SEQ)) {
params.toSeq = Long.parseLong(cl.getOptionValue(OPT_TO_SEQ));
System.out.printf("Using to-sequence of %d\n", params.toSeq);
}
if (params.fromSeq > params.toSeq) {
System.err.println("Error: fromSeq greater than toSeq");
System.exit(1);
}
if (params.fromTime > params.toTime) {
System.err.println("Error: fromTime later than toTime");
System.exit(1);
}
if (cl.hasOption(OPT_MAILBOX_ID)) {
params.mboxId = Integer.parseInt(cl.getOptionValue(OPT_MAILBOX_ID));
System.out.printf("Replaying operations for mailbox %d only\n", params.mboxId);
} else {
System.out.println("Replaying operations for all mailboxes");
}
if (cl.hasOption(OPT_THREADS))
params.threads = Integer.parseInt(cl.getOptionValue(OPT_THREADS));
System.out.printf("Using %d redo player threads\n", params.threads);
if (cl.hasOption(OPT_QUEUE_CAPACITY))
params.queueCapacity = Integer.parseInt(cl.getOptionValue(OPT_QUEUE_CAPACITY));
System.out.printf("Using %d as queue capacity for each redo player thread\n", params.queueCapacity);
List<File> logList = new ArrayList<File>();
if (cl.hasOption(OPT_LOGFILES)) {
String[] fnames = cl.getOptionValues(OPT_LOGFILES);
params.logfiles = new File[fnames.length];
for (int i = 0; i < fnames.length; i++) {
File f = new File(fnames[i]);
if (f.exists())
logList.add(f);
else
throw new FileNotFoundException("No such file: " + f.getAbsolutePath());
}
} else {
// By default, use /opt/zimbra/redolog/archive/*, then /opt/zimbra/redolog/redo.log,
// ordered by log sequence.
Provisioning prov = Provisioning.getInstance();
Server server = prov.getLocalServer();
String archiveDirPath = Config.getPathRelativeToZimbraHome(server.getAttr(Provisioning.A_zimbraRedoLogArchiveDir, "redolog/archive")).getAbsolutePath();
String redoLogPath = Config.getPathRelativeToZimbraHome(server.getAttr(Provisioning.A_zimbraRedoLogLogPath, "redolog/redo.log")).getAbsolutePath();
File archiveDir = new File(archiveDirPath);
if (archiveDir.exists()) {
File[] archiveLogs = RolloverManager.getArchiveLogs(archiveDir, params.fromSeq, params.toSeq);
for (File f : archiveLogs) {
logList.add(f);
}
}
File redoLog = new File(redoLogPath);
if (redoLog.exists()) {
FileLogReader logReader = new FileLogReader(redoLog);
long seq = logReader.getHeader().getSequence();
if (params.fromSeq <= seq && seq <= params.toSeq)
logList.add(redoLog);
}
}
// Filter out logs based on from/to times.
for (Iterator<File> iter = logList.iterator(); iter.hasNext(); ) {
File f = iter.next();
FileHeader hdr = (new FileLogReader(f)).getHeader();
if (hdr.getFirstOpTstamp() > params.toTime || (hdr.getLastOpTstamp() < params.fromTime && !hdr.getOpen())) {
// log is outside the time range
iter.remove();
System.out.printf("Redolog %s has no operation in the requested time range\n", f.getName());
}
}
params.logfiles = new File[logList.size()];
params.logfiles = logList.toArray(params.logfiles);
System.out.printf("%d redolog files to play back\n", params.logfiles.length);
return params;
}
Aggregations