Binary files BitcasaDiff-20140714/BitcasaDiff/BitcasaDiff.rc and BitcasaDiff-20140716/BitcasaDiff/BitcasaDiff.rc differ
diff -urN BitcasaDiff-20140714/BitcasaDiff/listBitcasa.cpp BitcasaDiff-20140716/BitcasaDiff/listBitcasa.cpp
--- BitcasaDiff-20140714/BitcasaDiff/listBitcasa.cpp	2014-07-13 03:48:52.000000000 +0900
+++ BitcasaDiff-20140716/BitcasaDiff/listBitcasa.cpp	2014-07-15 21:35:40.000000000 +0900
@@ -296,7 +296,7 @@
 
 std::wstring RemoteFileHash(BitcasaAPI& API, std::string fileid, INT64 filesize, HashFilter::Hash hashtype)
 {
-	int retrycount = 10;
+	int retrycount = 3;
 	while (retrycount-- > 0){
 		HashFilter::hashfilter hasher(hashtype);
 		starttick = GetTick();
@@ -311,7 +311,7 @@
 			fwprintf(stderr, L"%I64d / %I64d bytes (%.2f %%) processed...(%.2f MiB/sec)\r", trans, size, 100.0*trans / size, (double)trans / (1024 * 1024) * 1000 / (nowtick - starttick));
 		});
 		if (!done){
-			fwprintf(stderr, L"\ndownload failed. retry...\n");
+			fwprintf(stderr, L"\ndownload failed. \n");
 			continue;
 		}
 		fwprintf(stderr, L"\ndone.\n");
diff -urN BitcasaDiff-20140714/BitcasaDLL/BitcasaAPI.cpp BitcasaDiff-20140716/BitcasaDLL/BitcasaAPI.cpp
--- BitcasaDiff-20140714/BitcasaDLL/BitcasaAPI.cpp	2014-07-14 03:45:26.000000000 +0900
+++ BitcasaDiff-20140716/BitcasaDLL/BitcasaAPI.cpp	2014-07-16 00:18:46.000000000 +0900
@@ -533,6 +533,8 @@
 	std::string *URI;
 	int retrycount = retrymax;
 public:
+	const int master_retrymax = 5;
+	int master_retry = master_retrymax;
 	bool partial;
 	HANDLE readySlave;
 	HANDLE readyMaster;
@@ -569,19 +571,13 @@
 	}
 	void DoWork(){
 		while (WaitForSingleObject(die, 0) == WAIT_TIMEOUT){
+			// wait for master
 			if ((WaitForSingleObject(readySlave, INFINITE) != WAIT_OBJECT_0) || (WaitForSingleObject(die, 0) != WAIT_TIMEOUT))
 				break;
-			//std::cerr << "thread " << GetCurrentThreadId() << " wake." << std::endl;
-			//std::cerr << "thread " << GetCurrentThreadId() << " offset:" << offset << std::endl;
 			bitcasa->Clear();
 			bitcasa->request.query["access_token"] = *access_token;
 			bitcasa->AddHeader("Range", dynamic_cast<std::stringstream &>(std::stringstream() << "bytes=" << offset << "-" << (offset + len - 1)).str());
 			if (bitcasa->GET(*URI) != 0){
-				//std::cerr << "thread " << GetCurrentThreadId() << " DownloadFile failed" << std::endl;
-				//std::cerr << bitcasa->response.line << std::endl;
-				//for (auto it = bitcasa->response.header.begin(); it != bitcasa->response.header.end(); ++it)
-				//	std::cerr << it->first << ": " << it->second << std::endl;
-				//std::cerr << std::string(bitcasa->response.body.begin(), bitcasa->response.body.end()) << std::endl;
 				SetEvent(readySlave);
 				Sleep(1000 * 10);
 				if (--retrycount > 0)
@@ -590,7 +586,6 @@
 				break;
 			}
 
-			//std::wcerr << ".";
 			if (bitcasa->response.code == 503){
 				SetEvent(readySlave);
 				Sleep(1000 * 10);
@@ -600,9 +595,6 @@
 				break;
 			}
 			if ((bitcasa->response.code != 200) && (bitcasa->response.code != 206)) {
-				//std::wcerr << std::endl;
-				//std::cerr << "DownloadFile failed" << std::endl;
-				//std::cerr << std::string(bitcasa->response.body.begin(), bitcasa->response.body.end()) << std::endl;
 				buf = gcnew array<System::Byte>(0);
 				SetEvent(readySlave);
 				Sleep(1000 * 10);
@@ -623,11 +615,9 @@
 			}
 			buf = gcnew array<System::Byte>((int)bitcasa->response.body.size());
 			System::Runtime::InteropServices::Marshal::Copy((System::IntPtr)bitcasa->response.body.data(), buf, 0, buf->Length);
-
-			//std::cerr << "thread " << GetCurrentThreadId() << "done. offset:" << offset << std::endl;
+			// notify to master
 			SetEvent(readyMaster);
 		}
-		//std::cerr << "thread " << GetCurrentThreadId() << " done." << std::endl;
 	}
 };
 
@@ -696,7 +686,6 @@
 			if ((ret >= WAIT_ABANDONED_0) && (ret < WAIT_ABANDONED_0 + waithandles.size())) thread_no = ret - WAIT_ABANDONED_0;
 			if (ret == WAIT_TIMEOUT) 
 			{
-				//std::cerr << "thread wait timeout" << std::endl;
 				for (int i = 0; i < threadcount; i++){
 					ReleaseMutex(data[i]->die);
 					SetEvent(data[i]->readySlave);
@@ -706,7 +695,6 @@
 					workThreads[i]->Abort();
 				}
 			}
-			//std::cerr << "thread return:" << thread_no << std::endl;
 			if (thread_no < 0) return false;
 			if (thread_no == threadcount) return false;
 
@@ -716,12 +704,12 @@
 				// 206 success range
 				if (work->buf->Length == work->len)
 				{
+					work->master_retry = work->master_retrymax;
 					out.seekp(work->offset, std::ios::beg);
 					pin_ptr<System::Byte> dp = &work->buf[0];
 					out.write((char *)dp, work->buf->Length);
 					dp = nullptr;
-					if (callback)
-					{
+					if (callback){
 						progress = (progress < work->offset) ? work->offset : progress;
 						callback(progress);
 					}
@@ -738,6 +726,7 @@
 						continue;
 					}
 				}
+				// unmached range request, retry to download
 				std::cerr << "206 unmatch offset:" << work->offset << " want:" << work->len << " ret:" << work->buf->Length << " " << std::endl;
 			}
 			else{
@@ -751,14 +740,24 @@
 					offset = work->buf->Length;
 					break;
 				}
-				//std::cerr << "200 unmatch want:" << wantSize << " ret:" << work->buf->size() << std::endl;
 			}
-			// retry
-			//std::cerr << "retry " << work->offset << ":" << work->len << std::endl;
-			SetEvent(work->readySlave);
+			if (work->master_retry-- > 0){
+				// retry
+				SetEvent(work->readySlave);
+				continue;
+			}
+			// retry max abort...
+			for (int i = 0; i < threadcount; i++){
+				ReleaseMutex(data[i]->die);
+				SetEvent(data[i]->readySlave);
+				data[i]->Abort();
+			}
+			for (int i = 0; i < threadcount; i++){
+				workThreads[i]->Abort();
+			}
+			return false;
 		}
 		if (callback) callback(offset);
-		//std::wcerr << "done" << std::endl;
 		return true;
 	}
 	finally{
