/*
 * 
 * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
 * 
 * The contents of this file are subject to the Sun Community Source
 * License v3.0/Jini Technology Specific Attachment v 1.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://wwws.sun.com/software/jini/licensing/SCSL3_JiniTSA1.html.
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 * the License for the specific language governing rights and limitations
 * under the License.
 * 
 * The Reference Code is Jini Technology Core Platform code, v2.0. The
 * Developer of the Reference Code is Sun Microsystems, Inc.
 * 
 * Contributor(s): Sun Microsystems, Inc.
 * 
 * The contents of this file comply with the Jini Technology Core
 * Platform Compatibility Kit, v2.0A.
 * 
 * Tester(s): Sun Microsystems, Inc.
 * 
 * Test Platform(s):
 * Java 2 SDK, Standard Edition, Version 1.4.2_03 for Solaris(TM)SPARC/x86
 * Java 2 SDK, Standard Edition, Version 1.4.2_03 for Linux (Intel x86)
 * Java 2 SDK, Standard Edition, Version 1.4.2_03 for Windows (Intel Platform)
 * 
 */
package com.sun.jini.outrigger;

/**
 * Subclass of <code>QueryWatcher</code> for non-transactional reads.
 * Resolves with the first matching transition where the transaction
 * is <code>null</code> and the entry is visible (the entry's current
 * state is ignored).
 */
class ReadWatcher extends QueryWatcher {
    /**
     * Create a new <code>ReadWatcher</code>.
     * @param expiration the initial expiration time
     *        for this <code>TransitionWatcher</code> in 
     *        milliseconds since the beginning of the epoch.
     * @param timestamp the value that is used
     *        to sort <code>TransitionWatcher</code>s.
     * @param startOrdinal the highest ordinal associated
     *        with operations that are considered to have occurred 
     *        before the operation associated with this watcher.
     */
    ReadWatcher(long expiration, long timestamp, long startOrdinal) {
	super(expiration, timestamp, startOrdinal);
    }

    boolean isInterested(EntryTransition transition, long ordinal) {
	/* Note, !isResolved() without the lock will result only in
	 * false positives, not false negatives - it will only
	 * cause isInterested() to return false if we are resolved,
	 * we may still return true if we are resolved though.
	 */
	return (ordinal>startOrdinal) && !isResolved() && 
	    transition.isAvailable() && (transition.getTxn() == null);
    }

    synchronized void process(EntryTransition transition, long now) {
	// If isInterested was true then we can just resolve
	if (isResolved())
	    return; // Already done.

	// As long as it existed at one time we can return it
	resolve(transition.getHandle().rep(), null);
    }

    synchronized boolean catchUp(EntryTransition transition, long now) {
	if (isResolved())
	    return true;

	if (transition.isAvailable() && (transition.getTxn() == null)) {
	    /* As long as it existed at one time and we could have seen it
	     * we can return it
	     */
	    resolve(transition.getHandle().rep(), null);
	    return true;
	}

	return false;
    }
}

