Android Open Source - getrest In Memory Request Manager






From Project

Back to project page getrest.

License

The source code is released under:

Apache License

If you think the Android project getrest listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright 2012 Alexey Hanin/*from w  ww  . jav a  2  s.  com*/
 *
 * Licensed under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package getrest.android.client;

import getrest.android.core.*;
import getrest.android.core.Error;
import getrest.android.request.RequestManager;
import getrest.android.request.RequestStatus;
import getrest.android.util.Logger;
import getrest.android.util.LoggerFactory;

import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class InMemoryRequestManager implements RequestManager {

    private static final Logger LOGGER = LoggerFactory.getLogger("getrest.reqman");

    private final Map<String, RequestStatus> stateMap = new ConcurrentHashMap<String, RequestStatus>();

    private final Map<String, WeakValue<Request>> requestMap = new HashMap<String, WeakValue<Request>>();
    private final Map<String, WeakValue<Response>> responseMap = new HashMap<String, WeakValue<Response>>();

    private final ReferenceQueue<Object> gcQueue = new ReferenceQueue<Object>();

    private final Map<String, CandidateEntry> undeadQueue = new HashMap<String, CandidateEntry>();

    private static final long MAX_UNDEAD_AGE = 30000L;

    private static class WeakValue<T> extends SoftReference<T> {

        private String requestId;

        public WeakValue(String requestId, T referent, ReferenceQueue<? super T> q) {
            super(referent, q);
            this.requestId = requestId;
        }

        public String getRequestId() {
            return requestId;
        }
    }

    private class CleanupWorker implements Runnable {
        public void run() {
            while (true) {
                processQueue();
                processUndeadQueue();
                Thread.yield();
            }
        }
    }

    private void processQueue() {
        try {
            WeakValue<Object> ref;
            while ((ref = (WeakValue<Object>) gcQueue.remove()) != null) {
                final long now = System.currentTimeMillis();
                synchronized (undeadQueue) {
                    final Object obj = ref.get();
                    if (obj instanceof Request) {
                        final String requestId = ref.getRequestId();
                        final CandidateEntry candidateEntry = requireCandidateEntry(requestId);
                        candidateEntry.setRequest((Request) obj);
                        candidateEntry.setLastAccessedTime(now);
                    } else if (obj instanceof Response) {
                        final String requestId = ref.getRequestId();
                        final CandidateEntry candidateEntry = requireCandidateEntry(requestId);
                        candidateEntry.setResponse((Response) obj);
                        candidateEntry.setLastAccessedTime(now);
                    }
                }
            }
        } catch (InterruptedException e) {
            LOGGER.error("Interrupted exception", e);
        }
    }

    private void processUndeadQueue() {
        final long maxUndeadAge = System.currentTimeMillis() - MAX_UNDEAD_AGE;
        synchronized (undeadQueue) {
            final Set<String> enqueuedIds = new HashSet<String>();
            for (Map.Entry<String, CandidateEntry> entry : undeadQueue.entrySet()) {
                final CandidateEntry candidateEntry = entry.getValue();
                if (candidateEntry.getLastAccessedTime() < maxUndeadAge) {
                    enqueuedIds.add(entry.getKey());
                }
            }

            if (!enqueuedIds.isEmpty()) {
                undeadQueue.entrySet().removeAll(enqueuedIds);
                synchronized (requestMap) {
                    requestMap.keySet().removeAll(enqueuedIds);
                }
                synchronized (responseMap) {
                    responseMap.keySet().removeAll(enqueuedIds);
                }
            }
        }
    }

    private CandidateEntry requireCandidateEntry(final String requestId) {
        final CandidateEntry candidateEntry;
        synchronized (undeadQueue) {
            if (!undeadQueue.containsKey(requestId)) {
                candidateEntry = new CandidateEntry();
                undeadQueue.put(requestId, candidateEntry);
            } else {
                candidateEntry = undeadQueue.get(requestId);
            }
        }
        return candidateEntry;
    }

    public InMemoryRequestManager() {
        new Thread(new CleanupWorker()).start();
    }

    public void saveRequest(final Request request) {
        final String requestId = request.getRequestId();
        synchronized (requestMap) {
            if (stateMap.containsKey(requestId)) {
                throw new IllegalStateException("Request with id '" + requestId + "' is already registered");
            }
            requestMap.put(requestId, new WeakValue<Request>(requestId, request, gcQueue));
        }
    }

    public Request getRequest(final String requestId) {
        final WeakValue<Request> entry = requestMap.get(requestId);
        return entry != null ? entry.get() : null;
    }

    public void saveResponse(final String requestId, final Response response) {
        synchronized (requestMap) {
            final Request request = getRequest(requestId);
            if (request == null) {
                throw new IllegalStateException("Request must be acknowledged prior to response");
            }
            responseMap.put(requestId, new WeakValue<Response>(requestId, response, gcQueue));
        }
    }

    public Response getResponse(final String requestId) {
        final WeakValue<Response> entry = responseMap.get(requestId);
        return entry == null ? null : entry.get();
    }

    public void setRequestState(final String requestId, final RequestStatus status) {
        synchronized (stateMap) {
            final Request request = getRequest(requestId);
            if (request == null) {
                throw new IllegalStateException("Request must be acknowledged prior to response");
            }
            stateMap.put(requestId, status);
        }
    }

    public RequestStatus getRequestState(final String requestId) {
        return stateMap.get(requestId);
    }

    public void setRequestState(final String requestId, final ErrorState errorState, final String message) {
        final Request request = getRequest(requestId);
        if (request == null) {
            throw new IllegalStateException("Request is not acknowledged: " + requestId);
        }
        setRequestState(requestId, RequestStatus.ERROR);

        final Error error = new Error();
        error.setErrorState(errorState);
        error.setMessage(message);

        request.setError(error);
    }

    private class CandidateEntry {

        private Request request;
        private Response response;
        private long lastAccessedTime;

        public Request getRequest() {
            return request;
        }

        public void setRequest(final Request request) {
            this.request = request;
        }

        public Response getResponse() {
            return response;
        }

        public void setResponse(final Response response) {
            this.response = response;
        }

        public long getLastAccessedTime() {
            return lastAccessedTime;
        }

        public void setLastAccessedTime(final long lastAccessedTime) {
            this.lastAccessedTime = lastAccessedTime;
        }
    }

}




Java Source Code List

getrest.android.RestfulClient.java
getrest.android.client.InMemoryRequestManager.java
getrest.android.client.RequestCallbackFactory.java
getrest.android.client.RequestCallback.java
getrest.android.client.RequestExecutor.java
getrest.android.client.RequestFuture.java
getrest.android.client.RequestRegistry.java
getrest.android.client.impl.RequestEventRecord.java
getrest.android.client.impl.RequestFutureImpl.java
getrest.android.client.impl.RequestRegistryEditorImpl.java
getrest.android.client.impl.RequestRegistryEntryFactory.java
getrest.android.client.impl.RequestRegistryPreferencesImpl.java
getrest.android.client.impl.RestfulClientImpl.java
getrest.android.client.impl.TransactionalRequestEntryStorage.java
getrest.android.config.ConfigResolver.java
getrest.android.config.Config.java
getrest.android.config.DefaultContributor.java
getrest.android.config.HasConfig.java
getrest.android.config.ResourceContextContribution.java
getrest.android.config.ResourceContextContributor.java
getrest.android.config.ResourceNode.java
getrest.android.config.ResourcePath.java
getrest.android.core.BaseRequest.java
getrest.android.core.ErrorState.java
getrest.android.core.Error.java
getrest.android.core.HandlerException.java
getrest.android.core.HasHeaders.java
getrest.android.core.Header.java
getrest.android.core.HeadersHelper.java
getrest.android.core.Headers.java
getrest.android.core.Method.java
getrest.android.core.Pack.java
getrest.android.core.Request.java
getrest.android.core.Response.java
getrest.android.core.Status.java
getrest.android.exception.GetrestException.java
getrest.android.exception.GetrestRuntimeException.java
getrest.android.executor.Handler.java
getrest.android.executor.PostMethodPipeline.java
getrest.android.executor.RequestHandlerFactory.java
getrest.android.executor.RequestHandlerImpl.java
getrest.android.executor.RequestHandler.java
getrest.android.executor.RequestPipeline.java
getrest.android.http.HttpEntityRepresentation.java
getrest.android.http.HttpServiceRequestExecutor.java
getrest.android.http.RepresentationHttpEntity.java
getrest.android.request.RequestContext.java
getrest.android.request.RequestLifecycle.java
getrest.android.request.RequestManager.java
getrest.android.request.RequestStatus.java
getrest.android.resource.Marshaller.java
getrest.android.resource.Packer.java
getrest.android.resource.ResourceContextImpl.java
getrest.android.resource.ResourceContext.java
getrest.android.service.Broadcaster.java
getrest.android.service.Representation.java
getrest.android.service.RequestEventBus.java
getrest.android.service.RequestJob.java
getrest.android.service.RequestStateChangeEventWrapper.java
getrest.android.service.RequestWrapper.java
getrest.android.service.RestService.java
getrest.android.service.ServiceRequestExecutor.java
getrest.android.service.ServiceRequest.java
getrest.android.service.ServiceResponse.java
getrest.android.testapp.GetrestTestApplication.java
getrest.android.testapp.MainActivity.java
getrest.android.util.LoggerFactory.java
getrest.android.util.Logger.java
getrest.android.util.WorkerQueue.java