BitfieldMan.cc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  1. /* <!-- copyright */
  2. /*
  3. * aria2 - The high speed download utility
  4. *
  5. * Copyright (C) 2006 Tatsuhiro Tsujikawa
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. * In addition, as a special exception, the copyright holders give
  22. * permission to link the code of portions of this program with the
  23. * OpenSSL library under certain conditions as described in each
  24. * individual source file, and distribute linked combinations
  25. * including the two.
  26. * You must obey the GNU General Public License in all respects
  27. * for all of the code used other than OpenSSL. If you modify
  28. * file(s) with this exception, you may extend this exception to your
  29. * version of the file(s), but you are not obligated to do so. If you
  30. * do not wish to do so, delete this exception statement from your
  31. * version. If you delete this exception statement from all source
  32. * files in the program, then also delete it here.
  33. */
  34. /* copyright --> */
  35. #include "BitfieldMan.h"
  36. #include <cassert>
  37. #include <cstring>
  38. #include "util.h"
  39. #include "array_fun.h"
  40. #include "bitfield.h"
  41. using namespace aria2::expr;
  42. namespace aria2 {
  43. BitfieldMan::BitfieldMan(size_t blockLength, uint64_t totalLength)
  44. :blockLength(blockLength),
  45. totalLength(totalLength),
  46. bitfieldLength(0),
  47. blocks(0),
  48. filterEnabled(false),
  49. bitfield(0),
  50. useBitfield(0),
  51. filterBitfield(0),
  52. cachedNumMissingBlock(0),
  53. cachedNumFilteredBlock(0),
  54. cachedCompletedLength(0),
  55. cachedFilteredComletedLength(0),
  56. cachedFilteredTotalLength(0)
  57. {
  58. if(blockLength > 0 && totalLength > 0) {
  59. blocks = totalLength/blockLength+(totalLength%blockLength ? 1 : 0);
  60. bitfieldLength = blocks/8+(blocks%8 ? 1 : 0);
  61. bitfield = new unsigned char[bitfieldLength];
  62. useBitfield = new unsigned char[bitfieldLength];
  63. memset(bitfield, 0, bitfieldLength);
  64. memset(useBitfield, 0, bitfieldLength);
  65. updateCache();
  66. }
  67. }
  68. BitfieldMan::BitfieldMan(const BitfieldMan& bitfieldMan)
  69. :blockLength(bitfieldMan.blockLength),
  70. totalLength(bitfieldMan.totalLength),
  71. bitfieldLength(bitfieldMan.bitfieldLength),
  72. blocks(bitfieldMan.blocks),
  73. filterEnabled(bitfieldMan.filterEnabled),
  74. bitfield(new unsigned char[bitfieldLength]),
  75. useBitfield(new unsigned char[bitfieldLength]),
  76. filterBitfield(0),
  77. cachedNumMissingBlock(0),
  78. cachedNumFilteredBlock(0),
  79. cachedCompletedLength(0),
  80. cachedFilteredComletedLength(0),
  81. cachedFilteredTotalLength(0)
  82. {
  83. memcpy(bitfield, bitfieldMan.bitfield, bitfieldLength);
  84. memcpy(useBitfield, bitfieldMan.useBitfield, bitfieldLength);
  85. if(filterEnabled) {
  86. filterBitfield = new unsigned char[bitfieldLength];
  87. memcpy(filterBitfield, bitfieldMan.filterBitfield, bitfieldLength);
  88. }
  89. updateCache();
  90. }
  91. BitfieldMan& BitfieldMan::operator=(const BitfieldMan& bitfieldMan)
  92. {
  93. if(this != &bitfieldMan) {
  94. blockLength = bitfieldMan.blockLength;
  95. totalLength = bitfieldMan.totalLength;
  96. blocks = bitfieldMan.blocks;
  97. bitfieldLength = bitfieldMan.bitfieldLength;
  98. filterEnabled = bitfieldMan.filterEnabled;
  99. delete [] bitfield;
  100. bitfield = new unsigned char[bitfieldLength];
  101. memcpy(bitfield, bitfieldMan.bitfield, bitfieldLength);
  102. delete [] useBitfield;
  103. useBitfield = new unsigned char[bitfieldLength];
  104. memcpy(useBitfield, bitfieldMan.useBitfield, bitfieldLength);
  105. delete [] filterBitfield;
  106. if(filterEnabled) {
  107. filterBitfield = new unsigned char[bitfieldLength];
  108. memcpy(filterBitfield, bitfieldMan.filterBitfield, bitfieldLength);
  109. } else {
  110. filterBitfield = 0;
  111. }
  112. updateCache();
  113. }
  114. return *this;
  115. }
  116. BitfieldMan::~BitfieldMan() {
  117. delete [] bitfield;
  118. delete [] useBitfield;
  119. delete [] filterBitfield;
  120. }
  121. size_t BitfieldMan::getBlockLength(size_t index) const
  122. {
  123. if(index == blocks-1) {
  124. return getLastBlockLength();
  125. } else if(index < blocks-1) {
  126. return getBlockLength();
  127. } else {
  128. return 0;
  129. }
  130. }
  131. bool BitfieldMan::hasMissingPiece
  132. (const unsigned char* peerBitfield, size_t length) const
  133. {
  134. if(bitfieldLength != length) {
  135. return false;
  136. }
  137. bool retval = false;
  138. for(size_t i = 0; i < bitfieldLength; ++i) {
  139. unsigned char temp = peerBitfield[i] & ~bitfield[i];
  140. if(filterEnabled) {
  141. temp &= filterBitfield[i];
  142. }
  143. if(temp&0xff) {
  144. retval = true;
  145. break;
  146. }
  147. }
  148. return retval;
  149. }
  150. bool BitfieldMan::getFirstMissingUnusedIndex(size_t& index) const
  151. {
  152. if(filterEnabled) {
  153. return bitfield::getFirstMissingIndex
  154. (index, ~array(bitfield)&~array(useBitfield)&array(filterBitfield),
  155. blocks);
  156. } else {
  157. return bitfield::getFirstMissingIndex
  158. (index, ~array(bitfield)&~array(useBitfield), blocks);
  159. }
  160. }
  161. size_t BitfieldMan::getFirstNMissingUnusedIndex
  162. (std::vector<size_t>& out, size_t n) const
  163. {
  164. if(filterEnabled) {
  165. return bitfield::getFirstNMissingIndex
  166. (std::back_inserter(out), n,
  167. ~array(bitfield)&~array(useBitfield)&array(filterBitfield), blocks);
  168. } else {
  169. return bitfield::getFirstNMissingIndex
  170. (std::back_inserter(out), n,
  171. ~array(bitfield)&~array(useBitfield), blocks);
  172. }
  173. }
  174. bool BitfieldMan::getFirstMissingIndex(size_t& index) const
  175. {
  176. if(filterEnabled) {
  177. return bitfield::getFirstMissingIndex
  178. (index, ~array(bitfield)&array(filterBitfield), blocks);
  179. } else {
  180. return bitfield::getFirstMissingIndex(index, ~array(bitfield), blocks);
  181. }
  182. }
  183. template<typename Array>
  184. static size_t getStartIndex(size_t index, const Array& bitfield, size_t blocks) {
  185. while(index < blocks && bitfield::test(bitfield, blocks, index)) {
  186. ++index;
  187. }
  188. if(blocks <= index) {
  189. return blocks;
  190. } else {
  191. return index;
  192. }
  193. }
  194. template<typename Array>
  195. static size_t getEndIndex(size_t index, const Array& bitfield, size_t blocks) {
  196. while(index < blocks && !bitfield::test(bitfield, blocks, index)) {
  197. ++index;
  198. }
  199. return index;
  200. }
  201. template<typename Array>
  202. static bool getSparseMissingUnusedIndex
  203. (size_t& index,
  204. const Array& bitfield,
  205. const unsigned char* useBitfield,
  206. size_t blocks)
  207. {
  208. BitfieldMan::Range maxRange;
  209. BitfieldMan::Range currentRange;
  210. {
  211. size_t nextIndex = 0;
  212. while(nextIndex < blocks) {
  213. currentRange.startIndex =
  214. getStartIndex(nextIndex, bitfield, blocks);
  215. if(currentRange.startIndex == blocks) {
  216. break;
  217. }
  218. currentRange.endIndex =
  219. getEndIndex(currentRange.startIndex, bitfield, blocks);
  220. if(maxRange < currentRange) {
  221. maxRange = currentRange;
  222. }
  223. nextIndex = currentRange.endIndex;
  224. }
  225. }
  226. if(maxRange.getSize()) {
  227. if(maxRange.startIndex == 0) {
  228. index = 0;
  229. } else if(bitfield::test(useBitfield, blocks, maxRange.startIndex-1)) {
  230. index = maxRange.getMidIndex();
  231. } else {
  232. index = maxRange.startIndex;
  233. }
  234. return true;
  235. } else {
  236. return false;
  237. }
  238. }
  239. bool BitfieldMan::getSparseMissingUnusedIndex
  240. (size_t& index,
  241. const unsigned char* ignoreBitfield,
  242. size_t ignoreBitfieldLength) const
  243. {
  244. if(filterEnabled) {
  245. return aria2::getSparseMissingUnusedIndex
  246. (index, array(ignoreBitfield)|~array(filterBitfield)|array(bitfield)|array(useBitfield),
  247. useBitfield, blocks);
  248. } else {
  249. return aria2::getSparseMissingUnusedIndex
  250. (index, array(ignoreBitfield)|array(bitfield)|array(useBitfield),
  251. useBitfield, blocks);
  252. }
  253. }
  254. template<typename Array>
  255. static bool copyBitfield(unsigned char* dst, const Array& src, size_t blocks)
  256. {
  257. unsigned char bits = 0;
  258. size_t len = (blocks+7)/8;
  259. for(size_t i = 0; i < len-1; ++i) {
  260. dst[i] = src[i];
  261. bits |= dst[i];
  262. }
  263. dst[len-1] = src[len-1]&bitfield::lastByteMask(blocks);
  264. bits |= dst[len-1];
  265. return bits != 0;
  266. }
  267. bool BitfieldMan::getAllMissingIndexes(unsigned char* misbitfield, size_t len)
  268. const
  269. {
  270. assert(len == bitfieldLength);
  271. if(filterEnabled) {
  272. return copyBitfield
  273. (misbitfield, ~array(bitfield)&array(filterBitfield), blocks);
  274. } else {
  275. return copyBitfield(misbitfield, ~array(bitfield), blocks);
  276. }
  277. }
  278. bool BitfieldMan::getAllMissingIndexes(unsigned char* misbitfield, size_t len,
  279. const unsigned char* peerBitfield,
  280. size_t peerBitfieldLength) const
  281. {
  282. assert(len == bitfieldLength);
  283. if(bitfieldLength != peerBitfieldLength) {
  284. return false;
  285. }
  286. if(filterEnabled) {
  287. return copyBitfield
  288. (misbitfield, ~array(bitfield)&array(peerBitfield)&array(filterBitfield),
  289. blocks);
  290. } else {
  291. return copyBitfield
  292. (misbitfield, ~array(bitfield)&array(peerBitfield),
  293. blocks);
  294. }
  295. }
  296. bool BitfieldMan::getAllMissingUnusedIndexes(unsigned char* misbitfield,
  297. size_t len,
  298. const unsigned char* peerBitfield,
  299. size_t peerBitfieldLength) const
  300. {
  301. assert(len == bitfieldLength);
  302. if(bitfieldLength != peerBitfieldLength) {
  303. return false;
  304. }
  305. if(filterEnabled) {
  306. return copyBitfield
  307. (misbitfield,
  308. ~array(bitfield)&~array(useBitfield)&array(peerBitfield)&array(filterBitfield),
  309. blocks);
  310. } else {
  311. return copyBitfield
  312. (misbitfield,
  313. ~array(bitfield)&~array(useBitfield)&array(peerBitfield),
  314. blocks);
  315. }
  316. }
  317. size_t BitfieldMan::countMissingBlock() const {
  318. return cachedNumMissingBlock;
  319. }
  320. size_t BitfieldMan::countMissingBlockNow() const {
  321. if(filterEnabled) {
  322. array_ptr<unsigned char> temp(new unsigned char[bitfieldLength]);
  323. for(size_t i = 0; i < bitfieldLength; ++i) {
  324. temp[i] = bitfield[i]&filterBitfield[i];
  325. }
  326. size_t count = bitfield::countSetBit(filterBitfield, blocks)-
  327. bitfield::countSetBit(temp, blocks);
  328. return count;
  329. } else {
  330. return blocks-bitfield::countSetBit(bitfield, blocks);
  331. }
  332. }
  333. size_t BitfieldMan::countFilteredBlockNow() const {
  334. if(filterEnabled) {
  335. return bitfield::countSetBit(filterBitfield, blocks);
  336. } else {
  337. return 0;
  338. }
  339. }
  340. bool BitfieldMan::setBitInternal(unsigned char* bitfield, size_t index, bool on) {
  341. if(blocks <= index) { return false; }
  342. unsigned char mask = 128 >> (index%8);
  343. if(on) {
  344. bitfield[index/8] |= mask;
  345. } else {
  346. bitfield[index/8] &= ~mask;
  347. }
  348. return true;
  349. }
  350. bool BitfieldMan::setUseBit(size_t index) {
  351. return setBitInternal(useBitfield, index, true);
  352. }
  353. bool BitfieldMan::unsetUseBit(size_t index) {
  354. return setBitInternal(useBitfield, index, false);
  355. }
  356. bool BitfieldMan::setBit(size_t index) {
  357. bool b = setBitInternal(bitfield, index, true);
  358. updateCache();
  359. return b;
  360. }
  361. bool BitfieldMan::unsetBit(size_t index) {
  362. bool b = setBitInternal(bitfield, index, false);
  363. updateCache();
  364. return b;
  365. }
  366. bool BitfieldMan::isFilteredAllBitSet() const {
  367. if(filterEnabled) {
  368. for(size_t i = 0; i < bitfieldLength; ++i) {
  369. if((bitfield[i]&filterBitfield[i]) != filterBitfield[i]) {
  370. return false;
  371. }
  372. }
  373. return true;
  374. } else {
  375. return isAllBitSet();
  376. }
  377. }
  378. static bool testAllBitSet
  379. (const unsigned char* bitfield, size_t length, size_t blocks)
  380. {
  381. if(length == 0) {
  382. return true;
  383. }
  384. for(size_t i = 0; i < length-1; ++i) {
  385. if(bitfield[i] != 0xff) {
  386. return false;
  387. }
  388. }
  389. return bitfield[length-1] == bitfield::lastByteMask(blocks);
  390. }
  391. bool BitfieldMan::isAllBitSet() const
  392. {
  393. return testAllBitSet(bitfield, bitfieldLength, blocks);
  394. }
  395. bool BitfieldMan::isAllFilterBitSet() const
  396. {
  397. if(!filterBitfield) {
  398. return false;
  399. }
  400. return testAllBitSet(filterBitfield, bitfieldLength, blocks);
  401. }
  402. bool BitfieldMan::isBitSet(size_t index) const
  403. {
  404. return bitfield::test(bitfield, blocks, index);
  405. }
  406. bool BitfieldMan::isUseBitSet(size_t index) const
  407. {
  408. return bitfield::test(useBitfield, blocks, index);
  409. }
  410. void BitfieldMan::setBitfield(const unsigned char* bitfield, size_t bitfieldLength) {
  411. if(this->bitfieldLength != bitfieldLength) {
  412. return;
  413. }
  414. memcpy(this->bitfield, bitfield, this->bitfieldLength);
  415. memset(this->useBitfield, 0, this->bitfieldLength);
  416. updateCache();
  417. }
  418. void BitfieldMan::clearAllBit() {
  419. memset(this->bitfield, 0, this->bitfieldLength);
  420. updateCache();
  421. }
  422. void BitfieldMan::setAllBit() {
  423. for(size_t i = 0; i < blocks; ++i) {
  424. setBitInternal(bitfield, i, true);
  425. }
  426. updateCache();
  427. }
  428. void BitfieldMan::clearAllUseBit() {
  429. memset(this->useBitfield, 0, this->bitfieldLength);
  430. updateCache();
  431. }
  432. void BitfieldMan::setAllUseBit() {
  433. for(size_t i = 0; i < blocks; ++i) {
  434. setBitInternal(useBitfield, i, true);
  435. }
  436. }
  437. bool BitfieldMan::setFilterBit(size_t index) {
  438. return setBitInternal(filterBitfield, index, true);
  439. }
  440. void BitfieldMan::ensureFilterBitfield()
  441. {
  442. if(!filterBitfield) {
  443. filterBitfield = new unsigned char[bitfieldLength];
  444. memset(filterBitfield, 0, bitfieldLength);
  445. }
  446. }
  447. void BitfieldMan::addFilter(uint64_t offset, uint64_t length) {
  448. ensureFilterBitfield();
  449. if(length > 0) {
  450. size_t startBlock = offset/blockLength;
  451. size_t endBlock = (offset+length-1)/blockLength;
  452. for(size_t i = startBlock; i <= endBlock && i < blocks; i++) {
  453. setFilterBit(i);
  454. }
  455. }
  456. updateCache();
  457. }
  458. void BitfieldMan::removeFilter(uint64_t offset, uint64_t length) {
  459. ensureFilterBitfield();
  460. if(length > 0) {
  461. size_t startBlock = offset/blockLength;
  462. size_t endBlock = (offset+length-1)/blockLength;
  463. for(size_t i = startBlock; i <= endBlock && i < blocks; i++) {
  464. setBitInternal(filterBitfield, i, false);
  465. }
  466. }
  467. updateCache();
  468. }
  469. void BitfieldMan::addNotFilter(uint64_t offset, uint64_t length)
  470. {
  471. ensureFilterBitfield();
  472. if(length > 0 && blocks > 0) {
  473. size_t startBlock = offset/blockLength;
  474. if(blocks <= startBlock) {
  475. startBlock = blocks;
  476. }
  477. size_t endBlock = (offset+length-1)/blockLength;
  478. for(size_t i = 0; i < startBlock; ++i) {
  479. setFilterBit(i);
  480. }
  481. for(size_t i = endBlock+1; i < blocks; ++i) {
  482. setFilterBit(i);
  483. }
  484. }
  485. updateCache();
  486. }
  487. void BitfieldMan::enableFilter() {
  488. ensureFilterBitfield();
  489. filterEnabled = true;
  490. updateCache();
  491. }
  492. void BitfieldMan::disableFilter() {
  493. filterEnabled = false;
  494. updateCache();
  495. }
  496. void BitfieldMan::clearFilter() {
  497. if(filterBitfield) {
  498. delete [] filterBitfield;
  499. filterBitfield = 0;
  500. }
  501. filterEnabled = false;
  502. updateCache();
  503. }
  504. uint64_t BitfieldMan::getFilteredTotalLengthNow() const {
  505. if(!filterBitfield) {
  506. return 0;
  507. }
  508. size_t filteredBlocks = bitfield::countSetBit(filterBitfield, blocks);
  509. if(filteredBlocks == 0) {
  510. return 0;
  511. }
  512. if(bitfield::test(filterBitfield, blocks, blocks-1)) {
  513. return ((uint64_t)filteredBlocks-1)*blockLength+getLastBlockLength();
  514. } else {
  515. return ((uint64_t)filteredBlocks)*blockLength;
  516. }
  517. }
  518. uint64_t BitfieldMan::getCompletedLength(bool useFilter) const {
  519. unsigned char* temp;
  520. if(useFilter) {
  521. temp = new unsigned char[bitfieldLength];
  522. for(size_t i = 0; i < bitfieldLength; ++i) {
  523. temp[i] = bitfield[i];
  524. if(filterEnabled) {
  525. temp[i] &= filterBitfield[i];
  526. }
  527. }
  528. } else {
  529. temp = bitfield;
  530. }
  531. size_t completedBlocks = bitfield::countSetBit(temp, blocks);
  532. uint64_t completedLength = 0;
  533. if(completedBlocks == 0) {
  534. completedLength = 0;
  535. } else {
  536. if(bitfield::test(temp, blocks, blocks-1)) {
  537. completedLength = ((uint64_t)completedBlocks-1)*blockLength+getLastBlockLength();
  538. } else {
  539. completedLength = ((uint64_t)completedBlocks)*blockLength;
  540. }
  541. }
  542. if(useFilter) {
  543. delete [] temp;
  544. }
  545. return completedLength;
  546. }
  547. uint64_t BitfieldMan::getCompletedLengthNow() const {
  548. return getCompletedLength(false);
  549. }
  550. uint64_t BitfieldMan::getFilteredCompletedLengthNow() const {
  551. return getCompletedLength(true);
  552. }
  553. void BitfieldMan::updateCache()
  554. {
  555. cachedNumMissingBlock = countMissingBlockNow();
  556. cachedNumFilteredBlock = countFilteredBlockNow();
  557. cachedFilteredTotalLength = getFilteredTotalLengthNow();
  558. cachedCompletedLength = getCompletedLengthNow();
  559. cachedFilteredComletedLength = getFilteredCompletedLengthNow();
  560. }
  561. bool BitfieldMan::isBitRangeSet(size_t startIndex, size_t endIndex) const
  562. {
  563. for(size_t i = startIndex; i <= endIndex; ++i) {
  564. if(!isBitSet(i)) {
  565. return false;
  566. }
  567. }
  568. return true;
  569. }
  570. void BitfieldMan::unsetBitRange(size_t startIndex, size_t endIndex)
  571. {
  572. for(size_t i = startIndex; i <= endIndex; ++i) {
  573. unsetBit(i);
  574. }
  575. updateCache();
  576. }
  577. void BitfieldMan::setBitRange(size_t startIndex, size_t endIndex)
  578. {
  579. for(size_t i = startIndex; i <= endIndex; ++i) {
  580. setBit(i);
  581. }
  582. updateCache();
  583. }
  584. bool BitfieldMan::isBitSetOffsetRange(uint64_t offset, uint64_t length) const
  585. {
  586. if(length <= 0) {
  587. return false;
  588. }
  589. if(totalLength <= offset) {
  590. return false;
  591. }
  592. if(totalLength < offset+length) {
  593. length = totalLength-offset;
  594. }
  595. size_t startBlock = offset/blockLength;
  596. size_t endBlock = (offset+length-1)/blockLength;
  597. for(size_t i = startBlock; i <= endBlock; i++) {
  598. if(!isBitSet(i)) {
  599. return false;
  600. }
  601. }
  602. return true;
  603. }
  604. uint64_t BitfieldMan::getMissingUnusedLength(size_t startingIndex) const
  605. {
  606. if(startingIndex < 0 || blocks <= startingIndex) {
  607. return 0;
  608. }
  609. uint64_t length = 0;
  610. for(size_t i = startingIndex; i < blocks; ++i) {
  611. if(isBitSet(i) || isUseBitSet(i)) {
  612. break;
  613. }
  614. length += getBlockLength(i);
  615. }
  616. return length;
  617. }
  618. } // namespace aria2