Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
21481 rajender 1
/*
2
 * Copyright (C) 2011 The Android Open Source Project
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
 
17
package com.android.volley;
18
 
19
import android.os.Process;
20
 
21
import java.util.concurrent.BlockingQueue;
22
 
23
/**
24
 * Provides a thread for performing cache triage on a queue of requests.
25
 *
26
 * Requests added to the specified cache queue are resolved from cache.
27
 * Any deliverable response is posted back to the caller via a
28
 * {@link ResponseDelivery}.  Cache misses and responses that require
29
 * refresh are enqueued on the specified network queue for processing
30
 * by a {@link NetworkDispatcher}.
31
 */
32
public class CacheDispatcher extends Thread {
33
 
34
    private static final boolean DEBUG = VolleyLog.DEBUG;
35
 
36
    /** The queue of requests coming in for triage. */
37
    private final BlockingQueue<Request<?>> mCacheQueue;
38
 
39
    /** The queue of requests going out to the network. */
40
    private final BlockingQueue<Request<?>> mNetworkQueue;
41
 
42
    /** The cache to read from. */
43
    private final Cache mCache;
44
 
45
    /** For posting responses. */
46
    private final ResponseDelivery mDelivery;
47
 
48
    /** Used for telling us to die. */
49
    private volatile boolean mQuit = false;
50
 
51
    /**
52
     * Creates a new cache triage dispatcher thread.  You must call {@link #start()}
53
     * in order to begin processing.
54
     *
55
     * @param cacheQueue Queue of incoming requests for triage
56
     * @param networkQueue Queue to post requests that require network to
57
     * @param cache Cache interface to use for resolution
58
     * @param delivery Delivery interface to use for posting responses
59
     */
60
    public CacheDispatcher(
61
            BlockingQueue<Request<?>> cacheQueue, BlockingQueue<Request<?>> networkQueue,
62
            Cache cache, ResponseDelivery delivery) {
63
        mCacheQueue = cacheQueue;
64
        mNetworkQueue = networkQueue;
65
        mCache = cache;
66
        mDelivery = delivery;
67
    }
68
 
69
    /**
70
     * Forces this dispatcher to quit immediately.  If any requests are still in
71
     * the queue, they are not guaranteed to be processed.
72
     */
73
    public void quit() {
74
        mQuit = true;
75
        interrupt();
76
    }
77
 
78
    @Override
79
    public void run() {
80
        if (DEBUG) VolleyLog.v("start new dispatcher");
81
        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
82
 
83
        // Make a blocking call to initialize the cache.
84
        mCache.initialize();
85
 
86
        while (true) {
87
            try {
88
                // Get a request from the cache triage queue, blocking until
89
                // at least one is available.
90
                final Request<?> request = mCacheQueue.take();
91
                request.addMarker("cache-queue-take");
92
 
93
                // If the request has been canceled, don't bother dispatching it.
94
                if (request.isCanceled()) {
95
                    request.finish("cache-discard-canceled");
96
                    continue;
97
                }
98
 
99
                // Attempt to retrieve this item from cache.
100
                Cache.Entry entry = mCache.get(request.getCacheKey());
101
                if (entry == null) {
102
                    request.addMarker("cache-miss");
103
                    // Cache miss; send off to the network dispatcher.
104
                    mNetworkQueue.put(request);
105
                    continue;
106
                }
107
 
108
                // If it is completely expired, just send it to the network.
109
                if (entry.isExpired()) {
110
                    request.addMarker("cache-hit-expired");
111
                    request.setCacheEntry(entry);
112
                    mNetworkQueue.put(request);
113
                    continue;
114
                }
115
 
116
                // We have a cache hit; parse its data for delivery back to the request.
117
                request.addMarker("cache-hit");
118
                Response<?> response = request.parseNetworkResponse(
119
                        new NetworkResponse(entry.data, entry.responseHeaders));
120
                request.addMarker("cache-hit-parsed");
121
 
122
                if (!entry.refreshNeeded()) {
123
                    // Completely unexpired cache hit. Just deliver the response.
124
                    mDelivery.postResponse(request, response);
125
                } else {
126
                    // Soft-expired cache hit. We can deliver the cached response,
127
                    // but we need to also send the request to the network for
128
                    // refreshing.
129
                    request.addMarker("cache-hit-refresh-needed");
130
                    request.setCacheEntry(entry);
131
 
132
                    // Mark the response as intermediate.
133
                    response.intermediate = true;
134
 
135
                    // Post the intermediate response back to the user and have
136
                    // the delivery then forward the request along to the network.
137
                    mDelivery.postResponse(request, response, new Runnable() {
138
                        @Override
139
                        public void run() {
140
                            try {
141
                                mNetworkQueue.put(request);
142
                            } catch (InterruptedException e) {
143
                                // Not much we can do about this.
144
                            }
145
                        }
146
                    });
147
                }
148
 
149
            } catch (InterruptedException e) {
150
                // We may have been interrupted because it was time to quit.
151
                if (mQuit) {
152
                    return;
153
                }
154
                continue;
155
            }
156
        }
157
    }
158
}