Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*-
   * See the file LICENSE for redistribution information.
   *
   * Copyright (c) 2004, 2010 Oracle and/or its affiliates.  All rights reserved.
   *
   */
  
  package com.sleepycat.je.rep.util.ldiff;
  
 import java.util.List;
 
 
 /*
  * Class used for figuring out the difference on local and remote databases, 
  * also getting the VLSN number for different records.
  *
  * This class only needs to traverse the local and remote databases once and
  * do the check, this is because the different areas are sequential on the 
  * database. 
  *
  * It uses a hash set to save the records on the local different area, and
  * another hash set to save the records on the remote different area. Then
  * traverse the records in local set to see whether it exists in the remote
  * set, and do the same thing on records in remote set.
  */
 public class DiffRecordAnalyzer {
     public static final long DATABASE_END = -1;
 
     /* The analysis method used by network LDiff. */
     public static void doAnalysis(Database localDb,
                                   Protocol protocol,
                                   SocketChannel channel,
                                   DiffTracker tracker,
                                   boolean doPrint
         throws Exception {
 
         List<MismatchedRegionregions = tracker.getDiffRegions();
         Cursor localCursor = null;
         try {
             localCursor = localDb.openCursor(nullnull);
 
             for (MismatchedRegion region : regions) {
                 if (region.isLocalAdditional()) {
                     printLocalAdditional(localCursorregiondoPrint);
                     continue;
                 }
 
                 if (region.isRemoteAdditional()) {
                      HashSet<Recordrecords = 
                          getDiffArea(protocolchannelregion);
                      if (doPrint) {
                          printAdditional(recordstrue);
                      }
                      records.clear();
                      continue;
                 }
 
                 HashSet<RecordlocalRecords = 
                     getDiffArea(localCursorregion.getLocalBeginKey(), 
                                 region.getLocalBeginData(), 
                                 region.getLocalDiffSize());
                 HashSet<RecordremoteRecords = 
                     getDiffArea(protocolchannelregion);
                 if (doPrint) {
                 printDiffs(localRecordsremoteRecords);
             }
                 localRecords.clear();
                 remoteRecords.clear();
             }
         } finally {
             if (localCursor != null) {
                 localCursor.close();
             }
         }
     }
     
     /* The analysis method used by two local databases. */
     public static void doAnalysis(Database localDb
                                   Database remoteDb
                                   DiffTracker tracker,
                                   boolean doPrint
         throws Exception {
 
        List<MismatchedRegionregions = tracker.getDiffRegions();
        Cursor localCursor = null;
        Cursor remoteCursor = null;
        try {
            localCursor = localDb.openCursor(nullnull);
            remoteCursor = remoteDb.openCursor(nullnull);
            for (MismatchedRegion region : regions) {
                if (region.isLocalAdditional()) {
                    printLocalAdditional(localCursorregiondoPrint);
                    continue;
                }
             
                if (region.isRemoteAdditional()) {
                    HashSet<Recordrecords = 
                        getDiffArea(remoteCursorregion.getRemoteBeginKey(),
                                    region.getRemoteBeginData(),
                                    region.getRemoteDiffSize());
                    if (doPrint) {
                        printAdditional(recordstrue);
                    }
                    records.clear();
                    continue;
                }
                HashSet<RecordlocalRecords =
                    getDiffArea(localCursorregion.getLocalBeginKey(),
                                region.getLocalBeginData(), 
                                region.getLocalDiffSize());
                HashSet<RecordremoteRecords =
                    getDiffArea(remoteCursorregion.getRemoteBeginKey(), 
                                region.getRemoteBeginData(),
                                region.getRemoteDiffSize());
                if (doPrint) {
                printDiffs(localRecordsremoteRecords);
            }
                localRecords.clear();
                remoteRecords.clear();
            }
        } finally {
            if (localCursor != null) {
                localCursor.close();
            }
            if (remoteCursor != null) {
                remoteCursor.close();
            }
        }
    }
    /* Print local additional records. */
    private static void printLocalAdditional(Cursor cursor,
                                             MismatchedRegion region,
                                             boolean doPrint
        throws Exception {
        HashSet<Recordrecords = getDiffArea(cursor
                                              region.getLocalBeginKey(), 
                                    region.getLocalBeginData(),
                                              region.getLocalDiffSize());
        if (doPrint) {
            printAdditional(recordsfalse);
    }
        records.clear();
    }
    private static void printAdditional(HashSet<RecorddiffRecords
                                        boolean remote) {
        String side = remote ? "Remote" : "Local";
        ..println("************************************************");
        ..println(side + " database has additional records, the " + 
                           "additional range as following:");
        side = remote ? "remote" : "local";
        for (Record record : diffRecords) {
            printRecord(recordsidefalse);
        }
        ..println("************************************************");
    }
    /* 
     * Print out the VLSN (if this record has) and the key's context of this 
     * record. 
     */
    private static void printRecord(Record record,
                                    String side,
                                    boolean different) {
        ..print("Record with Key: [");
        byte[] keys = record.getKey();
        for (int i = 0; i < keys.lengthi++) {
            ..print(keys[i]);
            if (i < (keys.length - 1)) {
                ..print(" ");
            }
        }
        ..print("]");
        if (record.getVLSN().getSequence() != -1) {
            ..print(", VLSN: " + record.getVLSN());
        }
        if (different) {
            ..print(" does not exist on " + side + " database");
        }
        ..println();
    }
    /* Return a different area on local database in a hash set. */
    private static HashSet<RecordgetDiffArea(Cursor cursor,
                                               byte[] beginKey,
                                               byte[] beginData,
                                               long diffSize
        throws Exception {
        HashSet<Recordrecords = new HashSet<Record>();
        LogManager logManager = DbInternal.getEnvironmentImpl
            (cursor.getDatabase().getEnvironment()).getLogManager();
        DatabaseEntry key = new DatabaseEntry(beginKey);
        DatabaseEntry data = new DatabaseEntry(beginData);
        boolean scanToEnd = (diffSize ==  ? true : false);
        long count = 1;
        for (OperationStatus status = 
             cursor.getSearchBoth(keydata.); 
             status == .;
             status = cursor.getNext(keydata.)) {
            if (!scanToEnd && count > diffSize) {
                break;
            }
            records.add(new Record(key.getData(), data.getData(),
                                   getVLSN(cursorlogManager)));
            count++;
        }
        return records;
    }
    /* Used by LDiffService. */
    public static HashSet<RecordgetDiffArea(Cursor cursor
                                              RemoteDiffRequest request
        throws Exception {
        return getDiffArea(cursorrequest.getKey(), 
                           request.getData(), request.getDiffSize());
    }
    /* Get the records of a different area on remote database in a HashSet. */
    private static HashSet<RecordgetDiffArea(Protocol protocol,
                                               SocketChannel channel,
                                               MismatchedRegion region
        throws Exception {
        protocol.write(protocol.new RemoteDiffRequest(region), channel);
        /* Check whether getting records on remote database is successful. */
        Message message = protocol.read(channel);
        if (message.getOp() == .) {
            throw new LDiffRecordRequestException
                (((Protocol.Errormessage).getErrorMessage());
        }
        
        if (message.getOp() != .) {
            throw new ProtocolException
                (messageProtocol.DiffAreaStart.class);
        }
        /* Add those different records until protocol sees an end signal. */
        HashSet<Recordrecords = new HashSet<Record>();
        while (true) {
            try {
                Protocol.RemoteRecord record = 
                    protocol.read(channelProtocol.RemoteRecord.class);
                records.add(new Record(record.getKey(),
                                       record.getData(),
                                       record.getVLSN()));
            } catch (ProtocolException pe) {
                if (pe.getUnexpectedMessage().getOp() != 
                    .) {
                    throw pe;
                }
                break;
            }
        }
        return records;
    }
    /* Compare the differences between two sets. */
    private static void printDiffs(HashSet<RecordlocalDiffs,
                                     HashSet<RecordremoteDiffs) {
        ..println("************************************************");
        ..println("Different records between local and remote database " +
                           "in a specific different area.");
        for (Record record : localDiffs) {
            if (!remoteDiffs.contains(record)) {
                printRecord(record"remote"true);
            }
        }
        for (Record record : remoteDiffs) {
            if (!localDiffs.contains(record)) {
                printRecord(record"local"true);
            }
        }
        ..println("************************************************");
    }
    /* 
     * Get the LSN that the cursor currently points to, there are two cases 
     * that a record doesn't have a VLSN:
     * 1. compare between two local databases.
     * 2. compare between two converted environments.
     *
     * In the above two cases, we actually return NULL_VLSN instead of null, so
     * that the message doesn't complain about a null value. 
     */
    private static VLSN getVLSN(Cursor cursorLogManager logManager
        throws Exception {
        CursorImpl cursorImpl = DbInternal.getCursorImpl(cursor);
        BIN bin = cursorImpl.getBIN();
        int index = cursorImpl.getIndex();
        final long lsn = bin.getLsn(index);
        WholeEntry entry = logManager.getLogEntryAllowInvisible(lsn);
        VLSN vlsn = entry.getHeader().getVLSN();
        if (vlsn == null) {
            vlsn = .;
        }
        return vlsn;
    }
New to GrepCode? Check out our FAQ X