void addDFile(XmlPatch.DFileInfo df) { lock (mDFS) { if (mDFS.ContainsKey(df.id)) { return; } mDFS[df.id] = df; } }
void CDNFileDownThread(object param) { int threadIdx = (int)param; //Log.I("cdn sub thread start",Log.Tag.Update); XmlPatch.DFileInfo df = null; byte[] buf = new byte[RecvBuffSize]; int pLen = mThis.mDataPath.Length; int retryTimes = 0; while (!mError) { if (retryTimes <= 0) {//取下一个下载文件 lock (mLock) { if (mIDS.Count <= 0) { break; } mIndex = ++mIndex % mIDS.Count; df = mThis.lockDFile(mIDS[mIndex]); if (df == null) { continue; } if (df.size <= 0) { mIDS.RemoveAt(mIndex); continue; } } } HttpWebResponse rt = null; FileStream fs = null; Stream st = null; try { string savePath = df.path; string tmpPath = savePath + "." + mThis.mNewVersion + ".tmp"; fs = File.Exists(tmpPath)?new FileStream(tmpPath, FileMode.Append, FileAccess.Write, FileShare.Write):new FileStream(tmpPath, FileMode.Create); int tmpSize = (int)fs.Length; if (tmpSize < df.size) { mHWRS[threadIdx] = HttpWebRequest.Create(new Uri(mThis.mUrl + savePath.Substring(pLen))) as HttpWebRequest; //mHWRS[threadIdx].KeepAlive = true;//保持连接,否则消耗服务器的连接数,有的服务器设置会强制关闭连接/ mHWRS[threadIdx].KeepAlive = false; mHWRS[threadIdx].Timeout = TimeOut; mHWRS[threadIdx].ReadWriteTimeout = TimeOut; mHWRS[threadIdx].AddRange("bytes", tmpSize);//必须在GetResponse之前设置 rt = mHWRS[threadIdx].GetResponse() as HttpWebResponse; st = rt.GetResponseStream(); int size = ((int)df.size) - tmpSize; int n = 0; while (size > 0) { n = st.Read(buf, 0, size > RecvBuffSize?RecvBuffSize:size); if (n <= 0) { throw new Exception("HttpWebResponse read exception"); } fs.Write(buf, 0, n); size -= n; Interlocked.Add(ref mDownSize, n); } } fs.Close(); if (File.Exists(savePath)) { File.Delete(savePath); } File.Move(tmpPath, savePath); if (df.md5 != FileUtils.GetMd5Hash(savePath)) { File.Delete(savePath); Interlocked.Add(ref mDownSize, -df.size); throw new Exception("data md5 error"); } retryTimes = 0; df.size = 0;//标记文件下载完成 df.locked = false; } catch (Exception e) { ++retryTimes; if (mCancel || retryTimes >= 3) { mError = true; df.locked = false; Log.e("download failed file=" + df.path, Log.Tag.Update); Log.e(e, Log.Tag.Update); } else { Log.i("retry download file=" + df.path, Log.Tag.Update); Thread.Sleep(300); } } finally { if (null != fs) { fs.Close(); } if (null != st) { st.Close(); } if (null != rt) { rt.Close(); } } } Interlocked.Increment(ref mExitCount); //Log.I("cdn sub thread exit", Log.Tag.Update); }
void CDNDownThread(object param) { float progress = 0; Action action = Action.DownXml; try { //获取版本配置文件/ EventMgr.single.PostEvent("UpdateEvent", new UpdateEvent(this, progress, State.Doing, action)); if (mThis.mPatch.getVersion() != mThis.mNewVersion) { mHWR = HttpWebRequest.Create(new Uri(mThis.mUrl + "version.xml")) as HttpWebRequest; mHWR.KeepAlive = false; mHWR.Timeout = TimeOut; mHWR.ReadWriteTimeout = TimeOut; HttpWebResponse rt = mHWR.GetResponse() as HttpWebResponse; recvXml(mThis.mDataPath + "version.xml", rt.GetResponseStream(), (int)rt.ContentLength); rt.Close(); mTotalSize = 0; } mHWR = null; //计算下载文件 if (mTotalSize <= 0) { action = Action.CalcSize; mIDS = new List <int>(); mParts = mThis.mPatch.getDepends(mParts); List <XmlPatch.DFileInfo> dfs = mThis.mPatch.listDownFiles(delegate(float percent){ EventMgr.single.PostEvent("UpdateEvent", new UpdateEvent(this, progress = percent, State.Doing, action)); }, ref mCancel, mParts); long size = 0; long tmpSize = 0; for (int i = 0, max = dfs.Count; i < max; ++i) { XmlPatch.DFileInfo df = dfs[i]; mThis.addDFile(dfs[i]); mIDS.Add(df.id); size += df.size; FileInfo f = new FileInfo(df.path + "." + mThis.mNewVersion + ".tmp"); if (f.Exists) { tmpSize += f.Length; } } mTotalSize = size; mDownSize = tmpSize; System.GC.Collect(); if ((Action)param == Action.CalcSize) { EventMgr.single.PostEvent("UpdateEvent", new UpdateEvent(this, progress, State.Idle, action)); return; } } } catch (Exception e) { mHWR = null; mError = true; Log.e(e, Log.Tag.Update); EventMgr.single.PostEvent("UpdateEvent", new UpdateEvent(this, progress, State.Failed, action)); return; } //开启文件下载线程/ progress = mTotalSize > 0?1.0f * Interlocked.Read(ref mDownSize) / mTotalSize:1; action = Action.DownFile; EventMgr.single.PostEvent("UpdateEvent", new UpdateEvent(this, progress, State.Doing, action)); List <Thread> lsThread = new List <Thread> (); for (int i = 0; i < mHWRS.Length; ++i) { Thread t = new Thread(new ParameterizedThreadStart(CDNFileDownThread)); lsThread.Add(t); t.Start(i); } //通知显示资源下载进度/ while (Interlocked.Read(ref mExitCount) < lsThread.Count) { progress = mTotalSize > 0?1.0f * Interlocked.Read(ref mDownSize) / mTotalSize:1; EventMgr.single.PostEvent("UpdateEvent", new UpdateEvent(this, progress, State.Doing, action)); Thread.Sleep(100); } //等待下载线程结束/ for (int i = 0; i < lsThread.Count; ++i) { lsThread[i].Join(); } //解压lua脚本 mError = !unzipLua(ref action, ref progress); //=========== Log.i("cdn main thread exit,task name=" + this.mName, Log.Tag.Update); if (!mError) { //通知更新完成 EventMgr.single.PostEvent("UpdateEvent", new UpdateEvent(this, 1, State.Completed, action)); } else { Thread.Sleep(500); EventMgr.single.PostEvent("UpdateEvent", new UpdateEvent(this, progress, State.Failed, action)); } }