StorageWrapper.cpp
上传用户:lds876
上传日期:2013-05-25
资源大小:567k
文件大小:45k
源码类别:

P2P编程

开发平台:

Visual C++

  1. // StorageWrapperEx.cpp: implementation of the CStorageWrapperEx class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "testbt.h"
  6. #include "StorageWrapper.h"
  7. #include "storage.h"
  8. #include "Downloader.h"
  9. #include "DownloaderFeedback.h"
  10. #include "Sha.h"
  11. #ifdef _DEBUG
  12. #undef THIS_FILE
  13. static char THIS_FILE[]=__FILE__;
  14. #define new DEBUG_NEW
  15. #endif
  16. //////////////////////////////////////////////////////////////////////
  17. // Construction/Destruction
  18. //////////////////////////////////////////////////////////////////////
  19. CStorageWrapper::CStorageWrapper(const vector<CSize>& vUnNeededFileInxs)
  20. {
  21. //
  22. // set file inxs. make it at the end of the function.
  23. // set it at the first, because it may be called while stroage is checking or allocating.
  24. //
  25. SetUnNeededFilesInxs(vUnNeededFileInxs);
  26. }
  27. CStorageWrapperEx::CStorageWrapperEx()
  28. {
  29. m_pMain = 0;
  30. m_hevDone = 0;
  31. m_hevUnPause = 0;
  32. m_pStorage = 0;
  33. m_pDownloader = 0;
  34. m_request_size = 0;
  35. m_piece_length = 0;
  36. m_lTotalLength = 0;
  37. m_lAmountLeft = 0;
  38. m_lAmountInactive = 0;
  39. m_bCheckHashes = true;
  40. m_eAllocType = m_eAllocType;
  41. m_bDoubleCheck = false;
  42. m_bTripleCheck = false;
  43. m_bBgallocEnabled = false;
  44. m_bBgallocActive = false;
  45. m_lStatNumflunked = 0;
  46. m_lStatMumdownloaded = 0;
  47. m_lStatNumfound = 0;
  48. time(&m_tLast);
  49. m_tTimeSpan = 1;
  50. m_vNone.push_back(size(-1, -1));
  51. //
  52. // switch Unneedfiles.
  53. m_bModified = false;
  54. m_lPartAmountLeft = 0;
  55. m_lPartTotalLength = 0;
  56. m_lPartAmountInactive = 0;
  57. }
  58. CStorageWrapperEx::~CStorageWrapperEx()
  59. {
  60. }
  61. bool CStorageWrapperEx::do_I_have(long index)
  62. {
  63. // if (IsUnNeededIndex(index))
  64. // return false;
  65. assert(index < m_vHave.size());
  66. return m_vHave[index];
  67. }
  68. vector<bool>& CStorageWrapperEx::get_have_list()
  69. {
  70. return m_vHave;
  71. }
  72. BLONG CStorageWrapperEx::get_total_legth()
  73. {
  74. return m_pStorage->GetTotalLength();
  75. }
  76. BLONG CStorageWrapperEx::get_amount_left()
  77. {
  78. return m_lAmountLeft;
  79. }
  80. bool CStorageWrapperEx::do_I_have_anything()
  81. {
  82. return m_lAmountLeft < m_lTotalLength;
  83. }
  84. bool CStorageWrapperEx::is_everything_pending()
  85. {
  86. assert(m_lPartAmountInactive >= 0);
  87. if (m_lPartAmountInactive <= 0)
  88. {
  89. return true;
  90. }
  91. return false;
  92. return m_lAmountInactive == 0;
  93. }
  94. bool CStorageWrapperEx::do_I_have_requests(long index)
  95. {
  96. assert (index < m_vInactiveRequests.size());
  97. // if (m_vNone == m_vInactiveRequests[index])
  98. //  return true;
  99. if (IsUnNeededIndex(index))
  100. return false;
  101. return m_vInactiveRequests[index].size() != 0;
  102. }
  103. bool CStorageWrapperEx::_do_I_have_requests(long index)
  104. {
  105. assert (index < m_vInactiveRequests.size());
  106. return m_vInactiveRequests[index].size() != 0;
  107. }
  108. void CStorageWrapperEx::new_request(long index, long& begin, long& length)
  109. {
  110. if (index < 0 || index >= m_vHave.size() || m_vHave[index] || !do_I_have_requests(index))
  111. {
  112. assert(false);
  113. return;
  114. }
  115. if (m_vNone == m_vInactiveRequests[index])
  116. _make_inactive(index);
  117. m_vNumActive[index]++;
  118. vector<size> & rs = m_vInactiveRequests[index];
  119. size r = *rs.begin();
  120. begin = r.x;
  121. length = r.y;
  122. rs.erase(rs.begin());
  123. m_lAmountInactive -= length;
  124. m_lPartAmountInactive --; //= length;
  125. assert(m_lPartAmountInactive >= 0);
  126. m_pMain->PutFractionsState(index, 2);
  127. // m_vStatActive[index] = true;
  128. }
  129. void CStorageWrapperEx::request_lost(long index, long begin, long length)
  130. {
  131. assert(index < m_vInactiveRequests.size() && index >= 0);
  132. m_vInactiveRequests[index].push_back(size(begin, length));
  133. m_vNumActive[index]--;
  134. assert(m_vNumActive[index] >= 0);
  135. m_lAmountInactive += length;
  136. m_lPartAmountInactive ++; // = length;
  137. assert(m_lPartAmountInactive >= 0);
  138. if (m_vNumActive[index] <= 0)
  139. m_pMain->PutFractionsState(index, 0);
  140. }
  141. void CStorageWrapperEx::_make_inactive(long index)
  142. {
  143. assert (index < m_vInactiveRequests.size() && m_request_size > 0 && index >= 0);
  144. assert(m_vInactiveRequests[index] == m_vNone);
  145. // long lLength = min(m_piece_length , m_lTotalLength - (BLONG)m_piece_length * index);
  146. // ASSERT(lLength >= 0 && lLength <= m_piece_length);
  147. long lLength = _piecelen(index);
  148. vector<size>& v = m_vInactiveRequests[index];
  149. v.clear();
  150. long x = 0; 
  151. while ((x + m_request_size) < lLength)
  152. {
  153. v.push_back(size(x, m_request_size));
  154. x += m_request_size;
  155. }
  156. v.push_back(size(x, lLength-x));
  157. }
  158. //////////////////////////////////////////////////////////////////////////////////////////////////////
  159. // switch Unneedfiles.
  160. //
  161. bool CStorageWrapperEx::_ReadIndexData(char *pBuf, const BLONG lPos, const BLONG lAmount, bool bFlushFirst)
  162. {
  163. if (!m_piece_length)
  164. {
  165. assert(false);
  166. return false;
  167. }
  168. long index = lPos / m_piece_length;
  169. ASSERT(index >= 0);
  170. bool bEdge = false;
  171. for (int i=0; i<m_vRangeHoles.size(); i++)
  172. {
  173. if (index < m_vRangeHoles[i])
  174. break;
  175. if (index == m_vRangeHoles[i])
  176. {
  177. bEdge = (i > 0);
  178. break;
  179. }
  180. }
  181. if (bEdge)
  182. {
  183. assert(i < m_vFileOffset.size());
  184. long lfileoffset = m_vFileOffset[i];
  185. long lPrePartIndex = m_vOffsetTrueIndex[i];
  186. if (lfileoffset == 0 || lPrePartIndex < 0)
  187. {
  188. if (!m_pStorage->read(pBuf, lPos, lAmount, bFlushFirst))
  189. return false;
  190. }
  191. else
  192. {
  193. long lbeg = lPos % m_piece_length;
  194. assert(lbeg >= 0);
  195. if (lbeg < lfileoffset)
  196. {
  197. long len = lfileoffset - lbeg;
  198. assert(len >= 0);
  199. if (len >= lAmount)
  200. {
  201. if (!m_pStorage->read(pBuf, (BLONG)lPrePartIndex * m_piece_length + lbeg, lAmount, bFlushFirst))
  202. return false;
  203. }
  204. else
  205. {
  206. if (!m_pStorage->read(pBuf, (BLONG)lPrePartIndex * m_piece_length + lbeg, len, bFlushFirst))
  207. return false;
  208. if (!m_pStorage->read(pBuf + len, (BLONG)index * m_piece_length + lfileoffset, lAmount - len, bFlushFirst))
  209. return false;
  210. }
  211. }
  212. else
  213. {
  214. if (!m_pStorage->read(pBuf, lPos, lAmount, bFlushFirst))
  215. return false;
  216. }
  217. }
  218. }
  219. else
  220. {
  221. if (!m_pStorage->read(pBuf, lPos, lAmount, bFlushFirst))
  222. return false;
  223. }
  224. return true;
  225. }
  226. bool CStorageWrapperEx::_WriteIndexData(char *pBuf, const BLONG lPos, const BLONG lAmount)
  227. {
  228. if (!m_piece_length)
  229. {
  230. assert(false);
  231. return false;
  232. }
  233. long index = lPos / m_piece_length;
  234. ASSERT(index >= 0);
  235. bool bEdge = false;
  236. for (int i=0; i<m_vRangeHoles.size(); i++)
  237. {
  238. if (index < m_vRangeHoles[i])
  239. break;
  240. if (index == m_vRangeHoles[i])
  241. {
  242. bEdge = (i > 0);
  243. break;
  244. }
  245. }
  246. if (bEdge)
  247. {
  248. assert(i < m_vFileOffset.size());
  249. long lfileoffset = m_vFileOffset[i];
  250. long lPrePartIndex = m_vOffsetTrueIndex[i];
  251. if (lfileoffset == 0 || lPrePartIndex < 0)
  252. {
  253. if (!m_pStorage->write(pBuf, lPos, lAmount))
  254. return false;
  255. }
  256. else
  257. {
  258. long lbeg = lPos % m_piece_length;
  259. assert(lbeg >= 0);
  260. if (lbeg < lfileoffset)
  261. {
  262. long len = lfileoffset - lbeg;
  263. assert(len >= 0);
  264. if (len >= lAmount)
  265. {
  266. if (!m_pStorage->write(pBuf, (BLONG)lPrePartIndex * m_piece_length + lbeg, lAmount))
  267. return false;
  268. }
  269. else
  270. {
  271. if (!m_pStorage->write(pBuf, (BLONG)lPrePartIndex * m_piece_length + lbeg, len))
  272. return false;
  273. if (!m_pStorage->write(pBuf + len, (BLONG)index * m_piece_length + lfileoffset, lAmount - len))
  274. return false;
  275. }
  276. }
  277. else
  278. {
  279. if (!m_pStorage->write(pBuf, lPos, lAmount))
  280. return false;
  281. }
  282. }
  283. }
  284. else
  285. {
  286. if (!m_pStorage->write(pBuf, lPos, lAmount))
  287. return false;
  288. }
  289. return true;
  290. }
  291. void CStorageWrapperEx::_FormatRangeHoles()
  292. {
  293. if (m_piece_length <= 0)
  294. {
  295. assert(false);
  296. return;
  297. }
  298. m_pStorage->GetFilesRange(m_vRangeHoles, m_vFileOffset, m_piece_length);
  299. for (int i=0;i<m_vRangeHoles.size(); i++)
  300. {
  301. m_vOffsetTrueIndex.push_back(-1);
  302. m_vFileOffsetPreAllocated.push_back(false);
  303. }
  304. int iRangeHolesSize = m_vRangeHoles.size();
  305. int iFileOffsetSize = m_vFileOffset.size();
  306. int iOffsetTrueIndexSize = m_vOffsetTrueIndex.size();
  307. assert(iRangeHolesSize == iFileOffsetSize);
  308. assert(iFileOffsetSize == iOffsetTrueIndexSize);
  309. }
  310. float CStorageWrapperEx::GetPartCompletedPercent()
  311. {
  312. if (m_lPartTotalLength <= 0)
  313. return 1;
  314. return (float)(m_lPartTotalLength - m_lPartAmountLeft) / m_lPartTotalLength;
  315. }
  316. BLONG CStorageWrapperEx::get_total_legth_part()
  317. {
  318. return m_lPartTotalLength;
  319. }
  320. BLONG CStorageWrapperEx::get_amount_left_part()
  321. {
  322. return m_lPartAmountLeft;
  323. }
  324. BLONG CStorageWrapperEx::get_amount_left_part_include_temp()
  325. {
  326. BLONG lLeft = m_lPartAmountLeft;
  327. #ifdef _DEBUG
  328. int iCount = 0;
  329. unsigned long lsize = m_mPartAmountIncome.size();
  330. #endif
  331. for (map<unsigned long, unsigned long>::iterator i=m_mPartAmountIncome.begin(); i!=m_mPartAmountIncome.end(); i++)
  332. {
  333. if (!IsUnNeededIndex((*i).first))
  334. {
  335. lLeft += (*i).second;
  336. }
  337. #ifdef _DEBUG
  338. iCount ++;
  339. #endif
  340. }
  341. return lLeft;
  342. }
  343. bool CStorageWrapperEx::IsUnNeededIndex(long lIndex)
  344. {
  345. assert(lIndex >= 0);
  346. for (int i=0; i<m_vUnNeededIndexs.size(); i++)
  347. {
  348. long cx = m_vUnNeededIndexs[i].cx;
  349. long cy = m_vUnNeededIndexs[i].cy;
  350. if (lIndex > cy)
  351. continue;
  352. if (lIndex >= cx)
  353. return true;
  354. return false;
  355. }
  356. return false;
  357. }
  358. void CStorageWrapperEx::SetUnNeededFilesInxs(const vector<CSize>& vUnNeededFileInxs)
  359. {
  360. CSingleLock singleLock(&m_criticalSection, true);
  361. m_vUnNeededFileInxs = vUnNeededFileInxs;
  362. m_bModified = true;
  363. }
  364. bool CStorageWrapperEx::_GetUnNeededFilesInxs(vector<CSize>& vUnNeededFileInxs)
  365. {
  366. CSingleLock singleLock(&m_criticalSection, true);
  367. if (!m_bModified) return false;
  368. vUnNeededFileInxs = m_vUnNeededFileInxs;
  369. m_bModified = false;
  370. return true;
  371. }
  372. long CStorageWrapperEx::_GetRequestSize(long index)
  373. {
  374. assert(index <m_vHave.size() && index >= 0 && m_request_size > 0);
  375. if (m_request_size <= 0)
  376. {
  377. assert(false);
  378. return -1;
  379. }
  380. // long lRequestLength = min(m_piece_length , m_lTotalLength - m_piece_length * index);
  381. long lRequestLength = _piecelen(index);
  382. long lRequestCount = lRequestLength / m_request_size + ((lRequestLength % m_request_size) ? 1 : 0);
  383. assert(lRequestCount > 0 && lRequestLength >= 0);
  384. return lRequestCount;
  385. }
  386. /*************************************************************************************
  387. lbeg and lend is the true value of file seeking pos,
  388. which return value is the index value.
  389. *************************************************************************************/
  390. bool CStorageWrapperEx::_NormalizeUneedRange(BLONG & lbegPos, BLONG & lendPos)
  391. {
  392. assert(lendPos >= 0 && lbegPos >= 0);
  393. assert(!m_vRangeHoles.empty());
  394. const long lbegold = lbegPos/m_piece_length, lendold = lendPos/m_piece_length;
  395. assert(lbegold >= 0 && lendold >= 0);
  396. if (lbegold > lendold)
  397. {
  398. assert(false);
  399. return false;
  400. }
  401. bool bfindbeg = false, bfindend = false;
  402. for (int i=0; i<m_vRangeHoles.size();i++)
  403. {
  404. int iHoleIndex = m_vRangeHoles[i];
  405. if (lbegold <= m_vRangeHoles[i] && !bfindbeg)
  406. {
  407. lbegPos = m_vRangeHoles[i];
  408. if (m_vFileOffset[i] != 0)
  409. lbegPos += 1;
  410. bfindbeg = true;
  411. }
  412. // long lsize = m_vRangeHoles.size();
  413. long x = m_vRangeHoles[i];
  414. ASSERT(x >= 0);
  415. if (lendold  < m_vRangeHoles[i] && !bfindend)
  416. {
  417. assert(bfindbeg);
  418. assert(i > 0);
  419. lendPos = m_vRangeHoles[i - 1];
  420. if (m_vFileOffset[i - 1] != 0)
  421. lendPos -= 1;
  422. bfindend = true;
  423. }
  424. if (bfindbeg && bfindend)
  425. break;
  426. }
  427. /*
  428. if (!bfindbeg)
  429. {
  430. lbeg = m_vRangeHoles[m_vRangeHoles.size() - 1];
  431. if (m_vFileOffset[m_vRangeHoles.size() - 1])
  432. {
  433. lbeg ++;
  434. }
  435. }
  436. //*/
  437. if (!bfindend)
  438. {
  439. if (lendPos >= m_lTotalLength)
  440. {
  441. lendPos = m_lTotalLength / m_piece_length;
  442. }
  443. /*
  444. else if (lendold >= (m_lTotalLength / m_piece_length) )
  445. {
  446. lend = m_lTotalLength / m_piece_length;
  447. if (m_lTotalLength % m_piece_length)
  448. {
  449. lend -= 1;
  450. }
  451. }
  452. //*/
  453. else
  454. {
  455. lendPos = m_vRangeHoles[m_vRangeHoles.size() - 1];
  456. if (m_vFileOffset[m_vRangeHoles.size() - 1] != 0)
  457. lendPos -= 1;
  458. }
  459. bfindend = true;
  460. }
  461. // assert(lend >= lbeg);
  462. return bfindbeg && bfindend && (lendPos >= lendPos);
  463. }
  464. void CStorageWrapperEx::_MakeUnNeededIndexs()
  465. {
  466. vector<CSize> vUnFileInxs;
  467. if (!_GetUnNeededFilesInxs(vUnFileInxs))
  468. return;
  469. if (!m_piece_length)
  470. {
  471. assert(false);
  472. return;
  473. }
  474. m_lPartTotalLength = m_lTotalLength;
  475. m_lPartAmountLeft = m_lAmountLeft;
  476. m_vUnNeededIndexs.clear();
  477. //
  478. // Get unNeeded files range.
  479. //
  480. vector<CSizeEx> vRanges;
  481. m_pStorage->GetUnNeededRanges(vUnFileInxs, vRanges);
  482. #ifdef _DEBUG
  483. TRACE("rn_MakeUnNeededIndexs(%d) : rn", m_vHave.size());
  484. for (int j=0; j<vRanges.size(); j++)
  485. {
  486. TRACE("(%d, %d)", vRanges[j].cx, vRanges[j].cy);
  487. }
  488. TRACE("rn*");
  489. #endif
  490. //
  491. // compute the unNeeded indexs.
  492. //
  493. for (int i=0; i<vRanges.size(); i++)
  494. {
  495. BLONG tx = vRanges[i].cx, ty = vRanges[i].cy;
  496. /*
  497. unsigned long cx = vRanges[i].cx/m_piece_length;
  498. unsigned long cy = vRanges[i].cy/m_piece_length ;
  499. if (vRanges[i].cx % m_piece_length)
  500. cx += 1;
  501. if (vRanges[i].cy % m_piece_length)
  502. cy -= 1;
  503. if (vRanges[i].cy >= m_lTotalLength)
  504. {
  505. if (vRanges[i].cy%m_piece_length)
  506. {
  507. cy ++;
  508. }
  509. }
  510. if (cy >= 0)
  511. assert(cy < m_vHave.size());
  512. //*/
  513. if (!_NormalizeUneedRange(tx, ty))
  514. continue;
  515. if (tx >= ty) continue;
  516. m_vUnNeededIndexs.push_back(CSize(tx, ty));
  517. }
  518. //
  519. // Compute the Needed indexs and amount which had been haved.
  520. //
  521. m_lPartAmountInactive = 0;
  522. m_lPartTotalLength = 0;
  523. BLONG lAmountHave = 0;
  524. BLONG lbeg = 0, lend = 0;
  525. bool bIncludeLastPiece = false;
  526. int iLastIndex = m_vHave.size() - 1;
  527. for (i=0; i<m_vUnNeededIndexs.size(); i++)
  528. {
  529. CSize range = m_vUnNeededIndexs[i];
  530. lend = range.cx;
  531. m_lPartTotalLength += (BLONG)(lend - lbeg) * m_piece_length;
  532. for (int j=lbeg; j<lend; j++)
  533. {
  534. //
  535. // compute have amount.
  536. //
  537. if (j >= m_vHave.size())
  538. {
  539. assert(false);
  540. break;
  541. }
  542. if (m_vHave[j])
  543. lAmountHave  += _piecelen(j);
  544. //
  545. // compute inactive requests amount.
  546. //
  547. if (m_vInactiveRequests[j] == m_vNone)
  548. {
  549. long lRequestCount = _GetRequestSize(j);
  550. assert(lRequestCount >= 0);
  551. m_lPartAmountInactive += lRequestCount;
  552. }
  553. else
  554. {
  555. m_lPartAmountInactive += m_vInactiveRequests[j].size();
  556. }
  557. }
  558. lbeg  = range.cy + 1;
  559. }
  560. if (lbeg <= iLastIndex)
  561. {
  562. m_lPartTotalLength += (BLONG)(iLastIndex - lbeg) * m_piece_length;
  563. m_lPartTotalLength += _piecelen(iLastIndex);
  564. for (int j=lbeg; j<=iLastIndex; j++)
  565. {
  566. //
  567. // compute have amount.
  568. //
  569. if (m_vHave[j])
  570. lAmountHave  += _piecelen(j);
  571. //
  572. // compute inactive requests amount.
  573. //
  574. if (m_vInactiveRequests[j] == m_vNone)
  575. {
  576. long lRequestCount = _GetRequestSize(j);
  577. m_lPartAmountInactive += lRequestCount;
  578. }
  579. else
  580. {
  581. m_lPartAmountInactive += m_vInactiveRequests[j].size();
  582. }
  583. }
  584. }
  585.  
  586. m_lPartAmountLeft = m_lPartTotalLength - lAmountHave;
  587. assert(m_lPartAmountLeft >= 0);
  588. if (m_pDownloader && m_pDownloader->IsCreate())
  589. {
  590. if (m_pDownloader->is_endgame()) // && (m_lPartAmountInactive > 0) )
  591. {
  592. m_pDownloader->cancel_endgame();
  593. }
  594. m_pDownloader->OnNeedFilesChanged();
  595. }
  596. #ifdef _DEBUG
  597. TRACE("rn_MakeUnNeededIndexs(%d) : rn", m_vHave.size());
  598. for (i=0; i<vUnFileInxs.size();i++)
  599. {
  600. TRACE("(%d, %d)", vUnFileInxs[i].cx, vUnFileInxs[i].cy);
  601. }
  602. TRACE("rn*");
  603. TRACE("rn_MakeUnNeededIndexs(%d) : rn", m_vHave.size());
  604. for (i=0; i<vRanges.size();i++)
  605. {
  606. TRACE("(%d, %d)", vRanges[i].cx, vRanges[i].cy);
  607. }
  608. TRACE("rn*");
  609. for (i=0; i<m_vUnNeededIndexs.size();i++)
  610. {
  611. TRACE("(%d, %d)", m_vUnNeededIndexs[i].cx, m_vUnNeededIndexs[i].cy);
  612. }
  613. TRACE("rn");
  614. #endif
  615. }
  616. //////////////////////////////////////////////////////////////////////////////////////////////////////
  617. //
  618. bool CStorageWrapperEx::get_piece(long index, char* pPieceBuf, long begin, long length)
  619. {
  620. try
  621. {
  622. return _get_piece(index, pPieceBuf, begin, length);
  623. }
  624. catch (string& e)
  625. {
  626. throw string(e);
  627. }
  628. }
  629. bool CStorageWrapperEx::_get_piece(long index, char* pPieceBuf, long begin, long length)
  630. {
  631. if (index >= m_vHave.size() || !m_vHave[index] || begin < 0)
  632. {
  633. // assert(false);
  634. return false;
  635. }
  636. if ((begin + length) > _piecelen(index))
  637. {
  638. assert(false);
  639. return false;
  640. }
  641. // If piece was not checked, check it.
  642. if (!m_vWasChecked[index])
  643. {
  644. char* pszBuf = new char[m_piece_length];
  645. auto_ptr<char> aszBuf(pszBuf);
  646. assert(m_mPlaces.find(index) != m_mPlaces.end());
  647. if (!_ReadIndexData(pszBuf, (BLONG)m_piece_length * m_mPlaces[index], _piecelen(index)))
  648. return false;
  649. unsigned char shasum[20] = {0};
  650. CSHA sha;
  651. sha.start();
  652. sha.update((unsigned char*)pszBuf, _piecelen(index));
  653. sha.finish(shasum);
  654. if (m_vHashs[index] != shasum)
  655. {
  656. // todo : self.failed('told file complete on start-up, but piece failed hash check')
  657. m_pMain->SetBadMsg("文件已被修改或移动,导致数据丢失,请重新下载"); // told file complete on start-up, but piece failed hash check");
  658. return false;
  659. }
  660. m_vWasChecked[index] = true;
  661. }
  662. assert(m_mPlaces.find(index) != m_mPlaces.end());
  663. if (!_ReadIndexData(pPieceBuf, (BLONG)m_piece_length * m_mPlaces[index] + begin, length))
  664. return false;
  665. return true;
  666. }
  667. void CStorageWrapperEx::piece_came_in(long index, char *pPieceBuf, long begin,  long length)
  668. {
  669. try
  670. {
  671. _piece_came_in(index, pPieceBuf, begin, length);
  672. }
  673. catch (string& e)
  674. {
  675. assert(false);
  676. throw string(e);
  677. }
  678. }
  679. bool CStorageWrapperEx::_piece_came_in(long index, char *pPieceBuf, long begin,  long length)
  680. {
  681. if (index >= m_vHave.size() || m_vHave[index] || m_vNumActive[index] <= 0 || begin <0)
  682. {
  683. bool bHave = m_vHave[index];
  684. long lNumAcive = m_vNumActive[index];
  685. assert(false);
  686. return false;
  687. }
  688. // If the index not in slits.
  689. if (m_mPlaces.find(index) == m_mPlaces.end())
  690. {
  691. if (!_FindPlaceForNewComeIndex(index, true))
  692. {
  693. assert(false);
  694. m_pMain->SetBadMsg("_FindPlaceForNewComeIndex error : ");
  695. return false;
  696. }
  697. }// endif dosn't exist.
  698. assert(m_mPlaces.find(index) != m_mPlaces.end());
  699. if (!_WriteIndexData(pPieceBuf, (BLONG)m_piece_length * (BLONG)m_mPlaces[index] + begin, length))
  700. return false;
  701. m_vNumActive[index] --;
  702. //
  703. // record the amount income of each uncompleted piece.
  704. // 
  705. map<unsigned long, unsigned long>::iterator itAmount = m_mPartAmountIncome.find(index);
  706. if (itAmount == m_mPartAmountIncome.end())
  707. {
  708. m_mPartAmountIncome[index] = 0;
  709. }
  710. m_mPartAmountIncome[index] += length;
  711. //
  712. // check whether the piece completed.
  713. //
  714. if (!_do_I_have_requests(index) && !m_vNumActive[index])
  715. {
  716. //
  717. // if  completed the amount completed tranfered to m_vHave.
  718. //
  719. itAmount = m_mPartAmountIncome.find(index);
  720. if (itAmount != m_mPartAmountIncome.end())
  721. m_mPartAmountIncome.erase(itAmount);
  722. if (!_check_single(index, true))
  723. return false;
  724. }
  725. return true;
  726. }
  727. bool CStorageWrapperEx::_FindPlaceForNewComeIndex(long index, bool bFirst)
  728. {
  729. char* pszBuf = new char[m_piece_length];
  730. auto_ptr<char> aszBuf(pszBuf);
  731. #ifdef _DEBUG
  732. if (m_vHoles.empty())
  733. {
  734. assert(false);
  735. return false;
  736. }
  737. #endif
  738. //////////////////////////////////////////////////////////////////////////////
  739. // get hole index from the holes list decided previous.
  740. // the hole index is caculated by the file range that the index belongs to.
  741. long lFileIndex = -1;
  742. bool bFind = false;
  743. for (int i=0; i<m_vRangeHoles.size(); i++)
  744. {
  745. if (index < m_vRangeHoles[i])
  746. {
  747. bFind = true;
  748. lFileIndex = i - 1;
  749. break;
  750. }
  751. }
  752. if (!bFind)
  753. lFileIndex = m_vRangeHoles.size() - 1;
  754. assert(lFileIndex >= 0);
  755. long lMinHoleIndex = m_vRangeHoles[lFileIndex];
  756. long lPopHoleIndex = -1;
  757. for (i=0; i<m_vHoles.size(); i++)
  758. {
  759. if (m_vHoles[i] >= lMinHoleIndex)
  760. {
  761. // lPopHoleIndex = (*pvHoles)[i];
  762. lPopHoleIndex = i;
  763. break;
  764. }
  765. }
  766. if (lPopHoleIndex < 0)
  767. {
  768. assert(false);
  769. return false;
  770. }
  771. // const int n = (*pvHoles)[0];
  772. const int n = m_vHoles[lPopHoleIndex];
  773. //////////////////////////////////////////////////////////////////////////////
  774. // if the hole is the first place of the file range.
  775. if (n == lMinHoleIndex && lFileIndex > 0)
  776. {
  777. long lfileoffset = m_vFileOffset[lFileIndex];
  778. long lPrePartIndex = m_vOffsetTrueIndex[lFileIndex];
  779. if (lfileoffset != 0 && lPrePartIndex >= 0)
  780. {
  781. char c = 'f';
  782. if (!m_pStorage->write(&c, (BLONG)lPrePartIndex * m_piece_length + lfileoffset - 1, sizeof(char)))
  783. return false;
  784. }
  785. }
  786. //////////////////////////////////////////////////////////////////////////////
  787. // if the hole is took by next file offset part, move it to next index.
  788. if (lFileIndex < (m_vRangeHoles.size() - 1))
  789. {
  790. if (m_vOffsetTrueIndex[lFileIndex + 1] == n)
  791. {
  792. long lNextIndex = m_vRangeHoles[lFileIndex + 1];
  793. if (m_vOffsetTrueIndex[lFileIndex + 1] >= lNextIndex)
  794. {
  795. assert(false);
  796. return false;
  797. }
  798. //
  799. // tell whether the next file offset part filled, if yes move it.
  800. //
  801. // map<long, long>::iterator iter = m_mPlaces.find(lNextIndex);
  802. // if (iter != m_mPlaces.end()) 
  803. if (find(m_vHoles.begin(), m_vHoles.end(), lNextIndex) == m_vHoles.end())
  804. {
  805. if (!m_pStorage->read(pszBuf, (BLONG)m_piece_length * n, m_vFileOffset[lFileIndex + 1]))
  806. return false;
  807. if (!m_pStorage->write(pszBuf, (BLONG)m_piece_length * (n + 1), m_vFileOffset[lFileIndex + 1]))
  808. return false;
  809. }
  810. //
  811. // mark the offset to next index, no matter whether it is filled.
  812. //
  813. m_vOffsetTrueIndex[lFileIndex + 1] ++;
  814. if (m_vOffsetTrueIndex[lFileIndex + 1] >= lNextIndex)
  815. {
  816. m_vOffsetTrueIndex[lFileIndex + 1] = -1;
  817. }
  818. }
  819. }
  820. //////////////////////////////////////////////////////////////
  821. // find the index place, whether in holes or in place took by other piece.
  822. //
  823. long lIndexP = -1;
  824. if (find(m_vHoles.begin(), m_vHoles.end(), index) == m_vHoles.end())
  825. {
  826. for (map<long, long>::iterator j = m_mPlaces.begin(); j != m_mPlaces.end(); j++)
  827. {
  828. if ((*j).second == index)
  829. {
  830. lIndexP = (*j).first;
  831. break;
  832. }
  833. }
  834. if (j == m_mPlaces.end())
  835. {
  836. assert(false);
  837. return false;
  838. }
  839. }
  840. //////////////////////////////////////////////////////////////////////////////
  841. // old code. find the piece data to fill the hole, to free the true space for new coming piece.
  842. map<long, long>::iterator iter = m_mPlaces.find(n);
  843. // The new hole poped is needed by item in temps.
  844. if (iter != m_mPlaces.end()) 
  845. {
  846. // Move data from temp to split newly created from holes.
  847. long lOldPos = (*iter).second;
  848. if (!_ReadIndexData(pszBuf, (BLONG)m_piece_length * lOldPos, _piecelen(n)))
  849. return false;
  850. if (!_WriteIndexData(pszBuf, (BLONG)m_piece_length * n, _piecelen(n)))
  851. return false;
  852. CheckAfterMoveing(n, pszBuf);
  853. m_mPlaces[n] = n;
  854. if(index == lOldPos ||  lIndexP < 0 )
  855. {
  856. m_mPlaces[index] = lOldPos;
  857. }
  858. else
  859. {
  860. if (!_ReadIndexData(pszBuf, (BLONG)m_piece_length * index, _piecelen(lIndexP)))
  861. return false;
  862. if (!_WriteIndexData(pszBuf, (BLONG)m_piece_length * lOldPos, _piecelen(lIndexP)))
  863. return false;
  864. m_mPlaces[lIndexP] = lOldPos;
  865. m_mPlaces[index] = index;
  866. }
  867. }
  868. else
  869. {
  870. if (index == n || lIndexP < 0)// index item out of space. find(m_vHoles.begin(), m_vHoles.end(), index) != m_vHoles.end())
  871. {
  872. memset(pszBuf, 0xff, _piecelen(n));
  873. if (!_WriteIndexData(pszBuf, (BLONG)m_piece_length * n, _piecelen(n)))
  874. return false;
  875. m_mPlaces[index] = n;
  876. }
  877. else // Move item in index space to hole poped. Insert index item in space allocated. 
  878. {
  879. if (!_ReadIndexData(pszBuf, (BLONG)m_piece_length * index, _piecelen(lIndexP)))
  880. return false;
  881. if (!_WriteIndexData(pszBuf, (BLONG)m_piece_length * n, _piecelen(lIndexP)))
  882. return false;
  883. m_mPlaces[lIndexP] = n;
  884. m_mPlaces[index] = index;
  885. }// endif hole pop
  886. }
  887. //////////////////////////////////////////////////////////////////////////////
  888. // erase the poped hole from the needed or notneeded holes, and must erase from m_vHoles which is the base 
  889. // to generate the needed and notneeded holes when user change setup of files to be and not deleted .
  890. {
  891. vector<long>::iterator it = find(m_vHoles.begin(), m_vHoles.end(), n);
  892. if (it == m_vHoles.end())
  893. {
  894. TRACE("sdfsdfrn");
  895. for (i=0; i<m_vHoles.size(); i++)
  896. {
  897. TRACE("%d, ", m_vHoles[i]);
  898. }
  899. TRACE("rn");
  900. assert(false);
  901. return false;
  902. }
  903. // TRACE("rn *********erase holes(%d, %d, %d) **********rn", iState, n, m_vHoles.size());
  904. m_vHoles.erase(it);
  905. }
  906. return true;
  907. }
  908. bool CStorageWrapperEx::_check_single(long index, bool check)
  909. {
  910. char* pszBuf = new char[m_piece_length];
  911. auto_ptr<char> aszBuf(pszBuf);
  912. assert(m_mPlaces.find(index) != m_mPlaces.end());
  913. if (!_ReadIndexData(pszBuf, (BLONG)m_piece_length * m_mPlaces[index], _piecelen(index)))
  914. {
  915. assert(false);
  916. return false;
  917. }
  918. unsigned char shasum[20] = {0};
  919. CSHA sha;
  920. sha.start();
  921. sha.update((unsigned char*)pszBuf, _piecelen(index));
  922. sha.finish(shasum);
  923. if (m_vHashs[index] == shasum)
  924. {
  925. m_vHave[index] = true;
  926. m_lAmountLeft -= _piecelen(index);
  927. m_vInactiveRequests[index].clear();
  928. m_vWasChecked[index] = m_bCheckHashes;
  929. if (!IsUnNeededIndex(index))
  930. {
  931. m_lPartAmountLeft -= _piecelen(index);
  932. if (m_lPartAmountLeft <= 0)
  933. {
  934. m_pMain->PartCompleted();
  935. }
  936. }
  937. if (m_lAmountLeft <= 0)
  938. {
  939. // todo : finished();
  940. m_pMain->Completed();
  941. }
  942. m_pMain->PutFractionsState(index, 1);
  943. }
  944. else
  945. {
  946. // todo: data_flunk().
  947. m_pMain->data_flunked(_piecelen(index));
  948. m_vInactiveRequests[index] = m_vNone;
  949. m_lAmountInactive += _piecelen(index);
  950. m_lPartAmountInactive += _GetRequestSize(index);
  951. m_pMain->PutFractionsState(index, 0);
  952. return false;
  953. }
  954. return true;
  955. }
  956. bool CStorageWrapperEx::CheckAfterMoveing(int iIndex, char* pszBuf)
  957. {
  958. if (m_bDoubleCheck && m_vHave[iIndex])
  959. {
  960. if (m_bTripleCheck)
  961. {
  962. if (!_ReadIndexData(pszBuf, (BLONG)m_piece_length * iIndex, _piecelen(iIndex), true))
  963. return false;
  964. }
  965. unsigned char shasum[20] = {0};
  966. CSHA sha;
  967. sha.start();
  968. sha.update((unsigned char*)pszBuf, _piecelen(iIndex));
  969. sha.finish(shasum);
  970. if (m_vHashs[iIndex] != shasum)
  971. {
  972. assert(false);
  973. // todo : failed('download corrupted; please restart and resume').
  974. m_pMain->SetBadMsg("download corrupted; please restart and resume");
  975. return false;
  976. }
  977. }
  978. return true;
  979. }
  980. /*************************************************************************************
  981. parameter : 
  982. lAllocateRate : (n)M allocated per second.
  983. ************************************************************************************/
  984. bool CStorageWrapperEx::Create(CDownloaderFeedback* pMain,
  985.    HANDLE hevDone, HANDLE hevUnPause, CStorageEx* pStorageEx, CDownloader* pDownloader, vector<char*>& vPieces, 
  986.    bool check_hashes, long request_size, long piece_length, 
  987.    eAllocType eAllocType, 
  988.    long lAllocateRate, bool m_bDoubleCheck, bool m_bTripleCheck)
  989. {
  990. assert(pMain && hevDone && pStorageEx && lAllocateRate > 0);
  991. m_pMain = pMain;
  992. m_hevDone = hevDone;
  993. m_hevUnPause = hevUnPause;
  994. m_pStorage = pStorageEx;
  995. m_pDownloader = pDownloader;
  996. for (int i=0; i<vPieces.size(); i++)
  997. {
  998. m_vHashs.push_back((const char* const)vPieces[i]);
  999. m_vNumActive.push_back(0);
  1000. m_vInactiveRequests.push_back(m_vNone);
  1001. m_vHave.push_back(false);
  1002. // m_vStatActive.push_back(false);
  1003. m_vWasChecked.push_back(check_hashes);
  1004. }
  1005. m_bCheckHashes = check_hashes;
  1006. m_request_size = request_size;
  1007. m_piece_length = piece_length;
  1008. m_lTotalLength = m_pStorage->GetTotalLength();
  1009. m_lAmountLeft = m_lTotalLength;
  1010. m_lAmountInactive = m_lTotalLength;
  1011. // m_lPartAmountInactive = m_vHave.size(); // useless, but temp initialize the member data.
  1012. m_eAllocType = eAllocType;
  1013. if (m_lTotalLength <= ((BLONG)(vPieces.size()-1) * piece_length))
  1014. throw string("CStorageWrapper construct() error: bad data from tracker - total too small");
  1015. if (m_lTotalLength > ((BLONG)vPieces.size() * piece_length))
  1016. throw string("CStorageWrapper construct() error: bad data from tracker - total too big");
  1017. if (m_vHashs.size() <= 0)
  1018. {
  1019. m_pMain->Completed();
  1020. return true;
  1021. }
  1022. time(&m_tLast);
  1023. m_tTimeSpan = m_piece_length / (lAllocateRate * 1048576);
  1024. _FormatRangeHoles();
  1025. m_pMain->ShowSystemMessage("检查已下载数据,可能占用较多系统资源,请稍后.", CSystemMsg::eCmd);
  1026. m_pMain->ShowSystemMessage("开始检查...", CSystemMsg::eMsgOut);
  1027. if (!CheckFiles())
  1028. {
  1029. m_pMain->SetStorageChecking(false);
  1030. m_pMain->SetStorageAllocating(false);
  1031. return false;
  1032. }
  1033. m_pMain->SetStorageChecking(false);
  1034. m_pMain->SetStorageAllocating(false);
  1035. //
  1036. // Make UnNeeded files.
  1037. //
  1038. _MakeUnNeededIndexs();
  1039. if (!IsEventSet(m_hevDone))
  1040. {
  1041. float fCompleted = 0;
  1042. if (m_lTotalLength > 0)
  1043. fCompleted = ((float)(m_lTotalLength - m_lAmountLeft)) / m_lTotalLength;
  1044. m_pMain->SetCheckingDone(fCompleted, GetPartCompletedPercent());
  1045. m_pMain->ShowSystemMessage("检查完成.", CSystemMsg::eMsgIn);
  1046. }
  1047. return true;
  1048. }
  1049. bool CStorageWrapperEx::CheckFiles()
  1050. {
  1051. map<CHashItem, long> mTargets;
  1052. long lTotal = m_vHashs.size();
  1053. //
  1054. // compute the total length allocated to be checked, 
  1055. // but the critical index are skipped, it is a approximatetly value.
  1056. //
  1057. for (int i=0; i<m_vHashs.size(); i++)
  1058. {
  1059. if (!_waspre(i))
  1060. {
  1061. if (mTargets.find(m_vHashs[i]) == mTargets.end())
  1062. mTargets[m_vHashs[i]] = i;
  1063. else
  1064. mTargets.erase(m_vHashs[i]);
  1065. lTotal -= 1;
  1066. }
  1067. }
  1068. if (lTotal && m_bCheckHashes)
  1069. {
  1070. // todo : notify begin check.
  1071. m_pMain->SetStorageChecking(true);
  1072. }
  1073. long lNumChecked = 0;
  1074. long lLastLen = _piecelen(m_vHashs.size() - 1);
  1075. long lOutOfPlace = 0;
  1076. long lUpdateNum = lTotal/300 + 1;
  1077. long lUpdateCount = 0;
  1078. bool bFirstFileIndex = true;
  1079. bool bFirstNoPrepared = true;
  1080. long lNextHoleIdx = 0;
  1081. assert(m_vRangeHoles.size() == m_vFileOffset.size());
  1082. for (i=0; i<m_vHashs.size(); i++)
  1083. {
  1084. bFirstFileIndex = false;
  1085. bool bHaveNext = (lNextHoleIdx < (m_vRangeHoles.size()));
  1086. if (bHaveNext)
  1087. {
  1088. if (i == m_vRangeHoles[lNextHoleIdx])
  1089. {
  1090. bFirstFileIndex = true;
  1091. bFirstNoPrepared = true;
  1092. lNextHoleIdx ++;
  1093. }
  1094. }
  1095. char* pszBuf = new char[m_piece_length];
  1096. auto_ptr<char> aszBuf(pszBuf);
  1097. bool bSaveOffset = false;
  1098. if (!_waspre(i))
  1099. {
  1100. if (bFirstFileIndex)
  1101. {
  1102. assert((lNextHoleIdx - 1 ) >= 0);
  1103. long lcurIndex = lNextHoleIdx - 1;
  1104. if (m_vOffsetTrueIndex[lcurIndex] >= 0)
  1105. {
  1106. if (m_pStorage->was_preallocated((BLONG)m_vOffsetTrueIndex[lcurIndex] * m_piece_length, 
  1107. (BLONG)m_vFileOffset[lcurIndex]) && 
  1108. m_pStorage->was_preallocated((BLONG)i * m_piece_length + m_vFileOffset[lcurIndex], 
  1109. (BLONG)_piecelen(i) - m_vFileOffset[lcurIndex]))
  1110. {
  1111. m_vFileOffsetPreAllocated[lcurIndex] = true;
  1112. bSaveOffset = true;
  1113. }
  1114. }
  1115. }
  1116. else  if (bFirstNoPrepared)
  1117. {
  1118. bFirstNoPrepared = false;
  1119. if (bHaveNext)
  1120. m_vOffsetTrueIndex[lNextHoleIdx] = i;
  1121. }
  1122. if (!bSaveOffset)
  1123. {
  1124. if (!m_bCheckHashes)
  1125. {
  1126. // todo : told file complete on start-up, but data is missing.
  1127. m_pMain->SetBadMsg("文件已被修改或移动,导致数据丢失,请重新下载."); // told file complete on start-up, but data is missing.");
  1128. // assert(false);
  1129. return false;
  1130. }
  1131. m_vHoles.push_back(i);
  1132. continue;
  1133. }
  1134. }
  1135. else if (!m_bCheckHashes)
  1136. {
  1137. markgot(i, i);
  1138. continue;
  1139. }
  1140. //
  1141. // if the piece space was allocated, then check the data of it whether be valid.
  1142. //
  1143. if (!_ReadIndexData(pszBuf, (BLONG)m_piece_length * i, _piecelen(i)))
  1144. return false;
  1145. unsigned char shaPart[20] = {0};
  1146. unsigned char shaFull[20] = {0};
  1147. CSHA sha;
  1148. sha.start();
  1149. sha.update((unsigned char*)pszBuf, lLastLen);
  1150. sha.finish(shaPart);
  1151. sha.start();
  1152. sha.update((unsigned char*)pszBuf, _piecelen(i));
  1153. sha.finish(shaFull);
  1154. if (m_vHashs[i] == shaFull)
  1155. {
  1156. markgot(i, i);
  1157. }
  1158. else 
  1159. {
  1160. map<CHashItem, long>::iterator iter = mTargets.find(CHashItem((const char* const)shaFull));
  1161. if (iter != mTargets.end() && 
  1162. _piecelen(i) == _piecelen((*iter).second))
  1163. {
  1164. markgot((*iter).second, i);
  1165. mTargets.erase(iter);
  1166. lOutOfPlace += 1;
  1167. }
  1168. else if (!m_vHave[m_vHave.size()-1] &&
  1169. m_vHashs[m_vHashs.size() - 1] == shaPart &&
  1170. ((i == (m_vHashs.size() - 1)) || !_waspre(m_vHashs.size() - 1)) )
  1171. {
  1172. markgot(m_vHashs.size() - 1, i);
  1173. lOutOfPlace += 1;
  1174. }
  1175. else
  1176. {
  1177. m_mPlaces[i] = i;
  1178. }
  1179. }
  1180. if (!IsEventSet(m_hevUnPause))
  1181. {
  1182. m_pMain->ShowSystemMessage("用户暂停该任务...", CSystemMsg::eCmd);
  1183. DWORD dwRet = WaitForSingleObject(m_hevUnPause, INFINITE);
  1184. m_pMain->ShowSystemMessage("用户继续该任务...", CSystemMsg::eCmd);
  1185. }
  1186. if (IsEventSet(m_hevDone))
  1187. return false;
  1188. if (!bSaveOffset)
  1189. {
  1190. lNumChecked ++;
  1191. lUpdateCount ++;
  1192. if (lUpdateCount >= lUpdateNum)
  1193. {
  1194. lUpdateCount = 0;
  1195. if (lTotal > 0)
  1196. m_pMain->SetStorageChecking(true, (float)lNumChecked / lTotal);
  1197. }
  1198. }
  1199. } // end for 
  1200. // todo : Notify check complete.
  1201. m_pMain->SetStorageChecking(false);
  1202. m_pMain->PutFractions(m_vHave);
  1203. ShowDetailsTest();
  1204. if (m_lAmountLeft <= 0)
  1205. {
  1206. // todo : notify finished.
  1207. m_pMain->Completed();
  1208. }
  1209. if (m_eAllocType == eAllocSparse)
  1210. {
  1211. m_pStorage->top_off();
  1212. if (lOutOfPlace > 0)
  1213. {
  1214. // todo: statusfunc(activity = 'moving data', fractionDone = 1.0)
  1215. long lToMove = lOutOfPlace;
  1216. lUpdateNum = lOutOfPlace/300 + 1;
  1217. lUpdateCount = 0;
  1218. for (i=0; i<m_vHashs.size(); i++)
  1219. {
  1220. if (!IsEventSet(m_hevUnPause))
  1221. {
  1222. m_pMain->ShowSystemMessage("用户暂停该任务...", CSystemMsg::eCmd);
  1223. DWORD dwRet = WaitForSingleObject(m_hevUnPause, INFINITE);
  1224. m_pMain->ShowSystemMessage("用户继续该任务...", CSystemMsg::eCmd);
  1225. }
  1226. if (IsEventSet(m_hevDone))
  1227. return false;
  1228. if (m_mPlaces.find(i) == m_mPlaces.end())
  1229. {
  1230. m_mPlaces[i] = i;
  1231. }
  1232. else if (m_mPlaces[i] != i)
  1233. {
  1234. char* pszBuf = new char[m_piece_length];
  1235. auto_ptr<char> aszBuf(pszBuf);
  1236. if (!m_pStorage->read(pszBuf, (BLONG)m_piece_length * m_mPlaces[i], _piecelen(i)))
  1237. return false;
  1238. if (!m_pStorage->write(pszBuf, (BLONG)m_piece_length * i, _piecelen(i)))
  1239. return false;
  1240. // check move data result.
  1241. if (!CheckAfterMoveing(i, pszBuf))
  1242. return false;
  1243. m_mPlaces[i] = i;
  1244. lToMove --;
  1245. lUpdateCount ++;
  1246. if (lUpdateCount > lUpdateNum)
  1247. {
  1248. lUpdateCount = 0;
  1249. // todo : statusfunc(fractionDone = float(tomove)/out_of_place)
  1250. }
  1251. m_pStorage->flush();
  1252. // todo : statusfunc(fractionDone = 0.0)
  1253. }
  1254. } // endfor hashs
  1255. else
  1256. {
  1257. for (int i=0; i<m_vHoles.size(); i++)
  1258. {
  1259. long j = m_vHoles[i];
  1260. m_mPlaces[j] = j;
  1261. }
  1262. } // endif outofplace
  1263. TRACE("rn *** after Sparse ***********************rn");
  1264. ShowDetailsTest();
  1265. m_vHoles.clear();
  1266. return true;
  1267. } // endif sparse
  1268. if (m_vHoles.empty())
  1269. return true;
  1270. //
  1271. // Pre allocate space, mark all pieces un completed to correct index.
  1272. //
  1273. if (m_eAllocType == eAllocPreAllocate)
  1274. {
  1275. m_pMain->SetStorageAllocating(true);
  1276. long lNumHoles = m_vHoles.size();
  1277. lUpdateNum = lNumHoles/300 + 1;
  1278. lUpdateCount = 0;
  1279. while (!m_vHoles.empty())
  1280. {
  1281. if (!IsEventSet(m_hevUnPause))
  1282. {
  1283. m_pMain->ShowSystemMessage("用户暂停该任务...", CSystemMsg::eCmd);
  1284. DWORD dwRet = WaitForSingleObject(m_hevUnPause, INFINITE);
  1285. m_pMain->ShowSystemMessage("用户继续该任务...", CSystemMsg::eCmd);
  1286. }
  1287. if (IsEventSet(m_hevDone))
  1288. return false;
  1289. if (!_doalloc())
  1290. return false;
  1291. lUpdateCount ++;
  1292. if (lUpdateCount > lUpdateNum)
  1293. {
  1294. lUpdateCount = 0;
  1295. if (lNumHoles)
  1296. m_pMain->SetStorageAllocating(true, (float)(m_vHoles.size())/lNumHoles);
  1297. }
  1298. }
  1299. m_pStorage->flush();
  1300. // todo : statusfunc(fractionDone = 0.0)
  1301. m_pMain->SetStorageAllocating(false);
  1302. return true;
  1303. } // endif PreAllocate
  1304. if (m_eAllocType == eAllocBackGound)
  1305. {
  1306. bgalloc();
  1307. }
  1308. return true;
  1309. }
  1310. void CStorageWrapperEx::OnIdle()
  1311. {
  1312. time_t t;
  1313. time(&t);
  1314. time_t tspan = t - m_tLast;
  1315. assert(tspan >= 0);
  1316. if (tspan < 0)
  1317. m_tLast = t;
  1318. if (tspan < m_tTimeSpan)
  1319. return ;
  1320. _MakeUnNeededIndexs();
  1321. if (!m_bBgallocActive)
  1322. return;
  1323. _bgalloc();
  1324. }
  1325. bool CStorageWrapperEx::bgalloc()
  1326. {
  1327. /*
  1328. if (!m_vHoles.empty() && !m_bBgallocEnabled) // useless when no need catch flush command.
  1329. {
  1330. m_bBgallocEnabled = true;
  1331. }
  1332. //*/
  1333. m_bBgallocActive = true;
  1334. return true;
  1335. }
  1336. bool CStorageWrapperEx::_bgalloc()
  1337. {
  1338. if (!m_vHoles.empty())
  1339. {
  1340. _doalloc();
  1341. }
  1342. else
  1343. {
  1344. m_pStorage->flush();
  1345. m_bBgallocActive = false;
  1346. }
  1347. return true;
  1348. }
  1349. bool CStorageWrapperEx::_MakeOffsetToTruePlace(const long index, const long n)
  1350. {
  1351. //////////////////////////////////////////////////////////////////////////////
  1352. // if the hole is took by next file offset part, move it to next index.
  1353. char* pszBuf = new char[m_piece_length];
  1354. auto_ptr<char> aszBuf(pszBuf);
  1355. long lFileIndex = -1;
  1356. bool bFind = false;
  1357. for (int i=0; i<m_vRangeHoles.size(); i++)
  1358. {
  1359. if (index < m_vRangeHoles[i])
  1360. {
  1361. bFind = true;
  1362. lFileIndex = i - 1;
  1363. break;
  1364. }
  1365. }
  1366. if (!bFind)
  1367. lFileIndex = m_vRangeHoles.size() - 1;
  1368. assert(lFileIndex >= 0);
  1369. if (lFileIndex < (m_vRangeHoles.size() - 1))
  1370. {
  1371. if (m_vOffsetTrueIndex[lFileIndex + 1] == n)
  1372. {
  1373. long lNextIndex = m_vRangeHoles[lFileIndex + 1];
  1374. if (m_vOffsetTrueIndex[lFileIndex + 1] >= lNextIndex)
  1375. {
  1376. assert(false);
  1377. return false;
  1378. }
  1379. //
  1380. // tell whether the next file offset part filled, if yes move it.
  1381. //
  1382. if (find(m_vHoles.begin(), m_vHoles.end(), lNextIndex) == m_vHoles.end())
  1383. {
  1384. if (!m_pStorage->read(pszBuf, (BLONG)m_piece_length * n, m_vFileOffset[lFileIndex + 1]))
  1385. return false;
  1386. if (!m_pStorage->write(pszBuf, (BLONG)m_piece_length * lNextIndex , m_vFileOffset[lFileIndex + 1]))
  1387. return false;
  1388. }
  1389. //
  1390. // mark the offset to next index, no matter whether it is filled.
  1391. //
  1392. m_vOffsetTrueIndex[lFileIndex + 1] = -1;
  1393. }
  1394. }
  1395. return true;
  1396. }
  1397. bool CStorageWrapperEx::_doalloc()
  1398. {
  1399. if (m_vHoles.empty())
  1400. {
  1401. assert(false);
  1402. return false;
  1403. }
  1404. int n = m_vHoles[0];
  1405. m_vHoles.erase(m_vHoles.begin());
  1406. char* pszBuf = new char[m_piece_length];
  1407. auto_ptr<char> aszBuf(pszBuf);
  1408. //
  1409. // check to see whether the space is took by offset.
  1410. //
  1411. if (!_MakeOffsetToTruePlace(n, n))
  1412. return false;
  1413. map<long, long >::iterator iter = m_mPlaces.find(n);
  1414. if (iter != m_mPlaces.end())
  1415. {
  1416. long lOldPos = (*iter).second;
  1417. m_mPlaces[lOldPos] = lOldPos;
  1418. if (!_ReadIndexData(pszBuf, (BLONG)m_piece_length * lOldPos, _piecelen(n)))
  1419. return false;
  1420. if (!_WriteIndexData(pszBuf, (BLONG)m_piece_length * n, _piecelen(n)))
  1421. return false;
  1422. // check move data result.
  1423. if (!CheckAfterMoveing(n, pszBuf))
  1424. return false;
  1425. }
  1426. else
  1427. {
  1428. memset(pszBuf, 0xff, m_piece_length);
  1429. if (!_WriteIndexData(pszBuf, (BLONG)m_piece_length * n, _piecelen(n)))
  1430. return false;
  1431. }
  1432. // allocate done.
  1433. m_mPlaces[n] = n;
  1434. return true;
  1435. }
  1436. bool CStorageWrapperEx::_waspre(int iIndex)
  1437. {
  1438. return m_pStorage->was_preallocated((BLONG)iIndex * m_piece_length, _piecelen(iIndex));
  1439. }
  1440. void CStorageWrapperEx::markgot(long iPiece, long lPos)
  1441. {
  1442. m_mPlaces[iPiece] = lPos;
  1443. m_vHave[iPiece] = true;
  1444. m_lAmountLeft -= _piecelen(iPiece);
  1445. m_lAmountInactive -= _piecelen(iPiece);
  1446. m_vInactiveRequests[iPiece].clear();
  1447. m_vWasChecked[iPiece] = m_bCheckHashes;
  1448. m_lStatNumfound ++;
  1449. }
  1450. long CStorageWrapperEx::_piecelen(int iPiece)
  1451. {
  1452. if (iPiece < (m_vHashs.size() - 1))
  1453. return m_piece_length;
  1454. return m_lTotalLength - ((BLONG)iPiece * m_piece_length);
  1455. }
  1456. void printHave(long x)
  1457. {
  1458. TRACE("%d, ", x);
  1459. }
  1460. void printPlace(pair<long, long> p)
  1461. {
  1462. TRACE("(%d, %d)", p.first, p.second);
  1463. }
  1464. void CStorageWrapperEx::ShowDetailsTest()
  1465. {
  1466. TRACE("rn places : {");
  1467. for_each(m_mPlaces.begin(), m_mPlaces.end(), printPlace);
  1468. TRACE("}rn");
  1469. TRACE("rn have : {");
  1470. for_each(m_vHave.begin(), m_vHave.end(), printHave);
  1471. TRACE("}rn");
  1472. TRACE("rn m_vHoles: {");
  1473. for_each(m_vHoles.begin(), m_vHoles.end(), printHave);
  1474. TRACE("}rn");
  1475. TRACE("m_lAmountLeft : %d rn",m_lAmountLeft);
  1476. TRACE("m_lAmountInactive : %d rn",m_lAmountInactive);
  1477. }
  1478. /*
  1479. bool CStorageWrapperEx::_piece_came_in(long index, char *pPieceBuf, long begin,  long length)
  1480. {
  1481. char* pszBuf = new char[m_piece_length];
  1482. auto_ptr<char> aszBuf(pszBuf);
  1483. if (m_vHoles.empty())
  1484. {
  1485. assert(false);
  1486. return false;
  1487. }
  1488. //////////////////////////////////////////////////////////////
  1489. // Get hole in needed files 
  1490. //
  1491. /*
  1492. // const int n = m_vHoles[0];
  1493. // m_vHoles.erase(m_vHoles.begin());
  1494. int iHoleIndex = -1;
  1495. if (!IsUnNeededIndex(index))
  1496. {
  1497. for (int ih =0; ih<m_vHoles.size(); ih++)
  1498. {
  1499. if (!IsUnNeededIndex(m_vHoles[ih]))
  1500. {
  1501. iHoleIndex = m_vHoles[ih];
  1502. m_vHoles.erase(m_vHoles.begin() + ih);
  1503. break;
  1504. }
  1505. }
  1506. }
  1507. else
  1508. {
  1509. int iHoleIndex = m_vHoles[0];
  1510. m_vHoles.erase(m_vHoles.begin());
  1511. }
  1512. // get hole fail.
  1513. if (iHoleIndex < 0)
  1514. {
  1515. int iHoleIndex = m_vHoles[0];
  1516. m_vHoles.erase(m_vHoles.begin());
  1517. TRACE("rn***** get hole fail ******rn");
  1518. assert(false);
  1519. }
  1520. const int n = iHoleIndex;
  1521. map<long, long>::iterator iter = m_mPlaces.find(n);
  1522. // The new hole poped is needed by item in temps.
  1523. if (iter != m_mPlaces.end()) 
  1524. {
  1525. // Move data from temp to split newly created from holes.
  1526. long lOldPos = (*iter).second;
  1527. if (!m_pStorage->read(pszBuf, m_piece_length * lOldPos, _piecelen(n)))
  1528. return false;
  1529. if (!m_pStorage->write(pszBuf, m_piece_length * n, _piecelen(n)))
  1530. return false;
  1531. CheckAfterMoveing(n, pszBuf);
  1532. m_mPlaces[n] = n;
  1533. // Don't move, just specify the index item in the split newly created from holes.
  1534. if (index == lOldPos || 
  1535. find(m_vHoles.begin(), m_vHoles.end(), index) != m_vHoles.end())
  1536. {
  1537. m_mPlaces[index] = lOldPos;
  1538. }
  1539. else // Move data from split which take the place of index item.
  1540. {
  1541. long p = 0;
  1542. for (map<long, long>::iterator j = m_mPlaces.begin(); j != m_mPlaces.end(); j++)
  1543. {
  1544. if ((*j).second == index)
  1545. {
  1546. p = (*j).first;
  1547. break;
  1548. }
  1549. }
  1550. if (j == m_mPlaces.end())
  1551. {
  1552. assert(false);
  1553. return false;
  1554. }
  1555. if (!m_pStorage->read(pszBuf, m_piece_length * index, _piecelen(p)))
  1556. return false;
  1557. if (!m_pStorage->write(pszBuf, m_piece_length * lOldPos, _piecelen(p)))
  1558. return false;
  1559. m_mPlaces[p] = lOldPos;
  1560. m_mPlaces[index] = index;
  1561. }
  1562. }
  1563. else if (index == n || // index item out of space.
  1564. find(m_vHoles.begin(), m_vHoles.end(), index) != m_vHoles.end())
  1565. {
  1566. memset(pszBuf, 0xff, _piecelen(n));
  1567. if (!m_pStorage->write(pszBuf, m_piece_length * n, _piecelen(n)))
  1568. return false;
  1569. m_mPlaces[index] = n;
  1570. }
  1571. else // Move item in index space to hole poped. Insert index item in space allocated. 
  1572. {
  1573. long p = 0;
  1574. for (map<long, long>::iterator j = m_mPlaces.begin(); j != m_mPlaces.end(); j++)
  1575. {
  1576. if ((*j).second == index)
  1577. {
  1578. p = (*j).first;
  1579. break;
  1580. }
  1581. }
  1582. if (j == m_mPlaces.end())
  1583. {
  1584. assert(false);
  1585. return false;
  1586. }
  1587. if (!m_pStorage->read(pszBuf, m_piece_length * index, _piecelen(p)))
  1588. return false;
  1589. if (!m_pStorage->write(pszBuf, m_piece_length * n, _piecelen(p)))
  1590. return false;
  1591. m_mPlaces[p] = n;
  1592. m_mPlaces[index] = index;
  1593. }// endif hole pop
  1594. }
  1595. //*/
  1596. /*
  1597. long CStorageWrapperEx::_GetMinHolesIndex(const long index)
  1598. {
  1599. if (m_vRangeHoles.size() <= 0)
  1600. {
  1601. assert(false);
  1602. return -1;
  1603. }
  1604. for (int i=0; i<m_vRangeHoles.size(); i++)
  1605. {
  1606. if (index < m_vRangeHoles[i])
  1607. {
  1608. assert(i > 0);
  1609. return m_vRangeHoles[i - 1];
  1610. }
  1611. }
  1612. return m_vRangeHoles[m_vRangeHoles.size() - 1];
  1613. // assert(false);
  1614. return -1;
  1615. }
  1616. CSize CStorageWrapperEx::_GetFileOffset(const long index)
  1617. {
  1618. assert(m_vRangeHoles.size() == m_vFileOffset.size());
  1619. for (int i=0; i<m_vRangeHoles.size(); i++)
  1620. {
  1621. if (index >= m_vRangeHoles[i])
  1622. {
  1623. if (i >= (m_vRangeHoles.size()-1))
  1624. return CSize(-1, -1);
  1625. return CSize (m_vRangeHoles[i+1], m_vFileOffset[i + 1]);
  1626. }
  1627. }
  1628. assert(false);
  1629. return -1;
  1630. }
  1631. //*/