(startingTime == -1 || prepareOp.getTimestamp() >= startingTime)) {
(startTime == -1 || prepareOp.getTimestamp() >= startTime) && op.getTimestamp() < endTime) {
    public void playOp(RedoableOp op,                       boolean redoCommitted,                       Map<Integer, Integer> mboxIDsMap,                       long startingTime)    throws ServiceException {        if (op.isStartMarker()) {            synchronized (mOpsMapGuard) {                mOpsMap.put(op.getTransactionId(), op);                if (mHasOrphanOps) {                    RedoableOp x = (RedoableOp) mOrphanOps.remove(op.getTransactionId());                    if (x != null)                        mLog.error("Detected out-of-order insertion of change record for orphans commit/abort: change=" + op + ", orphan=" + x);                }            }        } else {            // When a checkpoint is encountered, discard all ops except            // those listed in the checkpoint.            if (op instanceof Checkpoint) {                Checkpoint ckpt = (Checkpoint) op;                Set txns = ckpt.getActiveTxns();                if (txns.size() > 0) {                    synchronized (mOpsMapGuard) {                        if (mOpsMap.size() != txns.size()) {                            // Unexpected discrepancy                            if (mLog.isDebugEnabled()) {                                StringBuffer sb1 = new StringBuffer("Current Uncommitted Ops: ");                                StringBuffer sb2 = new StringBuffer("Checkpoint Uncommitted Ops: ");                                int i = 0;                                for (Iterator it = mOpsMap.keySet().iterator(); it.hasNext(); i++) {                                	TransactionId id = (TransactionId) it.next();                                    if (i > 0)                                        sb1.append(", ");                                    sb1.append(id);                                }                                i = 0;                                for (Iterator it = txns.iterator(); it.hasNext(); i++) {                                    TransactionId id = (TransactionId) it.next();                                    if (i > 0)                                        sb2.append(", ");                                    sb2.append(id);                                }                                mLog.info("Checkpoint discrepancy: # current uncommitted ops = " + mOpsMap.size() +                                          ", # checkpoint uncommitted ops = " + txns.size() +                                          "\nMAP DUMP:\n" + sb1.toString() + "\n" + sb2.toString());                            }                        }                    }                } else {                    synchronized (mOpsMapGuard) {                        if (mOpsMap.size() != 0) {                            // Unexpected discrepancy                            if (mLog.isDebugEnabled()) {                                StringBuffer sb1 = new StringBuffer("Current Uncommitted Ops: ");                                int i = 0;                                for (Iterator it = mOpsMap.keySet().iterator(); it.hasNext(); i++) {                                    TransactionId id = (TransactionId) it.next();                                    if (i > 0)                                        sb1.append(", ");                                    sb1.append(id);                                }                                mLog.info("Checkpoint discrepancy: # current uncommitted ops = " +                                          mOpsMap.size() + " instead of 0\nMAP DUMP:\n" +                                          sb1.toString());                            }                        }                    }                }            } else if (op.isEndMarker()) {                // Encountered COMMIT or ABORT.  Discard the                // corresponding op from map, and optionally execute the committed op.                RedoableOp prepareOp;                synchronized (mOpsMapGuard) {                    prepareOp = (RedoableOp) mOpsMap.remove(op.getTransactionId());                    if (prepareOp == null) {                        mHasOrphanOps = true;                        mLog.error("Commit/abort record encountered before corresponding change record (" + op + ")");                        TransactionId tid = op.getTransactionId();                        RedoableOp x = (RedoableOp) mOrphanOps.get(tid);                        if (x != null)                        	mLog.error("Op [" + op + "] is already in orphans map: value=" + x);                        mOrphanOps.put(tid, op);                    }                }                if (redoCommitted && prepareOp != null && (op instanceof CommitTxn) &&                	(startingTime == -1 || prepareOp.getTimestamp() >= startingTime)) {                	boolean allowRedo = false;                	if (mboxIDsMap == null) {                		// Caller doesn't care which mailbox(es) the op is for.                		allowRedo = true;                	} else {                        int opMailboxId = prepareOp.getMailboxId();                        if (prepareOp instanceof StoreIncomingBlob) {                            assert(opMailboxId == RedoableOp.MAILBOX_ID_ALL);                        	// special case for StoreIncomingBlob op that has                        	// a list of mailbox IDs.                            StoreIncomingBlob storeOp = (StoreIncomingBlob) prepareOp;                        	List<Integer> list = storeOp.getMailboxIdList();                        	if (list != null) {	                        	Set<Integer> opMboxIds = new HashSet<Integer>(list);                                for (Map.Entry<Integer, Integer> entry : mboxIDsMap.entrySet()) {                                    if (opMboxIds.contains(entry.getKey())) {                                        allowRedo = true;                                        // Replace the mailbox ID list in the op.  We're                                        // replaying it only for the target mailbox ID we're                                        // interested in.                                        List<Integer> newList =                                            new ArrayList<Integer>(mboxIDsMap.values());                                        storeOp.setMailboxIdList(newList);                                        break;                                    }                                }                        	} else {                        		// Prior to redolog version 1.0 StoreIncomingBlob                        		// didn't keep track of mailbox list.  Always recreate                        		// the blob since we don't know which mailboxes will                        		// need it.                        		allowRedo = true;                        	}                        } else if (opMailboxId == RedoableOp.MAILBOX_ID_ALL) {                        	// This case should be checked after StoreIncomingBlob                        	// case because StoreIncomingBlob has mailbox ID of                        	// MAILBOX_ID_ALL.                        	allowRedo = true;                        } else {                            for (Map.Entry<Integer, Integer> entry : mboxIDsMap.entrySet()) {                                if (opMailboxId == entry.getKey().intValue()) {                                    if (entry.getValue() != null) {                                        // restore to a different mailbox                                        prepareOp.setMailboxId(entry.getValue().intValue());                                    }                                    allowRedo = true;                                    break;                                }                            }                        }                	}                	if (allowRedo) {                        try {                            if (mLog.isDebugEnabled())                                mLog.debug("Redoing: " + prepareOp.toString());                            prepareOp.redo();                        } catch(Exception e) {                            throw ServiceException.FAILURE("Error executing redoOp", e);                        }                	}                }            }        }    }