Search in sources :

Example 1 with FileHeader

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;
}
Also used : RandomAccessFile(java.io.RandomAccessFile) RedoableOp(com.zimbra.cs.redolog.op.RedoableOp) StoreIncomingBlob(com.zimbra.cs.redolog.op.StoreIncomingBlob) InputStream(java.io.InputStream) IOException(java.io.IOException) FileHeader(com.zimbra.cs.redolog.logger.FileHeader) FileLogReader(com.zimbra.cs.redolog.logger.FileLogReader)

Example 2 with FileHeader

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;
}
Also used : Server(com.zimbra.cs.account.Server) ArrayList(java.util.ArrayList) FileNotFoundException(java.io.FileNotFoundException) Date(java.util.Date) Provisioning(com.zimbra.cs.account.Provisioning) FileLogReader(com.zimbra.cs.redolog.logger.FileLogReader) SimpleDateFormat(java.text.SimpleDateFormat) File(java.io.File) FileHeader(com.zimbra.cs.redolog.logger.FileHeader)

Aggregations

FileHeader (com.zimbra.cs.redolog.logger.FileHeader)2 FileLogReader (com.zimbra.cs.redolog.logger.FileLogReader)2 Provisioning (com.zimbra.cs.account.Provisioning)1 Server (com.zimbra.cs.account.Server)1 RedoableOp (com.zimbra.cs.redolog.op.RedoableOp)1 StoreIncomingBlob (com.zimbra.cs.redolog.op.StoreIncomingBlob)1 File (java.io.File)1 FileNotFoundException (java.io.FileNotFoundException)1 IOException (java.io.IOException)1 InputStream (java.io.InputStream)1 RandomAccessFile (java.io.RandomAccessFile)1 SimpleDateFormat (java.text.SimpleDateFormat)1 ArrayList (java.util.ArrayList)1 Date (java.util.Date)1