summaryrefslogtreecommitdiff
path: root/src/BitfieldMan.cc
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2006-05-24 15:18:58 +0000
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2006-05-24 15:18:58 +0000
commit0411de92716bbdefa5dc795f1ecb8a2c2d61004e (patch)
tree374ffa60e707f21a17d3e599459e6614eda98489 /src/BitfieldMan.cc
parent896ca193e01f9f629f222fe992e05aebdca23a24 (diff)
2006-05-24 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
To attempt to handle EINTR: * src/SocketCore.cc (isReadable): Added EINTR handling. (isWritable): Added EINTR handling. To improve the performance: * src/AbstractCommand.cc (isTimeoutDetected): Use Util::difftvsec() instead of Util::difftv(). * src/PeerInteractionCommand.h (receiveMessage): Renamed as receiveMessages(). (receiveMessages): New function. * src/PeerInteractionCommand.cc (executeInternal): receiveMessage loop is moved to new receiveMessages () function. detectMessageFlooding() is moved here. (detectMessageFlooding): Use Util::difftvsec() instead of Util::difftv (). The flooding detection for have message is comment out. (checkLongTimePeerChoking): Use Util::difftvsec() instead of Util::difftv(). (receiveMessage): Renamed as receiveMessages(). (receiveMessages): New function. (keepAlive): Use Util::difftvsec() instead of Util::difftv(). (beforeSocketCheck): Commented out checkLongTimePeerChoking(). * src/SleepCommand.cc (execute): Use Util::difftvsec() instead of Util::difftv(). * src/BitfieldMan.h (getNthBitIndex): New function. (hasMissingPiece): New function. (getAllMissingIndexes): New function. * src/BitfieldMan.cc (countSetBit): Rewritten. (getNthBitIndex): New function. (getMissingIndexRandomly): Rewritten. (hasMissingPiece): New function. (getAllMissingIndexes): New function. * src/TorrentMan.cc (hasMissingPiece): New function. (deleteUsedPiece): Rewritten using STL. * src/PeerInteraction.cc (getNewPieceAndSendInterest): Use TorrentMan::hasMissingPiece(), which is a little bit faster then TorrentMan::getMissingPieceIndex(). (addRequests): Updated the number of pending requests. * src/PeerAbstractCommand.cc (isTimeoutDetected): Use Util::difftvsec() instead of Util::difftv(). (execute): Returns true if TorrentMan::isHalt() is true. Corrected the condition of upload limit checking. * src/Util.h (countBit): New function. * src/Util.cc (nbits): New variable. (countBit): New function. * src/DownloadEngine.h (SockCmdMap): New type definition. (waitData): Added an argument. (addSocket): Added an argument. (addSocketForReadCheck): Added an argument. (addSocketForWriteCheck): Added an argument. * src/DownloadEngine.cc (run): Executes only commands whose sockets are ready to read or write. All commands are executed in every 1 second. (waitData): Calls select() again if it returned EINTR. (addSocket): Saves socket and command object pair to the map. (deleteSocket): Deletes socket and command object pair from the map. (addSocketForReadCheck): Added an argument. (addSocketForWriteCheck): Added an argument. * src/DownloadCommand.cc (executeInternal): Use Util::difftvsec() instead of Util::difftv(). To send "event=stopped" to the tracker when the application finishes: * src/PeerChokeCommand.h (checkPoint): New variable. * src/PeerChokeCommand.cc (PeerChokeCommand): Added the initialization of checkPoint. (execute): The interval check is now done by checkPoint, not SleepCommand. Return true if TorrentMan::isHalt() is true. * src/TorrentMan.h (halt): New function. (hasMissingPiece): New function. (isHalt): New function. (setHalt): New function. * src/TorrentMan.cc (TorrentMan): Added the initialization of halt. * src/TorrentAutoSaveCommand.h (checkPoint): New variable. * src/PeerListenCommand.cc (execute): Returns true if TorrentMan::isHalt() is true. * src/main.cc (setSignalHander): Added flags argument. (torrentHandler): Just calls TorrentMan::setHalt(true) and returns. (main): Set SA_ONESHOT flag of the signal hander of SIGINT and SIGTERM. Removed printDownloadAbortMessage() after torrent downloading loop. * src/TorrentAutoSaveCommand.cc (TorrentAutoSaveCommand): Added the initialization of checkPoint. (execute): Returns true if TorrentMan::isHalt() is true. The interval check is now done by checkPoint, not SleepCommand. * src/TrackerWatcherCommand.cc (execute): If TorrentMan::isHalt(), then create a tracker request with event=stopped. * src/TrackerUpdateCommand.cc (prepareForRetry): Do not use SleepCommand here. (execute): Returns true if TorrentMan::isHalt() is true. Others: * src/TorrentMan.cc (getMissingPieceIndex): Updated log message. * src/PeerInteraction.cc (createPeerMessag): Updated log message.
Diffstat (limited to 'src/BitfieldMan.cc')
-rw-r--r--src/BitfieldMan.cc95
1 files changed, 84 insertions, 11 deletions
diff --git a/src/BitfieldMan.cc b/src/BitfieldMan.cc
index c5c120f9..0e32f912 100644
--- a/src/BitfieldMan.cc
+++ b/src/BitfieldMan.cc
@@ -20,6 +20,7 @@
*/
/* copyright --> */
#include "BitfieldMan.h"
+#include "Util.h"
#include <string.h>
BitfieldMan::BitfieldMan(int blockLength, long long int totalLength)
@@ -92,24 +93,21 @@ BitfieldMan& BitfieldMan::operator=(const BitfieldMan& bitfieldMan) {
int BitfieldMan::countSetBit(const unsigned char* bitfield, int len) const {
int count = 0;
- for(int i = 0; i < len; i++) {
- unsigned char bit = bitfield[i];
- for(int bs = 7; bs >= 0 && i*8+7-bs < blocks; bs--) {
- unsigned char mask = 1 << bs;
- if(bit & mask) {
- count++;
- }
- }
+ int size = sizeof(unsigned int);
+ for(int i = 0; i < len/size; i++) {
+ count += Util::countBit(*(unsigned int*)&bitfield[i*size]);
+ }
+ for(int i = len-len%size; i < len; i++) {
+ count += Util::countBit((unsigned int)bitfield[i]);
}
return count;
}
-int BitfieldMan::getMissingIndexRandomly(const unsigned char* bitfield, int len, int randMax) const {
+int BitfieldMan::getNthBitIndex(const unsigned char* bitfield, int len, int nth) const {
int index = -1;
- int nth = 1+(int)(((double)randMax)*random()/(RAND_MAX+1.0));
for(int i = 0; i < len && index == -1; i++) {
unsigned char bit = bitfield[i];
- for(int bs = 7; bs >= 0 && i*8+7-bs < blocks; bs--) {
+ for(int bs = 7; bs >= 0; bs--) {
unsigned char mask = 1 << bs;
if(bit & mask) {
nth--;
@@ -123,6 +121,61 @@ int BitfieldMan::getMissingIndexRandomly(const unsigned char* bitfield, int len,
return index;
}
+int BitfieldMan::getMissingIndexRandomly(const unsigned char* bitfield, int len, int randMax) const {
+ int nth = 1+(int)(((double)randMax)*random()/(RAND_MAX+1.0));
+
+ int count = 0;
+ int size = sizeof(unsigned int);
+ for(int i = 0; i < len/size; i++) {
+ int temp = Util::countBit(*(unsigned int*)&bitfield[i*size]);
+ if(nth <= count+temp) {
+ int t = i*size*8+getNthBitIndex(&bitfield[i*size], size, nth-count);
+ return t;
+ } else {
+ count += temp;
+ }
+ }
+ for(int i = len-len%size; i < len; i++) {
+ int temp = Util::countBit((unsigned int)bitfield[i]);
+ if(nth <= count+temp) {
+ int t = i*8+getNthBitIndex(&bitfield[i], 1, nth-count);
+ return t;
+ } else {
+ count += temp;
+ }
+ }
+ return -1;
+}
+
+bool BitfieldMan::hasMissingPiece(const unsigned char* peerBitfield, int length) const {
+ if(bitfieldLength != length) {
+ return false;
+ }
+ unsigned char* tempBitfield = new unsigned char[bitfieldLength];
+ for(int i = 0; i < bitfieldLength; i++) {
+ tempBitfield[i] = peerBitfield[i] & ~bitfield[i];
+ if(filterEnabled) {
+ tempBitfield[i] &= filterBitfield[i];
+ }
+ }
+ bool retval = false;
+ int size = sizeof(unsigned int);
+ for(int i = 0; i < length/size; i++) {
+ if(Util::countBit(*(unsigned int*)&tempBitfield[i*size]) > 0) {
+ retval = true;
+ break;
+ }
+ }
+ for(int i = length-length%size; i < length && retval == false; i++) {
+ if(Util::countBit((unsigned int)tempBitfield[i]) > 0) {
+ retval = true;
+ break;
+ }
+ }
+ delete [] tempBitfield;
+ return retval;
+}
+
int BitfieldMan::getMissingIndex(const unsigned char* peerBitfield, int length) const {
if(bitfieldLength != length) {
return -1;
@@ -223,6 +276,26 @@ BlockIndexes BitfieldMan::getAllMissingIndexes() const {
return missingIndexes;
}
+BlockIndexes BitfieldMan::getAllMissingIndexes(const unsigned char* peerBitfield, int peerBitfieldLength) const {
+ BlockIndexes missingIndexes;
+ if(bitfieldLength != peerBitfieldLength) {
+ return missingIndexes;
+ }
+ for(int i = 0; i < bitfieldLength; i++) {
+ unsigned char bit = peerBitfield[i] & ~bitfield[i];
+ if(filterEnabled) {
+ bit &= filterBitfield[i];
+ }
+ for(int bs = 7; bs >= 0 && i*8+7-bs < blocks; bs--) {
+ unsigned char mask = 1 << bs;
+ if(bit & mask) {
+ missingIndexes.push_back(i*8+7-bs);
+ }
+ }
+ }
+ return missingIndexes;
+}
+
int BitfieldMan::countMissingBlock() const {
if(filterEnabled) {
unsigned char* temp = new unsigned char[bitfieldLength];