コード例 #1
0
 /// <summary>
 /// 新增缓存数据
 /// </summary>
 public void Put(string key, Entry entry)
 {
     lock (this)
     {
         PruneIfNeeded(entry.Data.Length);
         var file = GetFileForKey(key);
         try
         {
             var         fos     = file.Open(FileMode.OpenOrCreate);
             CacheHeader e       = new CacheHeader(key, entry);
             bool        success = e.WriteHeader(fos);
             if (!success)
             {
                 fos.Close();
                 VolleyLog.D("Failed to write header for {0}", file.FullName);
                 throw new IOException();
             }
             fos.Write(entry.Data, 0, entry.Data.Length);
             fos.Close();
             PutEntry(key, e);
             return;
         }
         catch (IOException) { }
         file.Delete();
         if (File.Exists(file.FullName))
         {
             VolleyLog.D("Could not clean up file {0}", file.FullName);
         }
     }
 }
コード例 #2
0
 public void Finish(String tag)
 {
     if (mRequestQueue != null)
     {
         mRequestQueue.Finish(this);
     }
     if (MarkerLog.ENABLED)
     {
         long threadId = Java.Lang.Thread.CurrentThread().Id;
         if (Looper.MyLooper() != Looper.MainLooper)
         {
             Handler mainThread = new Handler(Looper.MainLooper);
             mainThread.Post(() =>
             {
                 mEventLog.Add(tag, threadId);
                 mEventLog.Finish(this.ToString());
             });
             return;
         }
         mEventLog.Add(tag, threadId);
         mEventLog.Finish(this.ToString());
     }
     else
     {
         long requestTime = SystemClock.ElapsedRealtime() - mRequestBirthTime;
         if (requestTime >= SLOW_REQUEST_THRESHOLD_MS)
         {
             VolleyLog.D("{0} ms:{1}", requestTime, this.ToString());
         }
     }
 }
コード例 #3
0
 /// <summary>
 /// 输出请求完成的信息(仅限调试)
 /// </summary>
 private void LogSlowRequests(long requestLifetime, Request request, byte[] responseContents, HttpStatusCode statusCode)
 {
     if (DEBUG || requestLifetime > SLOW_REQUEST_THRESHOLD_MS)
     {
         VolleyLog.D("HTTP response for request=<{0}> [lifetime={1}],[size={2}], [rc={3}],[retryCount={4}]", requestLifetime, requestLifetime,
                     responseContents != null ? responseContents.Length.ToString() : "null",
                     statusCode, request.GetRetryPolicy().CurrentRetryCount);
     }
 }
コード例 #4
0
 /// <summary>
 /// 删除缓存数据
 /// </summary>
 public void Remove(string key)
 {
     lock (this)
     {
         var fi = GetFileForKey(key);
         fi.Delete();
         RemoveEntry(key);
         if (File.Exists(fi.FullName))
         {
             VolleyLog.D("Could not delete cache entry for key={0},filename={1}", key, fi.FullName);
         }
     }
 }
コード例 #5
0
 public override byte[] GetBody()
 {
     try
     {
         return(mRequestBody == null ? null : Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(mRequestBody)));
     }
     catch (Exception)
     {
         VolleyLog.WTF("Unsupported Encoding while trying to get the bytes of {0} using {1}",
                       mRequestBody, PROTOCOL_CHARSET);
         return(null);
     }
 }
コード例 #6
0
        public Request Add(Request request)
        {
            request.SetRequestQueue(this);

            //添加到当前请求列表中
            lock (mCurrentRequests)
            {
                mCurrentRequests.Add(request);
            }

            request.Sequence = GetSequenceNumber();
            request.AddMarker("add-to-queue");

            //如果请求不需要缓存则直接加入到网络请求队列中
            if (!request.ShouldCache())
            {
                mNetworkQueue.Enqueue(request);
                return(request);
            }

            /*
             * 先将请求加入到缓存请求队列中,并且将后面的重复请求
             * 添加到mWaitingRequests中,目的是当第一个请求完成后
             * 后面重复的请求直接添加到缓存请求队列中,避免重复对
             * 网络进行请求
             */
            lock (mWaitingRequests)
            {
                String cacheKey = request.GetCacheKey();
                if (mWaitingRequests.ContainsKey(cacheKey))
                {
                    Queue <Request> stagedRequests = null;
                    mWaitingRequests.TryGetValue(cacheKey, out stagedRequests);
                    if (stagedRequests == null)
                    {
                        stagedRequests = new Queue <Request>();
                    }
                    stagedRequests.Enqueue(request);
                    if (VolleyLog.DEBUG)
                    {
                        VolleyLog.V("Request for cacheKey={0} is in flight,putting on hold.", cacheKey);
                    }
                }
                else
                {
                    mWaitingRequests.Add(cacheKey, null);
                    mCacheQueue.Enqueue(request);
                }
                return(request);
            }
        }
コード例 #7
0
        /// <summary>
        /// 初始化缓存
        /// </summary>
        public void Initialize()
        {
            lock (this)
            {
                if (!mRootDirectory.Exists)
                {
                    mRootDirectory.Create();
                    if (!mRootDirectory.Exists)
                    {
                        VolleyLog.E("Unable to create cache dir {0}", mRootDirectory.FullName);
                    }
                    return;
                }

                //获取已缓存文件并添加到缓存表中
                FileInfo[] files = mRootDirectory.GetFiles();
                if (files == null)
                {
                    return;
                }
                foreach (FileInfo file in files)
                {
                    FileStream fs = null;
                    try
                    {
                        fs = file.Open(FileMode.OpenOrCreate);
                        CacheHeader entry = CacheHeader.ReadHeader(fs);
                        entry.Size = fs.Length;
                        PutEntry(entry.Key, entry);
                    }
                    catch (IOException)
                    {
                        if (file != null)
                        {
                            file.Delete();
                        }
                    }
                    finally
                    {
                        try
                        {
                            if (fs != null)
                            {
                                fs.Close();
                            }
                        }
                        catch (IOException) { }
                    }
                }
            }
        }
コード例 #8
0
 public override Response ParseNetworkResponse(NetworkResponse response)
 {
     lock (sDecodeLock)
     {
         try
         {
             return(DoParse(response));
         }
         catch (Java.Lang.OutOfMemoryError e)
         {
             VolleyLog.E("Caught OOM for {0} byte image,url={1}", response.Data.Length, Url);
             return(Response.Error(new ParseError(e)));
         }
     }
 }
コード例 #9
0
 /// <summary>
 /// 清除缓存
 /// </summary>
 public void Clear()
 {
     lock (this)
     {
         FileInfo[] files = mRootDirectory.GetFiles();
         if (files != null)
         {
             foreach (FileInfo file in files)
             {
                 file.Delete();
             }
         }
         mEntries.Clear();
         mTotalSize = 0;
         VolleyLog.D("Cache cleared.");
     }
 }
コード例 #10
0
        /// <summary>
        /// 当需要的空间大于指定空间后清除部分缓存
        /// </summary>
        private void PruneIfNeeded(int neededSpace)
        {
            if (mTotalSize + neededSpace < mMaxCacheSizeInBytes)
            {
                return;
            }

            if (VolleyLog.DEBUG)
            {
                VolleyLog.V("Pruning old cache entries.");
            }

            long before      = mTotalSize;
            int  prunedFiles = 0;
            long startTime   = SystemClock.ElapsedRealtime();
            Dictionary <string, CacheHeader> delDic = new Dictionary <string, CacheHeader>();

            foreach (KeyValuePair <String, CacheHeader> pair in mEntries)
            {
                CacheHeader e  = pair.Value;
                var         fi = GetFileForKey(e.Key);
                fi.Delete();
                if (!File.Exists(fi.FullName))
                {
                    mTotalSize -= e.Size;
                }
                else
                {
                    VolleyLog.D("Could not delete cache entry for key={0},filename={1}", e.Key, GetFilenameForKey(e.Key));
                }
                prunedFiles++;
                delDic.Add(pair.Key, pair.Value);
                if (mTotalSize + neededSpace < mMaxCacheSizeInBytes * HYSTERESIS_FACTOR)
                {
                    break;
                }
            }
            foreach (KeyValuePair <string, CacheHeader> del in delDic)
            {
                mEntries.Remove(del.Key);
            }
            if (VolleyLog.DEBUG)
            {
                VolleyLog.V("Pruned {0} files,{1} bytes,{2} ms", prunedFiles, (mTotalSize - before), SystemClock.ElapsedRealtime() - startTime);
            }
        }
コード例 #11
0
        public void Finish(Request request)
        {
            lock (mCurrentRequests)
            {
                mCurrentRequests.Remove(request);
            }

            lock (mFinishedListeners)
            {
                foreach (IRequestFinishedListener listener in mFinishedListeners)
                {
                    listener.OnRequestFinished(request);
                }
            }

            if (request.ShouldCache())
            {
                /*
                 * 在该请求完成并缓存后将后面其他重复的
                 * 请求直接加入到缓存请求队列中
                 */
                lock (mWaitingRequests)
                {
                    String          cacheKey       = request.GetCacheKey();
                    Queue <Request> waitingRequets = null;
                    mWaitingRequests.TryGetValue(cacheKey, out waitingRequets);
                    mWaitingRequests.Remove(cacheKey);
                    if (waitingRequets != null)
                    {
                        if (VolleyLog.DEBUG)
                        {
                            VolleyLog.V("Releasing {0} waiting requests for cacheKey={1}", waitingRequets.Count, cacheKey);
                        }
                        foreach (Request addrequest in waitingRequets)
                        {
                            mCacheQueue.Enqueue(addrequest);
                        }
                    }
                }
            }
        }
コード例 #12
0
 /// <summary>
 /// 将缓存信息写入流中
 /// </summary>
 public bool WriteHeader(Stream output)
 {
     try
     {
         DiskBasedCache.WriteInt(output, DiskBasedCache.CACHE_MAGIC);
         DiskBasedCache.WriteString(output, Key);
         DiskBasedCache.WriteString(output, ETag == null ? "" : ETag);
         DiskBasedCache.WriteLong(output, ServerDate);
         DiskBasedCache.WriteLong(output, LastModified);
         DiskBasedCache.WriteLong(output, Ttl);
         DiskBasedCache.WriteLong(output, SoftTtl);
         DiskBasedCache.WriteStringStringMap(ResponseHeaders, output);
         output.Flush();
         return(true);
     }
     catch (Exception e)
     {
         VolleyLog.D("{0}", e.ToString());
         return(false);
     }
 }
コード例 #13
0
        /// <summary>
        /// 获取缓存数据
        /// </summary>
        public Entry Get(string key)
        {
            lock (this)
            {
                CacheHeader entry = null;
                mEntries.TryGetValue(key, out entry);
                if (entry == null)
                {
                    return(null);
                }

                FileInfo   file = GetFileForKey(key);
                FileStream fs   = null;
                try
                {
                    fs = file.Open(FileMode.OpenOrCreate);
                    CacheHeader.ReadHeader(fs);
                    byte[] data = StreamToBytes(fs, (int)(fs.Length - fs.Position));
                    return(entry.ToCacheEntry(data));
                }
                catch (IOException e)
                {
                    VolleyLog.D("{0}:{1}", file.FullName, e.ToString());
                }
                finally
                {
                    if (fs != null)
                    {
                        try
                        {
                            fs.Close();
                        }
                        catch (IOException) { }
                    }
                }
                return(null);
            }
        }
コード例 #14
0
        protected void LogError(String what, String url, long start)
        {
            long now = SystemClock.ElapsedRealtime();

            VolleyLog.V("HTTP ERROR({0}) {1} ms to fetch {2}", what, (now - start), url);
        }
コード例 #15
0
        /// <summary>
        /// 处理请求的核心
        /// 不包含底层请求的创建
        /// </summary>
        public NetworkResponse PerformRequest(Request request)
        {
            long requestStart = SystemClock.ElapsedRealtime();

            while (true)
            {
                HttpWebResponse             httpResponse     = null;
                byte[]                      responseContents = null;
                Dictionary <String, String> responseHeaders  = null;
                try
                {
                    Dictionary <String, String> headers = new Dictionary <string, string>();
                    AddCacheHeaders(headers, request.CacheEntry);

                    //处理请求
                    httpResponse = mHttpStack.PerformRequest(request, headers);

                    var statusCode = httpResponse.StatusCode;
                    responseHeaders = ConvertHeaders(httpResponse.Headers);

                    if (statusCode == HttpStatusCode.MovedPermanently || statusCode == HttpStatusCode.Moved)
                    {
                        String newUrl = responseHeaders["Location"];
                        request.SetRedirectUrl(newUrl);
                    }

                    //获取请求到的内容
                    Stream output = httpResponse.GetResponseStream();
                    if (output != null)
                    {
                        responseContents = EntityToBytes(output);
                    }
                    else
                    {
                        responseContents = new byte[0];
                    }

                    long requestLifetime = SystemClock.ElapsedRealtime() - requestStart;
                    LogSlowRequests(requestLifetime, request, responseContents, statusCode);

                    if (statusCode < HttpStatusCode.OK || (int)statusCode > 299)
                    {
                        throw new IOException();
                    }
                    return(new NetworkResponse(statusCode, responseContents, responseHeaders, false,
                                               SystemClock.ElapsedRealtime() - requestStart));
                }
                catch (WebException ex)
                {
                    if (ex.Response != null)
                    {
                        var result = ex.Response as HttpWebResponse;
                        if (result.StatusCode == HttpStatusCode.NotModified)
                        {
                            Entry entry = request.CacheEntry;
                            if (entry == null)
                            {
                                return(new NetworkResponse(HttpStatusCode.NotModified, null,
                                                           responseHeaders, true,
                                                           SystemClock.ElapsedRealtime() - requestStart));
                            }
                            //entry.ResponseHeaders = entry.ResponseHeaders.Intersect(responseHeaders).ToDictionary(x => x.Key, x => x.Value);
                            return(new NetworkResponse(HttpStatusCode.NotModified, entry.Data,
                                                       entry.ResponseHeaders, true,
                                                       SystemClock.ElapsedRealtime() - requestStart));
                        }
                    }
                    throw new NetworkError(ex);
                }
                catch (TimeoutException)
                {
                    AttempRetryOnException("connection", request, new TimeoutError());
                }
                catch (IOException e)
                {
                    HttpStatusCode  statusCode      = 0;
                    NetworkResponse networkResponse = null;
                    if (httpResponse != null)
                    {
                        statusCode = httpResponse.StatusCode;
                    }
                    else
                    {
                        throw new NoConnectionError(e);
                    }
                    if (statusCode == HttpStatusCode.MovedPermanently)
                    {
                        VolleyLog.E("Request at {0} has been redirected to {1}", request.OriginUrl, request.Url);
                    }
                    else
                    {
                        VolleyLog.E("Unexpected response code {0} for {1}", statusCode, request.Url);
                    }
                    if (responseContents != null)
                    {
                        networkResponse = new NetworkResponse(statusCode, responseContents,
                                                              responseHeaders, false, SystemClock.ElapsedRealtime() - requestStart);
                        if (statusCode == HttpStatusCode.Unauthorized || statusCode == HttpStatusCode.Forbidden)
                        {
                            AttempRetryOnException("auth", request, new AuthFailureError());
                        }
                        else if (statusCode == HttpStatusCode.MovedPermanently || statusCode == HttpStatusCode.Moved)
                        {
                            AttempRetryOnException("redirect", request, new AuthFailureError(networkResponse));
                        }
                        else
                        {
                            throw new ServerError(networkResponse);
                        }
                    }
                    else
                    {
                        throw new NetworkError(networkResponse);
                    }
                }
            }
        }
コード例 #16
0
        public override void Run()
        {
            Process.SetThreadPriority(ThreadPriority.Background);
            while (true)
            {
                long    startTimeMs = SystemClock.ElapsedRealtime();
                Request request;
                if (!mQueue.TryDequeue(out request))
                {
                    if (mQuit)
                    {
                        return;
                    }
                    continue;
                }

                try
                {
                    request.AddMarker("network-queue-take");

                    if (request.IsCanceled)
                    {
                        request.Finish("network-discard-cancelled");
                        continue;
                    }

                    AddTrafficStatsTag(request);

                    NetworkResponse networkResponse = mNetwork.PerformRequest(request);
                    request.AddMarker("network-http-complete");

                    if (networkResponse.NotModified && request.HasHadResponseDelivered())
                    {
                        request.Finish("not-modified");
                        continue;
                    }

                    Response response = request.ParseNetworkResponse(networkResponse);
                    request.AddMarker("network-parse-complete");

                    if (request.ShouldCache() && response.CacheEntry != null)
                    {
                        mCache.Put(request.GetCacheKey(), response.CacheEntry);
                        request.AddMarker("network-cache-written");
                    }

                    request.MarkDelivered();
                    mDelivery.PostResponse(request, response);
                }
                catch (VolleyError volleyError)
                {
                    volleyError.NetworkTimeMs = SystemClock.ElapsedRealtime() - startTimeMs;
                    ParseAndDeliverNetworkError(request, volleyError);
                }
                catch (Exception e)
                {
                    VolleyLog.E(e, "Unhandled exception {0}", e.ToString());
                    VolleyError volleyError = new VolleyError(e);
                    volleyError.NetworkTimeMs = SystemClock.ElapsedRealtime() - startTimeMs;
                    mDelivery.PostError(request, volleyError);
                }
            }
        }
コード例 #17
0
        public override void Run()
        {
            if (DEBUG)
            {
                VolleyLog.V("start new dispatcher");
            }
            Process.SetThreadPriority(ThreadPriority.Background);
            mCache.Initialize();

            while (true)
            {
                try
                {
                    Request request = null;
                    if (!mCacheQueue.TryDequeue(out request))
                    {
                        if (mQuit)
                        {
                            return;
                        }
                        continue;
                    }
                    request.AddMarker("cache-queue-take");

                    //请求是否已取消
                    if (request.IsCanceled)
                    {
                        request.Finish("cache-discard-canceled");
                        continue;
                    }

                    //不存在该缓存
                    Entry entry = mCache.Get(request.GetCacheKey());
                    if (entry == null)
                    {
                        request.AddMarker("cache-miss");
                        mNetworkQueue.Enqueue(request);
                        continue;
                    }

                    //缓存过期
                    if (entry.IsExpired)
                    {
                        request.AddMarker("cache-hit-expired");
                        request.CacheEntry = entry;
                        mNetworkQueue.Enqueue(request);
                        continue;
                    }

                    //缓存命中
                    request.AddMarker("cache-hit");
                    Response response = request.ParseNetworkResponse(new NetworkResponse(entry.Data, entry.ResponseHeaders));
                    request.AddMarker("cache-hit-parsed");

                    //判断缓存是否需要更新
                    if (!entry.RefreshNeeded())
                    {
                        mDelivery.PostResponse(request, response);
                    }
                    else
                    {
                        request.AddMarker("cache-hit-refresh-needed");
                        request.CacheEntry    = entry;
                        response.Intermediate = true;
                        mDelivery.PostResponse(request, response, () =>
                        {
                            mNetworkQueue.Enqueue(request);
                        });
                    }
                }
                catch (Exception)
                {
                    if (mQuit)
                    {
                        return;
                    }
                    continue;
                }
            }
        }