001/*
002 * ====================================================================
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *   http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied.  See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 * ====================================================================
020 *
021 * This software consists of voluntary contributions made by many
022 * individuals on behalf of the Apache Software Foundation.  For more
023 * information on the Apache Software Foundation, please see
024 * <http://www.apache.org/>.
025 *
026 */
027package org.apache.http.nio.pool;
028
029import java.util.concurrent.atomic.AtomicBoolean;
030import java.util.concurrent.atomic.AtomicReference;
031
032import org.apache.http.concurrent.BasicFuture;
033import org.apache.http.concurrent.Cancellable;
034import org.apache.http.nio.reactor.SessionRequest;
035import org.apache.http.pool.PoolEntry;
036import org.apache.http.util.Asserts;
037
038class LeaseRequest<T, C, E extends PoolEntry<T, C>> implements Cancellable {
039
040    private final T route;
041    private final Object state;
042    private final long connectTimeout;
043    private final long deadline;
044    private final BasicFuture<E> future;
045    private final AtomicReference<SessionRequest> sessionRequestRef;
046    private final AtomicBoolean completed;
047    private volatile E result;
048    private volatile Exception ex;
049
050    /**
051     * Contructor
052     * @param route route
053     * @param state state
054     * @param connectTimeout http connection timeout
055     * @param leaseTimeout timeout to wait in a request queue until kicked off
056     * @param future future callback
057     */
058    public LeaseRequest(
059            final T route,
060            final Object state,
061            final long connectTimeout,
062            final long leaseTimeout,
063            final BasicFuture<E> future) {
064        super();
065        this.route = route;
066        this.state = state;
067        this.connectTimeout = connectTimeout;
068        this.deadline = leaseTimeout > 0 ? System.currentTimeMillis() + leaseTimeout : Long.MAX_VALUE;
069        this.future = future;
070        this.sessionRequestRef = new AtomicReference<SessionRequest>(null);
071        this.completed = new AtomicBoolean(false);
072    }
073
074    public T getRoute() {
075        return this.route;
076    }
077
078    public Object getState() {
079        return this.state;
080    }
081
082    public long getConnectTimeout() {
083        return this.connectTimeout;
084    }
085
086    public long getDeadline() {
087        return this.deadline;
088    }
089
090    public boolean isDone() {
091        return this.completed.get();
092    }
093
094    public void attachSessionRequest(final SessionRequest sessionRequest) {
095        Asserts.check(this.sessionRequestRef.compareAndSet(null, sessionRequest), "Session request has already been set");
096    }
097
098    @Override
099    public boolean cancel() {
100        final boolean cancelled = this.completed.compareAndSet(false, true);
101        final SessionRequest sessionRequest = this.sessionRequestRef.getAndSet(null);
102        if (sessionRequest != null) {
103            sessionRequest.cancel();
104        }
105        return cancelled;
106    }
107
108    public void failed(final Exception ex) {
109        if (this.completed.compareAndSet(false, true)) {
110            this.ex = ex;
111        }
112    }
113
114    public void completed(final E result) {
115        if (this.completed.compareAndSet(false, true)) {
116            this.result = result;
117        }
118    }
119
120    public BasicFuture<E> getFuture() {
121        return this.future;
122    }
123
124    public E getResult() {
125        return this.result;
126    }
127
128    public Exception getException() {
129        return this.ex;
130    }
131
132    @Override
133    public String toString() {
134        final StringBuilder buffer = new StringBuilder();
135        buffer.append("[");
136        buffer.append(this.route);
137        buffer.append("][");
138        buffer.append(this.state);
139        buffer.append("]");
140        return buffer.toString();
141    }
142
143}